Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7c3d4b7bd7 |
@@ -3,27 +3,8 @@ import fetch from "node-fetch";
|
||||
import { Octokit } from "@octokit/rest";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { execSync } from "child_process";
|
||||
|
||||
function getBinInfo(path) {
|
||||
// let's be super naive about it. add a+x bits on the file and try to run the command
|
||||
try {
|
||||
let mode = fs.statSync(path).mode
|
||||
fs.chmodSync(path, mode | 0o111)
|
||||
|
||||
const raw = execSync(`${path} build-info --output=json`, { stdio: 'pipe', encoding: "utf8" });
|
||||
const parsed = JSON.parse(raw)
|
||||
return parsed
|
||||
} catch (_) {
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
async function run(assets, algorithm, filename, cache) {
|
||||
if (!cache) {
|
||||
console.warn("cache is set to 'false', but we we no longer support it")
|
||||
}
|
||||
|
||||
try {
|
||||
fs.mkdirSync('.tmp');
|
||||
} catch(e) {
|
||||
@@ -38,25 +19,26 @@ async function run(assets, algorithm, filename, cache) {
|
||||
|
||||
let buffer = null;
|
||||
let sig = null;
|
||||
if(cache) {
|
||||
// cache in `${WORKING_DIR}/.tmp/`
|
||||
const cacheFilename = path.resolve(`.tmp/${asset.name}`);
|
||||
if(!fs.existsSync(cacheFilename)) {
|
||||
console.log(`Downloading ${asset.browser_download_url}... to ${cacheFilename}`);
|
||||
buffer = Buffer.from(await fetch(asset.browser_download_url).then(res => res.arrayBuffer()));
|
||||
fs.writeFileSync(cacheFilename, buffer);
|
||||
} else {
|
||||
console.log(`Loading from ${cacheFilename}`);
|
||||
buffer = Buffer.from(fs.readFileSync(cacheFilename));
|
||||
|
||||
// cache in `${WORKING_DIR}/.tmp/`
|
||||
const cacheFilename = path.resolve(`.tmp/${asset.name}`);
|
||||
if(!fs.existsSync(cacheFilename)) {
|
||||
console.log(`Downloading ${asset.browser_download_url}... to ${cacheFilename}`);
|
||||
buffer = Buffer.from(await fetch(asset.browser_download_url).then(res => res.arrayBuffer()));
|
||||
fs.writeFileSync(cacheFilename, buffer);
|
||||
// console.log('Reading signature from content');
|
||||
// if(asset.name.endsWith('.sig')) {
|
||||
// sig = fs.readFileSync(cacheFilename).toString();
|
||||
// }
|
||||
}
|
||||
} else {
|
||||
console.log(`Loading from ${cacheFilename}`);
|
||||
buffer = Buffer.from(fs.readFileSync(cacheFilename));
|
||||
|
||||
// console.log('Reading signature from content');
|
||||
// if(asset.name.endsWith('.sig')) {
|
||||
// sig = fs.readFileSync(cacheFilename).toString();
|
||||
// }
|
||||
// fetch always
|
||||
buffer = Buffer.from(await fetch(asset.browser_download_url).then(res => res.arrayBuffer()));
|
||||
}
|
||||
|
||||
const binInfo = getBinInfo(cacheFilename)
|
||||
|
||||
if(!hashes[asset.name]) {
|
||||
hashes[asset.name] = {};
|
||||
}
|
||||
@@ -117,9 +99,6 @@ async function run(assets, algorithm, filename, cache) {
|
||||
if(kind) {
|
||||
hashes[asset.name].kind = kind;
|
||||
}
|
||||
if(binInfo) {
|
||||
hashes[asset.name].details = binInfo;
|
||||
}
|
||||
|
||||
// process Tauri signature files
|
||||
if(asset.name.endsWith('.sig')) {
|
||||
@@ -246,8 +225,6 @@ export async function createHashesFromReleaseTagOrNameOrId({ releaseTagOrNameOrI
|
||||
assets: hashes,
|
||||
};
|
||||
|
||||
console.log(output)
|
||||
|
||||
if(upload) {
|
||||
console.log(`🚚 Uploading ${filename} to release name="${release.name}" id=${release.id} (${release.upload_url})...`);
|
||||
|
||||
|
||||
@@ -6521,6 +6521,7 @@ dependencies = [
|
||||
"nym-validator-client",
|
||||
"nym-wireguard",
|
||||
"once_cell",
|
||||
"pretty_env_logger",
|
||||
"rand 0.7.3",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
@@ -6722,6 +6723,7 @@ dependencies = [
|
||||
"nym-types",
|
||||
"nym-validator-client",
|
||||
"opentelemetry",
|
||||
"pretty_env_logger",
|
||||
"rand 0.7.3",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -6746,7 +6748,6 @@ dependencies = [
|
||||
"log",
|
||||
"nym-bin-common",
|
||||
"nym-crypto",
|
||||
"nym-mixnet-contract-common",
|
||||
"nym-network-defaults",
|
||||
"nym-sphinx-acknowledgements",
|
||||
"nym-sphinx-addressing",
|
||||
@@ -6756,7 +6757,6 @@ dependencies = [
|
||||
"nym-sphinx-types",
|
||||
"nym-task",
|
||||
"nym-validator-client",
|
||||
"parking_lot 0.12.1",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
"thiserror",
|
||||
@@ -7594,36 +7594,6 @@ dependencies = [
|
||||
"x25519-dalek 2.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nymvisor"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-file-watcher",
|
||||
"bytes",
|
||||
"clap 4.4.7",
|
||||
"dotenvy",
|
||||
"flate2",
|
||||
"futures",
|
||||
"hex",
|
||||
"humantime 2.1.0",
|
||||
"humantime-serde",
|
||||
"nix 0.27.1",
|
||||
"nym-bin-common",
|
||||
"nym-config",
|
||||
"nym-task",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2 0.10.8",
|
||||
"tar",
|
||||
"thiserror",
|
||||
"time",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.32.1"
|
||||
@@ -9024,12 +8994,10 @@ dependencies = [
|
||||
"tokio-native-tls",
|
||||
"tokio-rustls 0.24.1",
|
||||
"tokio-socks",
|
||||
"tokio-util",
|
||||
"tower-service",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"wasm-streams",
|
||||
"web-sys",
|
||||
"winreg",
|
||||
]
|
||||
@@ -10615,17 +10583,6 @@ version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
||||
|
||||
[[package]]
|
||||
name = "tar"
|
||||
version = "0.4.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb"
|
||||
dependencies = [
|
||||
"filetime",
|
||||
"libc",
|
||||
"xattr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.8.0"
|
||||
@@ -11990,19 +11947,6 @@ dependencies = [
|
||||
"wasm-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-streams"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4609d447824375f43e1ffbc051b50ad8f4b3ae8219680c94452ea05eb240ac7"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-timer"
|
||||
version = "0.2.5"
|
||||
@@ -12627,15 +12571,6 @@ dependencies = [
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xattr"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4686009f71ff3e5c4dbcf1a282d0a44db3f021ba69350cd42086b3e5f1c6985"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yamux"
|
||||
version = "0.10.2"
|
||||
|
||||
@@ -105,7 +105,6 @@ members = [
|
||||
"tools/internal/sdk-version-bump",
|
||||
"tools/nym-cli",
|
||||
"tools/nym-nr-query",
|
||||
"tools/nymvisor",
|
||||
"tools/ts-rs-cli",
|
||||
"wasm/client",
|
||||
# "wasm/full-nym-wasm",
|
||||
@@ -121,7 +120,6 @@ default-members = [
|
||||
"service-providers/network-statistics",
|
||||
"mixnode",
|
||||
"nym-api",
|
||||
"tools/nymvisor",
|
||||
"explorer-api",
|
||||
]
|
||||
|
||||
@@ -160,12 +158,9 @@ schemars = "0.8.1"
|
||||
serde = "1.0.152"
|
||||
serde_json = "1.0.91"
|
||||
tap = "1.0.1"
|
||||
time = "0.3.30"
|
||||
thiserror = "1.0.48"
|
||||
tokio = "1.33.0"
|
||||
tokio-stream = "0.1.14"
|
||||
tokio = "1.24.1"
|
||||
tokio-tungstenite = "0.20.1"
|
||||
tokio-util = "0.7.9"
|
||||
tracing = "0.1.37"
|
||||
tungstenite = { version = "0.20.1", default-features = false }
|
||||
ts-rs = "7.0.0"
|
||||
|
||||
@@ -1,675 +0,0 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means tocopy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||
|
||||
@@ -10,8 +10,6 @@ use std::path::{Path, PathBuf};
|
||||
use std::time::Duration;
|
||||
use tokio::time::Instant;
|
||||
|
||||
pub use notify::{Error as NotifyError, Result as NotifyResult};
|
||||
|
||||
pub type FileWatcherEventSender = mpsc::UnboundedSender<Event>;
|
||||
pub type FileWatcherEventReceiver = mpsc::UnboundedReceiver<Event>;
|
||||
|
||||
@@ -24,7 +22,7 @@ pub struct AsyncFileWatcher {
|
||||
last_received: HashMap<EventKind, Instant>,
|
||||
tick_duration: Duration,
|
||||
|
||||
inner_rx: mpsc::UnboundedReceiver<NotifyResult<Event>>,
|
||||
inner_rx: mpsc::UnboundedReceiver<notify::Result<Event>>,
|
||||
event_sender: FileWatcherEventSender,
|
||||
}
|
||||
|
||||
@@ -32,7 +30,7 @@ impl AsyncFileWatcher {
|
||||
pub fn new_file_changes_watcher<P: AsRef<Path>>(
|
||||
path: P,
|
||||
event_sender: FileWatcherEventSender,
|
||||
) -> NotifyResult<Self> {
|
||||
) -> notify::Result<Self> {
|
||||
Self::new(
|
||||
path,
|
||||
event_sender,
|
||||
@@ -50,7 +48,7 @@ impl AsyncFileWatcher {
|
||||
event_sender: FileWatcherEventSender,
|
||||
filters: Option<Vec<EventKind>>,
|
||||
tick_duration: Option<Duration>,
|
||||
) -> NotifyResult<Self> {
|
||||
) -> notify::Result<Self> {
|
||||
let watcher_config = Config::default();
|
||||
let (inner_tx, inner_rx) = mpsc::unbounded();
|
||||
let watcher = RecommendedWatcher::new(
|
||||
@@ -114,17 +112,17 @@ impl AsyncFileWatcher {
|
||||
false
|
||||
}
|
||||
|
||||
fn start_watching(&mut self) -> NotifyResult<()> {
|
||||
fn start_watching(&mut self) -> notify::Result<()> {
|
||||
self.is_watching = true;
|
||||
self.watcher.watch(&self.path, RecursiveMode::NonRecursive)
|
||||
}
|
||||
|
||||
fn stop_watching(&mut self) -> NotifyResult<()> {
|
||||
fn stop_watching(&mut self) -> notify::Result<()> {
|
||||
self.is_watching = false;
|
||||
self.watcher.unwatch(&self.path)
|
||||
}
|
||||
|
||||
pub async fn watch(&mut self) -> NotifyResult<()> {
|
||||
pub async fn watch(&mut self) -> notify::Result<()> {
|
||||
self.start_watching()?;
|
||||
|
||||
while let Some(event) = self.inner_rx.next().await {
|
||||
|
||||
@@ -47,9 +47,8 @@ default = []
|
||||
openapi = ["utoipa"]
|
||||
output_format = ["serde_json"]
|
||||
bin_info_schema = ["schemars"]
|
||||
basic_tracing = ["tracing-subscriber"]
|
||||
tracing = [
|
||||
"basic_tracing",
|
||||
"tracing-subscriber",
|
||||
"tracing-tree",
|
||||
"opentelemetry-jaeger",
|
||||
"tracing-opentelemetry",
|
||||
|
||||
@@ -80,7 +80,7 @@ impl BinaryBuildInformation {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "bin_info_schema", derive(schemars::JsonSchema))]
|
||||
pub struct BinaryBuildInformationOwned {
|
||||
|
||||
@@ -43,30 +43,6 @@ pub fn setup_logging() {
|
||||
.init();
|
||||
}
|
||||
|
||||
#[cfg(feature = "basic_tracing")]
|
||||
pub fn setup_tracing_logger() {
|
||||
let log_builder = tracing_subscriber::fmt()
|
||||
// Use a more compact, abbreviated log format
|
||||
.compact()
|
||||
// Display source code file paths
|
||||
.with_file(true)
|
||||
// Display source code line numbers
|
||||
.with_line_number(true)
|
||||
// Don't display the event's target (module path)
|
||||
.with_target(false);
|
||||
|
||||
if ::std::env::var("RUST_LOG").is_ok() {
|
||||
log_builder
|
||||
.with_env_filter(tracing_subscriber::filter::EnvFilter::from_default_env())
|
||||
.init()
|
||||
} else {
|
||||
// default to 'Info
|
||||
log_builder
|
||||
.with_max_level(tracing_subscriber::filter::LevelFilter::INFO)
|
||||
.init()
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: This has to be a macro, running it as a function does not work for the file_appender for some reason
|
||||
#[cfg(feature = "tracing")]
|
||||
#[macro_export]
|
||||
|
||||
@@ -47,7 +47,7 @@ nym-credential-storage = { path = "../credential-storage" }
|
||||
nym-network-defaults = { path = "../network-defaults" }
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-stream]
|
||||
workspace = true
|
||||
version = "0.1.11"
|
||||
features = ["time"]
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio]
|
||||
@@ -55,7 +55,7 @@ workspace = true
|
||||
features = ["time"]
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-tungstenite]
|
||||
workspace = true
|
||||
version = "0.20.1"
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.sqlx]
|
||||
version = "0.6.2"
|
||||
|
||||
@@ -28,7 +28,6 @@ pub enum InputMessage {
|
||||
recipient: Recipient,
|
||||
data: Vec<u8>,
|
||||
lane: TransmissionLane,
|
||||
mix_hops: Option<u8>,
|
||||
},
|
||||
|
||||
/// Creates a message used for a duplex anonymous communication where the recipient
|
||||
@@ -44,7 +43,6 @@ pub enum InputMessage {
|
||||
data: Vec<u8>,
|
||||
reply_surbs: u32,
|
||||
lane: TransmissionLane,
|
||||
mix_hops: Option<u8>,
|
||||
},
|
||||
|
||||
/// Attempt to use our internally received and stored `ReplySurb` to send the message back
|
||||
@@ -94,29 +92,6 @@ impl InputMessage {
|
||||
recipient,
|
||||
data,
|
||||
lane,
|
||||
mix_hops: None,
|
||||
};
|
||||
if let Some(packet_type) = packet_type {
|
||||
InputMessage::new_wrapper(message, packet_type)
|
||||
} else {
|
||||
message
|
||||
}
|
||||
}
|
||||
|
||||
// IMHO `new_regular` should take `mix_hops: Option<u8>` as an argument instead of creating
|
||||
// this function, but that would potentially break backwards compatibility with the current API
|
||||
pub fn new_regular_with_custom_hops(
|
||||
recipient: Recipient,
|
||||
data: Vec<u8>,
|
||||
lane: TransmissionLane,
|
||||
packet_type: Option<PacketType>,
|
||||
mix_hops: Option<u8>,
|
||||
) -> Self {
|
||||
let message = InputMessage::Regular {
|
||||
recipient,
|
||||
data,
|
||||
lane,
|
||||
mix_hops,
|
||||
};
|
||||
if let Some(packet_type) = packet_type {
|
||||
InputMessage::new_wrapper(message, packet_type)
|
||||
@@ -137,31 +112,6 @@ impl InputMessage {
|
||||
data,
|
||||
reply_surbs,
|
||||
lane,
|
||||
mix_hops: None,
|
||||
};
|
||||
if let Some(packet_type) = packet_type {
|
||||
InputMessage::new_wrapper(message, packet_type)
|
||||
} else {
|
||||
message
|
||||
}
|
||||
}
|
||||
|
||||
// IMHO `new_anonymous` should take `mix_hops: Option<u8>` as an argument instead of creating
|
||||
// this function, but that would potentially break backwards compatibility with the current API
|
||||
pub fn new_anonymous_with_custom_hops(
|
||||
recipient: Recipient,
|
||||
data: Vec<u8>,
|
||||
reply_surbs: u32,
|
||||
lane: TransmissionLane,
|
||||
packet_type: Option<PacketType>,
|
||||
mix_hops: Option<u8>,
|
||||
) -> Self {
|
||||
let message = InputMessage::Anonymous {
|
||||
recipient,
|
||||
data,
|
||||
reply_surbs,
|
||||
lane,
|
||||
mix_hops,
|
||||
};
|
||||
if let Some(packet_type) = packet_type {
|
||||
InputMessage::new_wrapper(message, packet_type)
|
||||
|
||||
@@ -73,11 +73,10 @@ where
|
||||
content: Vec<u8>,
|
||||
lane: TransmissionLane,
|
||||
packet_type: PacketType,
|
||||
mix_hops: Option<u8>,
|
||||
) {
|
||||
if let Err(err) = self
|
||||
.message_handler
|
||||
.try_send_plain_message(recipient, content, lane, packet_type, mix_hops)
|
||||
.try_send_plain_message(recipient, content, lane, packet_type)
|
||||
.await
|
||||
{
|
||||
warn!("failed to send a plain message - {err}")
|
||||
@@ -91,18 +90,10 @@ where
|
||||
reply_surbs: u32,
|
||||
lane: TransmissionLane,
|
||||
packet_type: PacketType,
|
||||
mix_hops: Option<u8>,
|
||||
) {
|
||||
if let Err(err) = self
|
||||
.message_handler
|
||||
.try_send_message_with_reply_surbs(
|
||||
recipient,
|
||||
content,
|
||||
reply_surbs,
|
||||
lane,
|
||||
packet_type,
|
||||
mix_hops,
|
||||
)
|
||||
.try_send_message_with_reply_surbs(recipient, content, reply_surbs, lane, packet_type)
|
||||
.await
|
||||
{
|
||||
warn!("failed to send a repliable message - {err}")
|
||||
@@ -115,9 +106,8 @@ where
|
||||
recipient,
|
||||
data,
|
||||
lane,
|
||||
mix_hops,
|
||||
} => {
|
||||
self.handle_plain_message(recipient, data, lane, PacketType::Mix, mix_hops)
|
||||
self.handle_plain_message(recipient, data, lane, PacketType::Mix)
|
||||
.await
|
||||
}
|
||||
InputMessage::Anonymous {
|
||||
@@ -125,17 +115,9 @@ where
|
||||
data,
|
||||
reply_surbs,
|
||||
lane,
|
||||
mix_hops,
|
||||
} => {
|
||||
self.handle_repliable_message(
|
||||
recipient,
|
||||
data,
|
||||
reply_surbs,
|
||||
lane,
|
||||
PacketType::Mix,
|
||||
mix_hops,
|
||||
)
|
||||
.await
|
||||
self.handle_repliable_message(recipient, data, reply_surbs, lane, PacketType::Mix)
|
||||
.await
|
||||
}
|
||||
InputMessage::Reply {
|
||||
recipient_tag,
|
||||
@@ -153,9 +135,8 @@ where
|
||||
recipient,
|
||||
data,
|
||||
lane,
|
||||
mix_hops,
|
||||
} => {
|
||||
self.handle_plain_message(recipient, data, lane, packet_type, mix_hops)
|
||||
self.handle_plain_message(recipient, data, lane, packet_type)
|
||||
.await
|
||||
}
|
||||
InputMessage::Anonymous {
|
||||
@@ -163,17 +144,9 @@ where
|
||||
data,
|
||||
reply_surbs,
|
||||
lane,
|
||||
mix_hops,
|
||||
} => {
|
||||
self.handle_repliable_message(
|
||||
recipient,
|
||||
data,
|
||||
reply_surbs,
|
||||
lane,
|
||||
packet_type,
|
||||
mix_hops,
|
||||
)
|
||||
.await
|
||||
self.handle_repliable_message(recipient, data, reply_surbs, lane, packet_type)
|
||||
.await
|
||||
}
|
||||
InputMessage::Reply {
|
||||
recipient_tag,
|
||||
|
||||
@@ -69,7 +69,6 @@ pub(crate) struct PendingAcknowledgement {
|
||||
message_chunk: Fragment,
|
||||
delay: SphinxDelay,
|
||||
destination: PacketDestination,
|
||||
mix_hops: Option<u8>,
|
||||
}
|
||||
|
||||
impl PendingAcknowledgement {
|
||||
@@ -78,13 +77,11 @@ impl PendingAcknowledgement {
|
||||
message_chunk: Fragment,
|
||||
delay: SphinxDelay,
|
||||
recipient: Recipient,
|
||||
mix_hops: Option<u8>,
|
||||
) -> Self {
|
||||
PendingAcknowledgement {
|
||||
message_chunk,
|
||||
delay,
|
||||
destination: PacketDestination::KnownRecipient(recipient.into()),
|
||||
mix_hops,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,9 +98,6 @@ impl PendingAcknowledgement {
|
||||
recipient_tag,
|
||||
extra_surb_request,
|
||||
},
|
||||
// Messages sent using SURBs are using the number of mix hops set by the recipient when
|
||||
// they provided the SURBs, so it doesn't make sense to include it here.
|
||||
mix_hops: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,18 +49,12 @@ where
|
||||
packet_recipient: Recipient,
|
||||
chunk_data: Fragment,
|
||||
packet_type: PacketType,
|
||||
mix_hops: Option<u8>,
|
||||
) -> Result<PreparedFragment, PreparationError> {
|
||||
debug!("retransmitting normal packet...");
|
||||
|
||||
// TODO: Figure out retransmission packet type signaling
|
||||
self.message_handler
|
||||
.try_prepare_single_chunk_for_sending(
|
||||
packet_recipient,
|
||||
chunk_data,
|
||||
packet_type,
|
||||
mix_hops,
|
||||
)
|
||||
.try_prepare_single_chunk_for_sending(packet_recipient, chunk_data, packet_type)
|
||||
.await
|
||||
}
|
||||
|
||||
@@ -95,7 +89,6 @@ where
|
||||
**recipient,
|
||||
timed_out_ack.message_chunk.clone(),
|
||||
packet_type,
|
||||
timed_out_ack.mix_hops,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
@@ -418,10 +418,9 @@ where
|
||||
message: Vec<u8>,
|
||||
lane: TransmissionLane,
|
||||
packet_type: PacketType,
|
||||
mix_hops: Option<u8>,
|
||||
) -> Result<(), PreparationError> {
|
||||
let message = NymMessage::new_plain(message);
|
||||
self.try_split_and_send_non_reply_message(message, recipient, lane, packet_type, mix_hops)
|
||||
self.try_split_and_send_non_reply_message(message, recipient, lane, packet_type)
|
||||
.await
|
||||
}
|
||||
|
||||
@@ -431,7 +430,6 @@ where
|
||||
recipient: Recipient,
|
||||
lane: TransmissionLane,
|
||||
packet_type: PacketType,
|
||||
mix_hops: Option<u8>,
|
||||
) -> Result<(), PreparationError> {
|
||||
debug!("Sending non-reply message with packet type {packet_type}");
|
||||
// TODO: I really dislike existence of this assertion, it implies code has to be re-organised
|
||||
@@ -463,7 +461,6 @@ where
|
||||
&self.config.ack_key,
|
||||
&recipient,
|
||||
packet_type,
|
||||
mix_hops,
|
||||
)?;
|
||||
|
||||
let real_message = RealMessage::new(
|
||||
@@ -471,8 +468,7 @@ where
|
||||
Some(fragment.fragment_identifier()),
|
||||
);
|
||||
let delay = prepared_fragment.total_delay;
|
||||
let pending_ack =
|
||||
PendingAcknowledgement::new_known(fragment, delay, recipient, mix_hops);
|
||||
let pending_ack = PendingAcknowledgement::new_known(fragment, delay, recipient);
|
||||
|
||||
real_messages.push(real_message);
|
||||
pending_acks.push(pending_ack);
|
||||
@@ -489,7 +485,6 @@ where
|
||||
recipient: Recipient,
|
||||
amount: u32,
|
||||
packet_type: PacketType,
|
||||
mix_hops: Option<u8>,
|
||||
) -> Result<(), PreparationError> {
|
||||
debug!("Sending additional reply SURBs with packet type {packet_type}");
|
||||
let sender_tag = self.get_or_create_sender_tag(&recipient);
|
||||
@@ -506,7 +501,6 @@ where
|
||||
recipient,
|
||||
TransmissionLane::AdditionalReplySurbs,
|
||||
packet_type,
|
||||
mix_hops,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -523,7 +517,6 @@ where
|
||||
num_reply_surbs: u32,
|
||||
lane: TransmissionLane,
|
||||
packet_type: PacketType,
|
||||
mix_hops: Option<u8>,
|
||||
) -> Result<(), SurbWrappedPreparationError> {
|
||||
debug!("Sending message with reply SURBs with packet type {packet_type}");
|
||||
let sender_tag = self.get_or_create_sender_tag(&recipient);
|
||||
@@ -534,7 +527,7 @@ where
|
||||
let message =
|
||||
NymMessage::new_repliable(RepliableMessage::new_data(message, sender_tag, reply_surbs));
|
||||
|
||||
self.try_split_and_send_non_reply_message(message, recipient, lane, packet_type, mix_hops)
|
||||
self.try_split_and_send_non_reply_message(message, recipient, lane, packet_type)
|
||||
.await?;
|
||||
|
||||
log::trace!("storing {} reply keys", reply_keys.len());
|
||||
@@ -548,7 +541,6 @@ where
|
||||
recipient: Recipient,
|
||||
chunk: Fragment,
|
||||
packet_type: PacketType,
|
||||
mix_hops: Option<u8>,
|
||||
) -> Result<PreparedFragment, PreparationError> {
|
||||
debug!("Sending single chunk with packet type {packet_type}");
|
||||
let topology_permit = self.topology_access.get_read_permit().await;
|
||||
@@ -562,7 +554,6 @@ where
|
||||
&self.config.ack_key,
|
||||
&recipient,
|
||||
packet_type,
|
||||
mix_hops,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
||||
@@ -516,7 +516,6 @@ where
|
||||
recipient,
|
||||
to_send,
|
||||
nym_sphinx::params::PacketType::Mix,
|
||||
self.config.reply_surbs.surb_mix_hops,
|
||||
)
|
||||
.await
|
||||
{
|
||||
|
||||
@@ -607,10 +607,6 @@ pub struct ReplySurbs {
|
||||
/// This is going to be superseded by key rotation once implemented.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub maximum_reply_key_age: Duration,
|
||||
|
||||
/// Specifies the number of mixnet hops the packet should go through. If not specified, then
|
||||
/// the default value is used.
|
||||
pub surb_mix_hops: Option<u8>,
|
||||
}
|
||||
|
||||
impl Default for ReplySurbs {
|
||||
@@ -626,7 +622,6 @@ impl Default for ReplySurbs {
|
||||
maximum_reply_surb_drop_waiting_period: DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD,
|
||||
maximum_reply_surb_age: DEFAULT_MAXIMUM_REPLY_SURB_AGE,
|
||||
maximum_reply_key_age: DEFAULT_MAXIMUM_REPLY_KEY_AGE,
|
||||
surb_mix_hops: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,7 +155,6 @@ impl From<ConfigV1_1_30> for Config {
|
||||
.maximum_reply_surb_drop_waiting_period,
|
||||
maximum_reply_surb_age: value.debug.reply_surbs.maximum_reply_surb_age,
|
||||
maximum_reply_key_age: value.debug.reply_surbs.maximum_reply_key_age,
|
||||
surb_mix_hops: None,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ workspace = true
|
||||
features = ["macros", "rt", "net", "sync", "time"]
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-stream]
|
||||
workspace = true
|
||||
version = "0.1.11"
|
||||
features = ["net", "sync", "time"]
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-tungstenite]
|
||||
|
||||
@@ -10,7 +10,7 @@ edition = "2021"
|
||||
futures = { workspace = true }
|
||||
log = { workspace = true }
|
||||
tokio = { version = "1.24.1", features = ["time", "net", "rt"] }
|
||||
tokio-util = { workspace = true, features = ["codec"] }
|
||||
tokio-util = { version = "0.7.4", features = ["codec"] }
|
||||
|
||||
# internal
|
||||
nym-sphinx = { path = "../../nymsphinx" }
|
||||
|
||||
@@ -123,10 +123,13 @@ impl Client {
|
||||
// We could have as well used conn.send_all(receiver.map(Ok)), but considering we don't care
|
||||
// about neither receiver nor the connection, it doesn't matter which one gets consumed
|
||||
if let Err(err) = receiver.map(Ok).forward(conn).await {
|
||||
warn!("Failed to forward packets to {address} - {err}");
|
||||
warn!("Failed to forward packets to {} - {err}", address);
|
||||
}
|
||||
|
||||
debug!("connection manager to {address} is finished. Either the connection failed or mixnet client got dropped");
|
||||
debug!(
|
||||
"connection manager to {} is finished. Either the connection failed or mixnet client got dropped",
|
||||
address
|
||||
);
|
||||
}
|
||||
|
||||
/// If we're trying to reconnect, determine how long we should wait.
|
||||
@@ -204,7 +207,7 @@ impl SendWithoutResponse for Client {
|
||||
if let Some(sender) = self.conn_new.get_mut(&address) {
|
||||
if let Err(err) = sender.channel.try_send(framed_packet) {
|
||||
if err.is_full() {
|
||||
debug!("Connection to {address} seems to not be able to handle all the traffic - dropping the current packet");
|
||||
debug!("Connection to {} seems to not be able to handle all the traffic - dropping the current packet", address);
|
||||
// it's not a 'big' error, but we did not manage to send the packet
|
||||
// if the queue is full, we can't really do anything but to drop the packet
|
||||
Err(io::Error::new(
|
||||
@@ -212,8 +215,10 @@ impl SendWithoutResponse for Client {
|
||||
"connection queue is full",
|
||||
))
|
||||
} else if err.is_disconnected() {
|
||||
debug!("Connection to {address} seems to be dead. attempting to re-establish it...");
|
||||
|
||||
debug!(
|
||||
"Connection to {} seems to be dead. attempting to re-establish it...",
|
||||
address
|
||||
);
|
||||
// it's not a 'big' error, but we did not manage to send the packet, but queue
|
||||
// it up to send it as soon as the connection is re-established
|
||||
self.make_connection(address, err.into_inner());
|
||||
@@ -233,7 +238,7 @@ impl SendWithoutResponse for Client {
|
||||
}
|
||||
} else {
|
||||
// there was never a connection to begin with
|
||||
debug!("establishing initial connection to {address}");
|
||||
debug!("establishing initial connection to {}", address);
|
||||
// it's not a 'big' error, but we did not manage to send the packet, but queue the packet
|
||||
// for sending for as soon as the connection is created
|
||||
self.make_connection(address, framed_packet);
|
||||
|
||||
@@ -55,9 +55,6 @@ pub use tendermint_rpc::{
|
||||
};
|
||||
pub use tendermint_rpc::{Request, Response, SimpleRequest};
|
||||
|
||||
#[cfg(feature = "http-client")]
|
||||
pub use tendermint_rpc::Url as RpcUrl;
|
||||
|
||||
#[cfg(feature = "http-client")]
|
||||
use crate::http_client;
|
||||
#[cfg(feature = "http-client")]
|
||||
|
||||
@@ -21,7 +21,7 @@ rand = {version = "0.6", features = ["std"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
time = { workspace = true, features = ["parsing", "formatting"] }
|
||||
time = { version = "0.3.6", features = ["parsing", "formatting"] }
|
||||
toml = "0.5.6"
|
||||
url = { workspace = true }
|
||||
tap = "1"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
use handlebars::{Handlebars, TemplateRenderError};
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::Serialize;
|
||||
use std::fs::{create_dir_all, File};
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::{fs, io};
|
||||
@@ -72,22 +72,16 @@ where
|
||||
C: NymConfigTemplate,
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
let path = path.as_ref();
|
||||
log::debug!("trying to save config file to {}", path.display());
|
||||
log::debug!("trying to save config file to {}", path.as_ref().display());
|
||||
let file = File::create(path.as_ref())?;
|
||||
|
||||
if let Some(parent) = path.parent() {
|
||||
create_dir_all(parent)?;
|
||||
}
|
||||
|
||||
let file = File::create(path)?;
|
||||
|
||||
// TODO: check for whether any of our configs store anything sensitive
|
||||
// TODO: check for whether any of our configs stores anything sensitive
|
||||
// and change that to 0o644 instead
|
||||
#[cfg(target_family = "unix")]
|
||||
{
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
|
||||
let mut perms = fs::metadata(path)?.permissions();
|
||||
let mut perms = fs::metadata(path.as_ref())?.permissions();
|
||||
perms.set_mode(0o600);
|
||||
fs::set_permissions(path, perms)?;
|
||||
}
|
||||
|
||||
@@ -25,12 +25,12 @@ humantime-serde = "1.1.1"
|
||||
|
||||
# TO CHECK WHETHER STILL NEEDED:
|
||||
log = { workspace = true }
|
||||
time = { workspace = true, features = ["parsing", "formatting"] }
|
||||
time = { version = "0.3.6", features = ["parsing", "formatting"] }
|
||||
ts-rs = { workspace = true, optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
rand_chacha = "0.3"
|
||||
time = { workspace = true, features = ["serde", "macros"] }
|
||||
time = { version = "0.3.5", features = ["serde", "macros"] }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
@@ -623,24 +623,6 @@ pub enum Layer {
|
||||
Three = 3,
|
||||
}
|
||||
|
||||
impl Layer {
|
||||
pub fn try_next(&self) -> Option<Self> {
|
||||
match self {
|
||||
Layer::One => Some(Layer::Two),
|
||||
Layer::Two => Some(Layer::Three),
|
||||
Layer::Three => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_previous(&self) -> Option<Self> {
|
||||
match self {
|
||||
Layer::One => None,
|
||||
Layer::Two => Some(Layer::One),
|
||||
Layer::Three => Some(Layer::Two),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Layer> for String {
|
||||
fn from(layer: Layer) -> Self {
|
||||
(layer as u8).to_string()
|
||||
|
||||
@@ -108,26 +108,16 @@ pub enum IpPacketRequestData {
|
||||
pub struct StaticConnectRequest {
|
||||
pub request_id: u64,
|
||||
pub ip: IpAddr,
|
||||
// The nym-address the response should be sent back to
|
||||
pub reply_to: Recipient,
|
||||
// The number of mix node hops that responses should take, in addition to the entry and exit
|
||||
// node. Zero means only client -> entry -> exit -> client.
|
||||
pub reply_to_hops: Option<u8>,
|
||||
// The average delay at each mix node, in milliseconds. Currently this is not supported by the
|
||||
// ip packet router.
|
||||
pub reply_to_avg_mix_delays: Option<f64>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
pub struct DynamicConnectRequest {
|
||||
pub request_id: u64,
|
||||
// The nym-address the response should be sent back to
|
||||
pub reply_to: Recipient,
|
||||
// The number of mix node hops that responses should take, in addition to the entry and exit
|
||||
// node. Zero means only client -> entry -> exit -> client.
|
||||
pub reply_to_hops: Option<u8>,
|
||||
// The average delay at each mix node, in milliseconds. Currently this is not supported by the
|
||||
// ip packet router.
|
||||
pub reply_to_avg_mix_delays: Option<f64>,
|
||||
}
|
||||
|
||||
|
||||
@@ -12,21 +12,20 @@ futures = { workspace = true }
|
||||
humantime-serde = "1.0"
|
||||
log = { workspace = true }
|
||||
rand = "0.8"
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
tokio = { workspace = true, features = [
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
tokio = { version = "1.24.1", features = [
|
||||
"time",
|
||||
"macros",
|
||||
"rt",
|
||||
"net",
|
||||
"io-util",
|
||||
] }
|
||||
tokio-util = { workspace = true, features = ["codec"] }
|
||||
tokio-util = { version = "0.7.4", features = ["codec"] }
|
||||
url = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
parking_lot = { workspace = true }
|
||||
|
||||
## tracing
|
||||
tracing = { workspace = true, optional = true }
|
||||
tracing = { version = "0.1.37", optional = true }
|
||||
|
||||
nym-crypto = { path = "../crypto" }
|
||||
nym-network-defaults = { path = "../network-defaults" }
|
||||
@@ -38,7 +37,6 @@ nym-sphinx-params = { path = "../nymsphinx/params" }
|
||||
nym-sphinx-types = { path = "../nymsphinx/types" }
|
||||
nym-task = { path = "../task" }
|
||||
nym-validator-client = { path = "../client-libs/validator-client" }
|
||||
nym-mixnet-contract-common = { path = "../cosmwasm-smart-contracts/mixnet-contract" }
|
||||
nym-bin-common = { path = "../bin-common" }
|
||||
|
||||
cfg-if = "1.0.0"
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use nym_validator_client::nyxd::error::NyxdError;
|
||||
use std::net::IpAddr;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ForwardTravelError {
|
||||
#[error("received a connection request from a forbidden address: '{address}'")]
|
||||
DisallowedIngressAddress { address: IpAddr },
|
||||
|
||||
#[error("received a request to open connection to a forbidden address: '{address}'")]
|
||||
DisallowedEgressAddress { address: IpAddr },
|
||||
|
||||
#[error("no valid nyxd urls are available for topology queries")]
|
||||
NoNyxdUrlsAvailable,
|
||||
|
||||
#[error("nyxd interaction failure: {source}")]
|
||||
NyxdFailure {
|
||||
#[from]
|
||||
source: NyxdError,
|
||||
},
|
||||
|
||||
#[error("the current epoch appears to be stuck")]
|
||||
StuckEpoch,
|
||||
}
|
||||
@@ -1,356 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::forward_travel::error::ForwardTravelError;
|
||||
use log::{debug, error, info, trace, warn};
|
||||
use nym_mixnet_contract_common::{EpochId, GatewayBond, Layer, MixNodeBond};
|
||||
use nym_network_defaults::NymNetworkDetails;
|
||||
use nym_task::TaskClient;
|
||||
use nym_validator_client::client::IdentityKey;
|
||||
use nym_validator_client::nyxd::contract_traits::{MixnetQueryClient, PagedMixnetQueryClient};
|
||||
use nym_validator_client::{nyxd, QueryHttpRpcNyxdClient};
|
||||
use parking_lot::RwLock;
|
||||
use rand::seq::SliceRandom;
|
||||
use rand::{thread_rng, Rng};
|
||||
use std::collections::HashSet;
|
||||
use std::mem;
|
||||
use std::net::{IpAddr, ToSocketAddrs};
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use tokio::time::sleep;
|
||||
use url::Url;
|
||||
|
||||
pub mod error;
|
||||
|
||||
// TODO: to allow for separate ingress/egress we have to change our layer selection algorithm, i.e. it has to be announced before epoch change
|
||||
pub type AllowedIngress = AllowedPaths;
|
||||
pub type AllowedEgress = AllowedPaths;
|
||||
|
||||
pub struct AllowedAddressesProvider {
|
||||
current_epoch: EpochId,
|
||||
|
||||
identity: IdentityKey,
|
||||
|
||||
client_config: nyxd::Config,
|
||||
|
||||
/// URLs to the nyxd validators for obtaining unfiltered network topology.
|
||||
nyxd_endpoints: Vec<Url>,
|
||||
|
||||
// to allow for separate ingress/egress we have to change our layer selection algorithm, i.e. it has to be announced before epoch change
|
||||
// ingress: AllowedIngress,
|
||||
// egress: AllowedEgress,
|
||||
allowed: AllowedPaths,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl AllowedAddressesProvider {
|
||||
pub async fn new(
|
||||
identity: IdentityKey,
|
||||
nyxd_endpoints: Vec<Url>,
|
||||
allow_all: bool,
|
||||
network_details: Option<NymNetworkDetails>,
|
||||
) -> Result<Self, ForwardTravelError> {
|
||||
let network = network_details.unwrap_or(NymNetworkDetails::new_mainnet());
|
||||
let mut provider = AllowedAddressesProvider {
|
||||
current_epoch: 0,
|
||||
identity,
|
||||
client_config: nyxd::Config::try_from_nym_network_details(&network)?,
|
||||
nyxd_endpoints,
|
||||
allowed: AllowedPaths::new(allow_all),
|
||||
};
|
||||
|
||||
if !allow_all {
|
||||
// set initial values for ingress/egress
|
||||
let client = provider.ephemeral_nyxd_client()?;
|
||||
provider.update_state(client).await?;
|
||||
}
|
||||
|
||||
Ok(provider)
|
||||
}
|
||||
|
||||
fn ephemeral_nyxd_client(&self) -> Result<QueryHttpRpcNyxdClient, ForwardTravelError> {
|
||||
let mut possible_nyxd_endpoints = self.nyxd_endpoints.clone();
|
||||
possible_nyxd_endpoints.shuffle(&mut thread_rng());
|
||||
|
||||
let mut last_error = match QueryHttpRpcNyxdClient::connect(
|
||||
self.client_config.clone(),
|
||||
possible_nyxd_endpoints
|
||||
.pop()
|
||||
.ok_or(ForwardTravelError::NoNyxdUrlsAvailable)?
|
||||
.as_str(),
|
||||
) {
|
||||
Ok(client) => return Ok(client),
|
||||
Err(err) => err,
|
||||
};
|
||||
|
||||
for url in possible_nyxd_endpoints {
|
||||
match QueryHttpRpcNyxdClient::connect(self.client_config.clone(), url.as_str()) {
|
||||
Ok(client) => return Ok(client),
|
||||
Err(err) => last_error = err,
|
||||
};
|
||||
}
|
||||
|
||||
Err(last_error.into())
|
||||
}
|
||||
|
||||
pub fn ingress(&self) -> AllowedIngress {
|
||||
self.allowed.clone()
|
||||
}
|
||||
|
||||
pub fn egress(&self) -> AllowedEgress {
|
||||
self.allowed.clone()
|
||||
}
|
||||
|
||||
fn add_node_ips(raw_host: &str, identity: &str, set: &mut HashSet<IpAddr>) {
|
||||
if let Ok(ip) = IpAddr::from_str(raw_host) {
|
||||
set.insert(ip);
|
||||
} else {
|
||||
// this might still be a valid hostname
|
||||
//
|
||||
// annoyingly there exists a method of looking up a socket address but not an ip address,
|
||||
// so append any port and perform the lookup
|
||||
let Ok(sockets) = format!("{raw_host}:1789").to_socket_addrs() else {
|
||||
warn!("failed to resolve ip address of node '{identity}' (hostname: '{raw_host}')");
|
||||
return;
|
||||
};
|
||||
|
||||
for socket in sockets {
|
||||
set.insert(socket.ip());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_all_addresses(nodes: &[MixNodeBond], gateways: &[GatewayBond]) -> HashSet<IpAddr> {
|
||||
let mut allowed = HashSet::new();
|
||||
|
||||
for node in nodes.iter() {
|
||||
Self::add_node_ips(&node.mix_node.host, node.identity(), &mut allowed);
|
||||
}
|
||||
|
||||
for gateway in gateways.iter() {
|
||||
Self::add_node_ips(&gateway.gateway.host, gateway.identity(), &mut allowed);
|
||||
}
|
||||
|
||||
allowed
|
||||
}
|
||||
|
||||
/// Gets ip addresses of all mixnodes on given layer
|
||||
fn get_addresses_on_layer(layer: Layer, nodes: &[MixNodeBond]) -> HashSet<IpAddr> {
|
||||
let mut allowed = HashSet::new();
|
||||
|
||||
for node in nodes.iter().filter(|m| m.layer == layer) {
|
||||
Self::add_node_ips(&node.mix_node.host, node.identity(), &mut allowed);
|
||||
}
|
||||
|
||||
allowed
|
||||
}
|
||||
|
||||
fn gateway_addresses(gateways: &[GatewayBond]) -> HashSet<IpAddr> {
|
||||
let mut allowed = HashSet::new();
|
||||
|
||||
for gateway in gateways.iter() {
|
||||
Self::add_node_ips(&gateway.gateway.host, gateway.identity(), &mut allowed);
|
||||
}
|
||||
|
||||
allowed
|
||||
}
|
||||
|
||||
fn locate_layer(&self, nodes: &[MixNodeBond]) -> Option<Layer> {
|
||||
nodes
|
||||
.iter()
|
||||
.find(|m| m.identity() == self.identity)
|
||||
.map(|m| m.layer)
|
||||
}
|
||||
|
||||
fn is_gateway(&self, gateways: &[GatewayBond]) -> bool {
|
||||
gateways
|
||||
.iter()
|
||||
.any(|g| g.gateway.identity_key == self.identity)
|
||||
}
|
||||
|
||||
async fn update_state(
|
||||
&mut self,
|
||||
client: QueryHttpRpcNyxdClient,
|
||||
) -> Result<(), ForwardTravelError> {
|
||||
let current_interval = client.get_current_interval_details().await?;
|
||||
let current_epoch = current_interval.interval.current_epoch_absolute_id();
|
||||
|
||||
if current_epoch == self.current_epoch {
|
||||
error!("can't update the allowed ips list as the epoch appears to be stuck");
|
||||
return Err(ForwardTravelError::StuckEpoch);
|
||||
}
|
||||
|
||||
let has_epoch_deviated = current_epoch > self.current_epoch + 1;
|
||||
|
||||
let mixnodes = client.get_all_mixnode_bonds().await?;
|
||||
let gateways = client.get_all_gateways().await?;
|
||||
|
||||
let new_allowed = Self::get_all_addresses(&mixnodes, &gateways);
|
||||
|
||||
// I'm leaving this code commented out to preserve this logic for when we need it
|
||||
// to update to proper ingress/egress filtering
|
||||
|
||||
// let our_mix_layer = self.locate_layer(&mixnodes);
|
||||
//
|
||||
// let previous_mix_layer = our_mix_layer.and_then(|l| l.try_previous());
|
||||
// let next_mix_layer = our_mix_layer.and_then(|l| l.try_next());
|
||||
//
|
||||
// let (allowed_ingress, allowed_egress) = match (previous_mix_layer, next_mix_layer) {
|
||||
// // layer 1
|
||||
// (None, Some(next)) => {
|
||||
// let gateways = client.get_all_gateways().await?;
|
||||
//
|
||||
// (
|
||||
// Self::gateway_addresses(&gateways),
|
||||
// Self::get_addresses_on_layer(next, &mixnodes),
|
||||
// )
|
||||
// }
|
||||
// // layer 2
|
||||
// (Some(previous), Some(next)) => (
|
||||
// Self::get_addresses_on_layer(previous, &mixnodes),
|
||||
// Self::get_addresses_on_layer(next, &mixnodes),
|
||||
// ),
|
||||
// // layer 3
|
||||
// (Some(previous), None) => {
|
||||
// let gateways = client.get_all_gateways().await?;
|
||||
// (
|
||||
// Self::get_addresses_on_layer(previous, &mixnodes),
|
||||
// Self::gateway_addresses(&gateways),
|
||||
// )
|
||||
// }
|
||||
// // gateway (or not bonded)
|
||||
// (None, None) => {
|
||||
// let gateways = client.get_all_gateways().await?;
|
||||
//
|
||||
// if self.is_gateway(&gateways) {
|
||||
// let mut base_ingress = Self::get_addresses_on_layer(Layer::Three, &mixnodes);
|
||||
// let mut base_egress = Self::get_addresses_on_layer(Layer::One, &mixnodes);
|
||||
//
|
||||
// // TODO: this extension should be conditional on whether the node is running the vpn module
|
||||
// let gw_extension = Self::gateway_addresses(&gateways);
|
||||
//
|
||||
// base_ingress.extend(gw_extension.clone());
|
||||
// base_egress.extend(gw_extension.clone());
|
||||
//
|
||||
// (base_ingress, base_egress)
|
||||
// } else {
|
||||
// warn!("our node doesn't appear to be bonded - going to permit traffic from ALL mixnodes and gateways");
|
||||
// let all = Self::get_all_addresses(&mixnodes, &gateways);
|
||||
// (all.clone(), all)
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
|
||||
self.current_epoch = current_epoch;
|
||||
self.allowed.advance_epoch(new_allowed, has_epoch_deviated);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn update_allowed_addresses(&mut self) -> Result<(), ForwardTravelError> {
|
||||
// create new client every epoch because it results in different nyxd endpoint being used
|
||||
// what may help in distributing the load
|
||||
let client = self.ephemeral_nyxd_client()?;
|
||||
self.wait_for_epoch_rollover(&client).await?;
|
||||
self.update_state(client).await
|
||||
}
|
||||
|
||||
async fn wait_for_epoch_rollover(
|
||||
&self,
|
||||
client: &QueryHttpRpcNyxdClient,
|
||||
) -> Result<(), ForwardTravelError> {
|
||||
let current_interval = client.get_current_interval_details().await?;
|
||||
let current_epoch = current_interval.interval.current_epoch_absolute_id();
|
||||
|
||||
if current_epoch <= self.current_epoch {
|
||||
let remaining = current_interval.time_until_current_epoch_end();
|
||||
// add few more seconds to account for block time drift and to spread queries of all
|
||||
// other nodes
|
||||
let adjustment_secs = rand::thread_rng().gen_range(5..90);
|
||||
sleep(remaining + Duration::from_secs(adjustment_secs)).await;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn run(&mut self, mut task_client: TaskClient) {
|
||||
if self.allowed.allow_all {
|
||||
// debug_assert!(self.egress.allow_all);
|
||||
|
||||
info!("the forward travel is currently disabled - there's no point in starting the route refresher");
|
||||
task_client.mark_as_success();
|
||||
return;
|
||||
}
|
||||
|
||||
debug!("Started ValidAddressesProvider with graceful shutdown support");
|
||||
while !task_client.is_shutdown() {
|
||||
tokio::select! {
|
||||
biased;
|
||||
_ = task_client.recv() => {
|
||||
trace!("ValidAddressesProvider: Received shutdown");
|
||||
}
|
||||
res = self.update_allowed_addresses() => {
|
||||
if let Err(err) = res {
|
||||
warn!("failed to update the allowed addresses: {err}");
|
||||
|
||||
// don't retry immediately in case it was a network failure, wait a bit instead.
|
||||
task_client.wait(Duration::from_secs(5 * 60)).await
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
task_client.recv_timeout().await;
|
||||
log::debug!("ValidAddressesProvider: Exiting");
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AllowedPaths {
|
||||
// this is fine that this value is not wrapped in an Arc and is not atomic given
|
||||
// it's not expected to be modified at runtime
|
||||
allow_all: bool,
|
||||
inner: Arc<RwLock<AllowedPathsInner>>,
|
||||
}
|
||||
|
||||
impl AllowedPaths {
|
||||
fn new(allow_all: bool) -> Self {
|
||||
AllowedPaths {
|
||||
allow_all,
|
||||
inner: Arc::new(RwLock::new(AllowedPathsInner {
|
||||
previous_epoch: HashSet::new(),
|
||||
current_epoch: HashSet::new(),
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_allowed(&self, address: IpAddr) -> bool {
|
||||
if self.allow_all {
|
||||
return true;
|
||||
}
|
||||
|
||||
let guard = self.inner.read();
|
||||
guard.current_epoch.contains(&address) || guard.previous_epoch.contains(&address)
|
||||
}
|
||||
|
||||
fn advance_epoch(&self, current_epoch: HashSet<IpAddr>, reset_previous: bool) {
|
||||
// if this is triggered, it's an implementation bug;
|
||||
// we shouldn't be updating data if we're allowing everything regardless
|
||||
debug_assert!(!self.allow_all);
|
||||
|
||||
let mut guard = self.inner.write();
|
||||
|
||||
let old_current = mem::replace(&mut guard.current_epoch, current_epoch);
|
||||
|
||||
if reset_previous {
|
||||
guard.previous_epoch = HashSet::new()
|
||||
} else {
|
||||
guard.previous_epoch = old_current;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct AllowedPathsInner {
|
||||
previous_epoch: HashSet<IpAddr>,
|
||||
current_epoch: HashSet<IpAddr>,
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod forward_travel;
|
||||
pub mod packet_processor;
|
||||
pub mod verloc;
|
||||
|
||||
|
||||
@@ -1,50 +1,81 @@
|
||||
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
use std::io;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
#[derive(Debug)]
|
||||
pub enum RttError {
|
||||
#[error("the received echo packet had unexpected size")]
|
||||
UnexpectedEchoPacketSize,
|
||||
|
||||
#[error("the received reply packet had unexpected size")]
|
||||
UnexpectedReplyPacketSize,
|
||||
|
||||
#[error("the received echo packet had malformed sender")]
|
||||
MalformedSenderIdentity,
|
||||
|
||||
#[error("the received echo packet had malformed signature")]
|
||||
MalformedEchoSignature,
|
||||
|
||||
#[error("the received reply packet had malformed signature")]
|
||||
MalformedReplySignature,
|
||||
|
||||
#[error("the received echo packet had invalid signature")]
|
||||
InvalidEchoSignature,
|
||||
|
||||
#[error("the received reply packet had invalid signature")]
|
||||
InvalidReplySignature,
|
||||
|
||||
#[error("could not establish connection to {0}: {1}")]
|
||||
UnreachableNode(String, #[source] io::Error),
|
||||
|
||||
#[error("failed to write echo packet to {0}: {1}")]
|
||||
UnexpectedConnectionFailureWrite(String, #[source] io::Error),
|
||||
|
||||
#[error("failed to read reply packet from {0}: {1}")]
|
||||
UnexpectedConnectionFailureRead(String, #[source] io::Error),
|
||||
|
||||
#[error("timed out while trying to read reply packet from {0}")]
|
||||
UnreachableNode(String, io::Error),
|
||||
UnexpectedConnectionFailureWrite(String, io::Error),
|
||||
UnexpectedConnectionFailureRead(String, io::Error),
|
||||
ConnectionReadTimeout(String),
|
||||
|
||||
#[error("timed out while trying to write echo packet to {0}")]
|
||||
ConnectionWriteTimeout(String),
|
||||
|
||||
#[error("the received reply packet had an unexpected sequence number")]
|
||||
UnexpectedReplySequence,
|
||||
|
||||
#[error("shutdown signal received")]
|
||||
ShutdownReceived,
|
||||
}
|
||||
|
||||
impl Display for RttError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
RttError::UnexpectedEchoPacketSize => {
|
||||
write!(f, "The received echo packet had unexpected size")
|
||||
}
|
||||
RttError::UnexpectedReplyPacketSize => {
|
||||
write!(f, "The received reply packet had unexpected size")
|
||||
}
|
||||
RttError::MalformedSenderIdentity => {
|
||||
write!(f, "The received echo packet had malformed sender")
|
||||
}
|
||||
RttError::MalformedEchoSignature => {
|
||||
write!(f, "The received echo packet had malformed signature")
|
||||
}
|
||||
RttError::MalformedReplySignature => {
|
||||
write!(f, "The received reply packet had malformed signature")
|
||||
}
|
||||
RttError::InvalidEchoSignature => {
|
||||
write!(f, "The received echo packet had invalid signature")
|
||||
}
|
||||
RttError::InvalidReplySignature => {
|
||||
write!(f, "The received reply packet had invalid signature")
|
||||
}
|
||||
RttError::UnreachableNode(id, err) => {
|
||||
write!(f, "Could not establish connection to {id} - {err}")
|
||||
}
|
||||
RttError::UnexpectedConnectionFailureWrite(id, err) => {
|
||||
write!(f, "Failed to write echo packet to {id} - {err}")
|
||||
}
|
||||
RttError::UnexpectedConnectionFailureRead(id, err) => {
|
||||
write!(f, "Failed to read reply packet from {id} - {err}")
|
||||
}
|
||||
RttError::ConnectionReadTimeout(id) => {
|
||||
write!(f, "Timed out while trying to read reply packet from {id}")
|
||||
}
|
||||
RttError::ConnectionWriteTimeout(id) => {
|
||||
write!(f, "Timed out while trying to write echo packet to {id}")
|
||||
}
|
||||
RttError::UnexpectedReplySequence => write!(
|
||||
f,
|
||||
"The received reply packet had an unexpected sequence number"
|
||||
),
|
||||
RttError::ShutdownReceived => {
|
||||
write!(f, "Shutdown signal received")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for RttError {}
|
||||
|
||||
@@ -258,7 +258,6 @@ where
|
||||
&address,
|
||||
&address,
|
||||
PacketType::Mix,
|
||||
None,
|
||||
)?)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,13 +7,13 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
tokio-stream = { workspace = true } # this one seems to be a thing until `Stream` trait is stabilised in stdlib
|
||||
tokio-stream = "0.1.11" # this one seems to be a thing until `Stream` trait is stabilised in stdlib
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio]
|
||||
workspace = true
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-util]
|
||||
workspace = true
|
||||
version = "0.7.4"
|
||||
features = ["time"]
|
||||
|
||||
[target."cfg(target_arch = \"wasm32\")".dependencies.wasmtimer]
|
||||
|
||||
@@ -9,7 +9,7 @@ repository = { workspace = true }
|
||||
|
||||
[dependencies]
|
||||
bytes = "1.0"
|
||||
tokio-util = { workspace = true, features = ["codec"] }
|
||||
tokio-util = { version = "0.7.4", features = ["codec"] }
|
||||
thiserror = { workspace = true }
|
||||
|
||||
nym-sphinx-types = { path = "../types", features = ["sphinx", "outfox"] }
|
||||
|
||||
@@ -181,7 +181,6 @@ pub trait FragmentPreparer {
|
||||
/// - compute vk_b = g^x || v_b
|
||||
/// - compute sphinx_plaintext = SURB_ACK || g^x || v_b
|
||||
/// - compute sphinx_packet = Sphinx(recipient, sphinx_plaintext)
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn prepare_chunk_for_sending(
|
||||
&mut self,
|
||||
fragment: Fragment,
|
||||
@@ -190,7 +189,6 @@ pub trait FragmentPreparer {
|
||||
packet_sender: &Recipient,
|
||||
packet_recipient: &Recipient,
|
||||
packet_type: PacketType,
|
||||
mix_hops: Option<u8>,
|
||||
) -> Result<PreparedFragment, NymTopologyError> {
|
||||
// each plain or repliable packet (i.e. not a reply) attaches an ephemeral public key so that the recipient
|
||||
// could perform diffie-hellman with its own keys followed by a kdf to re-derive
|
||||
@@ -228,8 +226,7 @@ pub trait FragmentPreparer {
|
||||
};
|
||||
|
||||
// generate pseudorandom route for the packet
|
||||
let hops = mix_hops.unwrap_or(self.num_mix_hops());
|
||||
log::trace!("Preparing chunk for sending with {} mix hops", hops);
|
||||
let hops = self.num_mix_hops();
|
||||
let route =
|
||||
topology.random_route_to_gateway(self.rng(), hops, packet_recipient.gateway())?;
|
||||
let destination = packet_recipient.as_sphinx_destination();
|
||||
@@ -392,7 +389,6 @@ where
|
||||
ack_key: &AckKey,
|
||||
packet_recipient: &Recipient,
|
||||
packet_type: PacketType,
|
||||
mix_hops: Option<u8>,
|
||||
) -> Result<PreparedFragment, NymTopologyError> {
|
||||
let sender = self.sender_address;
|
||||
|
||||
@@ -404,7 +400,6 @@ where
|
||||
&sender,
|
||||
packet_recipient,
|
||||
packet_type,
|
||||
mix_hops,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -169,10 +169,6 @@ pub struct SphinxMessageReceiver {
|
||||
|
||||
impl SphinxMessageReceiver {
|
||||
/// Allows setting non-default number of expected mix hops in the network.
|
||||
// IMPORTANT NOTE: this is among others used to deserialize SURBs. Meaning that this is a
|
||||
// global setting and currently always set to the default value. The implication is that it is
|
||||
// not currently possible to have different number of hops for different SURB messages. So,
|
||||
// don't try to use <3 mix hops for SURBs until this is refactored.
|
||||
#[must_use]
|
||||
pub fn with_mix_hops(mut self, hops: u8) -> Self {
|
||||
self.num_mix_hops = hops;
|
||||
|
||||
@@ -9,7 +9,7 @@ edition = "2021"
|
||||
[dependencies]
|
||||
bytes = "1.0"
|
||||
tokio = { version = "1.24.1", features = [ "net", "io-util", "sync", "macros", "time", "rt-multi-thread" ] }
|
||||
tokio-util = { workspace = true, features = [ "io" ] } # reason for getting this guy is to to able to port to tokio 1.X more quickly by being able to use
|
||||
tokio-util = { version = "0.7.4", features = [ "io" ] } # reason for getting this guy is to to able to port to tokio 1.X more quickly by being able to use
|
||||
# their `read_buf` [from the util crate] replacement rather than having to rethink/reimplement `AvailableReader` with the new AsyncRead trait definition.
|
||||
# In the long run, the dependency should probably get removed in favour of pure-tokio implementation, but for time being it's fine.
|
||||
futures = { workspace = true }
|
||||
|
||||
@@ -373,14 +373,6 @@ impl TaskClient {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn wait(&mut self, duration: Duration) {
|
||||
tokio::select! {
|
||||
biased;
|
||||
_ = self.recv() => (),
|
||||
_ = sleep(duration) => (),
|
||||
}
|
||||
}
|
||||
|
||||
// Create a dummy that will never report that we should shutdown.
|
||||
pub fn dummy() -> TaskClient {
|
||||
let (_notify_tx, notify_rx) = watch::channel(());
|
||||
@@ -502,15 +494,12 @@ impl Drop for TaskClient {
|
||||
fn drop(&mut self) {
|
||||
if !self.mode.should_signal_on_drop() {
|
||||
self.log(
|
||||
Level::Debug,
|
||||
"the task client is getting dropped: this is expected during client shutdown",
|
||||
Level::Trace,
|
||||
"the task client is getting dropped (but instructed to not signal)",
|
||||
);
|
||||
return;
|
||||
} else {
|
||||
self.log(
|
||||
Level::Info,
|
||||
"the task client is getting dropped: this is expected during client shutdown",
|
||||
);
|
||||
self.log(Level::Debug, "the task client is getting dropped");
|
||||
}
|
||||
|
||||
if !self.is_shutdown_poll() {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use crate::{manager::SentError, TaskManager};
|
||||
|
||||
#[cfg(unix)]
|
||||
#[deprecated]
|
||||
pub async fn wait_for_signal() {
|
||||
use tokio::signal::unix::{signal, SignalKind};
|
||||
let mut sigterm = signal(SignalKind::terminate()).expect("Failed to setup SIGTERM channel");
|
||||
|
||||
@@ -434,10 +434,6 @@ pub struct ReplySurbsWasm {
|
||||
/// Defines maximum amount of time given reply key is going to be valid for.
|
||||
/// This is going to be superseded by key rotation once implemented.
|
||||
pub maximum_reply_key_age_ms: u32,
|
||||
|
||||
/// Defines how many mix nodes the reply surb should go through.
|
||||
/// If not set, the default value is going to be used.
|
||||
pub surb_mix_hops: Option<u8>,
|
||||
}
|
||||
|
||||
impl Default for ReplySurbsWasm {
|
||||
@@ -467,7 +463,6 @@ impl From<ReplySurbsWasm> for ConfigReplySurbs {
|
||||
maximum_reply_key_age: Duration::from_millis(
|
||||
reply_surbs.maximum_reply_key_age_ms as u64,
|
||||
),
|
||||
surb_mix_hops: reply_surbs.surb_mix_hops,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -489,7 +484,6 @@ impl From<ConfigReplySurbs> for ReplySurbsWasm {
|
||||
.as_millis() as u32,
|
||||
maximum_reply_surb_age_ms: reply_surbs.maximum_reply_surb_age.as_millis() as u32,
|
||||
maximum_reply_key_age_ms: reply_surbs.maximum_reply_key_age.as_millis() as u32,
|
||||
surb_mix_hops: reply_surbs.surb_mix_hops,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,9 +303,6 @@ pub struct ReplySurbsWasmOverride {
|
||||
/// This is going to be superseded by key rotation once implemented.
|
||||
#[tsify(optional)]
|
||||
pub maximum_reply_key_age_ms: Option<u32>,
|
||||
|
||||
#[tsify(optional)]
|
||||
pub surb_mix_hops: Option<u8>,
|
||||
}
|
||||
|
||||
impl From<ReplySurbsWasmOverride> for ReplySurbsWasm {
|
||||
@@ -340,7 +337,6 @@ impl From<ReplySurbsWasmOverride> for ReplySurbsWasm {
|
||||
maximum_reply_key_age_ms: value
|
||||
.maximum_reply_key_age_ms
|
||||
.unwrap_or(def.maximum_reply_key_age_ms),
|
||||
surb_mix_hops: value.surb_mix_hops,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -551,15 +551,6 @@ dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3"
|
||||
dependencies = [
|
||||
"powerfmt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derivative"
|
||||
version = "2.2.0"
|
||||
@@ -1567,12 +1558,6 @@ version = "0.3.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
|
||||
|
||||
[[package]]
|
||||
name = "powerfmt"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.17"
|
||||
@@ -1885,9 +1870,9 @@ checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.190"
|
||||
version = "1.0.160"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7"
|
||||
checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
@@ -1903,9 +1888,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.190"
|
||||
version = "1.0.160"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3"
|
||||
checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2100,13 +2085,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.30"
|
||||
version = "0.3.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5"
|
||||
checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"itoa",
|
||||
"powerfmt",
|
||||
"serde",
|
||||
"time-core",
|
||||
"time-macros",
|
||||
@@ -2114,15 +2097,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "time-core"
|
||||
version = "0.1.2"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
|
||||
checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd"
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.15"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20"
|
||||
checksum = "fd80a657e71da814b8e5d60d3374fc6d35045062245d80224748ae522dd76f36"
|
||||
dependencies = [
|
||||
"time-core",
|
||||
]
|
||||
|
||||
@@ -15,8 +15,8 @@ declare -a plugins=("admonish" "linkcheck" "last-changed" "theme" "variables" "c
|
||||
install_mdbook_deps() {
|
||||
printf "\ninstalling mdbook..."
|
||||
# installing mdbook with only specific features for speed
|
||||
# cargo install mdbook --no-default-features --features search --vers "^$MINOR_VERSION"
|
||||
cargo install mdbook --vers "^$MINOR_VERSION"
|
||||
cargo install mdbook --no-default-features --features search --vers "^$MINOR_VERSION"
|
||||
# cargo install mdbook --vers "^$MINOR_VERSION"
|
||||
|
||||
printf "\ninstalling plugins..."
|
||||
for i in "${plugins[@]}"
|
||||
|
||||
@@ -16,26 +16,25 @@ For example `./target/debug/nym-network-requester --no-banner build-info --outpu
|
||||
|
||||
## Upgrading your node
|
||||
|
||||
> The process is the similar for Mix Node, Gateway and Network Requester. In the following steps we use a placeholder `<NODE>` in the commands, please change it for the binary name you want to upgrade (ie `nym-mixnode`). Any particularities for the given type of node are included.
|
||||
> The process is the similar for Mix Node, Gateway and Network Requester. In the following steps we use a placeholder `<NODE>` in the commands, please change it for the type of node you want to upgrade. Any particularities for the given type of node are included.
|
||||
|
||||
Upgrading your node is a two-step process:
|
||||
|
||||
1. Updating the binary and `~/.nym/<NODE>/<YOUR_ID>/config/config.toml` on your VPS
|
||||
2. Updating the node information in the [mixnet smart contract](https://nymtech.net/docs/nyx/mixnet-contract.html). **This is the information that is present on the [mixnet explorer](https://explorer.nymtech.net)**.
|
||||
* Updating the binary and `~/.nym/<NODE>/<YOUR_ID>/config/config.toml` on your VPS
|
||||
* Updating the node information in the [mixnet smart contract](https://nymtech.net/docs/nyx/mixnet-contract.html). **This is the information that is present on the [mixnet explorer](https://explorer.nymtech.net)**.
|
||||
|
||||
### Step 1: Upgrading your binary
|
||||
Follow these steps to upgrade your Node binary and update its config file:
|
||||
* Pause your node process.
|
||||
- if you see the terminal window with your node, press `ctrl + c`
|
||||
- if you run it as `systemd` service, run: `systemctl stop <NODE>.service`
|
||||
- if you run it as `systemd` service, run: `systemctl stop nym-<NODE>.service`
|
||||
* Replace the existing `<NODE>` binary with the newest binary (which you can either [compile yourself](https://nymtech.net/docs/binaries/building-nym.html) or grab from our [releases page](https://github.com/nymtech/nym/releases)).
|
||||
* Re-run `init` with the same values as you used initially for your `<NODE>` ([Mix Node](./mix-node-setup.md#initialising-your-mix-node), [Gateway](./gateway-setup.md#initialising-your-gateway)) . **This will just update the config file, it will not overwrite existing keys**.
|
||||
* Restart your node process with the new binary:
|
||||
- if your node is *not automated*, just `run` your `<NODE>` with `./<NODE> run --id <ID>`. Here are exact guidelines for [Mix Node](./mix-node-setup.md#running-your-mix-node) and [Gateway](./gateway-setup.md#running-your-gateway).
|
||||
- if you *automated* your node with systemd (recommended) run:
|
||||
- if your node is not automated, just `run` your `<NODE>` with `./nym-<NODE> run --id <ID>`. Here are exact guidelines for [Mix Node](./mix-node-setup.md#running-your-mix-node) and [Gateway](./gateway-setup.md#running-your-gateway).
|
||||
- if you automatized your node via systemd (recommended) run:
|
||||
```sh
|
||||
systemctl daemon-reload # to pickup the new unit file
|
||||
systemctl start <NODE>.service
|
||||
systemctl start nym-<NODE>.service
|
||||
journalctl -f -u <NODE>.service # to monitor log of you node
|
||||
```
|
||||
|
||||
@@ -53,7 +52,7 @@ You can either do this graphically via the Desktop Wallet, or the CLI.
|
||||
|
||||

|
||||
|
||||
* Update the fields in the `Node Settings` page (usually the field `Version` is the only one to change) and click `Submit changes to the blockchain`.
|
||||
* Update the fields in the `Node Settings` page and click `Submit changes to the blockchain`.
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -45,9 +45,9 @@ serde = { version = "1.0", features = ["derive"] }
|
||||
serde_derive = "1.0.149"
|
||||
serde_json = "1.0.91"
|
||||
thiserror = { workspace = true }
|
||||
tokio = { workspace = true, features = ["macros", "net","rt-multi-thread"] }
|
||||
tokio = { version = "1", features = ["macros", "net","rt-multi-thread"] }
|
||||
tokio-tungstenite = { workspace = true }
|
||||
tokio-util = { workspace = true, features = ["full"] }
|
||||
tokio-util = { version = "0.7.4", features = ["full"] }
|
||||
toml = "0.7.0"
|
||||
unsigned-varint = "0.7.1"
|
||||
utoipa = { workspace = true, features = ["actix_extras"] }
|
||||
|
||||
@@ -8,7 +8,7 @@ edition = "2021"
|
||||
[dependencies]
|
||||
chrono = { version = "0.4.31", features = ["serde"] }
|
||||
clap = { workspace = true, features = ["cargo", "derive"] }
|
||||
dotenvy = { workspace = true }
|
||||
dotenvy = "0.15.6"
|
||||
humantime-serde = "1.0"
|
||||
isocountry = "0.3.2"
|
||||
itertools = "0.10.3"
|
||||
|
||||
@@ -31,7 +31,8 @@ humantime-serde = "1.0.1"
|
||||
ipnetwork = "0.16"
|
||||
lazy_static = "1.4.0"
|
||||
log = { workspace = true }
|
||||
once_cell = { workspace = true }
|
||||
once_cell = "1.7.2"
|
||||
pretty_env_logger = "0.4"
|
||||
rand = "0.7"
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
@@ -50,9 +51,9 @@ tokio = { workspace = true, features = [
|
||||
"fs",
|
||||
"time",
|
||||
] }
|
||||
tokio-stream = { workspace = true, features = ["fs"] }
|
||||
tokio-tungstenite = { workspace = true }
|
||||
tokio-util = { workspace = true, features = ["codec"] }
|
||||
tokio-stream = { version = "0.1.11", features = ["fs"] }
|
||||
tokio-tungstenite = { version = "0.20.1" }
|
||||
tokio-util = { version = "0.7.4", features = ["codec"] }
|
||||
url = { workspace = true, features = ["serde"] }
|
||||
zeroize = { workspace = true }
|
||||
|
||||
|
||||
@@ -38,7 +38,6 @@ pub(crate) struct OverrideConfig {
|
||||
pub(crate) statistics_service_url: Option<url::Url>,
|
||||
pub(crate) nym_apis: Option<Vec<url::Url>>,
|
||||
pub(crate) mnemonic: Option<bip39::Mnemonic>,
|
||||
pub(crate) enforce_forward_travel: Option<bool>,
|
||||
pub(crate) nyxd_urls: Option<Vec<url::Url>>,
|
||||
pub(crate) only_coconut_credentials: Option<bool>,
|
||||
pub(crate) with_network_requester: Option<bool>,
|
||||
@@ -53,10 +52,6 @@ impl OverrideConfig {
|
||||
.with_optional(Config::with_listening_address, self.listening_address)
|
||||
.with_optional(Config::with_mix_port, self.mix_port)
|
||||
.with_optional(Config::with_clients_port, self.clients_port)
|
||||
.with_optional(
|
||||
Config::with_enforce_forward_travel,
|
||||
self.enforce_forward_travel,
|
||||
)
|
||||
.with_optional_custom_env(
|
||||
Config::with_custom_nym_apis,
|
||||
self.nym_apis,
|
||||
|
||||
@@ -20,41 +20,41 @@ use super::helpers::OverrideIpPacketRouterConfig;
|
||||
#[derive(Args, Clone)]
|
||||
pub struct Init {
|
||||
/// Id of the gateway we want to create config for
|
||||
#[arg(long)]
|
||||
#[clap(long)]
|
||||
id: String,
|
||||
|
||||
/// The listening address on which the gateway will be receiving sphinx packets and listening for client data
|
||||
#[arg(long, alias = "host")]
|
||||
#[clap(long, alias = "host")]
|
||||
listening_address: IpAddr,
|
||||
|
||||
/// Comma separated list of public ip addresses that will announced to the nym-api and subsequently to the clients.
|
||||
/// In nearly all circumstances, it's going to be identical to the address you're going to use for bonding.
|
||||
#[arg(long, value_delimiter = ',')]
|
||||
#[clap(long, value_delimiter = ',')]
|
||||
public_ips: Option<Vec<IpAddr>>,
|
||||
|
||||
/// Optional hostname associated with this gateway that will announced to the nym-api and subsequently to the clients
|
||||
#[arg(long)]
|
||||
#[clap(long)]
|
||||
hostname: Option<String>,
|
||||
|
||||
/// The port on which the gateway will be listening for sphinx packets
|
||||
#[arg(long)]
|
||||
#[clap(long)]
|
||||
mix_port: Option<u16>,
|
||||
|
||||
/// The port on which the gateway will be listening for clients gateway-requests
|
||||
#[arg(long)]
|
||||
#[clap(long)]
|
||||
clients_port: Option<u16>,
|
||||
|
||||
/// Path to sqlite database containing all gateway persistent data
|
||||
#[arg(long)]
|
||||
#[clap(long)]
|
||||
datastore: Option<PathBuf>,
|
||||
|
||||
/// Comma separated list of endpoints of nym APIs
|
||||
#[arg(long, alias = "validator_apis", value_delimiter = ',')]
|
||||
#[clap(long, alias = "validator_apis", value_delimiter = ',')]
|
||||
// the alias here is included for backwards compatibility (1.1.4 and before)
|
||||
nym_apis: Option<Vec<url::Url>>,
|
||||
|
||||
/// Comma separated list of endpoints of the validator
|
||||
#[arg(
|
||||
#[clap(
|
||||
long,
|
||||
alias = "validators",
|
||||
alias = "nyxd_validators",
|
||||
@@ -65,52 +65,47 @@ pub struct Init {
|
||||
nyxd_urls: Option<Vec<url::Url>>,
|
||||
|
||||
/// Cosmos wallet mnemonic needed for double spending protection
|
||||
#[arg(long)]
|
||||
#[clap(long)]
|
||||
mnemonic: Option<bip39::Mnemonic>,
|
||||
|
||||
/// Set this gateway to work only with coconut credentials; that would disallow clients to
|
||||
/// bypass bandwidth credential requirement
|
||||
#[arg(long, hide = true)]
|
||||
#[clap(long, hide = true)]
|
||||
only_coconut_credentials: Option<bool>,
|
||||
|
||||
/// Enable/disable gateway anonymized statistics that get sent to a statistics aggregator server
|
||||
#[arg(long)]
|
||||
#[clap(long)]
|
||||
enabled_statistics: Option<bool>,
|
||||
|
||||
/// URL where a statistics aggregator is running. The default value is a Nym aggregator server
|
||||
#[arg(long)]
|
||||
#[clap(long)]
|
||||
statistics_service_url: Option<url::Url>,
|
||||
|
||||
/// Specifies whether this node should accepts and send out packets that would only go to nodes
|
||||
/// on the next mix layer
|
||||
#[arg(long)]
|
||||
enforce_forward_travel: bool,
|
||||
|
||||
/// Allows this gateway to run an embedded network requester for minimal network overhead
|
||||
#[arg(long, conflicts_with = "with_ip_packet_router")]
|
||||
#[clap(long, conflicts_with = "with_ip_packet_router")]
|
||||
with_network_requester: bool,
|
||||
|
||||
/// Allows this gateway to run an embedded network requester for minimal network overhead
|
||||
#[arg(long, hide = true, conflicts_with = "with_network_requester")]
|
||||
#[clap(long, hide = true, conflicts_with = "with_network_requester")]
|
||||
with_ip_packet_router: bool,
|
||||
|
||||
// ##### NETWORK REQUESTER FLAGS #####
|
||||
/// Specifies whether this network requester should run in 'open-proxy' mode
|
||||
#[arg(long, requires = "with_network_requester")]
|
||||
#[clap(long, requires = "with_network_requester")]
|
||||
open_proxy: Option<bool>,
|
||||
|
||||
/// Enable service anonymized statistics that get sent to a statistics aggregator server
|
||||
#[arg(long, requires = "with_network_requester")]
|
||||
#[clap(long, requires = "with_network_requester")]
|
||||
enable_statistics: Option<bool>,
|
||||
|
||||
/// Mixnet client address where a statistics aggregator is running. The default value is a Nym
|
||||
/// aggregator client
|
||||
#[arg(long, requires = "with_network_requester")]
|
||||
#[clap(long, requires = "with_network_requester")]
|
||||
statistics_recipient: Option<String>,
|
||||
|
||||
/// Mostly debug-related option to increase default traffic rate so that you would not need to
|
||||
/// modify config post init
|
||||
#[arg(
|
||||
#[clap(
|
||||
long,
|
||||
hide = true,
|
||||
conflicts_with = "medium_toggle",
|
||||
@@ -119,7 +114,7 @@ pub struct Init {
|
||||
fastmode: bool,
|
||||
|
||||
/// Disable loop cover traffic and the Poisson rate limiter (for debugging only)
|
||||
#[arg(
|
||||
#[clap(
|
||||
long,
|
||||
hide = true,
|
||||
conflicts_with = "medium_toggle",
|
||||
@@ -129,7 +124,7 @@ pub struct Init {
|
||||
|
||||
/// Enable medium mixnet traffic, for experiments only.
|
||||
/// This includes things like disabling cover traffic, no per hop delays, etc.
|
||||
#[arg(
|
||||
#[clap(
|
||||
long,
|
||||
hide = true,
|
||||
conflicts_with = "no_cover",
|
||||
@@ -141,10 +136,10 @@ pub struct Init {
|
||||
/// Specifies whether this network requester will run using the default ExitPolicy
|
||||
/// as opposed to the allow list.
|
||||
/// Note: this setting will become the default in the future releases.
|
||||
#[arg(long)]
|
||||
#[clap(long)]
|
||||
with_exit_policy: Option<bool>,
|
||||
|
||||
#[arg(short, long, default_value_t = OutputFormat::default())]
|
||||
#[clap(short, long, default_value_t = OutputFormat::default())]
|
||||
output: OutputFormat,
|
||||
}
|
||||
|
||||
@@ -159,7 +154,6 @@ impl From<Init> for OverrideConfig {
|
||||
datastore: init_config.datastore,
|
||||
nym_apis: init_config.nym_apis,
|
||||
mnemonic: init_config.mnemonic,
|
||||
enforce_forward_travel: Some(init_config.enforce_forward_travel),
|
||||
|
||||
enabled_statistics: init_config.enabled_statistics,
|
||||
statistics_service_url: init_config.statistics_service_url,
|
||||
@@ -308,7 +302,6 @@ mod tests {
|
||||
no_cover: false,
|
||||
medium_toggle: false,
|
||||
with_exit_policy: None,
|
||||
enforce_forward_travel: false,
|
||||
};
|
||||
std::env::set_var(BECH32_PREFIX, "n");
|
||||
|
||||
|
||||
@@ -108,11 +108,6 @@ pub struct Run {
|
||||
#[arg(long)]
|
||||
statistics_recipient: Option<String>,
|
||||
|
||||
/// Specifies whether this node should accepts and send out packets that would only go to nodes
|
||||
/// on the next mix layer
|
||||
#[arg(long)]
|
||||
enforce_forward_travel: Option<bool>,
|
||||
|
||||
/// Mostly debug-related option to increase default traffic rate so that you would not need to
|
||||
/// modify config post init
|
||||
#[arg(long, hide = true, conflicts_with = "medium_toggle")]
|
||||
@@ -162,7 +157,6 @@ impl From<Run> for OverrideConfig {
|
||||
datastore: run_config.datastore,
|
||||
nym_apis: run_config.nym_apis,
|
||||
mnemonic: run_config.mnemonic,
|
||||
enforce_forward_travel: run_config.enforce_forward_travel,
|
||||
|
||||
enabled_statistics: run_config.enabled_statistics,
|
||||
statistics_service_url: run_config.statistics_service_url,
|
||||
|
||||
@@ -188,13 +188,11 @@ impl Config {
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_enabled_network_requester(mut self, enabled_network_requester: bool) -> Self {
|
||||
self.network_requester.enabled = enabled_network_requester;
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_default_network_requester_config_path(mut self) -> Self {
|
||||
self.storage_paths = self
|
||||
.storage_paths
|
||||
@@ -214,43 +212,36 @@ impl Config {
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_only_coconut_credentials(mut self, only_coconut_credentials: bool) -> Self {
|
||||
self.gateway.only_coconut_credentials = only_coconut_credentials;
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_enabled_statistics(mut self, enabled_statistics: bool) -> Self {
|
||||
self.gateway.enabled_statistics = enabled_statistics;
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_custom_statistics_service_url(mut self, statistics_service_url: Url) -> Self {
|
||||
self.gateway.statistics_service_url = statistics_service_url;
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_custom_nym_apis(mut self, nym_api_urls: Vec<Url>) -> Self {
|
||||
self.gateway.nym_api_urls = nym_api_urls;
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_custom_validator_nyxd(mut self, validator_nyxd_urls: Vec<Url>) -> Self {
|
||||
self.gateway.nyxd_urls = validator_nyxd_urls;
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_cosmos_mnemonic(mut self, cosmos_mnemonic: bip39::Mnemonic) -> Self {
|
||||
self.gateway.cosmos_mnemonic = cosmos_mnemonic;
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_listening_address(mut self, listening_address: IpAddr) -> Self {
|
||||
self.gateway.listening_address = listening_address;
|
||||
|
||||
@@ -262,25 +253,16 @@ impl Config {
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_mix_port(mut self, port: u16) -> Self {
|
||||
self.gateway.mix_port = port;
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_clients_port(mut self, port: u16) -> Self {
|
||||
self.gateway.clients_port = port;
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_enforce_forward_travel(mut self, forward_travel: bool) -> Self {
|
||||
self.debug.enforce_forward_travel = forward_travel;
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_custom_persistent_store(mut self, store_dir: PathBuf) -> Self {
|
||||
self.storage_paths.clients_storage = store_dir;
|
||||
self
|
||||
@@ -346,8 +328,7 @@ pub struct Gateway {
|
||||
#[zeroize(skip)]
|
||||
pub nym_api_urls: Vec<Url>,
|
||||
|
||||
/// Addresses to nyxd validators via which the node can communicate with the chain directly,
|
||||
/// including for checking for double spending of coconut credentials.
|
||||
/// Addresses to validators which the node uses to check for double spending of ERC20 tokens.
|
||||
#[serde(alias = "validator_nymd_urls")]
|
||||
#[zeroize(skip)]
|
||||
pub nyxd_urls: Vec<Url>,
|
||||
@@ -440,10 +421,6 @@ pub struct Debug {
|
||||
/// Number of messages from offline client that can be pulled at once from the storage.
|
||||
pub message_retrieval_limit: i64,
|
||||
|
||||
/// Specifies whether this node should accepts and send out packets that would only go to nodes
|
||||
/// on the next mix layer.
|
||||
pub enforce_forward_travel: bool,
|
||||
|
||||
/// Specifies whether the mixnode should be using the legacy framing for the sphinx packets.
|
||||
// it's set to true by default. The reason for that decision is to preserve compatibility with the
|
||||
// existing nodes whilst everyone else is upgrading and getting the code for handling the new field.
|
||||
@@ -461,9 +438,6 @@ impl Default for Debug {
|
||||
maximum_connection_buffer_size: DEFAULT_MAXIMUM_CONNECTION_BUFFER_SIZE,
|
||||
stored_messages_filename_length: DEFAULT_STORED_MESSAGE_FILENAME_LENGTH,
|
||||
message_retrieval_limit: DEFAULT_MESSAGE_RETRIEVAL_LIMIT,
|
||||
|
||||
// let's keep it disabled for now to not surprise operators/users
|
||||
enforce_forward_travel: false,
|
||||
use_legacy_framed_packet_version: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,7 +163,6 @@ impl From<ConfigV1_1_31> for Config {
|
||||
presence_sending_delay: value.debug.presence_sending_delay,
|
||||
stored_messages_filename_length: value.debug.stored_messages_filename_length,
|
||||
message_retrieval_limit: value.debug.message_retrieval_limit,
|
||||
enforce_forward_travel: false,
|
||||
use_legacy_framed_packet_version: value.debug.use_legacy_framed_packet_version,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -116,10 +116,4 @@ ip_packet_router_config = '{{ storage_paths.ip_packet_router_config }}'
|
||||
|
||||
# TODO
|
||||
|
||||
[debug]
|
||||
|
||||
# Specifies whether this node should accepts and send out packets that would only go to nodes
|
||||
# on the next mix layer.
|
||||
enforce_forward_travel = {{ debug.enforce_forward_travel }}
|
||||
|
||||
"#;
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
use crate::node::storage::error::StorageError;
|
||||
use nym_ip_packet_router::error::IpPacketRouterError;
|
||||
use nym_mixnode_common::forward_travel::error::ForwardTravelError;
|
||||
use nym_network_requester::error::{ClientCoreError, NetworkRequesterError};
|
||||
use nym_validator_client::nyxd::error::NyxdError;
|
||||
use nym_validator_client::nyxd::AccountId;
|
||||
@@ -132,12 +131,6 @@ pub(crate) enum GatewayError {
|
||||
source: NyxdError,
|
||||
},
|
||||
|
||||
#[error("failure in enforcing forward travel of mix packets: {source}")]
|
||||
ForwardTravel {
|
||||
#[from]
|
||||
source: ForwardTravelError,
|
||||
},
|
||||
|
||||
// TODO: in the future this should work the other way, i.e. NymNode depending on Gateway errors
|
||||
#[error(transparent)]
|
||||
NymNodeError(#[from] nym_node::error::NymNodeError),
|
||||
|
||||
@@ -15,12 +15,12 @@ use nym_sphinx::forwarding::packet::MixPacket;
|
||||
use nym_task::TaskClient;
|
||||
use nym_validator_client::coconut::CoconutApiError;
|
||||
use rand::{CryptoRng, Rng};
|
||||
use std::net::SocketAddr;
|
||||
use std::{convert::TryFrom, process, time::Duration};
|
||||
use thiserror::Error;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
use tokio_tungstenite::tungstenite::{protocol::Message, Error as WsError};
|
||||
|
||||
use std::{convert::TryFrom, process, time::Duration};
|
||||
|
||||
use crate::node::{
|
||||
client_handling::{
|
||||
bandwidth::Bandwidth,
|
||||
@@ -40,13 +40,13 @@ pub(crate) enum RequestHandlingError {
|
||||
#[error("Internal gateway storage error")]
|
||||
StorageError(#[from] StorageError),
|
||||
|
||||
#[error("Provided bandwidth IV is malformed: {0}")]
|
||||
#[error("Provided bandwidth IV is malformed - {0}")]
|
||||
MalformedIV(#[from] IVConversionError),
|
||||
|
||||
#[error("Provided binary request was malformed: {0}")]
|
||||
#[error("Provided binary request was malformed - {0}")]
|
||||
InvalidBinaryRequest(#[from] GatewayRequestsError),
|
||||
|
||||
#[error("Provided binary request was malformed: {0}")]
|
||||
#[error("Provided binary request was malformed - {0}")]
|
||||
InvalidTextRequest(<ClientControlRequest as TryFrom<String>>::Error),
|
||||
|
||||
#[error("The received request is not valid in the current context")]
|
||||
@@ -61,10 +61,10 @@ pub(crate) enum RequestHandlingError {
|
||||
#[error("This gateway is only accepting coconut credentials for bandwidth")]
|
||||
OnlyCoconutCredentials,
|
||||
|
||||
#[error("Nyxd Error: {0}")]
|
||||
#[error("Nyxd Error - {0}")]
|
||||
NyxdError(#[from] nym_validator_client::nyxd::error::NyxdError),
|
||||
|
||||
#[error("Validator API error: {0}")]
|
||||
#[error("Validator API error - {0}")]
|
||||
APIError(#[from] nym_validator_client::ValidatorClientError),
|
||||
|
||||
#[error("Not enough nym API endpoints provided. Needed {needed}, received {received}")]
|
||||
@@ -73,17 +73,14 @@ pub(crate) enum RequestHandlingError {
|
||||
#[error("There was a problem with the proposal id: {reason}")]
|
||||
ProposalIdError { reason: String },
|
||||
|
||||
#[error("Coconut interface error: {0}")]
|
||||
#[error("Coconut interface error - {0}")]
|
||||
CoconutInterfaceError(#[from] nym_coconut_interface::error::CoconutInterfaceError),
|
||||
|
||||
#[error("coconut api query failure: {0}")]
|
||||
CoconutApiError(#[from] CoconutApiError),
|
||||
|
||||
#[error("Credential error: {0}")]
|
||||
#[error("Credential error - {0}")]
|
||||
CredentialError(#[from] nym_credentials::error::Error),
|
||||
|
||||
#[error("the outbound address of the received packet ('{address}') is forbidden as there are no nodes with that address on the next layer")]
|
||||
InvalidForwardHop { address: SocketAddr },
|
||||
}
|
||||
|
||||
impl RequestHandlingError {
|
||||
@@ -206,25 +203,11 @@ where
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `mix_packet`: packet received from the client that should get forwarded into the network.
|
||||
fn forward_packet(&self, mix_packet: MixPacket) -> Result<(), RequestHandlingError> {
|
||||
let next_hop: SocketAddr = mix_packet.next_hop().into();
|
||||
|
||||
// TODO: another option is to move this filter
|
||||
// (which is used by EVERY `ConnectionHandler`, so potentially hundreds of times)
|
||||
// to packet forwarder where we could be filtering at the time of attempting to open new outbound connections
|
||||
// However, in that case we wouldn't be able to return an error message to the client
|
||||
if !self.inner.allowed_egress.is_allowed(next_hop.ip()) {
|
||||
// TODO: perhaps this should get lowered in severity?
|
||||
warn!("received an packet that was meant to get forwarded to {next_hop}, but this address does not belong to any node on the next layer - dropping the packet");
|
||||
return Err(RequestHandlingError::InvalidForwardHop { address: next_hop });
|
||||
}
|
||||
|
||||
fn forward_packet(&self, mix_packet: MixPacket) {
|
||||
if let Err(err) = self.inner.outbound_mix_sender.unbounded_send(mix_packet) {
|
||||
error!("We failed to forward requested mix packet - {err}. Presumably our mix forwarder has crashed. We cannot continue.");
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Tries to handle the received bandwidth request by checking correctness of the received data
|
||||
@@ -334,7 +317,7 @@ where
|
||||
}
|
||||
|
||||
self.consume_bandwidth(consumed_bandwidth).await?;
|
||||
self.forward_packet(mix_packet)?;
|
||||
self.forward_packet(mix_packet);
|
||||
|
||||
Ok(ServerResponse::Send {
|
||||
remaining_bandwidth: available_bandwidth - consumed_bandwidth,
|
||||
|
||||
@@ -18,7 +18,6 @@ use nym_gateway_requests::{
|
||||
BinaryResponse, PROTOCOL_VERSION,
|
||||
};
|
||||
use nym_mixnet_client::forwarder::MixForwardingSender;
|
||||
use nym_mixnode_common::forward_travel::AllowedEgress;
|
||||
use nym_sphinx::DestinationAddressBytes;
|
||||
use rand::{CryptoRng, Rng};
|
||||
use std::{convert::TryFrom, sync::Arc, time::Duration};
|
||||
@@ -90,7 +89,6 @@ impl InitialAuthenticationError {
|
||||
pub(crate) struct FreshHandler<R, S, St> {
|
||||
rng: R,
|
||||
local_identity: Arc<identity::KeyPair>,
|
||||
pub(crate) allowed_egress: AllowedEgress,
|
||||
pub(crate) only_coconut_credentials: bool,
|
||||
pub(crate) active_clients_store: ActiveClientsStore,
|
||||
pub(crate) outbound_mix_sender: MixForwardingSender,
|
||||
@@ -112,7 +110,6 @@ where
|
||||
pub(crate) fn new(
|
||||
rng: R,
|
||||
conn: S,
|
||||
allowed_egress: AllowedEgress,
|
||||
only_coconut_credentials: bool,
|
||||
outbound_mix_sender: MixForwardingSender,
|
||||
local_identity: Arc<identity::KeyPair>,
|
||||
@@ -129,7 +126,6 @@ where
|
||||
local_identity,
|
||||
storage,
|
||||
coconut_verifier,
|
||||
allowed_egress,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ use crate::node::storage::Storage;
|
||||
use log::*;
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_mixnet_client::forwarder::MixForwardingSender;
|
||||
use nym_mixnode_common::forward_travel::AllowedEgress;
|
||||
use rand::rngs::OsRng;
|
||||
use std::net::SocketAddr;
|
||||
use std::process;
|
||||
@@ -17,7 +16,6 @@ use tokio::task::JoinHandle;
|
||||
|
||||
pub(crate) struct Listener {
|
||||
address: SocketAddr,
|
||||
allowed_egress: AllowedEgress,
|
||||
local_identity: Arc<identity::KeyPair>,
|
||||
only_coconut_credentials: bool,
|
||||
pub(crate) coconut_verifier: Arc<CoconutVerifier>,
|
||||
@@ -26,14 +24,12 @@ pub(crate) struct Listener {
|
||||
impl Listener {
|
||||
pub(crate) fn new(
|
||||
address: SocketAddr,
|
||||
allowed_egress: AllowedEgress,
|
||||
local_identity: Arc<identity::KeyPair>,
|
||||
only_coconut_credentials: bool,
|
||||
coconut_verifier: Arc<CoconutVerifier>,
|
||||
) -> Self {
|
||||
Listener {
|
||||
address,
|
||||
allowed_egress,
|
||||
local_identity,
|
||||
only_coconut_credentials,
|
||||
coconut_verifier,
|
||||
@@ -75,7 +71,6 @@ impl Listener {
|
||||
let handle = FreshHandler::new(
|
||||
OsRng,
|
||||
socket,
|
||||
self.allowed_egress.clone(),
|
||||
self.only_coconut_credentials,
|
||||
outbound_mix_sender.clone(),
|
||||
Arc::clone(&self.local_identity),
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
use crate::node::mixnet_handling::receiver::connection_handler::ConnectionHandler;
|
||||
use crate::node::storage::Storage;
|
||||
use log::*;
|
||||
use nym_mixnode_common::forward_travel::AllowedIngress;
|
||||
use nym_task::TaskClient;
|
||||
use std::net::SocketAddr;
|
||||
use std::process;
|
||||
@@ -12,22 +11,13 @@ use tokio::task::JoinHandle;
|
||||
|
||||
pub(crate) struct Listener {
|
||||
address: SocketAddr,
|
||||
allowed_ingress: AllowedIngress,
|
||||
shutdown: TaskClient,
|
||||
}
|
||||
|
||||
// TODO: this file is nearly identical to the one in mixnode
|
||||
impl Listener {
|
||||
pub(crate) fn new(
|
||||
address: SocketAddr,
|
||||
allowed_ingress: AllowedIngress,
|
||||
shutdown: TaskClient,
|
||||
) -> Self {
|
||||
Listener {
|
||||
address,
|
||||
allowed_ingress,
|
||||
shutdown,
|
||||
}
|
||||
pub(crate) fn new(address: SocketAddr, shutdown: TaskClient) -> Self {
|
||||
Listener { address, shutdown }
|
||||
}
|
||||
|
||||
pub(crate) async fn run<St>(&mut self, connection_handler: ConnectionHandler<St>)
|
||||
@@ -52,12 +42,6 @@ impl Listener {
|
||||
connection = tcp_listener.accept() => {
|
||||
match connection {
|
||||
Ok((socket, remote_addr)) => {
|
||||
if !self.allowed_ingress.is_allowed(remote_addr.ip()) {
|
||||
// TODO: perhaps this should get lowered in severity?
|
||||
warn!("received an incoming connection from {remote_addr}, but this address does not belong to any node on the previous layer - dropping the connection");
|
||||
continue
|
||||
}
|
||||
|
||||
let handler = connection_handler.clone();
|
||||
tokio::spawn(handler.handle_connection(socket, remote_addr, self.shutdown.clone().named(format!("MixnetConnectionHandler_{remote_addr}"))));
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ use futures::channel::{mpsc, oneshot};
|
||||
use log::*;
|
||||
use nym_crypto::asymmetric::{encryption, identity};
|
||||
use nym_mixnet_client::forwarder::{MixForwardingSender, PacketForwarder};
|
||||
use nym_mixnode_common::forward_travel::{AllowedAddressesProvider, AllowedEgress, AllowedIngress};
|
||||
use nym_network_defaults::NymNetworkDetails;
|
||||
use nym_network_requester::{LocalGateway, NRServiceProviderBuilder, RequestFilter};
|
||||
use nym_node::wireguard::types::GatewayClientRegistry;
|
||||
@@ -179,7 +178,6 @@ impl<St> Gateway<St> {
|
||||
&self,
|
||||
ack_sender: MixForwardingSender,
|
||||
active_clients_store: ActiveClientsStore,
|
||||
ingress: AllowedIngress,
|
||||
shutdown: TaskClient,
|
||||
) where
|
||||
St: Storage + Clone + 'static,
|
||||
@@ -201,8 +199,7 @@ impl<St> Gateway<St> {
|
||||
self.config.gateway.mix_port,
|
||||
);
|
||||
|
||||
mixnet_handling::Listener::new(listening_address, ingress, shutdown)
|
||||
.start(connection_handler);
|
||||
mixnet_handling::Listener::new(listening_address, shutdown).start(connection_handler);
|
||||
}
|
||||
|
||||
#[cfg(feature = "wireguard")]
|
||||
@@ -215,7 +212,6 @@ impl<St> Gateway<St> {
|
||||
|
||||
fn start_client_websocket_listener(
|
||||
&self,
|
||||
allowed_egress: AllowedEgress,
|
||||
forwarding_channel: MixForwardingSender,
|
||||
active_clients_store: ActiveClientsStore,
|
||||
shutdown: TaskClient,
|
||||
@@ -232,7 +228,6 @@ impl<St> Gateway<St> {
|
||||
|
||||
websocket::Listener::new(
|
||||
listening_address,
|
||||
allowed_egress,
|
||||
Arc::clone(&self.identity_keypair),
|
||||
self.config.gateway.only_coconut_credentials,
|
||||
coconut_verifier,
|
||||
@@ -245,28 +240,6 @@ impl<St> Gateway<St> {
|
||||
);
|
||||
}
|
||||
|
||||
async fn start_allowed_addresses_provider(
|
||||
&self,
|
||||
task_client: TaskClient,
|
||||
) -> Result<(AllowedIngress, AllowedEgress), GatewayError> {
|
||||
let identity = self.identity_keypair.public_key().to_base58_string();
|
||||
let nyxd_endpoints = self.config.gateway.nyxd_urls.clone();
|
||||
|
||||
let network = NymNetworkDetails::new_from_env();
|
||||
let mut provider = AllowedAddressesProvider::new(
|
||||
identity,
|
||||
nyxd_endpoints,
|
||||
!self.config.debug.enforce_forward_travel,
|
||||
Some(network),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let filters = (provider.ingress(), provider.egress());
|
||||
|
||||
tokio::spawn(async move { provider.run(task_client).await });
|
||||
Ok(filters)
|
||||
}
|
||||
|
||||
fn start_packet_forwarder(&self, shutdown: TaskClient) -> MixForwardingSender {
|
||||
info!("Starting mix packet forwarder...");
|
||||
|
||||
@@ -374,19 +347,19 @@ impl<St> Gateway<St> {
|
||||
|
||||
// TODO: well, wire it up internally to gateway traffic, shutdowns, etc.
|
||||
let (on_start_tx, on_start_rx) = oneshot::channel();
|
||||
let mut ip_packet_router =
|
||||
nym_ip_packet_router::IpPacketRouter::new(ip_opts.config.clone())
|
||||
let mut ip_builder =
|
||||
nym_ip_packet_router::IpPacketRouterBuilder::new(ip_opts.config.clone())
|
||||
.with_shutdown(shutdown)
|
||||
.with_custom_gateway_transceiver(Box::new(transceiver))
|
||||
.with_wait_for_gateway(true)
|
||||
.with_on_start(on_start_tx);
|
||||
|
||||
if let Some(custom_mixnet) = &ip_opts.custom_mixnet_path {
|
||||
ip_packet_router = ip_packet_router.with_stored_topology(custom_mixnet)?
|
||||
ip_builder = ip_builder.with_stored_topology(custom_mixnet)?
|
||||
}
|
||||
|
||||
tokio::spawn(async move {
|
||||
if let Err(err) = ip_packet_router.run_service_provider().await {
|
||||
if let Err(err) = ip_builder.run_service_provider().await {
|
||||
// no need to panic as we have passed a task client to the ip packet router so
|
||||
// we're most likely already in the process of shutting down
|
||||
error!("ip packet router has failed: {err}")
|
||||
@@ -476,12 +449,6 @@ impl<St> Gateway<St> {
|
||||
|
||||
let shutdown = TaskManager::new(10);
|
||||
|
||||
let (ingress, egress) = self
|
||||
.start_allowed_addresses_provider(
|
||||
shutdown.subscribe().named("AllowedAddressesProvider"),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let coconut_verifier = {
|
||||
let nyxd_client = self.random_nyxd_client()?;
|
||||
CoconutVerifier::new(nyxd_client)
|
||||
@@ -494,7 +461,6 @@ impl<St> Gateway<St> {
|
||||
self.start_mix_socket_listener(
|
||||
mix_forwarding_channel.clone(),
|
||||
active_clients_store.clone(),
|
||||
ingress,
|
||||
shutdown.subscribe().named("mixnet_handling::Listener"),
|
||||
);
|
||||
|
||||
@@ -512,7 +478,6 @@ impl<St> Gateway<St> {
|
||||
}
|
||||
|
||||
self.start_client_websocket_listener(
|
||||
egress,
|
||||
mix_forwarding_channel.clone(),
|
||||
active_clients_store.clone(),
|
||||
shutdown.subscribe().named("websocket::Listener"),
|
||||
|
||||
@@ -18,7 +18,7 @@ rust-version = "1.58.1"
|
||||
|
||||
[dependencies]
|
||||
axum = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
anyhow = "1.0.40"
|
||||
bs58 = "0.4.0"
|
||||
clap = { workspace = true, features = ["cargo", "derive"] }
|
||||
colored = "2.0"
|
||||
@@ -26,14 +26,15 @@ cupid = "0.6.1"
|
||||
dirs = "4.0"
|
||||
futures = { workspace = true }
|
||||
humantime-serde = "1.0"
|
||||
lazy_static = { workspace = true }
|
||||
lazy_static = "1.4.0"
|
||||
log = { workspace = true }
|
||||
pretty_env_logger = "0.4.0"
|
||||
rand = "0.7.3"
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
sysinfo = "0.27.7"
|
||||
tokio = { workspace = true, features = ["rt-multi-thread", "net", "signal"] }
|
||||
tokio-util = { workspace = true, features = ["codec"] }
|
||||
tokio = { version = "1.21.2", features = ["rt-multi-thread", "net", "signal"] }
|
||||
tokio-util = { version = "0.7.3", features = ["codec"] }
|
||||
toml = "0.5.8"
|
||||
url = { workspace = true, features = ["serde"] }
|
||||
cfg-if = "1.0.0"
|
||||
|
||||
@@ -16,40 +16,31 @@ use std::{fs, io};
|
||||
#[derive(Args, Clone)]
|
||||
pub(crate) struct Init {
|
||||
/// Id of the mixnode we want to create config for
|
||||
#[arg(long)]
|
||||
#[clap(long)]
|
||||
id: String,
|
||||
|
||||
/// The host on which the mixnode will be running
|
||||
#[arg(long)]
|
||||
#[clap(long)]
|
||||
host: IpAddr,
|
||||
|
||||
/// The port on which the mixnode will be listening for mix packets
|
||||
#[arg(long)]
|
||||
#[clap(long)]
|
||||
mix_port: Option<u16>,
|
||||
|
||||
/// The port on which the mixnode will be listening for verloc packets
|
||||
#[arg(long)]
|
||||
#[clap(long)]
|
||||
verloc_port: Option<u16>,
|
||||
|
||||
/// The port on which the mixnode will be listening for http requests
|
||||
#[arg(long)]
|
||||
#[clap(long)]
|
||||
http_api_port: Option<u16>,
|
||||
|
||||
/// Comma separated list of nym-api endpoints of the validators
|
||||
// the alias here is included for backwards compatibility (1.1.4 and before)
|
||||
#[arg(long, alias = "validators", value_delimiter = ',')]
|
||||
#[clap(long, alias = "validators", value_delimiter = ',')]
|
||||
nym_apis: Option<Vec<url::Url>>,
|
||||
|
||||
/// Comma separated list of endpoints of the nyxd validators
|
||||
#[arg(long, value_delimiter = ',')]
|
||||
nyxd_urls: Option<Vec<url::Url>>,
|
||||
|
||||
/// Specifies whether this node should accepts and send out packets that would only go to nodes
|
||||
/// on the next mix layer
|
||||
#[arg(long)]
|
||||
enforce_forward_travel: bool,
|
||||
|
||||
#[arg(short, long, default_value_t = OutputFormat::default())]
|
||||
#[clap(short, long, default_value_t = OutputFormat::default())]
|
||||
output: OutputFormat,
|
||||
}
|
||||
|
||||
@@ -61,9 +52,7 @@ impl From<Init> for OverrideConfig {
|
||||
mix_port: init_config.mix_port,
|
||||
verloc_port: init_config.verloc_port,
|
||||
http_api_port: init_config.http_api_port,
|
||||
enforce_forward_travel: Some(init_config.enforce_forward_travel),
|
||||
nym_apis: init_config.nym_apis,
|
||||
nyxd_urls: init_config.nyxd_urls,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ use colored::Colorize;
|
||||
use log::{error, info, warn};
|
||||
use nym_bin_common::completions::{fig_generate, ArgShell};
|
||||
use nym_bin_common::version_checker;
|
||||
use nym_config::defaults::var_names;
|
||||
use nym_config::defaults::var_names::{BECH32_PREFIX, NYM_API};
|
||||
use nym_config::OptionalSet;
|
||||
use nym_crypto::bech32_address_validation;
|
||||
use std::net::IpAddr;
|
||||
@@ -58,9 +58,7 @@ struct OverrideConfig {
|
||||
mix_port: Option<u16>,
|
||||
verloc_port: Option<u16>,
|
||||
http_api_port: Option<u16>,
|
||||
enforce_forward_travel: Option<bool>,
|
||||
nym_apis: Option<Vec<url::Url>>,
|
||||
nyxd_urls: Option<Vec<url::Url>>,
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Cli) -> anyhow::Result<()> {
|
||||
@@ -85,32 +83,22 @@ fn override_config(config: Config, args: OverrideConfig) -> Config {
|
||||
.with_optional(Config::with_mix_port, args.mix_port)
|
||||
.with_optional(Config::with_verloc_port, args.verloc_port)
|
||||
.with_optional(Config::with_http_api_port, args.http_api_port)
|
||||
.with_optional(
|
||||
Config::with_enforce_forward_travel,
|
||||
args.enforce_forward_travel,
|
||||
)
|
||||
.with_optional_custom_env(
|
||||
Config::with_custom_nym_apis,
|
||||
args.nym_apis,
|
||||
var_names::NYM_API,
|
||||
nym_config::parse_urls,
|
||||
)
|
||||
.with_optional_custom_env(
|
||||
Config::with_custom_nyxd,
|
||||
args.nyxd_urls,
|
||||
var_names::NYXD,
|
||||
NYM_API,
|
||||
nym_config::parse_urls,
|
||||
)
|
||||
}
|
||||
|
||||
/// Ensures that a given bech32 address is valid, or exits
|
||||
pub(crate) fn validate_bech32_address_or_exit(address: &str) {
|
||||
let prefix = std::env::var(var_names::BECH32_PREFIX).expect("bech32 prefix not set");
|
||||
let prefix = std::env::var(BECH32_PREFIX).expect("bech32 prefix not set");
|
||||
if let Err(bech32_address_validation::Bech32Error::DecodeFailed(err)) =
|
||||
bech32_address_validation::try_bech32_decode(address)
|
||||
{
|
||||
let error_message = format!("Error: wallet address decoding failed: {err}").red();
|
||||
error!("{error_message}");
|
||||
error!("{}", error_message);
|
||||
error!("Exiting...");
|
||||
process::exit(1);
|
||||
}
|
||||
@@ -119,7 +107,7 @@ pub(crate) fn validate_bech32_address_or_exit(address: &str) {
|
||||
bech32_address_validation::validate_bech32_prefix(&prefix, address)
|
||||
{
|
||||
let error_message = format!("Error: wallet address type is wrong, {err}").red();
|
||||
error!("{error_message}");
|
||||
error!("{}", error_message);
|
||||
error!("Exiting...");
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
@@ -14,44 +14,35 @@ use std::net::IpAddr;
|
||||
#[derive(Args, Clone)]
|
||||
pub(crate) struct Run {
|
||||
/// Id of the nym-mixnode we want to run
|
||||
#[arg(long)]
|
||||
#[clap(long)]
|
||||
id: String,
|
||||
|
||||
/// The custom host on which the mixnode will be running
|
||||
#[arg(long)]
|
||||
#[clap(long)]
|
||||
host: Option<IpAddr>,
|
||||
|
||||
/// The wallet address you will use to bond this mixnode, e.g. nymt1z9egw0knv47nmur0p8vk4rcx59h9gg4zuxrrr9
|
||||
#[arg(long)]
|
||||
#[clap(long)]
|
||||
wallet_address: Option<nyxd::AccountId>,
|
||||
|
||||
/// The port on which the mixnode will be listening for mix packets
|
||||
#[arg(long)]
|
||||
#[clap(long)]
|
||||
mix_port: Option<u16>,
|
||||
|
||||
/// The port on which the mixnode will be listening for verloc packets
|
||||
#[arg(long)]
|
||||
#[clap(long)]
|
||||
verloc_port: Option<u16>,
|
||||
|
||||
/// The port on which the mixnode will be listening for http requests
|
||||
#[arg(long)]
|
||||
#[clap(long)]
|
||||
http_api_port: Option<u16>,
|
||||
|
||||
/// Comma separated list of nym-api endpoints of the validators
|
||||
// the alias here is included for backwards compatibility (1.1.4 and before)
|
||||
#[arg(long, alias = "validators", value_delimiter = ',')]
|
||||
#[clap(long, alias = "validators", value_delimiter = ',')]
|
||||
nym_apis: Option<Vec<url::Url>>,
|
||||
|
||||
/// Comma separated list of endpoints of the nyxd validators
|
||||
#[arg(long, value_delimiter = ',')]
|
||||
nyxd_urls: Option<Vec<url::Url>>,
|
||||
|
||||
/// Specifies whether this node should accepts and send out packets that would only go to nodes
|
||||
/// on the next mix layer
|
||||
#[arg(long)]
|
||||
enforce_forward_travel: Option<bool>,
|
||||
|
||||
#[arg(short, long, default_value_t = OutputFormat::default())]
|
||||
#[clap(short, long, default_value_t = OutputFormat::default())]
|
||||
output: OutputFormat,
|
||||
}
|
||||
|
||||
@@ -63,9 +54,7 @@ impl From<Run> for OverrideConfig {
|
||||
mix_port: run_config.mix_port,
|
||||
verloc_port: run_config.verloc_port,
|
||||
http_api_port: run_config.http_api_port,
|
||||
enforce_forward_travel: run_config.enforce_forward_travel,
|
||||
nym_apis: run_config.nym_apis,
|
||||
nyxd_urls: run_config.nyxd_urls,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,19 +175,11 @@ impl Config {
|
||||
}
|
||||
|
||||
// builder methods
|
||||
#[must_use]
|
||||
pub fn with_custom_nym_apis(mut self, nym_api_urls: Vec<Url>) -> Self {
|
||||
self.mixnode.nym_api_urls = nym_api_urls;
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_custom_nyxd(mut self, nyxd_urls: Vec<Url>) -> Self {
|
||||
self.mixnode.nyxd_urls = nyxd_urls;
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_listening_address(mut self, listening_address: IpAddr) -> Self {
|
||||
self.mixnode.listening_address = listening_address;
|
||||
|
||||
@@ -197,31 +189,22 @@ impl Config {
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_mix_port(mut self, port: u16) -> Self {
|
||||
self.mixnode.mix_port = port;
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_verloc_port(mut self, port: u16) -> Self {
|
||||
self.mixnode.verloc_port = port;
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_http_api_port(mut self, port: u16) -> Self {
|
||||
let http_ip = self.http.bind_address.ip();
|
||||
self.http.bind_address = SocketAddr::new(http_ip, port);
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_enforce_forward_travel(mut self, forward_travel: bool) -> Self {
|
||||
self.debug.enforce_forward_travel = forward_travel;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn get_nym_api_endpoints(&self) -> Vec<Url> {
|
||||
self.mixnode.nym_api_urls.clone()
|
||||
}
|
||||
@@ -248,9 +231,6 @@ pub struct MixNode {
|
||||
|
||||
/// Addresses to nym APIs from which the node gets the view of the network.
|
||||
pub nym_api_urls: Vec<Url>,
|
||||
|
||||
/// Addresses to nyxd validators via which the node can communicate with the chain directly.
|
||||
pub nyxd_urls: Vec<Url>,
|
||||
}
|
||||
|
||||
impl MixNode {
|
||||
@@ -262,7 +242,6 @@ impl MixNode {
|
||||
mix_port: DEFAULT_MIX_LISTENING_PORT,
|
||||
verloc_port: DEFAULT_VERLOC_LISTENING_PORT,
|
||||
nym_api_urls: vec![Url::from_str(mainnet::NYM_API).expect("Invalid default API URL")],
|
||||
nyxd_urls: vec![Url::from_str(mainnet::NYXD_URL).expect("Invalid default nyxd URL")],
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -340,10 +319,6 @@ pub struct Debug {
|
||||
/// Maximum number of packets that can be stored waiting to get sent to a particular connection.
|
||||
pub maximum_connection_buffer_size: usize,
|
||||
|
||||
/// Specifies whether this node should accepts and send out packets that would only go to nodes
|
||||
/// on the next mix layer.
|
||||
pub enforce_forward_travel: bool,
|
||||
|
||||
/// Specifies whether the mixnode should be using the legacy framing for the sphinx packets.
|
||||
// it's set to true by default. The reason for that decision is to preserve compatibility with the
|
||||
// existing nodes whilst everyone else is upgrading and getting the code for handling the new field.
|
||||
@@ -360,9 +335,6 @@ impl Default for Debug {
|
||||
packet_forwarding_maximum_backoff: DEFAULT_PACKET_FORWARDING_MAXIMUM_BACKOFF,
|
||||
initial_connection_timeout: DEFAULT_INITIAL_CONNECTION_TIMEOUT,
|
||||
maximum_connection_buffer_size: DEFAULT_MAXIMUM_CONNECTION_BUFFER_SIZE,
|
||||
|
||||
// let's keep it disabled for now to not surprise operators/users
|
||||
enforce_forward_travel: false,
|
||||
use_legacy_framed_packet_version: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,8 +75,6 @@ impl ConfigV1_1_32 {
|
||||
|
||||
impl From<ConfigV1_1_32> for Config {
|
||||
fn from(value: ConfigV1_1_32) -> Self {
|
||||
let network = nym_config::defaults::NymNetworkDetails::new_from_env();
|
||||
|
||||
Config {
|
||||
// \/ ADDED
|
||||
save_path: None,
|
||||
@@ -106,18 +104,6 @@ impl From<ConfigV1_1_32> for Config {
|
||||
mix_port: value.mixnode.mix_port,
|
||||
verloc_port: value.mixnode.verloc_port,
|
||||
nym_api_urls: value.mixnode.nym_api_urls,
|
||||
|
||||
// \/ ADDED
|
||||
nyxd_urls: network
|
||||
.endpoints
|
||||
.into_iter()
|
||||
.map(|e| {
|
||||
e.nyxd_url
|
||||
.parse()
|
||||
.expect("malformed nyxd url in environment")
|
||||
})
|
||||
.collect(),
|
||||
// /\ ADDED
|
||||
},
|
||||
storage_paths: value.storage_paths,
|
||||
verloc: value.verloc.into(),
|
||||
@@ -257,7 +243,6 @@ impl From<DebugV1_1_32> for Debug {
|
||||
packet_forwarding_maximum_backoff: value.packet_forwarding_maximum_backoff,
|
||||
initial_connection_timeout: value.initial_connection_timeout,
|
||||
maximum_connection_buffer_size: value.maximum_connection_buffer_size,
|
||||
enforce_forward_travel: false,
|
||||
use_legacy_framed_packet_version: value.use_legacy_framed_packet_version,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,13 +49,6 @@ nym_api_urls = [
|
||||
{{/each}}
|
||||
]
|
||||
|
||||
# Addresses to nyxd validators via which the node can communicate with the chain directly.
|
||||
nyxd_urls = [
|
||||
{{#each mixnode.nyxd_urls }}
|
||||
'{{this}}',
|
||||
{{/each}}
|
||||
]
|
||||
|
||||
[http]
|
||||
# Socket address this node will use for binding its http API.
|
||||
# default: `0.0.0.0:8000`
|
||||
@@ -87,10 +80,4 @@ node_description = '{{ storage_paths.node_description }}'
|
||||
|
||||
# TODO
|
||||
|
||||
[debug]
|
||||
|
||||
# Specifies whether this node should accepts and send out packets that would only go to nodes
|
||||
# on the next mix layer.
|
||||
enforce_forward_travel = {{ debug.enforce_forward_travel }}
|
||||
|
||||
"#;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use nym_mixnode_common::forward_travel::error::ForwardTravelError;
|
||||
use std::io;
|
||||
use std::path::PathBuf;
|
||||
use thiserror::Error;
|
||||
@@ -45,24 +44,7 @@ pub enum MixnodeError {
|
||||
source: io::Error,
|
||||
},
|
||||
|
||||
#[error("experienced an error during shutdown: {message}")]
|
||||
ShutdownFailure { message: String },
|
||||
|
||||
#[error("failure in enforcing forward travel of mix packets: {source}")]
|
||||
ForwardTravel {
|
||||
#[from]
|
||||
source: ForwardTravelError,
|
||||
},
|
||||
|
||||
// TODO: in the future this should work the other way, i.e. NymNode depending on Gateway errors
|
||||
#[error(transparent)]
|
||||
NymNodeError(#[from] nym_node::error::NymNodeError),
|
||||
}
|
||||
|
||||
impl MixnodeError {
|
||||
pub(crate) fn shutdown_failure(err: Box<dyn std::error::Error + Send + Sync>) -> Self {
|
||||
MixnodeError::ShutdownFailure {
|
||||
message: err.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ use crate::node::listener::connection_handler::packet_processing::{
|
||||
use crate::node::packet_delayforwarder::PacketDelayForwardSender;
|
||||
use crate::node::TaskClient;
|
||||
use futures::StreamExt;
|
||||
use log::{debug, error, info, warn};
|
||||
use nym_mixnode_common::forward_travel::AllowedEgress;
|
||||
use log::debug;
|
||||
use log::{error, info, warn};
|
||||
use nym_mixnode_common::measure;
|
||||
use nym_sphinx::forwarding::packet::MixPacket;
|
||||
use nym_sphinx::framing::codec::NymCodec;
|
||||
@@ -26,37 +26,22 @@ pub(crate) mod packet_processing;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct ConnectionHandler {
|
||||
allowed_egress: AllowedEgress,
|
||||
packet_processor: PacketProcessor,
|
||||
delay_forwarding_channel: PacketDelayForwardSender,
|
||||
}
|
||||
|
||||
impl ConnectionHandler {
|
||||
pub(crate) fn new(
|
||||
allowed_egress: AllowedEgress,
|
||||
packet_processor: PacketProcessor,
|
||||
delay_forwarding_channel: PacketDelayForwardSender,
|
||||
) -> Self {
|
||||
ConnectionHandler {
|
||||
allowed_egress,
|
||||
packet_processor,
|
||||
delay_forwarding_channel,
|
||||
}
|
||||
}
|
||||
|
||||
fn delay_and_forward_packet(&self, mix_packet: MixPacket, delay: Option<SphinxDelay>) {
|
||||
let next_hop: SocketAddr = mix_packet.next_hop().into();
|
||||
|
||||
// TODO: another option is to move this filter
|
||||
// (which is used by EVERY `ConnectionHandler`, so potentially hundreds of times)
|
||||
// to the mixnet client where we could be filtering at the time of attempting to open new outbound connections
|
||||
// However, in that case we'd have gone through the troubles of possibly unnecessarily delaying the packet
|
||||
if !self.allowed_egress.is_allowed(next_hop.ip()) {
|
||||
// TODO: perhaps this should get lowered in severity?
|
||||
warn!("received an packet that was meant to get forwarded to {next_hop}, but this address does not belong to any node on the next layer - dropping the packet");
|
||||
return;
|
||||
}
|
||||
|
||||
// determine instant at which packet should get forwarded. this way we minimise effect of
|
||||
// being stuck in the queue [of the channel] to get inserted into the delay queue
|
||||
let forward_instant = delay.map(|delay| Instant::now() + delay.to_duration());
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
use crate::node::listener::connection_handler::ConnectionHandler;
|
||||
use log::{error, info, warn};
|
||||
use nym_mixnode_common::forward_travel::AllowedIngress;
|
||||
use std::net::SocketAddr;
|
||||
use std::process;
|
||||
use tokio::net::TcpListener;
|
||||
@@ -15,21 +14,12 @@ pub(crate) mod connection_handler;
|
||||
|
||||
pub(crate) struct Listener {
|
||||
address: SocketAddr,
|
||||
allowed_ingress: AllowedIngress,
|
||||
shutdown: TaskClient,
|
||||
}
|
||||
|
||||
impl Listener {
|
||||
pub(crate) fn new(
|
||||
address: SocketAddr,
|
||||
allowed_ingress: AllowedIngress,
|
||||
shutdown: TaskClient,
|
||||
) -> Self {
|
||||
Listener {
|
||||
address,
|
||||
allowed_ingress,
|
||||
shutdown,
|
||||
}
|
||||
pub(crate) fn new(address: SocketAddr, shutdown: TaskClient) -> Self {
|
||||
Listener { address, shutdown }
|
||||
}
|
||||
|
||||
async fn run(&mut self, connection_handler: ConnectionHandler) {
|
||||
@@ -51,12 +41,6 @@ impl Listener {
|
||||
connection = listener.accept() => {
|
||||
match connection {
|
||||
Ok((socket, remote_addr)) => {
|
||||
if !self.allowed_ingress.is_allowed(remote_addr.ip()) {
|
||||
// TODO: perhaps this should get lowered in severity?
|
||||
warn!("received an incoming connection from {remote_addr}, but this address does not belong to any node on the previous layer - dropping the connection");
|
||||
continue
|
||||
}
|
||||
|
||||
let handler = connection_handler.clone();
|
||||
tokio::spawn(handler.handle_connection(socket, remote_addr, self.shutdown.clone()));
|
||||
}
|
||||
|
||||
@@ -15,9 +15,7 @@ use crate::node::packet_delayforwarder::{DelayForwarder, PacketDelayForwardSende
|
||||
use log::{error, info, warn};
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
use nym_bin_common::version_checker::parse_version;
|
||||
use nym_config::defaults::NymNetworkDetails;
|
||||
use nym_crypto::asymmetric::{encryption, identity};
|
||||
use nym_mixnode_common::forward_travel::{AllowedAddressesProvider, AllowedEgress, AllowedIngress};
|
||||
use nym_mixnode_common::verloc::{self, AtomicVerlocResult, VerlocMeasurer};
|
||||
use nym_task::{TaskClient, TaskManager};
|
||||
use rand::seq::SliceRandom;
|
||||
@@ -103,8 +101,6 @@ impl MixNode {
|
||||
&self,
|
||||
node_stats_update_sender: node_statistics::UpdateSender,
|
||||
delay_forwarding_channel: PacketDelayForwardSender,
|
||||
ingress: AllowedIngress,
|
||||
egress: AllowedEgress,
|
||||
shutdown: TaskClient,
|
||||
) {
|
||||
info!("Starting socket listener...");
|
||||
@@ -112,37 +108,14 @@ impl MixNode {
|
||||
let packet_processor =
|
||||
PacketProcessor::new(self.sphinx_keypair.private_key(), node_stats_update_sender);
|
||||
|
||||
let connection_handler =
|
||||
ConnectionHandler::new(egress, packet_processor, delay_forwarding_channel);
|
||||
let connection_handler = ConnectionHandler::new(packet_processor, delay_forwarding_channel);
|
||||
|
||||
let listening_address = SocketAddr::new(
|
||||
self.config.mixnode.listening_address,
|
||||
self.config.mixnode.mix_port,
|
||||
);
|
||||
|
||||
Listener::new(listening_address, ingress, shutdown).start(connection_handler);
|
||||
}
|
||||
|
||||
async fn start_allowed_addresses_provider(
|
||||
&self,
|
||||
task_client: TaskClient,
|
||||
) -> Result<(AllowedIngress, AllowedEgress), MixnodeError> {
|
||||
let identity = self.identity_keypair.public_key().to_base58_string();
|
||||
let nyxd_endpoints = self.config.mixnode.nyxd_urls.clone();
|
||||
|
||||
let network = NymNetworkDetails::new_from_env();
|
||||
let mut provider = AllowedAddressesProvider::new(
|
||||
identity,
|
||||
nyxd_endpoints,
|
||||
!self.config.debug.enforce_forward_travel,
|
||||
Some(network),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let filters = (provider.ingress(), provider.egress());
|
||||
|
||||
tokio::spawn(async move { provider.run(task_client).await });
|
||||
Ok(filters)
|
||||
Listener::new(listening_address, shutdown).start(connection_handler);
|
||||
}
|
||||
|
||||
fn start_packet_delay_forwarder(
|
||||
@@ -242,16 +215,12 @@ impl MixNode {
|
||||
})
|
||||
}
|
||||
|
||||
async fn wait_for_interrupt(
|
||||
&self,
|
||||
shutdown: TaskManager,
|
||||
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||
let res = shutdown.catch_interrupt().await;
|
||||
log::info!("Stopping nym gateway");
|
||||
res
|
||||
async fn wait_for_interrupt(&self, shutdown: TaskManager) {
|
||||
let _res = shutdown.catch_interrupt().await;
|
||||
log::info!("Stopping nym mixnode");
|
||||
}
|
||||
|
||||
pub(crate) async fn run(&mut self) -> Result<(), MixnodeError> {
|
||||
pub async fn run(&mut self) -> Result<(), MixnodeError> {
|
||||
info!("Starting nym mixnode");
|
||||
|
||||
if self.check_if_bonded().await {
|
||||
@@ -260,12 +229,6 @@ impl MixNode {
|
||||
|
||||
let shutdown = TaskManager::default();
|
||||
|
||||
let (ingress, egress) = self
|
||||
.start_allowed_addresses_provider(
|
||||
shutdown.subscribe().named("AllowedAddressesProvider"),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let (node_stats_pointer, node_stats_update_sender) = self
|
||||
.start_node_stats_controller(shutdown.subscribe().named("node_statistics::Controller"));
|
||||
let delay_forwarding_channel = self.start_packet_delay_forwarder(
|
||||
@@ -275,8 +238,6 @@ impl MixNode {
|
||||
self.start_socket_listener(
|
||||
node_stats_update_sender,
|
||||
delay_forwarding_channel,
|
||||
ingress,
|
||||
egress,
|
||||
shutdown.subscribe().named("Listener"),
|
||||
);
|
||||
let atomic_verloc_results =
|
||||
@@ -292,9 +253,7 @@ impl MixNode {
|
||||
)?;
|
||||
|
||||
info!("Finished nym mixnode startup procedure - it should now be able to receive mix traffic!");
|
||||
|
||||
self.wait_for_interrupt(shutdown)
|
||||
.await
|
||||
.map_err(MixnodeError::shutdown_failure)
|
||||
self.wait_for_interrupt(shutdown).await;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,14 +37,14 @@ serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
tap = "1.0"
|
||||
thiserror = { workspace = true }
|
||||
time = { workspace = true, features = ["serde-human-readable", "parsing"] }
|
||||
tokio = { workspace = true, features = [
|
||||
time = { version = "0.3.14", features = ["serde-human-readable", "parsing"] }
|
||||
tokio = { version = "1.24.1", features = [
|
||||
"rt-multi-thread",
|
||||
"macros",
|
||||
"signal",
|
||||
"time",
|
||||
] }
|
||||
tokio-stream = { workspace = true }
|
||||
tokio-stream = "0.1.11"
|
||||
url = { workspace = true }
|
||||
|
||||
ts-rs = { workspace = true, optional = true}
|
||||
|
||||
@@ -1578,11 +1578,10 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.3.9"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3"
|
||||
checksum = "7684a49fb1af197853ef7b2ee694bc1f5b4179556f1e5710e1760c5db6f5e929"
|
||||
dependencies = [
|
||||
"powerfmt",
|
||||
"serde",
|
||||
]
|
||||
|
||||
@@ -5292,12 +5291,6 @@ dependencies = [
|
||||
"universal-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "powerfmt"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.17"
|
||||
@@ -6221,9 +6214,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.190"
|
||||
version = "1.0.183"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7"
|
||||
checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
@@ -6248,9 +6241,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.190"
|
||||
version = "1.0.183"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3"
|
||||
checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -7401,16 +7394,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.30"
|
||||
version = "0.3.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5"
|
||||
checksum = "b0fdd63d58b18d663fbdf70e049f00a22c8e42be082203be7f26589213cd75ea"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"itoa 1.0.9",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"num_threads",
|
||||
"powerfmt",
|
||||
"serde",
|
||||
"time-core",
|
||||
"time-macros",
|
||||
@@ -7418,15 +7410,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "time-core"
|
||||
version = "0.1.2"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
|
||||
checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.15"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20"
|
||||
checksum = "eb71511c991639bb078fd5bf97757e03914361c48100d52878b8e52b46fb92cd"
|
||||
dependencies = [
|
||||
"time-core",
|
||||
]
|
||||
@@ -7448,9 +7440,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.33.0"
|
||||
version = "1.31.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653"
|
||||
checksum = "40de3a2ba249dcb097e01be5e67a5ff53cf250397715a071a81543e8a832a920"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
@@ -7557,9 +7549,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.7.9"
|
||||
version = "0.7.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d"
|
||||
checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-core",
|
||||
|
||||
@@ -51,6 +51,6 @@
|
||||
"prettier": "^3.0.3",
|
||||
"tailwindcss": "^3.3.3",
|
||||
"typescript": "^5.0.2",
|
||||
"vite": "^5.0.5"
|
||||
"vite": "^5.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#0052b4" d="M256 0h256v512H0V256Z"/><path fill="#eee" d="M0 0v32l32 32L0 96v160h32l32-32 32 32h32v-83l83 83h45l-8-16 8-15v-14l-83-83h83V96l-32-32 32-32V0H96L64 32 32 0Z"/><path fill="#d80027" d="M32 0v32H0v64h32v160h64V96h160V32H96V0Zm96 128 128 128v-31l-97-97z"/><path fill="#6da544" d="m320 144 48-80 48 80z"/><circle cx="368" cy="144" r="48" fill="#acabb1"/><path fill="#338af3" d="M320 144v77c0 36 48 48 48 48s48-12 48-48v-77z"/><rect width="32" height="128" x="288" y="128" fill="#ff9811" rx="16" ry="16"/><rect width="32" height="128" x="416" y="128" fill="#ff9811" rx="16" ry="16"/><path fill="#6da544" d="m368 160-48 67c2 11 9 19 16 26l32-45 32 45c8-7 14-15 16-26z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 869 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#0052b4" d="M0 0h144.7l36 254.6-36 257.4H0z"/><path fill="#d80027" d="M367.3 0H512v512H367.3l-29.7-257.3z"/><path fill="#ffda44" d="M144.7 0h222.6v512H144.7z"/><path fill="#d80027" d="M256 354.5V256h66.8v47.3zm-66.8-165.3H256V256h-66.8z"/><path fill="#ff9811" d="M289.4 167a22.3 22.3 0 0 0-33.4-19.3 22.1 22.1 0 0 0-11.1-3c-12.3 0-22.3 10-22.3 22.3H167v111.3c0 41.4 32.9 65.4 58.7 77.8a22.1 22.1 0 0 0-3 11.2 22.3 22.3 0 0 0 33.3 19.3 22.1 22.1 0 0 0 11.1 3 22.3 22.3 0 0 0 19.2-33.5c25.8-12.4 58.7-36.4 58.7-77.8V167zm22.3 111.3c0 5.8 0 23.4-27.5 40.9a136.5 136.5 0 0 1-28.2 13.3c-7-2.4-17.8-6.7-28.2-13.3-27.5-17.5-27.5-35.1-27.5-41v-77.9h111.4z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 844 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#a2001d" d="M0 0h167l52.3 252L167 512H0z"/><path fill="#eee" d="m167 167 170.8-44.6L512 167v178l-173.2 36.9L167 345z"/><path fill="#6da544" d="M167 0h345v167H167z"/><path fill="#333" d="M167 345h345v167H167z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 404 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#d80027" d="M144.7 0h222.6l37 257.7-37 254.3H144.7l-42.4-255.2z"/><path fill="#496e2d" d="M367.3 0H512v512H367.3z"/><path fill="#333" d="M0 0h144.7v512H0z"/><g fill="#ffda44"><path d="M256 167a89 89 0 1 0 0 178 89 89 0 0 0 0-178zm0 144.7a55.7 55.7 0 1 1 0-111.4 55.7 55.7 0 0 1 0 111.4z"/><path d="M256 222.6c-12.3 0-22.3 10-22.3 22.3v33.4h44.6v-33.4c0-12.3-10-22.3-22.3-22.3z"/></g></g></svg>
|
||||
|
Before Width: | Height: | Size: 577 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#333" d="M0 .4h512l-34 229H36z"/><path fill="#ffda44" d="m367.3 205.3-109.7 19.4-112.9-19.4 45.5-21.3-24.2-44 49.3 9.4 6.3-49.9 34.4 36.7 34.4-36.6 6.3 50L346 140l-24.2 44z"/><path fill="#0052b4" d="M25.6 205.3h466.8L257 439.5z"/><path fill="#eee" d="M34 307.4h446L256 511.6z"/><path fill="#a2001d" d="m0 511.6 256 .4L0 .4zm256 .4 256-.4V0z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 537 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#0052b4" d="M256 0h256v512H0V256Z"/><path fill="#eee" d="M0 0v32l32 32L0 96v160h32l32-32 32 32h32v-83l83 83h45l-8-16 8-15v-14l-83-83h83V96l-32-32 32-32V0H96L64 32 32 0Z"/><path fill="#d80027" d="M32 0v32H0v64h32v160h64V96h160V32H96V0Zm96 128 128 128v-31l-97-97z"/><path fill="#496e2d" d="M445.2 256.1zm-155.8 0z"/><path fill="#eee" d="M433 293.6a62.4 62.4 0 0 0 12.2-37.5V144.8a55.4 55.4 0 0 1-33.4 11.1 55.6 55.6 0 0 1-44.5-22.2 55.6 55.6 0 0 1-44.5 22.2 55.4 55.4 0 0 1-33.4-11.1v111.3c0 15 5 27.3 12.3 37.5h131.2z"/><path fill="#ff9811" d="M409.8 235.5a91 91 0 0 0 6.3-27.6c0-10.1-13.2-18.3-13.2-18.3s-13.2 8.2-13.2 18.3a91 91 0 0 0 6.3 27.6l-7.6 17.1a38.3 38.3 0 0 0 29 0zm-51.5-55.6a91 91 0 0 0-27 8.3c-8.8 5-9.3 20.5-9.3 20.5s13.7 7.4 22.4 2.3c5.5-3.1 15-11.8 20.8-19.2l18.6-2a38.4 38.4 0 0 0-4.7-14 38.4 38.4 0 0 0-9.7-11.1zm-22.4 72.2a91 91 0 0 0 20.7 19.3c8.8 5 22.5-2.3 22.5-2.3s-.6-15.5-9.3-20.5a91 91 0 0 0-27-8.4l-11.1-15.1a38.4 38.4 0 0 0-9.7 11 38.4 38.4 0 0 0-4.8 14z"/><path fill="#338af3" d="M299 289.5c20.7 33.3 68.3 44.5 68.3 44.5s47.6-11.2 68.4-44.5H298.9Z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 1.2 KiB |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#d80027" d="M0 0h512v512H0z"/><path fill="#333" d="M400.7 190H308a33.3 33.3 0 0 0-24.2-56.4 33.3 33.3 0 0 0-27.8 14.9 33.4 33.4 0 1 0-52 41.5h-92.7a45.8 45.8 0 0 0 46 44.5h-1.5c0 24.6 20 44.6 44.5 44.6 0 8 2.1 15.4 5.8 21.8l-37 37 28.4 28.3 40.2-40.2a30.5 30.5 0 0 0 4.9 1.4l-24.3 54.8L256 423l37.7-40.8-24.3-54.8a30.4 30.4 0 0 0 4.9-1.4l40.2 40.2 28.3-28.3-37-37a44.2 44.2 0 0 0 5.9-21.8c24.5 0 44.5-20 44.5-44.6h-1.5c24.6 0 46-19.9 46-44.5z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 639 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#0052b4" d="m0 166.9 253-26.7L512 167v178l-261.1 26L0 344.8z"/><path fill="#d80027" d="M0 0h512v166.9H0z"/><path fill="#ff9811" d="M0 344.9h512V512H0z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 347 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#eee" d="M0 0h171l85 32 85-32h171v171l-32 85 32 85v171H341l-85-32-85 32H0V341l32-85-32-85Z"/><path fill="#d80027" d="M171 0h170v512H171z"/><path fill="#0052b4" d="M512 171v170H0V171z"/><path fill="#eee" d="m236 247 52-37h-64l52 37-20-61zm-45 79 52-37h-64l52 37-20-61zm90 0 52-37h-64l52 37-20-61zm74-47 52-37h-64l52 37-20-61zm-238 0 52-37h-64l52 37-20-61z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 551 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#d80027" d="M0 0h512v256l-253 36.6L0 256z"/><path fill="#333" d="M0 256h512v256H0z"/><g fill="#ffda44"><path d="m220.9 203.6 21.7 15.8-8.3 25.5L256 229l21.7 15.7-8.3-25.5 21.7-15.7h-26.8L256 178l-8.3 25.5z"/><path d="M320 145.1a127.2 127.2 0 0 0-64-17v33.3a94 94 0 0 1 47.3 12.7 94.7 94.7 0 0 1-94.6 163.8 94 94 0 0 1-31.6-29.8l-27.9 18.4a128.1 128.1 0 0 0 217.7-6.5A128.1 128.1 0 0 0 320 145.1z"/><path d="M182.2 233.7a33.4 33.4 0 0 0 13.3 45.4l108.4 59.2c-7.4 13.5-3.4 30 10 37.3l29.3 16a27.8 27.8 0 0 0 37.8-11l16-29.3z"/></g></g></svg>
|
||||
|
Before Width: | Height: | Size: 723 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#338af3" d="M0 0h512v512H0z"/><path fill="#eee" d="m135 343-41-70 17-38-40-51-9-37 74 51 45-11 19-67 50-29 75 11 87 45 4 74 28 10v76l-53 94-64 20-59-14 15-25-7-26-8 7z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 364 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#338af3" d="M0 0h512v144.7L488 256l24 111.3V512H0V367.3L26 256 0 144.7z"/><path fill="#eee" d="M0 144.7h512v222.6H0z"/><path fill="#ffda44" d="m332.4 256-31.2 14.7 16.7 30.3-34-6.5-4.2 34.3-23.7-25.2-23.6 25.2-4.3-34.3-34 6.5 16.6-30.3-31.2-14.7 31.3-14.7L194 211l34 6.5 4.3-34.3 23.6 25.2 23.6-25.2 4.4 34.3 34-6.5-16.7 30.3z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 523 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#eee" d="M512 20.4V490L23.8 255.8z"/><path fill="#a2001d" d="M445.2 246.5h-30.5c8-9.6 7.5-23.7-1.5-32.7a24.2 24.2 0 0 0 0-34.2l-.5.5a25 25 0 0 0 .5-34.8l-137 137a23.9 23.9 0 0 0 34 0l2.6-2.5 65.6-6v28.3h22.3v-30.2l33.4-3z"/><path fill="#ffda44" d="M278.3 311.7 256 300.5l22.3-11.1H423v22.3z"/><path fill="#0052b4" d="M0 0v512h512L28.7 256.2 512 0z"/><path fill="#d80027" d="M512 0 0 256l512 256v-22L43.8 256 512 20.4z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 614 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#d80027" d="M0 0h512v167l-23.2 89.7L512 345v167H0V345l29.4-89L0 167z"/><path fill="#eee" d="M0 167h512v178H0z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 306 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#0052b4" d="M0 0h512v512H0z"/><path fill="#eee" d="m154 300 14 30 32-8-14 30 25 20-32 7 1 33-26-21-26 21 1-33-33-7 26-20-14-30 32 8zm222-27h47l-38 27 15-44 14 44zm7-162 7 15 16-4-7 15 12 10-15 3v17l-13-11-13 11v-17l-15-3 12-10-7-15 16 4zm57 67 7 15 16-4-7 15 12 10-15 3v16l-13-10-13 11v-17l-15-3 12-10-7-15 16 4zm-122 22 7 15 16-4-7 15 12 10-15 3v16l-13-10-13 11v-17l-15-3 12-10-7-15 16 4zm65 156 7 15 16-4-7 15 12 10-15 3v17l-13-11-13 11v-17l-15-3 12-10-7-15 16 4zM0 0v32l32 32L0 96v160h32l32-32 32 32h32v-83l83 83h45l-8-16 8-15v-14l-83-83h83V96l-32-32 32-32V0H96L64 32 32 0Z"/><path fill="#d80027" d="M32 0v32H0v64h32v160h64V96h160V32H96V0Zm96 128 128 128v-31l-97-97z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 866 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#ffda44" d="m0 322.8 253.6-18.4L512 322.8v33.4l-258 15.3L0 356.2zm0 66.8 257.2-13.8L512 389.6V423l-253 16.9L0 423z"/><path fill="#338af3" d="M0 0h512v322.8H0zm0 356.2h512v33.4H0zM0 423h512v89H0z"/><path fill="#eee" d="m117.3 161.5-50-22.1 50-22 22-50.1 22.2 50 50 22-50 22.2-22.1 50z"/><path fill="#d80027" d="m139.4 94.9 13.6 30.9 31 13.6-31 13.6-13.6 31-13.6-31-31-13.6 31-13.6z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 577 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#0052b4" d="M0 0h100.2l68.3 40.7L233.7 0H512v189.2l-45.5 66 45.5 68.6V512H233.7l-65.8-39.2-67.7 39.2H0V322.8l45.6-67.5L0 189.2z"/><path fill="#ffda44" d="M100.2 0v189.2H0v33.4l23 34-23 32.8v33.4h100.2V512h33.4l33.9-22.6 32.8 22.6h33.4V323.8H512v-34.4l-24.2-32.2 24.2-34.6v-33.4H233.7V0h-33.4l-32.6 20-34.1-20z"/><path fill="#d80027" d="M133.6 0v222.6H0v66.8h133.6V512h66.7V289.4H512v-66.8H200.3V0h-66.7z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 600 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#d80027" d="m0 166.9 253-31.8 259 31.8v178l-257.5 37.4L0 345z"/><path fill="#338af3" d="M0 0h512v166.9H0z"/><path fill="#6da544" d="M0 344.9h512V512H0z"/><g fill="#eee"><path d="M261.6 328.2a72.3 72.3 0 1 1 34.4-136 89 89 0 1 0 0 127.3 72 72 0 0 1-34.4 8.7z"/><path d="m317.2 206 9.6 26.8 25.8-12.3-12.2 25.8 26.9 9.6-27 9.6 12.3 25.8-25.8-12.3-9.6 27-9.6-27-25.8 12.3 12.3-25.8-27-9.6 27-9.6-12.3-25.8 25.8 12.3z"/></g></g></svg>
|
||||
|
Before Width: | Height: | Size: 614 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#ffda44" d="M0 0h445.3l33.9 255-33.9 257-323.7-134.3L0 66.8z"/><path fill="#0052b4" d="M0 66.8V512h445.4z"/><path fill="#0052b4" d="M445.3 0H512v512h-66.7z"/><path fill="#eee" d="m354.6 456-8.3 25.6h-26.8l21.7 15.8-8.3 25.5 21.7-15.8 21.7 15.8-8.3-25.5 21.7-15.8h-26.8zm-55-55.4-8.3 25.5h-26.8l21.7 15.8-8.3 25.5 21.7-15.8 21.7 15.8-8.3-25.5 21.7-15.8h-26.8zM244.4 345l-8.3 25.5h-26.8l21.7 15.8-8.3 25.5 21.7-15.8 21.7 15.8-8.3-25.5 21.7-15.8h-26.8zm-55.1-55.7-8.3 25.5h-26.8l21.7 15.8-8.3 25.5 21.7-15.8L211 356l-8.3-25.5 21.7-15.8h-26.8zm-55.4-55.7-8.3 25.5H98.8l21.7 15.8-8.3 25.5 21.7-15.8 21.7 15.8-8.3-25.5L169 259h-26.8zM78.7 178l-8.3 25.5H43.6l21.7 15.8-8.3 25.5L78.7 229l21.7 15.8-8.3-25.5 21.7-15.8H87zm-55.2-55.7-8.3 25.5h-26.8l21.7 15.8L1.8 189l21.7-15.8L45.2 189l-8.3-25.5 21.7-15.8H31.8z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 998 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#0052b4" d="M0 0h144.8l112.9 36.7L367.4 0H512v512H367.4l-108.9-38.1L144.8 512H0z"/><path fill="#ffda44" d="M144.8 0h222.6v512H144.8z"/><path fill="#333" d="m334.1 155.8 14.8 7.5-14.9-7.5-15-7.4c-.8 1.8-20.3 41.4-23.5 102h-22.7v-94.6l-16.7-22.2-16.7 22.2v94.6h-22.7a278.3 278.3 0 0 0-23.6-102l-29.8 14.9c.2.4 20.5 41.7 20.5 103.8v16.7h55.6v94.6h33.4v-94.6h55.6v-16.7c0-32 5.6-58.6 10.3-75.1 5-18 10.2-28.6 10.3-28.7l-15-7.5z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 620 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#496e2d" d="M0 0h512v512H0z"/><circle cx="200.3" cy="256" r="111.3" fill="#d80027"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 278 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#333" d="M0 0h167l38.2 252.6L167 512H0z"/><path fill="#d80027" d="M345 0h167v512H345l-36.7-256z"/><path fill="#ffda44" d="M167 0h178v512H167z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 338 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#d80027" d="M0 0h512v256l-255.2 48L0 256z"/><path fill="#6da544" d="M0 256h512v256H0z"/><path fill="#ffda44" d="m256 167 19.3 59.5H338l-50.6 36.8 19.3 59.5L256 286l-50.6 36.8 19.3-59.5-50.6-36.8h62.6z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 397 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#496e2d" d="m0 166.9 258-31.7 254 31.7v178l-251.4 41.3L0 344.9z"/><path fill="#eee" d="M0 0h512v166.9H0z"/><path fill="#d80027" d="M0 344.9h512V512H0z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 347 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#eee" d="M0 0h182.5l88.1 268.5-88 243.5H0z"/><path fill="#d80027" d="m182.5 0-82.3 42.7 82.3 42.7-82.3 42.6 82.3 42.7-82.3 42.7 82.3 42.6-82.3 42.7 82.3 42.7-82.3 42.6 82.3 42.7-82.3 42.7 82.3 42.6H512V0H182.5z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 407 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#eee" d="M0 0h47.2l207.5 30L464.8 0H512v47.2L477.4 256 512 464.8V512h-47.2l-209.1-35.8L47.2 512H0v-47.2l32.8-202.7L0 47.2z"/><path fill="#d80027" d="M47.2 0 256 208.8 464.8 0H47.2zM256 303.2 47.2 512h417.6L256 303.2z"/><path fill="#6da544" d="M0 47.2v417.6L208.8 256 0 47.2zm512 0L303.2 256 512 464.8V47.2z"/><circle cx="256" cy="256" r="111.3" fill="#eee"/><path fill="#d80027" d="m256 178 9.6 16.8H285l-9.6 16.7 9.6 16.7h-19.3l-9.6 16.7-9.6-16.7H227l9.6-16.7-9.6-16.7h19.3zm-49 78 9.6 16.7H236l-9.6 16.7 9.6 16.7h-19.3l-9.6 16.7-9.6-16.7H178l9.6-16.7-9.6-16.7h19.3zm98 0 9.6 16.7H334l-9.6 16.7 9.6 16.7h-19.3l-9.6 16.7-9.6-16.7H276l9.6-16.7-9.6-16.7h19.3z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 854 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#6da544" d="M0 0h189.2l54 257.6-54 254.4H0z"/><path fill="#ffda44" d="M189.2 0H512v256l-159 53.5L189.1 256z"/><path fill="#d80027" d="M189.2 256H512v256H189.2z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 356 B |