diff --git a/Cargo.lock b/Cargo.lock
index 8969ff7..1ccb5df 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -10,39 +10,55 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "aead"
-version = "0.4.3"
+version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877"
+checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0"
dependencies = [
+ "crypto-common",
"generic-array",
+ "heapless",
]
[[package]]
name = "aes"
-version = "0.7.5"
+version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8"
+checksum = "433cfd6710c9986c576a25ca913c39d66a6474107b406f34f91d4a8923395241"
dependencies = [
"cfg-if",
- "cipher 0.3.0",
+ "cipher",
"cpufeatures",
- "opaque-debug",
]
[[package]]
name = "aes-gcm"
-version = "0.9.4"
+version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6"
+checksum = "209b47e8954a928e1d72e86eca7000ebb6655fe1436d33eefc2201cad027e237"
dependencies = [
"aead",
"aes",
- "cipher 0.3.0",
+ "cipher",
"ctr",
"ghash",
"subtle",
]
+[[package]]
+name = "aes-gcm-siv"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae0784134ba9375416d469ec31e7c5f9fa94405049cf08c5ce5b4698be673e0d"
+dependencies = [
+ "aead",
+ "aes",
+ "cipher",
+ "ctr",
+ "polyval",
+ "subtle",
+ "zeroize",
+]
+
[[package]]
name = "aho-corasick"
version = "1.0.1"
@@ -88,6 +104,17 @@ version = "1.0.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
+[[package]]
+name = "argon2"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95c2fcf79ad1932ac6269a738109997a83c227c09b75842ae564dc8ede6a861c"
+dependencies = [
+ "base64ct",
+ "blake2",
+ "password-hash",
+]
+
[[package]]
name = "arrayref"
version = "0.3.7"
@@ -288,7 +315,7 @@ dependencies = [
"futures-util",
"log",
"pin-project-lite",
- "tungstenite",
+ "tungstenite 0.17.3",
]
[[package]]
@@ -326,6 +353,15 @@ dependencies = [
"system-deps",
]
+[[package]]
+name = "atomic-polyfill"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3ff7eb3f316534d83a8a2c3d1674ace8a5a71198eba31e2e2b597833f699b28"
+dependencies = [
+ "critical-section",
+]
+
[[package]]
name = "atomic-waker"
version = "1.1.1"
@@ -350,6 +386,21 @@ version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
+[[package]]
+name = "base64-url"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c5b0a88aa36e9f095ee2e2b13fb8c5e4313e022783aedacc123328c0084916d"
+dependencies = [
+ "base64 0.21.0",
+]
+
+[[package]]
+name = "base64ct"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
+
[[package]]
name = "bincode"
version = "1.3.3"
@@ -359,6 +410,12 @@ dependencies = [
"serde",
]
+[[package]]
+name = "bit_field"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61"
+
[[package]]
name = "bitflags"
version = "1.3.2"
@@ -571,18 +628,6 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
-[[package]]
-name = "chacha20"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c80e5460aa66fe3b91d40bcbdab953a597b60053e34d684ac6903f863b680a6"
-dependencies = [
- "cfg-if",
- "cipher 0.3.0",
- "cpufeatures",
- "zeroize",
-]
-
[[package]]
name = "chacha20"
version = "0.9.1"
@@ -590,19 +635,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818"
dependencies = [
"cfg-if",
- "cipher 0.4.4",
+ "cipher",
"cpufeatures",
]
[[package]]
name = "chacha20poly1305"
-version = "0.9.1"
+version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a18446b09be63d457bbec447509e85f662f32952b035ce892290396bc0b0cff5"
+checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35"
dependencies = [
"aead",
- "chacha20 0.8.2",
- "cipher 0.3.0",
+ "chacha20",
+ "cipher",
"poly1305",
"zeroize",
]
@@ -620,15 +665,6 @@ dependencies = [
"winapi",
]
-[[package]]
-name = "cipher"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7"
-dependencies = [
- "generic-array",
-]
-
[[package]]
name = "cipher"
version = "0.4.4"
@@ -637,6 +673,7 @@ checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
dependencies = [
"crypto-common",
"inout",
+ "zeroize",
]
[[package]]
@@ -776,6 +813,12 @@ dependencies = [
"cfg-if",
]
+[[package]]
+name = "critical-section"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6548a0ad5d2549e111e1f6a11a6c2e2d00ce6a3dafe22948d67c2b443f775e52"
+
[[package]]
name = "crossbeam-channel"
version = "0.5.8"
@@ -786,6 +829,30 @@ dependencies = [
"crossbeam-utils",
]
+[[package]]
+name = "crossbeam-deque"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
+dependencies = [
+ "cfg-if",
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695"
+dependencies = [
+ "autocfg",
+ "cfg-if",
+ "crossbeam-utils",
+ "memoffset",
+ "scopeguard",
+]
+
[[package]]
name = "crossbeam-utils"
version = "0.8.15"
@@ -795,6 +862,12 @@ dependencies = [
"cfg-if",
]
+[[package]]
+name = "crunchy"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
+
[[package]]
name = "crypto-common"
version = "0.1.6"
@@ -802,6 +875,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
+ "rand_core 0.6.4",
"typenum",
]
@@ -844,11 +918,11 @@ dependencies = [
[[package]]
name = "ctr"
-version = "0.8.0"
+version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea"
+checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835"
dependencies = [
- "cipher 0.3.0",
+ "cipher",
]
[[package]]
@@ -864,9 +938,9 @@ dependencies = [
[[package]]
name = "curve25519-dalek"
-version = "3.2.1"
+version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0"
+checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61"
dependencies = [
"byteorder",
"digest 0.9.0",
@@ -875,6 +949,20 @@ dependencies = [
"zeroize",
]
+[[package]]
+name = "curve25519-dalek"
+version = "4.0.0-rc.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "03d928d978dbec61a1167414f5ec534f24bea0d7a0d24dd9b6233d3d8223e585"
+dependencies = [
+ "cfg-if",
+ "fiat-crypto",
+ "packed_simd_2",
+ "platforms",
+ "subtle",
+ "zeroize",
+]
+
[[package]]
name = "darling"
version = "0.20.1"
@@ -1024,7 +1112,7 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d"
dependencies = [
- "curve25519-dalek",
+ "curve25519-dalek 3.2.0",
"ed25519",
"rand 0.7.3",
"serde",
@@ -1066,6 +1154,19 @@ dependencies = [
"cfg-if",
]
+[[package]]
+name = "env_logger"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0"
+dependencies = [
+ "humantime",
+ "is-terminal",
+ "log",
+ "regex",
+ "termcolor",
+]
+
[[package]]
name = "errno"
version = "0.3.1"
@@ -1093,6 +1194,22 @@ version = "2.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
+[[package]]
+name = "exr"
+version = "1.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bdd2162b720141a91a054640662d3edce3d50a944a50ffca5313cd951abb35b4"
+dependencies = [
+ "bit_field",
+ "flume",
+ "half",
+ "lebe",
+ "miniz_oxide 0.6.2",
+ "rayon-core",
+ "smallvec",
+ "zune-inflate",
+]
+
[[package]]
name = "fastbloom-rs"
version = "0.5.3"
@@ -1129,6 +1246,12 @@ dependencies = [
"simd-adler32",
]
+[[package]]
+name = "fiat-crypto"
+version = "0.1.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77"
+
[[package]]
name = "field-offset"
version = "0.3.5"
@@ -1146,7 +1269,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743"
dependencies = [
"crc32fast",
- "miniz_oxide",
+ "miniz_oxide 0.7.1",
+]
+
+[[package]]
+name = "flume"
+version = "0.10.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577"
+dependencies = [
+ "futures-core",
+ "futures-sink",
+ "nanorand",
+ "pin-project",
+ "spin",
]
[[package]]
@@ -1448,14 +1584,24 @@ dependencies = [
[[package]]
name = "ghash"
-version = "0.4.4"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99"
+checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40"
dependencies = [
"opaque-debug",
"polyval",
]
+[[package]]
+name = "gif"
+version = "0.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045"
+dependencies = [
+ "color_quant",
+ "weezl",
+]
+
[[package]]
name = "gio"
version = "0.16.7"
@@ -1639,12 +1785,68 @@ dependencies = [
"tracing",
]
+[[package]]
+name = "half"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02b4af3693f1b705df946e9fe5631932443781d0aabb423b62fcd4d73f6d2fd0"
+dependencies = [
+ "crunchy",
+]
+
+[[package]]
+name = "hash32"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67"
+dependencies = [
+ "byteorder",
+]
+
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
+[[package]]
+name = "headers"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584"
+dependencies = [
+ "base64 0.13.1",
+ "bitflags",
+ "bytes",
+ "headers-core",
+ "http",
+ "httpdate",
+ "mime",
+ "sha1",
+]
+
+[[package]]
+name = "headers-core"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429"
+dependencies = [
+ "http",
+]
+
+[[package]]
+name = "heapless"
+version = "0.7.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743"
+dependencies = [
+ "atomic-polyfill",
+ "hash32",
+ "rustc_version",
+ "spin",
+ "stable_deref_trait",
+]
+
[[package]]
name = "heck"
version = "0.4.1"
@@ -1726,6 +1928,12 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
+[[package]]
+name = "humantime"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
+
[[package]]
name = "hyper"
version = "0.14.26"
@@ -1814,8 +2022,14 @@ dependencies = [
"bytemuck",
"byteorder",
"color_quant",
+ "exr",
+ "gif",
+ "jpeg-decoder",
"num-rational",
"num-traits",
+ "png",
+ "qoi",
+ "tiff",
]
[[package]]
@@ -1873,6 +2087,18 @@ version = "2.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f"
+[[package]]
+name = "is-terminal"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f"
+dependencies = [
+ "hermit-abi 0.3.1",
+ "io-lifetimes",
+ "rustix",
+ "windows-sys 0.48.0",
+]
+
[[package]]
name = "itertools"
version = "0.10.5"
@@ -1937,6 +2163,15 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
+[[package]]
+name = "jpeg-decoder"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e"
+dependencies = [
+ "rayon",
+]
+
[[package]]
name = "js-sys"
version = "0.3.63"
@@ -1985,12 +2220,24 @@ version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+[[package]]
+name = "lebe"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8"
+
[[package]]
name = "libc"
version = "0.2.144"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
+[[package]]
+name = "libm"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a"
+
[[package]]
name = "line-wrap"
version = "0.1.1"
@@ -2127,6 +2374,25 @@ version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
+[[package]]
+name = "mime_guess"
+version = "2.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef"
+dependencies = [
+ "mime",
+ "unicase",
+]
+
+[[package]]
+name = "miniz_oxide"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
+dependencies = [
+ "adler",
+]
+
[[package]]
name = "miniz_oxide"
version = "0.7.1"
@@ -2149,6 +2415,33 @@ dependencies = [
"windows-sys 0.45.0",
]
+[[package]]
+name = "multer"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "01acbdc23469fd8fe07ab135923371d5f5a422fbf9c522158677c8eb15bc51c2"
+dependencies = [
+ "bytes",
+ "encoding_rs",
+ "futures-util",
+ "http",
+ "httparse",
+ "log",
+ "memchr",
+ "mime",
+ "spin",
+ "version_check",
+]
+
+[[package]]
+name = "nanorand"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3"
+dependencies = [
+ "getrandom 0.2.9",
+]
+
[[package]]
name = "ndk"
version = "0.6.0"
@@ -2215,6 +2508,27 @@ dependencies = [
"tauri-build",
]
+[[package]]
+name = "ng-wallet"
+version = "0.1.0"
+dependencies = [
+ "aes-gcm-siv",
+ "argon2",
+ "base64-url",
+ "chacha20poly1305",
+ "debug_print",
+ "getrandom 0.1.16",
+ "image",
+ "p2p-net",
+ "p2p-repo",
+ "rand 0.7.3",
+ "safe-transmute",
+ "serde",
+ "serde-big-array",
+ "serde_bare",
+ "serde_bytes",
+]
+
[[package]]
name = "ngcli"
version = "0.1.0"
@@ -2229,8 +2543,8 @@ dependencies = [
"p2p-client-ws",
"p2p-net",
"p2p-repo",
- "p2p-stores-lmdb",
"rand 0.7.3",
+ "stores-lmdb",
"tempfile",
]
@@ -2244,6 +2558,31 @@ dependencies = [
"p2p-repo",
]
+[[package]]
+name = "ngone"
+version = "0.1.0"
+dependencies = [
+ "base64-url",
+ "bytes",
+ "debug_print",
+ "env_logger",
+ "log",
+ "ng-wallet",
+ "p2p-net",
+ "p2p-repo",
+ "rust-embed",
+ "serde",
+ "serde-big-array",
+ "serde_bare",
+ "serde_bytes",
+ "serde_json",
+ "slice_as_array",
+ "stores-lmdb",
+ "tokio",
+ "warp",
+ "warp-embed",
+]
+
[[package]]
name = "nodrop"
version = "0.1.14"
@@ -2252,23 +2591,22 @@ checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
[[package]]
name = "noise-protocol"
-version = "0.1.4"
+version = "0.2.0-rc1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4fb474d36dfe51bb4d7e733fee2b0dfd92ee1b95c716030a70e92737dea1a52b"
+checksum = "eecce5634c8ec4e9352dbb67bedaff4796503d81913cf27763bc121dac32fbd9"
dependencies = [
"arrayvec",
]
[[package]]
name = "noise-rust-crypto"
-version = "0.5.0"
+version = "0.6.0-rc.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "82e7cfeb8e6a63b4a5ccef34ed7a22d084a129b1e53a000c080bbc54c0da6f8c"
+checksum = "16c166af96e587866c91d5fba009fbab882ebeb892ab3e576b676120262b7f93"
dependencies = [
"aes-gcm",
"blake2",
"chacha20poly1305",
- "getrandom 0.2.9",
"noise-protocol",
"sha2 0.10.6",
"x25519-dalek",
@@ -2409,7 +2747,7 @@ dependencies = [
"async-std",
"async-trait",
"async-tungstenite",
- "chacha20 0.9.1",
+ "chacha20",
"debug_print",
"futures",
"getrandom 0.2.9",
@@ -2417,11 +2755,11 @@ dependencies = [
"p2p-client-ws",
"p2p-net",
"p2p-repo",
- "p2p-stores-lmdb",
"rust-fsm",
"serde",
"serde_bare",
"serde_bytes",
+ "stores-lmdb",
"tempfile",
]
@@ -2434,7 +2772,7 @@ dependencies = [
"async-std",
"async-trait",
"async-tungstenite",
- "chacha20 0.9.1",
+ "chacha20",
"debug_print",
"futures",
"getrandom 0.2.9",
@@ -2480,7 +2818,7 @@ name = "p2p-repo"
version = "0.1.0"
dependencies = [
"blake3",
- "chacha20 0.9.1",
+ "chacha20",
"debug_print",
"ed25519-dalek",
"fastbloom-rs",
@@ -2491,25 +2829,12 @@ dependencies = [
"serde_bytes",
]
-[[package]]
-name = "p2p-stores-lmdb"
-version = "0.1.0"
-dependencies = [
- "debug_print",
- "hex",
- "p2p-repo",
- "rkv",
- "serde",
- "serde_bare",
- "tempfile",
-]
-
[[package]]
name = "p2p-verifier"
version = "0.1.0"
dependencies = [
"blake3",
- "chacha20 0.9.1",
+ "chacha20",
"p2p-net",
"p2p-repo",
"serde",
@@ -2517,6 +2842,16 @@ dependencies = [
"serde_bytes",
]
+[[package]]
+name = "packed_simd_2"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1914cd452d8fccd6f9db48147b29fd4ae05bea9dc5d9ad578509f72415de282"
+dependencies = [
+ "cfg-if",
+ "libm",
+]
+
[[package]]
name = "pango"
version = "0.16.5"
@@ -2572,6 +2907,17 @@ dependencies = [
"windows-sys 0.45.0",
]
+[[package]]
+name = "password-hash"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166"
+dependencies = [
+ "base64ct",
+ "rand_core 0.6.4",
+ "subtle",
+]
+
[[package]]
name = "paste"
version = "1.0.12"
@@ -2692,6 +3038,26 @@ dependencies = [
"siphasher",
]
+[[package]]
+name = "pin-project"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead"
+dependencies = [
+ "pin-project-internal",
+]
+
+[[package]]
+name = "pin-project-internal"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.16",
+]
+
[[package]]
name = "pin-project-lite"
version = "0.2.9"
@@ -2710,6 +3076,12 @@ version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
+[[package]]
+name = "platforms"
+version = "3.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3d7ddaed09e0eb771a79ab0fd64609ba0afb0a8366421957936ad14cbd13630"
+
[[package]]
name = "plist"
version = "1.4.3"
@@ -2734,7 +3106,7 @@ dependencies = [
"crc32fast",
"fdeflate",
"flate2",
- "miniz_oxide",
+ "miniz_oxide 0.7.1",
]
[[package]]
@@ -2755,9 +3127,9 @@ dependencies = [
[[package]]
name = "poly1305"
-version = "0.7.2"
+version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "048aeb476be11a4b6ca432ca569e375810de9294ae78f4774e78ea98a9246ede"
+checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf"
dependencies = [
"cpufeatures",
"opaque-debug",
@@ -2766,9 +3138,9 @@ dependencies = [
[[package]]
name = "polyval"
-version = "0.5.3"
+version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1"
+checksum = "7ef234e08c11dfcb2e56f79fd70f6f2eb7f025c0ce2333e82f4f0518ecad30c6"
dependencies = [
"cfg-if",
"cpufeatures",
@@ -2865,6 +3237,15 @@ dependencies = [
"unicode-ident",
]
+[[package]]
+name = "qoi"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001"
+dependencies = [
+ "bytemuck",
+]
+
[[package]]
name = "quick-xml"
version = "0.28.2"
@@ -2970,6 +3351,28 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9"
+[[package]]
+name = "rayon"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
+dependencies = [
+ "either",
+ "rayon-core",
+]
+
+[[package]]
+name = "rayon-core"
+version = "1.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
+dependencies = [
+ "crossbeam-channel",
+ "crossbeam-deque",
+ "crossbeam-utils",
+ "num_cpus",
+]
+
[[package]]
name = "redox_syscall"
version = "0.2.16"
@@ -3089,6 +3492,40 @@ dependencies = [
"uuid 0.8.2",
]
+[[package]]
+name = "rust-embed"
+version = "6.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b68543d5527e158213414a92832d2aab11a84d2571a5eb021ebe22c43aab066"
+dependencies = [
+ "rust-embed-impl",
+ "rust-embed-utils",
+ "walkdir",
+]
+
+[[package]]
+name = "rust-embed-impl"
+version = "6.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4d4e0f0ced47ded9a68374ac145edd65a6c1fa13a96447b873660b2a568a0fd7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "rust-embed-utils",
+ "syn 1.0.109",
+ "walkdir",
+]
+
+[[package]]
+name = "rust-embed-utils"
+version = "7.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "512b0ab6853f7e14e3c8754acb43d6f748bb9ced66aa5915a6553ac8213f7731"
+dependencies = [
+ "sha2 0.10.6",
+ "walkdir",
+]
+
[[package]]
name = "rust-fsm"
version = "0.6.1"
@@ -3131,6 +3568,15 @@ dependencies = [
"windows-sys 0.48.0",
]
+[[package]]
+name = "rustls-pemfile"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b"
+dependencies = [
+ "base64 0.21.0",
+]
+
[[package]]
name = "rustversion"
version = "1.0.12"
@@ -3143,6 +3589,12 @@ version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
+[[package]]
+name = "safe-transmute"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "98a01dab6acf992653be49205bdd549f32f17cb2803e8eacf1560bf97259aae8"
+
[[package]]
name = "safemem"
version = "0.3.3"
@@ -3214,6 +3666,15 @@ dependencies = [
"serde_derive",
]
+[[package]]
+name = "serde-big-array"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "11fc7cc2c76d73e0f27ee52abbd64eec84d46f370c88371120433196934e4b7f"
+dependencies = [
+ "serde",
+]
+
[[package]]
name = "serde_bare"
version = "0.5.0"
@@ -3357,6 +3818,17 @@ dependencies = [
"digest 0.10.7",
]
+[[package]]
+name = "sha1"
+version = "0.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest 0.10.7",
+]
+
[[package]]
name = "sha2"
version = "0.9.9"
@@ -3436,6 +3908,12 @@ dependencies = [
"autocfg",
]
+[[package]]
+name = "slice_as_array"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64c963ee59ddedb5ab95dc2cd97c48b4a292572a52c5636fbbabdb9985bfe4c3"
+
[[package]]
name = "smallvec"
version = "1.10.0"
@@ -3480,6 +3958,15 @@ dependencies = [
"system-deps",
]
+[[package]]
+name = "spin"
+version = "0.9.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
+dependencies = [
+ "lock_api",
+]
+
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
@@ -3495,6 +3982,19 @@ dependencies = [
"loom",
]
+[[package]]
+name = "stores-lmdb"
+version = "0.1.0"
+dependencies = [
+ "debug_print",
+ "hex",
+ "p2p-repo",
+ "rkv",
+ "serde",
+ "serde_bare",
+ "tempfile",
+]
+
[[package]]
name = "string_cache"
version = "0.8.7"
@@ -3854,6 +4354,15 @@ dependencies = [
"utf-8",
]
+[[package]]
+name = "termcolor"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
+dependencies = [
+ "winapi-util",
+]
+
[[package]]
name = "termtree"
version = "0.4.1"
@@ -3896,6 +4405,17 @@ dependencies = [
"once_cell",
]
+[[package]]
+name = "tiff"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7449334f9ff2baf290d55d73983a7d6fa15e01198faef72af07e2a8db851e471"
+dependencies = [
+ "flate2",
+ "jpeg-decoder",
+ "weezl",
+]
+
[[package]]
name = "time"
version = "0.3.21"
@@ -3949,11 +4469,48 @@ dependencies = [
"libc",
"mio",
"num_cpus",
+ "parking_lot",
"pin-project-lite",
+ "signal-hook-registry",
"socket2",
+ "tokio-macros",
"windows-sys 0.48.0",
]
+[[package]]
+name = "tokio-macros"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.16",
+]
+
+[[package]]
+name = "tokio-stream"
+version = "0.1.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842"
+dependencies = [
+ "futures-core",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-tungstenite"
+version = "0.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "54319c93411147bced34cb5609a80e0a8e44c5999c93903a81cd866630ec0bfd"
+dependencies = [
+ "futures-util",
+ "log",
+ "tokio",
+ "tungstenite 0.18.0",
+]
+
[[package]]
name = "tokio-util"
version = "0.7.8"
@@ -4015,6 +4572,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
dependencies = [
"cfg-if",
+ "log",
"pin-project-lite",
"tracing-attributes",
"tracing-core",
@@ -4104,12 +4662,40 @@ dependencies = [
"utf-8",
]
+[[package]]
+name = "tungstenite"
+version = "0.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30ee6ab729cd4cf0fd55218530c4522ed30b7b6081752839b68fcec8d0960788"
+dependencies = [
+ "base64 0.13.1",
+ "byteorder",
+ "bytes",
+ "http",
+ "httparse",
+ "log",
+ "rand 0.8.5",
+ "sha1",
+ "thiserror",
+ "url",
+ "utf-8",
+]
+
[[package]]
name = "typenum"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
+[[package]]
+name = "unicase"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
+dependencies = [
+ "version_check",
+]
+
[[package]]
name = "unicode-bidi"
version = "0.3.13"
@@ -4150,11 +4736,11 @@ dependencies = [
[[package]]
name = "universal-hash"
-version = "0.4.1"
+version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05"
+checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea"
dependencies = [
- "generic-array",
+ "crypto-common",
"subtle",
]
@@ -4274,6 +4860,48 @@ dependencies = [
"try-lock",
]
+[[package]]
+name = "warp"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba431ef570df1287f7f8b07e376491ad54f84d26ac473489427231e1718e1f69"
+dependencies = [
+ "bytes",
+ "futures-channel",
+ "futures-util",
+ "headers",
+ "http",
+ "hyper",
+ "log",
+ "mime",
+ "mime_guess",
+ "multer",
+ "percent-encoding",
+ "pin-project",
+ "rustls-pemfile",
+ "scoped-tls",
+ "serde",
+ "serde_json",
+ "serde_urlencoded",
+ "tokio",
+ "tokio-stream",
+ "tokio-tungstenite",
+ "tokio-util",
+ "tower-service",
+ "tracing",
+]
+
+[[package]]
+name = "warp-embed"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b958139e25f097e0ebde85342a3a2dbb728983ca893ba96b7fb8f448337110af"
+dependencies = [
+ "mime_guess",
+ "rust-embed",
+ "warp",
+]
+
[[package]]
name = "wasi"
version = "0.9.0+wasi-snapshot-preview1"
@@ -4481,6 +5109,12 @@ dependencies = [
"windows-metadata",
]
+[[package]]
+name = "weezl"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb"
+
[[package]]
name = "winapi"
version = "0.3.9"
@@ -4817,12 +5451,13 @@ dependencies = [
[[package]]
name = "x25519-dalek"
-version = "1.2.0"
+version = "2.0.0-rc.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2392b6b94a576b4e2bf3c5b2757d63f10ada8020a2e4d08ac849ebcf6ea8e077"
+checksum = "fabd6e16dd08033932fc3265ad4510cc2eab24656058a6dcb107ffe274abcc95"
dependencies = [
- "curve25519-dalek",
- "rand_core 0.5.1",
+ "curve25519-dalek 4.0.0-rc.2",
+ "rand_core 0.6.4",
+ "serde",
"zeroize",
]
@@ -4867,9 +5502,9 @@ checksum = "735a71d46c4d68d71d4b24d03fdc2b98e38cea81730595801db779c04fe80d70"
[[package]]
name = "zeroize"
-version = "1.3.0"
+version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd"
+checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9"
dependencies = [
"zeroize_derive",
]
@@ -4884,3 +5519,12 @@ dependencies = [
"quote",
"syn 2.0.16",
]
+
+[[package]]
+name = "zune-inflate"
+version = "0.2.54"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02"
+dependencies = [
+ "simd-adler32",
+]
diff --git a/Cargo.toml b/Cargo.toml
index e0d5f22..7970242 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -5,11 +5,13 @@ members = [
"p2p-broker",
"p2p-client-ws",
"p2p-verifier",
- "p2p-stores-lmdb",
+ "stores-lmdb",
"ngcli",
"ngd",
+ "ngone",
"ng-app-js",
"ng-app-native/src-tauri",
+ "ng-wallet"
]
[profile.release]
diff --git a/README.md b/README.md
index dae92c1..7ba75f4 100644
--- a/README.md
+++ b/README.md
@@ -33,6 +33,7 @@ Read our [getting started guide](https://docs.nextgraph.org/en/getting-started/)
```
cargo install wasm-pack
+cargo install cargo-watch
// optionally, if you want a Rust REPL: cargo install evcxr_repl
git clone git@git.nextgraph.org:NextGraph/nextgraph-rs.git
cd nextgraph-rs
@@ -47,12 +48,14 @@ The crates are organized as follow :
- p2p-net : all the common types, traits and structs for the P2P networks
- p2p-broker : the broker code (as server and core peer)
- p2p-client-ws : the client connecting to a broker, used by the apps and verifier
-- p2p-stores-lmdb : lmdb backed stores for the p2p layer
- p2p-verifier : the code of the verifier
+- stores-lmdb : lmdb backed stores
- ngcli : CLI tool to manipulate the repos
- ngd : binary executable of the daemon (that can run a broker, verifier and/or Rust services)
+- ngone : server for nextgraph.one (boostrap into the right app)
- ng-app-js : contains the JS SDK, the web app, react app, and some node services
- ng-app-native : all the native apps, based on Tauri
+- ng-wallet : keeps the secret keys of all identities of the user in a safe wallet
### Run
diff --git a/ng-app-native/index.html b/ng-app-native/index.html
index 08ba759..53c4dc5 100644
--- a/ng-app-native/index.html
+++ b/ng-app-native/index.html
@@ -1,3 +1,13 @@
+
diff --git a/ng-app-native/src-tauri/src/lib.rs b/ng-app-native/src-tauri/src/lib.rs
index 0b7bf58..9615273 100644
--- a/ng-app-native/src-tauri/src/lib.rs
+++ b/ng-app-native/src-tauri/src/lib.rs
@@ -1,3 +1,12 @@
+// Copyright (c) 2022-2023 Niko Bonnieure, Par le Peuple, NextGraph.org developers
+// All rights reserved.
+// Licensed under the Apache License, Version 2.0
+//
+// or the MIT license ,
+// at your option. All files in the project carrying such
+// notice may not be copied, modified, or distributed except
+// according to those terms.
+
use tauri::App;
#[cfg(mobile)]
diff --git a/ng-app-native/src-tauri/src/main.rs b/ng-app-native/src-tauri/src/main.rs
index c80948a..cf3d4b8 100644
--- a/ng-app-native/src-tauri/src/main.rs
+++ b/ng-app-native/src-tauri/src/main.rs
@@ -1,3 +1,12 @@
+// Copyright (c) 2022-2023 Niko Bonnieure, Par le Peuple, NextGraph.org developers
+// All rights reserved.
+// Licensed under the Apache License, Version 2.0
+//
+// or the MIT license ,
+// at your option. All files in the project carrying such
+// notice may not be copied, modified, or distributed except
+// according to those terms.
+
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(
all(not(debug_assertions), target_os = "windows"),
diff --git a/ng-app-native/src-tauri/src/mobile.rs b/ng-app-native/src-tauri/src/mobile.rs
index 95e6c7f..868730d 100644
--- a/ng-app-native/src-tauri/src/mobile.rs
+++ b/ng-app-native/src-tauri/src/mobile.rs
@@ -1,3 +1,12 @@
+// Copyright (c) 2022-2023 Niko Bonnieure, Par le Peuple, NextGraph.org developers
+// All rights reserved.
+// Licensed under the Apache License, Version 2.0
+//
+// or the MIT license ,
+// at your option. All files in the project carrying such
+// notice may not be copied, modified, or distributed except
+// according to those terms.
+
#[tauri::mobile_entry_point]
fn main() {
crate::AppBuilder::new().run();
diff --git a/ng-app-native/src/App.svelte b/ng-app-native/src/App.svelte
index fee37a1..ef2c319 100644
--- a/ng-app-native/src/App.svelte
+++ b/ng-app-native/src/App.svelte
@@ -1,3 +1,14 @@
+
+
-
+
diff --git a/ng-app-native/src/lib/Greet.svelte b/ng-app-native/src/lib/Greet.svelte
index b96dbaf..c5fbc00 100644
--- a/ng-app-native/src/lib/Greet.svelte
+++ b/ng-app-native/src/lib/Greet.svelte
@@ -1,3 +1,14 @@
+
+
diff --git a/ng-app-native/src/routes/Test.svelte b/ng-app-native/src/routes/Test.svelte
index 6363a34..b307ed6 100644
--- a/ng-app-native/src/routes/Test.svelte
+++ b/ng-app-native/src/routes/Test.svelte
@@ -1,3 +1,14 @@
+
+
diff --git a/ng-app-native/src/styles.css b/ng-app-native/src/styles.css
index c11f1a2..e557431 100644
--- a/ng-app-native/src/styles.css
+++ b/ng-app-native/src/styles.css
@@ -1,3 +1,14 @@
+/*
+// Copyright (c) 2022-2023 Niko Bonnieure, Par le Peuple, NextGraph.org developers
+// All rights reserved.
+// Licensed under the Apache License, Version 2.0
+//
+// or the MIT license ,
+// at your option. All files in the project carrying such
+// notice may not be copied, modified, or distributed except
+// according to those terms.
+*/
+
:root {
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
font-size: 16px;
@@ -30,10 +41,6 @@
transition: 0.75s;
}
-.logo.tauri:hover {
- filter: drop-shadow(0 0 2em #24c8db);
-}
-
.row {
display: flex;
justify-content: center;
diff --git a/ng-wallet/.gitignore b/ng-wallet/.gitignore
new file mode 100644
index 0000000..8574aec
--- /dev/null
+++ b/ng-wallet/.gitignore
@@ -0,0 +1,3 @@
+.DS_Store
+tests/generated_security_image.jpg
+tests/wallet.ngw
\ No newline at end of file
diff --git a/ng-wallet/Cargo.toml b/ng-wallet/Cargo.toml
new file mode 100644
index 0000000..860659a
--- /dev/null
+++ b/ng-wallet/Cargo.toml
@@ -0,0 +1,27 @@
+[package]
+name = "ng-wallet"
+version = "0.1.0"
+edition = "2021"
+license = "MIT/Apache-2.0"
+authors = ["Niko PLP "]
+description = "keeps the secret keys of all identities of the user in a safe wallet"
+repository = "https://git.nextgraph.org/NextGraph/nextgraph-rs"
+
+[dependencies]
+debug_print = "1.0.0"
+serde = { version = "1.0.142", features = ["derive"] }
+serde_bare = "0.5.0"
+serde_bytes = "0.11.7"
+serde-big-array = "0.5.1"
+p2p-repo = { path = "../p2p-repo" }
+p2p-net = { path = "../p2p-net" }
+image = "0.24.6"
+getrandom = { version = "0.1.1", features = ["wasm-bindgen"] }
+rand = { version = "0.7", features = ["getrandom"] }
+chacha20poly1305 = "0.10.1"
+#{version = "0.10.1", features = ["heapless","getrandom"] }
+# slice_as_array = "1.1.0"
+argon2 = "0.5.0"
+safe-transmute = "0.11.2"
+aes-gcm-siv = {version = "0.11.1", features = ["aes","heapless","getrandom","std"] }
+base64-url = "2.0.0"
\ No newline at end of file
diff --git a/ng-wallet/src/bip39.rs b/ng-wallet/src/bip39.rs
new file mode 100644
index 0000000..5a1f8e1
--- /dev/null
+++ b/ng-wallet/src/bip39.rs
@@ -0,0 +1,213 @@
+pub const bip39_wordlist: [&str; 2048] = [
+ "abandon", "ability", "able", "about", "above", "absent", "absorb", "abstract", "absurd",
+ "abuse", "access", "accident", "account", "accuse", "achieve", "acid", "acoustic", "acquire",
+ "across", "act", "action", "actor", "actress", "actual", "adapt", "add", "addict", "address",
+ "adjust", "admit", "adult", "advance", "advice", "aerobic", "affair", "afford", "afraid",
+ "again", "age", "agent", "agree", "ahead", "aim", "air", "airport", "aisle", "alarm", "album",
+ "alcohol", "alert", "alien", "all", "alley", "allow", "almost", "alone", "alpha", "already",
+ "also", "alter", "always", "amateur", "amazing", "among", "amount", "amused", "analyst",
+ "anchor", "ancient", "anger", "angle", "angry", "animal", "ankle", "announce", "annual",
+ "another", "answer", "antenna", "antique", "anxiety", "any", "apart", "apology", "appear",
+ "apple", "approve", "april", "arch", "arctic", "area", "arena", "argue", "arm", "armed",
+ "armor", "army", "around", "arrange", "arrest", "arrive", "arrow", "art", "artefact", "artist",
+ "artwork", "ask", "aspect", "assault", "asset", "assist", "assume", "asthma", "athlete",
+ "atom", "attack", "attend", "attitude", "attract", "auction", "audit", "august", "aunt",
+ "author", "auto", "autumn", "average", "avocado", "avoid", "awake", "aware", "away", "awesome",
+ "awful", "awkward", "axis", "baby", "bachelor", "bacon", "badge", "bag", "balance", "balcony",
+ "ball", "bamboo", "banana", "banner", "bar", "barely", "bargain", "barrel", "base", "basic",
+ "basket", "battle", "beach", "bean", "beauty", "because", "become", "beef", "before", "begin",
+ "behave", "behind", "believe", "below", "belt", "bench", "benefit", "best", "betray", "better",
+ "between", "beyond", "bicycle", "bid", "bike", "bind", "biology", "bird", "birth", "bitter",
+ "black", "blade", "blame", "blanket", "blast", "bleak", "bless", "blind", "blood", "blossom",
+ "blouse", "blue", "blur", "blush", "board", "boat", "body", "boil", "bomb", "bone", "bonus",
+ "book", "boost", "border", "boring", "borrow", "boss", "bottom", "bounce", "box", "boy",
+ "bracket", "brain", "brand", "brass", "brave", "bread", "breeze", "brick", "bridge", "brief",
+ "bright", "bring", "brisk", "broccoli", "broken", "bronze", "broom", "brother", "brown",
+ "brush", "bubble", "buddy", "budget", "buffalo", "build", "bulb", "bulk", "bullet", "bundle",
+ "bunker", "burden", "burger", "burst", "bus", "business", "busy", "butter", "buyer", "buzz",
+ "cabbage", "cabin", "cable", "cactus", "cage", "cake", "call", "calm", "camera", "camp", "can",
+ "canal", "cancel", "candy", "cannon", "canoe", "canvas", "canyon", "capable", "capital",
+ "captain", "car", "carbon", "card", "cargo", "carpet", "carry", "cart", "case", "cash",
+ "casino", "castle", "casual", "cat", "catalog", "catch", "category", "cattle", "caught",
+ "cause", "caution", "cave", "ceiling", "celery", "cement", "census", "century", "cereal",
+ "certain", "chair", "chalk", "champion", "change", "chaos", "chapter", "charge", "chase",
+ "chat", "cheap", "check", "cheese", "chef", "cherry", "chest", "chicken", "chief", "child",
+ "chimney", "choice", "choose", "chronic", "chuckle", "chunk", "churn", "cigar", "cinnamon",
+ "circle", "citizen", "city", "civil", "claim", "clap", "clarify", "claw", "clay", "clean",
+ "clerk", "clever", "click", "client", "cliff", "climb", "clinic", "clip", "clock", "clog",
+ "close", "cloth", "cloud", "clown", "club", "clump", "cluster", "clutch", "coach", "coast",
+ "coconut", "code", "coffee", "coil", "coin", "collect", "color", "column", "combine", "come",
+ "comfort", "comic", "common", "company", "concert", "conduct", "confirm", "congress",
+ "connect", "consider", "control", "convince", "cook", "cool", "copper", "copy", "coral",
+ "core", "corn", "correct", "cost", "cotton", "couch", "country", "couple", "course", "cousin",
+ "cover", "coyote", "crack", "cradle", "craft", "cram", "crane", "crash", "crater", "crawl",
+ "crazy", "cream", "credit", "creek", "crew", "cricket", "crime", "crisp", "critic", "crop",
+ "cross", "crouch", "crowd", "crucial", "cruel", "cruise", "crumble", "crunch", "crush", "cry",
+ "crystal", "cube", "culture", "cup", "cupboard", "curious", "current", "curtain", "curve",
+ "cushion", "custom", "cute", "cycle", "dad", "damage", "damp", "dance", "danger", "daring",
+ "dash", "daughter", "dawn", "day", "deal", "debate", "debris", "decade", "december", "decide",
+ "decline", "decorate", "decrease", "deer", "defense", "define", "defy", "degree", "delay",
+ "deliver", "demand", "demise", "denial", "dentist", "deny", "depart", "depend", "deposit",
+ "depth", "deputy", "derive", "describe", "desert", "design", "desk", "despair", "destroy",
+ "detail", "detect", "develop", "device", "devote", "diagram", "dial", "diamond", "diary",
+ "dice", "diesel", "diet", "differ", "digital", "dignity", "dilemma", "dinner", "dinosaur",
+ "direct", "dirt", "disagree", "discover", "disease", "dish", "dismiss", "disorder", "display",
+ "distance", "divert", "divide", "divorce", "dizzy", "doctor", "document", "dog", "doll",
+ "dolphin", "domain", "donate", "donkey", "donor", "door", "dose", "double", "dove", "draft",
+ "dragon", "drama", "drastic", "draw", "dream", "dress", "drift", "drill", "drink", "drip",
+ "drive", "drop", "drum", "dry", "duck", "dumb", "dune", "during", "dust", "dutch", "duty",
+ "dwarf", "dynamic", "eager", "eagle", "early", "earn", "earth", "easily", "east", "easy",
+ "echo", "ecology", "economy", "edge", "edit", "educate", "effort", "egg", "eight", "either",
+ "elbow", "elder", "electric", "elegant", "element", "elephant", "elevator", "elite", "else",
+ "embark", "embody", "embrace", "emerge", "emotion", "employ", "empower", "empty", "enable",
+ "enact", "end", "endless", "endorse", "enemy", "energy", "enforce", "engage", "engine",
+ "enhance", "enjoy", "enlist", "enough", "enrich", "enroll", "ensure", "enter", "entire",
+ "entry", "envelope", "episode", "equal", "equip", "era", "erase", "erode", "erosion", "error",
+ "erupt", "escape", "essay", "essence", "estate", "eternal", "ethics", "evidence", "evil",
+ "evoke", "evolve", "exact", "example", "excess", "exchange", "excite", "exclude", "excuse",
+ "execute", "exercise", "exhaust", "exhibit", "exile", "exist", "exit", "exotic", "expand",
+ "expect", "expire", "explain", "expose", "express", "extend", "extra", "eye", "eyebrow",
+ "fabric", "face", "faculty", "fade", "faint", "faith", "fall", "false", "fame", "family",
+ "famous", "fan", "fancy", "fantasy", "farm", "fashion", "fat", "fatal", "father", "fatigue",
+ "fault", "favorite", "feature", "february", "federal", "fee", "feed", "feel", "female",
+ "fence", "festival", "fetch", "fever", "few", "fiber", "fiction", "field", "figure", "file",
+ "film", "filter", "final", "find", "fine", "finger", "finish", "fire", "firm", "first",
+ "fiscal", "fish", "fit", "fitness", "fix", "flag", "flame", "flash", "flat", "flavor", "flee",
+ "flight", "flip", "float", "flock", "floor", "flower", "fluid", "flush", "fly", "foam",
+ "focus", "fog", "foil", "fold", "follow", "food", "foot", "force", "forest", "forget", "fork",
+ "fortune", "forum", "forward", "fossil", "foster", "found", "fox", "fragile", "frame",
+ "frequent", "fresh", "friend", "fringe", "frog", "front", "frost", "frown", "frozen", "fruit",
+ "fuel", "fun", "funny", "furnace", "fury", "future", "gadget", "gain", "galaxy", "gallery",
+ "game", "gap", "garage", "garbage", "garden", "garlic", "garment", "gas", "gasp", "gate",
+ "gather", "gauge", "gaze", "general", "genius", "genre", "gentle", "genuine", "gesture",
+ "ghost", "giant", "gift", "giggle", "ginger", "giraffe", "girl", "give", "glad", "glance",
+ "glare", "glass", "glide", "glimpse", "globe", "gloom", "glory", "glove", "glow", "glue",
+ "goat", "goddess", "gold", "good", "goose", "gorilla", "gospel", "gossip", "govern", "gown",
+ "grab", "grace", "grain", "grant", "grape", "grass", "gravity", "great", "green", "grid",
+ "grief", "grit", "grocery", "group", "grow", "grunt", "guard", "guess", "guide", "guilt",
+ "guitar", "gun", "gym", "habit", "hair", "half", "hammer", "hamster", "hand", "happy",
+ "harbor", "hard", "harsh", "harvest", "hat", "have", "hawk", "hazard", "head", "health",
+ "heart", "heavy", "hedgehog", "height", "hello", "helmet", "help", "hen", "hero", "hidden",
+ "high", "hill", "hint", "hip", "hire", "history", "hobby", "hockey", "hold", "hole", "holiday",
+ "hollow", "home", "honey", "hood", "hope", "horn", "horror", "horse", "hospital", "host",
+ "hotel", "hour", "hover", "hub", "huge", "human", "humble", "humor", "hundred", "hungry",
+ "hunt", "hurdle", "hurry", "hurt", "husband", "hybrid", "ice", "icon", "idea", "identify",
+ "idle", "ignore", "ill", "illegal", "illness", "image", "imitate", "immense", "immune",
+ "impact", "impose", "improve", "impulse", "inch", "include", "income", "increase", "index",
+ "indicate", "indoor", "industry", "infant", "inflict", "inform", "inhale", "inherit",
+ "initial", "inject", "injury", "inmate", "inner", "innocent", "input", "inquiry", "insane",
+ "insect", "inside", "inspire", "install", "intact", "interest", "into", "invest", "invite",
+ "involve", "iron", "island", "isolate", "issue", "item", "ivory", "jacket", "jaguar", "jar",
+ "jazz", "jealous", "jeans", "jelly", "jewel", "job", "join", "joke", "journey", "joy", "judge",
+ "juice", "jump", "jungle", "junior", "junk", "just", "kangaroo", "keen", "keep", "ketchup",
+ "key", "kick", "kid", "kidney", "kind", "kingdom", "kiss", "kit", "kitchen", "kite", "kitten",
+ "kiwi", "knee", "knife", "knock", "know", "lab", "label", "labor", "ladder", "lady", "lake",
+ "lamp", "language", "laptop", "large", "later", "latin", "laugh", "laundry", "lava", "law",
+ "lawn", "lawsuit", "layer", "lazy", "leader", "leaf", "learn", "leave", "lecture", "left",
+ "leg", "legal", "legend", "leisure", "lemon", "lend", "length", "lens", "leopard", "lesson",
+ "letter", "level", "liar", "liberty", "library", "license", "life", "lift", "light", "like",
+ "limb", "limit", "link", "lion", "liquid", "list", "little", "live", "lizard", "load", "loan",
+ "lobster", "local", "lock", "logic", "lonely", "long", "loop", "lottery", "loud", "lounge",
+ "love", "loyal", "lucky", "luggage", "lumber", "lunar", "lunch", "luxury", "lyrics", "machine",
+ "mad", "magic", "magnet", "maid", "mail", "main", "major", "make", "mammal", "man", "manage",
+ "mandate", "mango", "mansion", "manual", "maple", "marble", "march", "margin", "marine",
+ "market", "marriage", "mask", "mass", "master", "match", "material", "math", "matrix",
+ "matter", "maximum", "maze", "meadow", "mean", "measure", "meat", "mechanic", "medal", "media",
+ "melody", "melt", "member", "memory", "mention", "menu", "mercy", "merge", "merit", "merry",
+ "mesh", "message", "metal", "method", "middle", "midnight", "milk", "million", "mimic", "mind",
+ "minimum", "minor", "minute", "miracle", "mirror", "misery", "miss", "mistake", "mix", "mixed",
+ "mixture", "mobile", "model", "modify", "mom", "moment", "monitor", "monkey", "monster",
+ "month", "moon", "moral", "more", "morning", "mosquito", "mother", "motion", "motor",
+ "mountain", "mouse", "move", "movie", "much", "muffin", "mule", "multiply", "muscle", "museum",
+ "mushroom", "music", "must", "mutual", "myself", "mystery", "myth", "naive", "name", "napkin",
+ "narrow", "nasty", "nation", "nature", "near", "neck", "need", "negative", "neglect",
+ "neither", "nephew", "nerve", "nest", "net", "network", "neutral", "never", "news", "next",
+ "nice", "night", "noble", "noise", "nominee", "noodle", "normal", "north", "nose", "notable",
+ "note", "nothing", "notice", "novel", "now", "nuclear", "number", "nurse", "nut", "oak",
+ "obey", "object", "oblige", "obscure", "observe", "obtain", "obvious", "occur", "ocean",
+ "october", "odor", "off", "offer", "office", "often", "oil", "okay", "old", "olive", "olympic",
+ "omit", "once", "one", "onion", "online", "only", "open", "opera", "opinion", "oppose",
+ "option", "orange", "orbit", "orchard", "order", "ordinary", "organ", "orient", "original",
+ "orphan", "ostrich", "other", "outdoor", "outer", "output", "outside", "oval", "oven", "over",
+ "own", "owner", "oxygen", "oyster", "ozone", "pact", "paddle", "page", "pair", "palace",
+ "palm", "panda", "panel", "panic", "panther", "paper", "parade", "parent", "park", "parrot",
+ "party", "pass", "patch", "path", "patient", "patrol", "pattern", "pause", "pave", "payment",
+ "peace", "peanut", "pear", "peasant", "pelican", "pen", "penalty", "pencil", "people",
+ "pepper", "perfect", "permit", "person", "pet", "phone", "photo", "phrase", "physical",
+ "piano", "picnic", "picture", "piece", "pig", "pigeon", "pill", "pilot", "pink", "pioneer",
+ "pipe", "pistol", "pitch", "pizza", "place", "planet", "plastic", "plate", "play", "please",
+ "pledge", "pluck", "plug", "plunge", "poem", "poet", "point", "polar", "pole", "police",
+ "pond", "pony", "pool", "popular", "portion", "position", "possible", "post", "potato",
+ "pottery", "poverty", "powder", "power", "practice", "praise", "predict", "prefer", "prepare",
+ "present", "pretty", "prevent", "price", "pride", "primary", "print", "priority", "prison",
+ "private", "prize", "problem", "process", "produce", "profit", "program", "project", "promote",
+ "proof", "property", "prosper", "protect", "proud", "provide", "public", "pudding", "pull",
+ "pulp", "pulse", "pumpkin", "punch", "pupil", "puppy", "purchase", "purity", "purpose",
+ "purse", "push", "put", "puzzle", "pyramid", "quality", "quantum", "quarter", "question",
+ "quick", "quit", "quiz", "quote", "rabbit", "raccoon", "race", "rack", "radar", "radio",
+ "rail", "rain", "raise", "rally", "ramp", "ranch", "random", "range", "rapid", "rare", "rate",
+ "rather", "raven", "raw", "razor", "ready", "real", "reason", "rebel", "rebuild", "recall",
+ "receive", "recipe", "record", "recycle", "reduce", "reflect", "reform", "refuse", "region",
+ "regret", "regular", "reject", "relax", "release", "relief", "rely", "remain", "remember",
+ "remind", "remove", "render", "renew", "rent", "reopen", "repair", "repeat", "replace",
+ "report", "require", "rescue", "resemble", "resist", "resource", "response", "result",
+ "retire", "retreat", "return", "reunion", "reveal", "review", "reward", "rhythm", "rib",
+ "ribbon", "rice", "rich", "ride", "ridge", "rifle", "right", "rigid", "ring", "riot", "ripple",
+ "risk", "ritual", "rival", "river", "road", "roast", "robot", "robust", "rocket", "romance",
+ "roof", "rookie", "room", "rose", "rotate", "rough", "round", "route", "royal", "rubber",
+ "rude", "rug", "rule", "run", "runway", "rural", "sad", "saddle", "sadness", "safe", "sail",
+ "salad", "salmon", "salon", "salt", "salute", "same", "sample", "sand", "satisfy", "satoshi",
+ "sauce", "sausage", "save", "say", "scale", "scan", "scare", "scatter", "scene", "scheme",
+ "school", "science", "scissors", "scorpion", "scout", "scrap", "screen", "script", "scrub",
+ "sea", "search", "season", "seat", "second", "secret", "section", "security", "seed", "seek",
+ "segment", "select", "sell", "seminar", "senior", "sense", "sentence", "series", "service",
+ "session", "settle", "setup", "seven", "shadow", "shaft", "shallow", "share", "shed", "shell",
+ "sheriff", "shield", "shift", "shine", "ship", "shiver", "shock", "shoe", "shoot", "shop",
+ "short", "shoulder", "shove", "shrimp", "shrug", "shuffle", "shy", "sibling", "sick", "side",
+ "siege", "sight", "sign", "silent", "silk", "silly", "silver", "similar", "simple", "since",
+ "sing", "siren", "sister", "situate", "six", "size", "skate", "sketch", "ski", "skill", "skin",
+ "skirt", "skull", "slab", "slam", "sleep", "slender", "slice", "slide", "slight", "slim",
+ "slogan", "slot", "slow", "slush", "small", "smart", "smile", "smoke", "smooth", "snack",
+ "snake", "snap", "sniff", "snow", "soap", "soccer", "social", "sock", "soda", "soft", "solar",
+ "soldier", "solid", "solution", "solve", "someone", "song", "soon", "sorry", "sort", "soul",
+ "sound", "soup", "source", "south", "space", "spare", "spatial", "spawn", "speak", "special",
+ "speed", "spell", "spend", "sphere", "spice", "spider", "spike", "spin", "spirit", "split",
+ "spoil", "sponsor", "spoon", "sport", "spot", "spray", "spread", "spring", "spy", "square",
+ "squeeze", "squirrel", "stable", "stadium", "staff", "stage", "stairs", "stamp", "stand",
+ "start", "state", "stay", "steak", "steel", "stem", "step", "stereo", "stick", "still",
+ "sting", "stock", "stomach", "stone", "stool", "story", "stove", "strategy", "street",
+ "strike", "strong", "struggle", "student", "stuff", "stumble", "style", "subject", "submit",
+ "subway", "success", "such", "sudden", "suffer", "sugar", "suggest", "suit", "summer", "sun",
+ "sunny", "sunset", "super", "supply", "supreme", "sure", "surface", "surge", "surprise",
+ "surround", "survey", "suspect", "sustain", "swallow", "swamp", "swap", "swarm", "swear",
+ "sweet", "swift", "swim", "swing", "switch", "sword", "symbol", "symptom", "syrup", "system",
+ "table", "tackle", "tag", "tail", "talent", "talk", "tank", "tape", "target", "task", "taste",
+ "tattoo", "taxi", "teach", "team", "tell", "ten", "tenant", "tennis", "tent", "term", "test",
+ "text", "thank", "that", "theme", "then", "theory", "there", "they", "thing", "this",
+ "thought", "three", "thrive", "throw", "thumb", "thunder", "ticket", "tide", "tiger", "tilt",
+ "timber", "time", "tiny", "tip", "tired", "tissue", "title", "toast", "tobacco", "today",
+ "toddler", "toe", "together", "toilet", "token", "tomato", "tomorrow", "tone", "tongue",
+ "tonight", "tool", "tooth", "top", "topic", "topple", "torch", "tornado", "tortoise", "toss",
+ "total", "tourist", "toward", "tower", "town", "toy", "track", "trade", "traffic", "tragic",
+ "train", "transfer", "trap", "trash", "travel", "tray", "treat", "tree", "trend", "trial",
+ "tribe", "trick", "trigger", "trim", "trip", "trophy", "trouble", "truck", "true", "truly",
+ "trumpet", "trust", "truth", "try", "tube", "tuition", "tumble", "tuna", "tunnel", "turkey",
+ "turn", "turtle", "twelve", "twenty", "twice", "twin", "twist", "two", "type", "typical",
+ "ugly", "umbrella", "unable", "unaware", "uncle", "uncover", "under", "undo", "unfair",
+ "unfold", "unhappy", "uniform", "unique", "unit", "universe", "unknown", "unlock", "until",
+ "unusual", "unveil", "update", "upgrade", "uphold", "upon", "upper", "upset", "urban", "urge",
+ "usage", "use", "used", "useful", "useless", "usual", "utility", "vacant", "vacuum", "vague",
+ "valid", "valley", "valve", "van", "vanish", "vapor", "various", "vast", "vault", "vehicle",
+ "velvet", "vendor", "venture", "venue", "verb", "verify", "version", "very", "vessel",
+ "veteran", "viable", "vibrant", "vicious", "victory", "video", "view", "village", "vintage",
+ "violin", "virtual", "virus", "visa", "visit", "visual", "vital", "vivid", "vocal", "voice",
+ "void", "volcano", "volume", "vote", "voyage", "wage", "wagon", "wait", "walk", "wall",
+ "walnut", "want", "warfare", "warm", "warrior", "wash", "wasp", "waste", "water", "wave",
+ "way", "wealth", "weapon", "wear", "weasel", "weather", "web", "wedding", "weekend", "weird",
+ "welcome", "west", "wet", "whale", "what", "wheat", "wheel", "when", "where", "whip",
+ "whisper", "wide", "width", "wife", "wild", "will", "win", "window", "wine", "wing", "wink",
+ "winner", "winter", "wire", "wisdom", "wise", "wish", "witness", "wolf", "woman", "wonder",
+ "wood", "wool", "word", "work", "world", "worry", "worth", "wrap", "wreck", "wrestle", "wrist",
+ "write", "wrong", "yard", "year", "yellow", "you", "young", "youth", "zebra", "zero", "zone",
+ "zoo",
+];
diff --git a/ng-wallet/src/lib.rs b/ng-wallet/src/lib.rs
new file mode 100644
index 0000000..63e070c
--- /dev/null
+++ b/ng-wallet/src/lib.rs
@@ -0,0 +1,546 @@
+// Copyright (c) 2022-2023 Niko Bonnieure, Par le Peuple, NextGraph.org developers
+// All rights reserved.
+// Licensed under the Apache License, Version 2.0
+//
+// or the MIT license ,
+// at your option. All files in the project carrying such
+// notice may not be copied, modified, or distributed except
+// according to those terms.
+
+// #[macro_use]
+// extern crate slice_as_array;
+#[macro_use]
+extern crate p2p_net;
+
+pub mod types;
+
+pub mod bip39;
+
+use std::io::Cursor;
+
+use crate::bip39::bip39_wordlist;
+use crate::types::*;
+use aes_gcm_siv::{
+ aead::{heapless::Vec as HeaplessVec, AeadInPlace, KeyInit},
+ Aes256GcmSiv, Nonce,
+};
+use argon2::{Algorithm, Argon2, AssociatedData, ParamsBuilder, Version};
+use chacha20poly1305::XChaCha20Poly1305;
+
+use image::{imageops::FilterType, io::Reader as ImageReader, ImageOutputFormat};
+use safe_transmute::transmute_to_bytes;
+
+use p2p_repo::types::{PubKey, Site, SiteType, Timestamp};
+use p2p_repo::utils::{generate_keypair, now_timestamp, sign, verify};
+use rand::{thread_rng, Rng};
+use serde_bare::{from_slice, to_vec};
+
+pub fn enc_master_key(
+ master_key: [u8; 32],
+ key: [u8; 32],
+ nonce: u8,
+ wallet_id: WalletId,
+) -> Result<[u8; 48], NgWalletError> {
+ let cipher = Aes256GcmSiv::new(&key.into());
+ let mut nonce_buffer = [0u8; 12];
+ nonce_buffer[0] = nonce;
+ let nonce = Nonce::from_slice(&nonce_buffer);
+
+ let mut buffer: HeaplessVec = HeaplessVec::new(); // Note: buffer needs 16-bytes overhead for auth tag
+ buffer.extend_from_slice(&master_key);
+
+ // Encrypt `buffer` in-place, replacing the plaintext contents with ciphertext
+ cipher
+ .encrypt_in_place(nonce, &to_vec(&wallet_id).unwrap(), &mut buffer)
+ .map_err(|e| NgWalletError::EncryptionError)?;
+
+ // `buffer` now contains the encrypted master key
+ // println!("cipher {:?}", buffer);
+ Ok(buffer.into_array::<48>().unwrap())
+}
+
+pub fn dec_master_key(
+ ciphertext: [u8; 48],
+ key: [u8; 32],
+ nonce: u8,
+ wallet_id: WalletId,
+) -> Result<[u8; 32], NgWalletError> {
+ let cipher = Aes256GcmSiv::new(&key.into());
+ let mut nonce_buffer = [0u8; 12];
+ nonce_buffer[0] = nonce;
+ let nonce = Nonce::from_slice(&nonce_buffer);
+
+ let mut buffer: HeaplessVec = HeaplessVec::from_slice(&ciphertext).unwrap(); // Note: buffer needs 16-bytes overhead for auth tag
+
+ // Decrypt `buffer` in-place, replacing its ciphertext context with the original plaintext
+ cipher
+ .decrypt_in_place(nonce, &to_vec(&wallet_id).unwrap(), &mut buffer)
+ .map_err(|e| NgWalletError::DecryptionError)?;
+ Ok(buffer.into_array::<32>().unwrap())
+}
+
+fn gen_nonce(peer_id: PubKey, nonce: u64) -> [u8; 24] {
+ let mut buffer = Vec::with_capacity(24);
+ buffer.extend_from_slice(&peer_id.slice()[0..16]);
+ buffer.extend_from_slice(&nonce.to_be_bytes());
+ buffer.try_into().unwrap()
+}
+
+fn gen_associated_data(timestamp: Timestamp, wallet_id: WalletId) -> Vec {
+ let ser_wallet = to_vec(&wallet_id).unwrap();
+ [ser_wallet, timestamp.to_be_bytes().to_vec()].concat()
+}
+
+pub fn enc_encrypted_block(
+ block: &EncryptedWalletV0,
+ master_key: [u8; 32],
+ peer_id: PubKey,
+ nonce: u64,
+ timestamp: Timestamp,
+ wallet_id: WalletId,
+) -> Result, NgWalletError> {
+ let ser_encrypted_block = to_vec(block).map_err(|e| NgWalletError::InternalError)?;
+
+ let nonce_buffer: [u8; 24] = gen_nonce(peer_id, nonce);
+
+ let cipher = XChaCha20Poly1305::new(&master_key.into());
+
+ let mut buffer: Vec = Vec::with_capacity(ser_encrypted_block.len() + 16); // Note: buffer needs 16-bytes overhead for auth tag
+ buffer.extend_from_slice(&ser_encrypted_block);
+
+ // Encrypt `buffer` in-place, replacing the plaintext contents with ciphertext
+ cipher
+ .encrypt_in_place(
+ &nonce_buffer.into(),
+ &gen_associated_data(timestamp, wallet_id),
+ &mut buffer,
+ )
+ .map_err(|e| NgWalletError::EncryptionError)?;
+
+ // `buffer` now contains the message ciphertext
+ // println!("encrypted_block ciphertext {:?}", buffer);
+
+ Ok(buffer)
+}
+
+pub fn dec_encrypted_block(
+ mut ciphertext: Vec,
+ master_key: [u8; 32],
+ peer_id: PubKey,
+ nonce: u64,
+ timestamp: Timestamp,
+ wallet_id: WalletId,
+) -> Result {
+ let nonce_buffer: [u8; 24] = gen_nonce(peer_id, nonce);
+
+ let cipher = XChaCha20Poly1305::new(&master_key.into());
+
+ // Decrypt `ciphertext` in-place, replacing its ciphertext context with the original plaintext
+ cipher
+ .decrypt_in_place(
+ &nonce_buffer.into(),
+ &gen_associated_data(timestamp, wallet_id),
+ &mut ciphertext,
+ )
+ .map_err(|e| NgWalletError::DecryptionError)?;
+
+ // `ciphertext` now contains the decrypted block
+ //println!("decrypted_block {:?}", ciphertext);
+
+ let decrypted_block =
+ from_slice::(&ciphertext).map_err(|e| NgWalletError::DecryptionError)?;
+
+ Ok(decrypted_block)
+}
+
+pub fn derive_key_from_pass(pass: Vec, salt: [u8; 16], wallet_id: WalletId) -> [u8; 32] {
+ let params = ParamsBuilder::new()
+ .m_cost(50 * 1024)
+ .t_cost(2)
+ .p_cost(1)
+ .data(AssociatedData::new(wallet_id.slice()).unwrap())
+ .output_len(32)
+ .build()
+ .unwrap();
+ let argon = Argon2::new(Algorithm::Argon2id, Version::V0x13, params);
+ let mut out = [0u8; 32];
+ argon.hash_password_into(&pass, &salt, &mut out).unwrap();
+ out
+}
+
+pub fn open_wallet_with_pazzle(
+ wallet: Wallet,
+ pazzle: Vec,
+ pin: [u8; 4],
+) -> Result {
+ verify(&wallet.content_as_bytes(), wallet.sig(), wallet.id())
+ .map_err(|e| NgWalletError::InvalidSignature)?;
+
+ match wallet {
+ Wallet::V0(v0) => {
+ let pazzle_key = derive_key_from_pass(
+ [pazzle, pin.to_vec()].concat(),
+ v0.content.salt_pazzle,
+ v0.id,
+ );
+
+ let master_key = dec_master_key(
+ v0.content.enc_master_key_pazzle,
+ pazzle_key,
+ v0.content.master_nonce,
+ v0.id,
+ )?;
+
+ Ok(EncryptedWallet::V0(dec_encrypted_block(
+ v0.content.encrypted,
+ master_key,
+ v0.content.peer_id,
+ v0.content.nonce,
+ v0.content.timestamp,
+ v0.id,
+ )?))
+ }
+ }
+}
+
+pub fn open_wallet_with_mnemonic(
+ wallet: Wallet,
+ mnemonic: [u16; 12],
+ pin: [u8; 4],
+) -> Result {
+ verify(&wallet.content_as_bytes(), wallet.sig(), wallet.id())
+ .map_err(|e| NgWalletError::InvalidSignature)?;
+
+ match wallet {
+ Wallet::V0(v0) => {
+ let mnemonic_key = derive_key_from_pass(
+ [transmute_to_bytes(&mnemonic), &pin].concat(),
+ v0.content.salt_mnemonic,
+ v0.id,
+ );
+
+ let master_key = dec_master_key(
+ v0.content.enc_master_key_mnemonic,
+ mnemonic_key,
+ v0.content.master_nonce,
+ v0.id,
+ )?;
+
+ Ok(EncryptedWallet::V0(dec_encrypted_block(
+ v0.content.encrypted,
+ master_key,
+ v0.content.peer_id,
+ v0.content.nonce,
+ v0.content.timestamp,
+ v0.id,
+ )?))
+ }
+ }
+}
+
+pub fn display_mnemonic(mnemonic: &[u16; 12]) -> Vec {
+ let res: Vec = mnemonic
+ .into_iter()
+ .map(|i| String::from(bip39_wordlist[*i as usize]))
+ .collect();
+ res
+}
+
+/// creates a Wallet from a pin, a security text and image (with option to send the bootstrap and wallet to nextgraph.one)
+/// and returns the Wallet, the pazzle and the mnemonic
+pub fn create_wallet_v0(
+ security_img: Vec,
+ security_txt: String,
+ pin: [u8; 4],
+ pazzle_length: u8,
+ send_bootstrap: Option<&Bootstrap>,
+ send_wallet: bool,
+ peer_id: PubKey,
+ nonce: u64,
+) -> Result<(Wallet, Vec, [u16; 12]), NgWalletError> {
+ // TODO : use some automatically zeroed variable for the 2 first arguments, and for the returned values
+
+ // pazzle_length can only be 9, 12, or 15
+ if (pazzle_length != 9 && pazzle_length != 12 && pazzle_length != 15) {
+ return Err(NgWalletError::InvalidPazzleLength);
+ }
+
+ // cannot submit wallet if we don't submit also the bootstrap
+ if send_bootstrap.is_none() && send_wallet {
+ return Err(NgWalletError::SubmissionError);
+ }
+
+ // check validity of PIN
+
+ // shouldn't start with 0
+ if pin[0] == 0 {
+ return Err(NgWalletError::InvalidPin);
+ }
+
+ // each digit shouldnt be greater than 9
+ if pin[0] > 9 || pin[1] > 9 || pin[2] > 9 || pin[3] > 9 {
+ return Err(NgWalletError::InvalidPin);
+ }
+
+ // check for uniqueness of each digit
+ if pin[1] == pin[0]
+ || pin[1] == pin[2]
+ || pin[1] == pin[3]
+ || pin[2] == pin[0]
+ || pin[2] == pin[3]
+ || pin[3] == pin[0]
+ {
+ return Err(NgWalletError::InvalidPin);
+ }
+
+ // check for ascending series
+ if pin[1] == pin[0] + 1 && pin[2] == pin[1] + 1 && pin[3] == pin[2] + 1 {
+ return Err(NgWalletError::InvalidPin);
+ }
+
+ // check for descending series
+ if pin[3] >= 3 && pin[2] == pin[3] - 1 && pin[1] == pin[2] - 1 && pin[0] == pin[1] - 1 {
+ return Err(NgWalletError::InvalidPin);
+ }
+
+ // check validity of security text
+ let words: Vec<_> = security_txt.split_whitespace().collect();
+ let new_string = words.join(" ");
+ let count = new_string.chars().count();
+ if count < 10 || count > 100 {
+ return Err(NgWalletError::InvalidSecurityText);
+ }
+
+ // check validity of image
+ let decoded_img = ImageReader::new(Cursor::new(security_img))
+ .with_guessed_format()
+ .map_err(|e| NgWalletError::InvalidSecurityImage)?
+ .decode()
+ .map_err(|e| NgWalletError::InvalidSecurityImage)?;
+
+ if decoded_img.height() < 150 || decoded_img.width() < 150 {
+ return Err(NgWalletError::InvalidSecurityImage);
+ }
+
+ let resized_img = decoded_img.resize_to_fill(400, 400, FilterType::Triangle);
+
+ let buffer: Vec = Vec::with_capacity(100000);
+ let mut cursor = Cursor::new(buffer);
+ resized_img
+ .write_to(&mut cursor, ImageOutputFormat::Jpeg(72))
+ .map_err(|e| NgWalletError::InvalidSecurityImage)?;
+
+ // creating the wallet keys
+
+ let (wallet_key, wallet_id) = generate_keypair();
+
+ let site = Site::create(SiteType::Individual).map_err(|e| NgWalletError::InternalError)?;
+
+ // let mut pazzle_random = vec![0u8; pazzle_length.into()];
+ // getrandom::getrandom(&mut pazzle_random).map_err(|e| NgWalletError::InternalError)?;
+
+ let mut pazzle = vec![0u8; pazzle_length.into()];
+ let mut ran = thread_rng();
+ for i in &mut pazzle {
+ *i = ran.gen_range(0, 16);
+ }
+
+ //println!("pazzle {:?}", pazzle);
+
+ let mut mnemonic = [0u16; 12];
+ for i in &mut mnemonic {
+ *i = ran.gen_range(0, 2048);
+ }
+
+ //println!("mnemonic {:?}", display_mnemonic(&mnemonic));
+
+ //slice_as_array!(&mnemonic, [String; 12])
+ //.ok_or(NgWalletError::InternalError)?
+ //.clone(),
+
+ let encrypted_block = EncryptedWalletV0 {
+ pazzle: pazzle.clone(),
+ mnemonic,
+ pin,
+ sites: vec![site],
+ };
+
+ let mut salt_pazzle = [0u8; 16];
+ getrandom::getrandom(&mut salt_pazzle).map_err(|e| NgWalletError::InternalError)?;
+
+ let mut salt_mnemonic = [0u8; 16];
+ getrandom::getrandom(&mut salt_mnemonic).map_err(|e| NgWalletError::InternalError)?;
+
+ //println!("salt_pazzle {:?}", salt_pazzle);
+ //println!("salt_mnemonic {:?}", salt_mnemonic);
+
+ let pazzle_key = derive_key_from_pass(
+ [pazzle.clone(), pin.to_vec()].concat(),
+ salt_pazzle,
+ wallet_id,
+ );
+
+ let mnemonic_key = derive_key_from_pass(
+ [transmute_to_bytes(&mnemonic), &pin].concat(),
+ salt_mnemonic,
+ wallet_id,
+ );
+
+ let mut master_key = [0u8; 32];
+ getrandom::getrandom(&mut master_key).map_err(|e| NgWalletError::InternalError)?;
+
+ let enc_master_key_pazzle = enc_master_key(master_key, pazzle_key, 0, wallet_id)?;
+
+ let enc_master_key_mnemonic = enc_master_key(master_key, mnemonic_key, 0, wallet_id)?;
+
+ let timestamp = now_timestamp();
+ let encrypted = enc_encrypted_block(
+ &encrypted_block,
+ master_key,
+ peer_id,
+ nonce,
+ timestamp,
+ wallet_id,
+ )?;
+
+ let wallet_content = WalletContentV0 {
+ security_img: cursor.into_inner(),
+ security_txt: new_string,
+ salt_pazzle,
+ salt_mnemonic,
+ enc_master_key_pazzle,
+ enc_master_key_mnemonic,
+ master_nonce: 0,
+ timestamp,
+ peer_id,
+ nonce,
+ encrypted,
+ };
+
+ let ser_wallet = serde_bare::to_vec(&wallet_content).unwrap();
+ let sig = sign(wallet_key, wallet_id, &ser_wallet).unwrap();
+
+ let wallet_v0 = WalletV0 {
+ /// ID
+ id: wallet_id,
+ /// Content
+ content: wallet_content,
+ /// Signature over content by wallet's private key
+ sig,
+ };
+
+ // let content = BootstrapContentV0 { servers: vec![] };
+ // let ser = serde_bare::to_vec(&content).unwrap();
+ // let sig = sign(wallet_key, wallet_id, &ser).unwrap();
+
+ // let bootstrap = Bootstrap::V0(BootstrapV0 {
+ // id: wallet_id,
+ // content,
+ // sig,
+ // });
+
+ // TODO send bootstrap (if)
+ // TODO send wallet (if)
+
+ Ok((Wallet::V0(wallet_v0), pazzle, mnemonic))
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use p2p_repo::utils::generate_keypair;
+ use std::fs::File;
+ use std::io::BufReader;
+ use std::io::Read;
+ use std::io::Write;
+ use std::time::Instant;
+
+ #[test]
+ fn create_wallet() {
+ // loading an image file from disk
+ let f = File::open("tests/valid_security_image.jpg")
+ .expect("open of tests/valid_security_image.jpg");
+ let mut reader = BufReader::new(f);
+ let mut img_buffer = Vec::new();
+ // Read file into vector.
+ reader
+ .read_to_end(&mut img_buffer)
+ .expect("read of valid_security_image.jpg");
+
+ let pin = [5, 2, 9, 1];
+
+ let creation = Instant::now();
+
+ let res = create_wallet_v0(
+ img_buffer,
+ " know yourself ".to_string(),
+ pin,
+ 9,
+ None,
+ false,
+ PubKey::Ed25519PubKey([
+ 119, 251, 253, 29, 135, 199, 254, 50, 134, 67, 1, 208, 117, 196, 167, 107, 2, 113,
+ 98, 243, 49, 90, 7, 0, 157, 58, 14, 187, 14, 3, 116, 86,
+ ]),
+ 0,
+ )
+ .expect("create_wallet_v0");
+
+ log!(
+ "creation of wallet took: {} ms",
+ creation.elapsed().as_millis()
+ );
+ log!("-----------------------------");
+
+ let (wallet, pazzle, mnemonic) = res;
+
+ let mut file = File::create("tests/wallet.ngw").expect("open wallet write file");
+ let ser_wallet = to_vec(&NgFile::V0(NgFileV0::Wallet(wallet.clone()))).unwrap();
+ file.write_all(&ser_wallet);
+
+ log!("wallet id: {:?}", base64_url::encode(&wallet.id().slice()));
+ log!("pazzle {:?}", pazzle);
+ log!("mnemonic {:?}", display_mnemonic(&mnemonic));
+ log!("pin {:?}", pin);
+
+ if let Wallet::V0(v0) = wallet {
+ log!("security text: {:?}", v0.content.security_txt);
+
+ let mut file =
+ File::create("tests/generated_security_image.jpg").expect("open write file");
+ file.write_all(&v0.content.security_img);
+
+ let f = File::open("tests/generated_security_image.jpg.compare")
+ .expect("open of generated_security_image.jpg.compare");
+ let mut reader = BufReader::new(f);
+ let mut generated_security_image_compare = Vec::new();
+ // Read file into vector.
+ reader
+ .read_to_end(&mut generated_security_image_compare)
+ .expect("read of generated_security_image.jpg.compare");
+
+ assert_eq!(v0.content.security_img, generated_security_image_compare);
+
+ let opening_mnemonic = Instant::now();
+
+ let w = open_wallet_with_mnemonic(Wallet::V0(v0.clone()), mnemonic, pin)
+ .expect("open with mnemonic");
+ //println!("encrypted part {:?}", w);
+
+ log!(
+ "opening of wallet with mnemonic took: {} ms",
+ opening_mnemonic.elapsed().as_millis()
+ );
+ let opening_pazzle = Instant::now();
+
+ let w = open_wallet_with_pazzle(Wallet::V0(v0.clone()), pazzle, pin)
+ .expect("open with pazzle");
+ //println!("encrypted part {:?}", w);
+
+ log!(
+ "opening of wallet with pazzle took: {} ms",
+ opening_pazzle.elapsed().as_millis()
+ );
+ }
+ }
+}
diff --git a/ng-wallet/src/types.rs b/ng-wallet/src/types.rs
new file mode 100644
index 0000000..bb03b7b
--- /dev/null
+++ b/ng-wallet/src/types.rs
@@ -0,0 +1,233 @@
+// Copyright (c) 2022-2023 Niko Bonnieure, Par le Peuple, NextGraph.org developers
+// All rights reserved.
+// Licensed under the Apache License, Version 2.0
+//
+// or the MIT license ,
+// at your option. All files in the project carrying such
+// notice may not be copied, modified, or distributed except
+// according to those terms.
+
+use serde::{Deserialize, Serialize};
+use serde_big_array::BigArray;
+
+use p2p_net::types::NetAddr;
+use p2p_repo::types::*;
+
+/// WalletId is a PubKey
+pub type WalletId = PubKey;
+
+/// BootstrapId is a WalletId
+pub type BootstrapId = WalletId;
+
+/// BootstrapServer type
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub enum BoostrapServerTypeV0 {
+ Localhost,
+ BoxPrivate(Vec),
+ BoxPublic(Vec),
+ BoxPublicDyn(Vec), // can be empty
+ Domain(String),
+}
+
+/// BootstrapServer details Version 0
+#[derive(Clone, Debug, Serialize, Deserialize)]
+pub struct BootstrapServerV0 {
+ /// Network addresses
+ pub serverType: BoostrapServerTypeV0,
+
+ /// peerId of the server
+ pub peerId: PubKey,
+}
+
+/// Bootstrap content Version 0
+#[derive(Clone, Debug, Serialize, Deserialize)]
+pub struct BootstrapContentV0 {
+ /// list of servers, in order of preference
+ pub servers: Vec,
+}
+
+/// Bootstrap Version 0
+#[derive(Clone, Debug, Serialize, Deserialize)]
+pub struct BootstrapV0 {
+ /// ID
+ pub id: BootstrapId,
+
+ /// Content
+ pub content: BootstrapContentV0,
+
+ /// Signature over content by wallet's private key
+ pub sig: Sig,
+}
+
+/// Bootstrap info
+#[derive(Clone, Debug, Serialize, Deserialize)]
+pub enum Bootstrap {
+ V0(BootstrapV0),
+}
+
+impl Bootstrap {
+ pub fn id(&self) -> BootstrapId {
+ match self {
+ Bootstrap::V0(v0) => v0.id,
+ }
+ }
+ pub fn content_as_bytes(&self) -> Vec {
+ match self {
+ Bootstrap::V0(v0) => serde_bare::to_vec(&v0.content).unwrap(),
+ }
+ }
+ pub fn sig(&self) -> Sig {
+ match self {
+ Bootstrap::V0(v0) => v0.sig,
+ }
+ }
+}
+
+/// EncryptedWallet block Version 0
+#[derive(Clone, Debug, Serialize, Deserialize)]
+pub struct EncryptedWalletV0 {
+ #[serde(with = "serde_bytes")]
+ pub pazzle: Vec,
+
+ pub mnemonic: [u16; 12],
+
+ pub pin: [u8; 4],
+
+ // first in the list is the main Site (Personal)
+ pub sites: Vec,
+}
+
+/// EncryptedWallet block
+#[derive(Clone, Debug, Serialize, Deserialize)]
+pub enum EncryptedWallet {
+ V0(EncryptedWalletV0),
+}
+
+/// Wallet content Version 0
+#[derive(Clone, Debug, Serialize, Deserialize)]
+pub struct WalletContentV0 {
+ #[serde(with = "serde_bytes")]
+ pub security_img: Vec,
+
+ pub security_txt: String,
+
+ pub salt_pazzle: [u8; 16],
+
+ pub salt_mnemonic: [u8; 16],
+
+ // encrypted master keys. first is encrypted with pazzle, second is encrypted with mnemonic
+ // AD = wallet_id
+ #[serde(with = "BigArray")]
+ pub enc_master_key_pazzle: [u8; 48],
+ #[serde(with = "BigArray")]
+ pub enc_master_key_mnemonic: [u8; 48],
+
+ // nonce for the encryption of masterkey
+ // incremented only if the masterkey changes
+ // be very careful with incrementing this, as a conflict would result in total loss of crypto guarantees.
+ pub master_nonce: u8,
+
+ pub timestamp: Timestamp,
+
+ // the peerId that update this version of the Wallet. this value is truncated by half and concatenated with the nonce
+ pub peer_id: PubKey,
+ pub nonce: u64,
+
+ // EncryptedWallet content encrypted with XChaCha20Poly1305, AD = timestamp and walletID
+ #[serde(with = "serde_bytes")]
+ pub encrypted: Vec,
+}
+
+/// Wallet Version 0
+#[derive(Clone, Debug, Serialize, Deserialize)]
+pub struct WalletV0 {
+ /// ID
+ pub id: WalletId,
+
+ /// Content
+ pub content: WalletContentV0,
+
+ /// Signature over content by wallet's private key
+ pub sig: Sig,
+}
+
+/// Wallet info
+#[derive(Clone, Debug, Serialize, Deserialize)]
+pub enum Wallet {
+ V0(WalletV0),
+}
+
+impl Wallet {
+ pub fn id(&self) -> WalletId {
+ match self {
+ Wallet::V0(v0) => v0.id,
+ }
+ }
+ pub fn content_as_bytes(&self) -> Vec {
+ match self {
+ Wallet::V0(v0) => serde_bare::to_vec(&v0.content).unwrap(),
+ }
+ }
+ pub fn sig(&self) -> Sig {
+ match self {
+ Wallet::V0(v0) => v0.sig,
+ }
+ }
+}
+
+/// Add Wallet Version 0
+#[derive(Clone, Debug, Serialize, Deserialize)]
+pub struct AddWalletV0 {
+ /// wallet. optional (for those who chose not to upload their wallet to nextgraph.one server)
+ pub wallet: Option,
+
+ /// bootstrap
+ pub bootstrap: Bootstrap,
+}
+
+/// Add Wallet
+#[derive(Clone, Debug, Serialize, Deserialize)]
+pub enum AddWallet {
+ V0(AddWalletV0),
+}
+
+impl AddWallet {
+ pub fn id(&self) -> BootstrapId {
+ match self {
+ AddWallet::V0(v0) => v0.bootstrap.id(),
+ }
+ }
+ pub fn bootstrap(&self) -> &Bootstrap {
+ match self {
+ AddWallet::V0(v0) => &v0.bootstrap,
+ }
+ }
+ pub fn wallet(&self) -> Option<&Wallet> {
+ match self {
+ AddWallet::V0(v0) => v0.wallet.as_ref(),
+ }
+ }
+}
+
+#[derive(Debug, Eq, PartialEq, Clone)]
+pub enum NgWalletError {
+ InvalidPin,
+ InvalidPazzleLength,
+ InvalidSecurityImage,
+ InvalidSecurityText,
+ SubmissionError,
+ InternalError,
+ EncryptionError,
+ DecryptionError,
+ InvalidSignature,
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize)]
+pub enum NgFileV0 {
+ Wallet(Wallet),
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize)]
+pub enum NgFile {
+ V0(NgFileV0),
+}
diff --git a/ng-wallet/tests/generated_security_image.jpg.compare b/ng-wallet/tests/generated_security_image.jpg.compare
new file mode 100644
index 0000000..345a6d2
Binary files /dev/null and b/ng-wallet/tests/generated_security_image.jpg.compare differ
diff --git a/ngcli/Cargo.toml b/ngcli/Cargo.toml
index 5fd3d71..84ef21a 100644
--- a/ngcli/Cargo.toml
+++ b/ngcli/Cargo.toml
@@ -13,7 +13,7 @@ p2p-repo = { path = "../p2p-repo" }
p2p-net = { path = "../p2p-net" }
p2p-client-ws = { path = "../p2p-client-ws" }
p2p-broker = { path = "../p2p-broker" }
-p2p-stores-lmdb = { path = "../p2p-stores-lmdb" }
+stores-lmdb = { path = "../stores-lmdb" }
async-std = { version = "1.12.0", features = ["attributes"] }
futures = "0.3.24"
tempfile = "3"
diff --git a/ngcli/src/main.rs b/ngcli/src/main.rs
index 68f3eef..0959f9e 100644
--- a/ngcli/src/main.rs
+++ b/ngcli/src/main.rs
@@ -16,8 +16,8 @@ use futures::{future, pin_mut, stream, SinkExt, StreamExt};
use p2p_broker::broker_store::config::ConfigMode;
use p2p_repo::object::Object;
use p2p_repo::store::{store_max_value_size, store_valid_value_size, HashMapRepoStore, RepoStore};
-use p2p_stores_lmdb::broker_store::LmdbBrokerStore;
-use p2p_stores_lmdb::repo_store::LmdbRepoStore;
+use stores_lmdb::kcv_store::LmdbKCVStore;
+use stores_lmdb::repo_store::LmdbRepoStore;
use rand::rngs::OsRng;
use std::collections::HashMap;
@@ -557,7 +557,7 @@ async fn test_local_connection() {
let master_key: [u8; 32] = [0; 32];
std::fs::create_dir_all(root.path()).unwrap();
println!("{}", root.path().to_str().unwrap());
- let store = LmdbBrokerStore::open(root.path(), master_key);
+ let store = LmdbKCVStore::open(root.path(), master_key);
//let mut server = BrokerServer::new(store, ConfigMode::Local).expect("starting broker");
diff --git a/ngone/Cargo.toml b/ngone/Cargo.toml
new file mode 100644
index 0000000..7b25483
--- /dev/null
+++ b/ngone/Cargo.toml
@@ -0,0 +1,29 @@
+[package]
+name = "ngone"
+version = "0.1.0"
+edition = "2021"
+license = "MIT/Apache-2.0"
+authors = ["Niko PLP "]
+description = "nextgraph.one server. used to bootstrap the app"
+repository = "https://git.nextgraph.org/NextGraph/nextgraph-rs"
+
+[dependencies]
+tokio = { version = "1.27", features = ["full"] }
+warp = "0.3"
+warp-embed = "0.4"
+rust-embed = "6"
+log = "0.4"
+env_logger = "0.10"
+stores-lmdb = { path = "../stores-lmdb" }
+p2p-repo = { path = "../p2p-repo" }
+p2p-net = { path = "../p2p-net" }
+ng-wallet = { path = "../ng-wallet" }
+serde = { version = "1.0.142", features = ["derive"] }
+serde_bare = "0.5.0"
+serde_bytes = "0.11.7"
+serde-big-array = "0.5.1"
+base64-url = "2.0.0"
+slice_as_array = "1.1.0"
+serde_json = "1.0.96"
+debug_print = "1.0.0"
+bytes = "1.0"
\ No newline at end of file
diff --git a/ngone/README.md b/ngone/README.md
new file mode 100644
index 0000000..3bd87ba
--- /dev/null
+++ b/ngone/README.md
@@ -0,0 +1,36 @@
+# nextgraph.one server (ngone)
+
+This server is used internally by NextGraph to redirect users to the right app server from web clients. You probably don't need this server in your infrastructure, even if you decide to self-host a broker under a domain name.
+
+## Install
+
+```
+cd web
+pnpm install
+```
+
+## Dev
+
+```
+cd web
+pnpm run dev
+// in another terminal
+cd ../
+cargo watch -c -w src -x run
+// then open http://localhost:5173/
+```
+
+## Build
+
+```
+cd web
+pnpm run build
+cd ..
+cargo build --release
+```
+
+## run
+
+```
+../target/release/ngone
+```
diff --git a/ngone/data/lock.mdb b/ngone/data/lock.mdb
new file mode 100644
index 0000000..4fe96da
Binary files /dev/null and b/ngone/data/lock.mdb differ
diff --git a/ngone/src/main.rs b/ngone/src/main.rs
new file mode 100644
index 0000000..7895c9d
--- /dev/null
+++ b/ngone/src/main.rs
@@ -0,0 +1,215 @@
+// Copyright (c) 2022-2023 Niko Bonnieure, Par le Peuple, NextGraph.org developers
+// All rights reserved.
+// Licensed under the Apache License, Version 2.0
+//
+// or the MIT license ,
+// at your option. All files in the project carrying such
+// notice may not be copied, modified, or distributed except
+// according to those terms.
+#[macro_use]
+extern crate slice_as_array;
+
+mod store;
+mod types;
+
+use p2p_repo::store::StorageError;
+use warp::reply::Response;
+use warp::{Filter, Reply};
+
+use debug_print::debug_println;
+use rust_embed::RustEmbed;
+use serde_bare::{from_slice, to_vec};
+use serde_json::json;
+use std::sync::Arc;
+use std::{env, fs};
+
+use crate::store::wallet_record::*;
+use crate::types::*;
+use ng_wallet::types::*;
+use p2p_repo::types::*;
+use p2p_repo::utils::{generate_keypair, sign, verify};
+use stores_lmdb::kcv_store::LmdbKCVStore;
+
+#[derive(RustEmbed)]
+#[folder = "web/dist"]
+struct Static;
+
+struct Server {
+ store: LmdbKCVStore,
+}
+
+impl Server {
+ fn add_wallet(&self, bytes: Vec) -> Result {
+ let add_wallet = from_slice::(&bytes).map_err(|e| NgHttpError::InvalidParams)?;
+
+ let bootstrap = add_wallet.bootstrap();
+
+ debug_println!("ADDING wallet {}", bootstrap.id());
+
+ verify(
+ &bootstrap.content_as_bytes(),
+ bootstrap.sig(),
+ bootstrap.id(),
+ )
+ .map_err(|e| NgHttpError::InvalidParams)?;
+
+ match add_wallet.wallet() {
+ Some(wallet) => {
+ verify(&wallet.content_as_bytes(), wallet.sig(), wallet.id())
+ .map_err(|e| NgHttpError::InvalidParams)?;
+ }
+ None => {}
+ }
+
+ let create_wallet_res = WalletRecord::create(&bootstrap.id(), bootstrap, &self.store);
+ match create_wallet_res {
+ Ok(wallet_record) => {
+ match add_wallet.wallet() {
+ Some(wallet) => {
+ let _ = wallet_record.replace_wallet(wallet);
+ }
+ None => {}
+ }
+ return Ok(warp::http::StatusCode::CREATED.into_response());
+ }
+ Err(StorageError::AlreadyExists) => return Err(NgHttpError::AlreadyExists),
+ Err(_) => return Err(NgHttpError::InternalError),
+ }
+ }
+
+ pub fn upload_wallet(&self, bytes: Vec) -> Response {
+ match self.add_wallet(bytes) {
+ Ok(_) => warp::http::StatusCode::CREATED.into_response(),
+ Err(e) => e.into_response(),
+ }
+ }
+
+ fn get_wallet(&self, encoded_id: String) -> Result {
+ debug_println!("DOWNLOAD wallet {}", encoded_id);
+ let id = base64_url::decode(&encoded_id).map_err(|e| NgHttpError::InvalidParams)?;
+ let array = slice_as_array!(&id, [u8; 32]).ok_or(NgHttpError::InvalidParams)?;
+ let wallet_id = PubKey::Ed25519PubKey(*array);
+ let wallet_record =
+ WalletRecord::open(&wallet_id, &self.store).map_err(|e| NgHttpError::NotFound)?;
+ let wallet = wallet_record.wallet().map_err(|e| NgHttpError::NotFound)?;
+ let data = to_vec(&wallet).map_err(|e| NgHttpError::NotFound)?;
+ Ok(Response::new(data.into()))
+ }
+
+ pub fn download_wallet(&self, encoded_id: String) -> Response {
+ match self.get_wallet(encoded_id) {
+ Ok(res) => res,
+ Err(e) => e.into_response(),
+ }
+ }
+
+ fn get_bootstrap(&self, encoded_id: String) -> Result {
+ debug_println!("DOWNLOAD bootstrap {}", encoded_id);
+
+ let id = base64_url::decode(&encoded_id).map_err(|e| NgHttpError::InvalidParams)?;
+ let array = slice_as_array!(&id, [u8; 32]).ok_or(NgHttpError::InvalidParams)?;
+ let wallet_id = PubKey::Ed25519PubKey(*array);
+ let wallet_record =
+ WalletRecord::open(&wallet_id, &self.store).map_err(|e| NgHttpError::NotFound)?;
+ let bootstrap = wallet_record
+ .bootstrap()
+ .map_err(|e| NgHttpError::NotFound)?;
+ let data = json!(bootstrap).to_string();
+ Ok(Response::new(data.into()))
+ }
+
+ pub fn download_bootstrap(&self, encoded_id: String) -> Response {
+ match self.get_bootstrap(encoded_id) {
+ Ok(res) => res,
+ Err(e) => e.into_response(),
+ }
+ }
+
+ // pub fn create_wallet_record(&self, bootstrap: &Bootstrap) {
+ // let wallet = WalletRecord::create(&bootstrap.id(), bootstrap, &self.store).unwrap();
+ // println!(
+ // "wallet created {}",
+ // base64_url::encode(&wallet.id().slice())
+ // );
+ // }
+
+ // pub fn open_wallet_record(&self, wallet_id: &WalletId) -> WalletRecord {
+ // let wallet2 = WalletRecord::open(wallet_id, &self.store).unwrap();
+ // println!(
+ // "wallet opened {}",
+ // base64_url::encode(&wallet2.id().slice())
+ // );
+ // wallet2
+ // }
+}
+
+#[tokio::main]
+async fn main() {
+ if std::env::var("RUST_LOG").is_err() {
+ std::env::set_var("RUST_LOG", "info"); //trace
+ }
+ env_logger::init();
+
+ let path_str = "data";
+ let mut dir = env::current_dir().unwrap();
+ dir.push(path_str);
+ // FIXME: use a real key for encryption at rest
+ let key: [u8; 32] = [0; 32];
+ println!("{}", dir.to_str().unwrap());
+ fs::create_dir_all(dir.clone()).unwrap();
+ let mut store = LmdbKCVStore::open(&dir, key);
+
+ let server = Arc::new(Server { store });
+
+ // let (wallet_key, wallet_id) = generate_keypair();
+ // let content = BootstrapContentV0 { servers: vec![] };
+ // let ser = serde_bare::to_vec(&content).unwrap();
+ // let sig = sign(wallet_key, wallet_id, &ser).unwrap();
+
+ // let bootstrap = Bootstrap::V0(BootstrapV0 {
+ // id: wallet_id,
+ // content,
+ // sig,
+ // });
+
+ // POST /api/v1/wallet with body containing a serialized AddWallet => 201 CREATED
+ let server_for_move = Arc::clone(&server);
+ let wallet_post_api = warp::post()
+ .and(warp::body::content_length_limit(1024 * 1024)) // 1 MB max
+ .and(warp::path!("wallet"))
+ .and(warp::body::bytes())
+ .map(move |bytes: bytes::Bytes| server_for_move.upload_wallet(bytes.to_vec()));
+ // GET /api/v1/wallet/:walletid => 200 OK with body serialized wallet
+ let server_for_move = Arc::clone(&server);
+ let wallet_get_api = warp::get()
+ .and(warp::path!("wallet" / String))
+ .map(move |id| server_for_move.download_wallet(id));
+ // GET /api/v1/bootstrap/:walletid => 200 OK with body serialized bootstrap
+ let server_for_move = Arc::clone(&server);
+ let bootstrap_get_api = warp::get()
+ .and(warp::path!("bootstrap" / String))
+ .map(move |id| server_for_move.download_bootstrap(id));
+ let api_v1 = warp::path!("api" / "v1" / ..)
+ .and(wallet_get_api.or(bootstrap_get_api).or(wallet_post_api));
+ //.with(warp::log("request"));
+
+ let static_files = warp::get().and(warp_embed::embed(&Static)).boxed();
+
+ let mut cors = warp::cors()
+ .allow_methods(vec!["GET", "POST"])
+ .allow_headers(vec!["Content-Type"]);
+
+ #[cfg(not(debug_assertions))]
+ {
+ cors = cors.allow_origin("https://nextgraph.one");
+ }
+ #[cfg(debug_assertions)]
+ {
+ println!("ANY ORIGIN");
+ cors = cors.allow_any_origin();
+ }
+ log::info!("Starting server on http://localhost:3030");
+ warp::serve(api_v1.or(static_files).with(cors))
+ .run(([127, 0, 0, 1], 3030))
+ .await;
+}
diff --git a/ngone/src/store/dynbox.rs b/ngone/src/store/dynbox.rs
new file mode 100644
index 0000000..ffed72a
--- /dev/null
+++ b/ngone/src/store/dynbox.rs
@@ -0,0 +1,101 @@
+// Copyright (c) 2022-2023 Niko Bonnieure, Par le Peuple, NextGraph.org developers
+// All rights reserved.
+// Licensed under the Apache License, Version 2.0
+//
+// or the MIT license ,
+// at your option. All files in the project carrying such
+// notice may not be copied, modified, or distributed except
+// according to those terms.
+
+//! ng-one bootstrap
+
+use p2p_net::types::*;
+use p2p_repo::kcv_store::KCVStore;
+use p2p_repo::store::*;
+use p2p_repo::types::PubKey;
+
+use serde::{Deserialize, Serialize};
+use serde_bare::{from_slice, to_vec};
+
+pub struct DynBox<'a> {
+ /// peer ID
+ id: PubKey,
+ store: &'a dyn KCVStore,
+}
+
+impl<'a> DynBox<'a> {
+ const PREFIX: u8 = b"d"[0];
+
+ // properties' suffixes
+ const ADDRS: u8 = b"a"[0];
+
+ const ALL_PROPERTIES: [u8; 1] = [Self::ADDRS];
+
+ const SUFFIX_FOR_EXIST_CHECK: u8 = Self::ADDRS;
+
+ pub fn open(id: &PubKey, store: &'a dyn KCVStore) -> Result, StorageError> {
+ let opening = DynBox {
+ id: id.clone(),
+ store,
+ };
+ if !opening.exists() {
+ return Err(StorageError::NotFound);
+ }
+ Ok(opening)
+ }
+ pub fn create(
+ id: &PubKey,
+ addrs: &Vec,
+ store: &'a dyn KCVStore,
+ ) -> Result, StorageError> {
+ let acc = DynBox {
+ id: id.clone(),
+ store,
+ };
+ if acc.exists() {
+ return Err(StorageError::BackendError);
+ }
+ store.write_transaction(&|tx| {
+ tx.put(
+ Self::PREFIX,
+ &to_vec(&id)?,
+ Some(Self::ADDRS),
+ &to_vec(&addrs)?,
+ )?;
+ Ok(())
+ })?;
+ Ok(acc)
+ }
+ pub fn exists(&self) -> bool {
+ self.store
+ .get(
+ Self::PREFIX,
+ &to_vec(&self.id).unwrap(),
+ Some(Self::SUFFIX_FOR_EXIST_CHECK),
+ )
+ .is_ok()
+ }
+ pub fn id(&self) -> PubKey {
+ self.id
+ }
+ pub fn replace_addresses(&self, addrs: &Vec) -> Result<(), StorageError> {
+ if !self.exists() {
+ return Err(StorageError::BackendError);
+ }
+ self.store.replace(
+ Self::PREFIX,
+ &to_vec(&self.id)?,
+ Some(Self::ADDRS),
+ to_vec(addrs)?,
+ )
+ }
+ pub fn remove_addresses(&self) -> Result<(), StorageError> {
+ self.store
+ .del(Self::PREFIX, &to_vec(&self.id)?, Some(Self::ADDRS))
+ }
+
+ pub fn del(&self) -> Result<(), StorageError> {
+ self.store
+ .del_all(Self::PREFIX, &to_vec(&self.id)?, &Self::ALL_PROPERTIES)
+ }
+}
diff --git a/ngone/src/store/mod.rs b/ngone/src/store/mod.rs
new file mode 100644
index 0000000..b185ee0
--- /dev/null
+++ b/ngone/src/store/mod.rs
@@ -0,0 +1,3 @@
+pub mod dynbox;
+
+pub mod wallet_record;
diff --git a/ngone/src/store/wallet_record.rs b/ngone/src/store/wallet_record.rs
new file mode 100644
index 0000000..905e0e7
--- /dev/null
+++ b/ngone/src/store/wallet_record.rs
@@ -0,0 +1,129 @@
+// Copyright (c) 2022-2023 Niko Bonnieure, Par le Peuple, NextGraph.org developers
+// All rights reserved.
+// Licensed under the Apache License, Version 2.0
+//
+// or the MIT license ,
+// at your option. All files in the project carrying such
+// notice may not be copied, modified, or distributed except
+// according to those terms.
+
+//! ng-wallet
+
+use ng_wallet::types::*;
+use p2p_repo::kcv_store::KCVStore;
+use p2p_repo::store::*;
+use p2p_repo::types::*;
+use serde::{Deserialize, Serialize};
+use serde_bare::{from_slice, to_vec};
+
+pub struct WalletRecord<'a> {
+ /// Wallet ID
+ id: WalletId,
+ store: &'a dyn KCVStore,
+}
+
+impl<'a> WalletRecord<'a> {
+ const PREFIX: u8 = b"w"[0];
+
+ // properties' suffixes
+ const WALLET: u8 = b"w"[0];
+ const BOOTSTRAP: u8 = b"b"[0];
+
+ const ALL_PROPERTIES: [u8; 2] = [Self::BOOTSTRAP, Self::WALLET];
+
+ const SUFFIX_FOR_EXIST_CHECK: u8 = Self::BOOTSTRAP;
+
+ pub fn open(id: &WalletId, store: &'a dyn KCVStore) -> Result, StorageError> {
+ let opening = WalletRecord {
+ id: id.clone(),
+ store,
+ };
+ if !opening.exists() {
+ return Err(StorageError::NotFound);
+ }
+ Ok(opening)
+ }
+ pub fn create(
+ id: &WalletId,
+ bootstrap: &Bootstrap,
+ store: &'a dyn KCVStore,
+ ) -> Result, StorageError> {
+ let wallet = WalletRecord {
+ id: id.clone(),
+ store,
+ };
+ if wallet.exists() {
+ return Err(StorageError::BackendError);
+ }
+ store.write_transaction(&|tx| {
+ tx.put(
+ Self::PREFIX,
+ &to_vec(&id)?,
+ Some(Self::BOOTSTRAP),
+ &to_vec(bootstrap)?,
+ )?;
+ Ok(())
+ })?;
+ Ok(wallet)
+ }
+ pub fn exists(&self) -> bool {
+ self.store
+ .get(
+ Self::PREFIX,
+ &to_vec(&self.id).unwrap(),
+ Some(Self::SUFFIX_FOR_EXIST_CHECK),
+ )
+ .is_ok()
+ }
+ pub fn id(&self) -> WalletId {
+ self.id
+ }
+ pub fn replace_wallet(&self, wallet: &Wallet) -> Result<(), StorageError> {
+ if !self.exists() {
+ return Err(StorageError::BackendError);
+ }
+ self.store.replace(
+ Self::PREFIX,
+ &to_vec(&self.id)?,
+ Some(Self::WALLET),
+ to_vec(wallet)?,
+ )
+ }
+
+ pub fn replace_bootstrap(&self, boot: &Bootstrap) -> Result<(), StorageError> {
+ if !self.exists() {
+ return Err(StorageError::BackendError);
+ }
+ self.store.replace(
+ Self::PREFIX,
+ &to_vec(&self.id)?,
+ Some(Self::BOOTSTRAP),
+ to_vec(boot)?,
+ )
+ }
+
+ pub fn wallet(&self) -> Result {
+ match self
+ .store
+ .get(Self::PREFIX, &to_vec(&self.id)?, Some(Self::WALLET))
+ {
+ Ok(w) => Ok(from_slice::(&w)?),
+ Err(e) => Err(e),
+ }
+ }
+
+ pub fn bootstrap(&self) -> Result {
+ match self
+ .store
+ .get(Self::PREFIX, &to_vec(&self.id)?, Some(Self::BOOTSTRAP))
+ {
+ Ok(meta) => Ok(from_slice::(&meta)?),
+ Err(e) => Err(e),
+ }
+ }
+
+ pub fn del(&self) -> Result<(), StorageError> {
+ self.store
+ .del_all(Self::PREFIX, &to_vec(&self.id)?, &Self::ALL_PROPERTIES)
+ }
+}
diff --git a/ngone/src/types.rs b/ngone/src/types.rs
new file mode 100644
index 0000000..ebea555
--- /dev/null
+++ b/ngone/src/types.rs
@@ -0,0 +1,30 @@
+// Copyright (c) 2022-2023 Niko Bonnieure, Par le Peuple, NextGraph.org developers
+// All rights reserved.
+// Licensed under the Apache License, Version 2.0
+//
+// or the MIT license ,
+// at your option. All files in the project carrying such
+// notice may not be copied, modified, or distributed except
+// according to those terms.
+
+use warp::{reply::Response, Reply};
+
+pub enum NgHttpError {
+ InvalidParams,
+ NotFound,
+ AlreadyExists,
+ InternalError,
+}
+
+impl Reply for NgHttpError {
+ fn into_response(self) -> Response {
+ match (self) {
+ NgHttpError::NotFound => warp::http::StatusCode::NOT_FOUND.into_response(),
+ NgHttpError::InvalidParams => warp::http::StatusCode::BAD_REQUEST.into_response(),
+ NgHttpError::AlreadyExists => warp::http::StatusCode::CONFLICT.into_response(),
+ NgHttpError::InternalError => {
+ warp::http::StatusCode::INTERNAL_SERVER_ERROR.into_response()
+ }
+ }
+ }
+}
diff --git a/ngone/web/.gitignore b/ngone/web/.gitignore
new file mode 100644
index 0000000..a547bf3
--- /dev/null
+++ b/ngone/web/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/ngone/web/.vscode/extensions.json b/ngone/web/.vscode/extensions.json
new file mode 100644
index 0000000..bdef820
--- /dev/null
+++ b/ngone/web/.vscode/extensions.json
@@ -0,0 +1,3 @@
+{
+ "recommendations": ["svelte.svelte-vscode"]
+}
diff --git a/ngone/web/index.html b/ngone/web/index.html
new file mode 100644
index 0000000..9ab71a4
--- /dev/null
+++ b/ngone/web/index.html
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+ Vite + Svelte
+
+
+
+
+
+
diff --git a/ngone/web/jsconfig.json b/ngone/web/jsconfig.json
new file mode 100644
index 0000000..5696a2d
--- /dev/null
+++ b/ngone/web/jsconfig.json
@@ -0,0 +1,32 @@
+{
+ "compilerOptions": {
+ "moduleResolution": "bundler",
+ "target": "ESNext",
+ "module": "ESNext",
+ /**
+ * svelte-preprocess cannot figure out whether you have
+ * a value or a type, so tell TypeScript to enforce using
+ * `import type` instead of `import` for Types.
+ */
+ "verbatimModuleSyntax": true,
+ "isolatedModules": true,
+ "resolveJsonModule": true,
+ /**
+ * To have warnings / errors of the Svelte compiler at the
+ * correct position, enable source maps by default.
+ */
+ "sourceMap": true,
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ /**
+ * Typecheck JS in `.svelte` and `.js` files by default.
+ * Disable this if you'd like to use dynamic types.
+ */
+ "checkJs": true
+ },
+ /**
+ * Use global.d.ts instead of compilerOptions.types
+ * to avoid limiting type declarations.
+ */
+ "include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.svelte"]
+}
diff --git a/ngone/web/package.json b/ngone/web/package.json
new file mode 100644
index 0000000..4ea51fa
--- /dev/null
+++ b/ngone/web/package.json
@@ -0,0 +1,16 @@
+{
+ "name": "ng-one-web",
+ "private": true,
+ "version": "0.1.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build --base=./",
+ "preview": "vite preview"
+ },
+ "devDependencies": {
+ "@sveltejs/vite-plugin-svelte": "^2.0.4",
+ "svelte": "^3.58.0",
+ "vite": "^4.3.9"
+ }
+}
diff --git a/ngone/web/pnpm-lock.yaml b/ngone/web/pnpm-lock.yaml
new file mode 100644
index 0000000..7d692ce
--- /dev/null
+++ b/ngone/web/pnpm-lock.yaml
@@ -0,0 +1,411 @@
+lockfileVersion: 5.4
+
+specifiers:
+ '@sveltejs/vite-plugin-svelte': ^2.0.4
+ svelte: ^3.58.0
+ vite: ^4.3.9
+
+devDependencies:
+ '@sveltejs/vite-plugin-svelte': 2.4.1_svelte@3.59.1+vite@4.3.9
+ svelte: 3.59.1
+ vite: 4.3.9
+
+packages:
+
+ /@esbuild/android-arm/0.17.19:
+ resolution: {integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/android-arm64/0.17.19:
+ resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/android-x64/0.17.19:
+ resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/darwin-arm64/0.17.19:
+ resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/darwin-x64/0.17.19:
+ resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/freebsd-arm64/0.17.19:
+ resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/freebsd-x64/0.17.19:
+ resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-arm/0.17.19:
+ resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-arm64/0.17.19:
+ resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-ia32/0.17.19:
+ resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-loong64/0.17.19:
+ resolution: {integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==}
+ engines: {node: '>=12'}
+ cpu: [loong64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-mips64el/0.17.19:
+ resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==}
+ engines: {node: '>=12'}
+ cpu: [mips64el]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-ppc64/0.17.19:
+ resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-riscv64/0.17.19:
+ resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==}
+ engines: {node: '>=12'}
+ cpu: [riscv64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-s390x/0.17.19:
+ resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==}
+ engines: {node: '>=12'}
+ cpu: [s390x]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-x64/0.17.19:
+ resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/netbsd-x64/0.17.19:
+ resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [netbsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/openbsd-x64/0.17.19:
+ resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [openbsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/sunos-x64/0.17.19:
+ resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [sunos]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/win32-arm64/0.17.19:
+ resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/win32-ia32/0.17.19:
+ resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/win32-x64/0.17.19:
+ resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@jridgewell/sourcemap-codec/1.4.15:
+ resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
+ dev: true
+
+ /@sveltejs/vite-plugin-svelte-inspector/1.0.2_qiij5gx4uovhfqjpd2vh63pzyq:
+ resolution: {integrity: sha512-Cy1dUMcYCnDVV/hPLXa43YZJ2jGKVW5rA0xuNL9dlmYhT0yoS1g7+FOFSRlgk0BXKk/Oc7grs+8BVA5Iz2fr8A==}
+ engines: {node: ^14.18.0 || >= 16}
+ peerDependencies:
+ '@sveltejs/vite-plugin-svelte': ^2.2.0
+ svelte: ^3.54.0 || ^4.0.0-next.0
+ vite: ^4.0.0
+ dependencies:
+ '@sveltejs/vite-plugin-svelte': 2.4.1_svelte@3.59.1+vite@4.3.9
+ debug: 4.3.4
+ svelte: 3.59.1
+ vite: 4.3.9
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@sveltejs/vite-plugin-svelte/2.4.1_svelte@3.59.1+vite@4.3.9:
+ resolution: {integrity: sha512-bNNKvoRY89ptY7udeBSCmTdCVwkjmMcZ0j/z9J5MuedT8jPjq0zrknAo/jF1sToAza4NVaAgR9AkZoD9oJJmnA==}
+ engines: {node: ^14.18.0 || >= 16}
+ peerDependencies:
+ svelte: ^3.54.0 || ^4.0.0-next.0
+ vite: ^4.0.0
+ dependencies:
+ '@sveltejs/vite-plugin-svelte-inspector': 1.0.2_qiij5gx4uovhfqjpd2vh63pzyq
+ debug: 4.3.4
+ deepmerge: 4.3.1
+ kleur: 4.1.5
+ magic-string: 0.30.0
+ svelte: 3.59.1
+ svelte-hmr: 0.15.2_svelte@3.59.1
+ vite: 4.3.9
+ vitefu: 0.2.4_vite@4.3.9
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /debug/4.3.4:
+ resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+ dependencies:
+ ms: 2.1.2
+ dev: true
+
+ /deepmerge/4.3.1:
+ resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /esbuild/0.17.19:
+ resolution: {integrity: sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==}
+ engines: {node: '>=12'}
+ hasBin: true
+ requiresBuild: true
+ optionalDependencies:
+ '@esbuild/android-arm': 0.17.19
+ '@esbuild/android-arm64': 0.17.19
+ '@esbuild/android-x64': 0.17.19
+ '@esbuild/darwin-arm64': 0.17.19
+ '@esbuild/darwin-x64': 0.17.19
+ '@esbuild/freebsd-arm64': 0.17.19
+ '@esbuild/freebsd-x64': 0.17.19
+ '@esbuild/linux-arm': 0.17.19
+ '@esbuild/linux-arm64': 0.17.19
+ '@esbuild/linux-ia32': 0.17.19
+ '@esbuild/linux-loong64': 0.17.19
+ '@esbuild/linux-mips64el': 0.17.19
+ '@esbuild/linux-ppc64': 0.17.19
+ '@esbuild/linux-riscv64': 0.17.19
+ '@esbuild/linux-s390x': 0.17.19
+ '@esbuild/linux-x64': 0.17.19
+ '@esbuild/netbsd-x64': 0.17.19
+ '@esbuild/openbsd-x64': 0.17.19
+ '@esbuild/sunos-x64': 0.17.19
+ '@esbuild/win32-arm64': 0.17.19
+ '@esbuild/win32-ia32': 0.17.19
+ '@esbuild/win32-x64': 0.17.19
+ dev: true
+
+ /fsevents/2.3.2:
+ resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /kleur/4.1.5:
+ resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /magic-string/0.30.0:
+ resolution: {integrity: sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==}
+ engines: {node: '>=12'}
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.4.15
+ dev: true
+
+ /ms/2.1.2:
+ resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
+ dev: true
+
+ /nanoid/3.3.6:
+ resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+ dev: true
+
+ /picocolors/1.0.0:
+ resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
+ dev: true
+
+ /postcss/8.4.24:
+ resolution: {integrity: sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==}
+ engines: {node: ^10 || ^12 || >=14}
+ dependencies:
+ nanoid: 3.3.6
+ picocolors: 1.0.0
+ source-map-js: 1.0.2
+ dev: true
+
+ /rollup/3.23.0:
+ resolution: {integrity: sha512-h31UlwEi7FHihLe1zbk+3Q7z1k/84rb9BSwmBSr/XjOCEaBJ2YyedQDuM0t/kfOS0IxM+vk1/zI9XxYj9V+NJQ==}
+ engines: {node: '>=14.18.0', npm: '>=8.0.0'}
+ hasBin: true
+ optionalDependencies:
+ fsevents: 2.3.2
+ dev: true
+
+ /source-map-js/1.0.2:
+ resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /svelte-hmr/0.15.2_svelte@3.59.1:
+ resolution: {integrity: sha512-q/bAruCvFLwvNbeE1x3n37TYFb3mTBJ6TrCq6p2CoFbSTNhDE9oAtEfpy+wmc9So8AG0Tja+X0/mJzX9tSfvIg==}
+ engines: {node: ^12.20 || ^14.13.1 || >= 16}
+ peerDependencies:
+ svelte: ^3.19.0 || ^4.0.0-next.0
+ dependencies:
+ svelte: 3.59.1
+ dev: true
+
+ /svelte/3.59.1:
+ resolution: {integrity: sha512-pKj8fEBmqf6mq3/NfrB9SLtcJcUvjYSWyePlfCqN9gujLB25RitWK8PvFzlwim6hD/We35KbPlRteuA6rnPGcQ==}
+ engines: {node: '>= 8'}
+ dev: true
+
+ /vite/4.3.9:
+ resolution: {integrity: sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': '>= 14'
+ less: '*'
+ sass: '*'
+ stylus: '*'
+ sugarss: '*'
+ terser: ^5.4.0
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ less:
+ optional: true
+ sass:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+ dependencies:
+ esbuild: 0.17.19
+ postcss: 8.4.24
+ rollup: 3.23.0
+ optionalDependencies:
+ fsevents: 2.3.2
+ dev: true
+
+ /vitefu/0.2.4_vite@4.3.9:
+ resolution: {integrity: sha512-fanAXjSaf9xXtOOeno8wZXIhgia+CZury481LsDaV++lSvcU2R9Ch2bPh3PYFyoHW+w9LqAeYRISVQjUIew14g==}
+ peerDependencies:
+ vite: ^3.0.0 || ^4.0.0
+ peerDependenciesMeta:
+ vite:
+ optional: true
+ dependencies:
+ vite: 4.3.9
+ dev: true
diff --git a/ngone/web/public/vite.svg b/ngone/web/public/vite.svg
new file mode 100644
index 0000000..e7b8dfb
--- /dev/null
+++ b/ngone/web/public/vite.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/ngone/web/src/App.svelte b/ngone/web/src/App.svelte
new file mode 100644
index 0000000..6c97e0f
--- /dev/null
+++ b/ngone/web/src/App.svelte
@@ -0,0 +1,62 @@
+
+
+
+
+
+ Vite + Svelte
+
+
+
+
+
+
+
+
+ Check out SvelteKit, the official Svelte app framework powered by Vite!
+
+
+ Click on the Vite and Svelte logos to learn more
+
+
+
diff --git a/ngone/web/src/Greeting.svelte b/ngone/web/src/Greeting.svelte
new file mode 100644
index 0000000..f358fd7
--- /dev/null
+++ b/ngone/web/src/Greeting.svelte
@@ -0,0 +1,25 @@
+
+
+{greeting}
diff --git a/ngone/web/src/app.css b/ngone/web/src/app.css
new file mode 100644
index 0000000..7c35f3d
--- /dev/null
+++ b/ngone/web/src/app.css
@@ -0,0 +1,91 @@
+/*
+// Copyright (c) 2022-2023 Niko Bonnieure, Par le Peuple, NextGraph.org developers
+// All rights reserved.
+// Licensed under the Apache License, Version 2.0
+//
+// or the MIT license ,
+// at your option. All files in the project carrying such
+// notice may not be copied, modified, or distributed except
+// according to those terms.
+*/
+
+:root {
+ font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
+ line-height: 1.5;
+ font-weight: 400;
+
+ color-scheme: light dark;
+ color: rgba(255, 255, 255, 0.87);
+ background-color: #242424;
+
+ font-synthesis: none;
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ -webkit-text-size-adjust: 100%;
+}
+
+a {
+ font-weight: 500;
+ color: #646cff;
+ text-decoration: inherit;
+}
+a:hover {
+ color: #535bf2;
+}
+
+body {
+ margin: 0;
+ display: flex;
+ place-items: center;
+ min-width: 320px;
+ min-height: 100vh;
+}
+
+h1 {
+ font-size: 3.2em;
+ line-height: 1.1;
+}
+
+.card {
+ padding: 2em;
+}
+
+#app {
+ max-width: 1280px;
+ margin: 0 auto;
+ padding: 2rem;
+ text-align: center;
+}
+
+button {
+ border-radius: 8px;
+ border: 1px solid transparent;
+ padding: 0.6em 1.2em;
+ font-size: 1em;
+ font-weight: 500;
+ font-family: inherit;
+ background-color: #1a1a1a;
+ cursor: pointer;
+ transition: border-color 0.25s;
+}
+button:hover {
+ border-color: #646cff;
+}
+button:focus,
+button:focus-visible {
+ outline: 4px auto -webkit-focus-ring-color;
+}
+
+@media (prefers-color-scheme: light) {
+ :root {
+ color: #213547;
+ background-color: #ffffff;
+ }
+ a:hover {
+ color: #747bff;
+ }
+ button {
+ background-color: #f9f9f9;
+ }
+}
diff --git a/ngone/web/src/assets/svelte.svg b/ngone/web/src/assets/svelte.svg
new file mode 100644
index 0000000..c5e0848
--- /dev/null
+++ b/ngone/web/src/assets/svelte.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/ngone/web/src/lib/Counter.svelte b/ngone/web/src/lib/Counter.svelte
new file mode 100644
index 0000000..e45f903
--- /dev/null
+++ b/ngone/web/src/lib/Counter.svelte
@@ -0,0 +1,10 @@
+
+
+
diff --git a/ngone/web/src/main.js b/ngone/web/src/main.js
new file mode 100644
index 0000000..8a909a1
--- /dev/null
+++ b/ngone/web/src/main.js
@@ -0,0 +1,8 @@
+import './app.css'
+import App from './App.svelte'
+
+const app = new App({
+ target: document.getElementById('app'),
+})
+
+export default app
diff --git a/ngone/web/src/vite-env.d.ts b/ngone/web/src/vite-env.d.ts
new file mode 100644
index 0000000..4078e74
--- /dev/null
+++ b/ngone/web/src/vite-env.d.ts
@@ -0,0 +1,2 @@
+///
+///
diff --git a/ngone/web/svelte.config.js b/ngone/web/svelte.config.js
new file mode 100644
index 0000000..b0683fd
--- /dev/null
+++ b/ngone/web/svelte.config.js
@@ -0,0 +1,7 @@
+import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
+
+export default {
+ // Consult https://svelte.dev/docs#compile-time-svelte-preprocess
+ // for more information about preprocessors
+ preprocess: vitePreprocess(),
+}
diff --git a/ngone/web/vite.config.js b/ngone/web/vite.config.js
new file mode 100644
index 0000000..d701969
--- /dev/null
+++ b/ngone/web/vite.config.js
@@ -0,0 +1,7 @@
+import { defineConfig } from 'vite'
+import { svelte } from '@sveltejs/vite-plugin-svelte'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [svelte()],
+})
diff --git a/p2p-broker/Cargo.toml b/p2p-broker/Cargo.toml
index 94923fb..fbed176 100644
--- a/p2p-broker/Cargo.toml
+++ b/p2p-broker/Cargo.toml
@@ -12,7 +12,7 @@ debug_print = "1.0.0"
p2p-repo = { path = "../p2p-repo" }
p2p-net = { path = "../p2p-net" }
p2p-client-ws = { path = "../p2p-client-ws" }
-p2p-stores-lmdb = { path = "../p2p-stores-lmdb" }
+stores-lmdb = { path = "../stores-lmdb" }
chacha20 = "0.9.0"
serde = { version = "1.0", features = ["derive"] }
serde_bare = "0.5.0"
diff --git a/p2p-broker/src/broker_store/account.rs b/p2p-broker/src/broker_store/account.rs
index 1842758..3e928ca 100644
--- a/p2p-broker/src/broker_store/account.rs
+++ b/p2p-broker/src/broker_store/account.rs
@@ -1,7 +1,7 @@
// Copyright (c) 2022-2023 Niko Bonnieure, Par le Peuple, NextGraph.org developers
// All rights reserved.
// Licensed under the Apache License, Version 2.0
-//
+//
// or the MIT license ,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
@@ -9,16 +9,16 @@
//! User account
-use p2p_repo::broker_store::BrokerStore;
+use p2p_net::types::*;
+use p2p_repo::kcv_store::KCVStore;
use p2p_repo::store::*;
use p2p_repo::types::*;
-use p2p_net::types::*;
use serde_bare::to_vec;
pub struct Account<'a> {
/// User ID
id: UserId,
- store: &'a dyn BrokerStore,
+ store: &'a dyn KCVStore,
}
impl<'a> Account<'a> {
@@ -33,7 +33,7 @@ impl<'a> Account<'a> {
const SUFFIX_FOR_EXIST_CHECK: u8 = Self::ADMIN;
- pub fn open(id: &UserId, store: &'a dyn BrokerStore) -> Result, StorageError> {
+ pub fn open(id: &UserId, store: &'a dyn KCVStore) -> Result, StorageError> {
let opening = Account {
id: id.clone(),
store,
@@ -46,7 +46,7 @@ impl<'a> Account<'a> {
pub fn create(
id: &UserId,
admin: bool,
- store: &'a dyn BrokerStore,
+ store: &'a dyn KCVStore,
) -> Result, StorageError> {
let acc = Account {
id: id.clone(),
@@ -161,7 +161,7 @@ mod test {
use p2p_repo::store::*;
use p2p_repo::types::*;
use p2p_repo::utils::*;
- use p2p_stores_lmdb::broker_store::LmdbBrokerStore;
+ use stores_lmdb::kcv_store::LmdbKCVStore;
use std::fs;
use tempfile::Builder;
@@ -174,7 +174,7 @@ mod test {
let key: [u8; 32] = [0; 32];
fs::create_dir_all(root.path()).unwrap();
println!("{}", root.path().to_str().unwrap());
- let mut store = LmdbBrokerStore::open(root.path(), key);
+ let mut store = LmdbKCVStore::open(root.path(), key);
let user_id = PubKey::Ed25519PubKey([1; 32]);
diff --git a/p2p-broker/src/broker_store/config.rs b/p2p-broker/src/broker_store/config.rs
index fe896e6..c7aef7b 100644
--- a/p2p-broker/src/broker_store/config.rs
+++ b/p2p-broker/src/broker_store/config.rs
@@ -10,7 +10,7 @@
//! Broker Config, persisted to store
use p2p_net::types::*;
-use p2p_repo::broker_store::BrokerStore;
+use p2p_repo::kcv_store::KCVStore;
use p2p_repo::store::*;
use p2p_repo::types::*;
use serde::{Deserialize, Serialize};
@@ -24,7 +24,7 @@ pub enum ConfigMode {
}
pub struct Config<'a> {
- store: &'a dyn BrokerStore,
+ store: &'a dyn KCVStore,
}
impl<'a> Config<'a> {
@@ -39,7 +39,7 @@ impl<'a> Config<'a> {
const SUFFIX_FOR_EXIST_CHECK: u8 = Self::MODE;
- pub fn open(store: &'a dyn BrokerStore) -> Result, StorageError> {
+ pub fn open(store: &'a dyn KCVStore) -> Result, StorageError> {
let opening = Config { store };
if !opening.exists() {
return Err(StorageError::NotFound);
@@ -48,7 +48,7 @@ impl<'a> Config<'a> {
}
pub fn get_or_create(
mode: &ConfigMode,
- store: &'a dyn BrokerStore,
+ store: &'a dyn KCVStore,
) -> Result, StorageError> {
match Self::open(store) {
Err(e) => {
@@ -66,10 +66,7 @@ impl<'a> Config<'a> {
}
}
}
- pub fn create(
- mode: &ConfigMode,
- store: &'a dyn BrokerStore,
- ) -> Result, StorageError> {
+ pub fn create(mode: &ConfigMode, store: &'a dyn KCVStore) -> Result, StorageError> {
let acc = Config { store };
if acc.exists() {
return Err(StorageError::BackendError);
diff --git a/p2p-broker/src/broker_store/overlay.rs b/p2p-broker/src/broker_store/overlay.rs
index 34f287f..b7cde3e 100644
--- a/p2p-broker/src/broker_store/overlay.rs
+++ b/p2p-broker/src/broker_store/overlay.rs
@@ -1,7 +1,7 @@
// Copyright (c) 2022-2023 Niko Bonnieure, Par le Peuple, NextGraph.org developers
// All rights reserved.
// Licensed under the Apache License, Version 2.0
-//
+//
// or the MIT license ,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
@@ -9,10 +9,10 @@
//! Overlay
-use p2p_repo::broker_store::BrokerStore;
+use p2p_net::types::*;
+use p2p_repo::kcv_store::KCVStore;
use p2p_repo::store::*;
use p2p_repo::types::*;
-use p2p_net::types::*;
use p2p_repo::utils::now_timestamp;
use serde::{Deserialize, Serialize};
use serde_bare::{from_slice, to_vec};
@@ -27,7 +27,7 @@ pub struct OverlayMeta {
pub struct Overlay<'a> {
/// Overlay ID
id: OverlayId,
- store: &'a dyn BrokerStore,
+ store: &'a dyn KCVStore,
}
impl<'a> Overlay<'a> {
@@ -50,7 +50,7 @@ impl<'a> Overlay<'a> {
const SUFFIX_FOR_EXIST_CHECK: u8 = Self::SECRET;
- pub fn open(id: &OverlayId, store: &'a dyn BrokerStore) -> Result, StorageError> {
+ pub fn open(id: &OverlayId, store: &'a dyn KCVStore) -> Result, StorageError> {
let opening = Overlay {
id: id.clone(),
store,
@@ -64,7 +64,7 @@ impl<'a> Overlay<'a> {
id: &OverlayId,
secret: &SymKey,
repo: Option,
- store: &'a dyn BrokerStore,
+ store: &'a dyn KCVStore,
) -> Result, StorageError> {
let acc = Overlay {
id: id.clone(),
@@ -85,7 +85,7 @@ impl<'a> Overlay<'a> {
Self::PREFIX,
&to_vec(&id)?,
Some(Self::REPO),
- & to_vec(&repo.unwrap())?,
+ &to_vec(&repo.unwrap())?,
)?;
}
let meta = OverlayMeta {
diff --git a/p2p-broker/src/broker_store/peer.rs b/p2p-broker/src/broker_store/peer.rs
index 8515ec4..1e5240c 100644
--- a/p2p-broker/src/broker_store/peer.rs
+++ b/p2p-broker/src/broker_store/peer.rs
@@ -10,7 +10,7 @@
//! Peer
use p2p_net::types::*;
-use p2p_repo::broker_store::BrokerStore;
+use p2p_repo::kcv_store::KCVStore;
use p2p_repo::store::*;
use p2p_repo::types::*;
use serde::{Deserialize, Serialize};
@@ -19,7 +19,7 @@ use serde_bare::{from_slice, to_vec};
pub struct Peer<'a> {
/// Topic ID
id: PeerId,
- store: &'a dyn BrokerStore,
+ store: &'a dyn KCVStore,
}
impl<'a> Peer<'a> {
@@ -33,7 +33,7 @@ impl<'a> Peer<'a> {
const SUFFIX_FOR_EXIST_CHECK: u8 = Self::VERSION;
- pub fn open(id: &PeerId, store: &'a dyn BrokerStore) -> Result, StorageError> {
+ pub fn open(id: &PeerId, store: &'a dyn KCVStore) -> Result, StorageError> {
let opening = Peer {
id: id.clone(),
store,
@@ -45,7 +45,7 @@ impl<'a> Peer<'a> {
}
pub fn update_or_create(
advert: &PeerAdvert,
- store: &'a dyn BrokerStore,
+ store: &'a dyn KCVStore,
) -> Result, StorageError> {
let id = advert.peer();
match Self::open(id, store) {
@@ -62,10 +62,7 @@ impl<'a> Peer<'a> {
}
}
}
- pub fn create(
- advert: &PeerAdvert,
- store: &'a dyn BrokerStore,
- ) -> Result, StorageError> {
+ pub fn create(advert: &PeerAdvert, store: &'a dyn KCVStore) -> Result, StorageError> {
let id = advert.peer();
let acc = Peer {
id: id.clone(),
diff --git a/p2p-broker/src/broker_store/repostoreinfo.rs b/p2p-broker/src/broker_store/repostoreinfo.rs
index c4d75b5..7279ede 100644
--- a/p2p-broker/src/broker_store/repostoreinfo.rs
+++ b/p2p-broker/src/broker_store/repostoreinfo.rs
@@ -1,7 +1,7 @@
// Copyright (c) 2022-2023 Niko Bonnieure, Par le Peuple, NextGraph.org developers
// All rights reserved.
// Licensed under the Apache License, Version 2.0
-//
+//
// or the MIT license ,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
@@ -12,10 +12,10 @@
//! A repoStore is identified by its repo pubkey if in local mode
//! In core mode, it is identified by the overlayid.
-use p2p_repo::broker_store::BrokerStore;
+use p2p_net::types::*;
+use p2p_repo::kcv_store::KCVStore;
use p2p_repo::store::*;
use p2p_repo::types::*;
-use p2p_net::types::*;
use serde::{Deserialize, Serialize};
use serde_bare::{from_slice, to_vec};
@@ -34,7 +34,7 @@ use serde_bare::{from_slice, to_vec};
pub struct RepoStoreInfo<'a> {
/// RepoStore ID
id: RepoHash,
- store: &'a dyn BrokerStore,
+ store: &'a dyn KCVStore,
}
impl<'a> RepoStoreInfo<'a> {
@@ -47,10 +47,7 @@ impl<'a> RepoStoreInfo<'a> {
const SUFFIX_FOR_EXIST_CHECK: u8 = Self::KEY;
- pub fn open(
- id: &RepoHash,
- store: &'a dyn BrokerStore,
- ) -> Result, StorageError> {
+ pub fn open(id: &RepoHash, store: &'a dyn KCVStore) -> Result, StorageError> {
let opening = RepoStoreInfo {
id: id.clone(),
store,
@@ -63,7 +60,7 @@ impl<'a> RepoStoreInfo<'a> {
pub fn create(
id: &RepoHash,
key: &SymKey,
- store: &'a dyn BrokerStore,
+ store: &'a dyn KCVStore,
) -> Result, StorageError> {
let acc = RepoStoreInfo {
id: id.clone(),
diff --git a/p2p-broker/src/broker_store/topic.rs b/p2p-broker/src/broker_store/topic.rs
index ba17fca..3fdb1eb 100644
--- a/p2p-broker/src/broker_store/topic.rs
+++ b/p2p-broker/src/broker_store/topic.rs
@@ -1,7 +1,7 @@
// Copyright (c) 2022-2023 Niko Bonnieure, Par le Peuple, NextGraph.org developers
// All rights reserved.
// Licensed under the Apache License, Version 2.0
-//
+//
// or the MIT license ,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
@@ -9,10 +9,10 @@
//! Topic
-use p2p_repo::broker_store::BrokerStore;
+use p2p_net::types::*;
+use p2p_repo::kcv_store::KCVStore;
use p2p_repo::store::*;
use p2p_repo::types::*;
-use p2p_net::types::*;
use serde::{Deserialize, Serialize};
use serde_bare::{from_slice, to_vec};
@@ -25,7 +25,7 @@ pub struct TopicMeta {
pub struct Topic<'a> {
/// Topic ID
id: TopicId,
- store: &'a dyn BrokerStore,
+ store: &'a dyn KCVStore,
}
impl<'a> Topic<'a> {
@@ -40,7 +40,7 @@ impl<'a> Topic<'a> {
const SUFFIX_FOR_EXIST_CHECK: u8 = Self::META;
- pub fn open(id: &TopicId, store: &'a dyn BrokerStore) -> Result, StorageError> {
+ pub fn open(id: &TopicId, store: &'a dyn KCVStore) -> Result, StorageError> {
let opening = Topic {
id: id.clone(),
store,
@@ -50,7 +50,7 @@ impl<'a> Topic<'a> {
}
Ok(opening)
}
- pub fn create(id: &TopicId, store: &'a mut dyn BrokerStore) -> Result, StorageError> {
+ pub fn create(id: &TopicId, store: &'a mut dyn KCVStore) -> Result, StorageError> {
let acc = Topic {
id: id.clone(),
store,
diff --git a/p2p-broker/src/server.rs b/p2p-broker/src/server.rs
index 4066ff3..185ac81 100644
--- a/p2p-broker/src/server.rs
+++ b/p2p-broker/src/server.rs
@@ -36,8 +36,8 @@ use p2p_repo::store::RepoStore;
use p2p_repo::store::StorageError;
use p2p_repo::types::*;
use p2p_repo::utils::*;
-use p2p_stores_lmdb::broker_store::LmdbBrokerStore;
-use p2p_stores_lmdb::repo_store::LmdbRepoStore;
+use stores_lmdb::broker_store::LmdbKCVStore;
+use stores_lmdb::repo_store::LmdbRepoStore;
#[derive(Debug, Eq, PartialEq, Clone)]
pub enum BrokerError {
@@ -526,7 +526,7 @@ pub struct BrokerPeerInfo {
const REPO_STORES_SUBDIR: &str = "repos";
pub struct BrokerServer {
- store: LmdbBrokerStore,
+ store: LmdbKCVStore,
mode: ConfigMode,
repo_stores: Arc>>,
// only used in ConfigMode::Local
@@ -560,7 +560,7 @@ impl BrokerServer {
writer.remove(&peer_id);
}
- pub fn new(store: LmdbBrokerStore, mode: ConfigMode) -> Result {
+ pub fn new(store: LmdbKCVStore, mode: ConfigMode) -> Result {
let mut configmode: ConfigMode;
{
let config = Config::get_or_create(&mode, &store)?;
@@ -579,7 +579,7 @@ impl BrokerServer {
where
F: FnOnce(&LmdbRepoStore) -> Result,
{
- // first let's find it in the BrokerStore.repostoreinfo table in order to get the encryption key
+ // first let's find it in the KCVStore.repostoreinfo table in order to get the encryption key
let info = RepoStoreInfo::open(&repo_hash, &self.store)
.map_err(|e| BrokerError::OverlayNotFound)?;
let key = info.key()?;
@@ -635,7 +635,7 @@ impl BrokerServer {
// }
// // we need to open/create it
- // // first let's find it in the BrokerStore.overlay table to retrieve its repo_pubkey
+ // // first let's find it in the KCVStore.overlay table to retrieve its repo_pubkey
// debug_println!("searching for overlayId {}", overlay_id);
// let overlay = Overlay::open(overlay_id, &self.store)?;
// debug_println!("found overlayId {}", overlay_id);
diff --git a/p2p-broker/src/server_ws.rs b/p2p-broker/src/server_ws.rs
index f7fbb92..cd8207e 100644
--- a/p2p-broker/src/server_ws.rs
+++ b/p2p-broker/src/server_ws.rs
@@ -26,8 +26,8 @@ use p2p_net::types::IP;
use p2p_net::utils::Sensitive;
use p2p_repo::types::{PrivKey, PubKey};
use p2p_repo::utils::generate_keypair;
-use p2p_stores_lmdb::broker_store::LmdbBrokerStore;
-use p2p_stores_lmdb::repo_store::LmdbRepoStore;
+use stores_lmdb::kcv_store::LmdbKCVStore;
+use stores_lmdb::repo_store::LmdbRepoStore;
use std::fs;
use std::ops::Deref;
use std::sync::Arc;
@@ -64,7 +64,7 @@ pub async fn run_server_accept_one(
let master_key: [u8; 32] = [0; 32];
std::fs::create_dir_all(root.path()).unwrap();
println!("{}", root.path().to_str().unwrap());
- let store = LmdbBrokerStore::open(root.path(), master_key);
+ let store = LmdbKCVStore::open(root.path(), master_key);
// TODO: remove this part
// let server: BrokerServer =
@@ -93,7 +93,7 @@ pub async fn run_server(
let master_key: [u8; 32] = [0; 32];
std::fs::create_dir_all(root.path()).unwrap();
println!("{}", root.path().to_str().unwrap());
- let store = LmdbBrokerStore::open(root.path(), master_key);
+ let store = LmdbKCVStore::open(root.path(), master_key);
// TODO: remove this part
// let server: BrokerServer =
diff --git a/p2p-net/Cargo.toml b/p2p-net/Cargo.toml
index decd001..42261e2 100644
--- a/p2p-net/Cargo.toml
+++ b/p2p-net/Cargo.toml
@@ -22,8 +22,8 @@ async-std = { version = "1.12.0", features = ["attributes","unstable"] }
wasm-bindgen = "0.2"
unique_id = "0.1.5"
once_cell = "1.17.1"
-noise-protocol = "0.1.4"
-noise-rust-crypto = "0.5.0"
+noise-protocol = "0.2.0-rc1"
+noise-rust-crypto = "0.6.0-rc.1"
ed25519-dalek = "1.0.1"
[target.'cfg(target_arch = "wasm32")'.dependencies]
diff --git a/p2p-repo/src/broker_store.rs b/p2p-repo/src/kcv_store.rs
similarity index 87%
rename from p2p-repo/src/broker_store.rs
rename to p2p-repo/src/kcv_store.rs
index 68d31dc..610fb91 100644
--- a/p2p-repo/src/broker_store.rs
+++ b/p2p-repo/src/kcv_store.rs
@@ -1,15 +1,14 @@
// Copyright (c) 2022-2023 Niko Bonnieure, Par le Peuple, NextGraph.org developers
// Licensed under the Apache License, Version 2.0
-//
+//
// or the MIT license ,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.
-use crate::store::{StorageError};
-
-pub trait WriteTransaction : ReadTransaction {
+use crate::store::StorageError;
+pub trait WriteTransaction: ReadTransaction {
/// Save a property value to the store.
fn put(
&mut self,
@@ -32,7 +31,12 @@ pub trait WriteTransaction : ReadTransaction {
fn del(&mut self, prefix: u8, key: &Vec, suffix: Option) -> Result<(), StorageError>;
/// Delete all properties of a key from the store.
- fn del_all(&mut self, prefix: u8, key: &Vec, all_suffixes: &[u8]) -> Result<(), StorageError>;
+ fn del_all(
+ &mut self,
+ prefix: u8,
+ key: &Vec,
+ all_suffixes: &[u8],
+ ) -> Result<(), StorageError>;
/// Delete a specific value for a property from the store.
fn del_property_value(
@@ -42,11 +46,9 @@ pub trait WriteTransaction : ReadTransaction {
suffix: Option,
value: &Vec,
) -> Result<(), StorageError>;
-
}
pub trait ReadTransaction {
-
/// Load a property from the store.
fn get(&self, prefix: u8, key: &Vec, suffix: Option) -> Result, StorageError>;
@@ -66,12 +68,13 @@ pub trait ReadTransaction {
suffix: Option,
value: Vec,
) -> Result<(), StorageError>;
-
}
-pub trait BrokerStore : ReadTransaction {
-
- fn write_transaction(&self, method: & dyn Fn(&mut dyn WriteTransaction) -> Result<(), StorageError> ) -> Result<(), StorageError> ;
+pub trait KCVStore: ReadTransaction {
+ fn write_transaction(
+ &self,
+ method: &dyn Fn(&mut dyn WriteTransaction) -> Result<(), StorageError>,
+ ) -> Result<(), StorageError>;
/// Save a property value to the store.
fn put(
@@ -105,6 +108,4 @@ pub trait BrokerStore : ReadTransaction {
suffix: Option,
value: Vec,
) -> Result<(), StorageError>;
-
-
}
diff --git a/p2p-repo/src/lib.rs b/p2p-repo/src/lib.rs
index 3164f82..71a4d2a 100644
--- a/p2p-repo/src/lib.rs
+++ b/p2p-repo/src/lib.rs
@@ -16,4 +16,6 @@ pub mod utils;
pub mod errors;
-pub mod broker_store;
+pub mod kcv_store;
+
+pub mod site;
diff --git a/p2p-repo/src/site.rs b/p2p-repo/src/site.rs
new file mode 100644
index 0000000..4bc8c8a
--- /dev/null
+++ b/p2p-repo/src/site.rs
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2022-2023 Niko Bonnieure, Par le Peuple, NextGraph.org developers
+ * All rights reserved.
+ * Licensed under the Apache License, Version 2.0
+ *
+ * or the MIT license ,
+ * at your option. All files in the project carrying such
+ * notice may not be copied, modified, or distributed except
+ * according to those terms.
+*/
+
+use crate::errors::NgError;
+use crate::types::{Identity, Site, SiteType};
+use crate::utils::{generate_keypair, sign, verify};
+
+impl Site {
+ pub fn create(site_type: SiteType) -> Result {
+ let (site_key, side_id) = generate_keypair();
+
+ let (public_key, public_id) = generate_keypair();
+
+ let (protected_key, protected_id) = generate_keypair();
+
+ let (private_key, private_id) = generate_keypair();
+
+ let site_identity;
+ let public_identity;
+ let protected_identity;
+ let private_identity;
+
+ match site_type {
+ SiteType::Individual => {
+ site_identity = Identity::IndividualSite(side_id);
+ public_identity = Identity::IndividualPublic(public_id);
+ protected_identity = Identity::IndividualProtected(protected_id);
+ private_identity = Identity::IndividualPrivate(private_id);
+ }
+ SiteType::Org => {
+ site_identity = Identity::OrgSite(side_id);
+ public_identity = Identity::OrgPublic(public_id);
+ protected_identity = Identity::OrgProtected(protected_id);
+ private_identity = Identity::OrgPrivate(private_id);
+ }
+ }
+
+ let public_sig = sign(
+ site_key,
+ side_id,
+ &serde_bare::to_vec(&public_identity).unwrap(),
+ )?;
+
+ let protected_sig = sign(
+ site_key,
+ side_id,
+ &serde_bare::to_vec(&protected_identity).unwrap(),
+ )?;
+
+ let private_sig = sign(
+ site_key,
+ side_id,
+ &serde_bare::to_vec(&private_identity).unwrap(),
+ )?;
+
+ Ok(Self {
+ site_type,
+ site_identity,
+ site_key,
+ public_identity,
+ public_key,
+ public_sig,
+ protected_identity,
+ protected_key,
+ protected_sig,
+ private_identity,
+ private_key,
+ private_sig,
+ })
+ }
+}
diff --git a/p2p-repo/src/store.rs b/p2p-repo/src/store.rs
index ad39bec..59d1b09 100644
--- a/p2p-repo/src/store.rs
+++ b/p2p-repo/src/store.rs
@@ -3,7 +3,7 @@
// This code is partly derived from work written by TG x Thoth from P2Pcollab.
// Copyright 2022 TG x Thoth
// Licensed under the Apache License, Version 2.0
-//
+//
// or the MIT license ,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
@@ -13,12 +13,12 @@
use crate::types::*;
+use std::sync::{Arc, RwLock};
use std::{
cmp::min,
collections::{hash_map::Iter, HashMap},
mem::size_of_val,
};
-use std::sync::{Arc, RwLock};
pub trait RepoStore {
/// Load a block from the store.
@@ -37,6 +37,7 @@ pub enum StorageError {
InvalidValue,
BackendError,
SerializationError,
+ AlreadyExists,
}
impl From for StorageError {
@@ -81,7 +82,12 @@ impl HashMapRepoStore {
}
pub fn get_all(&self) -> Vec {
- self.blocks.read().unwrap().values().map(|x| x.clone()).collect()
+ self.blocks
+ .read()
+ .unwrap()
+ .values()
+ .map(|x| x.clone())
+ .collect()
}
}
@@ -102,7 +108,12 @@ impl RepoStore for HashMapRepoStore {
}
fn del(&self, id: &BlockId) -> Result<(Block, usize), StorageError> {
- let block = self.blocks.write().unwrap().remove(id).ok_or(StorageError::NotFound)?;
+ let block = self
+ .blocks
+ .write()
+ .unwrap()
+ .remove(id)
+ .ok_or(StorageError::NotFound)?;
let size = size_of_val(&block);
Ok((block, size))
}
diff --git a/p2p-repo/src/types.rs b/p2p-repo/src/types.rs
index b9f5a0e..abd8fd8 100644
--- a/p2p-repo/src/types.rs
+++ b/p2p-repo/src/types.rs
@@ -89,7 +89,7 @@ impl fmt::Display for PubKey {
}
/// Private key
-#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)]
+#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub enum PrivKey {
Ed25519PrivKey(Ed25519PrivKey),
}
@@ -106,7 +106,7 @@ impl PrivKey {
pub type Ed25519Sig = [[u8; 32]; 2];
/// Cryptographic signature
-#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)]
+#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub enum Sig {
Ed25519Sig(Ed25519Sig),
}
@@ -165,19 +165,54 @@ pub enum PermissionType {
}
/// List of Identity types
+#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub enum Identity {
- ORG_SITE(PubKey),
- PERSO_SITE(PubKey),
- ORG_PUBLIC(PubKey),
- ORG_PROTECTED(PubKey),
- ORG_PRIVATE(PubKey),
- PERSO_PUBLIC(PubKey),
- PERSO_PROTECTED(PubKey),
- PERSO_PRIVATE(PubKey),
- GROUP(RepoId),
- DIALOG(RepoId),
- DOCUMENT(RepoId),
- DIALOG_OVERLAY(Digest),
+ OrgSite(PubKey),
+ IndividualSite(PubKey),
+ OrgPublic(PubKey),
+ OrgProtected(PubKey),
+ OrgPrivate(PubKey),
+ IndividualPublic(PubKey),
+ IndividualProtected(PubKey),
+ IndividualPrivate(PubKey),
+ Group(RepoId),
+ Dialog(RepoId),
+ Document(RepoId),
+ DialogOverlay(Digest),
+}
+
+/// Site type
+#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
+pub enum SiteType {
+ Org,
+ Individual, // formerly Personal
+}
+
+/// Site
+#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
+pub struct Site {
+ pub site_type: SiteType,
+ // Identity::OrgSite or Identity::IndividualSite
+ pub site_identity: Identity,
+ pub site_key: PrivKey,
+
+ // Identity::OrgPublic or Identity::IndividualPublic
+ pub public_identity: Identity,
+ pub public_key: PrivKey,
+ // signature of public_identity with site_key
+ pub public_sig: Sig,
+
+ // Identity::OrgProtected or Identity::IndividualProtected
+ pub protected_identity: Identity,
+ pub protected_key: PrivKey,
+ // signature of protected_identity with site_key
+ pub protected_sig: Sig,
+
+ // Identity::OrgPrivate or Identity::IndividualPrivate
+ pub private_identity: Identity,
+ pub private_key: PrivKey,
+ // signature of private_identity with site_key
+ pub private_sig: Sig,
}
/// RepoHash:
diff --git a/p2p-stores-lmdb/Cargo.toml b/stores-lmdb/Cargo.toml
similarity index 95%
rename from p2p-stores-lmdb/Cargo.toml
rename to stores-lmdb/Cargo.toml
index ebd4c7b..922bda2 100644
--- a/p2p-stores-lmdb/Cargo.toml
+++ b/stores-lmdb/Cargo.toml
@@ -1,5 +1,5 @@
[package]
-name = "p2p-stores-lmdb"
+name = "stores-lmdb"
version = "0.1.0"
edition = "2021"
license = "MIT/Apache-2.0"
diff --git a/p2p-stores-lmdb/src/broker_store.rs b/stores-lmdb/src/kcv_store.rs
similarity index 79%
rename from p2p-stores-lmdb/src/broker_store.rs
rename to stores-lmdb/src/kcv_store.rs
index 1565e4b..e815140 100644
--- a/p2p-stores-lmdb/src/broker_store.rs
+++ b/stores-lmdb/src/kcv_store.rs
@@ -1,13 +1,13 @@
// Copyright (c) 2022-2023 Niko Bonnieure, Par le Peuple, NextGraph.org developers
// All rights reserved.
// Licensed under the Apache License, Version 2.0
-//
+//
// or the MIT license ,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.
-use p2p_repo::broker_store::*;
+use p2p_repo::kcv_store::*;
use p2p_repo::store::*;
use p2p_repo::types::*;
use p2p_repo::utils::*;
@@ -29,29 +29,25 @@ use rkv::{
use serde::{Deserialize, Serialize};
use serde_bare::error::Error;
-
pub struct LmdbTransaction<'a> {
-
- store: &'a LmdbBrokerStore,
+ store: &'a LmdbKCVStore,
writer: Option>>,
-
}
impl<'a> LmdbTransaction<'a> {
-
fn commit(&mut self) {
self.writer.take().unwrap().commit().unwrap();
}
-
}
impl<'a> ReadTransaction for LmdbTransaction<'a> {
/// Load a single value property from the store.
fn get(&self, prefix: u8, key: &Vec, suffix: Option) -> Result, StorageError> {
- let property = LmdbBrokerStore::compute_property(prefix, key, suffix);
-
+ let property = LmdbKCVStore::compute_property(prefix, key, suffix);
+
let mut iter = self
- .store.main_store
+ .store
+ .main_store
.get(self.writer.as_ref().unwrap(), property)
.map_err(|e| StorageError::BackendError)?;
match iter.next() {
@@ -68,10 +64,11 @@ impl<'a> ReadTransaction for LmdbTransaction<'a> {
key: &Vec,
suffix: Option,
) -> Result>, StorageError> {
- let property = LmdbBrokerStore::compute_property(prefix, key, suffix);
-
+ let property = LmdbKCVStore::compute_property(prefix, key, suffix);
+
let mut iter = self
- .store.main_store
+ .store
+ .main_store
.get(self.writer.as_ref().unwrap(), property)
.map_err(|e| StorageError::BackendError)?;
let mut vector: Vec> = vec![];
@@ -95,11 +92,16 @@ impl<'a> ReadTransaction for LmdbTransaction<'a> {
suffix: Option,
value: Vec,
) -> Result<(), StorageError> {
- let property = LmdbBrokerStore::compute_property(prefix, key, suffix);
+ let property = LmdbKCVStore::compute_property(prefix, key, suffix);
let exists = self
- .store.main_store
- .get_key_value(self.writer.as_ref().unwrap(), property, &Value::Blob(value.as_slice()))
+ .store
+ .main_store
+ .get_key_value(
+ self.writer.as_ref().unwrap(),
+ property,
+ &Value::Blob(value.as_slice()),
+ )
.map_err(|e| StorageError::BackendError)?;
if exists {
Ok(())
@@ -107,11 +109,9 @@ impl<'a> ReadTransaction for LmdbTransaction<'a> {
Err(StorageError::NotFound)
}
}
-
}
impl<'a> WriteTransaction for LmdbTransaction<'a> {
-
/// Save a property value to the store.
fn put(
&mut self,
@@ -120,9 +120,14 @@ impl<'a> WriteTransaction for LmdbTransaction<'a> {
suffix: Option,
value: &Vec,
) -> Result<(), StorageError> {
- let property = LmdbBrokerStore::compute_property(prefix, key, suffix);
- self.store.main_store
- .put(self.writer.as_mut().unwrap(), property, &Value::Blob(value.as_slice()))
+ let property = LmdbKCVStore::compute_property(prefix, key, suffix);
+ self.store
+ .main_store
+ .put(
+ self.writer.as_mut().unwrap(),
+ property,
+ &Value::Blob(value.as_slice()),
+ )
.map_err(|e| StorageError::BackendError)?;
Ok(())
@@ -136,14 +141,20 @@ impl<'a> WriteTransaction for LmdbTransaction<'a> {
suffix: Option,
value: &Vec,
) -> Result<(), StorageError> {
- let property = LmdbBrokerStore::compute_property(prefix, key, suffix);
+ let property = LmdbKCVStore::compute_property(prefix, key, suffix);
- self.store.main_store
+ self.store
+ .main_store
.delete_all(self.writer.as_mut().unwrap(), property.clone())
.map_err(|e| StorageError::BackendError)?;
- self.store.main_store
- .put(self.writer.as_mut().unwrap(), property, &Value::Blob(value.as_slice()))
+ self.store
+ .main_store
+ .put(
+ self.writer.as_mut().unwrap(),
+ property,
+ &Value::Blob(value.as_slice()),
+ )
.map_err(|e| StorageError::BackendError)?;
Ok(())
@@ -151,8 +162,9 @@ impl<'a> WriteTransaction for LmdbTransaction<'a> {
/// Delete a property from the store.
fn del(&mut self, prefix: u8, key: &Vec, suffix: Option) -> Result<(), StorageError> {
- let property = LmdbBrokerStore::compute_property(prefix, key, suffix);
- self.store.main_store
+ let property = LmdbKCVStore::compute_property(prefix, key, suffix);
+ self.store
+ .main_store
.delete_all(self.writer.as_mut().unwrap(), property)
.map_err(|e| StorageError::BackendError)?;
@@ -167,16 +179,26 @@ impl<'a> WriteTransaction for LmdbTransaction<'a> {
suffix: Option,
value: &Vec,
) -> Result<(), StorageError> {
- let property = LmdbBrokerStore::compute_property(prefix, key, suffix);
- self.store.main_store
- .delete(self.writer.as_mut().unwrap(), property, &Value::Blob(value.as_slice()))
+ let property = LmdbKCVStore::compute_property(prefix, key, suffix);
+ self.store
+ .main_store
+ .delete(
+ self.writer.as_mut().unwrap(),
+ property,
+ &Value::Blob(value.as_slice()),
+ )
.map_err(|e| StorageError::BackendError)?;
Ok(())
}
/// Delete all properties of a key from the store.
- fn del_all(&mut self, prefix: u8, key: &Vec, all_suffixes: &[u8]) -> Result<(), StorageError> {
+ fn del_all(
+ &mut self,
+ prefix: u8,
+ key: &Vec,
+ all_suffixes: &[u8],
+ ) -> Result<(), StorageError> {
for suffix in all_suffixes {
self.del(prefix, key, Some(*suffix))?;
}
@@ -188,7 +210,7 @@ impl<'a> WriteTransaction for LmdbTransaction<'a> {
}
#[derive(Debug)]
-pub struct LmdbBrokerStore {
+pub struct LmdbKCVStore {
/// the main store where all the properties of keys are stored
main_store: MultiStore,
/// the opened environment so we can create new transactions
@@ -197,8 +219,7 @@ pub struct LmdbBrokerStore {
path: String,
}
-impl ReadTransaction for LmdbBrokerStore {
-
+impl ReadTransaction for LmdbKCVStore {
/// Load a single value property from the store.
fn get(&self, prefix: u8, key: &Vec, suffix: Option) -> Result, StorageError> {
let property = Self::compute_property(prefix, key, suffix);
@@ -263,28 +284,26 @@ impl ReadTransaction for LmdbBrokerStore {
Err(StorageError::NotFound)
}
}
-
-
}
-impl BrokerStore for LmdbBrokerStore {
-
- fn write_transaction(&self, method: & dyn Fn(&mut dyn WriteTransaction) -> Result<(), StorageError> )-> Result<(), StorageError> {
-
+impl KCVStore for LmdbKCVStore {
+ fn write_transaction(
+ &self,
+ method: &dyn Fn(&mut dyn WriteTransaction) -> Result<(), StorageError>,
+ ) -> Result<(), StorageError> {
let lock = self.environment.read().unwrap();
let writer = lock.write().unwrap();
-
+
let mut transaction = LmdbTransaction {
store: self,
writer: Some(writer),
};
let res = method(&mut transaction);
-
+
if res.is_ok() {
transaction.commit();
}
res
-
}
/// Save a property value to the store.
@@ -295,10 +314,7 @@ impl BrokerStore for LmdbBrokerStore {
suffix: Option,
value: Vec,
) -> Result<(), StorageError> {
-
- self.write_transaction(&|tx| {
- tx.put(prefix,key,suffix,&value)
- })
+ self.write_transaction(&|tx| tx.put(prefix, key, suffix, &value))
}
/// Replace the property of a key (single value) to the store.
@@ -309,17 +325,12 @@ impl BrokerStore for LmdbBrokerStore {
suffix: Option,
value: Vec,
) -> Result<(), StorageError> {
-
- self.write_transaction(&|tx| {
- tx.replace(prefix,key,suffix,&value)
- })
+ self.write_transaction(&|tx| tx.replace(prefix, key, suffix, &value))
}
/// Delete a property from the store.
fn del(&self, prefix: u8, key: &Vec, suffix: Option) -> Result<(), StorageError> {
- self.write_transaction(&|tx| {
- tx.del(prefix,key,suffix)
- })
+ self.write_transaction(&|tx| tx.del(prefix, key, suffix))
}
/// Delete a specific value for a property from the store.
@@ -330,9 +341,7 @@ impl BrokerStore for LmdbBrokerStore {
suffix: Option,
value: Vec,
) -> Result<(), StorageError> {
- self.write_transaction(&|tx| {
- tx.del_property_value(prefix,key,suffix, &value)
- })
+ self.write_transaction(&|tx| tx.del_property_value(prefix, key, suffix, &value))
}
/// Delete all properties of a key from the store.
@@ -347,7 +356,7 @@ impl BrokerStore for LmdbBrokerStore {
}
}
-impl LmdbBrokerStore {
+impl LmdbKCVStore {
pub fn path(&self) -> PathBuf {
PathBuf::from(&self.path)
}
@@ -362,9 +371,9 @@ impl LmdbBrokerStore {
new
}
- /// Opens the store and returns a BrokerStore object that should be kept and used to manipulate Accounts, Overlays, Topics and options
+ /// Opens the store and returns a KCVStore object that should be kept and used to manipulate the properties
/// The key is the encryption key for the data at rest.
- pub fn open<'a>(path: &Path, key: [u8; 32]) -> LmdbBrokerStore {
+ pub fn open<'a>(path: &Path, key: [u8; 32]) -> LmdbKCVStore {
let mut manager = Manager::::singleton().write().unwrap();
let shared_rkv = manager
.get_or_create(path, |path| {
@@ -378,7 +387,7 @@ impl LmdbBrokerStore {
let main_store = env.open_multi("main", StoreOptions::create()).unwrap();
- LmdbBrokerStore {
+ LmdbKCVStore {
environment: shared_rkv.clone(),
main_store,
path: path.to_str().unwrap().to_string(),
diff --git a/p2p-stores-lmdb/src/lib.rs b/stores-lmdb/src/lib.rs
similarity index 80%
rename from p2p-stores-lmdb/src/lib.rs
rename to stores-lmdb/src/lib.rs
index 49c50b3..7a62c33 100644
--- a/p2p-stores-lmdb/src/lib.rs
+++ b/stores-lmdb/src/lib.rs
@@ -2,4 +2,4 @@
pub mod repo_store;
#[cfg(not(target_arch = "wasm32"))]
-pub mod broker_store;
+pub mod kcv_store;
diff --git a/p2p-stores-lmdb/src/repo_store.rs b/stores-lmdb/src/repo_store.rs
similarity index 100%
rename from p2p-stores-lmdb/src/repo_store.rs
rename to stores-lmdb/src/repo_store.rs