Merge pull request #39 from kn0sys/kn0sys-dev

j4i2prs integration
This commit is contained in:
c2m 2024-09-23 09:43:51 +00:00 committed by GitHub
commit ba628f99a1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
52 changed files with 4963 additions and 3633 deletions

View file

@ -20,10 +20,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
submodules: 'true'
- name: Install dependencies
run: sudo apt install -y libssl-dev build-essential
- name: Build
run: cargo build --verbose
run: sudo apt install -y libssl-dev build-essential && rustup toolchain install nightly
- name: Build and Clippy
run: RUSTFLAGS="-Z threads=4" cargo +nightly build --future-incompat-report && cargo clippy
- name: Run tests
run: cd neveko-core && RUST_TEST_THREADS=1 cargo test --verbose
run: cd neveko-core && RUST_TEST_THREADS=1 cargo test

19
.gitignore vendored
View file

@ -10,6 +10,21 @@ notes.txt
.vscode/settings.json
*.bz2
*.zip
*/monero-x86_64-linux-gnu-v0.18.3.3/**
*/i2p-zero-linux.v1.20/**
monero-x86_64-linux-gnu-v*/
*.jar
opt/*
*.so
*.config
*.log
*.key
router.info
router.keys.dat
prngseed.rnd
hostsdb.blockfile
certificates/
netDb/*
peerProfiles/*
*.dat
*.txt
*.txt.gz
opt-backup/j4-i2p-rs/jassets/addressbook.war

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "j4-i2p-rs"]
path = j4-i2p-rs
url = https://github.com/kn0sys/j4-i2p-rs.git

305
Cargo.lock generated
View file

@ -71,7 +71,7 @@ dependencies = [
"android-properties",
"bitflags 1.3.2",
"cc",
"jni-sys",
"jni-sys 0.3.0",
"libc 0.2.153",
"log",
"ndk",
@ -249,6 +249,15 @@ version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "383d29d513d8764dcdc42ea295d979eb99c3c9f00607b3692cf68a431f7dca72"
[[package]]
name = "bincode"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
dependencies = [
"serde",
]
[[package]]
name = "bitflags"
version = "1.3.2"
@ -558,16 +567,6 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.3"
@ -658,9 +657,9 @@ dependencies = [
[[package]]
name = "devise"
version = "0.4.1"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6eacefd3f541c66fc61433d65e54e0e46e0a029a819a7dbbc7a7b489e8a85f8"
checksum = "f1d90b0c4c777a2cad215e3c7be59ac7c15adf45cf76317009b7d096d46f651d"
dependencies = [
"devise_codegen",
"devise_core",
@ -668,9 +667,9 @@ dependencies = [
[[package]]
name = "devise_codegen"
version = "0.4.1"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8cf4b8dd484ede80fd5c547592c46c3745a617c8af278e2b72bea86b2dfed6"
checksum = "71b28680d8be17a570a2334922518be6adc3f58ecc880cbb404eaeb8624fd867"
dependencies = [
"devise_core",
"quote",
@ -678,9 +677,9 @@ dependencies = [
[[package]]
name = "devise_core"
version = "0.4.1"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35b50dba0afdca80b187392b24f2499a88c336d5a8493e4b4ccfb608708be56a"
checksum = "b035a542cf7abf01f2e3c4d5a7acbaebfefe120ae4efc7bde3df98186e4b8af7"
dependencies = [
"bitflags 2.6.0",
"proc-macro2",
@ -767,6 +766,12 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
[[package]]
name = "dunce"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
[[package]]
name = "ecolor"
version = "0.21.0"
@ -1027,6 +1032,12 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "fs_extra"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
[[package]]
name = "futures"
version = "0.3.28"
@ -1035,6 +1046,7 @@ checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
@ -1057,12 +1069,34 @@ version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
[[package]]
name = "futures-executor"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964"
[[package]]
name = "futures-macro"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.58",
]
[[package]]
name = "futures-sink"
version = "0.3.28"
@ -1084,6 +1118,7 @@ dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
@ -1108,7 +1143,7 @@ dependencies = [
"libc 0.2.153",
"log",
"rustversion",
"windows",
"windows 0.48.0",
]
[[package]]
@ -1409,7 +1444,7 @@ dependencies = [
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
"windows",
"windows 0.48.0",
]
[[package]]
@ -1524,6 +1559,48 @@ version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
[[package]]
name = "j4-i2p-rs"
version = "0.2.0-alpha"
dependencies = [
"hex",
"j4rs",
"log",
"rand",
"thiserror",
]
[[package]]
name = "j4rs"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "689ae4f2bd4eba82601592f3d22b7e7147b1df52d3b525223f5218990501b4eb"
dependencies = [
"cesu8",
"dunce",
"fs_extra",
"futures",
"glob",
"java-locator",
"jni-sys 0.4.0",
"lazy_static 1.4.0",
"libc 0.2.153",
"libloading 0.8.0",
"log",
"serde",
"serde_json",
]
[[package]]
name = "java-locator"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2abecabd9961c5e01405a6426687fcf1bd94a269927137e4c3cc1a7419b93fd"
dependencies = [
"glob",
"lazy_static 1.4.0",
]
[[package]]
name = "jni"
version = "0.21.1"
@ -1533,7 +1610,7 @@ dependencies = [
"cesu8",
"cfg-if",
"combine",
"jni-sys",
"jni-sys 0.3.0",
"log",
"thiserror",
"walkdir",
@ -1546,6 +1623,25 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
[[package]]
name = "jni-sys"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c30a312d782b8d56a1e0897d45c1af33f31f9b4a4d13d31207a8675e0223b818"
dependencies = [
"jni-sys-macros",
]
[[package]]
name = "jni-sys-macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c199962dfd5610ced8eca382606e349f7940a4ac7d867b58a046123411cbb4"
dependencies = [
"quote",
"syn 1.0.109",
]
[[package]]
name = "jobserver"
version = "0.1.26"
@ -1703,7 +1799,7 @@ version = "0.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
dependencies = [
"libc 0.2.153",
"libc 0.1.12",
]
[[package]]
@ -1855,7 +1951,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0"
dependencies = [
"bitflags 1.3.2",
"jni-sys",
"jni-sys 0.3.0",
"ndk-sys",
"num_enum",
"raw-window-handle",
@ -1874,7 +1970,7 @@ version = "0.4.1+23.1.7779620"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3cf2aae958bd232cac5069850591667ad422d263686d75b52a065f9badeee5a3"
dependencies = [
"jni-sys",
"jni-sys 0.3.0",
]
[[package]]
@ -1915,6 +2011,7 @@ dependencies = [
name = "neveko_core"
version = "0.1.2-beta"
dependencies = [
"bincode",
"chrono",
"clap",
"curve25519-dalek",
@ -1922,6 +2019,7 @@ dependencies = [
"env_logger",
"hex",
"hmac",
"j4-i2p-rs",
"jwt",
"kn0sys-lmdb-rs",
"lazy_static 1.4.0",
@ -1936,6 +2034,8 @@ dependencies = [
"serde",
"serde_json",
"sha2",
"sysinfo",
"thiserror",
"tokio",
]
@ -1943,6 +2043,7 @@ dependencies = [
name = "neveko_gui"
version = "0.1.2-beta"
dependencies = [
"bincode",
"chrono",
"console_error_panic_hook",
"eframe",
@ -2025,6 +2126,15 @@ dependencies = [
"minimal-lexical",
]
[[package]]
name = "ntapi"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4"
dependencies = [
"winapi",
]
[[package]]
name = "nu-ansi-term"
version = "0.46.0"
@ -2484,9 +2594,9 @@ checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9"
[[package]]
name = "rayon"
version = "1.7.0"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
dependencies = [
"either",
"rayon-core",
@ -2494,14 +2604,12 @@ dependencies = [
[[package]]
name = "rayon-core"
version = "1.11.0"
version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-utils",
"num_cpus",
]
[[package]]
@ -3085,6 +3193,20 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
[[package]]
name = "sysinfo"
version = "0.31.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "355dbe4f8799b304b05e1b0f05fc59b2a18d36645cf169607da45bde2f69a1be"
dependencies = [
"core-foundation-sys",
"libc 0.2.153",
"memchr",
"ntapi",
"rayon",
"windows 0.57.0",
]
[[package]]
name = "system-configuration"
version = "0.5.1"
@ -3140,18 +3262,18 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.40"
version = "1.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.40"
version = "1.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
dependencies = [
"proc-macro2",
"quote",
@ -3807,6 +3929,59 @@ dependencies = [
"windows-targets 0.48.0",
]
[[package]]
name = "windows"
version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143"
dependencies = [
"windows-core",
"windows-targets 0.52.6",
]
[[package]]
name = "windows-core"
version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d"
dependencies = [
"windows-implement",
"windows-interface",
"windows-result",
"windows-targets 0.52.6",
]
[[package]]
name = "windows-implement"
version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.58",
]
[[package]]
name = "windows-interface"
version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.58",
]
[[package]]
name = "windows-result"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8"
dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-sys"
version = "0.42.0"
@ -3870,6 +4045,22 @@ dependencies = [
"windows_x86_64_msvc 0.48.0",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm 0.52.6",
"windows_aarch64_msvc 0.52.6",
"windows_i686_gnu 0.52.6",
"windows_i686_gnullvm",
"windows_i686_msvc 0.52.6",
"windows_x86_64_gnu 0.52.6",
"windows_x86_64_gnullvm 0.52.6",
"windows_x86_64_msvc 0.52.6",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.2"
@ -3882,6 +4073,12 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.2"
@ -3894,6 +4091,12 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.42.2"
@ -3906,6 +4109,18 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.42.2"
@ -3918,6 +4133,12 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.2"
@ -3930,6 +4151,12 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.2"
@ -3942,6 +4169,12 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.2"
@ -3954,6 +4187,12 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "winit"
version = "0.28.6"

View file

@ -19,21 +19,21 @@ NEVidebla-EKOnomia (invisible economy)
## Dev
* stack - rust (egui, rocket), lmdb, i2p-zero, monero(rpc, daemon)
* stack - rust (egui, rocket), lmdb, i2p, monero(rpc, daemon)
* install dependencies
* ubuntu example: `sudo apt update -y && sudo apt upgrade -y`
* `sudo apt install -y libssl-dev build-essential`
* `git clone https://github.com/creating2morrow/neveko`
* `git clone --recursive https://github.com/creating2morrow/neveko`
* `cd neveko && ./scripts/build_all_and_run.sh "-- -h"`
* Example to start neveko with remote stagenet node / i2p proxy remote for development:
* `./scripts/build_all_and_run.sh "-- --monero-location monero-x86_64-linux-gnu-v0.18.3.3 --monero-rpc-host http://127.0.0.1:38083 --monero-rpc-daemon http://xmr3kaacphwkk4z2gp35bdl47lrrnzimmyqj4oliauqrjzqecofa.b32.i2p:38081 --monero-rpc-username user --monero-rpc-cred pass --remote-node --i2p-advanced --i2p-tunnels-json /home/user/neveko/i2p-manual/config --i2p-proxy-host http://x.x.x.x:xxxx --i2p-socks-proxy-host http://x.x.x.x:xxxx"`
* `./scripts/build_all_and_run.sh "-- --monero-location monero-x86_64-linux-gnu-v0.18.3.4 --monero-rpc-host http://127.0.0.1:38083 --monero-rpc-daemon http://xmr3kaacphwkk4z2gp35bdl47lrrnzimmyqj4oliauqrjzqecofa.b32.i2p:38081 --monero-rpc-username user --monero-rpc-cred pass --remote-node --i2p-advanced --i2p-tunnels-json /home/user/neveko/i2p-manual/config --i2p-proxy-host http://x.x.x.x:xxxx --i2p-socks-proxy-host http://x.x.x.x:xxxx"`
* the `--monero-location` flag is needed even when using a remote node because
neveko has its own monero-wallet-rpc instance
* remote nodes are forced over the `--i2p-proxy-host`
* Recommended neveko-core startup with full node and i2p-zero locally running:
* ` ./scripts/build_all_and_run.sh "-- --monero-blockchain-dir=/home/user/.bitmonero --monero-location monero-x86_64-linux-gnu-v0.18.3.3 --i2p-zero-dir /home/user/i2p-zero-linux.v1.21/ --monero-blockchain-dir /home/user/.bitmonero"`
* Recommended neveko-core startup with full node:
* ` ./scripts/build_all_and_run.sh "-- --monero-blockchain-dir=/home/user/.bitmonero --monero-location monero-x86_64-linux-gnu-v0.18.3.4 --monero-blockchain-dir /home/user/.bitmonero"`
* monerod doesn't need to be running because neveko will start it and monero-wallet-rpc
* gui will automatically detect monerod, rpc and i2p-zero if neveko core is started first
* gui will automatically detect monerod, rpc if neveko core is started first
* Neveko doesn't write logs to file. Use the command below to write to a log file:
```bash
{NEVEKO_START_CMDS} > neveko.log 2>&1
@ -41,13 +41,14 @@ NEVidebla-EKOnomia (invisible economy)
* just remember to put cli password in the original window, not the log file window
* https://stackoverflow.com/questions/6674327/redirect-all-output-to-file-in-bash
* gui built with rust [egui](https://docs.rs/egui/latest/egui/)
* copy the `certificates` directory from `j4-i2p-rs` to `neveko` root
* see [j4-i2p-rs](https://github.com/kn0sys/j4-i2p-rs) for more information on embedded i2p
* darknet release server links are located at: http://neveko.i2p/index.txt
## Installation Mananger
* additional required software can be downloaded from the gui home or `Binaries` links below
* additional required software can be downloaded from `Binaries` links below
* hashes are in core [lib.rs](./neveko-core/src/lib.rs)
* download i2p-zero, put the path in the connection manager or cli `--i2p-zero-dir` flag
* download monero, update connection manager or cli
* `--monero-blockchain-dir`, where to put lmdb for monero (e.g. path/to/ssd)
* `--monero-location`, path to monero download
@ -101,7 +102,6 @@ NEVidebla-EKOnomia (invisible economy)
* can be overriden with remote node
* use the `--remote-node` flag
* [monero-wallet-rpc](https://www.getmonero.org/downloads/#cli) - (not included) interface for xmr wallet ops
* [i2p-zero](https://github.com/creating2morrow/i2p-zero/releases/tag/v1.21-neveko) - (not included) tunnel creation and http proxy
most of the complex logic stays in neveko-core, exported from [lib.rs](./neveko-core/src/lib.rs)

1
j4-i2p-rs Submodule

@ -0,0 +1 @@
Subproject commit 35874a836a66059fe4d177a8d8e8061c454d9d87

468
neveko-auth/Cargo.lock generated
View file

@ -17,7 +17,7 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
@ -127,10 +127,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "383d29d513d8764dcdc42ea295d979eb99c3c9f00607b3692cf68a431f7dca72"
[[package]]
name = "bitflags"
version = "0.7.0"
name = "bincode"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
dependencies = [
"serde",
]
[[package]]
name = "bitflags"
@ -140,9 +143,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.0.2"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "487f1e0fcbe47deb8b0574e646def1c903389d95241dd1bbcc6ce4a715dfc0c1"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "block-buffer"
@ -180,6 +183,12 @@ version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
[[package]]
name = "cesu8"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
[[package]]
name = "cfg-if"
version = "1.0.0"
@ -286,7 +295,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
dependencies = [
"core-foundation-sys",
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
@ -301,9 +310,34 @@ version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "280a9f2d8b3a38871a3c8a46fb80db65e5e5ed97da80c4d08bf27fb63e35e181"
dependencies = [
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
[[package]]
name = "crypto-common"
version = "0.1.6"
@ -316,15 +350,14 @@ dependencies = [
[[package]]
name = "curve25519-dalek"
version = "4.1.2"
version = "4.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348"
checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be"
dependencies = [
"cfg-if",
"cpufeatures",
"curve25519-dalek-derive",
"fiat-crypto",
"platforms",
"rustc_version",
"subtle",
"zeroize",
@ -411,7 +444,7 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35b50dba0afdca80b187392b24f2499a88c336d5a8493e4b4ccfb608708be56a"
dependencies = [
"bitflags 2.0.2",
"bitflags 2.6.0",
"proc-macro2",
"proc-macro2-diagnostics",
"quote",
@ -463,6 +496,12 @@ dependencies = [
"url",
]
[[package]]
name = "dunce"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
[[package]]
name = "either"
version = "1.8.1"
@ -486,7 +525,7 @@ checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0"
dependencies = [
"humantime",
"is-terminal",
"log 0.4.17",
"log",
"regex",
"termcolor",
]
@ -498,7 +537,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50d6a0976c999d473fe89ad888d5a284e55366d9dc9038b1ba2aa15128c4afa0"
dependencies = [
"errno-dragonfly",
"libc 0.2.140",
"libc 0.2.158",
"windows-sys 0.45.0",
]
@ -509,7 +548,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
dependencies = [
"cc",
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
@ -571,6 +610,12 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "fs_extra"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
[[package]]
name = "futures"
version = "0.3.27"
@ -579,6 +624,7 @@ checksum = "531ac96c6ff5fd7c62263c5e3c67a603af4fcaee2e1a0ae5565ba3a11e69e549"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
@ -601,12 +647,34 @@ version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86d7a0c1aa76363dac491de0ee99faf6941128376f1cf96f07db7603b7de69dd"
[[package]]
name = "futures-executor"
version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1997dd9df74cdac935c76252744c1ed5794fac083242ea4fe77ef3ed60ba0f83"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89d422fa3cbe3b40dca574ab087abb5bc98258ea57eea3fd6f1fa7162c778b91"
[[package]]
name = "futures-macro"
version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3eb14ed937631bd8b8b8977f2c198443447a8355b6e3ca599f38c975e5a963b6"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "futures-sink"
version = "0.3.27"
@ -628,6 +696,7 @@ dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
@ -649,8 +718,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33a20a288a94683f5f4da0adecdbe095c94a77c295e514cc6484e9394dd8376e"
dependencies = [
"cc",
"libc 0.2.140",
"log 0.4.17",
"libc 0.2.158",
"log",
"rustversion",
"windows 0.44.0",
]
@ -672,7 +741,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
dependencies = [
"cfg-if",
"libc 0.2.140",
"libc 0.2.158",
"wasi 0.11.0+wasi-snapshot-preview1",
]
@ -719,7 +788,7 @@ version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
dependencies = [
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
@ -887,7 +956,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09270fd4fa1111bc614ed2246c7ef56239a3063d5be0d1ec3b589c505d400aeb"
dependencies = [
"hermit-abi 0.3.1",
"libc 0.2.140",
"libc 0.2.158",
"windows-sys 0.45.0",
]
@ -915,6 +984,67 @@ version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
[[package]]
name = "j4-i2p-rs"
version = "0.2.0-alpha"
dependencies = [
"hex",
"j4rs",
"log",
"rand",
"thiserror",
]
[[package]]
name = "j4rs"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "689ae4f2bd4eba82601592f3d22b7e7147b1df52d3b525223f5218990501b4eb"
dependencies = [
"cesu8",
"dunce",
"fs_extra",
"futures",
"glob",
"java-locator",
"jni-sys",
"lazy_static 1.4.0",
"libc 0.2.158",
"libloading",
"log",
"serde",
"serde_json",
]
[[package]]
name = "java-locator"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2abecabd9961c5e01405a6426687fcf1bd94a269927137e4c3cc1a7419b93fd"
dependencies = [
"glob",
"lazy_static 1.4.0",
]
[[package]]
name = "jni-sys"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c30a312d782b8d56a1e0897d45c1af33f31f9b4a4d13d31207a8675e0223b818"
dependencies = [
"jni-sys-macros",
]
[[package]]
name = "jni-sys-macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c199962dfd5610ced8eca382606e349f7940a4ac7d867b58a046123411cbb4"
dependencies = [
"quote",
"syn 1.0.109",
]
[[package]]
name = "js-sys"
version = "0.3.61"
@ -939,6 +1069,18 @@ dependencies = [
"sha2 0.10.6",
]
[[package]]
name = "kn0sys-lmdb-rs"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58fbf491e9e95a325cbfe1459734cec781c0145c0d5cb7c4ced71af742364d19"
dependencies = [
"bitflags 2.6.0",
"libc 0.2.158",
"liblmdb-sys",
"log",
]
[[package]]
name = "lazy_static"
version = "0.2.11"
@ -959,9 +1101,9 @@ checksum = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122"
[[package]]
name = "libc"
version = "0.2.140"
version = "0.2.158"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
[[package]]
name = "liblmdb-sys"
@ -970,7 +1112,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "feed38a3a580f60bf61aaa067b0ff4123395966839adeaf67258a9e50c4d2e49"
dependencies = [
"gcc",
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
name = "libloading"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4"
dependencies = [
"cfg-if",
"windows-targets 0.52.6",
]
[[package]]
@ -988,18 +1140,6 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd550e73688e6d578f0ac2119e32b797a327631a42f9433e59d02e139c8df60d"
[[package]]
name = "lmdb-rs"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4aefe7b433f795629ce42f35ccf7a620c38bd457238bfaa2489dafc7e36167e7"
dependencies = [
"bitflags 0.7.0",
"libc 0.2.140",
"liblmdb-sys",
"log 0.3.9",
]
[[package]]
name = "lock_api"
version = "0.4.9"
@ -1012,21 +1152,9 @@ dependencies = [
[[package]]
name = "log"
version = "0.3.9"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
dependencies = [
"log 0.4.17",
]
[[package]]
name = "log"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "loom"
@ -1081,8 +1209,8 @@ version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
dependencies = [
"libc 0.2.140",
"log 0.4.17",
"libc 0.2.158",
"log",
"wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys 0.45.0",
]
@ -1098,7 +1226,7 @@ dependencies = [
"futures-util",
"http",
"httparse",
"log 0.4.17",
"log",
"memchr",
"mime",
"spin",
@ -1114,8 +1242,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e"
dependencies = [
"lazy_static 1.4.0",
"libc 0.2.140",
"log 0.4.17",
"libc 0.2.158",
"log",
"openssl",
"openssl-probe",
"openssl-sys",
@ -1130,7 +1258,7 @@ name = "neveko_auth"
version = "0.1.2-beta"
dependencies = [
"env_logger",
"log 0.4.17",
"log",
"neveko_core",
"rocket",
]
@ -1139,6 +1267,7 @@ dependencies = [
name = "neveko_core"
version = "0.1.2-beta"
dependencies = [
"bincode",
"chrono",
"clap",
"curve25519-dalek",
@ -1146,10 +1275,11 @@ dependencies = [
"env_logger",
"hex",
"hmac",
"j4-i2p-rs",
"jwt",
"kn0sys-lmdb-rs",
"lazy_static 1.4.0",
"lmdb-rs",
"log 0.4.17",
"log",
"num",
"rand",
"rand_core",
@ -1160,9 +1290,20 @@ dependencies = [
"serde",
"serde_json",
"sha2 0.10.6",
"sysinfo",
"thiserror",
"tokio",
]
[[package]]
name = "ntapi"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4"
dependencies = [
"winapi",
]
[[package]]
name = "nu-ansi-term"
version = "0.46.0"
@ -1256,7 +1397,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
dependencies = [
"hermit-abi 0.2.6",
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
@ -1280,7 +1421,7 @@ dependencies = [
"bitflags 1.3.2",
"cfg-if",
"foreign-types",
"libc 0.2.140",
"libc 0.2.158",
"once_cell",
"openssl-macros",
"openssl-sys",
@ -1311,7 +1452,7 @@ checksum = "666416d899cf077260dac8698d60a60b435a46d57e82acb1be3d0dad87284e5b"
dependencies = [
"autocfg",
"cc",
"libc 0.2.140",
"libc 0.2.158",
"pkg-config",
"vcpkg",
]
@ -1339,7 +1480,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
dependencies = [
"cfg-if",
"libc 0.2.140",
"libc 0.2.158",
"redox_syscall 0.2.16",
"smallvec",
"windows-sys 0.45.0",
@ -1392,12 +1533,6 @@ version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
[[package]]
name = "platforms"
version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7"
[[package]]
name = "ppv-lite86"
version = "0.2.17"
@ -1441,7 +1576,7 @@ version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc 0.2.140",
"libc 0.2.158",
"rand_chacha",
"rand_core",
]
@ -1465,6 +1600,26 @@ dependencies = [
"getrandom",
]
[[package]]
name = "rayon"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
]
[[package]]
name = "redox_syscall"
version = "0.2.16"
@ -1547,7 +1702,7 @@ dependencies = [
"hyper-tls",
"ipnet",
"js-sys",
"log 0.4.17",
"log",
"mime",
"native-tls",
"once_cell",
@ -1582,7 +1737,7 @@ dependencies = [
"futures",
"indexmap",
"is-terminal",
"log 0.4.17",
"log",
"memchr",
"multer",
"num_cpus",
@ -1633,7 +1788,7 @@ dependencies = [
"http",
"hyper",
"indexmap",
"log 0.4.17",
"log",
"memchr",
"pear",
"percent-encoding",
@ -1676,7 +1831,7 @@ dependencies = [
"bitflags 1.3.2",
"errno",
"io-lifetimes",
"libc 0.2.140",
"libc 0.2.158",
"linux-raw-sys",
"windows-sys 0.45.0",
]
@ -1738,7 +1893,7 @@ dependencies = [
"bitflags 1.3.2",
"core-foundation",
"core-foundation-sys",
"libc 0.2.140",
"libc 0.2.158",
"security-framework-sys",
]
@ -1749,7 +1904,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4"
dependencies = [
"core-foundation-sys",
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
@ -1840,7 +1995,7 @@ version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
dependencies = [
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
@ -1864,7 +2019,7 @@ version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"
dependencies = [
"libc 0.2.140",
"libc 0.2.158",
"winapi",
]
@ -1926,6 +2081,20 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "sysinfo"
version = "0.31.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "355dbe4f8799b304b05e1b0f05fc59b2a18d36645cf169607da45bde2f69a1be"
dependencies = [
"core-foundation-sys",
"libc 0.2.158",
"memchr",
"ntapi",
"rayon",
"windows 0.57.0",
]
[[package]]
name = "tempfile"
version = "3.5.0"
@ -1957,6 +2126,26 @@ dependencies = [
"libc 0.1.12",
]
[[package]]
name = "thiserror"
version = "1.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.58",
]
[[package]]
name = "thread_local"
version = "1.1.7"
@ -1973,7 +2162,7 @@ version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
dependencies = [
"libc 0.2.140",
"libc 0.2.158",
"wasi 0.10.0+wasi-snapshot-preview1",
"winapi",
]
@ -2028,7 +2217,7 @@ checksum = "d0de47a4eecbe11f498978a9b29d792f0d2692d1dd003650c24c76510e3bc001"
dependencies = [
"autocfg",
"bytes",
"libc 0.2.140",
"libc 0.2.158",
"mio",
"num_cpus",
"pin-project-lite",
@ -2139,7 +2328,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922"
dependencies = [
"lazy_static 1.4.0",
"log 0.4.17",
"log",
"tracing-core",
]
@ -2266,7 +2455,7 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
dependencies = [
"log 0.4.17",
"log",
"try-lock",
]
@ -2299,7 +2488,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
dependencies = [
"bumpalo",
"log 0.4.17",
"log",
"once_cell",
"proc-macro2",
"quote",
@ -2407,6 +2596,59 @@ dependencies = [
"windows-targets 0.47.0",
]
[[package]]
name = "windows"
version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143"
dependencies = [
"windows-core",
"windows-targets 0.52.6",
]
[[package]]
name = "windows-core"
version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d"
dependencies = [
"windows-implement",
"windows-interface",
"windows-result",
"windows-targets 0.52.6",
]
[[package]]
name = "windows-implement"
version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.58",
]
[[package]]
name = "windows-interface"
version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.58",
]
[[package]]
name = "windows-result"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8"
dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-sys"
version = "0.42.0"
@ -2461,6 +2703,22 @@ dependencies = [
"windows_x86_64_msvc 0.47.0",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm 0.52.6",
"windows_aarch64_msvc 0.52.6",
"windows_i686_gnu 0.52.6",
"windows_i686_gnullvm",
"windows_i686_msvc 0.52.6",
"windows_x86_64_gnu 0.52.6",
"windows_x86_64_gnullvm 0.52.6",
"windows_x86_64_msvc 0.52.6",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.2"
@ -2473,6 +2731,12 @@ version = "0.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "831d567d53d4f3cb1db332b68e6e2b6260228eb4d99a777d8b2e8ed794027c90"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.2"
@ -2485,6 +2749,12 @@ version = "0.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a42d54a417c60ce4f0e31661eed628f0fa5aca73448c093ec4d45fab4c51cdf"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.42.2"
@ -2497,6 +2767,18 @@ version = "0.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1925beafdbb22201a53a483db861a5644123157c1c3cee83323a2ed565d71e3"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.42.2"
@ -2509,6 +2791,12 @@ version = "0.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a8ef8f2f1711b223947d9b69b596cf5a4e452c930fb58b6fc3fdae7d0ec6b31"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.2"
@ -2521,6 +2809,12 @@ version = "0.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7acaa0c2cf0d2ef99b61c308a0c3dbae430a51b7345dedec470bd8f53f5a3642"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.2"
@ -2533,6 +2827,12 @@ version = "0.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5a0628f71be1d11e17ca4a0e9e15b3a5180f6fbf1c2d55e3ba3f850378052c1"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.2"
@ -2545,6 +2845,12 @@ version = "0.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d6e62c256dc6d40b8c8707df17df8d774e60e39db723675241e7c15e910bce7"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "winreg"
version = "0.10.1"

View file

@ -17,6 +17,6 @@ use neveko_core::{
/// Creates user on initial login
#[get("/login/<signature>/<aid>/<uid>")]
pub async fn login(aid: String, uid: String, signature: String) -> Custom<Json<Authorization>> {
let m_auth: Authorization = auth::verify_login(aid, uid, signature).await;
Custom(Status::Created, Json(m_auth))
let m_auth = auth::verify_login(aid, uid, signature).await;
Custom(Status::Created, Json(m_auth.unwrap_or_default()))
}

View file

@ -17,7 +17,7 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
@ -127,10 +127,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "383d29d513d8764dcdc42ea295d979eb99c3c9f00607b3692cf68a431f7dca72"
[[package]]
name = "bitflags"
version = "0.7.0"
name = "bincode"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
dependencies = [
"serde",
]
[[package]]
name = "bitflags"
@ -140,9 +143,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.0.2"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "487f1e0fcbe47deb8b0574e646def1c903389d95241dd1bbcc6ce4a715dfc0c1"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "block-buffer"
@ -180,6 +183,12 @@ version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
[[package]]
name = "cesu8"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
[[package]]
name = "cfg-if"
version = "1.0.0"
@ -286,7 +295,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
dependencies = [
"core-foundation-sys",
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
@ -301,9 +310,34 @@ version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "280a9f2d8b3a38871a3c8a46fb80db65e5e5ed97da80c4d08bf27fb63e35e181"
dependencies = [
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
[[package]]
name = "crypto-common"
version = "0.1.6"
@ -316,15 +350,14 @@ dependencies = [
[[package]]
name = "curve25519-dalek"
version = "4.1.2"
version = "4.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348"
checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be"
dependencies = [
"cfg-if",
"cpufeatures",
"curve25519-dalek-derive",
"fiat-crypto",
"platforms",
"rustc_version",
"subtle",
"zeroize",
@ -411,7 +444,7 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35b50dba0afdca80b187392b24f2499a88c336d5a8493e4b4ccfb608708be56a"
dependencies = [
"bitflags 2.0.2",
"bitflags 2.6.0",
"proc-macro2",
"proc-macro2-diagnostics",
"quote",
@ -463,6 +496,12 @@ dependencies = [
"url",
]
[[package]]
name = "dunce"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
[[package]]
name = "either"
version = "1.8.1"
@ -486,7 +525,7 @@ checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0"
dependencies = [
"humantime",
"is-terminal",
"log 0.4.17",
"log",
"regex",
"termcolor",
]
@ -498,7 +537,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50d6a0976c999d473fe89ad888d5a284e55366d9dc9038b1ba2aa15128c4afa0"
dependencies = [
"errno-dragonfly",
"libc 0.2.140",
"libc 0.2.158",
"windows-sys 0.45.0",
]
@ -509,7 +548,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
dependencies = [
"cc",
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
@ -571,6 +610,12 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "fs_extra"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
[[package]]
name = "futures"
version = "0.3.28"
@ -579,6 +624,7 @@ checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
@ -601,12 +647,34 @@ version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
[[package]]
name = "futures-executor"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964"
[[package]]
name = "futures-macro"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.58",
]
[[package]]
name = "futures-sink"
version = "0.3.28"
@ -628,6 +696,7 @@ dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
@ -649,8 +718,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33a20a288a94683f5f4da0adecdbe095c94a77c295e514cc6484e9394dd8376e"
dependencies = [
"cc",
"libc 0.2.140",
"log 0.4.17",
"libc 0.2.158",
"log",
"rustversion",
"windows 0.44.0",
]
@ -672,7 +741,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
dependencies = [
"cfg-if",
"libc 0.2.140",
"libc 0.2.158",
"wasi 0.11.0+wasi-snapshot-preview1",
]
@ -719,7 +788,7 @@ version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
dependencies = [
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
@ -887,7 +956,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09270fd4fa1111bc614ed2246c7ef56239a3063d5be0d1ec3b589c505d400aeb"
dependencies = [
"hermit-abi 0.3.1",
"libc 0.2.140",
"libc 0.2.158",
"windows-sys 0.45.0",
]
@ -915,6 +984,67 @@ version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
[[package]]
name = "j4-i2p-rs"
version = "0.2.0-alpha"
dependencies = [
"hex",
"j4rs",
"log",
"rand",
"thiserror",
]
[[package]]
name = "j4rs"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "689ae4f2bd4eba82601592f3d22b7e7147b1df52d3b525223f5218990501b4eb"
dependencies = [
"cesu8",
"dunce",
"fs_extra",
"futures",
"glob",
"java-locator",
"jni-sys",
"lazy_static 1.4.0",
"libc 0.2.158",
"libloading",
"log",
"serde",
"serde_json",
]
[[package]]
name = "java-locator"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2abecabd9961c5e01405a6426687fcf1bd94a269927137e4c3cc1a7419b93fd"
dependencies = [
"glob",
"lazy_static 1.4.0",
]
[[package]]
name = "jni-sys"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c30a312d782b8d56a1e0897d45c1af33f31f9b4a4d13d31207a8675e0223b818"
dependencies = [
"jni-sys-macros",
]
[[package]]
name = "jni-sys-macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c199962dfd5610ced8eca382606e349f7940a4ac7d867b58a046123411cbb4"
dependencies = [
"quote",
"syn 1.0.109",
]
[[package]]
name = "js-sys"
version = "0.3.61"
@ -939,6 +1069,18 @@ dependencies = [
"sha2 0.10.6",
]
[[package]]
name = "kn0sys-lmdb-rs"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58fbf491e9e95a325cbfe1459734cec781c0145c0d5cb7c4ced71af742364d19"
dependencies = [
"bitflags 2.6.0",
"libc 0.2.158",
"liblmdb-sys",
"log",
]
[[package]]
name = "lazy_static"
version = "0.2.11"
@ -959,9 +1101,9 @@ checksum = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122"
[[package]]
name = "libc"
version = "0.2.140"
version = "0.2.158"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
[[package]]
name = "liblmdb-sys"
@ -970,7 +1112,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "feed38a3a580f60bf61aaa067b0ff4123395966839adeaf67258a9e50c4d2e49"
dependencies = [
"gcc",
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
name = "libloading"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4"
dependencies = [
"cfg-if",
"windows-targets 0.52.6",
]
[[package]]
@ -988,18 +1140,6 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f"
[[package]]
name = "lmdb-rs"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4aefe7b433f795629ce42f35ccf7a620c38bd457238bfaa2489dafc7e36167e7"
dependencies = [
"bitflags 0.7.0",
"libc 0.2.140",
"liblmdb-sys",
"log 0.3.9",
]
[[package]]
name = "lock_api"
version = "0.4.9"
@ -1012,21 +1152,9 @@ dependencies = [
[[package]]
name = "log"
version = "0.3.9"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
dependencies = [
"log 0.4.17",
]
[[package]]
name = "log"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "loom"
@ -1081,8 +1209,8 @@ version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
dependencies = [
"libc 0.2.140",
"log 0.4.17",
"libc 0.2.158",
"log",
"wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys 0.45.0",
]
@ -1098,7 +1226,7 @@ dependencies = [
"futures-util",
"http",
"httparse",
"log 0.4.17",
"log",
"memchr",
"mime",
"spin",
@ -1114,8 +1242,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e"
dependencies = [
"lazy_static 1.4.0",
"libc 0.2.140",
"log 0.4.17",
"libc 0.2.158",
"log",
"openssl",
"openssl-probe",
"openssl-sys",
@ -1130,7 +1258,7 @@ name = "neveko_contact"
version = "0.1.2-beta"
dependencies = [
"env_logger",
"log 0.4.17",
"log",
"neveko_core",
"rocket",
]
@ -1139,6 +1267,7 @@ dependencies = [
name = "neveko_core"
version = "0.1.2-beta"
dependencies = [
"bincode",
"chrono",
"clap",
"curve25519-dalek",
@ -1146,10 +1275,11 @@ dependencies = [
"env_logger",
"hex",
"hmac",
"j4-i2p-rs",
"jwt",
"kn0sys-lmdb-rs",
"lazy_static 1.4.0",
"lmdb-rs",
"log 0.4.17",
"log",
"num",
"rand",
"rand_core",
@ -1160,9 +1290,20 @@ dependencies = [
"serde",
"serde_json",
"sha2 0.10.6",
"sysinfo",
"thiserror",
"tokio",
]
[[package]]
name = "ntapi"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4"
dependencies = [
"winapi",
]
[[package]]
name = "nu-ansi-term"
version = "0.46.0"
@ -1256,7 +1397,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
dependencies = [
"hermit-abi 0.2.6",
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
@ -1280,7 +1421,7 @@ dependencies = [
"bitflags 1.3.2",
"cfg-if",
"foreign-types",
"libc 0.2.140",
"libc 0.2.158",
"once_cell",
"openssl-macros",
"openssl-sys",
@ -1311,7 +1452,7 @@ checksum = "666416d899cf077260dac8698d60a60b435a46d57e82acb1be3d0dad87284e5b"
dependencies = [
"autocfg",
"cc",
"libc 0.2.140",
"libc 0.2.158",
"pkg-config",
"vcpkg",
]
@ -1339,7 +1480,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
dependencies = [
"cfg-if",
"libc 0.2.140",
"libc 0.2.158",
"redox_syscall 0.2.16",
"smallvec",
"windows-sys 0.45.0",
@ -1392,12 +1533,6 @@ version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
[[package]]
name = "platforms"
version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7"
[[package]]
name = "ppv-lite86"
version = "0.2.17"
@ -1441,7 +1576,7 @@ version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc 0.2.140",
"libc 0.2.158",
"rand_chacha",
"rand_core",
]
@ -1465,6 +1600,26 @@ dependencies = [
"getrandom",
]
[[package]]
name = "rayon"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
]
[[package]]
name = "redox_syscall"
version = "0.2.16"
@ -1547,7 +1702,7 @@ dependencies = [
"hyper-tls",
"ipnet",
"js-sys",
"log 0.4.17",
"log",
"mime",
"native-tls",
"once_cell",
@ -1582,7 +1737,7 @@ dependencies = [
"futures",
"indexmap",
"is-terminal",
"log 0.4.17",
"log",
"memchr",
"multer",
"num_cpus",
@ -1633,7 +1788,7 @@ dependencies = [
"http",
"hyper",
"indexmap",
"log 0.4.17",
"log",
"memchr",
"pear",
"percent-encoding",
@ -1676,7 +1831,7 @@ dependencies = [
"bitflags 1.3.2",
"errno",
"io-lifetimes",
"libc 0.2.140",
"libc 0.2.158",
"linux-raw-sys",
"windows-sys 0.45.0",
]
@ -1738,7 +1893,7 @@ dependencies = [
"bitflags 1.3.2",
"core-foundation",
"core-foundation-sys",
"libc 0.2.140",
"libc 0.2.158",
"security-framework-sys",
]
@ -1749,7 +1904,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4"
dependencies = [
"core-foundation-sys",
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
@ -1840,7 +1995,7 @@ version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
dependencies = [
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
@ -1864,7 +2019,7 @@ version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"
dependencies = [
"libc 0.2.140",
"libc 0.2.158",
"winapi",
]
@ -1926,6 +2081,20 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "sysinfo"
version = "0.31.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "355dbe4f8799b304b05e1b0f05fc59b2a18d36645cf169607da45bde2f69a1be"
dependencies = [
"core-foundation-sys",
"libc 0.2.158",
"memchr",
"ntapi",
"rayon",
"windows 0.57.0",
]
[[package]]
name = "tempfile"
version = "3.5.0"
@ -1957,6 +2126,26 @@ dependencies = [
"libc 0.1.12",
]
[[package]]
name = "thiserror"
version = "1.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.58",
]
[[package]]
name = "thread_local"
version = "1.1.7"
@ -1973,7 +2162,7 @@ version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
dependencies = [
"libc 0.2.140",
"libc 0.2.158",
"wasi 0.10.0+wasi-snapshot-preview1",
"winapi",
]
@ -2028,7 +2217,7 @@ checksum = "d0de47a4eecbe11f498978a9b29d792f0d2692d1dd003650c24c76510e3bc001"
dependencies = [
"autocfg",
"bytes",
"libc 0.2.140",
"libc 0.2.158",
"mio",
"num_cpus",
"pin-project-lite",
@ -2139,7 +2328,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922"
dependencies = [
"lazy_static 1.4.0",
"log 0.4.17",
"log",
"tracing-core",
]
@ -2266,7 +2455,7 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
dependencies = [
"log 0.4.17",
"log",
"try-lock",
]
@ -2299,7 +2488,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
dependencies = [
"bumpalo",
"log 0.4.17",
"log",
"once_cell",
"proc-macro2",
"quote",
@ -2407,6 +2596,59 @@ dependencies = [
"windows-targets 0.47.0",
]
[[package]]
name = "windows"
version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143"
dependencies = [
"windows-core",
"windows-targets 0.52.6",
]
[[package]]
name = "windows-core"
version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d"
dependencies = [
"windows-implement",
"windows-interface",
"windows-result",
"windows-targets 0.52.6",
]
[[package]]
name = "windows-implement"
version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.58",
]
[[package]]
name = "windows-interface"
version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.58",
]
[[package]]
name = "windows-result"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8"
dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-sys"
version = "0.42.0"
@ -2461,6 +2703,22 @@ dependencies = [
"windows_x86_64_msvc 0.47.0",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm 0.52.6",
"windows_aarch64_msvc 0.52.6",
"windows_i686_gnu 0.52.6",
"windows_i686_gnullvm",
"windows_i686_msvc 0.52.6",
"windows_x86_64_gnu 0.52.6",
"windows_x86_64_gnullvm 0.52.6",
"windows_x86_64_msvc 0.52.6",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.2"
@ -2473,6 +2731,12 @@ version = "0.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "831d567d53d4f3cb1db332b68e6e2b6260228eb4d99a777d8b2e8ed794027c90"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.2"
@ -2485,6 +2749,12 @@ version = "0.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a42d54a417c60ce4f0e31661eed628f0fa5aca73448c093ec4d45fab4c51cdf"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.42.2"
@ -2497,6 +2767,18 @@ version = "0.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1925beafdbb22201a53a483db861a5644123157c1c3cee83323a2ed565d71e3"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.42.2"
@ -2509,6 +2791,12 @@ version = "0.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a8ef8f2f1711b223947d9b69b596cf5a4e452c930fb58b6fc3fdae7d0ec6b31"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.2"
@ -2521,6 +2809,12 @@ version = "0.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7acaa0c2cf0d2ef99b61c308a0c3dbae430a51b7345dedec470bd8f53f5a3642"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.2"
@ -2533,6 +2827,12 @@ version = "0.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5a0628f71be1d11e17ca4a0e9e15b3a5180f6fbf1c2d55e3ba3f850378052c1"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.2"
@ -2545,6 +2845,12 @@ version = "0.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d6e62c256dc6d40b8c8707df17df8d774e60e39db723675241e7c15e910bce7"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "winreg"
version = "0.10.1"

View file

@ -15,7 +15,6 @@ use neveko_core::{
models::*,
proof,
reqres,
utils,
};
/// Add contact
@ -25,17 +24,18 @@ pub async fn add_contact(
_token: auth::BearerToken,
) -> Custom<Json<Contact>> {
let res_contact = contact::create(&req_contact).await;
if res_contact.cid == utils::empty_string() {
let u_contact = res_contact.unwrap_or_default();
if u_contact.cid.is_empty() {
return Custom(Status::BadRequest, Json(Default::default()));
}
Custom(Status::Ok, Json(res_contact))
Custom(Status::Ok, Json(u_contact))
}
/// Return all contacts
#[get("/")]
pub async fn get_contacts(_token: auth::BearerToken) -> Custom<Json<Vec<Contact>>> {
let contacts = contact::find_all();
Custom(Status::Ok, Json(contacts))
Custom(Status::Ok, Json(contacts.unwrap_or_default()))
}
/// Delete a contact by CID
@ -44,9 +44,9 @@ pub async fn remove_contact(
contact: String,
_token: auth::BearerToken,
) -> Custom<Json<Vec<Contact>>> {
contact::delete(&contact);
let _ = contact::delete(&contact);
let contacts = contact::find_all();
Custom(Status::Ok, Json(contacts))
Custom(Status::Ok, Json(contacts.unwrap_or_default()))
}
/// prove payment

385
neveko-core/Cargo.lock generated
View file

@ -17,7 +17,7 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
@ -126,6 +126,15 @@ version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "383d29d513d8764dcdc42ea295d979eb99c3c9f00607b3692cf68a431f7dca72"
[[package]]
name = "bincode"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
dependencies = [
"serde",
]
[[package]]
name = "bitflags"
version = "1.3.2"
@ -174,6 +183,12 @@ version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
[[package]]
name = "cesu8"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
[[package]]
name = "cfg-if"
version = "1.0.0"
@ -280,7 +295,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
dependencies = [
"core-foundation-sys",
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
@ -295,9 +310,34 @@ version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "280a9f2d8b3a38871a3c8a46fb80db65e5e5ed97da80c4d08bf27fb63e35e181"
dependencies = [
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
[[package]]
name = "crypto-common"
version = "0.1.6"
@ -465,6 +505,12 @@ dependencies = [
"url",
]
[[package]]
name = "dunce"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
[[package]]
name = "either"
version = "1.8.1"
@ -500,7 +546,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50d6a0976c999d473fe89ad888d5a284e55366d9dc9038b1ba2aa15128c4afa0"
dependencies = [
"errno-dragonfly",
"libc 0.2.140",
"libc 0.2.158",
"windows-sys 0.45.0",
]
@ -511,7 +557,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
dependencies = [
"cc",
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
@ -573,6 +619,12 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "fs_extra"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
[[package]]
name = "futures"
version = "0.3.27"
@ -581,6 +633,7 @@ checksum = "531ac96c6ff5fd7c62263c5e3c67a603af4fcaee2e1a0ae5565ba3a11e69e549"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
@ -603,12 +656,34 @@ version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86d7a0c1aa76363dac491de0ee99faf6941128376f1cf96f07db7603b7de69dd"
[[package]]
name = "futures-executor"
version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1997dd9df74cdac935c76252744c1ed5794fac083242ea4fe77ef3ed60ba0f83"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89d422fa3cbe3b40dca574ab087abb5bc98258ea57eea3fd6f1fa7162c778b91"
[[package]]
name = "futures-macro"
version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3eb14ed937631bd8b8b8977f2c198443447a8355b6e3ca599f38c975e5a963b6"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "futures-sink"
version = "0.3.27"
@ -630,6 +705,7 @@ dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
@ -651,7 +727,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33a20a288a94683f5f4da0adecdbe095c94a77c295e514cc6484e9394dd8376e"
dependencies = [
"cc",
"libc 0.2.140",
"libc 0.2.158",
"log",
"rustversion",
"windows 0.44.0",
@ -674,7 +750,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
dependencies = [
"cfg-if",
"libc 0.2.140",
"libc 0.2.158",
"wasi 0.11.0+wasi-snapshot-preview1",
]
@ -721,7 +797,7 @@ version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
dependencies = [
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
@ -889,7 +965,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09270fd4fa1111bc614ed2246c7ef56239a3063d5be0d1ec3b589c505d400aeb"
dependencies = [
"hermit-abi 0.3.1",
"libc 0.2.140",
"libc 0.2.158",
"windows-sys 0.45.0",
]
@ -917,6 +993,67 @@ version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
[[package]]
name = "j4-i2p-rs"
version = "0.2.0-alpha"
dependencies = [
"hex",
"j4rs",
"log",
"rand",
"thiserror",
]
[[package]]
name = "j4rs"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "689ae4f2bd4eba82601592f3d22b7e7147b1df52d3b525223f5218990501b4eb"
dependencies = [
"cesu8",
"dunce",
"fs_extra",
"futures",
"glob",
"java-locator",
"jni-sys",
"lazy_static 1.4.0",
"libc 0.2.158",
"libloading",
"log",
"serde",
"serde_json",
]
[[package]]
name = "java-locator"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2abecabd9961c5e01405a6426687fcf1bd94a269927137e4c3cc1a7419b93fd"
dependencies = [
"glob",
"lazy_static 1.4.0",
]
[[package]]
name = "jni-sys"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c30a312d782b8d56a1e0897d45c1af33f31f9b4a4d13d31207a8675e0223b818"
dependencies = [
"jni-sys-macros",
]
[[package]]
name = "jni-sys-macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c199962dfd5610ced8eca382606e349f7940a4ac7d867b58a046123411cbb4"
dependencies = [
"quote",
"syn 1.0.109",
]
[[package]]
name = "js-sys"
version = "0.3.61"
@ -948,7 +1085,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29e0b46b27729cc3238baa573fe2f4df74af76ad1fdb576ff9ccabb97ecf756c"
dependencies = [
"bitflags 2.6.0",
"libc 0.2.140",
"libc 0.2.158",
"liblmdb-sys",
"log",
]
@ -973,9 +1110,9 @@ checksum = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122"
[[package]]
name = "libc"
version = "0.2.140"
version = "0.2.158"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
[[package]]
name = "liblmdb-sys"
@ -984,7 +1121,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "feed38a3a580f60bf61aaa067b0ff4123395966839adeaf67258a9e50c4d2e49"
dependencies = [
"gcc",
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
name = "libloading"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4"
dependencies = [
"cfg-if",
"windows-targets 0.52.6",
]
[[package]]
@ -1071,7 +1218,7 @@ version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
dependencies = [
"libc 0.2.140",
"libc 0.2.158",
"log",
"wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys 0.45.0",
@ -1104,7 +1251,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e"
dependencies = [
"lazy_static 1.4.0",
"libc 0.2.140",
"libc 0.2.158",
"log",
"openssl",
"openssl-probe",
@ -1119,6 +1266,7 @@ dependencies = [
name = "neveko_core"
version = "0.1.2-beta"
dependencies = [
"bincode",
"chrono",
"clap",
"curve25519-dalek",
@ -1126,6 +1274,7 @@ dependencies = [
"env_logger",
"hex",
"hmac",
"j4-i2p-rs",
"jwt",
"kn0sys-lmdb-rs",
"lazy_static 1.4.0",
@ -1140,9 +1289,20 @@ dependencies = [
"serde",
"serde_json",
"sha2 0.10.6",
"sysinfo",
"thiserror",
"tokio",
]
[[package]]
name = "ntapi"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4"
dependencies = [
"winapi",
]
[[package]]
name = "nu-ansi-term"
version = "0.46.0"
@ -1242,7 +1402,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
dependencies = [
"hermit-abi 0.2.6",
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
@ -1266,7 +1426,7 @@ dependencies = [
"bitflags 1.3.2",
"cfg-if",
"foreign-types",
"libc 0.2.140",
"libc 0.2.158",
"once_cell",
"openssl-macros",
"openssl-sys",
@ -1297,7 +1457,7 @@ checksum = "666416d899cf077260dac8698d60a60b435a46d57e82acb1be3d0dad87284e5b"
dependencies = [
"autocfg",
"cc",
"libc 0.2.140",
"libc 0.2.158",
"pkg-config",
"vcpkg",
]
@ -1325,7 +1485,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
dependencies = [
"cfg-if",
"libc 0.2.140",
"libc 0.2.158",
"redox_syscall 0.2.16",
"smallvec",
"windows-sys 0.45.0",
@ -1427,7 +1587,7 @@ version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc 0.2.140",
"libc 0.2.158",
"rand_chacha",
"rand_core",
]
@ -1451,6 +1611,26 @@ dependencies = [
"getrandom",
]
[[package]]
name = "rayon"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
]
[[package]]
name = "redox_syscall"
version = "0.2.16"
@ -1662,7 +1842,7 @@ dependencies = [
"bitflags 1.3.2",
"errno",
"io-lifetimes",
"libc 0.2.140",
"libc 0.2.158",
"linux-raw-sys",
"windows-sys 0.45.0",
]
@ -1724,7 +1904,7 @@ dependencies = [
"bitflags 1.3.2",
"core-foundation",
"core-foundation-sys",
"libc 0.2.140",
"libc 0.2.158",
"security-framework-sys",
]
@ -1735,7 +1915,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4"
dependencies = [
"core-foundation-sys",
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
@ -1826,7 +2006,7 @@ version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
dependencies = [
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
@ -1850,7 +2030,7 @@ version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"
dependencies = [
"libc 0.2.140",
"libc 0.2.158",
"winapi",
]
@ -1912,6 +2092,20 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "sysinfo"
version = "0.31.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "355dbe4f8799b304b05e1b0f05fc59b2a18d36645cf169607da45bde2f69a1be"
dependencies = [
"core-foundation-sys",
"libc 0.2.158",
"memchr",
"ntapi",
"rayon",
"windows 0.57.0",
]
[[package]]
name = "tempfile"
version = "3.5.0"
@ -1943,6 +2137,26 @@ dependencies = [
"libc 0.1.12",
]
[[package]]
name = "thiserror"
version = "1.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.58",
]
[[package]]
name = "thread_local"
version = "1.1.7"
@ -1959,7 +2173,7 @@ version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
dependencies = [
"libc 0.2.140",
"libc 0.2.158",
"wasi 0.10.0+wasi-snapshot-preview1",
"winapi",
]
@ -2018,7 +2232,7 @@ checksum = "d0de47a4eecbe11f498978a9b29d792f0d2692d1dd003650c24c76510e3bc001"
dependencies = [
"autocfg",
"bytes",
"libc 0.2.140",
"libc 0.2.158",
"mio",
"num_cpus",
"pin-project-lite",
@ -2397,6 +2611,59 @@ dependencies = [
"windows-targets 0.47.0",
]
[[package]]
name = "windows"
version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143"
dependencies = [
"windows-core",
"windows-targets 0.52.6",
]
[[package]]
name = "windows-core"
version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d"
dependencies = [
"windows-implement",
"windows-interface",
"windows-result",
"windows-targets 0.52.6",
]
[[package]]
name = "windows-implement"
version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.58",
]
[[package]]
name = "windows-interface"
version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.58",
]
[[package]]
name = "windows-result"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8"
dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-sys"
version = "0.42.0"
@ -2451,6 +2718,22 @@ dependencies = [
"windows_x86_64_msvc 0.47.0",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm 0.52.6",
"windows_aarch64_msvc 0.52.6",
"windows_i686_gnu 0.52.6",
"windows_i686_gnullvm",
"windows_i686_msvc 0.52.6",
"windows_x86_64_gnu 0.52.6",
"windows_x86_64_gnullvm 0.52.6",
"windows_x86_64_msvc 0.52.6",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.2"
@ -2463,6 +2746,12 @@ version = "0.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "831d567d53d4f3cb1db332b68e6e2b6260228eb4d99a777d8b2e8ed794027c90"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.2"
@ -2475,6 +2764,12 @@ version = "0.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a42d54a417c60ce4f0e31661eed628f0fa5aca73448c093ec4d45fab4c51cdf"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.42.2"
@ -2487,6 +2782,18 @@ version = "0.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1925beafdbb22201a53a483db861a5644123157c1c3cee83323a2ed565d71e3"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.42.2"
@ -2499,6 +2806,12 @@ version = "0.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a8ef8f2f1711b223947d9b69b596cf5a4e452c930fb58b6fc3fdae7d0ec6b31"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.2"
@ -2511,6 +2824,12 @@ version = "0.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7acaa0c2cf0d2ef99b61c308a0c3dbae430a51b7345dedec470bd8f53f5a3642"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.2"
@ -2523,6 +2842,12 @@ version = "0.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5a0628f71be1d11e17ca4a0e9e15b3a5180f6fbf1c2d55e3ba3f850378052c1"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.2"
@ -2535,6 +2860,12 @@ version = "0.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d6e62c256dc6d40b8c8707df17df8d774e60e39db723675241e7c15e910bce7"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "winreg"
version = "0.10.1"

View file

@ -6,6 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
bincode = "1.3.3"
chrono = "0.4.23"
clap = { version = "4.1.4", features = ["derive"] }
curve25519-dalek = "4.1.3"
@ -13,6 +14,7 @@ diqwest = "1.1.1"
env_logger = "0.10.0"
hex = "0.4.3"
hmac = "0.12.1"
j4-i2p-rs = { path = "../j4-i2p-rs", version = "0.2.0-alpha" }
jwt = "0.16.0"
lazy_static = "1.4.0"
kn0sys-lmdb-rs = "0.1.2"
@ -21,10 +23,12 @@ num = "0.4.1"
rand = "0.8.5"
rand_core = "0.6.4"
reqwest = { version = "0.11.12", features = ["json"] }
rocket = { version = "0.5.0-rc.2", features = ["json"] }
rocket = { version = "0.5.0-rc.3", features = ["json"] }
rpassword = "0.0.4"
schedule_recv = "0.1.0"
sha2 = "0.10.6"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.94"
sysinfo = "0.31.2"
thiserror = "1.0.63"
tokio = "1.25.0"

View file

@ -10,21 +10,21 @@ pub struct Args {
short,
long,
help = "Set release environment (dev, prod)",
default_value = "dev"
default_value = "prod"
)]
pub release_env: String,
/// Monero location
#[arg(
long,
help = "Monero download absolute path.",
default_value = "monero-x86_64-linux-gnu-v0.18.3.3"
default_value = "monero-x86_64-linux-gnu-v0.18.3.4"
)]
pub monero_location: String,
/// Monero RPC host
#[arg(
long,
help = "Monero RPC host.",
default_value = "http://localhost:38083"
default_value = "http://localhost:18083"
)]
pub monero_rpc_host: String,
/// Monero blockchain location
@ -34,18 +34,11 @@ pub struct Args {
default_value = "/home/user/.bitmonero"
)]
pub monero_blockchain_dir: String,
/// Absolute path to i2p zero
#[arg(
long,
help = "Absolute path to i2p-zero directroy",
default_value = "/home/user/i2p-zero-linux.v1.21"
)]
pub i2p_zero_dir: String,
/// Monero RPC daemon host
#[arg(
long,
help = "Monero RPC daemon.",
default_value = "http://localhost:38081"
default_value = "http://localhost:18081"
)]
pub monero_rpc_daemon: String,
/// Monero RPC Username
@ -97,14 +90,14 @@ pub struct Args {
#[arg(
long,
help = "i2p http proxy host",
default_value = "http://localhost:4444"
default_value = "http://localhost:4456"
)]
pub i2p_proxy_host: String,
/// i2p wallet proxy host (i2p socks)
#[arg(
long,
help = "i2p remote node socks proxy host",
default_value = "http://localhost:9051"
default_value = "http://localhost:9056"
)]
pub i2p_socks_proxy_host: String,
/// Connect wallet rpc for a remote-node, WARNING: may harm privacy
@ -149,7 +142,7 @@ pub struct Args {
default_value = "/home/user/neveko/i2p-manual"
)]
pub i2p_tunnels_json: String,
/// Dummy flag for normal neveko i2p-zero config. Future use.
/// Dummy flag for normal neveko i2p config. Future use.
#[arg(
long,
help = "Normal mode. Neveko will handle i2p proxy tunnels and identity.",
@ -160,7 +153,7 @@ pub struct Args {
#[arg(
long,
help = "Set i2p anon inbound connectivity",
default_value = "38089"
default_value = "18089"
)]
pub anon_inbound_port: u16,
}

View file

@ -2,7 +2,10 @@
use crate::{
args,
db,
db::{
self,
DATABASE_LOCK,
},
models::*,
monero,
reqres,
@ -10,6 +13,7 @@ use crate::{
utils,
};
use clap::Parser;
use kn0sys_lmdb_rs::MdbError;
use log::{
debug,
error,
@ -32,7 +36,7 @@ use sha2::Sha384;
use std::collections::BTreeMap;
/// Create authorization data to sign and expiration
pub fn create(address: &String) -> Authorization {
pub fn create(address: &String) -> Result<Authorization, MdbError> {
info!("creating auth");
let aid: String = format!("{}{}", crate::AUTH_DB_KEY, utils::generate_rnd());
let rnd: String = utils::generate_rnd();
@ -41,32 +45,33 @@ pub fn create(address: &String) -> Authorization {
let new_auth = Authorization {
aid,
created,
uid: utils::empty_string(),
uid: String::new(),
rnd,
token,
xmr_address: String::from(address),
};
let s = db::Interface::open();
debug!("insert auth: {:?}", &new_auth);
let k = &new_auth.aid;
db::Interface::write(&s.env, &s.handle, k, &Authorization::to_db(&new_auth));
new_auth
let k = &new_auth.aid.as_bytes();
let v = bincode::serialize(&new_auth).unwrap_or_default();
let db = &DATABASE_LOCK;
db::write_chunks(&db.env, &db.handle, k, &v)?;
Ok(new_auth)
}
/// Authorization lookup for recurring requests
pub fn find(aid: &String) -> Authorization {
pub fn find(aid: &String) -> Result<Authorization, MdbError> {
info!("searching for auth: {}", aid);
let s = db::Interface::open();
let r = db::Interface::read(&s.env, &s.handle, &String::from(aid));
debug!("auth read: {}", r);
if r == utils::empty_string() {
return Default::default();
let db = &DATABASE_LOCK;
let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &aid.as_bytes().to_vec())?;
if r.is_empty() {
return Err(MdbError::NotFound);
}
Authorization::from_db(String::from(aid), r)
let result: Authorization = bincode::deserialize(&r[..]).unwrap_or_default();
Ok(result)
}
/// Update new authorization creation time
fn update_expiration(f_auth: &Authorization, address: &String) -> Authorization {
fn update_expiration(f_auth: &Authorization, address: &String) -> Result<Authorization, MdbError> {
info!("modify auth expiration");
let data = utils::generate_rnd();
let time: i64 = chrono::offset::Utc::now().timestamp();
@ -77,27 +82,28 @@ fn update_expiration(f_auth: &Authorization, address: &String) -> Authorization
data,
create_token(String::from(address), time),
);
let s = db::Interface::open();
db::Interface::delete(&s.env, &s.handle, &u_auth.aid);
db::Interface::write(
&s.env,
&s.handle,
&u_auth.aid,
&Authorization::to_db(&u_auth),
);
return u_auth;
let db = &DATABASE_LOCK;
let _ = db::DatabaseEnvironment::delete(&db.env, &db.handle, &u_auth.aid.as_bytes().to_vec())?;
let k = u_auth.aid.as_bytes();
let v = bincode::serialize(&u_auth).unwrap_or_default();
db::write_chunks(&db.env, &db.handle, k, &v)?;
Ok(u_auth)
}
/// Performs the signature verfication against stored auth
pub async fn verify_login(aid: String, uid: String, signature: String) -> Authorization {
pub async fn verify_login(
aid: String,
uid: String,
signature: String,
) -> Result<Authorization, MdbError> {
let wallet_name = String::from(crate::APP_NAME);
let wallet_password =
std::env::var(crate::MONERO_WALLET_PASSWORD).unwrap_or(String::from("password"));
monero::open_wallet(&wallet_name, &wallet_password).await;
let m_address: reqres::XmrRpcAddressResponse = monero::get_address().await;
let address = m_address.result.address;
let f_auth: Authorization = find(&aid);
if f_auth.xmr_address == utils::empty_string() {
let f_auth: Authorization = find(&aid)?;
if f_auth.xmr_address.is_empty() {
error!("auth not found");
monero::close_wallet(&wallet_name, &wallet_password).await;
return create(&address);
@ -113,51 +119,47 @@ pub async fn verify_login(aid: String, uid: String, signature: String) -> Author
if sig_address == utils::ApplicationErrors::LoginError.value() {
error!("signature validation failed");
monero::close_wallet(&wallet_name, &wallet_password).await;
return f_auth;
return Ok(f_auth);
}
let f_user: User = user::find(&uid);
if f_user.xmr_address == utils::empty_string() {
let f_user: User = user::find(&uid)?;
if f_user.xmr_address.is_empty() {
info!("creating new user");
let u: User = user::create(&address);
let u: User = user::create(&address)?;
// update auth with uid
let u_auth = Authorization::update_uid(f_auth, String::from(&u.uid));
let s = db::Interface::open();
db::Interface::delete(&s.env, &s.handle, &u_auth.aid);
db::Interface::write(
&s.env,
&s.handle,
&u_auth.aid,
&Authorization::to_db(&u_auth),
);
let db = &DATABASE_LOCK;
let _ = db::DatabaseEnvironment::delete(&db.env, &db.handle, &u_auth.aid.as_bytes())?;
let v = bincode::serialize(&u_auth).unwrap_or_default();
db::write_chunks(&db.env, &db.handle, u_auth.aid.as_bytes(), &v)?;
monero::close_wallet(&wallet_name, &wallet_password).await;
return u_auth;
} else if f_user.xmr_address != utils::empty_string() {
Ok(u_auth)
} else if !f_user.xmr_address.is_empty() {
info!("returning user");
let m_access = verify_access(&address, &signature).await;
let m_access = verify_access(&address, &signature).await?;
if !m_access {
monero::close_wallet(&wallet_name, &wallet_password).await;
return Default::default();
return Ok(Default::default());
}
monero::close_wallet(&wallet_name, &wallet_password).await;
return f_auth;
return Ok(f_auth);
} else {
error!("error creating user");
monero::close_wallet(&wallet_name, &wallet_password).await;
return Default::default();
return Ok(Default::default());
}
}
/// Called during auth flow to update data to sign and expiration
async fn verify_access(address: &String, signature: &String) -> bool {
async fn verify_access(address: &String, signature: &String) -> Result<bool, MdbError> {
// look up auth for address
let f_auth: Authorization = find(address);
if f_auth.xmr_address != utils::empty_string() {
let f_auth: Authorization = find(address)?;
if !f_auth.xmr_address.is_empty() {
// check expiration, generate new data to sign if necessary
let now: i64 = chrono::offset::Utc::now().timestamp();
let expiration = get_auth_expiration();
if now > f_auth.created + expiration {
update_expiration(&f_auth, address);
return false;
update_expiration(&f_auth, address)?;
return Ok(false);
}
}
// verify signature on the data if not expired
@ -171,10 +173,10 @@ async fn verify_access(address: &String, signature: &String) -> bool {
};
if sig_address == utils::ApplicationErrors::LoginError.value() {
debug!("signing failed");
return false;
return Ok(false);
}
info!("auth verified");
return true;
Ok(true)
}
/// get the auth expiration command line configuration
@ -184,8 +186,8 @@ fn get_auth_expiration() -> i64 {
}
fn create_token(address: String, created: i64) -> String {
let jwt_secret_key = utils::get_jwt_secret_key();
let key: Hmac<Sha384> = Hmac::new_from_slice(&jwt_secret_key.as_bytes()).expect("hash");
let jwt_secret_key = utils::get_jwt_secret_key().unwrap_or_default();
let key: Hmac<Sha384> = Hmac::new_from_slice(jwt_secret_key.as_bytes()).expect("hash");
let header = Header {
algorithm: AlgorithmType::Hs384,
..Default::default()
@ -202,6 +204,12 @@ fn create_token(address: String, created: i64) -> String {
#[derive(Debug)]
pub struct BearerToken(String);
impl BearerToken {
pub fn get_token(self) -> String {
self.0
}
}
#[derive(Debug)]
pub enum BearerTokenError {
Expired,
@ -217,7 +225,7 @@ impl<'r> FromRequest<'r> for BearerToken {
let env = utils::get_release_env();
let dev = utils::ReleaseEnvironment::Development;
if env == dev {
return Outcome::Success(BearerToken(utils::empty_string()));
return Outcome::Success(BearerToken(String::new()));
}
let token = request.headers().get_one("token");
let wallet_name = String::from(crate::APP_NAME);
@ -231,8 +239,8 @@ impl<'r> FromRequest<'r> for BearerToken {
match token {
Some(token) => {
// check validity
let jwt_secret_key = utils::get_jwt_secret_key();
let key: Hmac<Sha384> = Hmac::new_from_slice(&jwt_secret_key.as_bytes()).expect("");
let jwt_secret_key = utils::get_jwt_secret_key().unwrap_or_default();
let key: Hmac<Sha384> = Hmac::new_from_slice(jwt_secret_key.as_bytes()).expect("");
let jwt: Result<
Token<jwt::Header, BTreeMap<std::string::String, std::string::String>, _>,
jwt::Error,
@ -250,10 +258,7 @@ impl<'r> FromRequest<'r> for BearerToken {
}
// verify expiration
let now: i64 = chrono::offset::Utc::now().timestamp();
let expire = match claims["expiration"].parse::<i64>() {
Ok(n) => n,
Err(_) => 0,
};
let expire = claims["expiration"].parse::<i64>().unwrap_or(0);
if now > expire {
return Outcome::Failure((
Status::Unauthorized,
@ -275,82 +280,70 @@ impl<'r> FromRequest<'r> for BearerToken {
#[cfg(test)]
mod tests {
use crate::error::NevekoError;
use super::*;
async fn find_test_auth(k: &String) -> Authorization {
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
let s: db::Interface = db::Interface::async_open().await;
let v = db::Interface::async_read(&s.env, &s.handle, k).await;
Authorization::from_db(String::from(k), v)
fn find_test_auth(k: &String) -> Result<Authorization, MdbError> {
let db = &DATABASE_LOCK;
let v = db::DatabaseEnvironment::read(&db.env, &db.handle, &k.as_bytes().to_vec())?;
let result: Authorization = bincode::deserialize(&v[..]).unwrap_or_default();
Ok(result)
}
async fn cleanup(k: &String) {
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
let s = db::Interface::async_open().await;
db::Interface::async_delete(&s.env, &s.handle, k).await;
fn cleanup(k: &String) -> Result<(), MdbError> {
let db = &DATABASE_LOCK;
let _ = db::DatabaseEnvironment::delete(&db.env, &db.handle, k.as_bytes())?;
Ok(())
}
#[test]
fn create_test() {
// run and async cleanup so the test doesn't fail when deleting test data
fn create_test() -> Result<(), MdbError> {
use tokio::runtime::Runtime;
let rt = Runtime::new().expect("Unable to create Runtime for test");
let _enter = rt.enter();
let address: String = String::from(
"73a4nWuvkYoYoksGurDjKZQcZkmaxLaKbbeiKzHnMmqKivrCzq5Q2JtJG1UZNZFqLPbQ3MiXCk2Q5bdwdUNSr7X9QrPubkn"
);
let test_auth = create(&address);
let test_auth = create(&address)?;
assert_eq!(test_auth.xmr_address, address);
tokio::spawn(async move {
cleanup(&test_auth.aid).await;
});
Runtime::shutdown_background(rt);
let _ = cleanup(&test_auth.aid);
Ok(())
}
#[test]
fn find_test() {
// run and async cleanup so the test doesn't fail when deleting test data
use tokio::runtime::Runtime;
let rt = Runtime::new().expect("Unable to create Runtime for test");
let _enter = rt.enter();
fn find_test() -> Result<(), MdbError> {
let address: String = String::from(
"73a4nWuvkYoYoksGurDjKZQcZkmaxLaKbbeiKzHnMmqKivrCzq5Q2JtJG1UZNZFqLPbQ3MiXCk2Q5bdwdUNSr7X9QrPubkn"
);
let test_auth = create(&address);
let test_auth = create(&address)?;
let aid = String::from(&test_auth.aid);
tokio::spawn(async move {
let f_auth: Authorization = find_test_auth(&aid).await;
assert_ne!(f_auth.xmr_address, address);
cleanup(&test_auth.aid).await;
});
Runtime::shutdown_background(rt);
let f_auth: Authorization = find_test_auth(&aid)?;
assert_eq!(f_auth.xmr_address, address);
cleanup(&test_auth.aid)?;
Ok(())
}
#[test]
fn update_expiration_test() {
// run and async cleanup so the test doesn't fail when deleting test data
use tokio::runtime::Runtime;
let rt = Runtime::new().expect("Unable to create Runtime for test");
let _enter = rt.enter();
fn update_expiration_test() -> Result<(), MdbError> {
let address: String = String::from(
"73a4nWuvkYoYoksGurDjKZQcZkmaxLaKbbeiKzHnMmqKivrCzq5Q2JtJG1UZNZFqLPbQ3MiXCk2Q5bdwdUNSr7X9QrPubkn"
);
let test_auth = create(&address);
let test_auth = create(&address)?;
let aid = String::from(&test_auth.aid);
tokio::spawn(async move {
let f_auth = find_test_auth(&aid).await;
let u_auth = update_expiration(&f_auth, &address);
assert!(f_auth.created < u_auth.created);
cleanup(&test_auth.aid).await;
});
Runtime::shutdown_background(rt);
let f_auth = find_test_auth(&aid)?;
std::thread::sleep(std::time::Duration::from_secs(1));
let u_auth = update_expiration(&f_auth, &address)?;
assert!(f_auth.created < u_auth.created);
let _ = cleanup(&test_auth.aid)?;
Ok(())
}
#[test]
fn create_token_test() {
fn create_token_test() -> Result<(), NevekoError> {
let test_value = "test";
let test_jwt = create_token(String::from(test_value), 0);
let jwt_secret_key = utils::get_jwt_secret_key();
let jwt_secret_key = utils::get_jwt_secret_key().unwrap_or_default();
let key: Hmac<Sha384> = Hmac::new_from_slice(&jwt_secret_key.as_bytes()).expect("");
let jwt: Result<
Token<jwt::Header, BTreeMap<std::string::String, std::string::String>, _>,
@ -364,6 +357,7 @@ mod tests {
assert_eq!(expected, actual);
}
Err(_) => error!("create_token_test error"),
}
};
Ok(())
}
}

View file

@ -1,13 +1,18 @@
//! contact operations module
use crate::{
db,
db::{
self,
DATABASE_LOCK,
},
error::NevekoError,
i2p,
models::*,
monero,
reqres,
utils,
};
use kn0sys_lmdb_rs::MdbError;
use log::{
debug,
error,
@ -21,22 +26,8 @@ pub const NEVEKO_VENDOR_ENABLED: &str = "NEVEKO_VENDOR_ENABLED";
pub const NEVEKO_VENDOR_MODE_OFF: &str = "0";
pub const NEVEKO_VENDOR_MODE_ON: &str = "1";
pub enum Prune {
Full,
Pruned,
}
impl Prune {
pub fn value(&self) -> u32 {
match *self {
Prune::Full => 0,
Prune::Pruned => 1,
}
}
}
/// Create a new contact
pub async fn create(c: &Json<Contact>) -> Contact {
pub async fn create(c: &Json<Contact>) -> Result<Contact, MdbError> {
let f_cid: String = format!("{}{}", crate::CONTACT_DB_KEY, utils::generate_rnd());
info!("creating contact: {}", f_cid);
let new_contact = Contact {
@ -48,80 +39,90 @@ pub async fn create(c: &Json<Contact>) -> Contact {
};
let is_valid = validate_contact(c).await;
if !is_valid {
return Default::default();
log::error!("invalid contact");
return Ok(Default::default());
}
debug!("insert contact: {:?}", &new_contact);
let s = db::Interface::open();
let db = &DATABASE_LOCK;
let k = &new_contact.cid;
db::Interface::write(&s.env, &s.handle, k, &Contact::to_db(&new_contact));
let v = bincode::serialize(&new_contact).unwrap_or_default();
db::write_chunks(&db.env, &db.handle, k.as_bytes(), &v)?;
// in order to retrieve all contact, write keys to with cl
let list_key = crate::CONTACT_LIST_DB_KEY;
let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key));
if r == utils::empty_string() {
let str_lk = String::from(list_key);
let lk_bytes = str_lk.as_bytes();
let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &lk_bytes.to_vec())?;
if r.is_empty() {
debug!("creating contact index");
}
let contact_list = [r, String::from(&f_cid)].join(",");
let old: String = bincode::deserialize(&r[..]).unwrap_or_default();
let contact_list = [old, String::from(&f_cid)].join(",");
let s_contactlist = bincode::serialize(&contact_list).unwrap_or_default();
debug!(
"writing contact index {} for key {}",
contact_list, list_key
);
db::Interface::write(&s.env, &s.handle, &String::from(list_key), &contact_list);
new_contact
db::write_chunks(&db.env, &db.handle, list_key.as_bytes(), &s_contactlist)?;
Ok(new_contact)
}
/// Contact lookup
pub fn find(cid: &String) -> Contact {
let s = db::Interface::open();
let r = db::Interface::read(&s.env, &s.handle, &String::from(cid));
if r == utils::empty_string() {
pub fn find(cid: &String) -> Result<Contact, MdbError> {
let db = &DATABASE_LOCK;
let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &cid.as_bytes().to_vec())?;
if r.is_empty() {
error!("contact not found");
return Default::default();
return Err(MdbError::NotFound);
}
Contact::from_db(String::from(cid), r)
let result: Contact = bincode::deserialize(&r[..]).unwrap_or_default();
Ok(result)
}
/// Contact lookup
pub fn find_by_i2p_address(i2p_address: &String) -> Contact {
let contacts = find_all();
pub fn find_by_i2p_address(i2p_address: &String) -> Result<Contact, NevekoError> {
let contacts = find_all().map_err(|_| NevekoError::Database(MdbError::NotFound))?;
for c in contacts {
if c.i2p_address == String::from(i2p_address) {
return c;
if c.i2p_address == *i2p_address {
return Ok(c);
}
}
Default::default()
Err(NevekoError::Database(MdbError::NotFound))
}
/// Contact deletion
pub fn delete(cid: &String) {
let s = db::Interface::open();
let r = db::Interface::read(&s.env, &s.handle, &String::from(cid));
if r == utils::empty_string() {
pub fn delete(cid: &String) -> Result<(), MdbError> {
let db = &DATABASE_LOCK;
let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &cid.as_bytes().to_vec())?;
if r.is_empty() {
error!("contact not found");
return;
return Err(MdbError::NotFound);
}
db::Interface::delete(&s.env, &s.handle, &cid);
let _ = db::DatabaseEnvironment::delete(&db.env, &db.handle, cid.as_bytes())?;
Ok(())
}
/// All contact lookup
pub fn find_all() -> Vec<Contact> {
pub fn find_all() -> Result<Vec<Contact>, MdbError> {
info!("looking up all contacts");
let s = db::Interface::open();
let db = &DATABASE_LOCK;
let list_key = crate::CONTACT_LIST_DB_KEY;
let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key));
if r == utils::empty_string() {
let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &list_key.as_bytes().to_vec())?;
if r.is_empty() {
error!("contact index not found");
return Default::default();
return Err(MdbError::NotFound);
}
let v_cid = r.split(",");
let v: Vec<String> = v_cid.map(|s| String::from(s)).collect();
let str_r: String = bincode::deserialize(&r[..]).unwrap_or_default();
let v_cid = str_r.split(",");
let v: Vec<String> = v_cid.map(String::from).collect();
let mut contacts: Vec<Contact> = Vec::new();
for id in v {
if id != utils::empty_string() {
let contact: Contact = find(&id);
if !id.is_empty() {
let contact: Contact = find(&id)?;
contacts.push(contact);
}
}
contacts
Ok(contacts)
}
async fn validate_contact(j: &Json<Contact>) -> bool {
@ -140,35 +141,41 @@ async fn validate_contact(j: &Json<Contact>) -> bool {
}
/// Send our information
pub async fn share() -> Contact {
let s = db::Interface::async_open().await;
let r = db::Interface::async_read(&s.env, &s.handle, NEVEKO_VENDOR_ENABLED).await;
let is_vendor = r == NEVEKO_VENDOR_MODE_ON;
pub async fn share() -> Result<Contact, NevekoError> {
let db = &DATABASE_LOCK;
let r = db::DatabaseEnvironment::read(
&db.env,
&db.handle,
&NEVEKO_VENDOR_ENABLED.as_bytes().to_vec(),
)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let str_r: String = bincode::deserialize(&r[..]).unwrap_or_default();
let is_vendor = str_r == NEVEKO_VENDOR_MODE_ON;
let wallet_name = String::from(crate::APP_NAME);
let wallet_password =
std::env::var(crate::MONERO_WALLET_PASSWORD).unwrap_or(String::from("password"));
monero::open_wallet(&wallet_name, &wallet_password).await;
let m_address: reqres::XmrRpcAddressResponse = monero::get_address().await;
monero::close_wallet(&wallet_name, &wallet_password).await;
let nmpk = utils::get_nmpk();
let i2p_address = i2p::get_destination(None);
let nmpk = utils::get_nmpk()?;
let i2p_address = i2p::get_destination(i2p::ServerTunnelType::App)?;
let xmr_address = m_address.result.address;
Contact {
cid: utils::empty_string(),
Ok(Contact {
cid: String::new(),
nmpk,
i2p_address,
is_vendor,
xmr_address,
}
})
}
pub fn exists(from: &String) -> bool {
let all = find_all();
pub fn exists(from: &String) -> Result<bool, MdbError> {
let all = find_all()?;
let mut addresses: Vec<String> = Vec::new();
for c in all {
addresses.push(c.i2p_address);
}
return addresses.contains(from);
Ok(addresses.contains(from))
}
/// Get invoice for jwp creation
@ -228,10 +235,10 @@ pub async fn add_contact_request(contact: String) -> Result<Contact, Box<dyn Err
mod tests {
use super::*;
async fn cleanup(k: &String) {
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
let s = db::Interface::async_open().await;
db::Interface::async_delete(&s.env, &s.handle, k).await;
fn cleanup(k: &String) -> Result<(), MdbError> {
let db = &DATABASE_LOCK;
let _ = db::DatabaseEnvironment::delete(&db.env, &db.handle, k.as_bytes())?;
Ok(())
}
#[test]
@ -252,7 +259,10 @@ mod tests {
tokio::spawn(async move {
let test_contact = create(&j_contact).await;
let expected: Contact = Default::default();
assert_eq!(test_contact.xmr_address, expected.xmr_address);
assert_eq!(
test_contact.unwrap_or_default().xmr_address,
expected.xmr_address
);
});
Runtime::shutdown_background(rt);
}
@ -272,12 +282,12 @@ mod tests {
..Default::default()
};
tokio::spawn(async move {
let s = db::Interface::async_open().await;
db::Interface::async_write(&s.env, &s.handle, k, &Contact::to_db(&expected_contact))
.await;
let actual_contact: Contact = find(&String::from(k));
let db = &DATABASE_LOCK;
let v = bincode::serialize(&expected_contact).unwrap_or_default();
let _ = db::write_chunks(&db.env, &db.handle, k.as_bytes(), &v);
let actual_contact: Contact = find(&String::from(k)).unwrap_or_default();
assert_eq!(expected_contact.xmr_address, actual_contact.xmr_address);
cleanup(&String::from(k)).await;
let _ = cleanup(&String::from(k));
});
Runtime::shutdown_background(rt);
}

View file

@ -1,185 +1,212 @@
//! Primary LMDB interface for read, write, delete etc.
#![deny(missing_docs)]
//! Logic for interfacing with LMDB.
extern crate kn0sys_lmdb_rs as lmdb;
use lmdb::{
DbFlags,
DbHandle,
EnvBuilder,
Environment,
};
use lmdb::*;
use log::{
debug,
error,
info,
};
use std::sync::LazyLock;
use sysinfo::System;
use crate::utils;
/// LMDB Interface allows access to the env
/// Ratio of map size to available memory is 20 percent
const MAP_SIZE_MEMORY_RATIO: f32 = 0.2;
/// Ratio of chunk size to available memory is 0.2 percent
const CHUNK_SIZE_MEMORY_RATIO: f32 = MAP_SIZE_MEMORY_RATIO * 0.01;
/// Database lock is initialized on startup in order to cache the db handle
pub static DATABASE_LOCK: LazyLock<DatabaseEnvironment> = LazyLock::new(|| {
DatabaseEnvironment::open().unwrap_or_else(|_| panic!("failed to initialize lmdb!"))
});
/// The database environment for handling primary database operations.
///
/// and handle for the write, read and delete
///
/// functionality.
pub struct Interface {
/// By default the database will be written to /home/user/.neveko/{ENV}/lmdb
pub struct DatabaseEnvironment {
/// Represents LMDB Environment.
pub env: Environment,
/// DB handle.
pub handle: DbHandle,
}
impl Interface {
/// Instantiation of ```Environment``` and ```DbHandle```
pub fn open() -> Self {
info!("excecuting lmdb open");
let release_env = utils::get_release_env();
let file_path = format!(
"/home/{}/.{}/",
std::env::var("USER").unwrap_or(String::from("user")),
crate::APP_NAME,
);
let mut env_str: &str = "test-lmdb";
if release_env != utils::ReleaseEnvironment::Development {
env_str = "lmdb";
};
let env = EnvBuilder::new()
// increase map size for writing the multisig txset
.map_size(crate::LMDB_MAPSIZE)
.open(format!("{}/{}", file_path, env_str), 0o777)
.expect(&format!("could not open LMDB at {}", file_path));
let handle = env.get_default_db(DbFlags::empty()).unwrap();
Interface { env, handle }
}
pub async fn async_open() -> Self {
info!("excecuting lmdb async open");
tokio::time::sleep(std::time::Duration::from_micros(1)).await;
self::Interface::open()
}
/// Write a key-value to LMDB. NEVEKO does not currently support
impl DatabaseEnvironment {
/// Opens environment in specified path. The map size defaults to 20 percent
///
/// writing multiple key value pairs.
pub fn write(e: &Environment, h: &DbHandle, k: &str, v: &str) {
/// of available memory and can be set via the `LMDB_MAP_SIZE` environment
/// variable.
///
/// The path of the user can be set with `LMDB_USER`.
pub fn open() -> Result<Self, MdbError> {
let s = System::new_all();
let default_map_size: u64 =
(s.available_memory() as f32 * MAP_SIZE_MEMORY_RATIO).floor() as u64;
let env_map_size: u64 = match std::env::var("LMDB_MAP_SIZE") {
Err(_) => default_map_size,
Ok(size) => size.parse::<u64>().unwrap_or(default_map_size),
};
info!("setting lmdb map size to: {}", env_map_size);
let user: String = match std::env::var("LMDB_USER") {
Err(_) => std::env::var("USER").unwrap_or(String::from("user")),
Ok(user) => user,
};
info!("$LMDB_USER={}", user);
info!("excecuting lmdb open");
let file_path: String = format!("/home/{}/.{}/", user, "neveko");
let env_str = utils::get_release_env().value();
let env: Environment = EnvBuilder::new()
.map_size(env_map_size)
.open(format!("{}/{}", file_path, env_str), 0o777)
.unwrap_or_else(|_| panic!("could not open LMDB at {}", file_path));
let default: Result<DbHandle, MdbError> = env.get_default_db(DbFlags::empty());
if default.is_err() {
panic!("could not set db handle")
}
let handle: DbHandle = default?;
Ok(DatabaseEnvironment { env, handle })
}
/// Write a key/value pair to the database. It is not possible to
///
/// write with empty keys.
fn write(e: &Environment, h: &DbHandle, k: &Vec<u8>, v: &Vec<u8>) -> Result<(), MdbError> {
info!("excecuting lmdb write");
// don't try and write empty keys
if k.is_empty() {
error!("can't write empty key");
return;
return Err(MdbError::NotFound);
}
let txn = e.new_transaction().unwrap();
let new_txn = e.new_transaction()?;
let txn = new_txn;
{
// get a database bound to this transaction
let db = txn.bind(&h);
let pair = vec![(k, v)];
let db: Database = txn.bind(h);
let pair: Vec<(&Vec<u8>, &Vec<u8>)> = vec![(k, v)];
for &(key, value) in pair.iter() {
db.set(&key, &value).unwrap();
db.set(key, value)
.unwrap_or_else(|_| error!("failed to set key: {:?}", k));
}
}
match txn.commit() {
Err(_) => error!("failed to commit!"),
Ok(_) => (),
}
txn.commit()
}
pub async fn async_write(e: &Environment, h: &DbHandle, k: &str, v: &str) {
info!("excecuting lmdb async write");
tokio::time::sleep(std::time::Duration::from_micros(1)).await;
self::Interface::write(e, h, k, v)
}
/// Read a value from LMDB by passing the key as a static
/// Read key from the database. If it doesn't exist then
///
/// string. If the value does not exist an empty string is
/// an empty vector will be returned. Treat all empty vectors
///
/// returned. NEVEKO does not currently support duplicate keys.
pub fn read(e: &Environment, h: &DbHandle, k: &str) -> String {
/// from database operations as failures.
pub fn read(e: &Environment, h: &DbHandle, k: &Vec<u8>) -> Result<Vec<u8>, MdbError> {
info!("excecuting lmdb read");
// don't try and read empty keys
if k.is_empty() {
error!("can't read empty key");
return utils::empty_string();
return Err(MdbError::NotFound);
}
let get_reader = e.get_reader();
let reader: ReadonlyTransaction = get_reader?;
let db: Database = reader.bind(h);
let mut result: Vec<u8> = Vec::new();
for num_writes in 0..usize::MAX {
let mut new_key: Vec<u8> = k.to_vec();
let mut key_count: Vec<u8> = (num_writes).to_be_bytes().to_vec();
new_key.append(&mut key_count);
let mut r = db.get::<Vec<u8>>(&new_key).unwrap_or_default();
if r.is_empty() {
break;
}
result.append(&mut r);
}
let reader = e.get_reader().unwrap();
let db = reader.bind(&h);
let value = db.get::<&str>(&k).unwrap_or_else(|_| "");
let r = String::from(value);
{
if r == utils::empty_string() {
debug!("Failed to read from db.")
if result.is_empty() {
error!("failed to read key {:?} from db", k);
}
}
r
Ok(result)
}
pub async fn async_read(e: &Environment, h: &DbHandle, k: &str) -> String {
info!("excecuting lmdb async read");
tokio::time::sleep(std::time::Duration::from_micros(1)).await;
self::Interface::read(e, h, k)
}
/// Delete a value from LMDB by passing the key as a
///
/// static string. If the value does not exist then an
///
/// error will be logged.
pub fn delete(e: &Environment, h: &DbHandle, k: &str) {
/// Deletes a key/value pair from the database
pub fn delete(e: &Environment, h: &DbHandle, k: &[u8]) -> Result<(), MdbError> {
info!("excecuting lmdb delete");
// don't try and delete empty keys
if k.is_empty() {
error!("can't delete empty key");
return;
return Err(MdbError::NotFound);
}
let txn = e.new_transaction().unwrap();
let new_txn = e.new_transaction();
let txn = new_txn?;
let get_reader = e.get_reader();
let reader: ReadonlyTransaction = get_reader?;
let db_reader: Database = reader.bind(h);
{
// get a database bound to this transaction
let db = txn.bind(&h);
db.del(&k).unwrap_or_else(|_| error!("failed to delete"));
}
match txn.commit() {
Err(_) => error!("failed to commit!"),
Ok(_) => (),
let db = txn.bind(h);
for num_writes in 0..usize::MAX {
let mut new_key: Vec<u8> = k.to_vec();
let mut key_count: Vec<u8> = num_writes.to_be_bytes().to_vec();
new_key.append(&mut key_count);
let r = db_reader.get::<Vec<u8>>(&new_key).unwrap_or_default();
if r.is_empty() {
break;
}
db.del(&new_key)
.unwrap_or_else(|_| error!("failed to delete"));
}
}
txn.commit()
}
pub async fn async_delete(e: &Environment, h: &DbHandle, k: &str) {
info!("excecuting lmdb async delete");
tokio::time::sleep(std::time::Duration::from_micros(1)).await;
self::Interface::delete(e, h, k)
}
/// Write chunks to the database. This function uses one percent
///
/// of the map size . Setting the map_size to a low value
///
/// will cause degraded performance.
pub fn write_chunks(e: &Environment, h: &DbHandle, k: &[u8], v: &[u8]) -> Result<(), MdbError> {
let s = System::new_all();
let chunk_size = (s.available_memory() as f32 * CHUNK_SIZE_MEMORY_RATIO) as usize;
let mut writes: usize = 1;
let mut index: usize = 0;
let length = v.len();
loop {
let mut old_key: Vec<u8> = k.to_vec();
let mut append: Vec<u8> = (writes - 1).to_be_bytes().to_vec();
old_key.append(&mut append);
if length > chunk_size && (length - index > chunk_size) {
// write chunks until the last value which is smaller than chunk_size
let _ = DatabaseEnvironment::write(
e,
h,
&old_key,
&v[index..(chunk_size * writes)].to_vec(),
);
index += chunk_size;
writes += 1;
} else {
DatabaseEnvironment::write(e, h, &old_key, &v[index..length].to_vec())?;
return Ok(());
}
}
}
// Tests
//-------------------------------------------------------------------------------
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn async_write_and_read_test() {
// run and async cleanup so the test doesn't fail when deleting test data
use tokio::runtime::Runtime;
let rt = Runtime::new().expect("Unable to create Runtime for test");
let _enter = rt.enter();
tokio::spawn(async move {
let s = Interface::async_open().await;
let k = "async-test-key";
let v = "async-test-value";
Interface::async_write(&s.env, &s.handle, k, v).await;
let expected = String::from(v);
let actual = Interface::async_read(&s.env, &s.handle, k).await;
assert_eq!(expected, actual);
Interface::async_delete(&s.env, &s.handle, &k).await;
});
}
use rand::RngCore;
#[test]
fn async_write_and_delete_test() {
// run and async cleanup so the test doesn't fail when deleting test data
use tokio::runtime::Runtime;
let rt = Runtime::new().expect("Unable to create Runtime for test");
let _enter = rt.enter();
tokio::spawn(async move {
let s = Interface::open();
let k = "write_and_delete_test_test-key";
let v = "write_and_delete_test_test-value";
Interface::async_write(&s.env, &s.handle, k, v).await;
let expected = utils::empty_string();
Interface::async_delete(&s.env, &s.handle, &k).await;
let actual = Interface::async_read(&s.env, &s.handle, k).await;
assert_eq!(expected, actual);
});
fn environment_test() -> Result<(), MdbError> {
let db = &DATABASE_LOCK;
const DATA_SIZE_10MB: usize = 10000000;
let mut data = vec![0u8; DATA_SIZE_10MB];
rand::thread_rng().fill_bytes(&mut data);
let k = "test-key".as_bytes();
let expected = &data.to_vec();
write_chunks(&db.env, &db.handle, &Vec::from(k), &Vec::from(data))?;
let actual = DatabaseEnvironment::read(&db.env, &db.handle, &Vec::from(k));
assert_eq!(expected.to_vec(), actual?);
let _ = DatabaseEnvironment::delete(&db.env, &db.handle, &Vec::from(k))?;
Ok(())
}
}

View file

@ -3,11 +3,16 @@
use std::error::Error;
use crate::{
db,
db::{
self,
DATABASE_LOCK,
},
error::NevekoError,
models::*,
monero,
utils,
};
use kn0sys_lmdb_rs::MdbError;
use log::{
debug,
error,
@ -16,7 +21,7 @@ use log::{
use rocket::serde::json::Json;
/// Create a new dispute
pub fn create(d: Json<Dispute>) -> Dispute {
pub fn create(d: Json<Dispute>) -> Result<Dispute, MdbError> {
let f_did: String = format!("{}{}", crate::DISPUTE_DB_KEY, utils::generate_rnd());
info!("create dispute: {}", &f_did);
let new_dispute = Dispute {
@ -26,70 +31,78 @@ pub fn create(d: Json<Dispute>) -> Dispute {
tx_set: String::from(&d.tx_set),
};
debug!("insert dispute: {:?}", &d);
let s = db::Interface::open();
let db = &DATABASE_LOCK;
let k = &d.did;
db::Interface::write(&s.env, &s.handle, k, &Dispute::to_db(&new_dispute));
let v = bincode::serialize(&new_dispute).unwrap_or_default();
db::write_chunks(&db.env, &db.handle, k.as_bytes(), &v)?;
// in order to retrieve all orders, write keys to with dl
let list_key = crate::DISPUTE_LIST_DB_KEY;
let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key));
if r == utils::empty_string() {
let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &list_key.as_bytes().to_vec())?;
if r.is_empty() {
debug!("creating dispute index");
}
let dispute_list = [String::from(&r), String::from(&f_did)].join(",");
let s_r: String = bincode::deserialize(&r[..]).unwrap_or_default();
let dispute_list = [String::from(&s_r), String::from(&f_did)].join(",");
let s_dispute_list = bincode::serialize(&dispute_list).unwrap_or_default();
debug!(
"writing dispute index {} for id: {}",
dispute_list, list_key
);
db::Interface::write(&s.env, &s.handle, &String::from(list_key), &dispute_list);
db::write_chunks(&db.env, &db.handle, list_key.as_bytes(), &s_dispute_list)?;
// restart the dispute aut-settle thread
let cleared = is_dispute_clear(r);
let cleared = is_dispute_clear(s_r);
if !cleared {
debug!("restarting dispute auto-settle");
utils::restart_dispute_auto_settle();
}
new_dispute
Ok(new_dispute)
}
/// Dispute lookup
pub fn find(did: &String) -> Dispute {
let s = db::Interface::open();
let r = db::Interface::read(&s.env, &s.handle, &String::from(did));
if r == utils::empty_string() {
pub fn find(did: &String) -> Result<Dispute, NevekoError> {
let db = &DATABASE_LOCK;
let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &did.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
error!("dispute not found");
return Default::default();
return Err(NevekoError::Database(MdbError::Panic));
}
Dispute::from_db(String::from(did), r)
let result: Dispute = bincode::deserialize(&r[..]).unwrap_or_default();
Ok(result)
}
/// Lookup all disputes
pub fn find_all() -> Vec<Dispute> {
let d_s = db::Interface::open();
pub fn find_all() -> Result<Vec<Dispute>, NevekoError> {
let db = &DATABASE_LOCK;
let d_list_key = crate::DISPUTE_LIST_DB_KEY;
let d_r = db::Interface::read(&d_s.env, &d_s.handle, &String::from(d_list_key));
if d_r == utils::empty_string() {
let d_r = db::DatabaseEnvironment::read(&db.env, &db.handle, &d_list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if d_r.is_empty() {
error!("dispute index not found");
}
let d_v_did = d_r.split(",");
let d_v: Vec<String> = d_v_did.map(|s| String::from(s)).collect();
let str_r: String = bincode::deserialize(&d_r[..]).unwrap_or_default();
let d_v_did = str_r.split(",");
let d_v: Vec<String> = d_v_did.map(String::from).collect();
let mut disputes: Vec<Dispute> = Vec::new();
for o in d_v {
let dispute: Dispute = find(&o);
if dispute.did != utils::empty_string() {
let dispute: Dispute = find(&o)?;
if !dispute.did.is_empty() {
disputes.push(dispute);
}
}
disputes
Ok(disputes)
}
/// Dispute deletion
pub fn delete(did: &String) {
let s = db::Interface::open();
let r = db::Interface::read(&s.env, &s.handle, &String::from(did));
if r == utils::empty_string() {
pub fn delete(did: &String) -> Result<(), MdbError> {
let db = &DATABASE_LOCK;
let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &did.as_bytes().to_vec())?;
if r.is_empty() {
error!("dispute not found");
return Default::default();
return Err(MdbError::NotFound);
}
db::Interface::delete(&s.env, &s.handle, &String::from(did))
db::DatabaseEnvironment::delete(&db.env, &db.handle, did.as_bytes())
}
/// Triggered on DISPUTE_LAST_CHECK_DB_KEY.
@ -99,46 +112,50 @@ pub fn delete(did: &String) {
/// creation date of the dispute plus the one week
///
/// grace period then the dispute is auto-settled.
pub async fn settle_dispute() {
pub async fn settle_dispute() -> Result<(), NevekoError> {
let tick: std::sync::mpsc::Receiver<()> =
schedule_recv::periodic_ms(crate::DISPUTE_CHECK_INTERVAL);
loop {
debug!("running dispute auto-settle thread");
tick.recv().unwrap();
let s = db::Interface::open();
let db = &DATABASE_LOCK;
let list_key = crate::DISPUTE_LIST_DB_KEY;
let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key));
if r == utils::empty_string() {
let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
info!("dispute index not found");
return Err(NevekoError::Database(MdbError::NotFound));
}
let v_mid = r.split(",");
let d_vec: Vec<String> = v_mid.map(|s| String::from(s)).collect();
let str_r: String = bincode::deserialize(&r[..]).unwrap_or_default();
let v_mid = str_r.split(",");
let d_vec: Vec<String> = v_mid.map(String::from).collect();
debug!("dispute contents: {:#?}", d_vec);
let cleared = is_dispute_clear(r);
let cleared = is_dispute_clear(str_r);
if cleared {
// index was created but cleared
info!("terminating dispute auto-settle thread");
db::Interface::delete(&s.env, &s.handle, list_key);
return;
let _ = db::DatabaseEnvironment::delete(&db.env, &db.handle, list_key.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
return Ok(());
}
for d in d_vec {
let dispute: Dispute = find(&d);
if dispute.did != utils::empty_string() {
let dispute: Dispute = find(&d)?;
if !dispute.did.is_empty() {
let now = chrono::offset::Utc::now().timestamp();
let settle_date = dispute.created + crate::DISPUTE_AUTO_SETTLE as i64;
if settle_date > now {
let wallet_name = String::from(dispute.orid);
let wallet_password = utils::empty_string();
let wallet_name = dispute.orid;
let wallet_password = String::new();
monero::open_wallet(&wallet_name, &wallet_password).await;
let signed = monero::sign_multisig(dispute.tx_set).await;
let submit = monero::submit_multisig(signed.result.tx_data_hex).await;
monero::close_wallet(&wallet_name, &wallet_password).await;
if submit.result.tx_hash_list.is_empty() {
error!("could not broadcast txset for dispute: {}", &dispute.did);
return;
return Ok(());
}
// remove the dispute from the db
remove_from_auto_settle(dispute.did);
remove_from_auto_settle(dispute.did).map(|_| NevekoError::Dispute)?;
}
}
}
@ -147,43 +164,46 @@ pub async fn settle_dispute() {
fn is_dispute_clear(r: String) -> bool {
let v_mid = r.split(",");
let v: Vec<String> = v_mid.map(|s| String::from(s)).collect();
let v: Vec<String> = v_mid.map(String::from).collect();
debug!("dispute index contents: {:#?}", v);
let limit = v.len() <= 1;
if !limit {
return v.len() >= 2
&& v[v.len() - 1] == utils::empty_string()
&& v[0] == utils::empty_string();
v.len() >= 2 && v[v.len() - 1].is_empty() && v[0].is_empty()
} else {
return limit;
limit
}
}
/// clear dispute from index
fn remove_from_auto_settle(did: String) {
fn remove_from_auto_settle(did: String) -> Result<(), NevekoError> {
info!("removing id {} from disputes", &did);
let s = db::Interface::open();
let db = &DATABASE_LOCK;
let list_key = crate::DISPUTE_LIST_DB_KEY;
let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key));
if r == utils::empty_string() {
let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
debug!("dispute list index is empty");
}
let pre_v_fts = r.split(",");
let str_r: String = bincode::deserialize(&r[..]).unwrap_or_default();
let pre_v_fts = str_r.split(",");
let v: Vec<String> = pre_v_fts
.map(|s| {
if s != &did {
String::from(s)
} else {
utils::empty_string()
String::new()
}
})
.collect();
let dispute_list = v.join(",");
let s_dispute_list = bincode::serialize(&dispute_list).unwrap_or_default();
debug!(
"writing dipsute index {} for id: {}",
dispute_list, list_key
);
db::Interface::write(&s.env, &s.handle, &String::from(list_key), &dispute_list);
db::write_chunks(&db.env, &db.handle, list_key.as_bytes(), &s_dispute_list)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(())
}
/// Executes POST /market/dispute/create
@ -227,16 +247,21 @@ async fn transmit_dispute_request(
/// A decomposition trigger for the dispute request so that the logic
///
/// can be executed from the gui.
pub async fn trigger_dispute_request(contact: &String, dispute: &Dispute) -> Dispute {
pub async fn trigger_dispute_request(
contact: &String,
dispute: &Dispute,
) -> Result<Dispute, NevekoError> {
info!("executing trigger_dispute_request");
let s = db::Interface::async_open().await;
let db = &DATABASE_LOCK;
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &contact);
let jwp = db::Interface::async_read(&s.env, &s.handle, &k).await;
let dispute = transmit_dispute_request(contact, &jwp, dispute).await;
let jwp = db::DatabaseEnvironment::read(&db.env, &db.handle, &k.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let str_jwp: String = bincode::deserialize(&jwp[..]).unwrap_or_default();
let dispute = transmit_dispute_request(contact, &str_jwp, dispute).await;
// handle a failure to create dispute
if dispute.is_err() {
error!("failed to create dispute");
return Default::default();
return Err(NevekoError::Dispute);
}
dispute.unwrap_or(Default::default())
Ok(dispute.map_err(|_| NevekoError::Dispute)?)
}

21
neveko-core/src/error.rs Normal file
View file

@ -0,0 +1,21 @@
use kn0sys_lmdb_rs::MdbError;
use thiserror::Error;
/// Use for mapping errors in functions that can throw multiple errors.
#[derive(Debug, Error)]
#[error("Neveko error. See logs for more info.")]
pub enum NevekoError {
Auth,
Contact,
Database(MdbError),
Dispute,
I2P,
J4I2PRS,
Message,
MoneroRpc,
MoneroDaemon,
Nasr,
Order,
Product,
Unknown,
}

View file

@ -1,32 +1,73 @@
//! TODO: replace i2p-zero with i2pd bindings
//! embedded i2p module
use crate::{
args,
db::{
self,
DATABASE_LOCK,
},
error::NevekoError,
monero::get_anon_inbound_port,
utils,
DEFAULT_HTTP_PROXY_PORT,
DEFAULT_SOCKS_PORT,
};
use clap::Parser;
use log::{
debug,
info,
warn,
use j4i2prs::{
router_wrapper as rw,
tunnel_control as tc,
};
use kn0sys_lmdb_rs::MdbError;
use log::*;
use serde::{
Deserialize,
Serialize,
};
use std::{
env,
fs,
process::Command,
time::Duration,
fs::File,
io::{
self,
BufRead,
},
path::Path,
sync::mpsc::{
Receiver,
Sender,
},
thread,
};
struct Listener {
is_running: bool,
run_tx: Sender<bool>,
run_rx: Receiver<bool>,
}
impl Default for Listener {
fn default() -> Self {
let is_running = false;
let (run_tx, run_rx) = std::sync::mpsc::channel();
Listener {
is_running,
run_tx,
run_rx,
}
}
}
/// https://doc.rust-lang.org/rust-by-example/std_misc/file/read_lines.html
fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
where
P: AsRef<Path>,
{
let file = File::open(filename)?;
Ok(io::BufReader::new(file).lines())
}
#[derive(Debug, Deserialize, Serialize)]
pub struct HttpProxyStatus {
pub open: bool,
}
#[derive(Debug, Serialize, PartialEq)]
#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub enum ProxyStatus {
Opening,
Open,
@ -41,226 +82,220 @@ impl ProxyStatus {
}
}
#[derive(Serialize, Deserialize, Debug)]
struct Tunnel {
// http proxy tunnel wont have this field
dest: Option<String>,
port: String,
}
#[derive(Serialize, Deserialize, Debug)]
struct Tunnels {
tunnels: Vec<Tunnel>,
}
impl Default for Tunnels {
fn default() -> Self {
Tunnels {
tunnels: Vec::new(),
}
}
}
/// Looks for the `tunnels-config.json` at /home/$USER/.i2p-zero/config/
///
/// and attempts to extract the app and http proxy tunnel information.
async fn find_tunnels() {
let args = args::Args::parse();
let app_port = utils::get_app_port();
let file_path = format!(
"/home/{}/.i2p-zero/config/tunnels.json",
env::var("USER").unwrap_or(String::from("user"))
);
let contents = fs::read_to_string(file_path).unwrap_or(utils::empty_string());
debug!("i2p tunnels: {}", contents);
let has_app_tunnel = contents.contains(&format!("{}", app_port));
let proxy_port = get_i2p_proxy_port();
let socks_proxy_port = get_i2p_socks_proxy_port();
let has_http_tunnel = contents.contains(&proxy_port);
let has_socks_proxy_tunnel = contents.contains(&format!("{}", &socks_proxy_port));
let has_anon_inbound_tunnel = contents.contains(&format!("{}", args.anon_inbound_port));
if !has_app_tunnel || !has_http_tunnel || !has_anon_inbound_tunnel || !has_socks_proxy_tunnel {
tokio::time::sleep(Duration::new(120, 0)).await;
}
if !has_app_tunnel {
debug!("creating app tunnel");
create_tunnel();
}
if !has_http_tunnel {
debug!("creating http tunnel");
create_http_proxy();
}
if !has_anon_inbound_tunnel {
debug!("creating anon inbound tunnel");
create_anon_inbound_tunnel();
}
if !has_socks_proxy_tunnel {
debug!("creating socks proxy tunnel");
create_socks_proxy_tunnel();
}
}
/// Called on application startup for i2p tunnel creation,
///
/// proxy tunnel, etc. Logs proxy status every 10 minutes.
pub async fn start() {
info!("starting i2p-zero");
let args = args::Args::parse();
let path = args.i2p_zero_dir;
let output = Command::new(format!("{}/router/bin/i2p-zero", path)).spawn();
match output {
Ok(child) => debug!("{:?}", child.stdout),
_ => {
warn!("i2p-zero not installed, manual tunnel creation required");
()
}
}
find_tunnels().await;
{
tokio::spawn(async move {
let tick: std::sync::mpsc::Receiver<()> =
schedule_recv::periodic_ms(crate::I2P_CONNECTIVITY_CHECK_INTERVAL);
loop {
tick.recv().unwrap();
check_connection().await;
}
});
}
}
/// Create an i2p tunnel for the NEVEKO application
fn create_tunnel() {
info!("creating tunnel");
let args = args::Args::parse();
let path = args.i2p_zero_dir;
let output = Command::new(format!("{}/router/bin/tunnel-control.sh", path))
.args([
"server.create",
"127.0.0.1",
&format!("{}", utils::get_app_port()),
])
.spawn()
.expect("i2p-zero failed to create a app tunnel");
debug!("{:?}", output.stdout);
}
/// Create an i2p tunnel for the monero wallet socks proxy
fn create_socks_proxy_tunnel() {
info!("creating monerod socks proxy tunnel");
let args = args::Args::parse();
let path = args.i2p_zero_dir;
let output = Command::new(format!("{}/router/bin/tunnel-control.sh", path))
.args(["socks.create", &format!("{}", get_i2p_socks_proxy_port())])
.spawn()
.expect("i2p-zero failed to create a socks proxy tunnel");
debug!("{:?}", output.stdout);
}
/// Create an i2p tunnel for the monero tx proxy
fn create_anon_inbound_tunnel() {
info!("creating monerod anon inbound proxy tunnel");
let args = args::Args::parse();
let path = args.i2p_zero_dir;
let output = Command::new(format!("{}/router/bin/tunnel-control.sh", path))
.args([
"server.create",
"127.0.0.1",
&format!("{}", args.anon_inbound_port),
])
.spawn()
.expect("i2p-zero failed to create a anon inbound tunnel");
debug!("{:?}", output.stdout);
}
/// Extract i2p port from command line arg
fn get_i2p_proxy_port() -> String {
let proxy_host = utils::get_i2p_http_proxy();
let values = proxy_host.split(":");
let mut v: Vec<String> = values.map(|s| String::from(s)).collect();
let port = v.remove(2);
port
let mut v: Vec<String> = values.map(String::from).collect();
v.remove(2)
}
/// Extract i2p socks port from command line arg
fn get_i2p_socks_proxy_port() -> String {
let proxy_host = utils::get_i2p_wallet_proxy_host();
let values = proxy_host.split(":");
let mut v: Vec<String> = values.map(|s| String::from(s)).collect();
let port = v.remove(2);
port
}
/// Create the http proxy if it doesn't exist
fn create_http_proxy() {
let args = args::Args::parse();
let path = args.i2p_zero_dir;
info!("creating http proxy");
let port = get_i2p_proxy_port();
let output = Command::new(format!("{}/router/bin/tunnel-control.sh", path))
.args(["http.create", &port])
.spawn()
.expect("i2p-zero failed to create a http proxy");
debug!("{:?}", output.stdout);
let mut v: Vec<String> = values.map(String::from).collect();
v.remove(2)
}
/// This is the `dest` value of the app i2p tunnels
///
/// in `tunnels-config.json`.
///
/// `port` - the port of the tunnel (e.g. `utils::get_app_port()`)
pub fn get_destination(port: Option<u16>) -> String {
let mut file_path = format!(
"/home/{}/.i2p-zero/config/tunnels.json",
env::var("USER").unwrap_or(String::from("user"))
);
let args = args::Args::parse();
let is_advanced_mode =
std::env::var(crate::NEVEKO_I2P_ADVANCED_MODE).unwrap_or(utils::empty_string());
if args.i2p_advanced || is_advanced_mode == String::from("1") {
let advanced_tunnel =
std::env::var(crate::NEVEKO_I2P_TUNNELS_JSON).unwrap_or(utils::empty_string());
let manual_tunnel = if advanced_tunnel == utils::empty_string() {
args.i2p_tunnels_json
} else {
advanced_tunnel
};
file_path = format!("{}/tunnels.json", manual_tunnel);
/// `st` - ServerTunnelType (App or AnonInbound)
pub fn get_destination(st: ServerTunnelType) -> Result<String, NevekoError> {
let db = &DATABASE_LOCK;
let r_anon_b32_dest = db::DatabaseEnvironment::read(
&db.env,
&db.handle,
&crate::APP_ANON_IN_B32_DEST.as_bytes().to_vec(),
)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let r_app_b32_dest = db::DatabaseEnvironment::read(
&db.env,
&db.handle,
&crate::APP_B32_DEST.as_bytes().to_vec(),
)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let anon_b32_dest: String = bincode::deserialize(&r_anon_b32_dest[..]).unwrap_or_default();
let app_b32_dest: String = bincode::deserialize(&&r_app_b32_dest[..]).unwrap_or_default();
match st {
ServerTunnelType::App => Ok(app_b32_dest),
ServerTunnelType::AnonInbound => Ok(anon_b32_dest),
}
// Don't panic if i2p-zero isn't installed
let contents = match fs::read_to_string(file_path) {
Ok(file) => file,
_ => utils::empty_string(),
};
if contents != utils::empty_string() {
let input = format!(r#"{contents}"#);
let j: Tunnels = serde_json::from_str(&input).unwrap_or(Default::default());
let mut destination: String = utils::empty_string();
let tunnels: Vec<Tunnel> = j.tunnels;
for tunnel in tunnels {
if tunnel.port == format!("{}", port.unwrap_or(utils::get_app_port())) {
destination = tunnel.dest.unwrap_or(utils::empty_string());
}
}
return destination;
}
utils::empty_string()
}
/// Ping the i2p-zero http proxy `tunnel-control http.state <port>`
pub async fn check_connection() -> ProxyStatus {
let args = args::Args::parse();
let path = args.i2p_zero_dir;
let port = get_i2p_proxy_port();
let output = Command::new(format!("{}/router/bin/tunnel-control.sh", path))
.args(["http.state", &port])
.output()
.expect("check i2p connection failed");
let str_status = String::from_utf8(output.stdout).unwrap();
if str_status == ProxyStatus::Open.value() {
debug!("http proxy is open");
ProxyStatus::Open
} else {
debug!("http proxy is opening");
ProxyStatus::Opening
/// Ping our base 32 destination address over the http proxy
pub async fn check_connection() -> Result<ProxyStatus, NevekoError> {
let db = &DATABASE_LOCK;
let r =
db::DatabaseEnvironment::read(&db.env, &db.handle, &crate::I2P_STATUS.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
error!("i2p status not found");
return Err(NevekoError::Database(MdbError::NotFound));
}
let result: ProxyStatus = bincode::deserialize(&r[..]).unwrap_or(ProxyStatus::Opening);
Ok(result)
}
#[derive(PartialEq)]
pub enum ServerTunnelType {
App,
AnonInbound,
}
/// Create app and anon inbound server tunnels if they don't exist yet
fn create_server_tunnel(st: ServerTunnelType) -> Result<tc::Tunnel, NevekoError> {
let port: u16 = if st == ServerTunnelType::App {
utils::get_app_port()
} else {
get_anon_inbound_port()
};
let b32_key = if st == ServerTunnelType::App {
crate::APP_B32_DEST.as_bytes()
} else {
crate::APP_ANON_IN_B32_DEST.as_bytes()
};
let sk_key = if st == ServerTunnelType::App {
crate::APP_I2P_SK.as_bytes()
} else {
crate::APP_ANON_IN_SK.as_bytes()
};
let db = &DATABASE_LOCK;
let tunnel: tc::Tunnel =
tc::Tunnel::new("127.0.0.1".to_string(), port, tc::TunnelType::Server).unwrap_or_default();
let b32_dest: String = tunnel.get_destination();
log::debug!("destination: {}", &b32_dest);
let v_b32_dest = bincode::serialize(&b32_dest).unwrap_or_default();
let v_sk = bincode::serialize(&tunnel.get_sk()).unwrap_or_default();
db::write_chunks(&db.env, &db.handle, b32_key, &v_b32_dest)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::write_chunks(&db.env, &db.handle, sk_key, &v_sk)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(tunnel)
}
/// Start router and automatic i2p tunnel creation
///
/// We'll check for an existing i2p secret key. If it doesn't
///
/// exist create a new one.
pub fn start() -> Result<(), NevekoError> {
let http_proxy_port: u16 = get_i2p_proxy_port()
.parse::<u16>()
.unwrap_or(DEFAULT_HTTP_PROXY_PORT);
let socks_port: u16 = get_i2p_socks_proxy_port()
.parse::<u16>()
.unwrap_or(DEFAULT_SOCKS_PORT);
// check for existing app and anon inbound server tunnels
let db = &DATABASE_LOCK;
let r_anon_in_sk = db::DatabaseEnvironment::read(
&db.env,
&db.handle,
&crate::APP_ANON_IN_SK.as_bytes().to_vec(),
)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let r_app_sk =
db::DatabaseEnvironment::read(&db.env, &db.handle, &crate::APP_I2P_SK.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let anon_in_sk: String = bincode::deserialize(&r_anon_in_sk[..]).unwrap_or_default();
let app_sk: String = bincode::deserialize(&r_app_sk[..]).unwrap_or_default();
log::info!("starting j4i2prs...");
let r = rw::Wrapper::create_router().map_err(|_| NevekoError::I2P)?;
let mut l: Listener = Default::default();
let run_tx = l.run_tx.clone();
let _ = thread::spawn(move || {
log::info!("run thread started");
run_tx
.send(true)
.unwrap_or_else(|_| log::error!("failed to run router"));
});
// run the main thread forever unless we get a router shutdown signal
let _ = thread::spawn(move || {
std::thread::sleep(std::time::Duration::from_secs(10));
loop {
if let Ok(run) = l.run_rx.try_recv() {
if run {
log::info!("starting router");
r.invoke_router(rw::METHOD_RUN)
.unwrap_or_else(|_| log::error!("failed to run router"));
}
}
if !l.is_running {
let is_router_on = r.is_running().unwrap_or_default();
if !is_router_on {
log::info!("router is warming up, please wait...");
}
std::thread::sleep(std::time::Duration::from_secs(60));
if is_router_on {
// check router config
if let Ok(lines) = read_lines("./router.config") {
for line in lines.map_while(Result::ok) {
if line.contains("i2np.udp.port") {
let port = line.split("=").collect::<Vec<&str>>()[1];
log::info!("router is running on external port = {}", port);
log::info!("open this port for better connectivity");
log::info!("this port was randomly assigned, keep it private");
l.is_running = true;
// start the http proxy
let http_proxy: tc::Tunnel = tc::Tunnel::new(
"127.0.0.1".to_string(),
http_proxy_port,
tc::TunnelType::Http,
)
.unwrap_or_default();
let _ = http_proxy.start(None);
// start the socks proxy
let socks_proxy: tc::Tunnel = tc::Tunnel::new(
"127.0.0.1".to_string(),
socks_port,
tc::TunnelType::Socks,
)
.unwrap_or_default();
let _ = socks_proxy.start(None);
log::info!("http proxy on port {}", http_proxy.get_port());
log::info!("socks proxy on port {}", socks_proxy.get_port());
if app_sk.is_empty() {
let t = create_server_tunnel(ServerTunnelType::App)
.unwrap_or_default();
let _ = t.start(None);
} else {
let app_tunnel = tc::Tunnel::new(
"127.0.0.1".to_string(),
utils::get_app_port(),
tc::TunnelType::ExistingServer,
)
.unwrap_or_default();
let _ = app_tunnel.start(Some(String::from(&app_sk)));
}
if anon_in_sk.is_empty() {
let t = create_server_tunnel(ServerTunnelType::AnonInbound)
.unwrap_or_default();
let _ = t.start(None);
} else {
let anon_tunnel = tc::Tunnel::new(
"127.0.0.1".to_string(),
get_anon_inbound_port(),
tc::TunnelType::ExistingServer,
)
.unwrap_or_default();
let _ = anon_tunnel.start(Some(String::from(&anon_in_sk)));
}
let db = &DATABASE_LOCK;
let v = bincode::serialize(&ProxyStatus::Open).unwrap_or_default();
db::write_chunks(
&db.env,
&db.handle,
crate::I2P_STATUS.as_bytes(),
&v,
)
.map_err(|_| NevekoError::Database(MdbError::Panic))
.unwrap_or_else(|_| log::error!("failed to write i2p status."));
}
}
}
}
}
}
});
Ok(())
}

View file

@ -4,6 +4,7 @@ pub mod contact;
pub mod neveko25519;
pub mod dispute;
pub mod db;
pub mod error;
pub mod i2p;
pub mod message;
pub mod models;
@ -21,6 +22,10 @@ pub const NEVEKO_JWT_SECRET_KEY: &str = "NEVEKO_JWT_SECRET_KEY";
pub const NEVEKO_NMPK: &str = "NEVEKO_NMPK";
// LMDB Keys
pub const APP_B32_DEST: &str = "app-b32";
pub const APP_ANON_IN_B32_DEST: &str = "app-anon-in-b32";
pub const APP_I2P_SK: &str = "app-i2p-sk";
pub const APP_ANON_IN_SK: &str = "app-anon-in-sk";
pub const AUTH_DB_KEY: &str = "a";
pub const CONTACT_DB_KEY: &str = "c";
pub const DISPUTE_DB_KEY: &str = "d";
@ -37,7 +42,7 @@ pub const RX_MESSAGE_DB_KEY: &str = "rx";
pub const DISPUTE_LAST_CHECK_DB_KEY: &str = "dlc";
pub const FTS_DB_KEY: &str = "fts";
pub const CUSTOMER_ORDER_LIST_DB_KEY: &str = "olc";
pub const ADJUDICATOR_DB_KEY: &str = "med8";
pub const ADJUDICATOR_DB_KEY: &str = "med8";
pub const MSIG_MESSAGE_DB_KEY: &str = "msig";
pub const MSIG_MESSAGE_LIST_DB_KEY: &str = "msigl";
pub const FTS_JWP_DB_KEY: &str = "fts-jwp";
@ -48,8 +53,6 @@ pub const DELIVERY_INFO_DB_KEY: &str = "delivery";
pub const MONERO_WALLET_PASSWORD: &str = "MONERO_WALLET_PASSWORD";
/// Environment variable for I2P proxy host
pub const NEVEKO_I2P_PROXY_HOST: &str = "NEVEKO_I2P_PROXY_HOST";
/// Environment variable for I2P manual tunnels.json
pub const NEVEKO_I2P_TUNNELS_JSON: &str = "NEVEKO_I2P_TUNNELS_JSON";
/// Environment variable for I2P advanced mode
pub const NEVEKO_I2P_ADVANCED_MODE: &str = "NEVEKO_I2P_ADVANCED_MODE";
/// Environment variable for I2P advanced mode
@ -59,21 +62,15 @@ pub const MONERO_WALLET_RPC_HOST: &str = "MONERO_WALLET_RPC_HOST";
/// Reference to check if gui set remote node flag
pub const GUI_REMOTE_NODE: &str = "GUI_REMOTE_NODE";
pub const GUI_SET_REMOTE_NODE: &str = "1";
/// The latest monero release download
pub const MONERO_RELEASE_VERSION: &str = "monero-linux-x64-v0.18.3.2.tar.bz2";
pub const MONERO_RELEASE_HASH: &str =
"9dafd70230a7b3a73101b624f3b5f439cc5b84a19b12c17c24e6aab94b678cbb";
/// The latest i2p-zero release version
pub const I2P_ZERO_RELEASE_VERSION: &str = "v1.21";
pub const I2P_ZERO_RELEASH_HASH: &str =
"14f34052ad6abb0c24b048816b0ea86b696ae350dd139dd1e90a67ca88e1d07a";
pub const LMDB_MAPSIZE: u64 = 1 * 1024 * 1024 * 1024;
pub const I2P_CONNECTIVITY_CHECK_INTERVAL: u32 = 600000;
pub const FTS_RETRY_INTERVAL: u32 = 60000;
/// There is a one week grace period for manual intervention of disputes
pub const DISPUTE_AUTO_SETTLE: u32 = 1000 * 60 * 60 * 24 * 7;
/// Daily dispute auto-settle check interval
pub const DISPUTE_CHECK_INTERVAL: u32 = 1000 * 60 * 60 * 24;
/// Default app port
pub const DEFAULT_HTTP_PROXY_PORT: u16 = 4455;
/// Default app port
pub const DEFAULT_SOCKS_PORT: u16 = 9051;
/// I2P CONNECTION CHECK
pub const I2P_STATUS: &str = "I2P_STATUS";
// DO NOT EDIT BELOW THIS LINE

View file

@ -2,7 +2,11 @@
use crate::{
contact,
db,
db::{
self,
DATABASE_LOCK,
},
error::NevekoError,
i2p,
models::*,
monero,
@ -11,6 +15,7 @@ use crate::{
reqres,
utils,
};
use kn0sys_lmdb_rs::MdbError;
use log::{
debug,
error,
@ -36,24 +41,19 @@ pub enum MessageType {
Multisig,
}
#[derive(Default)]
struct MultisigMessageData {
info: String,
sub_type: String,
orid: String,
}
impl Default for MultisigMessageData {
fn default() -> Self {
MultisigMessageData {
info: utils::empty_string(),
sub_type: utils::empty_string(),
orid: utils::empty_string(),
}
}
}
/// Create a new message
pub async fn create(m: Json<Message>, jwp: String, m_type: MessageType) -> Message {
pub async fn create(
m: Json<Message>,
jwp: String,
m_type: MessageType,
) -> Result<Message, NevekoError> {
let rnd = utils::generate_rnd();
let mut f_mid: String = format!("{}{}", crate::MESSAGE_DB_KEY, &rnd);
if m_type == MessageType::Multisig {
@ -61,50 +61,60 @@ pub async fn create(m: Json<Message>, jwp: String, m_type: MessageType) -> Messa
}
info!("creating message: {}", &f_mid);
let created = chrono::offset::Utc::now().timestamp();
// get contact public gpg key and encipher the message
// get contact public message key and encipher the message
debug!("sending message: {:?}", &m);
let contact: Contact = contact::find(&m.to);
let contact: Contact = contact::find(&m.to).map_err(|_| NevekoError::Message)?;
let hex_nmpk: String = contact.nmpk;
let encipher = Some(String::from(neveko25519::ENCIPHER));
let e_body = neveko25519::cipher(&hex_nmpk, String::from(&m.body), encipher).await;
let new_message = Message {
mid: String::from(&f_mid),
uid: String::from(&m.uid),
from: i2p::get_destination(None),
from: i2p::get_destination(i2p::ServerTunnelType::App)?,
body: e_body,
created,
to: String::from(&m.to),
};
debug!("insert message: {:?}", &new_message);
let s = db::Interface::open();
let db = &DATABASE_LOCK;
let k = &new_message.mid;
db::Interface::write(&s.env, &s.handle, k, &Message::to_db(&new_message));
let message = bincode::serialize(&new_message).unwrap_or_default();
db::write_chunks(&db.env, &db.handle, k.as_bytes(), &message)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
// in order to retrieve all message, write keys to with ml
let list_key = crate::MESSAGE_LIST_DB_KEY;
let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key));
if r == utils::empty_string() {
let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
debug!("creating message index");
}
let msg_list = [r, String::from(&f_mid)].join(",");
let d_r: String = bincode::deserialize(&r[..]).unwrap_or_default();
let msg_list = [d_r, String::from(&f_mid)].join(",");
let s_msg_list = bincode::serialize(&msg_list).unwrap_or_default();
debug!("writing message index {} for id: {}", msg_list, list_key);
db::Interface::write(&s.env, &s.handle, &String::from(list_key), &msg_list);
let db = &DATABASE_LOCK;
db::write_chunks(&db.env, &db.handle, list_key.as_bytes(), &s_msg_list)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
info!("attempting to send message");
let send = send_message(&new_message, &jwp, m_type).await;
send.unwrap();
new_message
Ok(new_message)
}
/// Rx message
pub async fn rx(m: Json<Message>) {
pub async fn rx(m: Json<Message>) -> Result<(), NevekoError> {
info!("rx from: {}", &m.from);
// make sure the message isn't something strange
let is_valid = validate_message(&m);
if !is_valid {
return;
error!("invalid contact");
return Err(NevekoError::Contact);
}
// don't allow messages from outside the contact list
let is_in_contact_list = contact::exists(&m.from);
let is_in_contact_list = contact::exists(&m.from).map_err(|_| NevekoError::Contact)?;
if !is_in_contact_list {
return;
error!("not a mutual contact");
return Err(NevekoError::Contact);
}
let f_mid: String = format!("{}{}", crate::MESSAGE_DB_KEY, utils::generate_rnd());
let new_message = Message {
@ -116,30 +126,37 @@ pub async fn rx(m: Json<Message>) {
to: String::from(&m.to),
};
debug!("insert message: {:?}", &new_message);
let s = db::Interface::open();
let db = &DATABASE_LOCK;
let k = &new_message.mid;
db::Interface::write(&s.env, &s.handle, k, &Message::to_db(&new_message));
let message = bincode::serialize(&new_message).unwrap_or_default();
db::write_chunks(&db.env, &db.handle, k.as_bytes(), &message)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
// in order to retrieve all message, write keys to with rx
let list_key = crate::RX_MESSAGE_DB_KEY;
let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key));
if r == utils::empty_string() {
let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
debug!("creating message index");
}
let msg_list = [r, String::from(&f_mid)].join(",");
let old: String = bincode::deserialize(&r[..]).unwrap_or_default();
let msg_list = [old, String::from(&f_mid)].join(",");
let s_msg_list = bincode::serialize(&msg_list).unwrap_or_default();
debug!("writing message index {} for {}", msg_list, list_key);
db::Interface::write(&s.env, &s.handle, &String::from(list_key), &msg_list);
db::write_chunks(&db.env, &db.handle, list_key.as_bytes(), &s_msg_list)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(())
}
/// Parse the multisig message type and info
async fn parse_multisig_message(mid: String) -> MultisigMessageData {
let d: reqres::DecipheredMessageBody = decipher_body(mid).await;
let mut bytes = hex::decode(d.body.into_bytes()).unwrap_or(Vec::new());
let decoded = String::from_utf8(bytes).unwrap_or(utils::empty_string());
async fn parse_multisig_message(mid: String) -> Result<MultisigMessageData, NevekoError> {
let d: reqres::DecipheredMessageBody = decipher_body(mid).await?;
let mut bytes = hex::decode(d.body.into_bytes()).unwrap_or_default();
let decoded = String::from_utf8(bytes).unwrap_or(String::new());
let values = decoded.split(":");
let mut v: Vec<String> = values.map(|s| String::from(s)).collect();
let mut v: Vec<String> = values.map(String::from).collect();
if v.len() != VALID_MSIG_MSG_LENGTH {
error!("invalid msig message length");
return Default::default();
return Err(NevekoError::Message);
}
let sub_type: String = v.remove(0);
let orid: String = v.remove(0);
@ -153,11 +170,11 @@ async fn parse_multisig_message(mid: String) -> MultisigMessageData {
}
bytes = Vec::new();
debug!("zero decipher bytes: {:?}", bytes);
MultisigMessageData {
Ok(MultisigMessageData {
info,
sub_type,
orid,
}
})
}
/// Rx multisig message
@ -175,21 +192,24 @@ async fn parse_multisig_message(mid: String) -> MultisigMessageData {
///
/// ```rust
/// // lookup prepare info for vendor
/// use neveko_core::db;
/// let s = db::Interface::open();
/// use neveko_core::db::*;
/// let db = &DATABASE_LOCK;
/// let key = "prepare-o123-test.b32.i2p";
/// let info_str = db::Interface::read(&s.env, &s.handle, &key);
/// let info_str = DatabaseEnvironment::read(&db.env, &db.handle, &key.as_bytes().to_vec());
/// ```
pub async fn rx_multisig(m: Json<Message>) {
pub async fn rx_multisig(m: Json<Message>) -> Result<(), NevekoError> {
info!("rx multisig from: {}", &m.from);
// make sure the message isn't something strange
let is_valid = validate_message(&m);
if !is_valid {
return;
error!("invalid contact");
return Err(NevekoError::Contact);
}
// don't allow messages from outside the contact list
let is_in_contact_list = contact::exists(&m.from);
let is_in_contact_list = contact::exists(&m.from).map_err(|_| NevekoError::Contact)?;
if !is_in_contact_list {
return;
error!("not a mutual contact");
return Err(NevekoError::Contact);
}
let f_mid: String = format!("msig{}", utils::generate_rnd());
let new_message = Message {
@ -200,76 +220,103 @@ pub async fn rx_multisig(m: Json<Message>) {
created: chrono::offset::Utc::now().timestamp(),
to: String::from(&m.to),
};
let s = db::Interface::async_open().await;
let db = &DATABASE_LOCK;
let k = &new_message.mid;
db::Interface::async_write(&s.env, &s.handle, k, &Message::to_db(&new_message)).await;
let message = bincode::serialize(&new_message).unwrap_or_default();
db::write_chunks(&db.env, &db.handle, k.as_bytes(), &message)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
// in order to retrieve all msig messages, write keys to with msigl
let list_key = crate::MSIG_MESSAGE_LIST_DB_KEY;
let r = db::Interface::async_read(&s.env, &s.handle, &String::from(list_key)).await;
if r == utils::empty_string() {
let db = &DATABASE_LOCK;
let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
debug!("creating msig message index");
}
let msg_list = [r, String::from(&f_mid)].join(",");
let old: String = bincode::deserialize(&r[..]).unwrap_or_default();
let msg_list = [old, String::from(&f_mid)].join(",");
let s_msg_list = bincode::serialize(&msg_list).unwrap_or_default();
debug!(
"writing msig message index {} for id: {}",
msg_list, list_key
);
db::Interface::async_write(&s.env, &s.handle, &String::from(list_key), &msg_list).await;
let data: MultisigMessageData = parse_multisig_message(new_message.mid).await;
let db = &DATABASE_LOCK;
db::write_chunks(&db.env, &db.handle, list_key.as_bytes(), &s_msg_list)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let data: MultisigMessageData = parse_multisig_message(new_message.mid).await?;
debug!(
"writing multisig message type {} for order {}",
&data.sub_type, &data.orid
);
// lookup msig message data by {type}-{order id}-{contact .b32.i2p address}
// store info as {a_info}:{a_info (optional)}
let s_msig = db::Interface::async_open().await;
let s_msig =
db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let msig_key = format!("{}-{}-{}", &data.sub_type, &data.orid, &m.from);
db::Interface::async_write(&s_msig.env, &s_msig.handle, &msig_key, &data.info).await;
let db = &DATABASE_LOCK;
db::write_chunks(
&s_msig.env,
&db.handle,
msig_key.as_bytes(),
data.info.as_bytes(),
)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(())
}
/// Message lookup
pub fn find(mid: &String) -> Message {
let s = db::Interface::open();
let r = db::Interface::read(&s.env, &s.handle, &String::from(mid));
if r == utils::empty_string() {
/// Message lookup()
pub fn find(mid: &String) -> Result<Message, NevekoError> {
let db = &DATABASE_LOCK;
let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &mid.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
error!("message not found");
return Default::default();
return Err(NevekoError::Message);
}
Message::from_db(String::from(mid), r)
let result: Message = bincode::deserialize(&r[..]).unwrap_or_default();
Ok(result)
}
/// Message lookup
pub fn find_all() -> Vec<Message> {
let i_s = db::Interface::open();
pub fn find_all() -> Result<Vec<Message>, NevekoError> {
let db = &DATABASE_LOCK;
let i_list_key = crate::MESSAGE_LIST_DB_KEY;
let i_r = db::Interface::read(&i_s.env, &i_s.handle, &String::from(i_list_key));
if i_r == utils::empty_string() {
let i_r = db::DatabaseEnvironment::read(&db.env, &db.handle, &i_list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if i_r.is_empty() {
error!("message index not found");
}
let i_r: String = bincode::deserialize(&i_r[..]).unwrap_or_default();
let i_v_mid = i_r.split(",");
let i_v: Vec<String> = i_v_mid.map(|s| String::from(s)).collect();
let i_v: Vec<String> = i_v_mid.map(String::from).collect();
let mut messages: Vec<Message> = Vec::new();
for m in i_v {
let message: Message = find(&m);
if message.mid != utils::empty_string() {
let message: Message = find(&m)?;
if !message.mid.is_empty() {
messages.push(message);
}
}
let o_list_key = crate::RX_MESSAGE_DB_KEY;
let o_s = db::Interface::open();
let o_r = db::Interface::read(&o_s.env, &o_s.handle, &String::from(o_list_key));
if o_r == utils::empty_string() {
let o_r = db::DatabaseEnvironment::read(&db.env, &db.handle, &o_list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if o_r.is_empty() {
error!("message index not found");
}
let o_r: String = bincode::deserialize(&o_r[..]).unwrap_or_default();
let o_v_mid = o_r.split(",");
let o_v: Vec<String> = o_v_mid.map(|s| String::from(s)).collect();
let o_v: Vec<String> = o_v_mid.map(String::from).collect();
for m in o_v {
let message: Message = find(&m);
if message.mid != utils::empty_string() {
let message: Message = find(&m)?;
if !message.mid.is_empty() {
messages.push(message);
}
}
messages
Ok(messages)
}
/// Tx message
@ -286,7 +333,7 @@ async fn send_message(out: &Message, jwp: &str, m_type: MessageType) -> Result<(
.await
.unwrap_or(false);
if is_online {
return match client?
match client?
.post(url)
.header("proof", jwp)
.json(&out)
@ -297,8 +344,8 @@ async fn send_message(out: &Message, jwp: &str, m_type: MessageType) -> Result<(
let status = response.status();
debug!("send response: {:?}", status.as_str());
if status == StatusCode::OK || status == StatusCode::PAYMENT_REQUIRED {
remove_from_fts(String::from(&out.mid));
return Ok(());
remove_from_fts(String::from(&out.mid))?;
Ok(())
} else {
Ok(())
}
@ -307,27 +354,29 @@ async fn send_message(out: &Message, jwp: &str, m_type: MessageType) -> Result<(
error!("failed to send message due to: {:?}", e);
Ok(())
}
};
}
} else {
send_to_retry(String::from(&out.mid)).await;
send_to_retry(String::from(&out.mid)).await?;
Ok(())
}
}
/// Returns deciphered message
pub async fn decipher_body(mid: String) -> reqres::DecipheredMessageBody {
let m = find(&mid);
let contact = contact::find_by_i2p_address(&m.from);
pub async fn decipher_body(mid: String) -> Result<reqres::DecipheredMessageBody, NevekoError> {
let m = find(&mid)?;
let contact = contact::find_by_i2p_address(&m.from)?;
let nmpk = contact.nmpk;
let message = String::from(&m.body);
let body = neveko25519::cipher(&nmpk, message, None).await;
reqres::DecipheredMessageBody { mid, body }
Ok(reqres::DecipheredMessageBody { mid, body })
}
/// Message deletion
pub fn delete(mid: &String) {
let s = db::Interface::open();
db::Interface::delete(&s.env, &s.handle, &String::from(mid));
pub fn delete(mid: &String) -> Result<(), NevekoError> {
let db = &DATABASE_LOCK;
let _ = db::DatabaseEnvironment::delete(&db.env, &db.handle, mid.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(())
}
/// ping the contact health check over i2p
@ -363,63 +412,75 @@ async fn is_contact_online(contact: &String, jwp: String) -> Result<bool, Box<dy
}
/// stage message for async retry
async fn send_to_retry(mid: String) {
async fn send_to_retry(mid: String) -> Result<(), NevekoError> {
info!("sending {} to fts", &mid);
let s = db::Interface::open();
let db = &DATABASE_LOCK;
// in order to retrieve FTS (failed-to-send), write keys to db with fts
let list_key = crate::FTS_DB_KEY;
let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key));
if r == utils::empty_string() {
let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
debug!("creating fts message index");
}
let mut msg_list = [String::from(&r), String::from(&mid)].join(",");
let i_r: String = bincode::deserialize(&r[..]).unwrap_or_default();
let mut msg_list = [String::from(&i_r), String::from(&mid)].join(",");
let s_msg_list = bincode::serialize(&msg_list).unwrap_or_default();
// don't duplicate message ids in fts
if String::from(&r).contains(&String::from(&mid)) {
msg_list = r;
if String::from(&i_r).contains(&String::from(&mid)) {
msg_list = i_r;
}
debug!(
"writing fts message index {} for id: {}",
msg_list, list_key
);
db::Interface::write(&s.env, &s.handle, &String::from(list_key), &msg_list);
db::write_chunks(&db.env, &db.handle, list_key.as_bytes(), &s_msg_list)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
// restart fts if not empty
let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key));
let v_mid = r.split(",");
let v: Vec<String> = v_mid.map(|s| String::from(s)).collect();
let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let str_r: String = bincode::deserialize(&r[..]).unwrap_or_default();
let v_mid = str_r.split(",");
let v: Vec<String> = v_mid.map(String::from).collect();
debug!("fts contents: {:#?}", v);
let cleared = is_fts_clear(r);
let cleared = is_fts_clear(str_r);
if !cleared {
debug!("restarting fts");
utils::restart_retry_fts();
}
Ok(())
}
/// clear fts message from index
fn remove_from_fts(mid: String) {
fn remove_from_fts(mid: String) -> Result<(), NevekoError> {
info!("removing id {} from fts", &mid);
let s = db::Interface::open();
let db = &DATABASE_LOCK;
// in order to retrieve FTS (failed-to-send), write keys to with fts
let list_key = crate::FTS_DB_KEY;
let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key));
if r == utils::empty_string() {
let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
debug!("fts is empty");
}
let pre_v_fts = r.split(",");
let s_r: String = bincode::deserialize(&r[..]).unwrap_or_default();
let pre_v_fts = s_r.split(",");
let v: Vec<String> = pre_v_fts
.map(|s| {
if s != &mid {
String::from(s)
} else {
utils::empty_string()
String::new()
}
})
.collect();
let msg_list = v.join(",");
let s_msg_list = bincode::serialize(&msg_list).unwrap_or_default();
debug!(
"writing fts message index {} for id: {}",
msg_list, list_key
);
db::Interface::write(&s.env, &s.handle, &String::from(list_key), &msg_list);
db::write_chunks(&db.env, &db.handle, list_key.as_bytes(), &s_msg_list)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(())
}
/// Triggered on app startup, retries to send fts every minute
@ -427,42 +488,48 @@ fn remove_from_fts(mid: String) {
/// FTS thread terminates when empty and gets restarted on the next
///
/// failed-to-send message.
pub async fn retry_fts() {
pub async fn retry_fts() -> Result<(), NevekoError> {
let tick: std::sync::mpsc::Receiver<()> = schedule_recv::periodic_ms(crate::FTS_RETRY_INTERVAL);
loop {
debug!("running retry failed-to-send thread");
tick.recv().unwrap();
let s = db::Interface::open();
let db = &DATABASE_LOCK;
let list_key = crate::FTS_DB_KEY;
let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key));
if r == utils::empty_string() {
let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
info!("fts message index not found");
break; // terminate fts if no message to send
return Err(NevekoError::Database(MdbError::NotFound)); // terminate fts if no message to send
}
let v_mid = r.split(",");
let v: Vec<String> = v_mid.map(|s| String::from(s)).collect();
let s_r: String = bincode::deserialize(&r[..]).unwrap_or_default();
let v_mid = s_r.split(",");
let v: Vec<String> = v_mid.map(String::from).collect();
debug!("fts contents: {:#?}", v);
let cleared = is_fts_clear(r);
let cleared = is_fts_clear(s_r);
if cleared {
// index was created but cleared
info!("terminating retry fts thread");
db::Interface::delete(&s.env, &s.handle, list_key);
break;
let _ =
db::DatabaseEnvironment::delete(&db.env, &db.handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
break Err(NevekoError::Database(MdbError::NotFound));
}
for m in v {
let message: Message = find(&m);
if message.mid != utils::empty_string() {
let s = db::Interface::open();
let message: Message = find(&m)?;
if !message.mid.is_empty() {
// get jwp from db
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &message.to);
let jwp = db::Interface::read(&s.env, &s.handle, &k);
if jwp != utils::empty_string() {
let jwp =
db::DatabaseEnvironment::read(&db.env, &db.handle, &k.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if !jwp.is_empty() {
let m_type = if message.mid.contains("msig") {
MessageType::Multisig
} else {
MessageType::Normal
};
send_message(&message, &jwp, m_type).await.unwrap();
let str_jwp: String = bincode::deserialize(&jwp[..]).unwrap_or_default();
send_message(&message, &str_jwp, m_type).await.unwrap();
} else {
error!("not jwp found for fts id: {}", &message.mid);
}
@ -476,35 +543,34 @@ fn validate_message(j: &Json<Message>) -> bool {
info!("validating message: {}", &j.mid);
j.mid.len() < utils::string_limit()
&& j.body.len() < utils::message_limit()
&& j.to == i2p::get_destination(None)
&& j.to == i2p::get_destination(i2p::ServerTunnelType::App).unwrap_or_default()
&& j.uid.len() < utils::string_limit()
}
fn is_fts_clear(r: String) -> bool {
let v_mid = r.split(",");
let v: Vec<String> = v_mid.map(|s| String::from(s)).collect();
let v: Vec<String> = v_mid.map(String::from).collect();
debug!("fts contents: {:#?}", v);
let limit = v.len() <= 1;
if !limit {
return v.len() >= 2
&& v[v.len() - 1] == utils::empty_string()
&& v[0] == utils::empty_string();
v.len() >= 2 && v[v.len() - 1].is_empty() && v[0].is_empty()
} else {
return limit;
limit
}
}
/// Enciphers and sends the output from the monero-rpc
///
/// `prepare_multisig_info` method.
pub async fn send_prepare_info(orid: &String, contact: &String) {
let s = db::Interface::open();
pub async fn send_prepare_info(orid: &String, contact: &String) -> Result<(), NevekoError> {
let db = &DATABASE_LOCK;
let wallet_name = String::from(orid);
let wallet_password = utils::empty_string();
let wallet_password = String::new();
monero::open_wallet(&wallet_name, &wallet_password).await;
let prepare_info = monero::prepare_wallet().await;
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, contact);
let jwp = db::Interface::read(&s.env, &s.handle, &k);
let jwp = db::DatabaseEnvironment::read(&db.env, &db.handle, &k.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let body_str = format!(
"{}:{}:{}",
PREPARE_MSIG, orid, &prepare_info.result.multisig_info
@ -516,21 +582,28 @@ pub async fn send_prepare_info(orid: &String, contact: &String) {
..Default::default()
};
let j_message: Json<Message> = utils::message_to_json(&message);
monero::close_wallet(&orid, &wallet_password).await;
create(j_message, jwp, MessageType::Multisig).await;
monero::close_wallet(orid, &wallet_password).await;
let str_jwp: String = bincode::deserialize(&jwp[..]).unwrap_or_default();
create(j_message, str_jwp, MessageType::Multisig).await?;
Ok(())
}
/// Enciphers and sends the output from the monero-rpc
///
/// `make_multisig_info` method.
pub async fn send_make_info(orid: &String, contact: &String, info: Vec<String>) {
let s = db::Interface::open();
pub async fn send_make_info(
orid: &String,
contact: &String,
info: Vec<String>,
) -> Result<(), NevekoError> {
let db = &DATABASE_LOCK;
let wallet_name = String::from(orid);
let wallet_password = utils::empty_string();
let wallet_password = String::new();
monero::open_wallet(&wallet_name, &wallet_password).await;
let make_info = monero::make_wallet(info).await;
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, contact);
let jwp = db::Interface::read(&s.env, &s.handle, &k);
let jwp = db::DatabaseEnvironment::read(&db.env, &db.handle, &k.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let body_str = format!("{}:{}:{}", MAKE_MSIG, orid, &make_info.result.multisig_info);
let message: Message = Message {
body: body_str,
@ -539,8 +612,10 @@ pub async fn send_make_info(orid: &String, contact: &String, info: Vec<String>)
..Default::default()
};
let j_message: Json<Message> = utils::message_to_json(&message);
monero::close_wallet(&orid, &wallet_password).await;
create(j_message, jwp, MessageType::Multisig).await;
monero::close_wallet(orid, &wallet_password).await;
let str_jwp: String = bincode::deserialize(&jwp[..]).unwrap_or_default();
create(j_message, str_jwp, MessageType::Multisig).await?;
Ok(())
}
/// Enciphers and sends the output from the monero-rpc
@ -551,14 +626,15 @@ pub async fn send_exchange_info(
contact: &String,
info: Vec<String>,
kex_init: bool,
) {
let s = db::Interface::open();
) -> Result<(), NevekoError> {
let db = &DATABASE_LOCK;
let wallet_name = String::from(orid);
let wallet_password = utils::empty_string();
let wallet_password = String::new();
monero::open_wallet(&wallet_name, &wallet_password).await;
let exchange_info = monero::exchange_multisig_keys(false, info, &wallet_password).await;
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, contact);
let jwp = db::Interface::read(&s.env, &s.handle, &k);
let jwp = db::DatabaseEnvironment::read(&db.env, &db.handle, &k.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let mut body_str = format!(
"{}:{}:{}",
KEX_ONE_MSIG, orid, &exchange_info.result.multisig_info
@ -576,21 +652,24 @@ pub async fn send_exchange_info(
..Default::default()
};
let j_message: Json<Message> = utils::message_to_json(&message);
monero::close_wallet(&orid, &wallet_password).await;
create(j_message, jwp, MessageType::Multisig).await;
monero::close_wallet(orid, &wallet_password).await;
let str_jwp: String = bincode::deserialize(&jwp[..]).unwrap_or_default();
create(j_message, str_jwp, MessageType::Multisig).await?;
Ok(())
}
/// Enciphers and sends the output from the monero-rpc
///
/// `export_multisig_info` method.
pub async fn send_export_info(orid: &String, contact: &String) {
let s = db::Interface::open();
pub async fn send_export_info(orid: &String, contact: &String) -> Result<(), NevekoError> {
let db = &DATABASE_LOCK;
let wallet_name = String::from(orid);
let wallet_password = utils::empty_string();
let wallet_password = String::new();
monero::open_wallet(&wallet_name, &wallet_password).await;
let exchange_info = monero::export_multisig_info().await;
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, contact);
let jwp = db::Interface::read(&s.env, &s.handle, &k);
let jwp = db::DatabaseEnvironment::read(&db.env, &db.handle, &k.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let body_str = format!("{}:{}:{}", EXPORT_MSIG, orid, &exchange_info.result.info);
let message: Message = Message {
body: body_str,
@ -599,8 +678,10 @@ pub async fn send_export_info(orid: &String, contact: &String) {
..Default::default()
};
let j_message: Json<Message> = utils::message_to_json(&message);
monero::close_wallet(&orid, &wallet_password).await;
create(j_message, jwp, MessageType::Multisig).await;
monero::close_wallet(orid, &wallet_password).await;
let str_jwp: String = bincode::deserialize(&jwp[..]).unwrap_or_default();
create(j_message, str_jwp, MessageType::Multisig).await?;
Ok(())
}
/// The customer or vendor (dispute only) needs to export
@ -608,22 +689,23 @@ pub async fn send_export_info(orid: &String, contact: &String) {
/// multisig info after funding. Once the info is imported
///
/// successfully the order needs to be updated to `MultisigComplete`.
pub async fn send_import_info(orid: &String, info: &Vec<String>) {
pub async fn send_import_info(orid: &String, info: &Vec<String>) -> Result<(), NevekoError> {
let wallet_name = String::from(orid);
let wallet_password = utils::empty_string();
let wallet_password = String::new();
monero::open_wallet(&wallet_name, &wallet_password).await;
let pre_import = monero::import_multisig_info(info.to_vec()).await;
monero::close_wallet(&orid, &wallet_password).await;
monero::close_wallet(orid, &wallet_password).await;
if pre_import.result.n_outputs == 0 {
error!("unable to import multisig info for order: {}", orid);
return;
return Err(NevekoError::Database(MdbError::Panic))?;
}
let mut old_order = order::find(orid);
let mut old_order = order::find(orid)?;
let status = order::StatusType::MulitsigComplete.value();
old_order.status = String::from(&status);
let j_old_order = Json(old_order);
order::modify(j_old_order);
order::modify(j_old_order)?;
debug!("order: {} updated to: {}", orid, status);
Ok(())
}
/// Customer begins multisig orchestration by requesting the prepare info
@ -699,55 +781,54 @@ pub async fn d_trigger_msig_info(
mod tests {
use super::*;
async fn cleanup(k: &String) {
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
let s = db::Interface::async_open().await;
db::Interface::async_delete(&s.env, &s.handle, k).await;
fn cleanup(k: &String) -> Result<(), NevekoError> {
let db = &DATABASE_LOCK;
let _ = db::DatabaseEnvironment::delete(&db.env, &db.handle, k.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(())
}
#[test]
fn create_test() {
fn create_test() -> Result<(), NevekoError> {
// run and async cleanup so the test doesn't fail when deleting test data
use tokio::runtime::Runtime;
let rt = Runtime::new().expect("Unable to create Runtime for test");
let _enter = rt.enter();
let body: String = String::from("test body");
let message = Message {
body: body,
body,
..Default::default()
};
let j_message = utils::message_to_json(&message);
let jwp = String::from("test-jwp");
tokio::spawn(async move {
let test_message = create(j_message, jwp, MessageType::Normal).await;
let a_test_message = create(j_message, jwp, MessageType::Normal).await;
let test_message = a_test_message.unwrap_or_default();
let expected: Message = Default::default();
assert_eq!(test_message.body, expected.body);
cleanup(&test_message.mid).await;
cleanup(&test_message.mid).unwrap();
});
Runtime::shutdown_background(rt);
Ok(())
}
#[test]
fn find_test() {
fn find_test() -> Result<(), NevekoError> {
// run and async cleanup so the test doesn't fail when deleting test data
use tokio::runtime::Runtime;
let rt = Runtime::new().expect("Unable to create Runtime for test");
let _enter = rt.enter();
let body: String = String::from("test body");
let expected_message = Message {
body: body,
body,
..Default::default()
};
let k = "test-key";
tokio::spawn(async move {
let s = db::Interface::async_open().await;
db::Interface::async_write(&s.env, &s.handle, k, &Message::to_db(&expected_message))
.await;
let actual_message: Message = find(&String::from(k));
assert_eq!(expected_message.body, actual_message.body);
cleanup(&String::from(k)).await;
});
Runtime::shutdown_background(rt);
let db = &DATABASE_LOCK;
let message = bincode::serialize(&expected_message).unwrap_or_default();
db::write_chunks(&db.env, &db.handle, k.as_bytes(), &message)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let actual_message: Message = find(&String::from(k))?;
assert_eq!(expected_message.body, actual_message.body);
cleanup(&String::from(k))?;
Ok(())
}
#[test]
@ -758,7 +839,7 @@ mod tests {
let _enter = rt.enter();
let body: String = String::from("test body");
let message = Message {
body: body,
body,
..Default::default()
};
let j_message = utils::message_to_json(&message);

View file

@ -1,13 +1,12 @@
//! Custom object relational mapping (ORM) for structs into LMBD
use crate::utils;
use rocket::serde::{
json::Json,
Deserialize,
Serialize,
};
#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Default, Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct Authorization {
pub aid: String,
@ -18,47 +17,7 @@ pub struct Authorization {
pub xmr_address: String,
}
impl Default for Authorization {
fn default() -> Self {
Authorization {
aid: utils::empty_string(),
created: 0,
uid: utils::empty_string(),
rnd: utils::empty_string(),
token: utils::empty_string(),
xmr_address: utils::empty_string(),
}
}
}
impl Authorization {
pub fn to_db(a: &Authorization) -> String {
format!(
"{}:{}:{}:{}:{}",
a.created, a.uid, a.rnd, a.token, a.xmr_address
)
}
pub fn from_db(k: String, v: String) -> Authorization {
let values = v.split(":");
let mut v: Vec<String> = values.map(|s| String::from(s)).collect();
let created_str = v.remove(0);
let created = match created_str.parse::<i64>() {
Ok(n) => n,
Err(_e) => 0,
};
let uid = v.remove(0);
let rnd = v.remove(0);
let token = v.remove(0);
let xmr_address = v.remove(0);
Authorization {
aid: k,
created,
uid,
rnd,
token,
xmr_address,
}
}
pub fn update_uid(a: Authorization, uid: String) -> Authorization {
Authorization {
aid: a.aid,
@ -86,7 +45,7 @@ impl Authorization {
}
}
#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Default, Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct Contact {
pub cid: String,
@ -96,46 +55,7 @@ pub struct Contact {
pub nmpk: String,
}
impl Default for Contact {
fn default() -> Self {
Contact {
cid: utils::empty_string(),
nmpk: utils::empty_string(),
i2p_address: utils::empty_string(),
is_vendor: false,
xmr_address: utils::empty_string(),
}
}
}
impl Contact {
pub fn to_db(c: &Contact) -> String {
format!(
"{}!{}!{}!{}",
c.nmpk, c.i2p_address, c.is_vendor, c.xmr_address
)
}
pub fn from_db(k: String, v: String) -> Contact {
let values = v.split("!");
let mut v: Vec<String> = values.map(|s| String::from(s)).collect();
let nmpk = v.remove(0);
let i2p_address = v.remove(0);
let is_vendor = match v.remove(0).parse::<bool>() {
Ok(n) => n,
Err(_e) => false,
};
let xmr_address = v.remove(0);
Contact {
cid: k,
nmpk,
i2p_address,
is_vendor,
xmr_address,
}
}
}
#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Default, Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct Message {
pub mid: String,
@ -146,47 +66,7 @@ pub struct Message {
pub to: String,
}
impl Default for Message {
fn default() -> Self {
Message {
mid: utils::empty_string(),
uid: utils::empty_string(),
body: utils::empty_string(),
created: 0,
from: utils::empty_string(),
to: utils::empty_string(),
}
}
}
impl Message {
pub fn to_db(m: &Message) -> String {
format!("{}:{}:{}:{}:{}", m.uid, m.body, m.created, m.from, m.to)
}
pub fn from_db(k: String, v: String) -> Message {
let values = v.split(":");
let mut v: Vec<String> = values.map(|s| String::from(s)).collect();
let uid = v.remove(0);
let body = v.remove(0);
let created_str = v.remove(0);
let created = match created_str.parse::<i64>() {
Ok(n) => n,
Err(_e) => 0,
};
let from = v.remove(0);
let to = v.remove(0);
Message {
mid: k,
uid,
body,
created,
from,
to,
}
}
}
#[derive(Debug, Deserialize, Serialize)]
#[derive(Debug, Default, Deserialize, Serialize)]
#[serde(crate = "rocket::serde")]
pub struct User {
pub uid: String,
@ -194,31 +74,7 @@ pub struct User {
pub name: String,
}
impl Default for User {
fn default() -> Self {
User {
uid: utils::empty_string(),
xmr_address: utils::empty_string(),
name: utils::empty_string(),
}
}
}
impl User {
pub fn to_db(u: &User) -> String {
format!("{}:{}", u.name, u.xmr_address)
}
pub fn from_db(k: String, v: String) -> User {
let values = v.split(":");
let mut v: Vec<String> = values.map(|s| String::from(s)).collect();
let name = v.remove(0);
let xmr_address = v.remove(0);
User {
uid: k,
name,
xmr_address,
}
}
pub fn update(u: User, name: String) -> User {
User {
uid: u.uid,
@ -228,7 +84,7 @@ impl User {
}
}
#[derive(Debug, Deserialize, Serialize)]
#[derive(Debug, Default, Deserialize, Serialize)]
#[serde(crate = "rocket::serde")]
pub struct Product {
pub pid: String,
@ -240,61 +96,12 @@ pub struct Product {
pub qty: u128,
}
impl Default for Product {
fn default() -> Self {
Product {
pid: utils::empty_string(),
description: utils::empty_string(),
image: Vec::new(),
in_stock: false,
name: utils::empty_string(),
price: 0,
qty: 0,
}
}
}
impl Product {
pub fn to_db(p: &Product) -> String {
let image: String = hex::encode(&p.image);
format!(
"{}:{}:{}:{}:{}:{}",
p.description, image, p.in_stock, p.name, p.price, p.qty
)
}
pub fn from_db(k: String, v: String) -> Product {
let values = v.split(":");
let mut v: Vec<String> = values.map(|s| String::from(s)).collect();
let description = v.remove(0);
let image = hex::decode(v.remove(0)).unwrap_or(Vec::new());
let in_stock = match v.remove(0).parse::<bool>() {
Ok(b) => b,
Err(_) => false,
};
let name = v.remove(0);
let price = match v.remove(0).parse::<u128>() {
Ok(p) => p,
Err(_) => 0,
};
let qty = match v.remove(0).parse::<u128>() {
Ok(q) => q,
Err(_) => 0,
};
Product {
pid: k,
description,
image,
in_stock,
name,
price,
qty,
}
}
pub fn update(p: Product, jp: &Json<Product>) -> Product {
Product {
pid: p.pid,
description: String::from(&jp.description),
image: jp.image.iter().cloned().collect(),
image: jp.image.to_vec(),
in_stock: jp.in_stock,
name: String::from(&jp.name),
price: jp.price,
@ -303,7 +110,7 @@ impl Product {
}
}
#[derive(Debug, Deserialize, Serialize)]
#[derive(Debug, Default, Deserialize, Serialize)]
#[serde(crate = "rocket::serde")]
pub struct Order {
pub orid: String,
@ -341,152 +148,7 @@ pub struct Order {
pub xmr_address: String,
}
impl Default for Order {
fn default() -> Self {
Order {
orid: utils::empty_string(),
cid: utils::empty_string(),
pid: utils::empty_string(),
xmr_address: utils::empty_string(),
cust_kex_1: utils::empty_string(),
cust_kex_2: utils::empty_string(),
cust_kex_3: utils::empty_string(),
cust_msig_make: utils::empty_string(),
cust_msig_prepare: utils::empty_string(),
cust_msig_txset: utils::empty_string(),
date: 0,
deliver_date: 0,
hash: utils::empty_string(),
adjudicator_kex_1: utils::empty_string(),
adjudicator_kex_2: utils::empty_string(),
adjudicator_kex_3: utils::empty_string(),
adjudicator_msig_make: utils::empty_string(),
adjudicator_msig_prepare: utils::empty_string(),
ship_address: utils::empty_string(),
ship_date: 0,
subaddress: utils::empty_string(),
status: utils::empty_string(),
quantity: 0,
vend_kex_1: utils::empty_string(),
vend_kex_2: utils::empty_string(),
vend_kex_3: utils::empty_string(),
vend_msig_make: utils::empty_string(),
vend_msig_prepare: utils::empty_string(),
vend_msig_txset: utils::empty_string(),
}
}
}
impl Order {
pub fn to_db(o: &Order) -> String {
format!(
"{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}",
o.cid,
o.pid,
o.cust_kex_1,
o.cust_kex_2,
o.cust_kex_3,
o.cust_msig_make,
o.cust_msig_prepare,
o.cust_msig_txset,
o.date,
o.deliver_date,
o.hash,
o.adjudicator_msig_make,
o.adjudicator_msig_prepare,
o.adjudicator_kex_1,
o.adjudicator_kex_2,
o.adjudicator_kex_3,
o.ship_address,
o.ship_date,
o.subaddress,
o.status,
o.quantity,
o.vend_kex_1,
o.vend_kex_2,
o.vend_kex_3,
o.vend_msig_make,
o.vend_msig_prepare,
o.vend_msig_txset,
o.xmr_address,
)
}
pub fn from_db(k: String, v: String) -> Order {
let values = v.split(":");
let mut v: Vec<String> = values.map(|s| String::from(s)).collect();
let orid = k;
let cid = v.remove(0);
let pid = v.remove(0);
let cust_kex_1 = v.remove(0);
let cust_kex_2 = v.remove(0);
let cust_kex_3 = v.remove(0);
let cust_msig_make = v.remove(0);
let cust_msig_prepare = v.remove(0);
let cust_msig_txset = v.remove(0);
let date = match v.remove(0).parse::<i64>() {
Ok(d) => d,
Err(_) => 0,
};
let deliver_date = match v.remove(0).parse::<i64>() {
Ok(d) => d,
Err(_) => 0,
};
let hash = v.remove(0);
let adjudicator_msig_make = v.remove(0);
let adjudicator_msig_prepare = v.remove(0);
let adjudicator_kex_1 = v.remove(0);
let adjudicator_kex_2 = v.remove(0);
let adjudicator_kex_3 = v.remove(0);
let ship_address = v.remove(0);
let ship_date = match v.remove(0).parse::<i64>() {
Ok(d) => d,
Err(_) => 0,
};
let subaddress = v.remove(0);
let status = v.remove(0);
let quantity = match v.remove(0).parse::<u128>() {
Ok(d) => d,
Err(_) => 0,
};
let vend_kex_1 = v.remove(0);
let vend_kex_2 = v.remove(0);
let vend_kex_3 = v.remove(0);
let vend_msig_make = v.remove(0);
let vend_msig_prepare = v.remove(0);
let vend_msig_txset = v.remove(0);
let xmr_address = v.remove(0);
Order {
orid,
cid,
pid,
cust_kex_1,
cust_kex_2,
cust_kex_3,
cust_msig_make,
cust_msig_prepare,
cust_msig_txset,
date,
deliver_date,
hash,
adjudicator_kex_1,
adjudicator_kex_2,
adjudicator_kex_3,
adjudicator_msig_make,
adjudicator_msig_prepare,
ship_address,
ship_date,
subaddress,
status,
quantity,
vend_kex_1,
vend_kex_2,
vend_kex_3,
vend_msig_make,
vend_msig_prepare,
vend_msig_txset,
xmr_address,
}
}
pub fn update(orid: String, o: &Json<Order>) -> Order {
Order {
orid,
@ -522,7 +184,7 @@ impl Order {
}
}
#[derive(Debug, Deserialize, Serialize)]
#[derive(Debug, Default, Deserialize, Serialize)]
#[serde(crate = "rocket::serde")]
pub struct Dispute {
pub did: String,
@ -530,36 +192,3 @@ pub struct Dispute {
pub orid: String,
pub tx_set: String,
}
impl Default for Dispute {
fn default() -> Self {
Dispute {
did: utils::empty_string(),
created: 0,
orid: utils::empty_string(),
tx_set: utils::empty_string(),
}
}
}
impl Dispute {
pub fn to_db(d: &Dispute) -> String {
format!("{}:{}:{}", d.created, d.orid, d.tx_set)
}
pub fn from_db(k: String, v: String) -> Dispute {
let values = v.split(":");
let mut v: Vec<String> = values.map(|s| String::from(s)).collect();
let created = match v.remove(0).parse::<i64>() {
Ok(t) => t,
Err(_) => 0,
};
let orid = v.remove(0);
let tx_set = v.remove(0);
Dispute {
did: k,
created,
orid,
tx_set,
}
}
}

View file

@ -2,6 +2,7 @@
use crate::{
args,
error::NevekoError,
i2p,
proof,
reqres,
@ -17,11 +18,7 @@ use log::{
};
use std::{
error::Error,
io::Write,
process::{
Command,
Stdio,
},
process::Command,
};
use lazy_static::lazy_static;
@ -176,7 +173,7 @@ impl LockTimeLimit {
/// Start monerod from the `--monero-location` flag
///
/// default: /home/$USER/monero-xxx-xxx
pub fn start_daemon() {
pub fn start_daemon() -> Result<(), NevekoError> {
info!("starting monerod");
let blockchain_dir = get_blockchain_dir();
let bin_dir = get_monero_location();
@ -184,13 +181,13 @@ pub fn start_daemon() {
let mut socks_proxy_host = utils::get_i2p_wallet_proxy_host();
if socks_proxy_host.contains("http://") {
let values = socks_proxy_host.split("http://");
let mut v: Vec<String> = values.map(|s| String::from(s)).collect();
let mut v: Vec<String> = values.map(String::from).collect();
socks_proxy_host = v.remove(1);
};
let tx_proxy = format!("i2p,{}", socks_proxy_host);
// proxy host can't have protocol
let anon_in_port = get_anon_inbound_port();
let destination = i2p::get_destination(Some(anon_in_port));
let destination = i2p::get_destination(i2p::ServerTunnelType::App)?;
let anon_inbound = format!("{},127.0.0.1:{}", destination, anon_in_port);
let mut args = vec!["--data-dir", &blockchain_dir, "--detach"];
if release_env == utils::ReleaseEnvironment::Development {
@ -200,6 +197,7 @@ pub fn start_daemon() {
.spawn()
.expect("monerod failed to start");
debug!("{:?}", output.stdout);
Ok(())
} else {
args.push("--tx-proxy");
args.push(&tx_proxy);
@ -210,16 +208,17 @@ pub fn start_daemon() {
.spawn()
.expect("monerod failed to start");
debug!("{:?}", output.stdout);
Ok(())
}
}
/// Start monero-wallet-rpc
pub fn start_rpc() {
info!("starting monero-wallet-rpc");
let cli_args = args::Args::parse();
let bin_dir = get_monero_location();
let port = get_rpc_port();
let login = get_rpc_creds();
info!("starting monero-wallet-rpc from {}", &bin_dir);
let daemon_address = cli_args.monero_rpc_daemon;
let rpc_login = format!("{}:{}", &login.username, &login.credential);
let release_env = utils::get_release_env();
@ -241,7 +240,7 @@ pub fn start_rpc() {
let mut proxy_host = utils::get_i2p_wallet_proxy_host();
if proxy_host.contains("http://") {
let values = proxy_host.split("http://");
let mut v: Vec<String> = values.map(|s| String::from(s)).collect();
let mut v: Vec<String> = values.map(String::from).collect();
proxy_host = v.remove(1);
}
let mut args = vec![
@ -281,9 +280,9 @@ pub fn start_rpc() {
fn get_rpc_port() -> String {
let args = args::Args::parse();
let rpc = String::from(args.monero_rpc_host);
let rpc = args.monero_rpc_host;
let values = rpc.split(":");
let mut v: Vec<String> = values.map(|s| String::from(s)).collect();
let mut v: Vec<String> = values.map(String::from).collect();
let port = v.remove(2);
debug!("monero-wallet-rpc port: {}", port);
port
@ -291,28 +290,22 @@ fn get_rpc_port() -> String {
pub fn get_daemon_port() -> u16 {
let args = args::Args::parse();
let rpc = String::from(args.monero_rpc_daemon);
let rpc = args.monero_rpc_daemon;
let values = rpc.split(":");
let mut v: Vec<String> = values.map(|s| String::from(s)).collect();
let mut v: Vec<String> = values.map(String::from).collect();
let port = v.remove(2);
debug!("monerod port: {}", port);
match port.parse::<u16>() {
Ok(p) => p,
Err(_) => 0,
}
port.parse::<u16>().unwrap_or(0)
}
pub fn get_tx_proxy_port() -> u16 {
let args = args::Args::parse();
let rpc = String::from(args.i2p_socks_proxy_host);
let rpc = args.i2p_socks_proxy_host;
let values = rpc.split(":");
let mut v: Vec<String> = values.map(|s| String::from(s)).collect();
let mut v: Vec<String> = values.map(String::from).collect();
let port = v.remove(2);
debug!("i2p socks port: {}", port);
match port.parse::<u16>() {
Ok(p) => p,
Err(_) => 0,
}
port.parse::<u16>().unwrap_or(0)
}
pub fn get_anon_inbound_port() -> u16 {
@ -323,22 +316,21 @@ pub fn get_anon_inbound_port() -> u16 {
/// Get monero rpc host from command line argument
fn get_blockchain_dir() -> String {
let args = args::Args::parse();
String::from(args.monero_blockchain_dir)
args.monero_blockchain_dir
}
/// Get monero download location
fn get_monero_location() -> String {
let args = args::Args::parse();
let user = std::env::var("USER").unwrap_or(utils::empty_string());
format!("/home/{}/{}", &user, &args.monero_location)
args.monero_location.to_string()
}
/// Get monero rpc host from the `--monero-rpc-host` cli arg
fn get_rpc_host() -> String {
let args = args::Args::parse();
let gui_host = std::env::var(crate::MONERO_WALLET_RPC_HOST).unwrap_or(utils::empty_string());
let rpc = if gui_host == utils::empty_string() {
String::from(args.monero_rpc_host)
let gui_host = std::env::var(crate::MONERO_WALLET_RPC_HOST).unwrap_or(String::new());
let rpc = if gui_host.is_empty() {
args.monero_rpc_host
} else {
gui_host
};
@ -348,8 +340,8 @@ fn get_rpc_host() -> String {
/// Get creds from the `--monero-rpc-daemon` cli arg
fn get_rpc_creds() -> RpcLogin {
let args = args::Args::parse();
let username = String::from(args.monero_rpc_username);
let credential = String::from(args.monero_rpc_cred);
let username = args.monero_rpc_username;
let credential = args.monero_rpc_cred;
RpcLogin {
username,
credential,
@ -358,9 +350,9 @@ fn get_rpc_creds() -> RpcLogin {
fn get_rpc_daemon() -> String {
let args = args::Args::parse();
let gui_host = std::env::var(crate::MONERO_DAEMON_HOST).unwrap_or(utils::empty_string());
if gui_host == utils::empty_string() {
String::from(args.monero_rpc_daemon)
let gui_host = std::env::var(crate::MONERO_DAEMON_HOST).unwrap_or(String::new());
if gui_host.is_empty() {
args.monero_rpc_daemon
} else {
gui_host
}
@ -396,7 +388,7 @@ pub async fn get_version() -> reqres::XmrRpcVersionResponse {
}
/// Helper function for checking xmr rpc online during app startup
pub async fn check_rpc_connection() -> () {
pub async fn check_rpc_connection() {
let res: reqres::XmrRpcVersionResponse = get_version().await;
if res.result.version == INVALID_VERSION {
error!("failed to connect to monero-wallet-rpc");
@ -531,10 +523,10 @@ fn update_wallet_lock(filename: &String, closing: bool) -> bool {
}
if !closing {
*IS_WALLET_BUSY.lock().unwrap() = true;
return true;
true
} else {
*IS_WALLET_BUSY.lock().unwrap() = false;
return true;
true
}
}
@ -576,7 +568,7 @@ pub async fn open_wallet(filename: &String, password: &String) -> bool {
if r.contains("-1") {
return false;
}
return true;
true
}
_ => false,
}
@ -615,10 +607,7 @@ pub async fn close_wallet(filename: &String, password: &String) -> bool {
// The result from wallet operation is empty
let res = response.text().await;
debug!("{} response: {:?}", RpcFields::Close.value(), res);
match res {
Ok(_) => true,
_ => false,
}
res.is_ok()
}
Err(_) => false,
}
@ -662,7 +651,7 @@ pub async fn change_wallet_password(new_password: &String) -> bool {
if r.contains("-1") {
return false;
}
return true;
true
}
_ => false,
}

View file

@ -1,5 +1,6 @@
//! NEVEKO modified ed25519 library extending curve25519-dalek
use crate::monero;
use curve25519_dalek::{
edwards::{
CompressedEdwardsY,
@ -16,11 +17,6 @@ use sha2::{
Sha512,
};
use crate::{
monero,
utils,
};
#[derive(Debug)]
/// Container for the Neveko Message Keys
pub struct NevekoMessageKeys {
@ -39,8 +35,8 @@ impl Default for NevekoMessageKeys {
NevekoMessageKeys {
nmpk: [0u8; 32],
nmsk: [0u8; 32],
hex_nmpk: utils::empty_string(),
hex_nmsk: utils::empty_string(),
hex_nmpk: String::new(),
hex_nmsk: String::new(),
}
}
}
@ -54,7 +50,7 @@ fn curve_l_as_big_int() -> BigInt {
}
fn big_int_to_string(b: &BigInt) -> String {
String::from(String::from_utf8(b.to_signed_bytes_le()).unwrap_or_default())
String::from_utf8(b.to_signed_bytes_le()).unwrap_or_default()
}
/// Hash string input to scalar
@ -96,7 +92,7 @@ fn hash_to_scalar(s: Vec<&str>) -> Scalar {
/// Neveko Message Public Key (NMPK).
pub async fn generate_neveko_message_keys() -> NevekoMessageKeys {
log::info!("generating neveko message keys");
let password = std::env::var(crate::MONERO_WALLET_PASSWORD).unwrap_or(utils::empty_string());
let password = std::env::var(crate::MONERO_WALLET_PASSWORD).unwrap_or(String::new());
let filename = String::from(crate::APP_NAME);
let m_wallet = monero::open_wallet(&filename, &password).await;
if !m_wallet {
@ -110,8 +106,8 @@ pub async fn generate_neveko_message_keys() -> NevekoMessageKeys {
let point_nmpk = EdwardsPoint::mul_base(&scalar_nmsk);
let nmsk = *scalar_nmsk.as_bytes();
let nmpk: [u8; 32] = *point_nmpk.compress().as_bytes();
let hex_nmpk = hex::encode(&nmpk);
let hex_nmsk = hex::encode(&nmsk);
let hex_nmpk = hex::encode(nmpk);
let hex_nmsk = hex::encode(nmsk);
NevekoMessageKeys {
nmpk,
nmsk,
@ -130,7 +126,7 @@ pub async fn generate_neveko_message_keys() -> NevekoMessageKeys {
///
/// Pass `None` to encipher parameter to perform deciphering.
pub async fn cipher(hex_nmpk: &String, message: String, encipher: Option<String>) -> String {
let unwrap_encipher: String = encipher.unwrap_or(utils::empty_string());
let unwrap_encipher: String = encipher.unwrap_or(String::new());
let keys: NevekoMessageKeys = generate_neveko_message_keys().await;
// shared secret = nmpk * nmsk
let scalar_nmsk = Scalar::from_bytes_mod_order(keys.nmsk);
@ -143,15 +139,15 @@ pub async fn cipher(hex_nmpk: &String, message: String, encipher: Option<String>
// x = m + h or x = m - h'
let h = hash_to_scalar(vec![&ss_hex[..]]);
let h_bi = BigInt::from_bytes_le(Sign::Plus, h.as_bytes());
if unwrap_encipher == String::from(ENCIPHER) {
let msg_bi = BigInt::from_bytes_le(Sign::Plus, &message.as_bytes());
if unwrap_encipher == *ENCIPHER {
let msg_bi = BigInt::from_bytes_le(Sign::Plus, message.as_bytes());
let x = msg_bi + h_bi;
return hex::encode(x.to_bytes_le().1);
hex::encode(x.to_bytes_le().1)
} else {
let msg_bi = BigInt::from_bytes_le(Sign::Plus, &hex::decode(&message).unwrap_or_default());
let x = msg_bi - h_bi;
return big_int_to_string(&x);
};
big_int_to_string(&x)
}
}
// Tests
@ -162,7 +158,7 @@ mod tests {
use super::*;
fn test_cipher(message: &String, encipher: Option<String>) -> String {
let unwrap_encipher: String = encipher.unwrap_or(utils::empty_string());
let unwrap_encipher: String = encipher.unwrap_or(String::new());
let test_nmpk: [u8; 32] = [
203, 2, 188, 13, 167, 96, 59, 189, 38, 238, 2, 71, 84, 155, 153, 73, 241, 137, 9, 30,
28, 134, 91, 137, 134, 73, 231, 45, 174, 98, 103, 158,

View file

@ -4,7 +4,11 @@ use std::error::Error;
use crate::{
contact,
db,
db::{
self,
DATABASE_LOCK,
},
error::NevekoError,
i2p,
models::*,
monero,
@ -14,6 +18,9 @@ use crate::{
reqres,
utils,
};
use kn0sys_lmdb_rs::MdbError::{
self,
};
use log::{
debug,
error,
@ -42,7 +49,7 @@ impl StatusType {
}
/// Create a intial order
pub async fn create(j_order: Json<reqres::OrderRequest>) -> Order {
pub async fn create(j_order: Json<reqres::OrderRequest>) -> Result<Order, NevekoError> {
info!("creating order");
let wallet_name = String::from(crate::APP_NAME);
let wallet_password =
@ -65,147 +72,180 @@ pub async fn create(j_order: Json<reqres::OrderRequest>) -> Order {
..Default::default()
};
debug!("insert order: {:?}", new_order);
let order_wallet_password = utils::empty_string();
let order_wallet_password = String::new();
let m_wallet = monero::create_wallet(&orid, &order_wallet_password).await;
if !m_wallet {
error!("error creating msig wallet for order {}", &orid);
monero::close_wallet(&orid, &wallet_password).await;
return Default::default();
return Err(NevekoError::Order);
}
monero::close_wallet(&orid, &order_wallet_password).await;
debug!("insert order: {:?}", &new_order);
let s = db::Interface::async_open().await;
let db = &DATABASE_LOCK;
// inject adjudicator separately, modifying the order model is mendokusai
let adjudicator_k = format!("{}-{}", crate::ADJUDICATOR_DB_KEY, &orid);
db::Interface::async_write(&s.env, &s.handle, &adjudicator_k, &j_order.adjudicator).await;
db::write_chunks(
&db.env,
&db.handle,
adjudicator_k.as_bytes(),
j_order.adjudicator.as_bytes(),
)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let k = &new_order.orid;
db::Interface::async_write(&s.env, &s.handle, k, &Order::to_db(&new_order)).await;
let order = bincode::serialize(&new_order).unwrap_or_default();
db::write_chunks(&db.env, &db.handle, k.as_bytes(), &order)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
// in order to retrieve all orders, write keys to with ol
let list_key = crate::ORDER_LIST_DB_KEY;
let r = db::Interface::async_read(&s.env, &s.handle, &String::from(list_key)).await;
if r == utils::empty_string() {
let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
debug!("creating order index");
}
let order_list = [r, String::from(&orid)].join(",");
let old: String = bincode::deserialize(&r[..]).unwrap_or_default();
let order_list = [old, String::from(&orid)].join(",");
let s_order_list = bincode::serialize(&order_list).unwrap_or_default();
debug!("writing order index {} for id: {}", order_list, list_key);
db::Interface::async_write(&s.env, &s.handle, &String::from(list_key), &order_list).await;
new_order
db::write_chunks(&db.env, &db.handle, list_key.as_bytes(), &s_order_list)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(new_order)
}
/// Backup order for customer
pub fn backup(order: &Order) {
pub fn backup(order: &Order) -> Result<(), NevekoError> {
info!("creating backup of order: {}", order.orid);
let s = db::Interface::open();
let db = &DATABASE_LOCK;
let k = &order.orid;
db::Interface::delete(&s.env, &s.handle, k);
db::Interface::write(&s.env, &s.handle, k, &Order::to_db(&order));
db::DatabaseEnvironment::delete(&db.env, &db.handle, k.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let db = &DATABASE_LOCK;
let order_to_db = bincode::serialize(&order).unwrap_or_default();
db::write_chunks(&db.env, &db.handle, k.as_bytes(), &order_to_db)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
// in order to retrieve all orders, write keys to with col
let list_key = crate::CUSTOMER_ORDER_LIST_DB_KEY;
let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key));
if r == utils::empty_string() {
let db = &DATABASE_LOCK;
let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
debug!("creating customer order index");
}
let mut order_list = [String::from(&r), String::from(&order.orid)].join(",");
let d_r: String = bincode::deserialize(&r[..]).unwrap_or_default();
let mut order_list = [String::from(&d_r), String::from(&order.orid)].join(",");
let s_order_list = bincode::serialize(&order_list).unwrap_or_default();
// don't duplicate order ids when backing up updates from vendor
if String::from(&r).contains(&String::from(&order.orid)) {
order_list = r;
if String::from(&d_r).contains(&String::from(&order.orid)) {
order_list = d_r;
}
debug!("writing order index {} for id: {}", order_list, list_key);
db::Interface::write(&s.env, &s.handle, &String::from(list_key), &order_list);
let db = &DATABASE_LOCK;
db::write_chunks(&db.env, &db.handle, list_key.as_bytes(), &s_order_list)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(())
}
/// Lookup order
pub fn find(oid: &String) -> Order {
pub fn find(oid: &String) -> Result<Order, NevekoError> {
info!("find order: {}", &oid);
let s = db::Interface::open();
let r = db::Interface::read(&s.env, &s.handle, &String::from(oid));
if r == utils::empty_string() {
let db = &DATABASE_LOCK;
let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &oid.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
error!("order not found");
return Default::default();
return Err(NevekoError::Database(MdbError::NotFound));
}
Order::from_db(String::from(oid), r)
let result: Order = bincode::deserialize(&r[..]).unwrap_or_default();
Ok(result)
}
/// Lookup all orders from admin server
pub fn find_all() -> Vec<Order> {
let i_s = db::Interface::open();
pub fn find_all() -> Result<Vec<Order>, NevekoError> {
let db = &DATABASE_LOCK;
let i_list_key = crate::ORDER_LIST_DB_KEY;
let i_r = db::Interface::read(&i_s.env, &i_s.handle, &String::from(i_list_key));
if i_r == utils::empty_string() {
let i_r = db::DatabaseEnvironment::read(&db.env, &db.handle, &i_list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if i_r.is_empty() {
error!("order index not found");
}
let i_v_oid = i_r.split(",");
let i_v: Vec<String> = i_v_oid.map(|s| String::from(s)).collect();
let de: String = bincode::deserialize(&i_r[..]).unwrap_or_default();
let i_v_oid = de.split(",");
let i_v: Vec<String> = i_v_oid.map(String::from).collect();
let mut orders: Vec<Order> = Vec::new();
for o in i_v {
let order: Order = find(&o);
if order.orid != utils::empty_string() {
let order: Order = find(&o)?;
if !order.orid.is_empty() {
orders.push(order);
}
}
orders
Ok(orders)
}
/// Lookup all orders that customer has saved from gui
pub fn find_all_backup() -> Vec<Order> {
let i_s = db::Interface::open();
pub fn find_all_backup() -> Result<Vec<Order>, NevekoError> {
let db = &DATABASE_LOCK;
let i_list_key = crate::CUSTOMER_ORDER_LIST_DB_KEY;
let i_r = db::Interface::read(&i_s.env, &i_s.handle, &String::from(i_list_key));
if i_r == utils::empty_string() {
let i_r = db::DatabaseEnvironment::read(&db.env, &db.handle, &i_list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if i_r.is_empty() {
error!("customer order index not found");
}
let i_v_oid = i_r.split(",");
let i_v: Vec<String> = i_v_oid.map(|s| String::from(s)).collect();
let de: String = bincode::deserialize(&i_r[..]).unwrap_or_default();
let i_v_oid = de.split(",");
let i_v: Vec<String> = i_v_oid.map(String::from).collect();
let mut orders: Vec<Order> = Vec::new();
for o in i_v {
let order: Order = find(&o);
let visible = order.orid != utils::empty_string()
let order: Order = find(&o)?;
let visible = !order.orid.is_empty()
&& order.status != order::StatusType::Delivered.value()
&& order.status != order::StatusType::Cancelled.value();
if visible {
orders.push(order);
}
}
orders
Ok(orders)
}
/// Lookup all orders for customer
pub async fn find_all_customer_orders(cid: String) -> Vec<Order> {
pub async fn find_all_customer_orders(cid: String) -> Result<Vec<Order>, NevekoError> {
info!("lookup orders for customer: {}", &cid);
let i_s = db::Interface::open();
let db = &DATABASE_LOCK;
let i_list_key = crate::ORDER_LIST_DB_KEY;
let i_r = db::Interface::read(&i_s.env, &i_s.handle, &String::from(i_list_key));
if i_r == utils::empty_string() {
let i_r = db::DatabaseEnvironment::read(&db.env, &db.handle, &i_list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if i_r.is_empty() {
error!("order index not found");
}
let i_v_oid = i_r.split(",");
let i_v: Vec<String> = i_v_oid.map(|s| String::from(s)).collect();
let de: String = bincode::deserialize(&i_r[..]).unwrap_or_default();
let i_v_oid = de.split(",");
let i_v: Vec<String> = i_v_oid.map(String::from).collect();
let mut orders: Vec<Order> = Vec::new();
for o in i_v {
let order: Order = find(&o);
if order.orid != utils::empty_string() && order.cid == cid {
let order: Order = find(&o)?;
if !order.orid.is_empty() && order.cid == cid {
orders.push(order);
}
}
orders
Ok(orders)
}
/// Lookup all orders for vendor
pub fn find_all_vendor_orders() -> Vec<Order> {
pub fn find_all_vendor_orders() -> Result<Vec<Order>, NevekoError> {
info!("lookup orders for vendor");
let i_s = db::Interface::open();
let db = &DATABASE_LOCK;
let i_list_key = crate::ORDER_LIST_DB_KEY;
let i_r = db::Interface::read(&i_s.env, &i_s.handle, &String::from(i_list_key));
if i_r == utils::empty_string() {
let i_r = db::DatabaseEnvironment::read(&db.env, &db.handle, &i_list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if i_r.is_empty() {
error!("order index not found");
}
let i_v_oid = i_r.split(",");
let i_v: Vec<String> = i_v_oid.map(|s| String::from(s)).collect();
let de: String = bincode::deserialize(&i_r[..]).unwrap_or_default();
let i_v_oid = de.split(",");
let i_v: Vec<String> = i_v_oid.map(String::from).collect();
let mut orders: Vec<Order> = Vec::new();
let vendor_b32: String = i2p::get_destination(None);
let vendor_b32: String = i2p::get_destination(i2p::ServerTunnelType::App)?;
for o in i_v {
let order: Order = find(&o);
if order.orid != utils::empty_string() && order.cid != vendor_b32 {
let order: Order = find(&o)?;
if !order.orid.is_empty() && order.cid != vendor_b32 {
// TODO(c2m): separate functionality for archived orders
if order.status != order::StatusType::Cancelled.value()
&& order.status != order::StatusType::Delivered.value()
@ -214,22 +254,25 @@ pub fn find_all_vendor_orders() -> Vec<Order> {
}
}
}
orders
Ok(orders)
}
/// Modify order from admin server
pub fn modify(o: Json<Order>) -> Order {
pub fn modify(o: Json<Order>) -> Result<Order, NevekoError> {
info!("modify order: {}", &o.orid);
let f_order: Order = find(&o.orid);
if f_order.orid == utils::empty_string() {
let f_order: Order = find(&o.orid)?;
if f_order.orid.is_empty() {
error!("order not found");
return Default::default();
return Err(NevekoError::Database(MdbError::NotFound));
}
let db = &DATABASE_LOCK;
let u_order = Order::update(String::from(&f_order.orid), &o);
let s = db::Interface::open();
db::Interface::delete(&s.env, &s.handle, &u_order.orid);
db::Interface::write(&s.env, &s.handle, &u_order.orid, &Order::to_db(&u_order));
return u_order;
let _ = db::DatabaseEnvironment::delete(&db.env, &db.handle, &u_order.orid.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let v = bincode::serialize(&u_order).unwrap_or_default();
let _ = db::write_chunks(&db.env, &db.handle, &u_order.orid.as_bytes(), &v)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(u_order)
}
/// Sign and submit multisig
@ -238,13 +281,13 @@ pub async fn sign_and_submit_multisig(
tx_data_hex: &String,
) -> reqres::XmrRpcSubmitMultisigResponse {
info!("signing and submitting multisig");
let wallet_password = utils::empty_string();
monero::open_wallet(&orid, &wallet_password).await;
let wallet_password = String::new();
monero::open_wallet(orid, &wallet_password).await;
let r_sign: reqres::XmrRpcSignMultisigResponse =
monero::sign_multisig(String::from(tx_data_hex)).await;
let r_submit: reqres::XmrRpcSubmitMultisigResponse =
monero::submit_multisig(r_sign.result.tx_data_hex).await;
monero::close_wallet(&orid, &wallet_password).await;
monero::close_wallet(orid, &wallet_password).await;
if r_submit.result.tx_hash_list.is_empty() {
error!("unable to submit payment for order: {}", orid);
}
@ -259,12 +302,12 @@ pub async fn sign_and_submit_multisig(
/// access
///
/// the details of said order.
pub async fn secure_retrieval(orid: &String, signature: &String) -> Order {
pub async fn secure_retrieval(orid: &String, signature: &String) -> Result<Order, NevekoError> {
info!("secure order retrieval for {}", orid);
// get customer address for NEVEKO NOT order wallet
let m_order: Order = find(&orid);
let m_order: Order = find(orid).map_err(|_| NevekoError::Order)?;
let mut xmr_address: String = String::new();
let a_customers: Vec<Contact> = contact::find_all();
let a_customers: Vec<Contact> = contact::find_all().map_err(|_| NevekoError::Contact)?;
for customer in a_customers {
if customer.i2p_address == m_order.cid {
xmr_address = customer.xmr_address;
@ -281,20 +324,20 @@ pub async fn secure_retrieval(orid: &String, signature: &String) -> Order {
let is_valid_signature = monero::verify(xmr_address, id, sig).await;
monero::close_wallet(&wallet_name, &wallet_password).await;
if !is_valid_signature {
return Default::default();
return Err(NevekoError::Order);
}
m_order
Ok(m_order)
}
/// In order for the order (...ha) to only be cancelled by the customer
///
/// they must sign the order id with their NEVEKO wallet instance.
pub async fn cancel_order(orid: &String, signature: &String) -> Order {
pub async fn cancel_order(orid: &String, signature: &String) -> Result<Order, NevekoError> {
info!("cancel order {}", orid);
// get customer address for NEVEKO NOT order wallet
let mut m_order: Order = find(&orid);
let mut m_order: Order = find(orid).map_err(|_| NevekoError::Order)?;
let mut xmr_address: String = String::new();
let a_customers: Vec<Contact> = contact::find_all();
let a_customers: Vec<Contact> = contact::find_all().map_err(|_| NevekoError::Contact)?;
for customer in a_customers {
if customer.i2p_address == m_order.cid {
xmr_address = customer.xmr_address;
@ -311,52 +354,56 @@ pub async fn cancel_order(orid: &String, signature: &String) -> Order {
let is_valid_signature = monero::verify(xmr_address, id, sig).await;
monero::close_wallet(&wallet_name, &wallet_password).await;
if !is_valid_signature {
return Default::default();
return Err(NevekoError::Order);
}
// update the order status and send to customer
m_order.status = order::StatusType::Cancelled.value();
order::modify(Json(m_order));
order::find(&orid)
order::modify(Json(m_order))?;
order::find(orid).map_err(|_| NevekoError::Order)
}
/// Check for import multisig info, validate block time and that the
///
/// order wallet has been funded properly. Update the order to multisig complete
pub async fn validate_order_for_ship(orid: &String) -> reqres::FinalizeOrderResponse {
pub async fn validate_order_for_ship(
orid: &String,
) -> Result<reqres::FinalizeOrderResponse, NevekoError> {
info!("validating order for shipment");
let m_order: Order = find(orid);
let contact: Contact = contact::find(&m_order.cid);
let m_order: Order = find(orid).map_err(|_| NevekoError::Order)?;
let contact: Contact = contact::find(&m_order.cid).map_err(|_| NevekoError::Contact)?;
let hex_nmpk: String = contact.nmpk;
let s = db::Interface::async_open().await;
let db = &DATABASE_LOCK;
let k = String::from(crate::DELIVERY_INFO_DB_KEY);
let delivery_info: String = db::Interface::async_read(&s.env, &s.handle, &k).await;
let mut j_order: Order = find(orid);
let m_product: Product = product::find(&m_order.pid);
let delivery_info = db::DatabaseEnvironment::read(&db.env, &db.handle, &k.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let mut j_order: Order = find(orid).map_err(|_| NevekoError::Order)?;
let m_product: Product = product::find(&m_order.pid).map_err(|_| NevekoError::Product)?;
let price = m_product.price;
let total = price * &m_order.quantity;
let wallet_password = utils::empty_string();
monero::open_wallet(&orid, &wallet_password).await;
let wallet_password = String::new();
monero::open_wallet(orid, &wallet_password).await;
// check balance and unlock_time
let r_balance = monero::get_balance().await;
monero::close_wallet(&orid, &wallet_password).await;
monero::close_wallet(orid, &wallet_password).await;
// update the order status to multisig complete
let ready_to_ship: bool = r_balance.result.balance >= total as u128
&& r_balance.result.blocks_to_unlock < monero::LockTimeLimit::Blocks.value();
if ready_to_ship {
j_order.status = StatusType::Shipped.value();
order::modify(Json(j_order));
order::modify(Json(j_order))?;
}
let d_info: String = bincode::deserialize(&delivery_info[..]).unwrap_or_default();
let e_delivery_info: String = neveko25519::cipher(
&hex_nmpk,
hex::encode(delivery_info),
hex::encode(d_info),
Some(String::from(neveko25519::ENCIPHER)),
)
.await;
reqres::FinalizeOrderResponse {
Ok(reqres::FinalizeOrderResponse {
orid: String::from(orid),
delivery_info: e_delivery_info,
vendor_update_success: false,
}
})
}
/// NASR (neveko auto-ship request)
@ -405,10 +452,10 @@ pub async fn trigger_nasr(
pub async fn upload_delivery_info(
orid: &String,
delivery_info: &String,
) -> reqres::FinalizeOrderResponse {
) -> Result<reqres::FinalizeOrderResponse, NevekoError> {
info!("uploading delivery info");
let lookup: Order = order::find(orid);
let contact: Contact = contact::find(&lookup.cid);
let lookup: Order = order::find(orid).map_err(|_| NevekoError::Order)?;
let contact: Contact = contact::find(&lookup.cid).map_err(|_| NevekoError::Contact)?;
let hex_nmpk: String = contact.nmpk;
let e_delivery_info: String = neveko25519::cipher(
&hex_nmpk,
@ -420,43 +467,48 @@ pub async fn upload_delivery_info(
error!("unable to encipher delivery info");
}
// get draft payment txset
let wallet_password = utils::empty_string();
monero::open_wallet(&orid, &wallet_password).await;
let wallet_password = String::new();
monero::open_wallet(orid, &wallet_password).await;
monero::refresh().await;
let sweep: reqres::XmrRpcSweepAllResponse =
monero::sweep_all(String::from(&lookup.subaddress)).await;
monero::close_wallet(&orid, &wallet_password).await;
monero::close_wallet(orid, &wallet_password).await;
if sweep.result.multisig_txset.is_empty() {
error!("unable to create draft txset");
return Default::default();
return Err(NevekoError::MoneroRpc);
}
// update the order
let mut m_order: Order = find(orid);
let mut m_order: Order = find(orid).map_err(|_| NevekoError::Order)?;
m_order.status = StatusType::Shipped.value();
m_order.ship_date = chrono::offset::Utc::now().timestamp();
m_order.vend_msig_txset = sweep.result.multisig_txset;
// delivery info will be stored enciphered and separate from the rest of the
// order
let s = db::Interface::async_open().await;
let db = &DATABASE_LOCK;
let k = String::from(crate::DELIVERY_INFO_DB_KEY);
db::Interface::async_write(&s.env, &s.handle, &k, &hex::encode(&delivery_info)).await;
modify(Json(m_order));
db::write_chunks(&db.env, &db.handle, k.as_bytes(), delivery_info.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
modify(Json(m_order))?;
// trigger nasr, this will cause the customer's neveko instance to request the
// txset
let i2p_address = i2p::get_destination(None);
let s = db::Interface::open();
let i2p_address = i2p::get_destination(i2p::ServerTunnelType::App)?;
// get jwp from db
let db = &DATABASE_LOCK;
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &lookup.cid);
let jwp = db::Interface::read(&s.env, &s.handle, &k);
let nasr_order = trigger_nasr(&lookup.cid, &i2p_address, &jwp, orid).await;
let jwp = db::DatabaseEnvironment::read(&db.env, &db.handle, &k.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let str_jwp: String = bincode::deserialize(&jwp[..]).unwrap_or_default();
let nasr_order = trigger_nasr(&lookup.cid, &i2p_address, &str_jwp, orid).await;
if nasr_order.is_err() {
return Default::default();
error!("failed to trigger nasr");
return Err(NevekoError::Nasr);
}
reqres::FinalizeOrderResponse {
Ok(reqres::FinalizeOrderResponse {
delivery_info: e_delivery_info,
orid: String::from(orid),
vendor_update_success: false,
}
})
}
/// Vendor will very txset submission and then update the order to `Delivered`
@ -464,16 +516,16 @@ pub async fn upload_delivery_info(
/// status type. Then customer will update the status on the neveko instanced
///
/// upon a `vendor_update_success: true` response
pub async fn finalize_order(orid: &String) -> reqres::FinalizeOrderResponse {
pub async fn finalize_order(orid: &String) -> Result<reqres::FinalizeOrderResponse, NevekoError> {
info!("finalizing order: {}", orid);
// verify recipient and unlock time
let mut m_order: Order = order::find(orid);
if m_order.vend_msig_txset == utils::empty_string() {
let mut m_order: Order = order::find(orid).map_err(|_| NevekoError::Order)?;
if m_order.vend_msig_txset.is_empty() {
error!("txset missing");
return Default::default();
return Err(NevekoError::MoneroRpc);
}
// get draft payment txset
let wallet_password = utils::empty_string();
let wallet_password = String::new();
monero::open_wallet(orid, &wallet_password).await;
monero::refresh().await;
let address: String = String::from(&m_order.subaddress);
@ -489,22 +541,22 @@ pub async fn finalize_order(orid: &String) -> reqres::FinalizeOrderResponse {
if !valid {
monero::close_wallet(orid, &wallet_password).await;
error!("invalid txset");
return Default::default();
return Err(NevekoError::MoneroRpc);
}
// verify order wallet has been swept clean
let balance = monero::get_balance().await;
if balance.result.unlocked_balance != 0 {
monero::close_wallet(orid, &wallet_password).await;
error!("order wallet not swept");
return Default::default();
return Err(NevekoError::MoneroRpc);
}
monero::close_wallet(orid, &wallet_password).await;
m_order.status = order::StatusType::Delivered.value();
order::modify(Json(m_order));
reqres::FinalizeOrderResponse {
order::modify(Json(m_order))?;
Ok(reqres::FinalizeOrderResponse {
vendor_update_success: true,
..Default::default()
}
})
}
/// Executes POST /order/finalize/{orid}
@ -551,41 +603,44 @@ pub async fn trigger_finalize_request(
contact: &String,
jwp: &String,
orid: &String,
) -> reqres::FinalizeOrderResponse {
) -> Result<reqres::FinalizeOrderResponse, NevekoError> {
info!("executing trigger_finalize_request");
let finalize = transmit_finalize_request(contact, jwp, orid).await;
// cache finalize order request to db
if finalize.is_err() {
log::error!("failed to trigger cancel request");
return Default::default();
return Err(NevekoError::Order);
}
let unwrap: reqres::FinalizeOrderResponse = finalize.unwrap();
let mut m_order: Order = order::find(&orid);
let mut m_order: Order = order::find(orid).map_err(|_| NevekoError::Order)?;
m_order.status = order::StatusType::Delivered.value();
backup(&m_order);
unwrap
backup(&m_order)?;
Ok(unwrap)
}
/// Decomposition trigger for `finalize_order()`
pub async fn d_trigger_finalize_request(
contact: &String,
orid: &String,
) -> reqres::FinalizeOrderResponse {
) -> Result<reqres::FinalizeOrderResponse, NevekoError> {
// ugh, sorry seems we need to get jwp for vendor from fts cache
// get jwp from db
let s = db::Interface::async_open().await;
let db = &DATABASE_LOCK;
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &contact);
let jwp = db::Interface::async_read(&s.env, &s.handle, &k).await;
let jwp = db::DatabaseEnvironment::read(&db.env, &db.handle, &k.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
info!("executing d_trigger_finalize_request");
// request finalize if the order status is shipped
let order: Order = order::find(&orid);
let order: Order = order::find(orid).map_err(|_| NevekoError::Order)?;
let str_jwp: String = bincode::deserialize(&jwp[..]).unwrap_or_default();
if order.status != order::StatusType::Shipped.value() {
let trigger = trigger_finalize_request(contact, &jwp, orid).await;
let trigger = trigger_finalize_request(contact, &str_jwp, orid).await?;
if trigger.vendor_update_success {
return trigger;
return Ok(trigger);
}
}
Default::default()
Err(NevekoError::Order)
}
/// Send order request to vendor and start multisig flow
@ -693,7 +748,11 @@ pub async fn transmit_sor_request(
/// A decomposition trigger for the shipping request so that the logic
///
/// can be executed from the gui.
pub async fn trigger_ship_request(contact: &String, jwp: &String, orid: &String) -> Order {
pub async fn trigger_ship_request(
contact: &String,
jwp: &String,
orid: &String,
) -> Result<Order, NevekoError> {
info!("executing trigger_ship_request");
let data = String::from(orid);
let wallet_password =
@ -705,17 +764,21 @@ pub async fn trigger_ship_request(contact: &String, jwp: &String, orid: &String)
// cache order request to db
if order.is_err() {
log::error!("failed to trigger shipping request");
return Default::default();
return Err(NevekoError::Order);
}
let unwrap_order: Order = order.unwrap();
backup(&unwrap_order);
unwrap_order
backup(&unwrap_order)?;
Ok(unwrap_order)
}
/// A post-decomposition trigger for the cancel request so that the logic
///
/// can be executed from the gui.
pub async fn trigger_cancel_request(contact: &String, jwp: &String, orid: &String) -> Order {
pub async fn trigger_cancel_request(
contact: &String,
jwp: &String,
orid: &String,
) -> Result<Order, NevekoError> {
info!("executing trigger_cancel_request");
let data = String::from(orid);
let wallet_password =
@ -727,35 +790,43 @@ pub async fn trigger_cancel_request(contact: &String, jwp: &String, orid: &Strin
// cache order request to db
if order.is_err() {
log::error!("failed to trigger cancel request");
return Default::default();
return Err(NevekoError::Order);
}
let unwrap_order: Order = order.unwrap();
backup(&unwrap_order);
unwrap_order
backup(&unwrap_order)?;
Ok(unwrap_order)
}
/// Decomposition trigger for the shipping request
pub async fn d_trigger_ship_request(contact: &String, orid: &String) -> Order {
pub async fn d_trigger_ship_request(contact: &String, orid: &String) -> Result<Order, NevekoError> {
// ugh, sorry seems we need to get jwp for vendor from fts cache
// get jwp from db
let s = db::Interface::async_open().await;
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &contact);
let jwp = db::Interface::async_read(&s.env, &s.handle, &k).await;
let db = &DATABASE_LOCK;
let jwp = db::DatabaseEnvironment::read(&db.env, &db.handle, &k.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
info!("executing d_trigger_ship_request");
// request shipment if the order status is MultisigComplete
let trigger = trigger_ship_request(contact, &jwp, orid).await;
let str_jwp: String = bincode::deserialize(&jwp[..]).unwrap_or_default();
let trigger = trigger_ship_request(contact, &str_jwp, orid).await?;
if trigger.status == order::StatusType::MulitsigComplete.value() {
let ship_res = transmit_ship_request(contact, &jwp, orid).await;
let ship_res = transmit_ship_request(contact, &str_jwp, orid).await;
if ship_res.is_err() {
error!("failure to decompose trigger_ship_request");
return Default::default();
return Err(NevekoError::Order);
}
let u_ship_res = ship_res.unwrap_or(Default::default());
let hex_delivery_info: String = hex::encode(u_ship_res.delivery_info);
let key = format!("{}-{}", crate::DELIVERY_INFO_DB_KEY, orid);
db::Interface::write(&s.env, &s.handle, &key, &hex_delivery_info);
db::write_chunks(
&db.env,
&db.handle,
key.as_bytes(),
hex_delivery_info.as_bytes(),
)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
}
trigger
Ok(trigger)
}
/// Executes POST /order/cancel/orid/signature
@ -800,29 +871,34 @@ pub async fn transmit_cancel_request(
}
/// Decomposition trigger for the cancel request
pub async fn d_trigger_cancel_request(contact: &String, orid: &String) -> Order {
pub async fn d_trigger_cancel_request(
contact: &String,
orid: &String,
) -> Result<Order, NevekoError> {
// ugh, sorry seems we need to get jwp for vendor from fts cache
// get jwp from db
let s = db::Interface::async_open().await;
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &contact);
let jwp = db::Interface::async_read(&s.env, &s.handle, &k).await;
let db = &DATABASE_LOCK;
let jwp = db::DatabaseEnvironment::read(&db.env, &db.handle, &k.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
info!("executing d_trigger_cancel_request");
// request cancel if the order status is not MultisigComplete
let order: Order = order::find(&orid);
let order: Order = order::find(orid).map_err(|_| NevekoError::Order)?;
if order.status != order::StatusType::MulitsigComplete.value() {
let trigger = trigger_cancel_request(contact, &jwp, orid).await;
let str_jwp: String = bincode::deserialize(&jwp[..]).unwrap_or_default();
let trigger = trigger_cancel_request(contact, &str_jwp, orid).await?;
if trigger.status == order::StatusType::Cancelled.value() {
return trigger;
return Ok(trigger);
}
}
Default::default()
Err(NevekoError::Order)
}
pub async fn init_adjudicator_wallet(orid: &String) {
let password = utils::empty_string();
let password = String::new();
let m_wallet = monero::create_wallet(orid, &password).await;
if !m_wallet {
log::error!("failed to create adjudicator wallet");
}
monero::close_wallet(&orid, &password).await;
monero::close_wallet(orid, &password).await;
}

View file

@ -1,10 +1,15 @@
//! Marketplace products upload, modification, etc module
use crate::{
db,
db::{
self,
DATABASE_LOCK,
},
error::NevekoError,
models::*,
utils,
};
use kn0sys_lmdb_rs::MdbError;
use log::{
debug,
error,
@ -14,87 +19,101 @@ use rocket::serde::json::Json;
use std::error::Error;
/// Create a new product
pub fn create(d: Json<Product>) -> Product {
pub fn create(d: Json<Product>) -> Result<Product, NevekoError> {
let pid: String = format!("{}{}", crate::PRODUCT_DB_KEY, utils::generate_rnd());
if !validate_product(&d) {
error!("invalid product");
return Default::default();
return Err(NevekoError::Database(MdbError::NotFound));
}
let new_product = Product {
pid: String::from(&pid),
description: String::from(&d.description),
image: d.image.iter().cloned().collect(),
image: d.image.to_vec(),
in_stock: d.in_stock,
name: String::from(&d.name),
price: d.price,
qty: d.qty,
};
debug!("insert product: {:?}", &new_product);
let s = db::Interface::open();
let db = &DATABASE_LOCK;
let k = &new_product.pid;
db::Interface::write(&s.env, &s.handle, k, &Product::to_db(&new_product));
let product = bincode::serialize(&new_product).unwrap_or_default();
db::write_chunks(&db.env, &db.handle, k.as_bytes(), &product)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
// in order to retrieve all products, write keys to with pl
let list_key = crate::PRODUCT_LIST_DB_KEY;
let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key));
if r == utils::empty_string() {
let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
debug!("creating product index");
}
let product_list = [r, String::from(&pid)].join(",");
let old: String = bincode::deserialize(&r[..]).unwrap_or_default();
let product_list = [old, String::from(&pid)].join(",");
let s_product_list = bincode::serialize(&product_list).unwrap_or_default();
debug!(
"writing product index {} for id: {}",
product_list, list_key
);
db::Interface::write(&s.env, &s.handle, &String::from(list_key), &product_list);
new_product
db::write_chunks(&db.env, &db.handle, list_key.as_bytes(), &s_product_list)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(new_product)
}
/// Single Product lookup
pub fn find(pid: &String) -> Product {
let s = db::Interface::open();
let r = db::Interface::read(&s.env, &s.handle, &String::from(pid));
if r == utils::empty_string() {
pub fn find(pid: &String) -> Result<Product, NevekoError> {
let db = &DATABASE_LOCK;
let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &pid.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
error!("product not found");
return Default::default();
return Err(NevekoError::Database(MdbError::NotFound));
}
Product::from_db(String::from(pid), r)
let result: Product = bincode::deserialize(&r[..]).unwrap_or_default();
Ok(result)
}
/// Product lookup for all
pub fn find_all() -> Vec<Product> {
let i_s = db::Interface::open();
pub fn find_all() -> Result<Vec<Product>, NevekoError> {
let db = &DATABASE_LOCK;
let i_list_key = crate::PRODUCT_LIST_DB_KEY;
let i_r = db::Interface::read(&i_s.env, &i_s.handle, &String::from(i_list_key));
if i_r == utils::empty_string() {
let i_r = db::DatabaseEnvironment::read(&db.env, &db.handle, &i_list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if i_r.is_empty() {
error!("product index not found");
}
let i_v_pid = i_r.split(",");
let i_v: Vec<String> = i_v_pid.map(|s| String::from(s)).collect();
let str_r: String = bincode::deserialize(&i_r[..]).unwrap_or_default();
let i_v_pid = str_r.split(",");
let i_v: Vec<String> = i_v_pid.map(String::from).collect();
let mut products: Vec<Product> = Vec::new();
for p in i_v {
let mut product: Product = find(&p);
if product.pid != utils::empty_string() {
let mut product: Product = find(&p)?;
if !product.pid.is_empty() {
// don't return images
product.image = Vec::new();
products.push(product);
}
}
products
Ok(products)
}
/// Modify product
pub fn modify(p: Json<Product>) -> Product {
pub fn modify(p: Json<Product>) -> Result<Product, NevekoError> {
// TODO(c2m): don't allow modification to products with un-delivered orders
info!("modify product: {}", &p.pid);
let f_prod: Product = find(&p.pid);
if f_prod.pid == utils::empty_string() {
let f_prod: Product = find(&p.pid)?;
if f_prod.pid.is_empty() {
error!("product not found");
return Default::default();
return Err(NevekoError::Database(MdbError::NotFound));
}
let u_prod = Product::update(f_prod, &p);
let s = db::Interface::open();
db::Interface::delete(&s.env, &s.handle, &u_prod.pid);
db::Interface::write(&s.env, &s.handle, &u_prod.pid, &Product::to_db(&u_prod));
return u_prod;
let db = &DATABASE_LOCK;
let _ = db::DatabaseEnvironment::delete(&db.env, &db.handle, u_prod.pid.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let product = bincode::serialize(&u_prod).unwrap_or_default();
let db = &DATABASE_LOCK;
db::write_chunks(&db.env, &db.handle, u_prod.pid.as_bytes(), &product)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(u_prod)
}
/// check product field lengths to prevent db spam

View file

@ -1,11 +1,16 @@
//! External authorization module via JWPs
use crate::{
db,
db::{
self,
DATABASE_LOCK,
},
error::NevekoError,
monero,
reqres,
utils,
};
use kn0sys_lmdb_rs::MdbError;
use log::{
error,
info,
@ -31,7 +36,7 @@ use serde::{
use sha2::Sha512;
use std::collections::BTreeMap;
#[derive(Debug, Deserialize, Serialize)]
#[derive(Debug, Default, Deserialize, Serialize)]
pub struct TxProof {
pub subaddress: String,
pub confirmations: u64,
@ -40,18 +45,6 @@ pub struct TxProof {
pub signature: String,
}
impl Default for TxProof {
fn default() -> Self {
TxProof {
subaddress: utils::empty_string(),
confirmations: 0,
hash: utils::empty_string(),
message: utils::empty_string(),
signature: utils::empty_string(),
}
}
}
/// Provide neccessary information for contacts to
///
/// provide proof of payment.
@ -89,12 +82,12 @@ pub async fn create_jwp(proof: &TxProof) -> String {
info!("creating jwp");
// validate the proof
let c_txp: TxProof = validate_proof(proof).await;
if c_txp.hash == utils::empty_string() {
if c_txp.hash.is_empty() {
error!("invalid transaction proof");
return utils::empty_string();
return String::new();
}
let jwp_secret_key = utils::get_jwp_secret_key();
let key: Hmac<Sha512> = Hmac::new_from_slice(&jwp_secret_key.as_bytes()).expect("hash");
let jwp_secret_key = utils::get_jwp_secret_key().unwrap_or_default();
let key: Hmac<Sha512> = Hmac::new_from_slice(jwp_secret_key.as_bytes()).expect("hash");
let header = Header {
algorithm: AlgorithmType::Hs512,
..Default::default()
@ -134,10 +127,16 @@ pub async fn prove_payment(contact: String, txp: &TxProof) -> Result<reqres::Jwp
match res {
Ok(r) => {
// cache the jwp for for fts
let s = db::Interface::open();
let db = &DATABASE_LOCK;
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &contact);
db::Interface::delete(&s.env, &s.handle, &k);
db::Interface::write(&s.env, &s.handle, &k, &r.jwp);
let _ = db::DatabaseEnvironment::delete(&db.env, &db.handle, k.as_bytes())?;
db::write_chunks(
&db.env,
&db.handle,
&k.as_bytes(),
&r.jwp.as_bytes().to_vec(),
)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(r)
}
_ => Ok(Default::default()),
@ -192,8 +191,8 @@ impl<'r> FromRequest<'r> for PaymentProof {
match proof {
Some(proof) => {
// check validity of address, payment amount and tx confirmations
let jwp_secret_key = utils::get_jwp_secret_key();
let key: Hmac<Sha512> = Hmac::new_from_slice(&jwp_secret_key.as_bytes()).expect("");
let jwp_secret_key = utils::get_jwp_secret_key().unwrap_or_default();
let key: Hmac<Sha512> = Hmac::new_from_slice(jwp_secret_key.as_bytes()).expect("");
let jwp: Result<
Token<jwt::Header, BTreeMap<std::string::String, std::string::String>, _>,
jwt::Error,
@ -301,5 +300,5 @@ async fn validate_subaddress(subaddress: &String) -> bool {
for s_address in all_address {
address_list.push(s_address.address);
}
return address_list.contains(&subaddress);
address_list.contains(subaddress)
}

File diff suppressed because it is too large Load diff

View file

@ -2,56 +2,45 @@
//! authenticated user
use crate::{
db,
db::{
self,
DATABASE_LOCK,
},
models::*,
utils,
};
use kn0sys_lmdb_rs::MdbError;
use log::{
debug,
error,
info,
};
use rocket::serde::json::Json;
/// Create a new user
pub fn create(address: &String) -> User {
pub fn create(address: &String) -> Result<User, MdbError> {
let f_uid: String = format!("{}{}", crate::USER_DB_KEY, utils::generate_rnd());
let new_user = User {
uid: String::from(&f_uid),
xmr_address: String::from(address),
name: utils::empty_string(),
name: String::new(),
};
debug!("insert user: {:?}", &new_user);
let s = db::Interface::open();
let db = &DATABASE_LOCK;
let k = &new_user.uid;
db::Interface::write(&s.env, &s.handle, k, &User::to_db(&new_user));
new_user
let v = bincode::serialize(&new_user).unwrap_or_default();
let _ = db::write_chunks(&db.env, &db.handle, k.as_bytes(), &v)?;
Ok(new_user)
}
/// User lookup
pub fn find(uid: &String) -> User {
let s = db::Interface::open();
let r = db::Interface::read(&s.env, &s.handle, &String::from(uid));
if r == utils::empty_string() {
pub fn find(uid: &String) -> Result<User, MdbError> {
let db = &DATABASE_LOCK;
let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &uid.as_bytes().to_vec())?;
if r.is_empty() {
error!("user not found");
return Default::default();
return Err(MdbError::NotFound);
}
User::from_db(String::from(uid), r)
}
/// Modify user - not implemented
fn _modify(u: Json<User>) -> User {
info!("modify user: {}", u.uid);
let f_cust: User = find(&u.uid);
if f_cust.uid == utils::empty_string() {
error!("user not found");
return Default::default();
}
let u_user = User::update(f_cust, String::from(&u.name));
let s = db::Interface::open();
db::Interface::delete(&s.env, &s.handle, &u_user.uid);
db::Interface::write(&s.env, &s.handle, &u_user.uid, &User::to_db(&u_user));
todo!()
let user: User = bincode::deserialize(&r[..]).unwrap_or_default();
Ok(user)
}
// Tests
@ -59,42 +48,35 @@ fn _modify(u: Json<User>) -> User {
#[cfg(test)]
mod tests {
use kn0sys_lmdb_rs::MdbError;
use super::*;
async fn cleanup(k: &String) {
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
let s = db::Interface::async_open().await;
db::Interface::async_delete(&s.env, &s.handle, k).await;
fn cleanup(k: &String) -> Result<(), MdbError> {
let db = &DATABASE_LOCK;
db::DatabaseEnvironment::delete(&db.env, &db.handle, k.as_bytes())?;
Ok(())
}
#[test]
fn create_test() {
fn create_test() -> Result<(), MdbError> {
// run and async cleanup so the test doesn't fail when deleting test data
use tokio::runtime::Runtime;
let rt = Runtime::new().expect("Unable to create Runtime for test");
let _enter = rt.enter();
let address: String = String::from(
"73a4nWuvkYoYoksGurDjKZQcZkmaxLaKbbeiKzHnMmqKivrCzq5Q2JtJG1UZNZFqLPbQ3MiXCk2Q5bdwdUNSr7X9QrPubkn"
);
let test_user = create(&address);
tokio::spawn(async move {
let s = db::Interface::async_open().await;
let r = db::Interface::async_read(&s.env, &s.handle, &test_user.uid).await;
let id = String::from(&test_user.uid);
let cleanup_id = String::from(&test_user.uid);
let expected_user = User::from_db(id, r);
assert_eq!(test_user.xmr_address, expected_user.xmr_address);
cleanup(&cleanup_id).await;
});
Runtime::shutdown_background(rt);
let test_user = create(&address)?;
let db = &DATABASE_LOCK;
let r =
db::DatabaseEnvironment::read(&db.env, &db.handle, &test_user.uid.as_bytes().to_vec())?;
let cleanup_id = String::from(&test_user.uid);
let expected_user: User = bincode::deserialize(&r[..]).unwrap_or_default();
assert_eq!(test_user.xmr_address, expected_user.xmr_address);
cleanup(&cleanup_id)?;
Ok(())
}
#[test]
fn find_test() {
// run and async cleanup so the test doesn't fail when deleting test data
use tokio::runtime::Runtime;
let rt = Runtime::new().expect("Unable to create Runtime for test");
let _enter = rt.enter();
fn find_test() -> Result<(), MdbError> {
let address: String = String::from(
"73a4nWuvkYoYoksGurDjKZQcZkmaxLaKbbeiKzHnMmqKivrCzq5Q2JtJG1UZNZFqLPbQ3MiXCk2Q5bdwdUNSr7X9QrPubkn"
);
@ -103,13 +85,12 @@ mod tests {
xmr_address: address,
..Default::default()
};
tokio::spawn(async move {
let s = db::Interface::async_open().await;
db::Interface::async_write(&s.env, &s.handle, k, &User::to_db(&expected_user)).await;
let actual_user: User = find(&String::from(k));
assert_eq!(expected_user.xmr_address, actual_user.xmr_address);
cleanup(&String::from(k)).await;
});
Runtime::shutdown_background(rt);
let db = &DATABASE_LOCK;
let v = bincode::serialize(&expected_user).unwrap_or_default();
db::write_chunks(&db.env, &db.handle, k.as_bytes(), &v)?;
let actual_user: User = find(&String::from(k))?;
assert_eq!(expected_user.xmr_address, actual_user.xmr_address);
cleanup(&String::from(k))?;
Ok(())
}
}

View file

@ -3,17 +3,24 @@
use crate::{
args,
contact,
db,
db::{
self,
DATABASE_LOCK,
},
dispute,
i2p,
error::NevekoError,
i2p::{
self,
ProxyStatus,
},
message,
models,
monero,
neveko25519,
reqres,
utils,
};
use clap::Parser;
use kn0sys_lmdb_rs::MdbError;
use log::{
debug,
error,
@ -49,35 +56,13 @@ pub struct ContactStatus {
impl Default for ContactStatus {
fn default() -> Self {
ContactStatus {
exp: utils::empty_string(),
h_exp: utils::empty_string(),
i2p: utils::empty_string(),
exp: String::new(),
h_exp: String::new(),
i2p: String::new(),
is_vendor: false,
jwp: utils::empty_string(),
jwp: String::new(),
nick: String::from("anon"),
txp: utils::empty_string(),
}
}
}
/// Enum for selecting hash validation
#[derive(PartialEq)]
enum ExternalSoftware {
I2PZero,
XMR,
}
/// Handles the state for the installation manager popup
pub struct Installations {
pub xmr: bool,
pub i2p_zero: bool,
}
impl Default for Installations {
fn default() -> Self {
Installations {
xmr: false,
i2p_zero: false,
txp: String::new(),
}
}
}
@ -88,9 +73,6 @@ pub struct Connections {
pub daemon_host: String,
pub i2p_proxy_host: String,
pub i2p_socks_host: String,
/// path to manually created tunnels json
pub i2p_tunnels_json: String,
pub i2p_zero_dir: String,
pub is_remote_node: bool,
pub is_i2p_advanced: bool,
pub mainnet: bool,
@ -104,18 +86,16 @@ impl Default for Connections {
fn default() -> Self {
Connections {
blockchain_dir: String::from("/home/user/.bitmonero"),
daemon_host: String::from("http://127.0.0.1:38081"),
i2p_proxy_host: String::from("http://127.0.0.1:4444"),
i2p_socks_host: String::from("http://127.0.0.1:9051"),
i2p_tunnels_json: String::from("/home/user/neveko/i2p-manual"),
i2p_zero_dir: String::from("/home/user/i2p-zero-linux.v1.21"),
daemon_host: String::from("http://127.0.0.1:18081"),
i2p_proxy_host: String::from("http://127.0.0.1:4456"),
i2p_socks_host: String::from("http://127.0.0.1:9056"),
is_remote_node: false,
is_i2p_advanced: false,
mainnet: false,
monero_location: String::from("/home/user/monero-x86_64-linux-gnu-v0.18.3.3"),
mainnet: true,
monero_location: String::from("/home/user/monero-x86_64-linux-gnu-v0.18.3.4"),
rpc_credential: String::from("pass"),
rpc_username: String::from("user"),
rpc_host: String::from("http://127.0.0.1:38083"),
rpc_host: String::from("http://127.0.0.1:18083"),
}
}
}
@ -176,14 +156,10 @@ pub fn start_core(conn: &Connections) {
&conn.rpc_username,
"--monero-rpc-cred",
&conn.rpc_credential,
"--i2p-zero-dir",
&conn.i2p_zero_dir,
"-r",
env,
remote_node,
i2p_advanced,
"--i2p-tunnels-json",
&conn.i2p_tunnels_json,
"--i2p-proxy-host",
&conn.i2p_proxy_host,
"--i2p-socks-proxy-host",
@ -191,16 +167,12 @@ pub fn start_core(conn: &Connections) {
];
if conn.is_i2p_advanced {
// set the i2p proxy host for advanced user re-use
std::env::set_var(crate::NEVEKO_I2P_PROXY_HOST, &conn.i2p_proxy_host.clone());
std::env::set_var(
crate::NEVEKO_I2P_TUNNELS_JSON,
&conn.i2p_tunnels_json.clone(),
);
std::env::set_var(crate::NEVEKO_I2P_PROXY_HOST, conn.i2p_proxy_host.clone());
std::env::set_var(crate::NEVEKO_I2P_ADVANCED_MODE, String::from("1"));
}
if conn.is_remote_node {
std::env::set_var(crate::MONERO_DAEMON_HOST, &conn.daemon_host.clone());
std::env::set_var(crate::MONERO_WALLET_RPC_HOST, &conn.rpc_host.clone());
std::env::set_var(crate::MONERO_DAEMON_HOST, conn.daemon_host.clone());
std::env::set_var(crate::MONERO_WALLET_RPC_HOST, conn.rpc_host.clone());
std::env::set_var(crate::GUI_REMOTE_NODE, crate::GUI_SET_REMOTE_NODE)
}
let output = std::process::Command::new("./neveko")
@ -230,11 +202,11 @@ pub fn generate_rnd() -> String {
/// Helper for separation of dev and prod concerns
pub fn get_release_env() -> ReleaseEnvironment {
let args = args::Args::parse();
let env = String::from(args.release_env);
let env = args.release_env;
if env == "prod" {
return ReleaseEnvironment::Production;
ReleaseEnvironment::Production
} else {
return ReleaseEnvironment::Development;
ReleaseEnvironment::Development
}
}
@ -247,8 +219,8 @@ pub fn get_app_port() -> u16 {
/// i2p http proxy
pub fn get_i2p_http_proxy() -> String {
let args = args::Args::parse();
let advanced_proxy = std::env::var(crate::NEVEKO_I2P_PROXY_HOST).unwrap_or(empty_string());
if advanced_proxy == empty_string() {
let advanced_proxy = std::env::var(crate::NEVEKO_I2P_PROXY_HOST).unwrap_or(String::new());
if advanced_proxy.is_empty() {
args.i2p_proxy_host
} else {
advanced_proxy
@ -314,7 +286,7 @@ pub fn message_to_json(m: &models::Message) -> Json<models::Message> {
let r_message: models::Message = models::Message {
body: String::from(&m.body),
mid: String::from(&m.mid),
uid: utils::empty_string(),
uid: String::new(),
created: m.created,
from: String::from(&m.from),
to: String::from(&m.to),
@ -327,7 +299,7 @@ pub fn product_to_json(m: &models::Product) -> Json<models::Product> {
let r_product: models::Product = models::Product {
pid: String::from(&m.pid),
description: String::from(&m.description),
image: m.image.iter().cloned().collect(),
image: m.image.to_vec(),
in_stock: m.in_stock,
name: String::from(&m.name),
price: m.price,
@ -357,11 +329,6 @@ pub fn dispute_to_json(d: &models::Dispute) -> Json<models::Dispute> {
Json(dispute)
}
/// Instead of putting `String::from("")`
pub fn empty_string() -> String {
String::from("")
}
// DoS prevention
pub const fn string_limit() -> usize {
512
@ -418,87 +385,147 @@ async fn gen_app_wallet(password: &String) {
}
/// Secret keys for signing internal/external auth tokens
fn gen_signing_keys() {
fn gen_signing_keys() -> Result<(), NevekoError> {
info!("generating signing keys");
let jwp = get_jwp_secret_key();
let jwt = get_jwt_secret_key();
let jwp = get_jwp_secret_key().unwrap_or_default();
let jwt = get_jwt_secret_key().unwrap_or_default();
// send to db
let s = db::Interface::open();
if jwp == utils::empty_string() {
let rnd_jwp = generate_rnd();
db::Interface::write(&s.env, &s.handle, crate::NEVEKO_JWP_SECRET_KEY, &rnd_jwp);
if jwp.is_empty() {
let mut data = [0u8; 32];
rand::thread_rng().fill_bytes(&mut data);
let db = &DATABASE_LOCK;
let h = hex::encode(data);
let v = bincode::serialize(&h).unwrap_or_default();
db::write_chunks(
&db.env,
&db.handle,
crate::NEVEKO_JWP_SECRET_KEY.as_bytes(),
&v,
)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
}
if jwt == utils::empty_string() {
let rnd_jwt = generate_rnd();
db::Interface::write(&s.env, &s.handle, crate::NEVEKO_JWT_SECRET_KEY, &rnd_jwt);
if jwt.is_empty() {
let mut data = [0u8; 32];
rand::thread_rng().fill_bytes(&mut data);
let db = &DATABASE_LOCK;
let h = hex::encode(data);
let v = bincode::serialize(&h).unwrap_or_default();
db::write_chunks(
&db.env,
&db.handle,
crate::NEVEKO_JWT_SECRET_KEY.as_bytes(),
&v,
)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
}
Ok(())
}
/// TODO(c2m): add a button to gui to call this
///
/// dont' forget to generate new keys as well
pub fn revoke_signing_keys() {
let s = db::Interface::open();
db::Interface::delete(&s.env, &s.handle, crate::NEVEKO_JWT_SECRET_KEY);
db::Interface::delete(&s.env, &s.handle, crate::NEVEKO_JWP_SECRET_KEY);
pub fn revoke_signing_keys() -> Result<(), NevekoError> {
let db = &DATABASE_LOCK;
db::DatabaseEnvironment::delete(&db.env, &db.handle, crate::NEVEKO_JWT_SECRET_KEY.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let db = &DATABASE_LOCK;
db::DatabaseEnvironment::delete(&db.env, &db.handle, crate::NEVEKO_JWP_SECRET_KEY.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(())
}
pub fn get_jwt_secret_key() -> String {
let s = db::Interface::open();
let r = db::Interface::read(&s.env, &s.handle, crate::NEVEKO_JWT_SECRET_KEY);
if r == utils::empty_string() {
pub fn get_jwt_secret_key() -> Result<String, NevekoError> {
let db = &DATABASE_LOCK;
let r = db::DatabaseEnvironment::read(
&db.env,
&db.handle,
&crate::NEVEKO_JWT_SECRET_KEY.as_bytes().to_vec(),
)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
error!("JWT key not found");
return Default::default();
return Err(NevekoError::Database(MdbError::Panic));
}
r
let result: String = bincode::deserialize(&r[..]).unwrap_or_default();
Ok(result)
}
pub fn get_jwp_secret_key() -> String {
let s = db::Interface::open();
let r = db::Interface::read(&s.env, &s.handle, crate::NEVEKO_JWP_SECRET_KEY);
if r == utils::empty_string() {
pub fn get_jwp_secret_key() -> Result<String, NevekoError> {
let db = &DATABASE_LOCK;
let r = db::DatabaseEnvironment::read(
&db.env,
&db.handle,
&crate::NEVEKO_JWP_SECRET_KEY.as_bytes().to_vec(),
)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
error!("JWP key not found");
return Default::default();
return Err(NevekoError::Database(MdbError::NotFound));
}
r
let result: String = bincode::deserialize(&r[..]).unwrap_or_default();
Ok(result)
}
/// Returns the hex encoded neveko message public key from LMDB
pub fn get_nmpk() -> String {
let s = db::Interface::open();
let r = db::Interface::read(&s.env, &s.handle, crate::NEVEKO_NMPK);
if r == utils::empty_string() {
pub fn get_nmpk() -> Result<String, NevekoError> {
let db = &DATABASE_LOCK;
let r =
db::DatabaseEnvironment::read(&db.env, &db.handle, &crate::NEVEKO_NMPK.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
error!("neveko message public key not found");
return Default::default();
return Err(NevekoError::Database(MdbError::Panic));
}
r
let result: String = bincode::deserialize(&r[..]).unwrap_or_default();
Ok(result)
}
async fn generate_nmpk() {
async fn generate_nmpk() -> Result<(), NevekoError> {
info!("generating neveko message public key");
let nmpk: String = get_nmpk();
let nmpk: String = get_nmpk().unwrap_or_default();
// send to db
let s = db::Interface::open();
if nmpk == utils::empty_string() {
let db = &DATABASE_LOCK;
if nmpk.is_empty() {
let nmk: neveko25519::NevekoMessageKeys = neveko25519::generate_neveko_message_keys().await;
db::Interface::write(&s.env, &s.handle, crate::NEVEKO_NMPK, &nmk.hex_nmpk);
let v = bincode::serialize(&nmk.hex_nmpk).unwrap_or_default();
db::write_chunks(&db.env, &db.handle, crate::NEVEKO_NMPK.as_bytes(), &v)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
}
Ok(())
}
fn reset_i2p_status() -> Result<(), NevekoError> {
let db = &DATABASE_LOCK;
let v = bincode::serialize(&ProxyStatus::Opening).unwrap_or_default();
db::write_chunks(&db.env, &db.handle, crate::I2P_STATUS.as_bytes(), &v)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(())
}
/// Put all app pre-checks here
pub async fn start_up() {
pub async fn start_up() -> Result<(), NevekoError> {
let db = &DATABASE_LOCK;
db::write_chunks(
&db.env,
&db.handle,
crate::NEVEKO_NMPK.as_bytes(),
&Vec::new(),
)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
info!("neveko is starting up");
let _ = reset_i2p_status()?;
warn!("monero multisig is experimental and usage of neveko may lead to loss of funds");
let args = args::Args::parse();
if args.clear_fts {
clear_fts();
clear_fts()?;
}
if args.clear_disputes {
clear_disputes();
clear_disputes()?;
}
gen_signing_keys();
gen_signing_keys()?;
if !is_using_remote_node() {
monero::start_daemon();
let _ = monero::start_daemon();
}
create_wallet_dir();
// wait for daemon for a bit
@ -507,9 +534,8 @@ pub async fn start_up() {
// wait for rpc server for a bit
tokio::time::sleep(std::time::Duration::new(5, 0)).await;
monero::check_rpc_connection().await;
let mut wallet_password =
std::env::var(crate::MONERO_WALLET_PASSWORD).unwrap_or(empty_string());
if wallet_password == empty_string() {
let mut wallet_password = std::env::var(crate::MONERO_WALLET_PASSWORD).unwrap_or_default();
if wallet_password.is_empty() {
print!(
"MONERO_WALLET_PASSWORD not set, enter neveko wallet password for monero-wallet-rpc: "
);
@ -517,20 +543,39 @@ pub async fn start_up() {
wallet_password = read_password().unwrap();
std::env::set_var(crate::MONERO_WALLET_PASSWORD, &wallet_password);
}
generate_nmpk().await;
let env: String = get_release_env().value();
if !args.i2p_advanced {
i2p::start().await;
let i2p = i2p::start();
if i2p.is_err() {
panic!("failed to start i2p");
}
}
gen_app_wallet(&wallet_password).await;
// start async background tasks here
{
tokio::spawn(async {
message::retry_fts().await;
dispute::settle_dispute().await;
tokio::spawn(async move {
let _ = message::retry_fts().await;
// wait for the i2p http proxy tunnel since remote nodes are forced over i2p
if is_using_remote_node() {
loop {
let is_i2p_online = i2p::check_connection().await;
let i2p_status = is_i2p_online.unwrap_or(ProxyStatus::Opening);
if i2p_status == ProxyStatus::Opening {
log::error!("i2p has not warmed up yet, check wrapper.log");
} else {
break;
}
std::thread::sleep(std::time::Duration::from_secs(60));
}
}
gen_app_wallet(&wallet_password).await;
generate_nmpk()
.await
.unwrap_or_else(|_| log::debug!("unable to generate neveko message keys"));
let _ = dispute::settle_dispute().await;
});
}
info!("{} - neveko is online", env);
Ok(())
}
/// TODO(?): get rid of this after implementing monero bindings
@ -566,120 +611,33 @@ pub fn kill_child_processes(cm: bool) {
/// We can restart fts from since it gets terminated when empty
pub fn restart_retry_fts() {
tokio::spawn(async move {
message::retry_fts().await;
let _ = message::retry_fts().await;
});
}
/// We can restart dispute auto-settle from since it gets terminated when empty
pub fn restart_dispute_auto_settle() {
tokio::spawn(async move {
dispute::settle_dispute().await;
let _ = dispute::settle_dispute().await;
});
}
/// Called on app startup if `--clear-fts` flag is passed.
fn clear_fts() {
fn clear_fts() -> Result<(), NevekoError> {
info!("clear fts");
let s = db::Interface::open();
db::Interface::delete(&s.env, &s.handle, crate::FTS_DB_KEY);
let db = &DATABASE_LOCK;
db::DatabaseEnvironment::delete(&db.env, &db.handle, crate::FTS_DB_KEY.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(())
}
/// Called on app startup if `--clear-dispute` flag is passed.
fn clear_disputes() {
fn clear_disputes() -> Result<(), NevekoError> {
info!("clear_disputes");
let s = db::Interface::open();
db::Interface::delete(&s.env, &s.handle, crate::DISPUTE_LIST_DB_KEY);
}
/// TODO(?): get rid of this after implementing monero bindings
///
/// Handle the request from user to additional software
///
/// from gui startup. Power users will most like install
///
/// software on their own. Note that software pull is over
///
/// clearnet. TODO(c2m): remove this after monero and i2pd
///
/// are completed.
pub async fn install_software(installations: Installations) -> bool {
let mut valid_i2p_zero_hash = true;
let mut valid_xmr_hash = true;
if installations.i2p_zero {
info!("installing i2p-zero");
let i2p_version = crate::I2P_ZERO_RELEASE_VERSION;
let i2p_zero_zip = format!("i2p-zero-linux.{}.zip", i2p_version);
let link = format!(
"https://github.com/creating2morrow/i2p-zero/releases/download/{}-neveko/{}",
i2p_version, i2p_zero_zip
);
let curl = std::process::Command::new("curl")
.args(["-LO#", &link])
.status();
match curl {
Ok(curl_output) => {
debug!("{:?}", curl_output);
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
let unzip_output = std::process::Command::new("unzip")
.arg(&i2p_zero_zip)
.spawn()
.expect("i2p unzip failed");
debug!("{:?}", unzip_output.stdout);
}
_ => error!("i2p-zero download failed"),
}
valid_i2p_zero_hash = validate_installation_hash(ExternalSoftware::I2PZero, &i2p_zero_zip);
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
}
if installations.xmr {
info!("installing monero");
let link = format!(
"https://downloads.getmonero.org/cli/{}",
crate::MONERO_RELEASE_VERSION
);
let curl = std::process::Command::new("curl")
.args(["-O#", &link])
.status();
match curl {
Ok(curl_output) => {
debug!("{:?}", curl_output);
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
let tar_output = std::process::Command::new("tar")
.args(["-xvf", crate::MONERO_RELEASE_VERSION])
.spawn()
.expect("monero tar extraction failed");
debug!("{:?}", tar_output.stdout);
}
_ => error!("monero download failed"),
}
valid_xmr_hash = validate_installation_hash(
ExternalSoftware::XMR,
&String::from(crate::MONERO_RELEASE_VERSION),
);
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
}
valid_i2p_zero_hash && valid_xmr_hash
}
/// Linux specific hash validation using the command `sha256sum`
fn validate_installation_hash(sw: ExternalSoftware, filename: &String) -> bool {
debug!("validating hash");
let expected_hash = if sw == ExternalSoftware::I2PZero {
String::from(crate::I2P_ZERO_RELEASH_HASH)
} else {
String::from(crate::MONERO_RELEASE_HASH)
};
let sha_output = std::process::Command::new("sha256sum")
.arg(filename)
.output()
.expect("hash validation failed");
let str_sha = String::from_utf8(sha_output.stdout).unwrap();
let split1 = str_sha.split(" ");
let mut v: Vec<String> = split1.map(|s| String::from(s)).collect();
let actual_hash = v.remove(0);
debug!("actual hash: {}", actual_hash);
debug!("expected hash: {}", expected_hash);
actual_hash == expected_hash
let db = &DATABASE_LOCK;
db::DatabaseEnvironment::delete(&db.env, &db.handle, crate::DISPUTE_LIST_DB_KEY.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(())
}
/// ### The highly ineffecient fee estimator.
@ -707,8 +665,8 @@ pub async fn estimate_fee() -> u128 {
let mut count: u64 = 1;
let mut v_fee: Vec<u128> = Vec::new();
let mut r_height: reqres::XmrDaemonGetHeightResponse = Default::default();
let remote_var = std::env::var(crate::GUI_REMOTE_NODE).unwrap_or(utils::empty_string());
let remote_set = remote_var == String::from(crate::GUI_SET_REMOTE_NODE);
let remote_var = std::env::var(crate::GUI_REMOTE_NODE).unwrap_or(String::new());
let remote_set = remote_var == *crate::GUI_SET_REMOTE_NODE;
if remote_set {
let p_height = monero::p_get_height().await;
r_height = p_height.unwrap_or(r_height);
@ -726,12 +684,12 @@ pub async fn estimate_fee() -> u128 {
}
// TODO(?): determine a more effecient fix than this for slow fee estimation
// over i2p
if v_fee.len() >= 1 && remote_set {
if !v_fee.is_empty() && remote_set {
break;
}
height = r_height.height - count;
let mut block: reqres::XmrDaemonGetBlockResponse = Default::default();
if remote_var == String::from(crate::GUI_SET_REMOTE_NODE) {
if remote_var == *crate::GUI_SET_REMOTE_NODE {
let p_block = monero::p_get_block(height).await;
block = p_block.unwrap_or(block);
} else {
@ -748,10 +706,10 @@ pub async fn estimate_fee() -> u128 {
}
for tx in transactions.txs_as_json {
let pre_fee_split = tx.split("txnFee\":");
let mut v1: Vec<String> = pre_fee_split.map(|s| String::from(s)).collect();
let mut v1: Vec<String> = pre_fee_split.map(String::from).collect();
let fee_split = v1.remove(1);
let post_fee_split = fee_split.split(",");
let mut v2: Vec<String> = post_fee_split.map(|s| String::from(s)).collect();
let mut v2: Vec<String> = post_fee_split.map(String::from).collect();
let fee: u128 = match v2.remove(0).trim().parse::<u128>() {
Ok(n) => n,
Err(_e) => 0,
@ -785,47 +743,58 @@ pub async fn can_transfer(invoice: u128) -> bool {
}
/// Gui toggle for vendor mode
pub fn toggle_vendor_enabled() -> bool {
pub fn toggle_vendor_enabled() -> Result<bool, MdbError> {
// TODO(c2m): Dont toggle vendors with orders status != Delivered
let s = db::Interface::open();
let r = db::Interface::read(&s.env, &s.handle, contact::NEVEKO_VENDOR_ENABLED);
if r != contact::NEVEKO_VENDOR_MODE_ON {
let db = &DATABASE_LOCK;
let r = db::DatabaseEnvironment::read(
&db.env,
&db.handle,
&contact::NEVEKO_VENDOR_ENABLED.as_bytes().to_vec(),
)?;
let mode: String = bincode::deserialize(&r[..]).unwrap_or_default();
if mode != contact::NEVEKO_VENDOR_MODE_ON {
info!("neveko vendor mode enabled");
db::Interface::write(
&s.env,
&s.handle,
contact::NEVEKO_VENDOR_ENABLED,
contact::NEVEKO_VENDOR_MODE_ON,
);
return true;
db::write_chunks(
&db.env,
&db.handle,
contact::NEVEKO_VENDOR_ENABLED.as_bytes(),
contact::NEVEKO_VENDOR_MODE_ON.as_bytes(),
)?;
Ok(true)
} else {
info!("neveko vendor mode disabled");
db::Interface::write(
&s.env,
&s.handle,
contact::NEVEKO_VENDOR_ENABLED,
contact::NEVEKO_VENDOR_MODE_OFF,
);
return false;
db::write_chunks(
&db.env,
&db.handle,
contact::NEVEKO_VENDOR_ENABLED.as_bytes(),
contact::NEVEKO_VENDOR_MODE_OFF.as_bytes(),
)?;
Ok(false)
}
}
pub fn search_gui_db(f: String, data: String) -> String {
let s = db::Interface::open();
pub fn search_gui_db(f: String, data: String) -> Result<String, MdbError> {
let db = &DATABASE_LOCK;
let k = format!("{}-{}", f, data);
db::Interface::read(&s.env, &s.handle, &k)
let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &k.as_bytes().to_vec())?;
let result: String = bincode::deserialize(&r[..]).unwrap_or_default();
Ok(result)
}
pub fn write_gui_db(f: String, key: String, data: String) {
let s = db::Interface::open();
pub fn write_gui_db(f: String, key: String, data: String) -> Result<(), MdbError> {
let db = &DATABASE_LOCK;
let k = format!("{}-{}", f, key);
db::Interface::write(&s.env, &s.handle, &k, &data);
let v = bincode::serialize(&data).unwrap_or_default();
db::write_chunks(&db.env, &db.handle, k.as_bytes(), &v)?;
Ok(())
}
pub fn clear_gui_db(f: String, key: String) {
let s = db::Interface::open();
pub fn clear_gui_db(f: String, key: String) -> Result<(), MdbError> {
let db = &DATABASE_LOCK;
let k = format!("{}-{}", f, key);
db::Interface::delete(&s.env, &s.handle, &k);
db::DatabaseEnvironment::delete(&db.env, &db.handle, k.as_bytes())?;
Ok(())
}
// Tests
@ -853,7 +822,7 @@ mod tests {
#[test]
fn release_env_test() {
let actual = get_release_env();
let expected = ReleaseEnvironment::Development;
let expected = ReleaseEnvironment::Production;
assert_eq!(expected, actual)
}

28
neveko-gui/.gitignore vendored
View file

@ -2,4 +2,30 @@
/core
notes.txt
.env
neveko
neveko
*.ping
/wallet
/.build
genkey-batch
monero-wallet-rpc.log
notes.txt
.vscode/settings.json
*.bz2
*.zip
monero-x86_64-linux-gnu-v*/
*.jar
opt/*
*.so
*.config
*.log
*.key
router.info
router.keys.dat
prngseed.rnd
hostsdb.blockfile
certificates/
netDb/*
peerProfiles/*
*.dat
*.txt
*.txt.gz

597
neveko-gui/Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -26,6 +26,7 @@ wgpu = ["eframe/wgpu", "bytemuck"]
[dependencies]
bincode = "1.3.3"
chrono = { version = "0.4", features = ["js-sys", "wasmbind"] }
eframe = { version = "0.21.0", path = "./crates/eframe", default-features = false }
egui = { version = "0.21.0", path = "./crates/egui", features = [

View file

@ -13,7 +13,7 @@ use egui_winit::winit;
use crate::{epi, Result};
use super::epi_integration::{self, EpiIntegration};
use super::epi_integration::{self};
// ----------------------------------------------------------------------------
@ -58,10 +58,6 @@ enum EventResult {
}
trait WinitApp {
fn is_focused(&self) -> bool;
fn integration(&self) -> Option<&EpiIntegration>;
fn window(&self) -> Option<&winit::window::Window>;
fn save_and_destroy(&mut self);
@ -736,14 +732,6 @@ mod glow_integration {
}
impl WinitApp for GlowWinitApp {
fn is_focused(&self) -> bool {
self.is_focused
}
fn integration(&self) -> Option<&EpiIntegration> {
self.running.as_ref().map(|r| &r.integration)
}
fn window(&self) -> Option<&winit::window::Window> {
self.running.as_ref().map(|r| r.gl_window.window())
}

View file

@ -16,7 +16,7 @@ pub struct WindowSettings {
impl WindowSettings {
pub fn from_display(window: &winit::window::Window) -> Self {
let inner_size_points = window.inner_size().to_logical::<f32>(window.scale_factor());
let position = if cfg!(macos) {
let position = if cfg!(unix) || cfg!(windows) {
// MacOS uses inner position when positioning windows.
window
.inner_position()

View file

@ -217,8 +217,6 @@ impl TextureAtlas {
if required_height > self.max_height() {
// This is a bad place to be - we need to start reusing space :/
#[cfg(feature = "tracing")]
tracing::wan!("epaint texture atlas overflowed!");
self.cursor = (0, self.image.height() / 3); // Restart a bit down - the top of the atlas has too many important things in it
self.overflowed = true; // this will signal the user that we need to recreate the texture atlas next frame.

View file

@ -18,8 +18,8 @@ struct Compose {
impl Default for Compose {
fn default() -> Self {
Compose {
message: utils::empty_string(),
to: utils::empty_string(),
message: String::new(),
to: String::new(),
}
}
}
@ -86,7 +86,7 @@ impl Default for AddressBookApp {
let (payment_tx, payment_rx) = std::sync::mpsc::channel();
let (send_message_tx, send_message_rx) = std::sync::mpsc::channel();
AddressBookApp {
add_nick: utils::empty_string(),
add_nick: String::new(),
approve_contact: false,
approve_payment: false,
added: false,
@ -94,7 +94,7 @@ impl Default for AddressBookApp {
can_transfer_rx,
can_transfer_tx,
compose: Default::default(),
contact: utils::empty_string(),
contact: String::new(),
contacts: Vec::new(),
contacts_init: false,
contact_add_tx,
@ -103,7 +103,7 @@ impl Default for AddressBookApp {
contact_info_rx,
contact_timeout_tx,
contact_timeout_rx,
find_contact: utils::empty_string(),
find_contact: String::new(),
invoice_tx,
invoice_rx,
is_adding: false,
@ -134,7 +134,7 @@ impl eframe::App for AddressBookApp {
//-----------------------------------------------------------------------------------
if let Ok(contact_info) = self.contact_info_rx.try_recv() {
self.s_contact = contact_info;
if self.s_contact.xmr_address != utils::empty_string() && !self.showing_status {
if !self.s_contact.xmr_address.is_empty() && !self.showing_status {
self.approve_contact = true;
}
if self.showing_status {
@ -144,7 +144,7 @@ impl eframe::App for AddressBookApp {
if let Ok(added_contact) = self.contact_add_rx.try_recv() {
self.s_added_contact = added_contact;
if self.s_added_contact.cid != utils::empty_string() {
if !self.s_added_contact.cid.is_empty() {
self.added = true;
self.is_loading = false;
}
@ -156,7 +156,7 @@ impl eframe::App for AddressBookApp {
self.is_loading = false;
self.is_adding = false;
self.approve_contact = false;
self.contact = utils::empty_string();
self.contact = String::new();
}
}
@ -186,7 +186,7 @@ impl eframe::App for AddressBookApp {
if self.is_message_sent {
self.is_loading = false;
self.is_composing = false;
self.compose.message = utils::empty_string();
self.compose.message = String::new();
}
}
@ -197,7 +197,7 @@ impl eframe::App for AddressBookApp {
// initial contact load
if !self.contacts_init {
self.contacts = contact::find_all();
self.contacts = contact::find_all().unwrap_or_default();
self.contacts_init = true;
}
@ -222,7 +222,7 @@ impl eframe::App for AddressBookApp {
});
if !self.is_loading {
self.compose.to = self.status.i2p.clone();
if self.status.jwp != utils::empty_string() {
if !self.status.jwp.is_empty() {
if ui.button("Send").clicked() {
self.is_loading = true;
send_message_req(
@ -242,8 +242,7 @@ impl eframe::App for AddressBookApp {
// Payment approval window
//-----------------------------------------------------------------------------------
let mut is_approving_payment =
self.approve_payment && self.s_invoice.address != utils::empty_string();
let mut is_approving_payment = self.approve_payment && !self.s_invoice.address.is_empty();
let address = self.s_invoice.address.clone();
let amount = self.s_invoice.pay_threshold;
let expire = self.s_invoice.conf_threshold;
@ -265,7 +264,7 @@ impl eframe::App for AddressBookApp {
ui.label(format!("pay to: {}", address));
ui.label(format!("amount: {} piconero(s)", amount));
ui.label(format!("expiration: {} blocks", expire));
let show_approve = self.s_invoice.address != utils::empty_string()
let show_approve = !self.s_invoice.address.is_empty()
&& self.can_transfer
&& !self.is_estimating_fee;
if !self.is_loading {
@ -316,7 +315,7 @@ impl eframe::App for AddressBookApp {
ui.add(egui::Spinner::new());
ui.label(spinner_text);
}
let status = if self.s_contact.xmr_address != utils::empty_string() {
let status = if !self.s_contact.xmr_address.is_empty() {
"online"
} else {
"offline"
@ -326,10 +325,10 @@ impl eframe::App for AddressBookApp {
ui.label(format!("tx proof: {}", self.status.txp));
ui.label(format!("jwp: {}", self.status.jwp));
ui.label(format!("expiration: {}", self.status.h_exp));
if self.status.jwp == utils::empty_string()
if self.status.jwp.is_empty()
&& !self.is_pinging
&& status == "online"
&& self.status.txp == utils::empty_string()
&& self.status.txp.is_empty()
{
if ui.button("Create JWP").clicked() {
self.s_invoice = Default::default();
@ -343,20 +342,19 @@ impl eframe::App for AddressBookApp {
self.is_approving_jwp = true;
}
}
let failed_to_prove = self.status.txp != utils::empty_string()
&& self.status.jwp == utils::empty_string();
if self.status.jwp != utils::empty_string() || failed_to_prove {
let failed_to_prove = !self.status.txp.is_empty() && self.status.jwp.is_empty();
if !self.status.jwp.is_empty() || failed_to_prove {
if ui.button("Clear stale JWP").clicked() {
utils::clear_gui_db(String::from("gui-txp"), self.status.i2p.clone());
utils::clear_gui_db(String::from("gui-jwp"), self.status.i2p.clone());
utils::clear_gui_db(String::from("gui-exp"), self.status.i2p.clone());
utils::clear_gui_db(String::from("gui-txp"), self.status.i2p.clone())
.unwrap();
utils::clear_gui_db(String::from("gui-jwp"), self.status.i2p.clone())
.unwrap();
utils::clear_gui_db(String::from("gui-exp"), self.status.i2p.clone())
.unwrap();
self.showing_status = false;
}
}
if self.status.txp != utils::empty_string()
&& self.status.jwp == utils::empty_string()
&& status == "online"
{
if !self.status.txp.is_empty() && self.status.jwp.is_empty() && status == "online" {
if ui.button("Prove Retry").clicked() {
send_payment_req(
self.payment_tx.clone(),
@ -376,7 +374,7 @@ impl eframe::App for AddressBookApp {
});
if ui.button("Change nick").clicked() {
change_nick_req(self.status.i2p.clone(), self.add_nick.clone());
self.add_nick = utils::empty_string();
self.add_nick = String::new();
}
if ui.button("Exit").clicked() {
self.showing_status = false;
@ -419,10 +417,10 @@ impl eframe::App for AddressBookApp {
ui.label(format!("i2p address: {}", self.s_added_contact.i2p_address));
if ui.button("Exit").clicked() {
self.added = false;
self.contact = utils::empty_string();
self.contact = String::new();
self.is_adding = false;
self.approve_contact = false;
self.contacts = contact::find_all();
self.contacts = contact::find_all().unwrap_or_default();
for c in &self.contacts {
ui.label(format!("{}", c.i2p_address));
}
@ -541,10 +539,11 @@ impl eframe::App for AddressBookApp {
String::from(crate::GUI_NICK_DB_KEY),
String::from(&c.i2p_address),
);
let nick = if nick_db == utils::empty_string() {
let u_nick = nick_db.unwrap_or_default();
let nick = if u_nick.is_empty() {
String::from("anon")
} else {
nick_db
u_nick
};
self.status.nick = nick;
self.status.i2p = String::from(&c.i2p_address);
@ -552,16 +551,19 @@ impl eframe::App for AddressBookApp {
self.status.txp = utils::search_gui_db(
String::from(crate::GUI_TX_PROOF_DB_KEY),
String::from(&c.i2p_address),
);
)
.unwrap_or_default();
// get the jwp
self.status.jwp = utils::search_gui_db(
String::from(crate::GUI_JWP_DB_KEY),
String::from(&c.i2p_address),
);
)
.unwrap_or_default();
let r_exp = utils::search_gui_db(
String::from(crate::GUI_EXP_DB_KEY),
String::from(&c.i2p_address),
);
)
.unwrap_or_default();
self.status.exp = r_exp;
let expire = match self.status.exp.parse::<i64>() {
Ok(n) => n,
@ -587,7 +589,7 @@ impl eframe::App for AddressBookApp {
Err(_e) => 0,
};
if now < expire
&& self.status.jwp != utils::empty_string()
&& !self.status.jwp.is_empty()
&& c.i2p_address == self.status.i2p
{
if ui.button("Compose").clicked() {
@ -622,8 +624,8 @@ fn send_create_contact_req(tx: Sender<models::Contact>, ctx: egui::Context, c: m
log::debug!("async send_create_contact_req");
tokio::spawn(async move {
let j_contact = utils::contact_to_json(&c);
let a_contact: models::Contact = contact::create(&j_contact).await;
let _ = tx.send(a_contact);
let a_contact = contact::create(&j_contact).await;
let _ = tx.send(a_contact.unwrap_or_default());
ctx.request_repaint();
});
}
@ -662,9 +664,9 @@ fn send_payment_req(
log::debug!("cleaning stale jwp values");
tokio::spawn(async move {
if !retry {
utils::clear_gui_db(String::from("gui-txp"), String::from(&contact));
utils::clear_gui_db(String::from("gui-jwp"), String::from(&contact));
utils::clear_gui_db(String::from("gui-exp"), String::from(&contact));
utils::clear_gui_db(String::from("gui-txp"), String::from(&contact)).unwrap();
utils::clear_gui_db(String::from("gui-jwp"), String::from(&contact)).unwrap();
utils::clear_gui_db(String::from("gui-exp"), String::from(&contact)).unwrap();
let ptxp_address = String::from(&d.address);
let ftxp_address = String::from(&d.address);
log::debug!("sending {} piconero(s) to: {}", &d.amount, &d.address);
@ -683,14 +685,13 @@ fn send_payment_req(
subaddress: ptxp_address,
confirmations: 0,
hash: ptxp_hash,
message: utils::empty_string(),
signature: utils::empty_string(),
message: String::new(),
signature: String::new(),
};
log::debug!("creating transaction proof for: {}", &ptxp.hash);
// if we made it this far we can now request a JWP from our friend
// wait a bit for the tx to propogate, i2p takes longer
let wait = if std::env::var(neveko_core::GUI_REMOTE_NODE)
.unwrap_or(utils::empty_string())
let wait = if std::env::var(neveko_core::GUI_REMOTE_NODE).unwrap_or(String::new())
== String::from(neveko_core::GUI_SET_REMOTE_NODE)
{
crate::I2P_PROPAGATION_TIME_IN_SECS_EST
@ -705,29 +706,33 @@ fn send_payment_req(
subaddress: ftxp_address,
confirmations: 0,
hash: ftxp_hash,
message: utils::empty_string(),
message: String::new(),
signature: get_txp.result.signature,
};
utils::write_gui_db(
String::from(crate::GUI_TX_PROOF_DB_KEY),
String::from(&contact),
String::from(&ftxp.signature),
);
)
.unwrap();
utils::write_gui_db(
String::from(crate::GUI_TX_HASH_DB_KEY),
String::from(&contact),
String::from(&ftxp.hash),
);
)
.unwrap();
utils::write_gui_db(
String::from(crate::GUI_TX_SIGNATURE_DB_KEY),
String::from(&contact),
String::from(&ftxp.signature),
);
)
.unwrap();
utils::write_gui_db(
String::from(crate::GUI_TX_SUBADDRESS_DB_KEY),
String::from(&contact),
String::from(&ftxp.subaddress),
);
)
.unwrap();
log::debug!(
"proving payment to {} for: {}",
String::from(&contact),
@ -739,7 +744,8 @@ fn send_payment_req(
String::from(crate::GUI_JWP_DB_KEY),
String::from(&contact),
String::from(&result.jwp),
);
)
.unwrap();
// this is just an estimate expiration but should suffice
let seconds: i64 = expire as i64 * 2 * 60;
let unix: i64 = chrono::offset::Utc::now().timestamp() + seconds;
@ -747,7 +753,8 @@ fn send_payment_req(
String::from(crate::GUI_EXP_DB_KEY),
String::from(&contact),
format!("{}", unix),
);
)
.unwrap();
ctx.request_repaint();
}
_ => log::error!("failed to obtain jwp"),
@ -758,14 +765,15 @@ fn send_payment_req(
let k_hash = String::from(crate::GUI_TX_HASH_DB_KEY);
let k_sig = String::from(crate::GUI_TX_SIGNATURE_DB_KEY);
let k_subaddress = String::from(crate::GUI_TX_SUBADDRESS_DB_KEY);
let hash = utils::search_gui_db(k_hash, String::from(&contact));
let signature = utils::search_gui_db(k_sig, String::from(&contact));
let subaddress = utils::search_gui_db(k_subaddress, String::from(&contact));
let hash = utils::search_gui_db(k_hash, String::from(&contact)).unwrap_or_default();
let signature = utils::search_gui_db(k_sig, String::from(&contact)).unwrap_or_default();
let subaddress =
utils::search_gui_db(k_subaddress, String::from(&contact)).unwrap_or_default();
let ftxp: proof::TxProof = proof::TxProof {
subaddress,
confirmations: 0,
hash: String::from(&hash),
message: utils::empty_string(),
message: String::new(),
signature,
};
log::debug!(
@ -779,7 +787,8 @@ fn send_payment_req(
String::from(crate::GUI_JWP_DB_KEY),
String::from(&contact),
String::from(&result.jwp),
);
)
.unwrap();
ctx.request_repaint();
}
_ => log::error!("failed to obtain jwp"),
@ -795,17 +804,18 @@ fn send_message_req(tx: Sender<bool>, ctx: egui::Context, body: String, to: Stri
let m: models::Message = models::Message {
body: body,
to,
mid: utils::empty_string(),
uid: utils::empty_string(),
mid: String::new(),
uid: String::new(),
created: 0,
from: i2p::get_destination(None),
from: i2p::get_destination(i2p::ServerTunnelType::App).unwrap_or_default(),
};
let j_message = utils::message_to_json(&m);
tokio::spawn(async move {
let m_type = message::MessageType::Normal;
let result = message::create(j_message, jwp, m_type).await;
if result.mid != utils::empty_string() {
log::info!("sent message: {}", result.mid);
let u_res = result.unwrap_or_default();
if !u_res.mid.is_empty() {
log::info!("sent message: {}", u_res.mid);
let _ = tx.send(true);
ctx.request_repaint();
}
@ -814,12 +824,13 @@ fn send_message_req(tx: Sender<bool>, ctx: egui::Context, body: String, to: Stri
fn change_nick_req(contact: String, nick: String) {
log::debug!("change nick");
utils::clear_gui_db(String::from(crate::GUI_NICK_DB_KEY), String::from(&contact));
utils::clear_gui_db(String::from(crate::GUI_NICK_DB_KEY), String::from(&contact)).unwrap();
utils::write_gui_db(
String::from(crate::GUI_NICK_DB_KEY),
String::from(&contact),
nick,
);
)
.unwrap();
}
fn send_can_transfer_req(tx: Sender<bool>, ctx: egui::Context, invoice: u128) {

View file

@ -18,16 +18,13 @@ use std::{
};
pub struct HomeApp {
b32_destination: String,
/// blocks fetched during last wallet refresh
blocks_fetched: u64,
wallet_height: u64,
connections: utils::Connections,
core_timeout_tx: Sender<bool>,
core_timeout_rx: Receiver<bool>,
has_install_failed: bool,
installations: utils::Installations,
installation_tx: Sender<bool>,
installation_rx: Receiver<bool>,
is_core_running: bool,
is_editing_connections: bool,
is_init: bool,
@ -69,10 +66,10 @@ pub struct HomeApp {
impl Default for HomeApp {
fn default() -> Self {
let b32_destination = i2p::get_destination(i2p::ServerTunnelType::App)
.unwrap_or(String::from("error: b32 address not found."));
let blocks_fetched = 0;
let connections = Default::default();
let has_install_failed = false;
let installations = Default::default();
let is_core_running = false;
let is_editing_connections = false;
let is_init = true;
@ -91,7 +88,6 @@ impl Default for HomeApp {
let (wallet_height_tx, wallet_height_rx) = std::sync::mpsc::channel();
let (can_refresh_tx, can_refresh_rx) = std::sync::mpsc::channel();
let (i2p_status_tx, i2p_status_rx) = std::sync::mpsc::channel();
let (installation_tx, installation_rx) = std::sync::mpsc::channel();
let contents = std::fs::read("./assets/qr.png").unwrap_or(Vec::new());
let s_xmr_rpc_ver = Default::default();
let s_xmr_address = Default::default();
@ -107,14 +103,11 @@ impl Default for HomeApp {
egui_extras::RetainedImage::from_image_bytes("./assets/i2p.png", &c_i2p_logo).unwrap();
let wallet_height = 0;
Self {
b32_destination,
blocks_fetched,
connections,
core_timeout_rx,
core_timeout_tx,
has_install_failed,
installations,
installation_rx,
installation_tx,
is_core_running,
is_editing_connections,
is_init,
@ -183,13 +176,6 @@ impl eframe::App for HomeApp {
if let Ok(info) = self.xmrd_get_info_rx.try_recv() {
self.s_xmrd_get_info = info;
}
if let Ok(install) = self.installation_rx.try_recv() {
self.is_installing = !install;
if !install && self.is_loading {
self.has_install_failed = true
}
self.is_loading = false;
}
if let Ok(timeout) = self.core_timeout_rx.try_recv() {
self.is_timeout = true;
if timeout {
@ -207,8 +193,9 @@ impl eframe::App for HomeApp {
.title_bar(false)
.vscroll(true)
.show(ctx, |ui| {
let mut i2p_address = i2p::get_destination(None);
if !self.is_qr_set && i2p_address != utils::empty_string() {
let mut i2p_address =
i2p::get_destination(i2p::ServerTunnelType::App).unwrap_or_default();
if !self.is_qr_set && !i2p_address.is_empty() {
let code = QrCode::new(&i2p_address).unwrap();
let image = code.render::<Luma<u8>>().build();
let file_path = format!(
@ -232,22 +219,6 @@ impl eframe::App for HomeApp {
}
});
// Installation Error window
//-----------------------------------------------------------------------------------
let mut has_install_failed = self.has_install_failed;
egui::Window::new("error")
.open(&mut has_install_failed)
.title_bar(false)
.vscroll(false)
.show(&ctx, |ui| {
ui.heading("Installation Failure");
if ui.button("Exit").clicked() {
self.has_install_failed = false;
self.is_installing = false;
self.is_loading = false;
}
});
// Connection Manager window
//-----------------------------------------------------------------------------------
let mut is_editing_connections = self.is_editing_connections;
@ -287,13 +258,6 @@ impl eframe::App for HomeApp {
ui.text_edit_singleline(&mut self.connections.monero_location)
.labelled_by(cm_xmr_dir_label.id);
});
if !self.connections.is_i2p_advanced {
ui.horizontal(|ui| {
let cm_i2p_dir_label = ui.label("i2p-zero path: \t");
ui.text_edit_singleline(&mut self.connections.i2p_zero_dir)
.labelled_by(cm_i2p_dir_label.id);
});
}
if self.connections.is_i2p_advanced {
ui.horizontal(|ui| {
let cm_i2p_proxy_label = ui.label("i2p proxy host: \t");
@ -305,11 +269,6 @@ impl eframe::App for HomeApp {
ui.text_edit_singleline(&mut self.connections.i2p_socks_host)
.labelled_by(cm_i2p_socks_label.id);
});
ui.horizontal(|ui| {
let cm_i2p_tunnels_label = ui.label("tunnels.json dir: ");
ui.text_edit_singleline(&mut self.connections.i2p_tunnels_json)
.labelled_by(cm_i2p_tunnels_label.id);
});
}
let mut is_remote_node = self.connections.is_remote_node;
if ui.checkbox(&mut is_remote_node, "remote node").changed() {
@ -343,42 +302,6 @@ impl eframe::App for HomeApp {
}
});
// Installation Manager window
//-----------------------------------------------------------------------------------
let mut is_installing = self.is_installing;
egui::Window::new("installation")
.open(&mut is_installing)
.title_bar(false)
.vscroll(true)
.show(&ctx, |ui| {
ui.heading("Installation Manager");
let mut wants_i2p_zero = self.installations.i2p_zero;
let mut wants_xmr = self.installations.xmr;
if ui.checkbox(&mut wants_i2p_zero, "i2p-zero").changed() {
self.installations.i2p_zero = !self.installations.i2p_zero;
}
if ui.checkbox(&mut wants_xmr, "xmr").changed() {
self.installations.xmr = !self.installations.xmr;
}
let install = &self.installations;
if install.i2p_zero || install.xmr {
if !self.is_loading {
if ui.button("Install").clicked() {
self.is_loading = true;
install_software_req(
self.installation_tx.clone(),
ctx.clone(),
&self.installations,
);
}
}
}
if ui.button("Exit").clicked() {
self.is_installing = false;
self.is_loading = false;
}
});
//----------------------------------------------------------------------------------------------
egui::CentralPanel::default().show(ctx, |ui| {
if !self.is_updated {
@ -420,9 +343,8 @@ impl eframe::App for HomeApp {
ui.horizontal(|ui| {
self.logo_i2p.show(ui);
ui.horizontal(|ui| {
let i2p_address = i2p::get_destination(None);
ui.label(
RichText::new(format!("- status: {}\n- address: {}", str_i2p_status, i2p_address))
RichText::new(format!("- status: {}\n- address: {}", str_i2p_status, self.b32_destination))
.size(16.0)
.color(color),
).on_hover_text(hover_txt);
@ -467,14 +389,6 @@ impl eframe::App for HomeApp {
}
}
}
if !self.is_core_running && !self.is_installing && !self.connections.is_remote_node && !self.connections.is_i2p_advanced
&& (self.s_xmr_rpc_ver.result.version == 0 || self.s_i2p_status == i2p::ProxyStatus::Opening) {
if !self.is_loading {
if ui.button("Install Software").clicked() {
self.is_installing = true;
}
}
}
});
}
}
@ -483,8 +397,7 @@ impl eframe::App for HomeApp {
//-------------------------------------------------------------------------------------------------
fn send_xmrd_get_info_req(tx: Sender<reqres::XmrDaemonGetInfoResponse>, ctx: egui::Context) {
tokio::spawn(async move {
let remote_var =
std::env::var(neveko_core::GUI_REMOTE_NODE).unwrap_or(utils::empty_string());
let remote_var = std::env::var(neveko_core::GUI_REMOTE_NODE).unwrap_or(String::new());
if remote_var == String::from(neveko_core::GUI_SET_REMOTE_NODE) {
let p_info = monero::p_get_info().await;
let info = p_info.unwrap_or(Default::default());
@ -533,7 +446,7 @@ fn send_wallet_req(
fn send_i2p_status_req(tx: Sender<i2p::ProxyStatus>, ctx: egui::Context) {
tokio::spawn(async move {
let status = i2p::check_connection().await;
let _ = tx.send(status);
let _ = tx.send(status.unwrap_or(i2p::ProxyStatus::Opening));
ctx.request_repaint();
});
}
@ -561,19 +474,3 @@ fn start_core_timeout(tx: Sender<bool>, ctx: egui::Context) {
ctx.request_repaint();
});
}
fn install_software_req(
tx: Sender<bool>,
ctx: egui::Context,
installations: &utils::Installations,
) {
let req_install: utils::Installations = utils::Installations {
i2p_zero: installations.i2p_zero,
xmr: installations.xmr,
};
tokio::spawn(async move {
let did_install = utils::install_software(req_install).await;
let _ = tx.send(did_install);
ctx.request_repaint();
});
}

View file

@ -1,4 +1,5 @@
use crate::CREDENTIAL_KEY;
use db::DATABASE_LOCK;
use neveko_core::*;
use sha2::{
Digest,
@ -15,7 +16,7 @@ struct LockScreen {
impl Default for LockScreen {
fn default() -> Self {
LockScreen {
credential: utils::empty_string(),
credential: String::new(),
}
}
}
@ -62,13 +63,19 @@ impl eframe::App for LockScreenApp {
self.lock_screen.credential.clone(),
);
// Get the credential hash from lmdb
let s = db::Interface::open();
let r = db::Interface::read(&s.env, &s.handle, CREDENTIAL_KEY);
let db = &DATABASE_LOCK;
let r = db::DatabaseEnvironment::read(
&db.env,
&db.handle,
&CREDENTIAL_KEY.as_bytes().to_vec(),
)
.unwrap();
// hash the text entered and compare
let mut hasher = Sha512::new();
hasher.update(self.lock_screen.credential.clone());
let result = hasher.finalize();
let hex = hex::encode(&result[..]);
let r: String = bincode::deserialize(&r[..]).unwrap_or_default();
if hex == r {
self.is_locked = false;
}

View file

@ -23,7 +23,7 @@ impl Default for MailBoxApp {
let (refresh_on_delete_tx, refresh_on_delete_rx) = std::sync::mpsc::channel();
let (deciphered_tx, deciphered_rx) = std::sync::mpsc::channel();
MailBoxApp {
deciphered: utils::empty_string(),
deciphered: String::new(),
is_showing_decipher: false,
messages: Vec::new(),
message_init: false,
@ -51,7 +51,7 @@ impl eframe::App for MailBoxApp {
// initial message load
if !self.message_init {
self.messages = message::find_all();
self.messages = message::find_all().unwrap_or_default();
self.message_init = true;
}
@ -67,14 +67,14 @@ impl eframe::App for MailBoxApp {
ui.label(format!("{}", self.deciphered));
ui.label("\n");
if ui.button("Exit").clicked() {
self.deciphered = utils::empty_string();
self.deciphered = String::new();
self.is_showing_decipher = false;
}
});
egui::CentralPanel::default().show(ctx, |ui| {
if ui.button("Refresh").clicked() {
self.messages = message::find_all();
self.messages = message::find_all().unwrap_or_default();
}
ui.label("\n");
use egui_extras::{
@ -144,7 +144,7 @@ impl eframe::App for MailBoxApp {
}
}
if ui.button("Delete").clicked() {
message::delete(&m.mid);
message::delete(&m.mid).unwrap();
refresh_on_delete_req(
self.refresh_on_delete_tx.clone(),
ctx.clone(),
@ -173,7 +173,7 @@ fn decipher_req(m: &Message, tx: Sender<String>, ctx: egui::Context) {
let body: String = String::from(&m.body);
tokio::spawn(async move {
log::info!("async decipher_req");
let contact = contact::find_by_i2p_address(&from);
let contact = contact::find_by_i2p_address(&from).unwrap_or_default();
let deciphered = neveko25519::cipher(&contact.nmpk, body, None).await;
let _ = tx.send(deciphered);
ctx.request_repaint();

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,4 @@
use db::DATABASE_LOCK;
use neveko_core::*;
use sha2::{
Digest,
@ -22,7 +23,7 @@ impl Default for SettingsApp {
fn default() -> Self {
let (change_wallet_password_tx, change_wallet_password_rx) = std::sync::mpsc::channel();
SettingsApp {
credential: utils::empty_string(),
credential: String::new(),
change_wallet_password_rx,
change_wallet_password_tx,
is_loading: false,
@ -63,20 +64,27 @@ impl eframe::App for SettingsApp {
}
if ui.button("Change").clicked() {
self.is_loading = true;
let s = db::Interface::open();
let db = &DATABASE_LOCK;
let k = CREDENTIAL_KEY;
db::Interface::delete(&s.env, &s.handle, &k);
let _ = db::DatabaseEnvironment::delete(&db.env, &db.handle, k.as_bytes())
.unwrap_or_else(|_| log::error!("failed to delete credential"));
let mut hasher = Sha512::new();
hasher.update(self.credential.clone());
let result = hasher.finalize();
db::Interface::write(&s.env, &s.handle, &k, &hex::encode(&result[..]));
db::write_chunks(
&db.env,
&db.handle,
k.as_bytes(),
hex::encode(&result[..]).as_bytes(),
)
.unwrap_or_else(|_| log::error!("failed to write credential"));
// update wallet rpc
change_wallet_password(
self.change_wallet_password_tx.clone(),
&self.credential,
ctx.clone(),
);
self.credential = utils::empty_string();
self.credential = String::new();
}
});
});

View file

@ -34,12 +34,12 @@ impl Default for WalletApp {
is_showing_qr: false,
is_showing_sweep_result: false,
qr: egui_extras::RetainedImage::from_image_bytes("qr.png", &contents).unwrap(),
sweep_address: utils::empty_string(),
sweep_address: String::new(),
xmr_address_rx,
xmr_address_tx,
xmr_sweep_all_rx,
xmr_sweep_all_tx,
s_xmr_address: utils::empty_string(),
s_xmr_address: String::new(),
x_xmr_sweep_res: Default::default(),
}
}
@ -85,7 +85,7 @@ impl eframe::App for WalletApp {
.title_bar(false)
.vscroll(true)
.show(ctx, |ui| {
if !self.is_qr_set && self.s_xmr_address != utils::empty_string() {
if !self.is_qr_set && !self.s_xmr_address.is_empty() {
let code = QrCode::new(&self.s_xmr_address.clone()).unwrap();
let image = code.render::<Luma<u8>>().build();
let file_path = format!(
@ -135,7 +135,7 @@ impl eframe::App for WalletApp {
ctx.clone(),
self.sweep_address.clone(),
);
self.sweep_address = utils::empty_string();
self.sweep_address = String::new();
self.is_showing_sweep_result = true;
self.is_loading = true;
}

View file

@ -40,7 +40,7 @@ pub const I2P_PROPAGATION_TIME_IN_SECS_EST: u64 = PROPAGATION_TIME_IN_SECS_EST *
/// time to wait before giving up on adding a contact
pub const ADD_CONTACT_TIMEOUT_SECS: u64 = 0x5A;
/// time to wait before giving up on neveko core
pub const START_CORE_TIMEOUT_SECS: u64 = 0x79;
pub const START_CORE_TIMEOUT_SECS: u64 = 0x4B0;
/// bytes in a a GB for calculating space on home page
pub const BYTES_IN_GB: u64 = 1000000000;
/// Useful flag to keep services running in background

View file

@ -1,4 +1,5 @@
use crate::CREDENTIAL_KEY;
use db::DATABASE_LOCK;
use neveko_core::*;
use sha2::{
Digest,
@ -14,7 +15,7 @@ pub struct LoginApp {
impl Default for LoginApp {
fn default() -> Self {
let credential = utils::empty_string();
let credential = String::new();
let is_cred_generated = false;
let is_not_showing_password = true;
LoginApp {
@ -54,9 +55,11 @@ impl eframe::App for LoginApp {
let mut hasher = Sha512::new();
hasher.update(self.credential.clone());
let result = hasher.finalize();
let s = db::Interface::open();
db::Interface::write(&s.env, &s.handle, k, &hex::encode(&result[..]));
self.credential = utils::empty_string();
let db = &DATABASE_LOCK;
let v = bincode::serialize(&hex::encode(&result[..])).unwrap_or_default();
db::write_chunks(&db.env, &db.handle, k.as_bytes(), &v)
.unwrap_or_else(|_| log::error!("failed to set credential"));
self.credential = String::new();
}
});
}

View file

@ -1,3 +1,4 @@
use db::DATABASE_LOCK;
#[cfg(feature = "glow")]
use eframe::glow;
use neveko_core::*;
@ -236,9 +237,14 @@ impl WrapApp {
ctx.set_pixels_per_point(1.5);
// initial cred check, is there a better way to do this?
if !self.state.is_cred_set {
let s = db::Interface::open();
let r = db::Interface::read(&s.env, &s.handle, crate::CREDENTIAL_KEY);
if r != utils::empty_string() {
let db = &DATABASE_LOCK;
let r = db::DatabaseEnvironment::read(
&db.env,
&db.handle,
&crate::CREDENTIAL_KEY.as_bytes().to_vec(),
)
.unwrap_or_default();
if !r.is_empty() {
self.state.is_cred_set = true;
self.state.is_checking_cred = false;
}
@ -308,9 +314,14 @@ impl WrapApp {
loop {
log::debug!("check for cred");
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
let s = db::Interface::open();
let r = db::Interface::read(&s.env, &s.handle, crate::CREDENTIAL_KEY);
if r == utils::empty_string() {
let db = &DATABASE_LOCK;
let r = db::DatabaseEnvironment::read(
&db.env,
&db.handle,
&crate::CREDENTIAL_KEY.as_bytes().to_vec(),
)
.unwrap_or_default();
if r.is_empty() {
log::debug!("credential not found");
let _ = tx.send(false);
ctx.request_repaint();

760
neveko-market/Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -19,15 +19,15 @@ pub async fn create_product(
req_product: Json<models::Product>,
_token: auth::BearerToken,
) -> Custom<Json<models::Product>> {
let m_product: models::Product = product::create(req_product);
Custom(Status::Created, Json(m_product))
let m_product = product::create(req_product);
Custom(Status::Created, Json(m_product.unwrap_or_default()))
}
/// Get a product by passing id
#[get("/<pid>")]
pub async fn get_product(pid: String, _token: auth::BearerToken) -> Custom<Json<models::Product>> {
let m_product: models::Product = product::find(&pid);
Custom(Status::Ok, Json(m_product))
let m_product = product::find(&pid);
Custom(Status::Ok, Json(m_product.unwrap_or_default()))
}
/// Update product information
@ -36,29 +36,29 @@ pub async fn update_product(
product: Json<models::Product>,
_token: auth::BearerToken,
) -> Custom<Json<models::Product>> {
let m_product: models::Product = product::modify(product);
Custom(Status::Ok, Json(m_product))
let m_product = product::modify(product);
Custom(Status::Ok, Json(m_product.unwrap_or_default()))
}
/// Return all products
#[get("/")]
pub async fn get_products(_token: auth::BearerToken) -> Custom<Json<Vec<models::Product>>> {
let m_products: Vec<models::Product> = product::find_all();
Custom(Status::Ok, Json(m_products))
let m_products = product::find_all();
Custom(Status::Ok, Json(m_products.unwrap_or_default()))
}
/// Get a order by passing id
#[get("/<orid>")]
pub async fn get_order(orid: String, _token: auth::BearerToken) -> Custom<Json<models::Order>> {
let m_order: models::Order = order::find(&orid);
Custom(Status::Ok, Json(m_order))
let m_order = order::find(&orid);
Custom(Status::Ok, Json(m_order.unwrap_or_default()))
}
/// Get all orders
#[get("/")]
pub async fn get_orders(_token: auth::BearerToken) -> Custom<Json<Vec<models::Order>>> {
let m_orders: Vec<models::Order> = order::find_all();
Custom(Status::Ok, Json(m_orders))
let m_orders = order::find_all();
Custom(Status::Ok, Json(m_orders.unwrap_or_default()))
}
/// Update order information
@ -67,8 +67,8 @@ pub async fn update_order(
order: Json<models::Order>,
_token: auth::BearerToken,
) -> Custom<Json<models::Order>> {
let m_order: models::Order = order::modify(order);
Custom(Status::Ok, Json(m_order))
let m_order = order::modify(order);
Custom(Status::Ok, Json(m_order.unwrap_or_default()))
}
/// Create a dispute
@ -77,15 +77,15 @@ pub async fn create_dispute(
dispute: Json<models::Dispute>,
_token: auth::BearerToken,
) -> Custom<Json<models::Dispute>> {
let m_dispute: models::Dispute = dispute::create(dispute);
Custom(Status::Ok, Json(m_dispute))
let m_dispute = dispute::create(dispute);
Custom(Status::Ok, Json(m_dispute.unwrap_or_default()))
}
/// Fetch a dispute
#[get("/<did>")]
pub async fn get_dispute(_token: auth::BearerToken, did: String) -> Custom<Json<models::Dispute>> {
let m_dispute: models::Dispute = dispute::find(&did);
Custom(Status::Ok, Json(m_dispute))
let m_dispute = dispute::find(&did);
Custom(Status::Ok, Json(m_dispute.unwrap_or_default()))
}
/// Sign and submit multisig
@ -113,12 +113,12 @@ pub async fn upload_delivery_info(
r_data: Json<reqres::FinalizeOrderResponse>,
_token: auth::BearerToken,
) -> Custom<Json<reqres::FinalizeOrderResponse>> {
let upload: reqres::FinalizeOrderResponse =
order::upload_delivery_info(&orid, &r_data.delivery_info).await;
if upload.delivery_info.is_empty() {
let upload = order::upload_delivery_info(&orid, &r_data.delivery_info).await;
let u_upload = upload.unwrap_or_default();
if u_upload.delivery_info.is_empty() {
return Custom(Status::BadRequest, Json(Default::default()));
}
Custom(Status::Ok, Json(upload))
Custom(Status::Ok, Json(u_upload))
}
/// toggle vendor mode
@ -126,7 +126,7 @@ pub async fn upload_delivery_info(
pub async fn toggle_vendor_mode(
_token: auth::BearerToken,
) -> Custom<Json<reqres::VendorModeResponse>> {
let mode = utils::toggle_vendor_enabled();
let mode = utils::toggle_vendor_enabled().unwrap_or_default();
Custom(Status::Ok, Json(reqres::VendorModeResponse { mode }))
}
// END JSON APIs

View file

@ -17,7 +17,7 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
@ -127,10 +127,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "383d29d513d8764dcdc42ea295d979eb99c3c9f00607b3692cf68a431f7dca72"
[[package]]
name = "bitflags"
version = "0.7.0"
name = "bincode"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
dependencies = [
"serde",
]
[[package]]
name = "bitflags"
@ -140,9 +143,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.0.2"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "487f1e0fcbe47deb8b0574e646def1c903389d95241dd1bbcc6ce4a715dfc0c1"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "block-buffer"
@ -180,6 +183,12 @@ version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
[[package]]
name = "cesu8"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
[[package]]
name = "cfg-if"
version = "1.0.0"
@ -286,7 +295,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
dependencies = [
"core-foundation-sys",
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
@ -301,9 +310,34 @@ version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "280a9f2d8b3a38871a3c8a46fb80db65e5e5ed97da80c4d08bf27fb63e35e181"
dependencies = [
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
[[package]]
name = "crypto-common"
version = "0.1.6"
@ -316,15 +350,14 @@ dependencies = [
[[package]]
name = "curve25519-dalek"
version = "4.1.2"
version = "4.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348"
checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be"
dependencies = [
"cfg-if",
"cpufeatures",
"curve25519-dalek-derive",
"fiat-crypto",
"platforms",
"rustc_version",
"subtle",
"zeroize",
@ -411,7 +444,7 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35b50dba0afdca80b187392b24f2499a88c336d5a8493e4b4ccfb608708be56a"
dependencies = [
"bitflags 2.0.2",
"bitflags 2.6.0",
"proc-macro2",
"proc-macro2-diagnostics",
"quote",
@ -463,6 +496,12 @@ dependencies = [
"url",
]
[[package]]
name = "dunce"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
[[package]]
name = "either"
version = "1.8.1"
@ -486,7 +525,7 @@ checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0"
dependencies = [
"humantime",
"is-terminal",
"log 0.4.17",
"log",
"regex",
"termcolor",
]
@ -498,7 +537,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50d6a0976c999d473fe89ad888d5a284e55366d9dc9038b1ba2aa15128c4afa0"
dependencies = [
"errno-dragonfly",
"libc 0.2.140",
"libc 0.2.158",
"windows-sys 0.45.0",
]
@ -509,7 +548,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
dependencies = [
"cc",
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
@ -571,6 +610,12 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "fs_extra"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
[[package]]
name = "futures"
version = "0.3.28"
@ -579,6 +624,7 @@ checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
@ -601,12 +647,34 @@ version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
[[package]]
name = "futures-executor"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964"
[[package]]
name = "futures-macro"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.58",
]
[[package]]
name = "futures-sink"
version = "0.3.28"
@ -628,6 +696,7 @@ dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
@ -649,8 +718,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33a20a288a94683f5f4da0adecdbe095c94a77c295e514cc6484e9394dd8376e"
dependencies = [
"cc",
"libc 0.2.140",
"log 0.4.17",
"libc 0.2.158",
"log",
"rustversion",
"windows 0.44.0",
]
@ -672,7 +741,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
dependencies = [
"cfg-if",
"libc 0.2.140",
"libc 0.2.158",
"wasi 0.11.0+wasi-snapshot-preview1",
]
@ -719,7 +788,7 @@ version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
dependencies = [
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
@ -887,7 +956,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09270fd4fa1111bc614ed2246c7ef56239a3063d5be0d1ec3b589c505d400aeb"
dependencies = [
"hermit-abi 0.3.1",
"libc 0.2.140",
"libc 0.2.158",
"windows-sys 0.45.0",
]
@ -915,6 +984,67 @@ version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
[[package]]
name = "j4-i2p-rs"
version = "0.2.0-alpha"
dependencies = [
"hex",
"j4rs",
"log",
"rand",
"thiserror",
]
[[package]]
name = "j4rs"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "689ae4f2bd4eba82601592f3d22b7e7147b1df52d3b525223f5218990501b4eb"
dependencies = [
"cesu8",
"dunce",
"fs_extra",
"futures",
"glob",
"java-locator",
"jni-sys",
"lazy_static 1.4.0",
"libc 0.2.158",
"libloading",
"log",
"serde",
"serde_json",
]
[[package]]
name = "java-locator"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2abecabd9961c5e01405a6426687fcf1bd94a269927137e4c3cc1a7419b93fd"
dependencies = [
"glob",
"lazy_static 1.4.0",
]
[[package]]
name = "jni-sys"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c30a312d782b8d56a1e0897d45c1af33f31f9b4a4d13d31207a8675e0223b818"
dependencies = [
"jni-sys-macros",
]
[[package]]
name = "jni-sys-macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c199962dfd5610ced8eca382606e349f7940a4ac7d867b58a046123411cbb4"
dependencies = [
"quote",
"syn 1.0.109",
]
[[package]]
name = "js-sys"
version = "0.3.61"
@ -939,6 +1069,18 @@ dependencies = [
"sha2 0.10.6",
]
[[package]]
name = "kn0sys-lmdb-rs"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58fbf491e9e95a325cbfe1459734cec781c0145c0d5cb7c4ced71af742364d19"
dependencies = [
"bitflags 2.6.0",
"libc 0.2.158",
"liblmdb-sys",
"log",
]
[[package]]
name = "lazy_static"
version = "0.2.11"
@ -959,9 +1101,9 @@ checksum = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122"
[[package]]
name = "libc"
version = "0.2.140"
version = "0.2.158"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
[[package]]
name = "liblmdb-sys"
@ -970,7 +1112,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "feed38a3a580f60bf61aaa067b0ff4123395966839adeaf67258a9e50c4d2e49"
dependencies = [
"gcc",
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
name = "libloading"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4"
dependencies = [
"cfg-if",
"windows-targets 0.52.6",
]
[[package]]
@ -988,18 +1140,6 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f"
[[package]]
name = "lmdb-rs"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4aefe7b433f795629ce42f35ccf7a620c38bd457238bfaa2489dafc7e36167e7"
dependencies = [
"bitflags 0.7.0",
"libc 0.2.140",
"liblmdb-sys",
"log 0.3.9",
]
[[package]]
name = "lock_api"
version = "0.4.9"
@ -1012,21 +1152,9 @@ dependencies = [
[[package]]
name = "log"
version = "0.3.9"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
dependencies = [
"log 0.4.17",
]
[[package]]
name = "log"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "loom"
@ -1081,8 +1209,8 @@ version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
dependencies = [
"libc 0.2.140",
"log 0.4.17",
"libc 0.2.158",
"log",
"wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys 0.45.0",
]
@ -1098,7 +1226,7 @@ dependencies = [
"futures-util",
"http",
"httparse",
"log 0.4.17",
"log",
"memchr",
"mime",
"spin",
@ -1114,8 +1242,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e"
dependencies = [
"lazy_static 1.4.0",
"libc 0.2.140",
"log 0.4.17",
"libc 0.2.158",
"log",
"openssl",
"openssl-probe",
"openssl-sys",
@ -1129,6 +1257,7 @@ dependencies = [
name = "neveko_core"
version = "0.1.2-beta"
dependencies = [
"bincode",
"chrono",
"clap",
"curve25519-dalek",
@ -1136,10 +1265,11 @@ dependencies = [
"env_logger",
"hex",
"hmac",
"j4-i2p-rs",
"jwt",
"kn0sys-lmdb-rs",
"lazy_static 1.4.0",
"lmdb-rs",
"log 0.4.17",
"log",
"num",
"rand",
"rand_core",
@ -1150,6 +1280,8 @@ dependencies = [
"serde",
"serde_json",
"sha2 0.10.6",
"sysinfo",
"thiserror",
"tokio",
]
@ -1158,11 +1290,20 @@ name = "neveko_message"
version = "0.1.2-beta"
dependencies = [
"env_logger",
"log 0.4.17",
"log",
"neveko_core",
"rocket",
]
[[package]]
name = "ntapi"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4"
dependencies = [
"winapi",
]
[[package]]
name = "nu-ansi-term"
version = "0.46.0"
@ -1256,7 +1397,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
dependencies = [
"hermit-abi 0.2.6",
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
@ -1280,7 +1421,7 @@ dependencies = [
"bitflags 1.3.2",
"cfg-if",
"foreign-types",
"libc 0.2.140",
"libc 0.2.158",
"once_cell",
"openssl-macros",
"openssl-sys",
@ -1311,7 +1452,7 @@ checksum = "666416d899cf077260dac8698d60a60b435a46d57e82acb1be3d0dad87284e5b"
dependencies = [
"autocfg",
"cc",
"libc 0.2.140",
"libc 0.2.158",
"pkg-config",
"vcpkg",
]
@ -1339,7 +1480,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
dependencies = [
"cfg-if",
"libc 0.2.140",
"libc 0.2.158",
"redox_syscall 0.2.16",
"smallvec",
"windows-sys 0.45.0",
@ -1392,12 +1533,6 @@ version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
[[package]]
name = "platforms"
version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7"
[[package]]
name = "ppv-lite86"
version = "0.2.17"
@ -1441,7 +1576,7 @@ version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc 0.2.140",
"libc 0.2.158",
"rand_chacha",
"rand_core",
]
@ -1465,6 +1600,26 @@ dependencies = [
"getrandom",
]
[[package]]
name = "rayon"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
]
[[package]]
name = "redox_syscall"
version = "0.2.16"
@ -1547,7 +1702,7 @@ dependencies = [
"hyper-tls",
"ipnet",
"js-sys",
"log 0.4.17",
"log",
"mime",
"native-tls",
"once_cell",
@ -1582,7 +1737,7 @@ dependencies = [
"futures",
"indexmap",
"is-terminal",
"log 0.4.17",
"log",
"memchr",
"multer",
"num_cpus",
@ -1633,7 +1788,7 @@ dependencies = [
"http",
"hyper",
"indexmap",
"log 0.4.17",
"log",
"memchr",
"pear",
"percent-encoding",
@ -1676,7 +1831,7 @@ dependencies = [
"bitflags 1.3.2",
"errno",
"io-lifetimes",
"libc 0.2.140",
"libc 0.2.158",
"linux-raw-sys",
"windows-sys 0.45.0",
]
@ -1738,7 +1893,7 @@ dependencies = [
"bitflags 1.3.2",
"core-foundation",
"core-foundation-sys",
"libc 0.2.140",
"libc 0.2.158",
"security-framework-sys",
]
@ -1749,7 +1904,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4"
dependencies = [
"core-foundation-sys",
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
@ -1840,7 +1995,7 @@ version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
dependencies = [
"libc 0.2.140",
"libc 0.2.158",
]
[[package]]
@ -1864,7 +2019,7 @@ version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"
dependencies = [
"libc 0.2.140",
"libc 0.2.158",
"winapi",
]
@ -1926,6 +2081,20 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "sysinfo"
version = "0.31.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "355dbe4f8799b304b05e1b0f05fc59b2a18d36645cf169607da45bde2f69a1be"
dependencies = [
"core-foundation-sys",
"libc 0.2.158",
"memchr",
"ntapi",
"rayon",
"windows 0.57.0",
]
[[package]]
name = "tempfile"
version = "3.5.0"
@ -1957,6 +2126,26 @@ dependencies = [
"libc 0.1.12",
]
[[package]]
name = "thiserror"
version = "1.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.58",
]
[[package]]
name = "thread_local"
version = "1.1.7"
@ -1973,7 +2162,7 @@ version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
dependencies = [
"libc 0.2.140",
"libc 0.2.158",
"wasi 0.10.0+wasi-snapshot-preview1",
"winapi",
]
@ -2028,7 +2217,7 @@ checksum = "d0de47a4eecbe11f498978a9b29d792f0d2692d1dd003650c24c76510e3bc001"
dependencies = [
"autocfg",
"bytes",
"libc 0.2.140",
"libc 0.2.158",
"mio",
"num_cpus",
"pin-project-lite",
@ -2139,7 +2328,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922"
dependencies = [
"lazy_static 1.4.0",
"log 0.4.17",
"log",
"tracing-core",
]
@ -2266,7 +2455,7 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
dependencies = [
"log 0.4.17",
"log",
"try-lock",
]
@ -2299,7 +2488,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
dependencies = [
"bumpalo",
"log 0.4.17",
"log",
"once_cell",
"proc-macro2",
"quote",
@ -2407,6 +2596,59 @@ dependencies = [
"windows-targets 0.47.0",
]
[[package]]
name = "windows"
version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143"
dependencies = [
"windows-core",
"windows-targets 0.52.6",
]
[[package]]
name = "windows-core"
version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d"
dependencies = [
"windows-implement",
"windows-interface",
"windows-result",
"windows-targets 0.52.6",
]
[[package]]
name = "windows-implement"
version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.58",
]
[[package]]
name = "windows-interface"
version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.58",
]
[[package]]
name = "windows-result"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8"
dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-sys"
version = "0.42.0"
@ -2461,6 +2703,22 @@ dependencies = [
"windows_x86_64_msvc 0.47.0",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm 0.52.6",
"windows_aarch64_msvc 0.52.6",
"windows_i686_gnu 0.52.6",
"windows_i686_gnullvm",
"windows_i686_msvc 0.52.6",
"windows_x86_64_gnu 0.52.6",
"windows_x86_64_gnullvm 0.52.6",
"windows_x86_64_msvc 0.52.6",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.2"
@ -2473,6 +2731,12 @@ version = "0.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "831d567d53d4f3cb1db332b68e6e2b6260228eb4d99a777d8b2e8ed794027c90"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.2"
@ -2485,6 +2749,12 @@ version = "0.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a42d54a417c60ce4f0e31661eed628f0fa5aca73448c093ec4d45fab4c51cdf"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.42.2"
@ -2497,6 +2767,18 @@ version = "0.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1925beafdbb22201a53a483db861a5644123157c1c3cee83323a2ed565d71e3"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.42.2"
@ -2509,6 +2791,12 @@ version = "0.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a8ef8f2f1711b223947d9b69b596cf5a4e452c930fb58b6fc3fdae7d0ec6b31"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.2"
@ -2521,6 +2809,12 @@ version = "0.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7acaa0c2cf0d2ef99b61c308a0c3dbae430a51b7345dedec470bd8f53f5a3642"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.2"
@ -2533,6 +2827,12 @@ version = "0.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5a0628f71be1d11e17ca4a0e9e15b3a5180f6fbf1c2d55e3ba3f850378052c1"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.2"
@ -2545,6 +2845,12 @@ version = "0.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d6e62c256dc6d40b8c8707df17df8d774e60e39db723675241e7c15e910bce7"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "winreg"
version = "0.10.1"

View file

@ -29,23 +29,23 @@ pub async fn send_message(
} else {
message::MessageType::Normal
};
let res: Message = message::create(m_req, token.get_jwp(), m_type).await;
Custom(Status::Ok, Json(res))
let res = message::create(m_req, token.get_jwp(), m_type).await;
Custom(Status::Ok, Json(res.unwrap_or_default()))
}
/// Return all messages
#[get("/")]
pub async fn get_messages(_token: auth::BearerToken) -> Custom<Json<Vec<Message>>> {
let messages = message::find_all();
Custom(Status::Ok, Json(messages))
Custom(Status::Ok, Json(messages.unwrap_or_default()))
}
/// Delete a message by mid
#[delete("/<mid>")]
pub async fn remove_message(mid: String, _token: auth::BearerToken) -> Custom<Json<Vec<Message>>> {
message::delete(&mid);
let _ = message::delete(&mid);
let messages = message::find_all();
Custom(Status::Ok, Json(messages))
Custom(Status::Ok, Json(messages.unwrap_or_default()))
}
/// decipher a message body
@ -55,5 +55,5 @@ pub async fn decipher(
_token: auth::BearerToken,
) -> Custom<Json<reqres::DecipheredMessageBody>> {
let d_message = message::decipher_body(mid).await;
Custom(Status::Ok, Json(d_message))
Custom(Status::Ok, Json(d_message.unwrap_or_default()))
}

View file

@ -31,8 +31,8 @@ pub async fn get_version(_jwp: proof::PaymentProof) -> Custom<Json<reqres::XmrRp
/// This also functions as a health check
#[get("/status")]
pub async fn get_i2p_status() -> Custom<Json<i2p::HttpProxyStatus>> {
let status: i2p::ProxyStatus = i2p::check_connection().await;
if status == i2p::ProxyStatus::Open {
let status = i2p::check_connection().await;
if status.unwrap_or(i2p::ProxyStatus::Opening) == i2p::ProxyStatus::Open {
Custom(Status::Ok, Json(i2p::HttpProxyStatus { open: true }))
} else {
Custom(Status::Ok, Json(i2p::HttpProxyStatus { open: false }))
@ -44,8 +44,8 @@ pub async fn get_i2p_status() -> Custom<Json<i2p::HttpProxyStatus>> {
/// Protected: false
#[get("/")]
pub async fn share_contact_info() -> Custom<Json<models::Contact>> {
let info: models::Contact = contact::share().await;
Custom(Status::Ok, Json(info))
let info = contact::share().await;
Custom(Status::Ok, Json(info.unwrap_or_default()))
}
/// Recieve messages here
@ -56,7 +56,7 @@ pub async fn rx_message(
_jwp: proof::PaymentProof,
message: Json<models::Message>,
) -> Custom<Json<models::Message>> {
message::rx(message).await;
let _ = message::rx(message).await;
Custom(Status::Ok, Json(Default::default()))
}
@ -84,8 +84,8 @@ pub async fn gen_jwp(proof: Json<proof::TxProof>) -> Custom<Json<reqres::Jwp>> {
/// Get a product by passing id
#[get("/<pid>")]
pub async fn get_product(pid: String, _jwp: proof::PaymentProof) -> Custom<Json<models::Product>> {
let m_product: models::Product = product::find(&pid);
Custom(Status::Ok, Json(m_product))
let m_product = product::find(&pid);
Custom(Status::Ok, Json(m_product.unwrap_or_default()))
}
/// Get all products
@ -93,7 +93,7 @@ pub async fn get_product(pid: String, _jwp: proof::PaymentProof) -> Custom<Json<
/// Protected: true
#[get("/products")]
pub async fn get_products(_jwp: proof::PaymentProof) -> Custom<Json<Vec<models::Product>>> {
let m_products: Vec<models::Product> = product::find_all();
let m_products: Vec<models::Product> = product::find_all().unwrap_or_default();
Custom(Status::Ok, Json(m_products))
}
@ -105,8 +105,8 @@ pub async fn create_order(
r_order: Json<reqres::OrderRequest>,
_jwp: proof::PaymentProof,
) -> Custom<Json<models::Order>> {
let m_order: models::Order = order::create(r_order).await;
Custom(Status::Created, Json(m_order))
let m_order = order::create(r_order).await;
Custom(Status::Created, Json(m_order.unwrap_or_default()))
}
/// Customer order retreival. Must send `signature`
@ -120,8 +120,9 @@ pub async fn retrieve_order(
signature: String,
_jwp: proof::PaymentProof,
) -> Custom<Json<models::Order>> {
let m_order = order::secure_retrieval(&orid, &signature).await;
if m_order.cid == utils::empty_string() {
let r_m_order = order::secure_retrieval(&orid, &signature).await;
let m_order = r_m_order.unwrap_or_default();
if m_order.cid.is_empty() {
return Custom(Status::BadRequest, Json(Default::default()));
}
Custom(Status::Created, Json(m_order))
@ -135,21 +136,22 @@ pub async fn get_multisig_info(
r_info: Json<reqres::MultisigInfoRequest>,
_jwp: proof::PaymentProof,
) -> Custom<Json<models::Order>> {
let info: Vec<String> = r_info.info.iter().cloned().collect();
if r_info.msig_type == String::from(message::PREPARE_MSIG) {
let info: Vec<String> = r_info.info.to_vec();
if r_info.msig_type == *message::PREPARE_MSIG {
// adjudicator won't have wallet for order yet do that first
if r_info.init_adjudicator {
order::init_adjudicator_wallet(&r_info.orid).await;
}
message::send_prepare_info(&r_info.orid, &r_info.contact).await;
} else if r_info.msig_type == String::from(message::MAKE_MSIG) {
message::send_make_info(&r_info.orid, &r_info.contact, info).await;
} else if r_info.msig_type == String::from(message::EXPORT_MSIG) {
message::send_export_info(&r_info.orid, &r_info.contact).await;
} else if r_info.msig_type == String::from(message::IMPORT_MSIG) {
message::send_import_info(&r_info.orid, &r_info.info).await;
let _ = message::send_prepare_info(&r_info.orid, &r_info.contact).await;
} else if r_info.msig_type == *message::MAKE_MSIG {
let _ = message::send_make_info(&r_info.orid, &r_info.contact, info).await;
} else if r_info.msig_type == *message::EXPORT_MSIG {
let _ = message::send_export_info(&r_info.orid, &r_info.contact).await;
} else if r_info.msig_type == *message::IMPORT_MSIG {
let _ = message::send_import_info(&r_info.orid, &r_info.info).await;
} else {
message::send_exchange_info(&r_info.orid, &r_info.contact, info, r_info.kex_init).await;
let _ =
message::send_exchange_info(&r_info.orid, &r_info.contact, info, r_info.kex_init).await;
}
Custom(Status::Ok, Json(Default::default()))
}
@ -162,7 +164,7 @@ pub async fn rx_multisig_message(
_jwp: proof::PaymentProof,
message: Json<models::Message>,
) -> Custom<Json<models::Message>> {
message::rx_multisig(message).await;
let _ = message::rx_multisig(message).await;
Custom(Status::Ok, Json(Default::default()))
}
@ -182,7 +184,8 @@ pub async fn request_shipment(
orid: String,
_jwp: proof::PaymentProof,
) -> Custom<Json<reqres::FinalizeOrderResponse>> {
let finalize: reqres::FinalizeOrderResponse = order::validate_order_for_ship(&orid).await;
let r_finalize = order::validate_order_for_ship(&orid).await;
let finalize = r_finalize.unwrap_or_default();
if finalize.delivery_info.is_empty() {
return Custom(Status::BadRequest, Json(Default::default()));
}
@ -204,8 +207,9 @@ pub async fn trigger_nasr(
vendor: String,
_jwp: proof::PaymentProof,
) -> Custom<Json<models::Order>> {
let order: models::Order = order::d_trigger_ship_request(&vendor, &orid).await;
if order.orid == utils::empty_string() {
let r_order = order::d_trigger_ship_request(&vendor, &orid).await;
let order = r_order.unwrap_or_default();
if order.orid.is_empty() {
return Custom(Status::BadRequest, Json(Default::default()));
}
Custom(Status::Ok, Json(order))
@ -222,8 +226,9 @@ pub async fn cancel_order(
signature: String,
_jwp: proof::PaymentProof,
) -> Custom<Json<models::Order>> {
let m_order = order::cancel_order(&orid, &signature).await;
if m_order.cid == utils::empty_string() {
let r_m_order = order::cancel_order(&orid, &signature).await;
let m_order = r_m_order.unwrap_or_default();
if m_order.cid.is_empty() {
return Custom(Status::BadRequest, Json(Default::default()));
}
Custom(Status::Ok, Json(m_order))
@ -239,7 +244,8 @@ pub async fn finalize_order(
orid: String,
_jwp: proof::PaymentProof,
) -> Custom<Json<reqres::FinalizeOrderResponse>> {
let finalize = order::finalize_order(&orid).await;
let r_finalize = order::finalize_order(&orid).await;
let finalize = r_finalize.unwrap_or_default();
if !finalize.vendor_update_success {
return Custom(Status::BadRequest, Json(Default::default()));
}
@ -252,7 +258,8 @@ pub async fn create_dispute(
dispute: Json<models::Dispute>,
_jwp: proof::PaymentProof,
) -> Custom<Json<models::Dispute>> {
let m_dispute: models::Dispute = dispute::create(dispute);
let r_m_dispute = dispute::create(dispute);
let m_dispute = r_m_dispute.unwrap_or_default();
Custom(Status::Ok, Json(m_dispute))
}

View file

@ -19,7 +19,7 @@ async fn rocket() -> _ {
..rocket::Config::debug_default()
};
env_logger::init();
utils::start_up().await;
let _ = utils::start_up().await;
rocket::custom(&config)
.register(
"/",