cache db handle

This commit is contained in:
kn0sys 2024-09-11 00:30:52 -04:00
parent 4aa2dcfcba
commit efaf76da93
No known key found for this signature in database
GPG key ID: 3BDB674C95F103FA
45 changed files with 1147 additions and 398 deletions

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

106
Cargo.lock generated
View file

@ -71,7 +71,7 @@ dependencies = [
"android-properties", "android-properties",
"bitflags 1.3.2", "bitflags 1.3.2",
"cc", "cc",
"jni-sys", "jni-sys 0.3.0",
"libc 0.2.153", "libc 0.2.153",
"log", "log",
"ndk", "ndk",
@ -766,6 +766,12 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
[[package]]
name = "dunce"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
[[package]] [[package]]
name = "ecolor" name = "ecolor"
version = "0.21.0" version = "0.21.0"
@ -1026,6 +1032,12 @@ dependencies = [
"percent-encoding", "percent-encoding",
] ]
[[package]]
name = "fs_extra"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
[[package]] [[package]]
name = "futures" name = "futures"
version = "0.3.28" version = "0.3.28"
@ -1034,6 +1046,7 @@ checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40"
dependencies = [ dependencies = [
"futures-channel", "futures-channel",
"futures-core", "futures-core",
"futures-executor",
"futures-io", "futures-io",
"futures-sink", "futures-sink",
"futures-task", "futures-task",
@ -1056,12 +1069,34 @@ version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" 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]] [[package]]
name = "futures-io" name = "futures-io"
version = "0.3.28" version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" 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]] [[package]]
name = "futures-sink" name = "futures-sink"
version = "0.3.28" version = "0.3.28"
@ -1083,6 +1118,7 @@ dependencies = [
"futures-channel", "futures-channel",
"futures-core", "futures-core",
"futures-io", "futures-io",
"futures-macro",
"futures-sink", "futures-sink",
"futures-task", "futures-task",
"memchr", "memchr",
@ -1523,6 +1559,48 @@ version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" 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]] [[package]]
name = "jni" name = "jni"
version = "0.21.1" version = "0.21.1"
@ -1532,7 +1610,7 @@ dependencies = [
"cesu8", "cesu8",
"cfg-if", "cfg-if",
"combine", "combine",
"jni-sys", "jni-sys 0.3.0",
"log", "log",
"thiserror", "thiserror",
"walkdir", "walkdir",
@ -1545,6 +1623,25 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" 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]] [[package]]
name = "jobserver" name = "jobserver"
version = "0.1.26" version = "0.1.26"
@ -1854,7 +1951,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0" checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0"
dependencies = [ dependencies = [
"bitflags 1.3.2", "bitflags 1.3.2",
"jni-sys", "jni-sys 0.3.0",
"ndk-sys", "ndk-sys",
"num_enum", "num_enum",
"raw-window-handle", "raw-window-handle",
@ -1873,7 +1970,7 @@ version = "0.4.1+23.1.7779620"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3cf2aae958bd232cac5069850591667ad422d263686d75b52a065f9badeee5a3" checksum = "3cf2aae958bd232cac5069850591667ad422d263686d75b52a065f9badeee5a3"
dependencies = [ dependencies = [
"jni-sys", "jni-sys 0.3.0",
] ]
[[package]] [[package]]
@ -1922,6 +2019,7 @@ dependencies = [
"env_logger", "env_logger",
"hex", "hex",
"hmac", "hmac",
"j4-i2p-rs",
"jwt", "jwt",
"kn0sys-lmdb-rs", "kn0sys-lmdb-rs",
"lazy_static 1.4.0", "lazy_static 1.4.0",

View file

@ -0,0 +1,13 @@
-----BEGIN CERTIFICATE-----
MIIB6jCCAY+gAwIBAgIJAPeWi4iUKLBJMAoGCCqGSM49BAMCMHoxCzAJBgNVBAYT
AlhYMQswCQYDVQQIDAJYWDELMAkGA1UEBwwCWFgxHjAcBgNVBAoMFUkyUCBBbm9u
eW1vdXMgTmV0d29yazEPMA0GA1UECwwGZmFtaWx5MSAwHgYDVQQDDBdnb3N0Y29p
bi5mYW1pbHkuaTJwLm5ldDAeFw0xNzA4MDExMzQ4MzdaFw0yNzA3MzAxMzQ4Mzda
MHoxCzAJBgNVBAYTAlhYMQswCQYDVQQIDAJYWDELMAkGA1UEBwwCWFgxHjAcBgNV
BAoMFUkyUCBBbm9ueW1vdXMgTmV0d29yazEPMA0GA1UECwwGZmFtaWx5MSAwHgYD
VQQDDBdnb3N0Y29pbi5mYW1pbHkuaTJwLm5ldDBZMBMGByqGSM49AgEGCCqGSM49
AwEHA0IABC+9iIYumUNnsqKbnTluHimV8OdGvo7yeGxuqhfNNB2b3jvbFJ81scgH
dsZtMQmUxgKM5nH+NQJMoCxHhSlRy2QwCgYIKoZIzj0EAwIDSQAwRgIhANNh7mOp
nBBPRh2a/ipG1VYS0d+mNjSrpz8xWcG3CXPLAiEAjM5MTfv9sOJ74PeZVhFZ02w4
vhgyZCeLJ57f123Lm1A=
-----END CERTIFICATE-----

View file

@ -0,0 +1,13 @@
-----BEGIN CERTIFICATE-----
MIICCjCCAa2gAwIBAgIEfT9YJTAMBggqhkjOPQQDAgUAMHkxCzAJBgNVBAYTAlhY
MQswCQYDVQQIEwJYWDELMAkGA1UEBxMCWFgxHjAcBgNVBAoTFUkyUCBBbm9ueW1v
dXMgTmV0d29yazEPMA0GA1UECxMGZmFtaWx5MR8wHQYDVQQDExZpMnAtZGV2LmZh
bWlseS5pMnAubmV0MB4XDTE1MTIwOTIxNDIzM1oXDTI1MTIwODIxNDIzM1oweTEL
MAkGA1UEBhMCWFgxCzAJBgNVBAgTAlhYMQswCQYDVQQHEwJYWDEeMBwGA1UEChMV
STJQIEFub255bW91cyBOZXR3b3JrMQ8wDQYDVQQLEwZmYW1pbHkxHzAdBgNVBAMT
FmkycC1kZXYuZmFtaWx5LmkycC5uZXQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC
AAR7FPSglYrxeSPzv74A1fTwjajZWV0TljqEMBS/56juZQB/7xOwrsHFHA0eEEF9
dTH64wx3lhV/9sh/stwPU2MToyEwHzAdBgNVHQ4EFgQUQh4uRP1aaX8TJX5dljrS
CeFNjcAwDAYIKoZIzj0EAwIFAANJADBGAiEAhXlEKGCjJ4urpi2db3OIMl9pB+9t
M+oVtAqBamWvVBICIQDBaIqfwLzFameO5ULgGRMysKQkL0O5mH6xo910YQV8jQ==
-----END CERTIFICATE-----

View file

@ -0,0 +1,13 @@
-----BEGIN CERTIFICATE-----
MIIB6TCCAY+gAwIBAgIJAI7G9MXxh7OjMAoGCCqGSM49BAMCMHoxCzAJBgNVBAYT
AlhYMQswCQYDVQQIDAJYWDELMAkGA1UEBwwCWFgxHjAcBgNVBAoMFUkyUCBBbm9u
eW1vdXMgTmV0d29yazEPMA0GA1UECwwGZmFtaWx5MSAwHgYDVQQDDBdpMnBkLWRl
di5mYW1pbHkuaTJwLm5ldDAeFw0xNjAyMjAxNDE2MzhaFw0yNjAyMTcxNDE2Mzha
MHoxCzAJBgNVBAYTAlhYMQswCQYDVQQIDAJYWDELMAkGA1UEBwwCWFgxHjAcBgNV
BAoMFUkyUCBBbm9ueW1vdXMgTmV0d29yazEPMA0GA1UECwwGZmFtaWx5MSAwHgYD
VQQDDBdpMnBkLWRldi5mYW1pbHkuaTJwLm5ldDBZMBMGByqGSM49AgEGCCqGSM49
AwEHA0IABMlWL3loKVOfsA8Rm91QR53Il69mQiaB7n3rUhfPkJb9MYc1S4198azE
iSnNZSXicKDPIifaCgvONmbACzElHc8wCgYIKoZIzj0EAwIDSAAwRQIgYWmSFuai
TJvVrlB5RlbiiNFCEootjWP8BFM3t/yFeaQCIQDkg4xcQIRGTHhjrCsxmlz9KcRF
G+eIF+ATfI93nPseLw==
-----END CERTIFICATE-----

View file

@ -0,0 +1,12 @@
-----BEGIN CERTIFICATE-----
MIIBxDCCAWmgAwIBAgIJAJnJIdKHYwWcMAoGCCqGSM49BAMCMGcxCzAJBgNVBAYT
AkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRn
aXRzIFB0eSBMdGQxIDAeBgNVBAMMF3ZvbGF0aWxlLmZhbWlseS5pMnAubmV0MB4X
DTE2MDQyNjE1MjAyNloXDTI2MDQyNDE1MjAyNlowZzELMAkGA1UEBhMCQVUxEzAR
BgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5
IEx0ZDEgMB4GA1UEAwwXdm9sYXRpbGUuZmFtaWx5LmkycC5uZXQwWTATBgcqhkjO
PQIBBggqhkjOPQMBBwNCAARf6LBfbbfL6HInvC/4wAGaN3rj0eeLE/OdBpA93R3L
s8EUp0YTEJHWPo9APiKMmAwQSsMJfjhNrbp+UWEnnx2LMAoGCCqGSM49BAMCA0kA
MEYCIQDpQu2KPV5G1JOFLoZvdj+rcvEnjxM/FxkaqikwkVx8FAIhANP7DkUal+GT
SuiCtcqM4QyIBsfsCJBWEMzovft164Bo
-----END CERTIFICATE-----

View file

@ -0,0 +1,32 @@
-----BEGIN CERTIFICATE-----
MIIFhTCCA22gAwIBAgIEGdD2PTANBgkqhkiG9w0BAQ0FADBzMQswCQYDVQQGEwJY
WDELMAkGA1UECBMCWFgxCzAJBgNVBAcTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnlt
b3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEcMBoGA1UEAwwTYW1wZXJuYW5kQGdt
YWlsLmNvbTAeFw0xNTA3MjIxMjMxMTBaFw0yNTA3MjExMjMxMTBaMHMxCzAJBgNV
BAYTAlhYMQswCQYDVQQIEwJYWDELMAkGA1UEBxMCWFgxHjAcBgNVBAoTFUkyUCBB
bm9ueW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMRwwGgYDVQQDDBNhbXBlcm5h
bmRAZ21haWwuY29tMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjpTU
nBYHsqpQbAodtOQlEaRTMMI4YUi+JBMNEmlU2/9MozW13xxFr6brfgYTje0dTTgN
eGe/pvDM7H/a5ppSIEFCGDnn9mwrciIjHMaXeb7Z4cvxwFVwOxMclsFiw/+3sHQj
GyoR6TQQfsIupdtKwedmBQgVmHU+UKg3WKCyaE6J7DNHa0/nD4vtW+vaXFpv8o1w
PqEOar1Y34glxq6NTiivgGFtckBWkFLTQNjOAh/uSsdhnSDKiNHKFa3mNzjm2glf
B0ETP3yOMkEbVf9tTanlJbYsMEpfeajymGd5+P1S/2Eo0c2MlJOvLkLXAvXMdHzK
kmOTsSn/65bm5Rc2X+GQflLJlC0kuBoIyTXqFiAY7CN5y4F9llbjQ91CE2WgRv5U
dGcEilAjE36ZenQvHlKfHEs0SLAfb86GA0R5cBPQeTZq3AEqAJ9NaFgFzGvKzlJ/
8c3JeOMyc/1YwodoWwhuNICGijAA5X7MUrJVZAh4Z18ZoOd3ITkUz/ugkHhmFU3Z
vV8LrHUoIiZxTsjSxhxYz7JHQa3eZQty4/66j+FXZThzwBm419RlXLnHVURwwQaX
znC7qYUE0YeiHDw4NaGwM8qlayPYMyD8sggZfXDH+SoeJBCji6zfgbdpF/aEsQhi
++/SWDNJfy6V1TQL5AXpmJEZmUTnZKm7paJfgyUCAwEAAaMhMB8wHQYDVR0OBBYE
FIBx9Nz6oPIgX8pKgmL04wxFkVWuMA0GCSqGSIb3DQEBDQUAA4ICAQAMsHfnEB/q
p8ToRmythRTiDjgSEc0VDOzKdizieJtFcFgK0WEzpuTeTXo012bTCv+qE5wWf32d
Lgv49PDJw+j8spkkdZzO6GIRhbI1C/4sCPe6p6ev/a3SZIbUi4NGIW48DeEIArjt
AwF94b3v4t067oZ1rNIHgdiKvqIMdztPiyqOjcx1/iuFDkrOnByqvWXVmOxHGskZ
F7CqId1/WVRCdzVYK6Ln5HwDHfZr8EYWTZE6zUd5osHJMYeitRYBtk7tylrDk3uP
88BD/fHRxc5+hBKEhVHua7Arm9R2CPvgK352dyxIpoiGuOUr98A8tM08pU6gNnuO
OZ7LU+5+Oc8FqPuUyhogwgDuBFA7s0fx464F1jofVPWOlarNZq7Mc0AwlA6jwLRY
1HExOlKkMbhALSOOAnSypozxFg1t8bkb0QUaUuz7Rck3gKvHX99mqzl7Ql6ZS4rm
umJNDEsGh0F6dxEQJ+b2I7NbSpGEf8PaUM5jASZeQncjPCMfBjPC8QwzYySLad5Y
n9e9sZN92zPYetdiQfpHwRY4N8itb4rb6TpwiSG6vVVvQJdFt77Y+4MtgFm9ofqA
ZDOBxt0r2AOT4Jrj92ifCKLDjevTaZjCSS2lPMMZbxoL+TXvNu12IKCm9rKn/+oP
WX+lDNy2nNJXrnKSvcyrBWxAi8+t0ZzGug==
-----END CERTIFICATE-----

View file

@ -0,0 +1,32 @@
-----BEGIN CERTIFICATE-----
MIIFfzCCA2egAwIBAgIESg3kkzANBgkqhkiG9w0BAQ0FADBwMQswCQYDVQQGEwJY
WDELMAkGA1UECBMCWFgxCzAJBgNVBAcTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnlt
b3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEZMBcGA1UEAwwQZWNoZWxvbkBtYWls
LmkycDAeFw0xNDA3MzExNjQ3MDJaFw0yNDA3MzAxNjQ3MDJaMHAxCzAJBgNVBAYT
AlhYMQswCQYDVQQIEwJYWDELMAkGA1UEBxMCWFgxHjAcBgNVBAoTFUkyUCBBbm9u
eW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMRkwFwYDVQQDDBBlY2hlbG9uQG1h
aWwuaTJwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAmcEgLwwhzLNe
XLOMSrhwB8hWpOhfjo4s6S/wjBtjjUc8nI3D0hSn3HY26p0rvcvNEWexPUpPULmC
exGkU463nu7PiFONiORI1eJAiUFHibRiaA7Wboyo38pO73KirwjG07Y+Ua0jp+HS
+4FQ/I/9H/bPplReTOU/6hmRbgQ69U8nE68HzZHQxP68yVJ2rPHSXMPhF4R1h0G1
1mCAT+TgTsnwHNGF77XHJnY4/M4e2cgycEZjZow36C3t2mNDVkMgF19QQeb9WmLR
zREn3nq9BJqHpUkn9yWw0kKXTZSds+7UxESfzf3BzK0+hky2fh5H+qbYAo2lz4yj
81MXTAu+4RRkg4DBLlF+2dkclhwQLxxzvkRC6tPkn5i33Yltg7EfzA9IoQ05potJ
I+iOcF+aStfFgFj9u3B5UkcF4P0cH1QD3c6BK4hIezQYqRoPly1gHqg+XdwjG/dr
4as7HA9FTz3p2E8nClpIC1x3hfgwAdfd29aeBxO1WW/z99iMF7TBAF+u5T86XEW1
WpknqCbTli36yJ8a5fPWxZHrryBRJT5yLxejjFeadtutBSwljiVFq+Y38VqwFivq
VLiBt7IxAsZ8iilgfnnnAvBH6chWfSKb4H7kB4TJvDiV96QmmvoEaWYNHZozMhyK
tO3b5w+xqbJXyCLA3Q75jD0km76hjcECAwEAAaMhMB8wHQYDVR0OBBYEFAHQcAam
QRS/EUhuCSr9pB4Ux0rYMA0GCSqGSIb3DQEBDQUAA4ICAQBq1+1QLmgLAjrTg3tb
4XKgAVICQRoBDNUEobQg3pYeUX9eFNya2RxNljuvYpwT80ilGMPOXcjddmr5ngiK
dbGRcuuJk9MPEHtPaPT3+JJlvKQ3B3g2wva2Wz2OAyLZUGQs389K4nTbwh4QF0n2
aHFL8BHiD62hiKnCoNaW4ZovUNNvOxo9lMyAiaFU2gqQNcdad8hP9EAllbvbxDx9
Tjww2UbwQUIHS9rna4Tlu+f0hDXTWIutc2A51W2fJCb7L3+lYO7Wv55ND/WtryLZ
XpMp27+MpuEnN3kQmz/l9R0hIJsWc/x9GQkjm5wEaIZEyTtenqwRKGmVCtAj0Pgv
jn1L3/lWmrNq+OZHb/QeyfKtA3nXfQKVmT98ewQiK/S5i1xIAXCJPytOD887b/o1
cdurTmCiZMwgiQ+HLJqCg3MDa5mvKqRkRdZXfE6aQWEcSbpAhpV15R17q7L+Fg0W
shLSNucxyGNU8PjiC/nOmqfqUiPiMltJjPmscxBLim8foyxjakC4+6N6m+Jzgznj
PocBehFAfKYj66XEwzIBN7Z2uuXoYH9YptkocFjTzvchcryVulDWZ4FWxreUMhpM
4oyjjhSB4tB9clXlwMqg577q3D6Ms0zLTqsztyPN3zr6jGev3jpVq7Q1GOlciHPv
JNJOWTH/Vas1W6XlwGcOOAARTQ==
-----END CERTIFICATE-----

View file

@ -0,0 +1,33 @@
-----BEGIN CERTIFICATE-----
MIIFtTCCA52gAwIBAgIJXecLH1IN9PiFMA0GCSqGSIb3DQEBDQUAMF4xHjAcBgNV
BAcTFUkyUCBBbm9ueW1vdXMgTmV0d29yazEMMAoGA1UEChMDSTJQMQwwCgYDVQQL
EwNJMlAxIDAeBgNVBAMMF2hhbmtoaWxsMTk1ODBAZ21haWwuY29tMB4XDTE5MDUw
NTIyMzcwNFoXDTI5MDUwNTIyMzcwNFowXjEeMBwGA1UEBxMVSTJQIEFub255bW91
cyBOZXR3b3JrMQwwCgYDVQQKEwNJMlAxDDAKBgNVBAsTA0kyUDEgMB4GA1UEAwwX
aGFua2hpbGwxOTU4MEBnbWFpbC5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
ggIKAoICAQCi+KYA++ZxEswy1pJz3mZgSBtASzgatj5GqA9WwfKsuUNfJbLgTzkP
+TQBGkRwPKdwqqJeMxau3IvCzDSfxnUn7CX5V2kliGqyfHG0vMku0YuOT7iQzdgk
sxu3nrDmVNCSe8ngQYW9D5jnGXkgQxLVtJz1nKMJdWZqiNoPHUemwDP2hSmsUs4P
5wb1tl43WYRQ5Kmrc2PoZC45YZe3qqsdR1BVg9MmuUCCFaemjG0ZgSYJDR32qCm2
LjKkdzSu1QAboc+Ck0XgSXD+NUNefTxLHeJkjAXNRXsZdIl8Rt5ExtFoXbJH19Un
1y4qUkpqQzErYLKV/o1YM6IaJlCmnlSI2V5oY/Naa4T/JMx0XAmitcXOn5Y8zGGn
o09CKkJN4oe+dHI/hPi24Smm8OW6W8vQMHLRFUnCKXK7VbTzh96habE83GgEYbV/
xiNI/8NbSA2q76rwMjCHO62yxQvrFziQPsQzuSEguZc9KtXkT2dd2RECgIO8nPcE
cu1VEDx4J+lk95RIOkpbYgux2fwNSefuGCpARU0aryq6w+YaKPngSCaBNRvQ+CtR
WqIExdl3TzzKkhn9CBc3urdryy09QVr19VdDSpZw0BnJc2B60lftFONerD7BirmK
W5KhirzkoO0H1AncaVFfe8wkY6emksT/vP64dyfBC2R6eOnF0DXuQwIDAQABo3Yw
dDAdBgNVHQ4EFgQU6gvVvoomCNtBD46pDGlPJC5knNswHwYDVR0jBBgwFoAU6gvV
voomCNtBD46pDGlPJC5knNswDgYDVR0PAQH/BAQDAgGmMCIGA1UdEQQbMBmBF2hh
bmtoaWxsMTk1ODBAZ21haWwuY29tMA0GCSqGSIb3DQEBDQUAA4ICAQAKbEh8eDlu
PDPzH44mFQFqvuYTcUasGSmHfxQrqsv+48LE7UMVxDAge4OjcfVUP2PO4PQeBllw
jcqSh/xvbgUgI0WrwhdWliXqGNP1BlJGv8U+8UIqzeVzhsYmu+U9FHbfnXoPsp7G
ikPENCQCCvRpx6trgiYZT4Mmpd7KG67dZSnMQ/3bJLGtqrshXAbyUqZNcS5rlJoM
5R8AHYyfkjvzcnzQ1GBi4qE52EVdRHka/fJwt1/q5rp5nxFGSi20iMnYgwyanyYJ
v08O82/feouxskiGflc3oAxwnSYvPI36nAsLKsoaDJ5WShGH+R2R8HepvVmIe7iw
TRD0uWx0afHuUpAqEOET03MDYoXC9LpqNTOWeV2EjAGOzvLbc9c69PbI71O8lJGz
oEpn/sWeqg1uS1VwmvjgLT4gGldFm8ySDvXSU/G4PLGRyDMXHPgCyLgB4ZU19Zzi
Srw9hxHhORp6eOzdbdW+etzzlcsxzF0bU2GPyBkr1oYAMtubFBdW3tESBpBF5OJb
9edvOhB464O0AuCK6rzqH/KxKnk48HdHJwkAP8aByTZk5V8joD1kXly49gFXhcYi
s0s6mdAsX05ppXjNGYbEw4mEcxtGCFy+hcmqG63Q5US/eFjtnzs9Xsms+WqLzlnH
gn3ZOT24+I02rwRjjwRLgNbgbieebWM5NA==
-----END CERTIFICATE-----

View file

@ -0,0 +1,33 @@
-----BEGIN CERTIFICATE-----
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
-----END CERTIFICATE-----

View file

@ -0,0 +1,33 @@
-----BEGIN CERTIFICATE-----
MIIFnTCCA4WgAwIBAgIJTngNC7YLAYpnMA0GCSqGSIb3DQEBDQUAMFYxHjAcBgNV
BAcTFUkyUCBBbm9ueW1vdXMgTmV0d29yazEMMAoGA1UEChMDSTJQMQwwCgYDVQQL
EwNJMlAxGDAWBgNVBAMMD2JhY2t1cEBtYWlsLmkycDAeFw0xOTA2MTEwOTE0NTJa
Fw0yOTA2MTEwOTE0NTJaMFYxHjAcBgNVBAcTFUkyUCBBbm9ueW1vdXMgTmV0d29y
azEMMAoGA1UEChMDSTJQMQwwCgYDVQQLEwNJMlAxGDAWBgNVBAMMD2JhY2t1cEBt
YWlsLmkycDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMGlYRD27TJX
1O2Zmf6jirLwArs1Zz4fLiiGUcGO+q47KINc/xfAngRRvzVxbwbuJhSP7aP6Wzyy
FQdmngLKHpceA3cYNILoPEd5jWTcjOtveBN2sJnggIo/mm21rYxJI3nwIx5vvSGj
YHBOhkF21d7UY5BVGPSZ+QPaRKmHVR9O/6dwXXm87BgYhTmFSqXXjQhzPok0Svl1
AbLcN6Y9ThCmvcql2o3W9iDxvI9rpTZaTLmvE3VS06ezgXP7fBYPu1lCEZHsYH6f
HtY2T1Gh2gFS6kZJvOwk8XWdQ9pLF7+eIGl9X7BH5V8pD1SSfy9LvYRboZUMGtb1
DwjSHOZjk8VoTsT5tiwN/uvIdkQ+tz81r346uCw8D56RTO9AE5p6j7ThxtKRcnGQ
e2NvBB/q9Qo8DL2CPBUCqYF3i8o44NOsYklRk3657n+VB45rPQHGfCMNL0Q89vpA
IEWso4duLY5EKcLG14ZOA12Xi+iy/v6qzc1fOZeuTvycj2EYXqadS840G5WPEzqx
SLg0AlAYGtfJWKvoYQshM10J30iF5gkR4/2qb8vaSgk5KD0wkA6tJ+1LTxdznisK
Zmx/xLCLKU/AGD9f1F+LoZXTuhqa00NncF+XigNpvBPvEZ+k7/vHzBOBU8KcJ+TR
hToy1jqFdh0mwendDvJxJYlU1zXBzFlVAgMBAAGjbjBsMB0GA1UdDgQWBBQQpUe7
AnP4KJNN3IrRfq2JigVifjAfBgNVHSMEGDAWgBQQpUe7AnP4KJNN3IrRfq2JigVi
fjAOBgNVHQ8BAf8EBAMCAaYwGgYDVR0RBBMwEYEPYmFja3VwQG1haWwuaTJwMA0G
CSqGSIb3DQEBDQUAA4ICAQAWCMW/OokXeMYQpvG8SNikkzboqRoaRMT+W73/jgAq
EMmT7A43Gv/qKZ7iuxhxhPVAYRvLQZy9NTdGxXe/lUTItMipMPaSm1/0wla4+dtG
q4nSS9DPTQNStcoVa1ljZp/jufKUCDx8a+vSg/p0aKzkeXwS0XvzB1Uc9WbGr51y
i1NwfgsvbltYC2g8sGVgwiwbCogYmbMZF5d//CUQf0LLbFqroeFlCpmAG30E75tB
YVjpr0RNn+OBSjn95IIr5urTSxCWJcmIl7GSLyf7becUSz9EpP2WC8mXiheMPU7D
unofiIt21V5mRXBOuF1B2KISYXfn5mYZAj/KEnUhMzC3YNv8GA7IoG4I/KCl9V06
fhW5UvaOCl1QSZMSCFYbE5OXYGOTbVF66K8kwGHGSIuFEgh6IXf4MLp1xILUgK9l
UmT1NJSkSt1FCOI0kP+CfmCINUiQ5elFxOPNTjCEhLZHNhHGa1p33l4ggG/CZQUW
41rUtxyrN7dY+g+AopHePMLvtGFWKlm4O5bKwD3f4UtBFme/dycWlwp6TQrzI6Mo
BRgGeKJzpRs1YXWT+ZaOHLJvFUNaPlImEfUWa3egJo2mnuhAg1N3DPWk4yda+TOH
/sjrPREOVGQ5wl4NKgYApB/dwnzgKSsecLzHheB+ekks1OC3wGxrdPnAQhIofc+G
wg==
-----END CERTIFICATE-----

View file

@ -0,0 +1,32 @@
-----BEGIN CERTIFICATE-----
MIIFfTCCA2WgAwIBAgIEUTjHEzANBgkqhkiG9w0BAQ0FADBvMQswCQYDVQQGEwJY
WDELMAkGA1UECBMCWFgxCzAJBgNVBAcTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnlt
b3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEYMBYGA1UEAwwPY2FjYXBvQG1haWwu
aTJwMB4XDTE1MDIwOTEyNTQxOFoXDTI1MDIwODEyNTQxOFowbzELMAkGA1UEBhMC
WFgxCzAJBgNVBAgTAlhYMQswCQYDVQQHEwJYWDEeMBwGA1UEChMVSTJQIEFub255
bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxGDAWBgNVBAMMD2NhY2Fwb0BtYWls
LmkycDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJjVqyjEJqCCufjO
E80hXMPZiQZCiBjSKiA27dTX5rKABI26eLzcKl7e80Ooe9wEGBXEHZCxGIXAFt8x
EHBP4W2u1dmBLpnz6cGxZRMvlTuCKHAbzdJwsWblruXgRg6EQCrtewJ9yuY5SypM
WyJEkL68XMiTeg6fsU367ifWeuPnaO9wqL45pjt9raJMYzXZb3dc6WNUIhg0u7w0
GA4z7X3CZc3f58/4F5ivKOmDd3FqM/suIH6qZJHvQQJZqLtfReLquD5TlqQjcZ1I
vtfYJWsx3Mx3tyXU4x7CHlXyxM4hEGOgMb041GR8td7AvqM0PLuexvNUHO1wDyWF
C6lydNlBwOOUXqPZCG5afgjliwAIIt0WoASEUqSFDiRmhaQZyShQ9P7NUg7jo8x1
SK/YL6agSRfyARvKG+lVoSPlVMdwuP4SGYHW9OA0wlI1fO3aY+q71iP3DFfWsLCh
hE/KXKzruDdGe0tIQdWaz5Xrv4bLN8Ot5a79TYRFUeY7lCyFP7vqert+l31hiyZS
gVugjF6zz91F/gtLsjG+y2HdbdlD3TR/+I/dZFuoiZoVPtXGla36CHLrzyTmKPg9
nZLtrVmOKAfUW1ejYjSeO9Rv05hOsGtPtdi70jw1b7WkUC7Ic8L4HzJE0zDzKwEk
ESVZiLX9G9b0O9CDQnKxRluuZDmVAgMBAAGjITAfMB0GA1UdDgQWBBT9cbSyt2cH
nN9RnC6o9TOoPH5QWTANBgkqhkiG9w0BAQ0FAAOCAgEAVMpgq3aTTv4v3ZmSJ1P6
jZBXX85IdnRUvadXX0HDgqpqs8k3Sm67C0UwpLQHeYw5t6ilSJocCw62pMCgfxwf
dmJ9VEcFoQSd30BdCMXNmPxAnQ+/INUBPzmcZwe+KlI07IQUsjoEPtRG9LBxwric
PifjxKzzVgOlPPb5XGNmVLdlncY9Z4v5McZPQx6+hG4CqNULEOrx/xRpQDTsGUem
AXR/ocHm7dDwUIQrkRPkbPK+urEtqKS+RL5ttQ4myzJWasCiDoAdlDv15X7u2G+i
E8rTSohtr4Crd4DbNpT11aQHtnympNJCAc7PyRLcQRV3FASXvDUsvwT4dMcPN+M1
ZR5oatbo9hxy/MPyhQun4awMRvaF7HSKrPI8XJRdJzzufusv662N6A7UX31i5W82
rnSxfP/haklNfwcBAQ0R3R/MkoURYanJYoHnr2WuAx0yfxNIYlJMX7hfPdWOW6a4
7nQQAkrgW3knQGlKwCEypjm0tdK0bsUrQ0F91wUUYSUSFuPDPb19ifKXklBoCVlB
6u3ckHu7LG/YZcHmtsxMRMuT+6LtIs/huFnfs4YhJYggswFJHjEX5PcBfsiQklz+
ahs+UsJAb+lbMOlWj+LYDdyC4T7ZHT+Ii/JZdBN3WNXiBzNuXGC7bd0KWBgCaFuU
ZAPV0YlmPjsGRaSl7vfh+cI=
-----END CERTIFICATE-----

View file

@ -0,0 +1,32 @@
-----BEGIN CERTIFICATE-----
MIIFezCCA2OgAwIBAgIEB0a3pTANBgkqhkiG9w0BAQ0FADBuMQswCQYDVQQGEwJY
WDELMAkGA1UECBMCWFgxCzAJBgNVBAcTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnlt
b3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEXMBUGA1UEAwwOc3RyNGRAbWFpbC5p
MnAwHhcNMTUwMTA0MDYxOTU3WhcNMjUwMTAzMDYxOTU3WjBuMQswCQYDVQQGEwJY
WDELMAkGA1UECBMCWFgxCzAJBgNVBAcTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnlt
b3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEXMBUGA1UEAwwOc3RyNGRAbWFpbC5p
MnAwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDGUObeKxkmQ+KOeASG
I4Hx0MJc2Q5PMvD7MWZxI/nFr2Rme83O1xxPUDfu2k0pRhbdkA4PaHkfBcfYD8Jj
+TFZlV2slnw6+jdlfbR8Ez2SH+ImPeLQ5moftDxB3H05LmC3fJ/BjRTWuAQsmury
ySKEH0v1L1eHJQ9OMQieSgLjNzld8UwofsuPqupYU3aVptoO1AkAnqbcjFb++QJ1
X+abt3xTocgFzCHIpkhBfmobWqy0w7HCg7Lr/Pm+PcLEAJfd51nqWeI+H9C38uzE
vqCjDohB8ux07gxS9D5ImPqFVzjWe4/dvc/FLl/ELpRGZphWcubPW8Grc7eAMGov
SRFCVpQnMF0Dx9+NoAvUTpZYuIe8zRtrn3Ifnnl687JQxS379cunZxr5eONDeFdS
Lf29VSI7FO0t+XNTEx9ThWEWFKk9Y5Q7BJGeR4IirvR7wOdje44Rz5jNEqNNZtaT
qlvPEmeVUrBIPMzvXaMi8llXN4FvA6LE9u8vwPE19HOj9Z4dwxgVJNJ07NfE2z85
qUX0BrTSZwS/vprFLrIfhzYv56xo4ImvDxDMc54+OJMnyZZSP/c1eI0dC7iCEBfq
uaLX8lIyklVB/8UwdS/J++rJNeRrPeujYuRVIW1uG8SIXnhLRoxfbhzS1aotiIsX
KZSJr4AppiYAxiQdvuLeXH/iFwIDAQABoyEwHzAdBgNVHQ4EFgQU0142G9eAgnVS
ij8nR1YS5OxM6GgwDQYJKoZIhvcNAQENBQADggIBABL/fL4xkx5IPwq0ptjV6O4l
ZkeqazPxzzqVrct87w96aDTu3Xq2VYL2lEAOH2sYHCUNXKKU4XlJCrOapXHM81OH
NPMwIftSAPLUHVkFRIcA/tsLCx9DXrvlHB3pgoyoa7tW/Kn+MwAq+VTvOH60n06z
e+InFh/Nic8rznbepszF6UUAsMioewxWEOD3sMa35SIYjG/doFCfU8dYpeknKKG0
OQzE6duv6vo0nhIZQAmzwYkmdkSsoKp75dCSJxgcZCk5gyn8zB2AYY+lrzI2JGGP
1UTS96fa/iJd74rDXVL5RVsLYbKzIe+qufUoGvq+aMedu0LJSoq2r6j6ebzdbLnP
SGflktZQEDmyvUbCt3b7V/PsSMICNoqh7oE4cYZ50supfKDPZJ2DBT6woEf3Zk9G
1jyiy1iYY/HbU80crjgiOoPLcCt6IXiwZT3mqfZx9WMPVVvmxAoDMV0LnP7hZHNI
KyDPsl6HXccM8gk4kwFDr5krfKz7IOVwKw+HAoWDYRqa0qx6ZBxhQpJsN9L58N49
aWsGANBHrZjOV1Rgt+C/tHsxeGm3WaqSGCiyOLiROaXmTiw9PaLEXfoFNibzSPXq
vth2u62pWqp3aYEEuoutZxf/zPiMLl5412tUkz1UAJt0YcCz+LWIPqeyUHijgWxj
wl3IpsPIn5zAcd9srrdy
-----END CERTIFICATE-----

View file

@ -0,0 +1,32 @@
-----BEGIN CERTIFICATE-----
MIIFkzCCA3ugAwIBAgIIefINnsa4ZtswDQYJKoZIhvcNAQENBQAwUzEeMBwGA1UE
BxMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQKEwNJMlAxDDAKBgNVBAsT
A0kyUDEVMBMGA1UEAwwMemFiQG1haWwuaTJwMB4XDTE5MDQwMzEzMTIzNVoXDTI5
MDQwMzEzMTIzNVowUzEeMBwGA1UEBxMVSTJQIEFub255bW91cyBOZXR3b3JrMQww
CgYDVQQKEwNJMlAxDDAKBgNVBAsTA0kyUDEVMBMGA1UEAwwMemFiQG1haWwuaTJw
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvkm0/e9w6iZT25A7AapZ
t6c2SdHZZrkVHOQXpgCfO5WzCbHyCKykXh1adxBU7YW1FQW1c/QrW7CPPN1qXmjB
S9bKv/VGoTkv/JA21eD4m887Ygtdmmm+EKgvRxa0spj7pqYj1Nuz2OYyYS4AxhJf
aNQG0Y4WMq+8+GK0eXF+DixsjZFDwFmKrsa7/Me9wO0W/eEhMoNSM9OVaZzFTrb5
Qes+2mAlRnd6vmHvA44aJM2aqxFpNHCIK3Pa6guj7mp4FCBq884HSHg4K2mA7esS
Ym47U1A6K6+Twwg8RtHpqUZ/HANk2rhlKyqynOvQSQvzuY6jujAL73++uJMRYF5h
nhVlzfmR3ijctl4WT1u49PkfhX+e0vqgloWKIO/Cg3x4OD8OJeZZI6kA42Q3vN4g
I3ZnxwbW8X4iPzF1LyTWMx6ABmEB4DBjlIk09TUYxt4grcUlYarOxfQkATyp+tMf
NjwvfWzU0766RVaIjvwA4zFSmzorRPSLEHwOc8SUz/ndTbZr88gt8ig5soEtsy+6
wGfKuxkvMrlcRRlJ0EVeRISeEZTV3cO7jo1Me7GgGk09aw0O701tzmnVJhqU0yi9
zxJeEoPWEazTPukk4qx/3p2pnQFp2z3tIphPuu/vMN+SZzOP0bvPtiepgDdJcRIf
WmZIHQ+mnyafplg8i+CLg6ECAwEAAaNrMGkwHQYDVR0OBBYEFHu2zaewzgpognLi
D8TJmXo5j47DMB8GA1UdIwQYMBaAFHu2zaewzgpognLiD8TJmXo5j47DMA4GA1Ud
DwEB/wQEAwIBpjAXBgNVHREEEDAOgQx6YWJAbWFpbC5pMnAwDQYJKoZIhvcNAQEN
BQADggIBABhISvTz6MJ/xqKklVxWrpWsbmtfCKewBQZBEVZLLwr2FEnC+CQl1wRT
yF5CwyOoz3MB+B2cmY8T45ffC9nVRf9AZzY9TyDFcJYkMFRGil1PrU1qjWK+MRh7
2R5KWrBZf709BmybcDZ8x6B2L94NivBjg7T+4B6bnkBkrZ6PQIsi2zbuM62uOF1v
xVLjwh3X7g4l6WmVubZFEOZ8QdPphhbCOrSufH6LFcKNVf5G52IaBSIvvOqPGzCl
2bYSCQ0q0QDkkVCJzfyupeX9ZBgNfKhx20r0oGcAMO55LEucqwDWNrcS5uvJpx+t
V+kNJUdgzZvNJfl5/2Y0FSqpZc0OOVq2b5vI7ZZmVOzo20NNjAg6Bme1Grwhbr4Z
ZuOmqHxxXpfVdIRVZ7iAVsBKTIMlo25MAYD+1BsN0uDq5K3kczqV8odMiAfVRkkX
E5xZgMsmjR9vn/nEpSMF5wT2IY0/w05hp9tnI1m8sPuu7wM9wPC/XXhxwa/8XFh4
lX29+kpi6W/WdnBFQfXX8f5bKDq2+q5MoSpz9s0WoIPWLDkQGPb9vs/Hw3vs8IJt
OdC6Uc1DawpGQhwiy0g+jmTjG8KSXCFeQv1u8q/yGIC2BAeor5y9HxsZq+6jvKtz
WNXTB3h5OC1YUiUOSvnvACeLSQSYc9qYM8yXM3TCJtX/tpEXrwNO
-----END CERTIFICATE-----

View file

@ -0,0 +1,32 @@
-----BEGIN CERTIFICATE-----
MIIFhTCCA22gAwIBAgIERiD+VDANBgkqhkiG9w0BAQ0FADBzMQswCQYDVQQGEwJY
WDELMAkGA1UECBMCWFgxCzAJBgNVBAcTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnlt
b3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEcMBoGA1UEAwwTenp6LXBsdWdpbkBt
YWlsLmkycDAeFw0xNDA4MDcyMTA0NDlaFw0yNDA4MDYyMTA0NDlaMHMxCzAJBgNV
BAYTAlhYMQswCQYDVQQIEwJYWDELMAkGA1UEBxMCWFgxHjAcBgNVBAoTFUkyUCBB
bm9ueW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMRwwGgYDVQQDDBN6enotcGx1
Z2luQG1haWwuaTJwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAzWRY
ZFGmPO3lOfD9vu5LFxmZchqEiT+QYyTU1FllIlppgb3dkAo7Tn8R1QcwyKkoJkYI
oFdUCYwUOhUmbKv5j6oBTmLlav/MQi2nM7dHfBVP3ubzZP7Z/zKGQUf1Ze7136Yh
l6Lfbl/wN3O7IIGs6NksSiq/hnDrAmZAQwfc7/dahPh4gxPRuK9Bg7NFPJyQ07vJ
FQC1I2uWb49WL/rzJnR20fSeJa/LJ5JnKnWG6RjbTKHp6wN2S0d389BkJvUCEmeT
o5JdV1xcrB4GY/z0gfmS8haZYeW3ySPKuaEOpZGrwLFaKnZGITegMrnVTTZD8RAk
SqvJC8+X8pdFN41I9tkwAK/FTtrNxVubPLfvzgQ2Z8WFtLPFWkbEYn58AnKWj59X
Zs1delvTF1vJHYSY6ZMmymnOBWmRSofXpByBzBCXVKMWZ8ah7BJKLkzGd2/XYeY/
mIRm+SghTjojUg2F3G26W/z67HoSWMunwor0ur2A/r8HMKWqhSzNdEOx9zzX7ihf
W3tUbI/E7BDWLs0sd6gmGMSYbxkrB2pM21X9UmpthDazo6CTC+nrNYRjSpDisOiV
gnu1fPmbfoa61pRoWAQOHVN+D5mDKeJW+WConOxRKuLY/aymeXwSKBcLLkYHasc/
ooJwSofj/SYooGR9aVJO2oEKYbpLu4fFduHIrrMCAwEAAaMhMB8wHQYDVR0OBBYE
FADW2hreviSWGPa+xSDnNpUO+ih2MA0GCSqGSIb3DQEBDQUAA4ICAQBePI57drix
BLUXhB4rAeyCUaA3hp40gzz5oQKijQF8Z+aP3j74NuCUMuPF0f62mPdq4Yrm/QM4
bdKTHtoOuvQyEtnsfRj241CppdzTeVtCMRcBmDUeejE0BjRYtmHOpV7Ylyf3olX+
IddPrkKshN+zy0TiNhwWrKG44C2JkmSqFQRicCm34+0dxINBUqv/+srmriBFesdg
74Z9EPpXRA1xpB0ud4GTq5NQDPby9mm6tXMrziomLtuG66emW7dtisQcmn59Te6E
8OSZrbRzTOshsyqsbyMXnEfLUMRu94WHQ+yJTQSXwAKeXZGfSuTMiiyGJ3bSEDwy
dCA7RW9QF58a6wVlW5s8xLZ+JxVx8QkyCkCsu7mFB6XJh3t8YZTMUC1EwH0Zy8y0
JQeAw9A+I/XILoRhtOISM0vPrw9/TrKkKg8FGPAIE+fSTt6y7X5BWBqIE38u0wi7
MyQZjmAhVz9nBkX6iggY9js/7Ix4LkCk6ERQoQxA0RWXcPX9LzBmisxL3nb86eYo
o9f2fFtK9ErU7ZiYkb32U8/Jd205rrqWOxBhvQAcOqPsxVH5USi1I2gs912NVkXB
dbb9dlEDIwiP+6E0EtEW/PodF8hzptbg8fjhu2G7l3f/ZLgBOvnyTJFHrgpRX7ce
rK4SWkfGugRmgkD8S2Us0V1llpclJ6Baiw==
-----END CERTIFICATE-----

View file

@ -0,0 +1,35 @@
-----BEGIN CERTIFICATE-----
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
Hz8KWVkHZg==
-----END CERTIFICATE-----

View file

@ -0,0 +1,32 @@
-----BEGIN CERTIFICATE-----
MIIFfzCCA2egAwIBAgIESg3kkzANBgkqhkiG9w0BAQ0FADBwMQswCQYDVQQGEwJY
WDELMAkGA1UECBMCWFgxCzAJBgNVBAcTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnlt
b3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEZMBcGA1UEAwwQZWNoZWxvbkBtYWls
LmkycDAeFw0xNDA3MzExNjQ3MDJaFw0yNDA3MzAxNjQ3MDJaMHAxCzAJBgNVBAYT
AlhYMQswCQYDVQQIEwJYWDELMAkGA1UEBxMCWFgxHjAcBgNVBAoTFUkyUCBBbm9u
eW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMRkwFwYDVQQDDBBlY2hlbG9uQG1h
aWwuaTJwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAmcEgLwwhzLNe
XLOMSrhwB8hWpOhfjo4s6S/wjBtjjUc8nI3D0hSn3HY26p0rvcvNEWexPUpPULmC
exGkU463nu7PiFONiORI1eJAiUFHibRiaA7Wboyo38pO73KirwjG07Y+Ua0jp+HS
+4FQ/I/9H/bPplReTOU/6hmRbgQ69U8nE68HzZHQxP68yVJ2rPHSXMPhF4R1h0G1
1mCAT+TgTsnwHNGF77XHJnY4/M4e2cgycEZjZow36C3t2mNDVkMgF19QQeb9WmLR
zREn3nq9BJqHpUkn9yWw0kKXTZSds+7UxESfzf3BzK0+hky2fh5H+qbYAo2lz4yj
81MXTAu+4RRkg4DBLlF+2dkclhwQLxxzvkRC6tPkn5i33Yltg7EfzA9IoQ05potJ
I+iOcF+aStfFgFj9u3B5UkcF4P0cH1QD3c6BK4hIezQYqRoPly1gHqg+XdwjG/dr
4as7HA9FTz3p2E8nClpIC1x3hfgwAdfd29aeBxO1WW/z99iMF7TBAF+u5T86XEW1
WpknqCbTli36yJ8a5fPWxZHrryBRJT5yLxejjFeadtutBSwljiVFq+Y38VqwFivq
VLiBt7IxAsZ8iilgfnnnAvBH6chWfSKb4H7kB4TJvDiV96QmmvoEaWYNHZozMhyK
tO3b5w+xqbJXyCLA3Q75jD0km76hjcECAwEAAaMhMB8wHQYDVR0OBBYEFAHQcAam
QRS/EUhuCSr9pB4Ux0rYMA0GCSqGSIb3DQEBDQUAA4ICAQBq1+1QLmgLAjrTg3tb
4XKgAVICQRoBDNUEobQg3pYeUX9eFNya2RxNljuvYpwT80ilGMPOXcjddmr5ngiK
dbGRcuuJk9MPEHtPaPT3+JJlvKQ3B3g2wva2Wz2OAyLZUGQs389K4nTbwh4QF0n2
aHFL8BHiD62hiKnCoNaW4ZovUNNvOxo9lMyAiaFU2gqQNcdad8hP9EAllbvbxDx9
Tjww2UbwQUIHS9rna4Tlu+f0hDXTWIutc2A51W2fJCb7L3+lYO7Wv55ND/WtryLZ
XpMp27+MpuEnN3kQmz/l9R0hIJsWc/x9GQkjm5wEaIZEyTtenqwRKGmVCtAj0Pgv
jn1L3/lWmrNq+OZHb/QeyfKtA3nXfQKVmT98ewQiK/S5i1xIAXCJPytOD887b/o1
cdurTmCiZMwgiQ+HLJqCg3MDa5mvKqRkRdZXfE6aQWEcSbpAhpV15R17q7L+Fg0W
shLSNucxyGNU8PjiC/nOmqfqUiPiMltJjPmscxBLim8foyxjakC4+6N6m+Jzgznj
PocBehFAfKYj66XEwzIBN7Z2uuXoYH9YptkocFjTzvchcryVulDWZ4FWxreUMhpM
4oyjjhSB4tB9clXlwMqg577q3D6Ms0zLTqsztyPN3zr6jGev3jpVq7Q1GOlciHPv
JNJOWTH/Vas1W6XlwGcOOAARTQ==
-----END CERTIFICATE-----

View file

@ -0,0 +1,34 @@
-----BEGIN CERTIFICATE-----
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
CCOJyu3XtyzFf+tAeixOnuQ=
-----END CERTIFICATE-----

View file

@ -0,0 +1,33 @@
-----BEGIN CERTIFICATE-----
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
-----END CERTIFICATE-----

View file

@ -0,0 +1,33 @@
-----BEGIN CERTIFICATE-----
MIIFvjCCA6agAwIBAgIQIDtv8tGMh0FyB2w5XjfZxTANBgkqhkiG9w0BAQsFADBt
MQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYDVQQK
ExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEWMBQGA1UEAwwN
aWdvckBub3ZnLm5ldDAeFw0xNzA3MjQxODI4NThaFw0yNzA3MjQxODI4NThaMG0x
CzAJBgNVBAYTAlhYMQswCQYDVQQHEwJYWDELMAkGA1UECRMCWFgxHjAcBgNVBAoT
FUkyUCBBbm9ueW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMRYwFAYDVQQDDA1p
Z29yQG5vdmcubmV0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxst4
cam3YibBtQHGPCPX13uRQti56U3XZytSZntaKrUFmJxjt41Q/mOy3KYo+lBvhfDF
x3tWKjgP9LJOJ28zvddFhZVNxqZRjcnAoPuSOVCw88g01D9OAasKF11hCfdxZP6h
vGm8WCnjD8KPcYFxJC4HJUiFeProAwuTzEAESTRk4CAQe3Ie91JspuqoLUc5Qxlm
w5QpjnjfZY4kaVHmZDKGIZDgNIt5v85bu4pWwZ6O+o90xQqjxvjyz/xccIec3sHw
MHJ8h8ZKMokCKEJTaRWBvdeNXki7nf3gUy/3GjYQlzo0Nxk/Hw4svPcA+eL0AYiy
Jn83bIB5VToW2zYUdV4u3qHeAhEg8Y7HI0kKcSUGm9AQXzbzP8YCHxi0sbb0GAJy
f1Xf3XzoPfT64giD8ReUHhwKpyMB6uvG/NfWSZAzeAO/NT7DAwXpKIVQdkVdqy8b
mvHvjf9/kWKOirA2Nygf3r79Vbg2mqbYC/b63XI9hheU689+O7qyhTEhNz+11X0d
Zax7UPrLrwOeB9TNfEnztsmrHNdv2n+KcOO2o11Wvz2nHP9g+dgwoZSD1ZEpFzWP
0sD5knKLwAL/64qLlAQ1feqW7hMr80IADcKjLSODkIDIIGm0ksXqEzTjz1JzbRDq
jUjq7EAlkw3G69rv1gHxIntllJRQidAqecyWHOMCAwEAAaNaMFgwDgYDVR0PAQH/
BAQDAgKEMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNVHRMBAf8E
BTADAQH/MBYGA1UdDgQPBA1pZ29yQG5vdmcubmV0MA0GCSqGSIb3DQEBCwUAA4IC
AQADyPaec28qc1HQtAV5dscJr47k92RTfvan+GEgIwyQDHZQm38eyTb05xipQCdk
5ruUDFXLB5qXXFJKUbQM6IpaktmWDJqk4Zn+1nGbtFEbKgrF55pd63+NQer5QW9o
3+dGj0eZJa3HX5EBkd2r7j2LFuB6uxv3r/xiTeHaaflCnsmyDLfb7axvYhyEzHQS
AUi1bR+ln+dXewdtuojqc1+YmVGDgzWZK2T0oOz2E21CpZUDiP3wv9QfMaotLEal
zECnbhS++q889inN3GB4kIoN6WpPpeYtTV+/r7FLv9+KUOV1s2z6mxIqC5wBFhZs
0Sr1kVo8hB/EW/YYhDp99LoAOjIO6nn1h+qttfzBYr6C16j+8lGK2A12REJ4LiUQ
cQI/0zTjt2C8Ns6ueNzMLQN1Mvmlg1Z8wIB7Az7jsIbY2zFJ0M5qR5VJveTj33K4
4WSbC/zMWOBYHTVBvGmc6JGhu5ZUTZ+mWP7QfimGu+tdhvtrybFjE9ROIE/4yFr6
GkxEyt0UY87TeKXJ/3KygvkMwdvqGWiZhItb807iy99+cySujtbGfF2ZXYGjBXVW
dJOVRbyGQkHh6lrWHQM4ntBv4x+5QA+OAan5PBF3tcDx1vefPx+asYslbOXpzII5
qhvoQxuRs6j5jsVFG6RdsKNeQAt87Mb2u2zK2ZakMdyD1w==
-----END CERTIFICATE-----

View file

@ -0,0 +1,34 @@
-----BEGIN CERTIFICATE-----
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
+g==
-----END CERTIFICATE-----

View file

@ -0,0 +1,34 @@
-----BEGIN CERTIFICATE-----
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
LD8d2z2Lgg==
-----END CERTIFICATE-----

View file

@ -0,0 +1,32 @@
-----BEGIN CERTIFICATE-----
MIIFfzCCA2egAwIBAgIESg3kkzANBgkqhkiG9w0BAQ0FADBwMQswCQYDVQQGEwJY
WDELMAkGA1UECBMCWFgxCzAJBgNVBAcTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnlt
b3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEZMBcGA1UEAwwQZWNoZWxvbkBtYWls
LmkycDAeFw0xNDA3MzExNjQ3MDJaFw0yNDA3MzAxNjQ3MDJaMHAxCzAJBgNVBAYT
AlhYMQswCQYDVQQIEwJYWDELMAkGA1UEBxMCWFgxHjAcBgNVBAoTFUkyUCBBbm9u
eW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMRkwFwYDVQQDDBBlY2hlbG9uQG1h
aWwuaTJwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAmcEgLwwhzLNe
XLOMSrhwB8hWpOhfjo4s6S/wjBtjjUc8nI3D0hSn3HY26p0rvcvNEWexPUpPULmC
exGkU463nu7PiFONiORI1eJAiUFHibRiaA7Wboyo38pO73KirwjG07Y+Ua0jp+HS
+4FQ/I/9H/bPplReTOU/6hmRbgQ69U8nE68HzZHQxP68yVJ2rPHSXMPhF4R1h0G1
1mCAT+TgTsnwHNGF77XHJnY4/M4e2cgycEZjZow36C3t2mNDVkMgF19QQeb9WmLR
zREn3nq9BJqHpUkn9yWw0kKXTZSds+7UxESfzf3BzK0+hky2fh5H+qbYAo2lz4yj
81MXTAu+4RRkg4DBLlF+2dkclhwQLxxzvkRC6tPkn5i33Yltg7EfzA9IoQ05potJ
I+iOcF+aStfFgFj9u3B5UkcF4P0cH1QD3c6BK4hIezQYqRoPly1gHqg+XdwjG/dr
4as7HA9FTz3p2E8nClpIC1x3hfgwAdfd29aeBxO1WW/z99iMF7TBAF+u5T86XEW1
WpknqCbTli36yJ8a5fPWxZHrryBRJT5yLxejjFeadtutBSwljiVFq+Y38VqwFivq
VLiBt7IxAsZ8iilgfnnnAvBH6chWfSKb4H7kB4TJvDiV96QmmvoEaWYNHZozMhyK
tO3b5w+xqbJXyCLA3Q75jD0km76hjcECAwEAAaMhMB8wHQYDVR0OBBYEFAHQcAam
QRS/EUhuCSr9pB4Ux0rYMA0GCSqGSIb3DQEBDQUAA4ICAQBq1+1QLmgLAjrTg3tb
4XKgAVICQRoBDNUEobQg3pYeUX9eFNya2RxNljuvYpwT80ilGMPOXcjddmr5ngiK
dbGRcuuJk9MPEHtPaPT3+JJlvKQ3B3g2wva2Wz2OAyLZUGQs389K4nTbwh4QF0n2
aHFL8BHiD62hiKnCoNaW4ZovUNNvOxo9lMyAiaFU2gqQNcdad8hP9EAllbvbxDx9
Tjww2UbwQUIHS9rna4Tlu+f0hDXTWIutc2A51W2fJCb7L3+lYO7Wv55ND/WtryLZ
XpMp27+MpuEnN3kQmz/l9R0hIJsWc/x9GQkjm5wEaIZEyTtenqwRKGmVCtAj0Pgv
jn1L3/lWmrNq+OZHb/QeyfKtA3nXfQKVmT98ewQiK/S5i1xIAXCJPytOD887b/o1
cdurTmCiZMwgiQ+HLJqCg3MDa5mvKqRkRdZXfE6aQWEcSbpAhpV15R17q7L+Fg0W
shLSNucxyGNU8PjiC/nOmqfqUiPiMltJjPmscxBLim8foyxjakC4+6N6m+Jzgznj
PocBehFAfKYj66XEwzIBN7Z2uuXoYH9YptkocFjTzvchcryVulDWZ4FWxreUMhpM
4oyjjhSB4tB9clXlwMqg577q3D6Ms0zLTqsztyPN3zr6jGev3jpVq7Q1GOlciHPv
JNJOWTH/Vas1W6XlwGcOOAARTQ==
-----END CERTIFICATE-----

View file

@ -0,0 +1,33 @@
-----BEGIN CERTIFICATE-----
MIIFtTCCA52gAwIBAgIJXecLH1IN9PiFMA0GCSqGSIb3DQEBDQUAMF4xHjAcBgNV
BAcTFUkyUCBBbm9ueW1vdXMgTmV0d29yazEMMAoGA1UEChMDSTJQMQwwCgYDVQQL
EwNJMlAxIDAeBgNVBAMMF2hhbmtoaWxsMTk1ODBAZ21haWwuY29tMB4XDTE5MDUw
NTIyMzcwNFoXDTI5MDUwNTIyMzcwNFowXjEeMBwGA1UEBxMVSTJQIEFub255bW91
cyBOZXR3b3JrMQwwCgYDVQQKEwNJMlAxDDAKBgNVBAsTA0kyUDEgMB4GA1UEAwwX
aGFua2hpbGwxOTU4MEBnbWFpbC5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
ggIKAoICAQCi+KYA++ZxEswy1pJz3mZgSBtASzgatj5GqA9WwfKsuUNfJbLgTzkP
+TQBGkRwPKdwqqJeMxau3IvCzDSfxnUn7CX5V2kliGqyfHG0vMku0YuOT7iQzdgk
sxu3nrDmVNCSe8ngQYW9D5jnGXkgQxLVtJz1nKMJdWZqiNoPHUemwDP2hSmsUs4P
5wb1tl43WYRQ5Kmrc2PoZC45YZe3qqsdR1BVg9MmuUCCFaemjG0ZgSYJDR32qCm2
LjKkdzSu1QAboc+Ck0XgSXD+NUNefTxLHeJkjAXNRXsZdIl8Rt5ExtFoXbJH19Un
1y4qUkpqQzErYLKV/o1YM6IaJlCmnlSI2V5oY/Naa4T/JMx0XAmitcXOn5Y8zGGn
o09CKkJN4oe+dHI/hPi24Smm8OW6W8vQMHLRFUnCKXK7VbTzh96habE83GgEYbV/
xiNI/8NbSA2q76rwMjCHO62yxQvrFziQPsQzuSEguZc9KtXkT2dd2RECgIO8nPcE
cu1VEDx4J+lk95RIOkpbYgux2fwNSefuGCpARU0aryq6w+YaKPngSCaBNRvQ+CtR
WqIExdl3TzzKkhn9CBc3urdryy09QVr19VdDSpZw0BnJc2B60lftFONerD7BirmK
W5KhirzkoO0H1AncaVFfe8wkY6emksT/vP64dyfBC2R6eOnF0DXuQwIDAQABo3Yw
dDAdBgNVHQ4EFgQU6gvVvoomCNtBD46pDGlPJC5knNswHwYDVR0jBBgwFoAU6gvV
voomCNtBD46pDGlPJC5knNswDgYDVR0PAQH/BAQDAgGmMCIGA1UdEQQbMBmBF2hh
bmtoaWxsMTk1ODBAZ21haWwuY29tMA0GCSqGSIb3DQEBDQUAA4ICAQAKbEh8eDlu
PDPzH44mFQFqvuYTcUasGSmHfxQrqsv+48LE7UMVxDAge4OjcfVUP2PO4PQeBllw
jcqSh/xvbgUgI0WrwhdWliXqGNP1BlJGv8U+8UIqzeVzhsYmu+U9FHbfnXoPsp7G
ikPENCQCCvRpx6trgiYZT4Mmpd7KG67dZSnMQ/3bJLGtqrshXAbyUqZNcS5rlJoM
5R8AHYyfkjvzcnzQ1GBi4qE52EVdRHka/fJwt1/q5rp5nxFGSi20iMnYgwyanyYJ
v08O82/feouxskiGflc3oAxwnSYvPI36nAsLKsoaDJ5WShGH+R2R8HepvVmIe7iw
TRD0uWx0afHuUpAqEOET03MDYoXC9LpqNTOWeV2EjAGOzvLbc9c69PbI71O8lJGz
oEpn/sWeqg1uS1VwmvjgLT4gGldFm8ySDvXSU/G4PLGRyDMXHPgCyLgB4ZU19Zzi
Srw9hxHhORp6eOzdbdW+etzzlcsxzF0bU2GPyBkr1oYAMtubFBdW3tESBpBF5OJb
9edvOhB464O0AuCK6rzqH/KxKnk48HdHJwkAP8aByTZk5V8joD1kXly49gFXhcYi
s0s6mdAsX05ppXjNGYbEw4mEcxtGCFy+hcmqG63Q5US/eFjtnzs9Xsms+WqLzlnH
gn3ZOT24+I02rwRjjwRLgNbgbieebWM5NA==
-----END CERTIFICATE-----

View file

@ -0,0 +1,33 @@
-----BEGIN CERTIFICATE-----
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
-----END CERTIFICATE-----

View file

@ -0,0 +1,24 @@
-----BEGIN CERTIFICATE-----
MIIEAzCCAuugAwIBAgIJAJzD01zwSBKsMA0GCSqGSIb3DQEBCwUAMIGWMQswCQYD
VQQGEwJERTEQMA4GA1UECAwHR2VybWFueTESMBAGA1UEBwwJRnJhbmtmdXJ0MQww
CgYDVQQKDANJMlAxDzANBgNVBAsMBnJlc2VlZDEeMBwGA1UEAwwVcmVzZWVkLmky
cC1wcm9qZWt0LmRlMSIwIAYJKoZIhvcNAQkBFhNlY2hlbG9uQGkycG1haWwub3Jn
MCAXDTE3MDIxMTE5MTUyNloYDzIwNTAxMTMwMTkxNTI2WjCBljELMAkGA1UEBhMC
REUxEDAOBgNVBAgMB0dlcm1hbnkxEjAQBgNVBAcMCUZyYW5rZnVydDEMMAoGA1UE
CgwDSTJQMQ8wDQYDVQQLDAZyZXNlZWQxHjAcBgNVBAMMFXJlc2VlZC5pMnAtcHJv
amVrdC5kZTEiMCAGCSqGSIb3DQEJARYTZWNoZWxvbkBpMnBtYWlsLm9yZzCCASIw
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALX9QXseJD1t0FeAK4YysZaIx1mv
uOnpFjmTeR06perdAX/2N7sKyJpcTo1CCEaDf5CxADAIr6Bt9IkCfvLYQRIV8TM/
bVF7W52sW8PyHC2jEx/s28hp4UtYasPISt+QYT9ByOgcV02/InGE9FwnXi6mvKvv
0VeC71OiMBT/I9Z5Z+VknapdM9D+kYXT3+pjjneSxn2XZ7kfnegydQ0J63nrGOi7
Lj4Syj84GtPc0Bgv4QLvmB+70X2Qr/X1TZt7QuxqFh0StgdQU1pT4r9PRgzcA4FN
NScPbcPUycmvBptbel31z2s7jos9AnGeWvVd63y8bbRpVzGft51yZtcUDo8CAwEA
AaNQME4wHQYDVR0OBBYEFLzp7fVErgTYTMqLdh8uHlr3kDDYMB8GA1UdIwQYMBaA
FLzp7fVErgTYTMqLdh8uHlr3kDDYMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEL
BQADggEBAKz+q73JpbqNjjXtg2/A+AXoOOhLd6Qah8a2AtiB/H2RevWem/09J1sb
VIkW4/YT6GLGg8UbHJLzlQxs8Apk2J0ebWTeQZOvy07tADKMrItrKyEY/HZk7d2L
7Dnz0QJ/JoJJBmjqQxFtZ2um0FyoT/bvxg03pJv0ZCQWTNpZcez0jHqMTdN1DqSJ
2oN163rHrINyCGGAlm1x1O/SKRWA4bD7CBBasarilYb3gbjSVZiuSF9zw8zl0KRh
AH0AqQ2sOSoyY/t5d03YEKMwzM9yQ9MZ0mB34TgiqgRJmKH4nSep0ARqp14oeagA
pZjtThe6YgidpmH1UXFYbRzHxU4NYCk=
-----END CERTIFICATE-----

View file

@ -0,0 +1,16 @@
-----BEGIN CERTIFICATE-----
MIICkDCCAhWgAwIBAgIRAMhQCy2Tr8yJROCbIMWY1ucwCgYIKoZIzj0EAwQwejEL
MAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYDVQQJEwJYWDEeMBwGA1UEChMV
STJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxIzAhBgNVBAMTGmky
cHNlZWQuY3JlYXRpdmVjb3dwYXQubmV0MB4XDTE3MDUyNjE5NDQzMFoXDTIyMDUy
NTE5NDQzMFowejELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYDVQQJEwJY
WDEeMBwGA1UEChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAx
IzAhBgNVBAMTGmkycHNlZWQuY3JlYXRpdmVjb3dwYXQubmV0MHYwEAYHKoZIzj0C
AQYFK4EEACIDYgAEK2UzxGNMwqY4DUSE8O1wqyBGi8x2eZ/OX0+RFz3BUZ2RQUsB
Lwni0DZ4SvQZdxJHbbikRyM/QpcLPBdQZOcOSI6L3qxguyfzgb+EnyOcTZh/xg8S
4R1ltrCqBribBYKRo18wXTAOBgNVHQ8BAf8EBAMCAqQwEwYDVR0lBAwwCgYIKwYB
BQUHAwEwDwYDVR0TAQH/BAUwAwEB/zAlBgNVHREEHjAcghppMnBzZWVkLmNyZWF0
aXZlY293cGF0Lm5ldDAKBggqhkjOPQQDBANpADBmAjEAmgPDIN5HLpz3dJ8/QnUr
rd8KSBRzneZDnQA2qcptlp+wjpm1rtpb2bG2SKwk0LKXAjEAkdHzbkw0C0hoawIU
UX7CUhwIXQDhNe09fF4G0sHBS6xcCVWjfz3y7ktQ1+B+7vJL
-----END CERTIFICATE-----

View file

@ -0,0 +1,31 @@
-----BEGIN CERTIFICATE-----
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
-----END CERTIFICATE-----

1
j4-i2p-rs Submodule

@ -0,0 +1 @@
Subproject commit 76f6ee1ff79bd2f9096d91e393dcd8c28968ca3d

View file

@ -14,6 +14,7 @@ diqwest = "1.1.1"
env_logger = "0.10.0" env_logger = "0.10.0"
hex = "0.4.3" hex = "0.4.3"
hmac = "0.12.1" hmac = "0.12.1"
j4-i2p-rs = { path = "../j4-i2p-rs", version = "0.2.0-alpha" }
jwt = "0.16.0" jwt = "0.16.0"
lazy_static = "1.4.0" lazy_static = "1.4.0"
kn0sys-lmdb-rs = "0.1.2" kn0sys-lmdb-rs = "0.1.2"

View file

@ -2,7 +2,7 @@
use crate::{ use crate::{
args, args,
db, db::{self, DATABASE_LOCK},
models::*, models::*,
monero, monero,
reqres, reqres,
@ -47,21 +47,19 @@ pub fn create(address: &String) -> Result<Authorization, MdbError> {
token, token,
xmr_address: String::from(address), xmr_address: String::from(address),
}; };
let s = db::DatabaseEnvironment::open()?;
debug!("insert auth: {:?}", &new_auth); debug!("insert auth: {:?}", &new_auth);
let k = &new_auth.aid.as_bytes(); let k = &new_auth.aid.as_bytes();
let v = bincode::serialize(&new_auth).unwrap_or_default(); let v = bincode::serialize(&new_auth).unwrap_or_default();
db::write_chunks(&s.env, &s.handle?, k, &v)?; let db = &DATABASE_LOCK;
db::write_chunks(&db.env, &db.handle, k, &v)?;
Ok(new_auth) Ok(new_auth)
} }
/// Authorization lookup for recurring requests /// Authorization lookup for recurring requests
pub fn find(aid: &String) -> Result<Authorization, MdbError> { pub fn find(aid: &String) -> Result<Authorization, MdbError> {
info!("searching for auth: {}", aid); info!("searching for auth: {}", aid);
let db = &DATABASE_LOCK;
let s = db::DatabaseEnvironment::open()?; let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &aid.as_bytes().to_vec())?;
let r = db::DatabaseEnvironment::read(&s.env, &s.handle?, &aid.as_bytes().to_vec())?;
if r.is_empty() { if r.is_empty() {
return Err(MdbError::NotFound); return Err(MdbError::NotFound);
} }
@ -81,13 +79,11 @@ fn update_expiration(f_auth: &Authorization, address: &String) -> Result<Authori
data, data,
create_token(String::from(address), time), create_token(String::from(address), time),
); );
let db = &DATABASE_LOCK;
let s = db::DatabaseEnvironment::open()?; let _ = db::DatabaseEnvironment::delete(&db.env, &db.handle, &u_auth.aid.as_bytes().to_vec())?;
let _ = db::DatabaseEnvironment::delete(&s.env, &s.handle?, &u_auth.aid.as_bytes().to_vec())?;
let k = u_auth.aid.as_bytes(); let k = u_auth.aid.as_bytes();
let v = bincode::serialize(&u_auth).unwrap_or_default(); let v = bincode::serialize(&u_auth).unwrap_or_default();
let s = db::DatabaseEnvironment::open()?; db::write_chunks(&db.env, &db.handle, k, &v)?;
db::write_chunks(&s.env, &s.handle?, k, &v)?;
Ok(u_auth) Ok(u_auth)
} }
@ -124,12 +120,10 @@ pub async fn verify_login(aid: String, uid: String, signature: String) -> Result
let u: User = user::create(&address)?; let u: User = user::create(&address)?;
// update auth with uid // update auth with uid
let u_auth = Authorization::update_uid(f_auth, String::from(&u.uid)); let u_auth = Authorization::update_uid(f_auth, String::from(&u.uid));
let db = &DATABASE_LOCK;
let s = db::DatabaseEnvironment::open()?; let _ = db::DatabaseEnvironment::delete(&db.env, &db.handle, &u_auth.aid.as_bytes())?;
let _ = db::DatabaseEnvironment::delete(&s.env, &s.handle?, &u_auth.aid.as_bytes())?;
let v = bincode::serialize(&u_auth).unwrap_or_default(); let v = bincode::serialize(&u_auth).unwrap_or_default();
let s = db::DatabaseEnvironment::open()?; db::write_chunks(&db.env, &db.handle, u_auth.aid.as_bytes(), &v)?;
db::write_chunks(&s.env, &s.handle?, u_auth.aid.as_bytes(), &v)?;
monero::close_wallet(&wallet_name, &wallet_password).await; monero::close_wallet(&wallet_name, &wallet_password).await;
Ok(u_auth) Ok(u_auth)
} else if !f_user.xmr_address.is_empty() { } else if !f_user.xmr_address.is_empty() {
@ -284,14 +278,14 @@ mod tests {
fn find_test_auth(k: &String) -> Result<Authorization, MdbError> { fn find_test_auth(k: &String) -> Result<Authorization, MdbError> {
let s: db::Interface = db::DatabaseEnvironment::open()?; let s: db::Interface = db::DatabaseEnvironment::open()?;
let v = db::DatabaseEnvironment::read(&s.env, &s.handle, &k.as_bytes().to_vec())?; let v = db::DatabaseEnvironment::read(&db.env, &s.handle, &k.as_bytes().to_vec())?;
let result: Authorization = bincode::deserialize(&v[..]).unwrap_or_default(); let result: Authorization = bincode::deserialize(&v[..]).unwrap_or_default();
Ok(result) Ok(result)
} }
fn cleanup(k: &String) -> Result<(), MdbError>{ fn cleanup(k: &String) -> Result<(), MdbError>{
let s = db::DatabaseEnvironment::open()?; let db = &DATABASE_LOCK;
let _ = db::DatabaseEnvironment::delete(&s.env, &s.handle?, k.as_bytes())?; let _ = db::DatabaseEnvironment::delete(&db.env, &db.handle, k.as_bytes())?;
Ok(()) Ok(())
} }

View file

@ -1,7 +1,7 @@
//! contact operations module //! contact operations module
use crate::{ use crate::{
db, error::NevekoError, i2p, models::*, monero, reqres, utils db::{self, DATABASE_LOCK}, error::NevekoError, i2p, models::*, monero, reqres, utils
}; };
use kn0sys_lmdb_rs::MdbError; use kn0sys_lmdb_rs::MdbError;
use log::{ use log::{
@ -34,17 +34,15 @@ pub async fn create(c: &Json<Contact>) -> Result<Contact, MdbError> {
return Ok(Default::default()); return Ok(Default::default());
} }
debug!("insert contact: {:?}", &new_contact); debug!("insert contact: {:?}", &new_contact);
let db = &DATABASE_LOCK;
let s = db::DatabaseEnvironment::open()?;
let k = &new_contact.cid; let k = &new_contact.cid;
let v = bincode::serialize(&new_contact).unwrap_or_default(); let v = bincode::serialize(&new_contact).unwrap_or_default();
db::write_chunks(&s.env, &s.handle?, k.as_bytes(), &v)?; db::write_chunks(&db.env, &db.handle, k.as_bytes(), &v)?;
// in order to retrieve all contact, write keys to with cl // in order to retrieve all contact, write keys to with cl
let list_key = crate::CONTACT_LIST_DB_KEY; let list_key = crate::CONTACT_LIST_DB_KEY;
let str_lk = String::from(list_key); let str_lk = String::from(list_key);
let s = db::DatabaseEnvironment::open()?;
let lk_bytes = str_lk.as_bytes(); let lk_bytes = str_lk.as_bytes();
let r = db::DatabaseEnvironment::read(&s.env, &s.handle?, &lk_bytes.to_vec())?; let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &lk_bytes.to_vec())?;
if r.is_empty() { if r.is_empty() {
debug!("creating contact index"); debug!("creating contact index");
} }
@ -54,16 +52,15 @@ pub async fn create(c: &Json<Contact>) -> Result<Contact, MdbError> {
"writing contact index {} for key {}", "writing contact index {} for key {}",
contact_list, list_key contact_list, list_key
); );
let s = db::DatabaseEnvironment::open()?;
db::write_chunks(&s.env, &s.handle?, list_key.as_bytes(), &contact_list.as_bytes())?; db::write_chunks(&db.env, &db.handle, list_key.as_bytes(), &contact_list.as_bytes())?;
Ok(new_contact) Ok(new_contact)
} }
/// Contact lookup /// Contact lookup
pub fn find(cid: &String) -> Result<Contact, MdbError> { pub fn find(cid: &String) -> Result<Contact, MdbError> {
let db = &DATABASE_LOCK;
let s = db::DatabaseEnvironment::open()?; let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &cid.as_bytes().to_vec())?;
let r = db::DatabaseEnvironment::read(&s.env, &s.handle?, &cid.as_bytes().to_vec())?;
if r.is_empty() { if r.is_empty() {
error!("contact not found"); error!("contact not found");
return Err(MdbError::NotFound); return Err(MdbError::NotFound);
@ -85,25 +82,22 @@ pub fn find_by_i2p_address(i2p_address: &String) -> Result<Contact , NevekoError
/// Contact deletion /// Contact deletion
pub fn delete(cid: &String) -> Result<(), MdbError> { pub fn delete(cid: &String) -> Result<(), MdbError> {
let db = &DATABASE_LOCK;
let s = db::DatabaseEnvironment::open()?; let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &cid.as_bytes().to_vec())?;
let r = db::DatabaseEnvironment::read(&s.env, &s.handle?, &cid.as_bytes().to_vec())?;
if r.is_empty() { if r.is_empty() {
error!("contact not found"); error!("contact not found");
return Err(MdbError::NotFound); return Err(MdbError::NotFound);
} }
let s = db::DatabaseEnvironment::open()?; let _ = db::DatabaseEnvironment::delete(&db.env, &db.handle, cid.as_bytes())?;
let _ = db::DatabaseEnvironment::delete(&s.env, &s.handle?, cid.as_bytes())?;
Ok(()) Ok(())
} }
/// All contact lookup /// All contact lookup
pub fn find_all() -> Result<Vec<Contact>, MdbError> { pub fn find_all() -> Result<Vec<Contact>, MdbError> {
info!("looking up all contacts"); info!("looking up all contacts");
let db = &DATABASE_LOCK;
let s = db::DatabaseEnvironment::open()?;
let list_key = crate::CONTACT_LIST_DB_KEY; let list_key = crate::CONTACT_LIST_DB_KEY;
let r = db::DatabaseEnvironment::read(&s.env, &s.handle?, &list_key.as_bytes().to_vec())?; let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &list_key.as_bytes().to_vec())?;
if r.is_empty() { if r.is_empty() {
error!("contact index not found"); error!("contact index not found");
return Err(MdbError::NotFound); return Err(MdbError::NotFound);
@ -138,9 +132,8 @@ async fn validate_contact(j: &Json<Contact>) -> bool {
/// Send our information /// Send our information
pub async fn share() -> Result<Contact, NevekoError> { pub async fn share() -> Result<Contact, NevekoError> {
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?; let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &NEVEKO_VENDOR_ENABLED.as_bytes().to_vec())
let r = db::DatabaseEnvironment::read(&s.env, handle, &NEVEKO_VENDOR_ENABLED.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
let str_r: String = bincode::deserialize(&r[..]).unwrap_or_default(); let str_r: String = bincode::deserialize(&r[..]).unwrap_or_default();
let is_vendor = str_r == NEVEKO_VENDOR_MODE_ON; let is_vendor = str_r == NEVEKO_VENDOR_MODE_ON;
@ -229,9 +222,8 @@ mod tests {
use super::*; use super::*;
fn cleanup(k: &String) { fn cleanup(k: &String) {
let db = &DATABASE_LOCK;
let s = db::DatabaseEnvironment::open(); let _ = db::DatabaseEnvironment::delete(&db.env, &s.handle, k)?;
let _ = db::DatabaseEnvironment::delete(&s.env, &s.handle, k)?;
} }
#[test] #[test]
@ -272,9 +264,9 @@ mod tests {
..Default::default() ..Default::default()
}; };
tokio::spawn(async move { tokio::spawn(async move {
let s = db::DatabaseEnvironment::open().unwrap(); let db = &DATABASE_LOCK;
let v = bincode::serialize(&expected_contact).unwrap_or_default(); let v = bincode::serialize(&expected_contact).unwrap_or_default();
db::write_chunks(&s.env, &s.handle, k.as_bytes(), &v); db::write_chunks(&db.env, &db.handle, k.as_bytes(), &v);
let actual_contact: Contact = find(&String::from(k)); let actual_contact: Contact = find(&String::from(k));
assert_eq!(expected_contact.xmr_address, actual_contact.xmr_address); assert_eq!(expected_contact.xmr_address, actual_contact.xmr_address);
cleanup(&String::from(k)); cleanup(&String::from(k));

View file

@ -7,6 +7,7 @@ extern crate kn0sys_lmdb_rs as lmdb;
use lmdb::*; use lmdb::*;
use log::{error, info}; use log::{error, info};
use sysinfo::System; use sysinfo::System;
use std::sync::LazyLock;
use crate::utils; use crate::utils;
@ -15,16 +16,19 @@ const MAP_SIZE_MEMORY_RATIO: f32 = 0.2;
/// Ratio of chunk size to available memory is 0.2 percent /// Ratio of chunk size to available memory is 0.2 percent
const CHUNK_SIZE_MEMORY_RATIO: f32 = MAP_SIZE_MEMORY_RATIO * 0.01; 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. /// The database environment for handling primary database operations.
/// ///
/// By default the database will be written to /home/user/.neveko/{ENV}/lmdb /// By default the database will be written to /home/user/.neveko/{ENV}/lmdb
pub struct DatabaseEnvironment { pub struct DatabaseEnvironment {
/// Represents LMDB Environment. /// Represents LMDB Environment.
//TODO(n12n): cache the DB handle to avoid multiple open ops
pub env: Environment, pub env: Environment,
/// DB handle. /// DB handle.
// TODO(n12n): cache the DB handle to avoid multiple open ops pub handle: DbHandle,
pub handle: Result<DbHandle, MdbError>,
} }
impl DatabaseEnvironment { impl DatabaseEnvironment {
@ -61,7 +65,7 @@ impl DatabaseEnvironment {
let handle: DbHandle = default?; let handle: DbHandle = default?;
Ok(DatabaseEnvironment { Ok(DatabaseEnvironment {
env, env,
handle: Ok(handle), handle,
}) })
} }
/// Write a key/value pair to the database. It is not possible to /// Write a key/value pair to the database. It is not possible to
@ -192,18 +196,16 @@ mod tests {
#[test] #[test]
fn environment_test() -> Result<(), MdbError> { fn environment_test() -> Result<(), MdbError> {
let db = DatabaseEnvironment::open()?; let db: DatabaseEnvironment = &DATABASE_LOCK;
const DATA_SIZE_10MB: usize = 10000000; const DATA_SIZE_10MB: usize = 10000000;
let mut data = vec![0u8; DATA_SIZE_10MB]; let mut data = vec![0u8; DATA_SIZE_10MB];
rand::thread_rng().fill_bytes(&mut data); rand::thread_rng().fill_bytes(&mut data);
let k = "test-key".as_bytes(); let k = "test-key".as_bytes();
let expected = &data.to_vec(); let expected = &data.to_vec();
write_chunks(&db.env, &db.handle?, &Vec::from(k), &Vec::from(data))?; write_chunks(&db.env, &db.handle, &Vec::from(k), &Vec::from(data))?;
let db = DatabaseEnvironment::open()?; let actual = DatabaseEnvironment::read(&db.env, &db.handle, &Vec::from(k));
let actual = DatabaseEnvironment::read(&db.env, &db.handle?, &Vec::from(k));
assert_eq!(expected.to_vec(), actual?); assert_eq!(expected.to_vec(), actual?);
let db = DatabaseEnvironment::open()?; let _ = DatabaseEnvironment::delete(&db.env, &db.handle, &Vec::from(k))?;
let _ = DatabaseEnvironment::delete(&db.env, &db.handle?, &Vec::from(k))?;
Ok(()) Ok(())
} }
} }

View file

@ -3,7 +3,7 @@
use std::error::Error; use std::error::Error;
use crate::{ use crate::{
db, error::NevekoError, models::*, monero, utils db::{self, DATABASE_LOCK}, error::NevekoError, models::*, monero, utils
}; };
use kn0sys_lmdb_rs::MdbError; use kn0sys_lmdb_rs::MdbError;
use log::{ use log::{
@ -24,15 +24,13 @@ pub fn create(d: Json<Dispute>) -> Result<Dispute, MdbError> {
tx_set: String::from(&d.tx_set), tx_set: String::from(&d.tx_set),
}; };
debug!("insert dispute: {:?}", &d); debug!("insert dispute: {:?}", &d);
let db = &DATABASE_LOCK;
let s = db::DatabaseEnvironment::open()?;
let k = &d.did; let k = &d.did;
let v = bincode::serialize(&new_dispute).unwrap_or_default(); let v = bincode::serialize(&new_dispute).unwrap_or_default();
db::write_chunks(&s.env, &s.handle?, k.as_bytes(), &v)?; db::write_chunks(&db.env, &db.handle, k.as_bytes(), &v)?;
// in order to retrieve all orders, write keys to with dl // in order to retrieve all orders, write keys to with dl
let list_key = crate::DISPUTE_LIST_DB_KEY; let list_key = crate::DISPUTE_LIST_DB_KEY;
let s = db::DatabaseEnvironment::open()?; let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &list_key.as_bytes().to_vec())?;
let r = db::DatabaseEnvironment::read(&s.env, &s.handle?, &list_key.as_bytes().to_vec())?;
if r.is_empty() { if r.is_empty() {
debug!("creating dispute index"); debug!("creating dispute index");
} }
@ -42,8 +40,7 @@ pub fn create(d: Json<Dispute>) -> Result<Dispute, MdbError> {
"writing dispute index {} for id: {}", "writing dispute index {} for id: {}",
dispute_list, list_key dispute_list, list_key
); );
let s = db::DatabaseEnvironment::open()?; db::write_chunks(&db.env, &db.handle, list_key.as_bytes(), dispute_list.as_bytes())?;
db::write_chunks(&s.env, &s.handle?, list_key.as_bytes(), dispute_list.as_bytes())?;
// restart the dispute aut-settle thread // restart the dispute aut-settle thread
let cleared = is_dispute_clear(s_r); let cleared = is_dispute_clear(s_r);
if !cleared { if !cleared {
@ -55,9 +52,8 @@ pub fn create(d: Json<Dispute>) -> Result<Dispute, MdbError> {
/// Dispute lookup /// Dispute lookup
pub fn find(did: &String) -> Result<Dispute, MdbError> { pub fn find(did: &String) -> Result<Dispute, MdbError> {
let db = &DATABASE_LOCK;
let s = db::DatabaseEnvironment::open()?; let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &did.as_bytes().to_vec())?;
let r = db::DatabaseEnvironment::read(&s.env, &s.handle?, &did.as_bytes().to_vec())?;
if r.is_empty() { if r.is_empty() {
error!("dispute not found"); error!("dispute not found");
return Err(MdbError::NotFound); return Err(MdbError::NotFound);
@ -68,10 +64,9 @@ pub fn find(did: &String) -> Result<Dispute, MdbError> {
/// Lookup all disputes /// Lookup all disputes
pub fn find_all() -> Result<Vec<Dispute>, MdbError> { pub fn find_all() -> Result<Vec<Dispute>, MdbError> {
let db = &DATABASE_LOCK;
let d_s = db::DatabaseEnvironment::open()?;
let d_list_key = crate::DISPUTE_LIST_DB_KEY; let d_list_key = crate::DISPUTE_LIST_DB_KEY;
let d_r = db::DatabaseEnvironment::read(&d_s.env, &d_s.handle?, &d_list_key.as_bytes().to_vec())?; let d_r = db::DatabaseEnvironment::read(&db.env, &db.handle, &d_list_key.as_bytes().to_vec())?;
if d_r.is_empty() { if d_r.is_empty() {
error!("dispute index not found"); error!("dispute index not found");
} }
@ -90,15 +85,14 @@ pub fn find_all() -> Result<Vec<Dispute>, MdbError> {
/// Dispute deletion /// Dispute deletion
pub fn delete(did: &String) -> Result<(), MdbError> { pub fn delete(did: &String) -> Result<(), MdbError> {
let db = &DATABASE_LOCK;
let s = db::DatabaseEnvironment::open()?; let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &did.as_bytes().to_vec())?;
let r = db::DatabaseEnvironment::read(&s.env, &s.handle?, &did.as_bytes().to_vec())?;
if r.is_empty() { if r.is_empty() {
error!("dispute not found"); error!("dispute not found");
return Err(MdbError::NotFound); return Err(MdbError::NotFound);
} }
let s = db::DatabaseEnvironment::open()?;
db::DatabaseEnvironment::delete(&s.env, &s.handle?, did.as_bytes()) db::DatabaseEnvironment::delete(&db.env, &db.handle, did.as_bytes())
} }
/// Triggered on DISPUTE_LAST_CHECK_DB_KEY. /// Triggered on DISPUTE_LAST_CHECK_DB_KEY.
@ -114,10 +108,9 @@ pub async fn settle_dispute() -> Result<(), MdbError>{
loop { loop {
debug!("running dispute auto-settle thread"); debug!("running dispute auto-settle thread");
tick.recv().unwrap(); tick.recv().unwrap();
let db = &DATABASE_LOCK;
let s = db::DatabaseEnvironment::open()?;
let list_key = crate::DISPUTE_LIST_DB_KEY; let list_key = crate::DISPUTE_LIST_DB_KEY;
let r = db::DatabaseEnvironment::read(&s.env, &s.handle?, &list_key.as_bytes().to_vec())?; let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &list_key.as_bytes().to_vec())?;
if r.is_empty() { if r.is_empty() {
info!("dispute index not found"); info!("dispute index not found");
} }
@ -129,8 +122,7 @@ pub async fn settle_dispute() -> Result<(), MdbError>{
if cleared { if cleared {
// index was created but cleared // index was created but cleared
info!("terminating dispute auto-settle thread"); info!("terminating dispute auto-settle thread");
let s = db::DatabaseEnvironment::open()?; let _ = db::DatabaseEnvironment::delete(&db.env, &db.handle, list_key.as_bytes())?;
let _ = db::DatabaseEnvironment::delete(&s.env, &s.handle?, list_key.as_bytes())?;
return Ok(()); return Ok(());
} }
for d in d_vec { for d in d_vec {
@ -174,10 +166,9 @@ fn is_dispute_clear(r: String) -> bool {
/// clear dispute from index /// clear dispute from index
fn remove_from_auto_settle(did: String) -> Result<(), MdbError> { fn remove_from_auto_settle(did: String) -> Result<(), MdbError> {
info!("removing id {} from disputes", &did); info!("removing id {} from disputes", &did);
let db = &DATABASE_LOCK;
let s = db::DatabaseEnvironment::open()?;
let list_key = crate::DISPUTE_LIST_DB_KEY; let list_key = crate::DISPUTE_LIST_DB_KEY;
let r = db::DatabaseEnvironment::read(&s.env, &s.handle?, &list_key.as_bytes().to_vec())?; let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &list_key.as_bytes().to_vec())?;
if r.is_empty() { if r.is_empty() {
debug!("dispute list index is empty"); debug!("dispute list index is empty");
} }
@ -197,8 +188,8 @@ fn remove_from_auto_settle(did: String) -> Result<(), MdbError> {
"writing dipsute index {} for id: {}", "writing dipsute index {} for id: {}",
dispute_list, list_key dispute_list, list_key
); );
let s = db::DatabaseEnvironment::open()?;
db::write_chunks(&s.env, &s.handle?, list_key.as_bytes(), dispute_list.as_bytes())?; db::write_chunks(&db.env, &db.handle, list_key.as_bytes(), dispute_list.as_bytes())?;
Ok(()) Ok(())
} }
@ -245,12 +236,9 @@ async fn transmit_dispute_request(
/// can be executed from the gui. /// can be executed from the gui.
pub async fn trigger_dispute_request(contact: &String, dispute: &Dispute) -> Result<Dispute, NevekoError> { pub async fn trigger_dispute_request(contact: &String, dispute: &Dispute) -> Result<Dispute, NevekoError> {
info!("executing trigger_dispute_request"); info!("executing trigger_dispute_request");
let db = &DATABASE_LOCK;
let s = db::DatabaseEnvironment::open()
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &contact); let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &contact);
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?; let jwp = db::DatabaseEnvironment::read(&db.env, &db.handle, &k.as_bytes().to_vec())
let jwp = db::DatabaseEnvironment::read(&s.env, handle, &k.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
let str_jwp: String = bincode::deserialize(&jwp[..]).unwrap_or_default(); let str_jwp: String = bincode::deserialize(&jwp[..]).unwrap_or_default();
let dispute = transmit_dispute_request(contact, &str_jwp, dispute).await; let dispute = transmit_dispute_request(contact, &str_jwp, dispute).await;

View file

@ -2,7 +2,7 @@
use crate::{ use crate::{
contact, contact,
db, db::{self, DATABASE_LOCK},
error::NevekoError, error::NevekoError,
i2p, i2p,
models::*, models::*,
@ -69,15 +69,14 @@ pub async fn create(m: Json<Message>, jwp: String, m_type: MessageType) -> Resul
to: String::from(&m.to), to: String::from(&m.to),
}; };
debug!("insert message: {:?}", &new_message); debug!("insert message: {:?}", &new_message);
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let k = &new_message.mid; let k = &new_message.mid;
let message = bincode::serialize(&new_message).unwrap_or_default(); let message = bincode::serialize(&new_message).unwrap_or_default();
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?; db::write_chunks(&db.env, &db.handle, k.as_bytes(), &message)
db::write_chunks(&s.env, handle, k.as_bytes(), &message)
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
// in order to retrieve all message, write keys to with ml // in order to retrieve all message, write keys to with ml
let list_key = crate::MESSAGE_LIST_DB_KEY; let list_key = crate::MESSAGE_LIST_DB_KEY;
let r = db::DatabaseEnvironment::read(&s.env, handle, &list_key.as_bytes().to_vec()) let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() { if r.is_empty() {
debug!("creating message index"); debug!("creating message index");
@ -85,9 +84,8 @@ pub async fn create(m: Json<Message>, jwp: String, m_type: MessageType) -> Resul
let d_r: String = bincode::deserialize(&r[..]).unwrap_or_default(); let d_r: String = bincode::deserialize(&r[..]).unwrap_or_default();
let msg_list = [d_r, String::from(&f_mid)].join(","); let msg_list = [d_r, String::from(&f_mid)].join(",");
debug!("writing message index {} for id: {}", msg_list, list_key); debug!("writing message index {} for id: {}", msg_list, list_key);
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?; db::write_chunks(&db.env, &db.handle, list_key.as_bytes(), msg_list.as_bytes())
db::write_chunks(&s.env, handle, list_key.as_bytes(), msg_list.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
info!("attempting to send message"); info!("attempting to send message");
let send = send_message(&new_message, &jwp, m_type).await; let send = send_message(&new_message, &jwp, m_type).await;
@ -121,17 +119,14 @@ pub async fn rx(m: Json<Message>) -> Result<(), NevekoError>{
to: String::from(&m.to), to: String::from(&m.to),
}; };
debug!("insert message: {:?}", &new_message); debug!("insert message: {:?}", &new_message);
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let k = &new_message.mid; let k = &new_message.mid;
let message = bincode::serialize(&new_message).unwrap_or_default(); let message = bincode::serialize(&new_message).unwrap_or_default();
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?; db::write_chunks(&db.env, &db.handle, k.as_bytes(), &message)
db::write_chunks(&s.env, handle, k.as_bytes(), &message)
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
// in order to retrieve all message, write keys to with rx // in order to retrieve all message, write keys to with rx
let list_key = crate::RX_MESSAGE_DB_KEY; let list_key = crate::RX_MESSAGE_DB_KEY;
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &list_key.as_bytes().to_vec())
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let r = db::DatabaseEnvironment::read(&s.env, handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() { if r.is_empty() {
debug!("creating message index"); debug!("creating message index");
@ -139,9 +134,7 @@ pub async fn rx(m: Json<Message>) -> Result<(), NevekoError>{
let old: String = bincode::deserialize(&r[..]).unwrap_or_default(); let old: String = bincode::deserialize(&r[..]).unwrap_or_default();
let msg_list = [old, String::from(&f_mid)].join(","); let msg_list = [old, String::from(&f_mid)].join(",");
debug!("writing message index {} for {}", msg_list, list_key); debug!("writing message index {} for {}", msg_list, list_key);
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; db::write_chunks(&db.env, &db.handle, list_key.as_bytes(), msg_list.as_bytes())
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::write_chunks(&s.env, handle, list_key.as_bytes(), msg_list.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(()) Ok(())
} }
@ -196,7 +189,7 @@ async fn parse_multisig_message(mid: String) -> Result<MultisigMessageData, Neve
/// use neveko_core::db; /// use neveko_core::db;
/// let s = db::DatabaseEnvironment::open(); /// let s = db::DatabaseEnvironment::open();
/// let key = "prepare-o123-test.b32.i2p"; /// let key = "prepare-o123-test.b32.i2p";
/// let info_str = db::DatabaseEnvironment::read(&s.env, &s.handle, &key); /// let info_str = db::DatabaseEnvironment::read(&db.env, &s.handle, &key);
/// ``` /// ```
pub async fn rx_multisig(m: Json<Message>) -> Result<(), NevekoError> { pub async fn rx_multisig(m: Json<Message>) -> Result<(), NevekoError> {
info!("rx multisig from: {}", &m.from); info!("rx multisig from: {}", &m.from);
@ -222,17 +215,17 @@ pub async fn rx_multisig(m: Json<Message>) -> Result<(), NevekoError> {
created: chrono::offset::Utc::now().timestamp(), created: chrono::offset::Utc::now().timestamp(),
to: String::from(&m.to), to: String::from(&m.to),
}; };
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let k = &new_message.mid; let k = &new_message.mid;
let message = bincode::serialize(&new_message).unwrap_or_default(); let message = bincode::serialize(&new_message).unwrap_or_default();
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::write_chunks(&s.env, handle, k.as_bytes(), &message) db::write_chunks(&db.env, &db.handle, k.as_bytes(), &message)
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
// in order to retrieve all msig messages, write keys to with msigl // in order to retrieve all msig messages, write keys to with msigl
let list_key = crate::MSIG_MESSAGE_LIST_DB_KEY; let list_key = crate::MSIG_MESSAGE_LIST_DB_KEY;
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let r = db::DatabaseEnvironment::read(&s.env, handle, &list_key.as_bytes().to_vec()) let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() { if r.is_empty() {
debug!("creating msig message index"); debug!("creating msig message index");
@ -243,9 +236,9 @@ pub async fn rx_multisig(m: Json<Message>) -> Result<(), NevekoError> {
"writing msig message index {} for id: {}", "writing msig message index {} for id: {}",
msg_list, list_key msg_list, list_key
); );
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::write_chunks(&s.env, handle, list_key.as_bytes(), msg_list.as_bytes()) db::write_chunks(&db.env, &db.handle, list_key.as_bytes(), msg_list.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
let data: MultisigMessageData = parse_multisig_message(new_message.mid).await?; let data: MultisigMessageData = parse_multisig_message(new_message.mid).await?;
debug!( debug!(
@ -256,18 +249,18 @@ pub async fn rx_multisig(m: Json<Message>) -> Result<(), NevekoError> {
// store info as {a_info}:{a_info (optional)} // store info as {a_info}:{a_info (optional)}
let s_msig = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let s_msig = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let msig_key = format!("{}-{}-{}", &data.sub_type, &data.orid, &m.from); let msig_key = format!("{}-{}-{}", &data.sub_type, &data.orid, &m.from);
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::write_chunks(&s_msig.env, handle, msig_key.as_bytes(), data.info.as_bytes()) db::write_chunks(&s_msig.env, &db.handle, msig_key.as_bytes(), data.info.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(()) Ok(())
} }
/// Message lookup() /// Message lookup()
pub fn find(mid: &String) -> Result<Message, NevekoError> { pub fn find(mid: &String) -> Result<Message, NevekoError> {
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let r = db::DatabaseEnvironment::read(&s.env, handle, &mid.as_bytes().to_vec()) let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &mid.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() { if r.is_empty() {
error!("message not found"); error!("message not found");
@ -279,10 +272,9 @@ pub fn find(mid: &String) -> Result<Message, NevekoError> {
/// Message lookup /// Message lookup
pub fn find_all() -> Result<Vec<Message>, NevekoError> { pub fn find_all() -> Result<Vec<Message>, NevekoError> {
let i_s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let i_list_key = crate::MESSAGE_LIST_DB_KEY; let i_list_key = crate::MESSAGE_LIST_DB_KEY;
let handle = &i_s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?; let i_r = db::DatabaseEnvironment::read(&db.env, &db.handle, &i_list_key.as_bytes().to_vec())
let i_r = db::DatabaseEnvironment::read(&i_s.env, handle, &i_list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
if i_r.is_empty() { if i_r.is_empty() {
error!("message index not found"); error!("message index not found");
@ -298,9 +290,7 @@ pub fn find_all() -> Result<Vec<Message>, NevekoError> {
} }
} }
let o_list_key = crate::RX_MESSAGE_DB_KEY; let o_list_key = crate::RX_MESSAGE_DB_KEY;
let o_s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let o_r = db::DatabaseEnvironment::read(&db.env, &db.handle, &o_list_key.as_bytes().to_vec())
let handle = &o_s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let o_r = db::DatabaseEnvironment::read(&o_s.env, handle, &o_list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
if o_r.is_empty() { if o_r.is_empty() {
error!("message index not found"); error!("message index not found");
@ -371,9 +361,8 @@ pub async fn decipher_body(mid: String) -> Result<reqres::DecipheredMessageBody,
/// Message deletion /// Message deletion
pub fn delete(mid: &String) -> Result<(), NevekoError> { pub fn delete(mid: &String) -> Result<(), NevekoError> {
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?; let _ = db::DatabaseEnvironment::delete(&db.env, &db.handle, mid.as_bytes())
let _ = db::DatabaseEnvironment::delete(&s.env, handle, mid.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(()) Ok(())
} }
@ -413,11 +402,10 @@ async fn is_contact_online(contact: &String, jwp: String) -> Result<bool, Box<dy
/// stage message for async retry /// stage message for async retry
async fn send_to_retry(mid: String) -> Result<(), NevekoError>{ async fn send_to_retry(mid: String) -> Result<(), NevekoError>{
info!("sending {} to fts", &mid); info!("sending {} to fts", &mid);
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
// in order to retrieve FTS (failed-to-send), write keys to db with fts // in order to retrieve FTS (failed-to-send), write keys to db with fts
let list_key = crate::FTS_DB_KEY; let list_key = crate::FTS_DB_KEY;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?; let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &list_key.as_bytes().to_vec())
let r = db::DatabaseEnvironment::read(&s.env, handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() { if r.is_empty() {
debug!("creating fts message index"); debug!("creating fts message index");
@ -432,12 +420,10 @@ async fn send_to_retry(mid: String) -> Result<(), NevekoError>{
"writing fts message index {} for id: {}", "writing fts message index {} for id: {}",
msg_list, list_key msg_list, list_key
); );
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; db::write_chunks(&db.env, &db.handle, list_key.as_bytes(), msg_list.as_bytes())
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::write_chunks(&s.env, handle, list_key.as_bytes(), msg_list.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
// restart fts if not empty // restart fts if not empty
let r = db::DatabaseEnvironment::read(&s.env, handle, &list_key.as_bytes().to_vec()) let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
let str_r: String = bincode::deserialize(&r[..]).unwrap_or_default(); let str_r: String = bincode::deserialize(&r[..]).unwrap_or_default();
let v_mid = str_r.split(","); let v_mid = str_r.split(",");
@ -454,11 +440,10 @@ async fn send_to_retry(mid: String) -> Result<(), NevekoError>{
/// clear fts message from index /// clear fts message from index
fn remove_from_fts(mid: String) -> Result<(), NevekoError> { fn remove_from_fts(mid: String) -> Result<(), NevekoError> {
info!("removing id {} from fts", &mid); info!("removing id {} from fts", &mid);
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
// in order to retrieve FTS (failed-to-send), write keys to with fts // in order to retrieve FTS (failed-to-send), write keys to with fts
let list_key = crate::FTS_DB_KEY; let list_key = crate::FTS_DB_KEY;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?; let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &list_key.as_bytes().to_vec())
let r = db::DatabaseEnvironment::read(&s.env, handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() { if r.is_empty() {
debug!("fts is empty"); debug!("fts is empty");
@ -479,9 +464,7 @@ fn remove_from_fts(mid: String) -> Result<(), NevekoError> {
"writing fts message index {} for id: {}", "writing fts message index {} for id: {}",
msg_list, list_key msg_list, list_key
); );
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; db::write_chunks(&db.env, &db.handle, list_key.as_bytes(), msg_list.as_bytes())
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::write_chunks(&s.env, handle, list_key.as_bytes(), msg_list.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(()) Ok(())
} }
@ -496,10 +479,9 @@ pub async fn retry_fts() -> Result<(), NevekoError> {
loop { loop {
debug!("running retry failed-to-send thread"); debug!("running retry failed-to-send thread");
tick.recv().unwrap(); tick.recv().unwrap();
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let list_key = crate::FTS_DB_KEY; let list_key = crate::FTS_DB_KEY;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?; let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &list_key.as_bytes().to_vec())
let r = db::DatabaseEnvironment::read(&s.env, handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() { if r.is_empty() {
info!("fts message index not found"); info!("fts message index not found");
@ -513,9 +495,7 @@ pub async fn retry_fts() -> Result<(), NevekoError> {
if cleared { if cleared {
// index was created but cleared // index was created but cleared
info!("terminating retry fts thread"); info!("terminating retry fts thread");
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let _ = db::DatabaseEnvironment::delete(&db.env, &db.handle, &list_key.as_bytes().to_vec())
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let _ = db::DatabaseEnvironment::delete(&s.env, handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
break Err(NevekoError::Database(MdbError::NotFound)); break Err(NevekoError::Database(MdbError::NotFound));
} }
@ -524,9 +504,7 @@ pub async fn retry_fts() -> Result<(), NevekoError> {
if !message.mid.is_empty() { if !message.mid.is_empty() {
// get jwp from db // get jwp from db
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &message.to); let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &message.to);
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let jwp = db::DatabaseEnvironment::read(&db.env, &db.handle, &k.as_bytes().to_vec())
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let jwp = db::DatabaseEnvironment::read(&s.env, handle, &k.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
if !jwp.is_empty() { if !jwp.is_empty() {
let m_type = if message.mid.contains("msig") { let m_type = if message.mid.contains("msig") {
@ -571,14 +549,13 @@ fn is_fts_clear(r: String) -> bool {
/// ///
/// `prepare_multisig_info` method. /// `prepare_multisig_info` method.
pub async fn send_prepare_info(orid: &String, contact: &String) -> Result<(), NevekoError> { pub async fn send_prepare_info(orid: &String, contact: &String) -> Result<(), NevekoError> {
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let wallet_name = String::from(orid); let wallet_name = String::from(orid);
let wallet_password = String::new(); let wallet_password = String::new();
monero::open_wallet(&wallet_name, &wallet_password).await; monero::open_wallet(&wallet_name, &wallet_password).await;
let prepare_info = monero::prepare_wallet().await; let prepare_info = monero::prepare_wallet().await;
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, contact); let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, contact);
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?; let jwp = db::DatabaseEnvironment::read(&db.env, &db.handle, &k.as_bytes().to_vec())
let jwp = db::DatabaseEnvironment::read(&s.env, handle, &k.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
let body_str = format!( let body_str = format!(
"{}:{}:{}", "{}:{}:{}",
@ -601,14 +578,13 @@ pub async fn send_prepare_info(orid: &String, contact: &String) -> Result<(), Ne
/// ///
/// `make_multisig_info` method. /// `make_multisig_info` method.
pub async fn send_make_info(orid: &String, contact: &String, info: Vec<String>) -> Result<(), NevekoError> { pub async fn send_make_info(orid: &String, contact: &String, info: Vec<String>) -> Result<(), NevekoError> {
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let wallet_name = String::from(orid); let wallet_name = String::from(orid);
let wallet_password = String::new(); let wallet_password = String::new();
monero::open_wallet(&wallet_name, &wallet_password).await; monero::open_wallet(&wallet_name, &wallet_password).await;
let make_info = monero::make_wallet(info).await; let make_info = monero::make_wallet(info).await;
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, contact); let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, contact);
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?; let jwp = db::DatabaseEnvironment::read(&db.env, &db.handle, &k.as_bytes().to_vec())
let jwp = db::DatabaseEnvironment::read(&s.env, handle, &k.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
let body_str = format!("{}:{}:{}", MAKE_MSIG, orid, &make_info.result.multisig_info); let body_str = format!("{}:{}:{}", MAKE_MSIG, orid, &make_info.result.multisig_info);
let message: Message = Message { let message: Message = Message {
@ -633,14 +609,13 @@ pub async fn send_exchange_info(
info: Vec<String>, info: Vec<String>,
kex_init: bool, kex_init: bool,
) -> Result<(), NevekoError> { ) -> Result<(), NevekoError> {
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let wallet_name = String::from(orid); let wallet_name = String::from(orid);
let wallet_password = String::new(); let wallet_password = String::new();
monero::open_wallet(&wallet_name, &wallet_password).await; monero::open_wallet(&wallet_name, &wallet_password).await;
let exchange_info = monero::exchange_multisig_keys(false, info, &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 k = format!("{}-{}", crate::FTS_JWP_DB_KEY, contact);
let jwp = db::DatabaseEnvironment::read(&s.env, handle, &k.as_bytes().to_vec()) let jwp = db::DatabaseEnvironment::read(&db.env, &db.handle, &k.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
let mut body_str = format!( let mut body_str = format!(
"{}:{}:{}", "{}:{}:{}",
@ -669,14 +644,13 @@ pub async fn send_exchange_info(
/// ///
/// `export_multisig_info` method. /// `export_multisig_info` method.
pub async fn send_export_info(orid: &String, contact: &String) -> Result<(), NevekoError> { pub async fn send_export_info(orid: &String, contact: &String) -> Result<(), NevekoError> {
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let wallet_name = String::from(orid); let wallet_name = String::from(orid);
let wallet_password = String::new(); let wallet_password = String::new();
monero::open_wallet(&wallet_name, &wallet_password).await; monero::open_wallet(&wallet_name, &wallet_password).await;
let exchange_info = monero::export_multisig_info().await; let exchange_info = monero::export_multisig_info().await;
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, contact); let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, contact);
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?; let jwp = db::DatabaseEnvironment::read(&db.env, &db.handle, &k.as_bytes().to_vec())
let jwp = db::DatabaseEnvironment::read(&s.env, handle, &k.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
let body_str = format!("{}:{}:{}", EXPORT_MSIG, orid, &exchange_info.result.info); let body_str = format!("{}:{}:{}", EXPORT_MSIG, orid, &exchange_info.result.info);
let message: Message = Message { let message: Message = Message {
@ -792,7 +766,7 @@ mod tests {
fn cleanup(k: &String) -> Result<(), NevekoError> { fn cleanup(k: &String) -> Result<(), NevekoError> {
let s = db::DatabaseEnvironment::open() let s = db::DatabaseEnvironment::open()
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
let _ = db::DatabaseEnvironment::delete(&s.env, &s.handle, k.as_bytes()) let _ = db::DatabaseEnvironment::delete(&db.env, &s.handle, k.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(()) Ok(())
} }
@ -828,9 +802,9 @@ mod tests {
..Default::default() ..Default::default()
}; };
let k = "test-key"; let k = "test-key";
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let message = bincode::serialize(&new_message).unwrap_or_default(); let message = bincode::serialize(&new_message).unwrap_or_default();
db::write_chunks(&s.env, &s.handle, k, &message); db::write_chunks(&db.env, &s.handle, k, &message);
let actual_message: Message = find(&String::from(k)); let actual_message: Message = find(&String::from(k));
assert_eq!(expected_message.body, actual_message.body); assert_eq!(expected_message.body, actual_message.body);
cleanup(&String::from(k)); cleanup(&String::from(k));

View file

@ -3,7 +3,7 @@
use std::error::Error; use std::error::Error;
use crate::{ use crate::{
contact, db, error::NevekoError, i2p, models::*, monero, neveko25519, order, product, reqres, utils contact, db::{self, DATABASE_LOCK}, error::NevekoError, i2p, models::*, monero, neveko25519, order, product, reqres, utils
}; };
use kn0sys_lmdb_rs::MdbError::{self}; use kn0sys_lmdb_rs::MdbError::{self};
use log::{ use log::{
@ -66,26 +66,18 @@ pub async fn create(j_order: Json<reqres::OrderRequest>) -> Result<Order, Neveko
} }
monero::close_wallet(&orid, &order_wallet_password).await; monero::close_wallet(&orid, &order_wallet_password).await;
debug!("insert order: {:?}", &new_order); debug!("insert order: {:?}", &new_order);
let s = db::DatabaseEnvironment::open() let db = &DATABASE_LOCK;
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
// inject adjudicator separately, modifying the order model is mendokusai // inject adjudicator separately, modifying the order model is mendokusai
let adjudicator_k = format!("{}-{}", crate::ADJUDICATOR_DB_KEY, &orid); let adjudicator_k = format!("{}-{}", crate::ADJUDICATOR_DB_KEY, &orid);
db::write_chunks(&s.env, handle, adjudicator_k.as_bytes(), j_order.adjudicator.as_bytes()) db::write_chunks(&db.env, &db.handle, adjudicator_k.as_bytes(), j_order.adjudicator.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
let k = &new_order.orid; let k = &new_order.orid;
let s = db::DatabaseEnvironment::open()
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let order = bincode::serialize(&new_order).unwrap_or_default(); let order = bincode::serialize(&new_order).unwrap_or_default();
db::write_chunks(&s.env, handle, k.as_bytes(), &order) db::write_chunks(&db.env, &db.handle, k.as_bytes(), &order)
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
// in order to retrieve all orders, write keys to with ol // in order to retrieve all orders, write keys to with ol
let list_key = crate::ORDER_LIST_DB_KEY; let list_key = crate::ORDER_LIST_DB_KEY;
let s = db::DatabaseEnvironment::open() let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let r = db::DatabaseEnvironment::read(&s.env, handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() { if r.is_empty() {
debug!("creating order index"); debug!("creating order index");
@ -93,9 +85,7 @@ pub async fn create(j_order: Json<reqres::OrderRequest>) -> Result<Order, Neveko
let old: String = bincode::deserialize(&r[..]).unwrap_or_default(); let old: String = bincode::deserialize(&r[..]).unwrap_or_default();
let order_list = [old, String::from(&orid)].join(","); let order_list = [old, String::from(&orid)].join(",");
debug!("writing order index {} for id: {}", order_list, list_key); debug!("writing order index {} for id: {}", order_list, list_key);
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; db::write_chunks(&db.env, &db.handle, list_key.as_bytes(), &order_list.as_bytes())
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::write_chunks(&s.env, handle, list_key.as_bytes(), &order_list.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(new_order) Ok(new_order)
} }
@ -103,20 +93,18 @@ pub async fn create(j_order: Json<reqres::OrderRequest>) -> Result<Order, Neveko
/// Backup order for customer /// Backup order for customer
pub fn backup(order: &Order) -> Result<(), NevekoError> { pub fn backup(order: &Order) -> Result<(), NevekoError> {
info!("creating backup of order: {}", order.orid); info!("creating backup of order: {}", order.orid);
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let k = &order.orid; let k = &order.orid;
db::DatabaseEnvironment::delete(&s.env, handle, k.as_bytes()) db::DatabaseEnvironment::delete(&db.env, &db.handle, k.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let order_to_db = bincode::serialize(&order).unwrap_or_default(); let order_to_db = bincode::serialize(&order).unwrap_or_default();
db::write_chunks(&s.env, handle, k.as_bytes(), &order_to_db) db::write_chunks(&db.env, &db.handle, k.as_bytes(), &order_to_db)
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
// in order to retrieve all orders, write keys to with col // in order to retrieve all orders, write keys to with col
let list_key = crate::CUSTOMER_ORDER_LIST_DB_KEY; let list_key = crate::CUSTOMER_ORDER_LIST_DB_KEY;
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?; let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &list_key.as_bytes().to_vec())
let r = db::DatabaseEnvironment::read(&s.env, handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() { if r.is_empty() {
debug!("creating customer order index"); debug!("creating customer order index");
@ -128,9 +116,8 @@ pub fn backup(order: &Order) -> Result<(), NevekoError> {
order_list = d_r; order_list = d_r;
} }
debug!("writing order index {} for id: {}", order_list, list_key); debug!("writing order index {} for id: {}", order_list, list_key);
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?; db::write_chunks(&db.env, &db.handle, list_key.as_bytes(), order_list.as_bytes())
db::write_chunks(&s.env, handle, list_key.as_bytes(), order_list.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(()) Ok(())
} }
@ -138,10 +125,8 @@ pub fn backup(order: &Order) -> Result<(), NevekoError> {
/// Lookup order /// Lookup order
pub fn find(oid: &String) -> Result<Order, NevekoError> { pub fn find(oid: &String) -> Result<Order, NevekoError> {
info!("find order: {}", &oid); info!("find order: {}", &oid);
let s = db::DatabaseEnvironment::open() let db = &DATABASE_LOCK;
.map_err(|_| NevekoError::Database(MdbError::Panic))?; let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &oid.as_bytes().to_vec())
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let r = db::DatabaseEnvironment::read(&s.env, handle, &oid.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() { if r.is_empty() {
error!("order not found"); error!("order not found");
@ -153,11 +138,9 @@ pub fn find(oid: &String) -> Result<Order, NevekoError> {
/// Lookup all orders from admin server /// Lookup all orders from admin server
pub fn find_all() -> Result<Vec<Order>, NevekoError> { pub fn find_all() -> Result<Vec<Order>, NevekoError> {
let s = db::DatabaseEnvironment::open() let db = &DATABASE_LOCK;
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let i_list_key = crate::ORDER_LIST_DB_KEY; let i_list_key = crate::ORDER_LIST_DB_KEY;
let i_r = db::DatabaseEnvironment::read(&s.env, handle, &i_list_key.as_bytes().to_vec()) let i_r = db::DatabaseEnvironment::read(&db.env, &db.handle, &i_list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
if i_r.is_empty() { if i_r.is_empty() {
error!("order index not found"); error!("order index not found");
@ -177,11 +160,9 @@ pub fn find_all() -> Result<Vec<Order>, NevekoError> {
/// Lookup all orders that customer has saved from gui /// Lookup all orders that customer has saved from gui
pub fn find_all_backup() -> Result<Vec<Order>, NevekoError> { pub fn find_all_backup() -> Result<Vec<Order>, NevekoError> {
let i_s = db::DatabaseEnvironment::open() let db = &DATABASE_LOCK;
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &i_s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let i_list_key = crate::CUSTOMER_ORDER_LIST_DB_KEY; let i_list_key = crate::CUSTOMER_ORDER_LIST_DB_KEY;
let i_r = db::DatabaseEnvironment::read(&i_s.env, handle, &i_list_key.as_bytes().to_vec()) let i_r = db::DatabaseEnvironment::read(&db.env, &db.handle, &i_list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
if i_r.is_empty() { if i_r.is_empty() {
error!("customer order index not found"); error!("customer order index not found");
@ -205,11 +186,9 @@ pub fn find_all_backup() -> Result<Vec<Order>, NevekoError> {
/// Lookup all orders for customer /// Lookup all orders for customer
pub async fn find_all_customer_orders(cid: String) -> Result<Vec<Order>, NevekoError> { pub async fn find_all_customer_orders(cid: String) -> Result<Vec<Order>, NevekoError> {
info!("lookup orders for customer: {}", &cid); info!("lookup orders for customer: {}", &cid);
let i_s = db::DatabaseEnvironment::open() let db = &DATABASE_LOCK;
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &i_s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let i_list_key = crate::ORDER_LIST_DB_KEY; let i_list_key = crate::ORDER_LIST_DB_KEY;
let i_r = db::DatabaseEnvironment::read(&i_s.env, handle, &i_list_key.as_bytes().to_vec()) let i_r = db::DatabaseEnvironment::read(&db.env, &db.handle, &i_list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
if i_r.is_empty() { if i_r.is_empty() {
error!("order index not found"); error!("order index not found");
@ -230,11 +209,9 @@ pub async fn find_all_customer_orders(cid: String) -> Result<Vec<Order>, NevekoE
/// Lookup all orders for vendor /// Lookup all orders for vendor
pub fn find_all_vendor_orders() -> Result<Vec<Order>, NevekoError> { pub fn find_all_vendor_orders() -> Result<Vec<Order>, NevekoError> {
info!("lookup orders for vendor"); info!("lookup orders for vendor");
let i_s = db::DatabaseEnvironment::open() let db = &DATABASE_LOCK;
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &i_s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let i_list_key = crate::ORDER_LIST_DB_KEY; let i_list_key = crate::ORDER_LIST_DB_KEY;
let i_r = db::DatabaseEnvironment::read(&i_s.env, handle, &i_list_key.as_bytes().to_vec()) let i_r = db::DatabaseEnvironment::read(&db.env, &db.handle, &i_list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
if i_r.is_empty() { if i_r.is_empty() {
error!("order index not found"); error!("order index not found");
@ -266,17 +243,12 @@ pub fn modify(o: Json<Order>) -> Result<Order, NevekoError> {
error!("order not found"); error!("order not found");
return Err(NevekoError::Database(MdbError::NotFound)); return Err(NevekoError::Database(MdbError::NotFound));
} }
let db = &DATABASE_LOCK;
let u_order = Order::update(String::from(&f_order.orid), &o); let u_order = Order::update(String::from(&f_order.orid), &o);
let s = db::DatabaseEnvironment::open() let _ = db::DatabaseEnvironment::delete(&db.env, &db.handle, &u_order.orid.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let _ = db::DatabaseEnvironment::delete(&s.env, handle, &u_order.orid.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
let v = bincode::serialize(&u_order).unwrap_or_default(); let v = bincode::serialize(&u_order).unwrap_or_default();
let s = db::DatabaseEnvironment::open() let _ = db::write_chunks(&db.env, &db.handle, &u_order.orid.as_bytes(), &v)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let _ = db::write_chunks(&s.env, handle, &u_order.orid.as_bytes(), &v)
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(u_order) Ok(u_order)
} }
@ -376,10 +348,9 @@ pub async fn validate_order_for_ship(orid: &String) -> Result<reqres::FinalizeOr
let m_order: Order = find(orid).map_err(|_| NevekoError::Order)?; let m_order: Order = find(orid).map_err(|_| NevekoError::Order)?;
let contact: Contact = contact::find(&m_order.cid).map_err(|_| NevekoError::Contact)?; let contact: Contact = contact::find(&m_order.cid).map_err(|_| NevekoError::Contact)?;
let hex_nmpk: String = contact.nmpk; let hex_nmpk: String = contact.nmpk;
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let k = String::from(crate::DELIVERY_INFO_DB_KEY); let k = String::from(crate::DELIVERY_INFO_DB_KEY);
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?; let delivery_info = db::DatabaseEnvironment::read(&db.env, &db.handle, &k.as_bytes().to_vec())
let delivery_info = db::DatabaseEnvironment::read(&s.env, handle, &k.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
let mut j_order: Order = find(orid).map_err(|_| NevekoError::Order)?; 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 m_product: Product = product::find(&m_order.pid).map_err(|_| NevekoError::Product)?;
@ -489,20 +460,19 @@ pub async fn upload_delivery_info(
m_order.vend_msig_txset = sweep.result.multisig_txset; m_order.vend_msig_txset = sweep.result.multisig_txset;
// delivery info will be stored enciphered and separate from the rest of the // delivery info will be stored enciphered and separate from the rest of the
// order // order
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let k = String::from(crate::DELIVERY_INFO_DB_KEY); let k = String::from(crate::DELIVERY_INFO_DB_KEY);
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?; db::write_chunks(&db.env, &db.handle, k.as_bytes(), delivery_info.as_bytes())
db::write_chunks(&s.env, handle, k.as_bytes(), delivery_info.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
modify(Json(m_order))?; modify(Json(m_order))?;
// trigger nasr, this will cause the customer's neveko instance to request the // trigger nasr, this will cause the customer's neveko instance to request the
// txset // txset
let i2p_address = i2p::get_destination(None); let i2p_address = i2p::get_destination(None);
// get jwp from db // get jwp from db
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &lookup.cid); let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &lookup.cid);
let jwp = db::DatabaseEnvironment::read(&s.env, handle, &k.as_bytes().to_vec()) let jwp = db::DatabaseEnvironment::read(&db.env, &db.handle, &k.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
let str_jwp: String = bincode::deserialize(&jwp[..]).unwrap_or_default(); let str_jwp: String = bincode::deserialize(&jwp[..]).unwrap_or_default();
let nasr_order = trigger_nasr(&lookup.cid, &i2p_address, &str_jwp, orid).await; let nasr_order = trigger_nasr(&lookup.cid, &i2p_address, &str_jwp, orid).await;
@ -635,10 +605,10 @@ pub async fn d_trigger_finalize_request(
) -> Result<reqres::FinalizeOrderResponse, NevekoError> { ) -> Result<reqres::FinalizeOrderResponse, NevekoError> {
// ugh, sorry seems we need to get jwp for vendor from fts cache // ugh, sorry seems we need to get jwp for vendor from fts cache
// get jwp from db // get jwp from db
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &contact); let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &contact);
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let jwp = db::DatabaseEnvironment::read(&s.env, handle, &k.as_bytes().to_vec()) let jwp = db::DatabaseEnvironment::read(&db.env, &db.handle, &k.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
info!("executing d_trigger_finalize_request"); info!("executing d_trigger_finalize_request");
// request finalize if the order status is shipped // request finalize if the order status is shipped
@ -811,11 +781,9 @@ pub async fn trigger_cancel_request(
pub async fn d_trigger_ship_request(contact: &String, orid: &String) -> Result<Order, NevekoError> { 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 // ugh, sorry seems we need to get jwp for vendor from fts cache
// get jwp from db // get jwp from db
let s = db::DatabaseEnvironment::open()
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &contact); let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &contact);
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let jwp = db::DatabaseEnvironment::read(&s.env, handle, &k.as_bytes().to_vec()) let jwp = db::DatabaseEnvironment::read(&db.env, &db.handle, &k.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
info!("executing d_trigger_ship_request"); info!("executing d_trigger_ship_request");
// request shipment if the order status is MultisigComplete // request shipment if the order status is MultisigComplete
@ -830,10 +798,7 @@ pub async fn d_trigger_ship_request(contact: &String, orid: &String) -> Result<O
let u_ship_res = ship_res.unwrap_or(Default::default()); let u_ship_res = ship_res.unwrap_or(Default::default());
let hex_delivery_info: String = hex::encode(u_ship_res.delivery_info); let hex_delivery_info: String = hex::encode(u_ship_res.delivery_info);
let key = format!("{}-{}", crate::DELIVERY_INFO_DB_KEY, orid); let key = format!("{}-{}", crate::DELIVERY_INFO_DB_KEY, orid);
let s = db::DatabaseEnvironment::open() db::write_chunks(&db.env, &db.handle, key.as_bytes(), hex_delivery_info.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::write_chunks(&s.env, handle, key.as_bytes(), hex_delivery_info.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
} }
Ok(trigger) Ok(trigger)
@ -884,11 +849,9 @@ pub async fn transmit_cancel_request(
pub async fn d_trigger_cancel_request(contact: &String, orid: &String) -> Result<Order, NevekoError> { 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 // ugh, sorry seems we need to get jwp for vendor from fts cache
// get jwp from db // get jwp from db
let s = db::DatabaseEnvironment::open()
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &contact); let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &contact);
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let jwp = db::DatabaseEnvironment::read(&s.env, handle, &k.as_bytes().to_vec()) let jwp = db::DatabaseEnvironment::read(&db.env, &db.handle, &k.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
info!("executing d_trigger_cancel_request"); info!("executing d_trigger_cancel_request");
// request cancel if the order status is not MultisigComplete // request cancel if the order status is not MultisigComplete

View file

@ -1,7 +1,7 @@
//! Marketplace products upload, modification, etc module //! Marketplace products upload, modification, etc module
use crate::{ use crate::{
db, error::NevekoError, models::*, utils db::{self, DATABASE_LOCK}, error::NevekoError, models::*, utils
}; };
use kn0sys_lmdb_rs::MdbError; use kn0sys_lmdb_rs::MdbError;
use log::{ use log::{
@ -29,17 +29,14 @@ pub fn create(d: Json<Product>) -> Result<Product, NevekoError> {
qty: d.qty, qty: d.qty,
}; };
debug!("insert product: {:?}", &new_product); debug!("insert product: {:?}", &new_product);
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let k = &new_product.pid; let k = &new_product.pid;
let product = bincode::serialize(&new_product).unwrap_or_default(); let product = bincode::serialize(&new_product).unwrap_or_default();
db::write_chunks(&s.env, handle, k.as_bytes(), &product) db::write_chunks(&db.env, &db.handle, k.as_bytes(), &product)
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
// in order to retrieve all products, write keys to with pl // in order to retrieve all products, write keys to with pl
let list_key = crate::PRODUCT_LIST_DB_KEY; let list_key = crate::PRODUCT_LIST_DB_KEY;
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &list_key.as_bytes().to_vec())
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let r = db::DatabaseEnvironment::read(&s.env, handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() { if r.is_empty() {
debug!("creating product index"); debug!("creating product index");
@ -50,18 +47,15 @@ pub fn create(d: Json<Product>) -> Result<Product, NevekoError> {
"writing product index {} for id: {}", "writing product index {} for id: {}",
product_list, list_key product_list, list_key
); );
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; db::write_chunks(&db.env, &db.handle, list_key.as_bytes(), product_list.as_bytes())
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::write_chunks(&s.env, handle, list_key.as_bytes(), product_list.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(new_product) Ok(new_product)
} }
/// Single Product lookup /// Single Product lookup
pub fn find(pid: &String) -> Result<Product, NevekoError> { pub fn find(pid: &String) -> Result<Product, NevekoError> {
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?; let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &pid.as_bytes().to_vec())
let r = db::DatabaseEnvironment::read(&s.env, handle, &pid.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() { if r.is_empty() {
error!("product not found"); error!("product not found");
@ -73,10 +67,9 @@ pub fn find(pid: &String) -> Result<Product, NevekoError> {
/// Product lookup for all /// Product lookup for all
pub fn find_all() -> Result<Vec<Product>, NevekoError> { pub fn find_all() -> Result<Vec<Product>, NevekoError> {
let i_s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let i_list_key = crate::PRODUCT_LIST_DB_KEY; let i_list_key = crate::PRODUCT_LIST_DB_KEY;
let handle = &i_s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?; let i_r = db::DatabaseEnvironment::read(&db.env, &db.handle, &i_list_key.as_bytes().to_vec())
let i_r = db::DatabaseEnvironment::read(&i_s.env, handle, &i_list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
if i_r.is_empty() { if i_r.is_empty() {
error!("product index not found"); error!("product index not found");
@ -106,13 +99,12 @@ pub fn modify(p: Json<Product>) -> Result<Product, NevekoError> {
return Err(NevekoError::Database(MdbError::NotFound)); return Err(NevekoError::Database(MdbError::NotFound));
} }
let u_prod = Product::update(f_prod, &p); let u_prod = Product::update(f_prod, &p);
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?; let _ = db::DatabaseEnvironment::delete(&db.env, &db.handle, u_prod.pid.as_bytes())
let _ = db::DatabaseEnvironment::delete(&s.env, handle, u_prod.pid.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
let product = bincode::serialize(&u_prod).unwrap_or_default(); let product = bincode::serialize(&u_prod).unwrap_or_default();
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
db::write_chunks(&s.env, handle, u_prod.pid.as_bytes(), &product) db::write_chunks(&db.env, &db.handle, u_prod.pid.as_bytes(), &product)
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(u_prod) Ok(u_prod)
} }

View file

@ -1,7 +1,7 @@
//! External authorization module via JWPs //! External authorization module via JWPs
use crate::{ use crate::{
db, error::NevekoError, monero, reqres, utils db::{self, DATABASE_LOCK}, error::NevekoError, monero, reqres, utils
}; };
use kn0sys_lmdb_rs::MdbError; use kn0sys_lmdb_rs::MdbError;
use log::{ use log::{
@ -120,12 +120,10 @@ pub async fn prove_payment(contact: String, txp: &TxProof) -> Result<reqres::Jwp
match res { match res {
Ok(r) => { Ok(r) => {
// cache the jwp for for fts // cache the jwp for for fts
let db = &DATABASE_LOCK;
let s = db::DatabaseEnvironment::open()?;
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &contact); let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &contact);
let _ = db::DatabaseEnvironment::delete(&s.env, &s.handle?, k.as_bytes())?; let _ = db::DatabaseEnvironment::delete(&db.env, &db.handle, k.as_bytes())?;
let s = db::DatabaseEnvironment::open()?; db::write_chunks(&db.env, &db.handle, &k.as_bytes(), &r.jwp.as_bytes().to_vec())
db::write_chunks(&s.env, &s.handle?, &k.as_bytes(), &r.jwp.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(r) Ok(r)
} }

View file

@ -2,7 +2,7 @@
//! authenticated user //! authenticated user
use crate::{ use crate::{
db, db::{self, DATABASE_LOCK},
models::*, models::*,
utils, utils,
}; };
@ -21,19 +21,17 @@ pub fn create(address: &String) -> Result<User, MdbError> {
name: String::new(), name: String::new(),
}; };
debug!("insert user: {:?}", &new_user); debug!("insert user: {:?}", &new_user);
let db = &DATABASE_LOCK;
let s = db::DatabaseEnvironment::open()?;
let k = &new_user.uid; let k = &new_user.uid;
let v = bincode::serialize(&new_user).unwrap_or_default(); let v = bincode::serialize(&new_user).unwrap_or_default();
db::write_chunks(&s.env, &s.handle?, k.as_bytes(), &v)?; db::write_chunks(&db.env, &db.handle, k.as_bytes(), &v)?;
Ok(new_user) Ok(new_user)
} }
/// User lookup /// User lookup
pub fn find(uid: &String) -> Result<User, MdbError> { pub fn find(uid: &String) -> Result<User, MdbError> {
let db = &DATABASE_LOCK;
let s = db::DatabaseEnvironment::open()?; let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &uid.as_bytes().to_vec())?;
let r = db::DatabaseEnvironment::read(&s.env, &s.handle?, &uid.as_bytes().to_vec())?;
if r.is_empty() { if r.is_empty() {
error!("user not found"); error!("user not found");
return Err(MdbError::NotFound); return Err(MdbError::NotFound);
@ -52,8 +50,8 @@ mod tests {
use super::*; use super::*;
fn cleanup(k: &String) -> Result<(), MdbError> { fn cleanup(k: &String) -> Result<(), MdbError> {
let s = db::DatabaseEnvironment::open()?; let db = &DATABASE_LOCK;
db::DatabaseEnvironment::delete(&s.env, &s.handle?, k.as_bytes()); db::DatabaseEnvironment::delete(&db.env, &db.handle, k.as_bytes());
Ok(()) Ok(())
} }
@ -64,8 +62,8 @@ mod tests {
"73a4nWuvkYoYoksGurDjKZQcZkmaxLaKbbeiKzHnMmqKivrCzq5Q2JtJG1UZNZFqLPbQ3MiXCk2Q5bdwdUNSr7X9QrPubkn" "73a4nWuvkYoYoksGurDjKZQcZkmaxLaKbbeiKzHnMmqKivrCzq5Q2JtJG1UZNZFqLPbQ3MiXCk2Q5bdwdUNSr7X9QrPubkn"
); );
let test_user = create(&address); let test_user = create(&address);
let s = db::DatabaseEnvironment::open()?; let db = &DATABASE_LOCK;
let r = db::DatabaseEnvironment::read(&s.env, &s.handle?, &test_user.uid); let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &test_user.uid);
let id = String::from(&test_user.uid); let id = String::from(&test_user.uid);
let cleanup_id = String::from(&test_user.uid); let cleanup_id = String::from(&test_user.uid);
let expected_user = User::from_db(id, r); let expected_user = User::from_db(id, r);
@ -83,8 +81,8 @@ mod tests {
xmr_address: address, xmr_address: address,
..Default::default() ..Default::default()
}; };
let s = db::DatabaseEnvironment::open()?; let db = &DATABASE_LOCK;
db::DatabaseEnvironment::write_chunks(&s.env, &s.handle?, k, &User::to_db(&expected_user)); db::DatabaseEnvironment::write_chunks(&db.env, &db.handle, k, &User::to_db(&expected_user));
let actual_user: User = find(&String::from(k)); let actual_user: User = find(&String::from(k));
assert_eq!(expected_user.xmr_address, actual_user.xmr_address); assert_eq!(expected_user.xmr_address, actual_user.xmr_address);
cleanup(&String::from(k)); cleanup(&String::from(k));

View file

@ -1,7 +1,7 @@
//! Generic functions for startup and convenience //! Generic functions for startup and convenience
use crate::{ use crate::{
args, contact, db, dispute, error::NevekoError, i2p, message, models, monero, neveko25519, reqres args, contact, db::{self, DATABASE_LOCK}, dispute, error::NevekoError, i2p, message, models, monero, neveko25519, reqres
}; };
use clap::Parser; use clap::Parser;
use kn0sys_lmdb_rs::MdbError; use kn0sys_lmdb_rs::MdbError;
@ -390,17 +390,16 @@ fn gen_signing_keys() -> Result<(), NevekoError> {
if jwp.is_empty() { if jwp.is_empty() {
let mut data = [0u8; 32]; let mut data = [0u8; 32];
rand::thread_rng().fill_bytes(&mut data); rand::thread_rng().fill_bytes(&mut data);
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?; db::write_chunks(&db.env, &db.handle, crate::NEVEKO_JWP_SECRET_KEY.as_bytes(), &data)
db::write_chunks(&s.env, handle, crate::NEVEKO_JWP_SECRET_KEY.as_bytes(), &data)
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
} }
if jwt.is_empty() { if jwt.is_empty() {
let mut data = [0u8; 32]; let mut data = [0u8; 32];
rand::thread_rng().fill_bytes(&mut data); rand::thread_rng().fill_bytes(&mut data);
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::write_chunks(&s.env, handle, crate::NEVEKO_JWT_SECRET_KEY.as_bytes(), &data) db::write_chunks(&db.env, &db.handle, crate::NEVEKO_JWT_SECRET_KEY.as_bytes(), &data)
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
} }
Ok(()) Ok(())
@ -410,20 +409,18 @@ fn gen_signing_keys() -> Result<(), NevekoError> {
/// ///
/// dont' forget to generate new keys as well /// dont' forget to generate new keys as well
pub fn revoke_signing_keys() -> Result<(), NevekoError> { pub fn revoke_signing_keys() -> Result<(), NevekoError> {
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?; db::DatabaseEnvironment::delete(&db.env, &db.handle, crate::NEVEKO_JWT_SECRET_KEY.as_bytes())
db::DatabaseEnvironment::delete(&s.env, handle, crate::NEVEKO_JWT_SECRET_KEY.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
db::DatabaseEnvironment::delete(&s.env, handle, crate::NEVEKO_JWP_SECRET_KEY.as_bytes()) db::DatabaseEnvironment::delete(&db.env, &db.handle, crate::NEVEKO_JWP_SECRET_KEY.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(()) Ok(())
} }
pub fn get_jwt_secret_key() -> Result<String, NevekoError> { pub fn get_jwt_secret_key() -> Result<String, NevekoError> {
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?; let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &crate::NEVEKO_JWT_SECRET_KEY.as_bytes().to_vec())
let r = db::DatabaseEnvironment::read(&s.env, handle, &crate::NEVEKO_JWT_SECRET_KEY.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() { if r.is_empty() {
error!("JWT key not found"); error!("JWT key not found");
@ -434,10 +431,8 @@ pub fn get_jwt_secret_key() -> Result<String, NevekoError> {
} }
pub fn get_jwp_secret_key() -> Result<String, NevekoError> { pub fn get_jwp_secret_key() -> Result<String, NevekoError> {
let db = &DATABASE_LOCK;
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &crate::NEVEKO_JWP_SECRET_KEY.as_bytes().to_vec())
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let r = db::DatabaseEnvironment::read(&s.env, handle, &crate::NEVEKO_JWP_SECRET_KEY.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() { if r.is_empty() {
error!("JWP key not found"); error!("JWP key not found");
@ -449,9 +444,8 @@ pub fn get_jwp_secret_key() -> Result<String, NevekoError> {
/// Returns the hex encoded neveko message public key from LMDB /// Returns the hex encoded neveko message public key from LMDB
pub fn get_nmpk() -> Result<String, NevekoError> { pub fn get_nmpk() -> Result<String, NevekoError> {
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?; let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &crate::NEVEKO_NMPK.as_bytes().to_vec())
let r = db::DatabaseEnvironment::read(&s.env, handle, &crate::NEVEKO_NMPK.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() { if r.is_empty() {
error!("neveko message public key not found"); error!("neveko message public key not found");
@ -465,11 +459,11 @@ async fn generate_nmpk() -> Result<(), NevekoError> {
info!("generating neveko message public key"); info!("generating neveko message public key");
let nmpk: String = get_nmpk()?; let nmpk: String = get_nmpk()?;
// send to db // send to db
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?; let db = &DATABASE_LOCK;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if nmpk.is_empty() { if nmpk.is_empty() {
let nmk: neveko25519::NevekoMessageKeys = neveko25519::generate_neveko_message_keys().await; let nmk: neveko25519::NevekoMessageKeys = neveko25519::generate_neveko_message_keys().await;
db::write_chunks(&s.env, handle, crate::NEVEKO_NMPK.as_bytes(), nmk.hex_nmpk.as_bytes()) db::write_chunks(&db.env, &db.handle, crate::NEVEKO_NMPK.as_bytes(), nmk.hex_nmpk.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
} }
Ok(()) Ok(())
@ -571,10 +565,8 @@ pub fn restart_dispute_auto_settle() {
/// Called on app startup if `--clear-fts` flag is passed. /// Called on app startup if `--clear-fts` flag is passed.
fn clear_fts() -> Result<(), NevekoError> { fn clear_fts() -> Result<(), NevekoError> {
info!("clear fts"); info!("clear fts");
let s = db::DatabaseEnvironment::open() let db = &DATABASE_LOCK;
.map_err(|_| NevekoError::Database(MdbError::Panic))?; db::DatabaseEnvironment::delete(&db.env, &db.handle, crate::FTS_DB_KEY.as_bytes())
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::DatabaseEnvironment::delete(&s.env, handle, crate::FTS_DB_KEY.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(()) Ok(())
} }
@ -582,10 +574,8 @@ fn clear_fts() -> Result<(), NevekoError> {
/// Called on app startup if `--clear-dispute` flag is passed. /// Called on app startup if `--clear-dispute` flag is passed.
fn clear_disputes() -> Result<(), NevekoError> { fn clear_disputes() -> Result<(), NevekoError> {
info!("clear_disputes"); info!("clear_disputes");
let s = db::DatabaseEnvironment::open() let db = &DATABASE_LOCK;
.map_err(|_| NevekoError::Database(MdbError::Panic))?; db::DatabaseEnvironment::delete(&db.env, &db.handle, crate::DISPUTE_LIST_DB_KEY.as_bytes())
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::DatabaseEnvironment::delete(&s.env, handle, crate::DISPUTE_LIST_DB_KEY.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?; .map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(()) Ok(())
} }
@ -695,25 +685,24 @@ pub async fn can_transfer(invoice: u128) -> bool {
/// Gui toggle for vendor mode /// Gui toggle for vendor mode
pub fn toggle_vendor_enabled() -> Result<bool, MdbError> { pub fn toggle_vendor_enabled() -> Result<bool, MdbError> {
// TODO(c2m): Dont toggle vendors with orders status != Delivered // TODO(c2m): Dont toggle vendors with orders status != Delivered
let s = db::DatabaseEnvironment::open()?; let db = &DATABASE_LOCK;
let r = db::DatabaseEnvironment::read(&s.env, &s.handle?, &contact::NEVEKO_VENDOR_ENABLED.as_bytes().to_vec())?; 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(); let mode: String = bincode::deserialize(&r[..]).unwrap_or_default();
if mode != contact::NEVEKO_VENDOR_MODE_ON { if mode != contact::NEVEKO_VENDOR_MODE_ON {
info!("neveko vendor mode enabled"); info!("neveko vendor mode enabled");
let s = db::DatabaseEnvironment::open()?;
db::write_chunks( db::write_chunks(
&s.env, &db.env,
&s.handle?, &db.handle,
contact::NEVEKO_VENDOR_ENABLED.as_bytes(), contact::NEVEKO_VENDOR_ENABLED.as_bytes(),
contact::NEVEKO_VENDOR_MODE_ON.as_bytes(), contact::NEVEKO_VENDOR_MODE_ON.as_bytes(),
)?; )?;
Ok(true) Ok(true)
} else { } else {
info!("neveko vendor mode disabled"); info!("neveko vendor mode disabled");
let s = db::DatabaseEnvironment::open()?;
db::write_chunks( db::write_chunks(
&s.env, &db.env,
&s.handle?, &db.handle,
contact::NEVEKO_VENDOR_ENABLED.as_bytes(), contact::NEVEKO_VENDOR_ENABLED.as_bytes(),
contact::NEVEKO_VENDOR_MODE_OFF.as_bytes(), contact::NEVEKO_VENDOR_MODE_OFF.as_bytes(),
)?; )?;
@ -722,24 +711,24 @@ pub fn toggle_vendor_enabled() -> Result<bool, MdbError> {
} }
pub fn search_gui_db(f: String, data: String) -> Result<String, MdbError> { pub fn search_gui_db(f: String, data: String) -> Result<String, MdbError> {
let s = db::DatabaseEnvironment::open()?; let db = &DATABASE_LOCK;
let k = format!("{}-{}", f, data); let k = format!("{}-{}", f, data);
let r = db::DatabaseEnvironment::read(&s.env, &s.handle?, &k.as_bytes().to_vec())?; let r = db::DatabaseEnvironment::read(&db.env, &db.handle, &k.as_bytes().to_vec())?;
let result: String = bincode::deserialize(&r[..]).unwrap_or_default(); let result: String = bincode::deserialize(&r[..]).unwrap_or_default();
Ok(result) Ok(result)
} }
pub fn write_gui_db(f: String, key: String, data: String) -> Result<(), MdbError> { pub fn write_gui_db(f: String, key: String, data: String) -> Result<(), MdbError> {
let s = db::DatabaseEnvironment::open()?; let db = &DATABASE_LOCK;
let k = format!("{}-{}", f, key); let k = format!("{}-{}", f, key);
db::write_chunks(&s.env, &s.handle?, k.as_bytes(), data.as_bytes())?; db::write_chunks(&db.env, &db.handle, k.as_bytes(), data.as_bytes())?;
Ok(()) Ok(())
} }
pub fn clear_gui_db(f: String, key: String) -> Result<(), MdbError> { pub fn clear_gui_db(f: String, key: String) -> Result<(), MdbError> {
let s = db::DatabaseEnvironment::open()?; let db = &DATABASE_LOCK;
let k = format!("{}-{}", f, key); let k = format!("{}-{}", f, key);
db::DatabaseEnvironment::delete(&s.env, &s.handle?, k.as_bytes())?; db::DatabaseEnvironment::delete(&db.env, &db.handle, k.as_bytes())?;
Ok(()) Ok(())
} }

View file

@ -1,4 +1,5 @@
use crate::CREDENTIAL_KEY; use crate::CREDENTIAL_KEY;
use db::DATABASE_LOCK;
use neveko_core::*; use neveko_core::*;
use sha2::{ use sha2::{
Digest, Digest,
@ -62,10 +63,10 @@ impl eframe::App for LockScreenApp {
self.lock_screen.credential.clone(), self.lock_screen.credential.clone(),
); );
// Get the credential hash from lmdb // Get the credential hash from lmdb
let s = db::DatabaseEnvironment::open().unwrap(); let db = &DATABASE_LOCK;
let r = db::DatabaseEnvironment::read( let r = db::DatabaseEnvironment::read(
&s.env, &db.env,
&s.handle.unwrap(), &db.handle,
&CREDENTIAL_KEY.as_bytes().to_vec(), &CREDENTIAL_KEY.as_bytes().to_vec(),
).unwrap(); ).unwrap();
// hash the text entered and compare // hash the text entered and compare

View file

@ -1,3 +1,4 @@
use db::DATABASE_LOCK;
use egui::RichText; use egui::RichText;
use image::Luma; use image::Luma;
use neveko_core::*; use neveko_core::*;
@ -140,12 +141,12 @@ impl Default for MarketApp {
let (_refresh_on_delete_product_tx, _refresh_on_delete_product_rx) = let (_refresh_on_delete_product_tx, _refresh_on_delete_product_rx) =
std::sync::mpsc::channel(); std::sync::mpsc::channel();
let read_product_image = std::fs::read("./assets/qr.png").unwrap_or(Vec::new()); let read_product_image = std::fs::read("./assets/qr.png").unwrap_or(Vec::new());
let s = db::DatabaseEnvironment::open().unwrap(); let db = &DATABASE_LOCK;
let r = db::DatabaseEnvironment::read( let r = db::DatabaseEnvironment::read(
&s.env, &db.env,
&s.handle.unwrap(), &db.handle,
&contact::NEVEKO_VENDOR_ENABLED.as_bytes().to_vec(), &contact::NEVEKO_VENDOR_ENABLED.as_bytes().to_vec(),
).unwrap(); ).unwrap_or_default();
let sr: String = bincode::deserialize(&r[..]).unwrap_or_default(); let sr: String = bincode::deserialize(&r[..]).unwrap_or_default();
let is_vendor_enabled = sr == contact::NEVEKO_VENDOR_MODE_ON; let is_vendor_enabled = sr == contact::NEVEKO_VENDOR_MODE_ON;
let (contact_info_tx, contact_info_rx) = std::sync::mpsc::channel(); let (contact_info_tx, contact_info_rx) = std::sync::mpsc::channel();
@ -1882,7 +1883,7 @@ fn send_prepare_info_req(
).unwrap(); ).unwrap();
// Request adjudicator and vendor while we're at it // Request adjudicator and vendor while we're at it
// Will coordinating send this on make requests next // Will coordinating send this on make requests next
let s = db::DatabaseEnvironment::open().unwrap(); let db = &DATABASE_LOCK;
let m_msig_key = format!( let m_msig_key = format!(
"{}-{}-{}", "{}-{}-{}",
message::PREPARE_MSIG, message::PREPARE_MSIG,
@ -1895,9 +1896,10 @@ fn send_prepare_info_req(
String::from(&v_orid), String::from(&v_orid),
vendor vendor
); );
let m_prepare = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &m_msig_key.as_bytes().to_vec()).unwrap(); let m_prepare = db::DatabaseEnvironment::read(&db.env, &db.handle, &m_msig_key.as_bytes().to_vec())
let s = db::DatabaseEnvironment::open().unwrap(); .unwrap_or_default();
let v_prepare = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &v_msig_key.as_bytes().to_vec()).unwrap(); let v_prepare = db::DatabaseEnvironment::read(&db.env, &db.handle, &v_msig_key.as_bytes().to_vec())
.unwrap_or_default();
if v_prepare.is_empty() { if v_prepare.is_empty() {
log::debug!( log::debug!(
"constructing vendor {} msig messages", "constructing vendor {} msig messages",
@ -1969,7 +1971,7 @@ fn send_make_info_req(
String::from(crate::GUI_MSIG_PREPARE_DB_KEY), String::from(crate::GUI_MSIG_PREPARE_DB_KEY),
String::from(&w_orid), String::from(&w_orid),
); );
let s = db::DatabaseEnvironment::open().unwrap(); let db = &DATABASE_LOCK;
let m_msig_key = format!( let m_msig_key = format!(
"{}-{}-{}", "{}-{}-{}",
message::PREPARE_MSIG, message::PREPARE_MSIG,
@ -1982,10 +1984,11 @@ fn send_make_info_req(
String::from(&v_orid), String::from(&v_orid),
vendor vendor
); );
let m_prepare = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &m_msig_key.as_bytes().to_vec()).unwrap(); let m_prepare = db::DatabaseEnvironment::read(&db.env, &db.handle, &m_msig_key.as_bytes().to_vec())
.unwrap_or_default();
let sm_prepare: String = bincode::deserialize(&m_prepare[..]).unwrap_or_default(); let sm_prepare: String = bincode::deserialize(&m_prepare[..]).unwrap_or_default();
let s = db::DatabaseEnvironment::open().unwrap(); let v_prepare = db::DatabaseEnvironment::read(&db.env, &db.handle, &v_msig_key.as_bytes().to_vec())
let v_prepare = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &v_msig_key.as_bytes().to_vec()).unwrap(); .unwrap_or_default();
let sv_prepare: String = bincode::deserialize(&&v_prepare[..]).unwrap_or_default(); let sv_prepare: String = bincode::deserialize(&&v_prepare[..]).unwrap_or_default();
prepare_info_prep.push(String::from(&sm_prepare)); prepare_info_prep.push(String::from(&sm_prepare));
prepare_info_prep.push(String::from(&sv_prepare)); prepare_info_prep.push(String::from(&sv_prepare));
@ -2012,7 +2015,6 @@ fn send_make_info_req(
} }
// Request adjudicator and vendor while we're at it // Request adjudicator and vendor while we're at it
// Will coordinating send this on make requests next // Will coordinating send this on make requests next
let s = db::DatabaseEnvironment::open().unwrap();
let m_msig_key = format!( let m_msig_key = format!(
"{}-{}-{}", "{}-{}-{}",
message::MAKE_MSIG, message::MAKE_MSIG,
@ -2025,9 +2027,10 @@ fn send_make_info_req(
String::from(&v_orid), String::from(&v_orid),
vendor vendor
); );
let m_make = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &m_msig_key.as_bytes().to_vec()).unwrap(); let m_make = db::DatabaseEnvironment::read(&db.env, &db.handle, &m_msig_key.as_bytes().to_vec())
let s = db::DatabaseEnvironment::open().unwrap(); .unwrap_or_default();
let v_make = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &v_msig_key.as_bytes().to_vec()).unwrap(); let v_make = db::DatabaseEnvironment::read(&db.env, &db.handle, &v_msig_key.as_bytes().to_vec())
.unwrap_or_default();
if v_make.is_empty() { if v_make.is_empty() {
log::debug!("constructing vendor {} msig messages", message::MAKE_MSIG); log::debug!("constructing vendor {} msig messages", message::MAKE_MSIG);
let v_msig_request: reqres::MultisigInfoRequest = reqres::MultisigInfoRequest { let v_msig_request: reqres::MultisigInfoRequest = reqres::MultisigInfoRequest {
@ -2096,7 +2099,7 @@ fn send_kex_initial_req(
String::from(crate::GUI_MSIG_MAKE_DB_KEY), String::from(crate::GUI_MSIG_MAKE_DB_KEY),
String::from(&w_orid), String::from(&w_orid),
).unwrap_or_default(); ).unwrap_or_default();
let s = db::DatabaseEnvironment::open().unwrap(); let db = &DATABASE_LOCK;
let m_msig_key = format!( let m_msig_key = format!(
"{}-{}-{}", "{}-{}-{}",
message::MAKE_MSIG, message::MAKE_MSIG,
@ -2109,10 +2112,11 @@ fn send_kex_initial_req(
String::from(&v_orid), String::from(&v_orid),
vendor vendor
); );
let m_kex_init = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &m_msig_key.as_bytes().to_vec()).unwrap(); let m_kex_init = db::DatabaseEnvironment::read(&db.env, &db.handle, &m_msig_key.as_bytes().to_vec())
.unwrap_or_default();
let sm_kex_init: String = bincode::deserialize(&m_kex_init[..]).unwrap_or_default(); let sm_kex_init: String = bincode::deserialize(&m_kex_init[..]).unwrap_or_default();
let s = db::DatabaseEnvironment::open().unwrap(); let v_kex_init = db::DatabaseEnvironment::read(&db.env, &db.handle, &v_msig_key.as_bytes().to_vec())
let v_kex_init = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &v_msig_key.as_bytes().to_vec()).unwrap(); .unwrap_or_default();
let sv_kex_init: String = bincode::deserialize(&v_kex_init[..]).unwrap_or_default(); let sv_kex_init: String = bincode::deserialize(&v_kex_init[..]).unwrap_or_default();
kex_init_prep.push(String::from(&sm_kex_init)); kex_init_prep.push(String::from(&sm_kex_init));
kex_init_prep.push(String::from(&sv_kex_init)); kex_init_prep.push(String::from(&sv_kex_init));
@ -2139,7 +2143,6 @@ fn send_kex_initial_req(
} }
// Request adjudicator and vendor while we're at it // Request adjudicator and vendor while we're at it
// Will coordinating send this on kex round two next // Will coordinating send this on kex round two next
let s = db::DatabaseEnvironment::open().unwrap();
let m_msig_key = format!( let m_msig_key = format!(
"{}-{}-{}", "{}-{}-{}",
message::KEX_ONE_MSIG, message::KEX_ONE_MSIG,
@ -2152,9 +2155,10 @@ fn send_kex_initial_req(
String::from(&v_orid), String::from(&v_orid),
vendor vendor
); );
let m_kex_init = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &m_msig_key.as_bytes().to_vec()).unwrap(); let m_kex_init = db::DatabaseEnvironment::read(&db.env, &db.handle, &m_msig_key.as_bytes().to_vec())
let s = db::DatabaseEnvironment::open().unwrap(); .unwrap_or_default();
let v_kex_init = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &v_msig_key.as_bytes().to_vec()).unwrap(); let v_kex_init = db::DatabaseEnvironment::read(&db.env, &db.handle, &v_msig_key.as_bytes().to_vec())
.unwrap_or_default();
if v_kex_init.is_empty() { if v_kex_init.is_empty() {
log::debug!( log::debug!(
"constructing vendor {} msig messages", "constructing vendor {} msig messages",
@ -2224,7 +2228,7 @@ fn send_kex_final_req(
String::from(crate::GUI_MSIG_KEX_ONE_DB_KEY), String::from(crate::GUI_MSIG_KEX_ONE_DB_KEY),
String::from(&w_orid), String::from(&w_orid),
).unwrap_or_default(); ).unwrap_or_default();
let s = db::DatabaseEnvironment::open().unwrap(); let db = &DATABASE_LOCK;
let m_msig_key = format!( let m_msig_key = format!(
"{}-{}-{}", "{}-{}-{}",
message::KEX_ONE_MSIG, message::KEX_ONE_MSIG,
@ -2237,9 +2241,10 @@ fn send_kex_final_req(
String::from(&v_orid), String::from(&v_orid),
vendor vendor
); );
let r_m_kex_final = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &m_msig_key.as_bytes().to_vec()).unwrap(); let r_m_kex_final = db::DatabaseEnvironment::read(&db.env, &db.handle, &m_msig_key.as_bytes().to_vec())
let s = db::DatabaseEnvironment::open().unwrap(); .unwrap_or_default();
let r_v_kex_final = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &v_msig_key.as_bytes().to_vec()).unwrap(); let r_v_kex_final = db::DatabaseEnvironment::read(&db.env, &db.handle, &v_msig_key.as_bytes().to_vec())
.unwrap_or_default();
let m_kex_final: String = bincode::deserialize(&r_m_kex_final[..]).unwrap_or_default(); let m_kex_final: String = bincode::deserialize(&r_m_kex_final[..]).unwrap_or_default();
let v_kex_final: String = bincode::deserialize(&r_v_kex_final[..]).unwrap_or_default(); let v_kex_final: String = bincode::deserialize(&r_v_kex_final[..]).unwrap_or_default();
kex_final_prep.push(String::from(&m_kex_final)); kex_final_prep.push(String::from(&m_kex_final));
@ -2266,7 +2271,6 @@ fn send_kex_final_req(
} }
} }
// we can verify all good if the senders all send back the correct wallet address // we can verify all good if the senders all send back the correct wallet address
let s = db::DatabaseEnvironment::open().unwrap();
let m_msig_key = format!( let m_msig_key = format!(
"{}-{}-{}", "{}-{}-{}",
message::KEX_TWO_MSIG, message::KEX_TWO_MSIG,
@ -2279,9 +2283,10 @@ fn send_kex_final_req(
String::from(&v_orid), String::from(&v_orid),
vendor vendor
); );
let m_kex_final = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &m_msig_key.as_bytes().to_vec()).unwrap(); let m_kex_final = db::DatabaseEnvironment::read(&db.env, &db.handle, &m_msig_key.as_bytes().to_vec())
let s = db::DatabaseEnvironment::open().unwrap(); .unwrap_or_default();
let v_kex_final = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &v_msig_key.as_bytes().to_vec()).unwrap(); let v_kex_final = db::DatabaseEnvironment::read(&db.env, &db.handle, &v_msig_key.as_bytes().to_vec())
.unwrap_or_default();
if v_kex_final.is_empty() { if v_kex_final.is_empty() {
log::debug!( log::debug!(
"constructing vendor {} msig messages", "constructing vendor {} msig messages",
@ -2400,14 +2405,15 @@ fn send_import_info_req(tx: Sender<String>, ctx: egui::Context, orid: &String, v
).unwrap_or_default(); ).unwrap_or_default();
// Request vendor while we're at it // Request vendor while we're at it
// Will coordinating send this on make requests next // Will coordinating send this on make requests next
let s = db::DatabaseEnvironment::open().unwrap(); let db = &DATABASE_LOCK;
let v_msig_key = format!( let v_msig_key = format!(
"{}-{}-{}", "{}-{}-{}",
message::EXPORT_MSIG, message::EXPORT_MSIG,
String::from(&v_orid), String::from(&v_orid),
vendor vendor
); );
let v_export = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &v_msig_key.as_bytes().to_vec()).unwrap(); let v_export = db::DatabaseEnvironment::read(&db.env, &db.handle, &v_msig_key.as_bytes().to_vec())
.unwrap_or_default();
if v_export.is_empty() { if v_export.is_empty() {
log::debug!("constructing vendor {} msig messages", message::EXPORT_MSIG); log::debug!("constructing vendor {} msig messages", message::EXPORT_MSIG);
let v_msig_request: reqres::MultisigInfoRequest = reqres::MultisigInfoRequest { let v_msig_request: reqres::MultisigInfoRequest = reqres::MultisigInfoRequest {
@ -2469,12 +2475,13 @@ fn validate_msig_step(
vendor: &String, vendor: &String,
sub_type: &String, sub_type: &String,
) -> bool { ) -> bool {
let s = db::DatabaseEnvironment::open().unwrap(); let db = &DATABASE_LOCK;
let m_msig_key = format!("{}-{}-{}", sub_type, orid, adjudicator); let m_msig_key = format!("{}-{}-{}", sub_type, orid, adjudicator);
let v_msig_key = format!("{}-{}-{}", sub_type, orid, vendor); let v_msig_key = format!("{}-{}-{}", sub_type, orid, vendor);
let r_m_info = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &m_msig_key.as_bytes().to_vec()).unwrap(); let r_m_info = db::DatabaseEnvironment::read(&db.env, &db.handle, &m_msig_key.as_bytes().to_vec())
let s = db::DatabaseEnvironment::open().unwrap(); .unwrap_or_default();
let r_v_info = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &v_msig_key.as_bytes().to_vec()).unwrap(); let r_v_info = db::DatabaseEnvironment::read(&db.env, &db.handle, &v_msig_key.as_bytes().to_vec())
.unwrap_or_default();
let m_info: String = bincode::deserialize(&&r_m_info[..]).unwrap_or_default(); let m_info: String = bincode::deserialize(&&r_m_info[..]).unwrap_or_default();
let v_info: String = bincode::deserialize(&&r_v_info[..]).unwrap_or_default(); let v_info: String = bincode::deserialize(&&r_v_info[..]).unwrap_or_default();
log::debug!("{} adjudicator info: {}", sub_type, &m_info); log::debug!("{} adjudicator info: {}", sub_type, &m_info);

View file

@ -1,3 +1,4 @@
use db::DATABASE_LOCK;
use neveko_core::*; use neveko_core::*;
use sha2::{ use sha2::{
Digest, Digest,
@ -63,17 +64,15 @@ impl eframe::App for SettingsApp {
} }
if ui.button("Change").clicked() { if ui.button("Change").clicked() {
self.is_loading = true; self.is_loading = true;
let db = &DATABASE_LOCK;
// TODO: don't open the database in the GUI
let s = db::DatabaseEnvironment::open().unwrap();
let k = CREDENTIAL_KEY; let k = CREDENTIAL_KEY;
let _ = db::DatabaseEnvironment::delete(&s.env, &s.handle.unwrap(), k.as_bytes()).unwrap(); 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(); let mut hasher = Sha512::new();
hasher.update(self.credential.clone()); hasher.update(self.credential.clone());
let result = hasher.finalize(); let result = hasher.finalize();
let s = db::DatabaseEnvironment::open().unwrap(); db::write_chunks(&db.env, &db.handle, k.as_bytes(), hex::encode(&result[..]).as_bytes())
db::write_chunks(&s.env, &s.handle.unwrap(), k.as_bytes(), hex::encode(&result[..]).as_bytes()).unwrap(); .unwrap_or_else(|_| log::error!("failed to write credential"));
// update wallet rpc // update wallet rpc
change_wallet_password( change_wallet_password(
self.change_wallet_password_tx.clone(), self.change_wallet_password_tx.clone(),

View file

@ -1,4 +1,5 @@
use crate::CREDENTIAL_KEY; use crate::CREDENTIAL_KEY;
use db::DATABASE_LOCK;
use neveko_core::*; use neveko_core::*;
use sha2::{ use sha2::{
Digest, Digest,
@ -54,8 +55,9 @@ impl eframe::App for LoginApp {
let mut hasher = Sha512::new(); let mut hasher = Sha512::new();
hasher.update(self.credential.clone()); hasher.update(self.credential.clone());
let result = hasher.finalize(); let result = hasher.finalize();
let s = db::DatabaseEnvironment::open().unwrap(); let db = &DATABASE_LOCK;
db::write_chunks(&s.env, &s.handle.unwrap(), k.as_bytes(), hex::encode(&result[..]).as_bytes()).unwrap(); db::write_chunks(&db.env, &db.handle, k.as_bytes(), hex::encode(&result[..]).as_bytes())
.unwrap_or_else(|_| log::error!("failed to set credential"));
self.credential = String::new(); self.credential = String::new();
} }
}); });

View file

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