Compare commits

...

16 Commits

Author SHA1 Message Date
Bogdan-Ștefan Neacșu 28e330821e Try adding contract feature 2023-06-29 18:54:15 +03:00
Bogdan-Ștefan Neacșu f46ab0dc68 Merge remote-tracking branch 'origin' into feature/ephemera 2023-06-29 14:49:23 +03:00
Jon Häggblad 31568b544c Minor fixes to support harbourmaster beacon (#3618)
* wip

* wip
2023-06-29 12:38:03 +02:00
Bogdan-Ștefan Neacşu 7e0d016375 Umock contract membership of ephemera (#3574)
* Pass nyxd client to members provider

* Basic ephemera contract

* Add register peer tx

* Add query all peers

* Nyxd ephemera client

* Add registration of ephemera peer

* Replace epoch http api with actual contract

* Merge ephemera config into nym-api config

* Load cluster from contract
2023-06-28 19:00:52 +03:00
Jon Häggblad ed76000dd0 Remove unmaintained upgrade commands (#3599)
* Remove unmaintained upgrade commands

* Remove unused with_custom_version functions
2023-06-28 15:59:27 +02:00
Pierre Dommerc 0dfe1460e4 fix lint (#3612) 2023-06-28 13:43:43 +02:00
Dave Hrycyszyn e06087ad3f Made a few additions to upgrade notes 2023-06-28 12:24:21 +02:00
Pierre Dommerc 0a6a015987 feat(nc): monitoring update (#3609) 2023-06-28 12:20:29 +02:00
Bogdan-Ștefan Neacșu 13c6296c3f Merge remote-tracking branch 'origin/develop' into feature/ephemera 2023-06-27 14:56:59 +03:00
Bogdan-Ștefan Neacșu 2f29e33f1e Merge remote-tracking branch 'origin/develop' into feature/ephemera 2023-06-22 13:36:37 +03:00
Bogdan-Ștefan Neacșu 8325001e8c Merge remote-tracking branch 'origin/develop' into feature/ephemera 2023-06-16 12:25:55 +03:00
Bogdan-Ștefan Neacşu 666c11cc28 Start ephemera components in nym-api (#3475)
* Start ephemera components in nym-api

* Pass nyxd client and use common metric structures

* Swap url endpoint with contract for sending rewarding messages

* Fix build after rebase

* Perform ephemera rewards computation before normal nym-api ones

* Remove contract mock from ephemera

* Take raw rewards from network monitor

* Remove ephemera old reward version

* Use nym shutdown procedure in ephemera

* Temporary fix for some warnings
2023-06-16 11:22:00 +03:00
Bogdan-Ștefan Neacșu 04f910fbf3 Merge remote-tracking branch 'origin/develop' into feature/ephemera 2023-06-15 10:46:15 +03:00
Bogdan-Ștefan Neacșu 315652b26a Merge remote-tracking branch 'origin/develop' into feature/ephemera 2023-06-13 12:32:05 +03:00
Bogdan-Ștefan Neacșu 56a5d847c4 Merge remote-tracking branch 'origin/develop' into feature/ephemera 2023-05-30 14:09:04 +03:00
Bogdan-Ștefan Neacşu 29f95febe9 Feature/ephemera compile (#3437)
* Include ephemera node code in repo

* Upgrade deps

* Bump minor version of cosmwasm-std

* Include ephemera in nym-api dep and downgrade rusqlite

* Fix clippy and ephemera docs code

* More clippy on ephemera

---------

Co-authored-by: Andrus Salumets <andrus@nymtech.net>
2023-05-25 11:24:49 +03:00
223 changed files with 19262 additions and 1938 deletions
Generated
+2971 -116
View File
File diff suppressed because it is too large Load Diff
+14 -11
View File
@@ -34,6 +34,7 @@ members = [
"common/cosmwasm-smart-contracts/coconut-bandwidth-contract",
"common/cosmwasm-smart-contracts/coconut-dkg",
"common/cosmwasm-smart-contracts/contracts-common",
"common/cosmwasm-smart-contracts/ephemera",
"common/cosmwasm-smart-contracts/group-contract",
"common/cosmwasm-smart-contracts/mixnet-contract",
"common/cosmwasm-smart-contracts/multisig-contract",
@@ -117,19 +118,21 @@ anyhow = "1.0.71"
async-trait = "0.1.64"
bip39 = { version = "2.0.0", features = ["zeroize"] }
cfg-if = "1.0.0"
cosmwasm-derive = "=1.0.0"
cosmwasm-schema = "=1.0.0"
cosmwasm-std = "=1.0.0"
cosmwasm-storage = "=1.0.0"
cw-controllers = "=0.13.4"
cw-storage-plus = "=0.13.4"
cw-utils = "=0.13.4"
cw2 = { version = "=0.13.4" }
cw3 = { version = "=0.13.4" }
cw3-fixed-multisig = { version = "=0.13.4" }
cw4 = { version = "=0.13.4" }
cosmwasm-derive = "=1.2.5"
cosmwasm-schema = "=1.2.5"
cosmwasm-std = "=1.2.5"
cosmwasm-storage = "=1.2.5"
cosmrs = "=0.8.0"
cw-utils = "=1.0.1"
cw-storage-plus = "=1.0.1"
cw2 = { version = "=1.0.1" }
cw3 = { version = "=1.0.1" }
cw3-fixed-multisig = { version = "=1.0.1" }
cw4 = { version = "=1.0.1" }
cw-controllers = { version = "=1.0.1" }
dotenvy = "0.15.6"
generic-array = "0.14.7"
k256 = "0.11"
getrandom = "0.2.10"
lazy_static = "1.4.0"
log = "0.4"
+1 -4
View File
@@ -24,7 +24,6 @@ use std::net::IpAddr;
pub(crate) mod init;
pub(crate) mod run;
pub(crate) mod upgrade;
lazy_static! {
pub static ref PRETTY_BUILD_INFORMATION: String =
@@ -51,10 +50,9 @@ pub(crate) struct Cli {
pub(crate) enum Commands {
/// Initialise a Nym client. Do this first!
Init(init::Init),
/// Run the Nym client with provided configuration client optionally overriding set parameters
Run(run::Run),
/// Try to upgrade the client
Upgrade(upgrade::Upgrade),
/// Generate shell completions
Completions(ArgShell),
@@ -81,7 +79,6 @@ pub(crate) async fn execute(args: &Cli) -> Result<(), Box<dyn Error + Send + Syn
match &args.command {
Commands::Init(m) => init::execute(m).await?,
Commands::Run(m) => run::execute(m).await?,
Commands::Upgrade(m) => upgrade::execute(m),
Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name),
Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name),
}
-78
View File
@@ -1,78 +0,0 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::client::config::Config;
use crate::commands::try_load_current_config;
use clap::Args;
use nym_bin_common::version_checker::Version;
use std::process;
fn unimplemented_upgrade(current_version: &Version, config_version: &Version) -> ! {
eprintln!("Cannot perform upgrade from {config_version} to {current_version} as it hasn't been implemented yet");
process::exit(1)
}
#[derive(Args, Clone)]
pub(crate) struct Upgrade {
/// Id of the nym-client we want to upgrade
#[clap(long)]
id: String,
}
fn parse_config_version(config: &Config) -> Version {
let version = Version::parse(&config.base.client.version).unwrap_or_else(|err| {
eprintln!("failed to parse client version! - {err}");
process::exit(1)
});
if version.is_prerelease() || !version.build.is_empty() {
eprintln!(
"Trying to upgrade from a non-released version {version}. This is not supported!"
);
process::exit(1)
}
version
}
fn parse_package_version() -> Version {
let version = Version::parse(env!("CARGO_PKG_VERSION")).unwrap();
// technically this is not a correct way of checking it as a released version might contain valid build identifiers
// however, we are not using them ourselves at the moment and hence it should be fine.
// if we change our mind, we could easily tweak this code
if version.is_prerelease() || !version.build.is_empty() {
eprintln!("Trying to upgrade to a non-released version {version}. This is not supported!");
process::exit(1)
}
version
}
fn do_upgrade(config: Config, _args: &Upgrade, package_version: &Version) {
let config_version = parse_config_version(&config);
if &config_version == package_version {
println!("You're using the most recent version!");
return;
}
unimplemented_upgrade(package_version, &config_version)
}
pub(crate) fn execute(args: &Upgrade) {
let package_version = parse_package_version();
let id = &args.id;
let existing_config = try_load_current_config(id).unwrap_or_else(|err| {
eprintln!("failed to load existing config file! - {err}");
process::exit(1)
});
if existing_config.base.client.version.is_empty() {
eprintln!("the existing configuration file does not seem to contain version number.");
process::exit(1);
}
do_upgrade(existing_config, args, &package_version)
}
-5
View File
@@ -24,7 +24,6 @@ use std::error::Error;
pub mod init;
pub(crate) mod run;
pub(crate) mod upgrade;
lazy_static! {
pub static ref PRETTY_BUILD_INFORMATION: String =
@@ -55,9 +54,6 @@ pub(crate) enum Commands {
/// Run the Nym client with provided configuration client optionally overriding set parameters
Run(run::Run),
/// Try to upgrade the client
Upgrade(upgrade::Upgrade),
/// Generate shell completions
Completions(ArgShell),
@@ -83,7 +79,6 @@ pub(crate) async fn execute(args: &Cli) -> Result<(), Box<dyn Error + Send + Syn
match &args.command {
Commands::Init(m) => init::execute(m).await?,
Commands::Run(m) => run::execute(m).await?,
Commands::Upgrade(m) => upgrade::execute(m),
Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name),
Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name),
}
-78
View File
@@ -1,78 +0,0 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::commands::try_load_current_config;
use crate::config::Config;
use clap::Args;
use nym_bin_common::version_checker::Version;
use std::process;
fn unimplemented_upgrade(current_version: &Version, config_version: &Version) -> ! {
eprintln!("Cannot perform upgrade from {config_version} to {current_version} as it hasn't been implemented yet");
process::exit(1)
}
#[derive(Args, Clone)]
pub(crate) struct Upgrade {
/// Id of the nym-client we want to upgrade
#[clap(long)]
id: String,
}
fn parse_config_version(config: &Config) -> Version {
let version = Version::parse(&config.core.base.client.version).unwrap_or_else(|err| {
eprintln!("failed to parse client version! - {err}");
process::exit(1)
});
if version.is_prerelease() || !version.build.is_empty() {
eprintln!(
"Trying to upgrade from a non-released version {version}. This is not supported!"
);
process::exit(1)
}
version
}
fn parse_package_version() -> Version {
let version = Version::parse(env!("CARGO_PKG_VERSION")).unwrap();
// technically this is not a correct way of checking it as a released version might contain valid build identifiers
// however, we are not using them ourselves at the moment and hence it should be fine.
// if we change our mind, we could easily tweak this code
if version.is_prerelease() || !version.build.is_empty() {
eprintln!("Trying to upgrade to a non-released version {version}. This is not supported!");
process::exit(1)
}
version
}
fn do_upgrade(config: Config, _args: &Upgrade, package_version: &Version) {
let config_version = parse_config_version(&config);
if &config_version == package_version {
println!("You're using the most recent version!");
return;
}
unimplemented_upgrade(package_version, &config_version)
}
pub(crate) fn execute(args: &Upgrade) {
let package_version = parse_package_version();
let id = &args.id;
let existing_config = try_load_current_config(id).unwrap_or_else(|err| {
eprintln!("failed to load existing config file! - {err}");
process::exit(1)
});
if existing_config.core.base.client.version.is_empty() {
eprintln!("the existing configuration file does not seem to contain version number.");
process::exit(1);
}
do_upgrade(existing_config, args, &package_version)
}
+195 -85
View File
@@ -237,18 +237,18 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
[[package]]
name = "bip32"
version = "0.3.0"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "873faa4363bfc54c36a48321da034c92a0645a363eed34d948683ffc1706e37f"
checksum = "b30ed1d6f8437a487a266c8293aeb95b61a23261273e3e02912cdb8b68bf798b"
dependencies = [
"bs58",
"hmac 0.11.0",
"hmac 0.12.1",
"k256",
"once_cell",
"pbkdf2",
"rand_core 0.6.4",
"ripemd160",
"sha2 0.9.9",
"ripemd",
"sha2 0.10.6",
"subtle 2.4.1",
"zeroize",
]
@@ -332,7 +332,6 @@ version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
dependencies = [
"block-padding",
"generic-array 0.14.7",
]
@@ -345,12 +344,6 @@ dependencies = [
"generic-array 0.14.7",
]
[[package]]
name = "block-padding"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae"
[[package]]
name = "bls12_381"
version = "0.5.0"
@@ -577,9 +570,9 @@ dependencies = [
[[package]]
name = "const-oid"
version = "0.7.1"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3"
checksum = "520fbf3c07483f94e3e3ca9d0cfd913d7718ef2483d2cfd91c0d9e91474ab913"
[[package]]
name = "constant_time_eq"
@@ -605,8 +598,9 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
[[package]]
name = "cosmos-sdk-proto"
version = "0.12.3"
source = "git+https://github.com/neacsu/cosmos-rust?branch=neacsu/feegrant_support#f63ded63ec13e753ebe8bdafe9dc503df265d67d"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8bb61f3d2224c90ea78e1fa7444787761a549170c46b6b0ed09b93f9b7e4076a"
dependencies = [
"prost",
"prost-types",
@@ -615,8 +609,9 @@ dependencies = [
[[package]]
name = "cosmrs"
version = "0.7.1"
source = "git+https://github.com/neacsu/cosmos-rust?branch=neacsu/feegrant_support#f63ded63ec13e753ebe8bdafe9dc503df265d67d"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20d5890dac07a62337e5841adb8f2074a66a962a098a48df9460f64d483beaf4"
dependencies = [
"bip32",
"cosmos-sdk-proto",
@@ -637,11 +632,11 @@ dependencies = [
[[package]]
name = "cosmwasm-crypto"
version = "1.0.1"
version = "1.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "970d1d705862179b5d7a233ae36f02f21c4ec1b8075fe60c77fc5b43471331fa"
checksum = "75836a10cb9654c54e77ee56da94d592923092a10b369cdb0dbd56acefc16340"
dependencies = [
"digest 0.9.0",
"digest 0.10.6",
"ed25519-zebra",
"k256",
"rand_core 0.6.4",
@@ -650,26 +645,53 @@ dependencies = [
[[package]]
name = "cosmwasm-derive"
version = "1.0.0"
version = "1.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b36e527620a2a3e00e46b6e731ab6c9b68d11069c986f7d7be8eba79ef081a4"
checksum = "1c9f7f0e51bfc7295f7b2664fe8513c966428642aa765dad8a74acdab5e0c773"
dependencies = [
"syn 1.0.109",
]
[[package]]
name = "cosmwasm-std"
version = "1.0.0"
name = "cosmwasm-schema"
version = "1.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "875994993c2082a6fcd406937bf0fca21c349e4a624f3810253a14fa83a3a195"
checksum = "0f00b363610218eea83f24bbab09e1a7c3920b79f068334fdfcc62f6129ef9fc"
dependencies = [
"cosmwasm-schema-derive",
"schemars",
"serde",
"serde_json",
"thiserror",
]
[[package]]
name = "cosmwasm-schema-derive"
version = "1.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae38f909b2822d32b275c9e2db9728497aa33ffe67dd463bc67c6a3b7092785c"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "cosmwasm-std"
version = "1.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a49b85345e811c8e80ec55d0d091e4fcb4f00f97ab058f9be5f614c444a730cb"
dependencies = [
"base64 0.13.1",
"cosmwasm-crypto",
"cosmwasm-derive",
"derivative",
"forward_ref",
"hex",
"schemars",
"serde",
"serde-json-wasm",
"serde-json-wasm 0.5.1",
"sha2 0.10.6",
"thiserror",
"uint",
]
@@ -783,9 +805,9 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]]
name = "crypto-bigint"
version = "0.3.2"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21"
checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef"
dependencies = [
"generic-array 0.14.7",
"rand_core 0.6.4",
@@ -867,10 +889,11 @@ dependencies = [
[[package]]
name = "cw-controllers"
version = "0.13.4"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f0bc6019b4d3d81e11f5c384bcce7173e2210bd654d75c6c9668e12cca05dfa"
checksum = "91440ce8ec4f0642798bc8c8cb6b9b53c1926c6dadaf0eed267a5145cd529071"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw-storage-plus",
"cw-utils",
@@ -881,9 +904,9 @@ dependencies = [
[[package]]
name = "cw-storage-plus"
version = "0.13.4"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "648b1507290bbc03a8d88463d7cd9b04b1fa0155e5eef366c4fa052b9caaac7a"
checksum = "053a5083c258acd68386734f428a5a171b29f7d733151ae83090c6fcc9417ffa"
dependencies = [
"cosmwasm-std",
"schemars",
@@ -892,22 +915,26 @@ dependencies = [
[[package]]
name = "cw-utils"
version = "0.13.4"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dbaecb78c8e8abfd6b4258c7f4fbeb5c49a5e45ee4d910d3240ee8e1d714e1b"
checksum = "c80e93d1deccb8588db03945016a292c3c631e6325d349ebb35d2db6f4f946f7"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw2",
"schemars",
"semver 1.0.17",
"serde",
"thiserror",
]
[[package]]
name = "cw2"
version = "0.13.4"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04cf4639517490dd36b333bbd6c4fbd92e325fd0acf4683b41753bc5eb63bfc1"
checksum = "8fb70cee2cf0b4a8ff7253e6bc6647107905e8eb37208f87d54f67810faa62f8"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw-storage-plus",
"schemars",
@@ -915,11 +942,12 @@ dependencies = [
]
[[package]]
name = "cw3"
version = "0.13.4"
name = "cw20"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe19462a7f644ba60c19d3443cb90d00c50d9b6b3b0a3a7fca93df8261af979b"
checksum = "91666da6c7b40c8dd5ff94df655a28114efc10c79b70b4d06f13c31e37d60609"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw-utils",
"schemars",
@@ -927,11 +955,27 @@ dependencies = [
]
[[package]]
name = "cw4"
version = "0.13.4"
name = "cw3"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0acc3549d5ce11c6901b3a676f2e2628684722197054d97cd0101ea174ed5cbd"
checksum = "2fe0b587008aa221cd2a2579a21990a28c4347dc53ad43167c68ad765f5b6efa"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw-utils",
"cw20",
"schemars",
"serde",
"thiserror",
]
[[package]]
name = "cw4"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c236e0bae02ce97e89235a681dd0e07d099524b369f1ef908d704db3e6b049b"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw-storage-plus",
"schemars",
@@ -953,11 +997,23 @@ dependencies = [
[[package]]
name = "der"
version = "0.5.1"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c"
checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de"
dependencies = [
"const-oid",
"zeroize",
]
[[package]]
name = "derivative"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
@@ -1050,9 +1106,9 @@ checksum = "68b0cf012f1230e43cd00ebb729c6bb58707ecfa8ad08b52ef3a4ccd2697fc30"
[[package]]
name = "ecdsa"
version = "0.13.4"
version = "0.14.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0d69ae62e0ce582d56380743515fefaf1a8c70cec685d9677636d7e30ae9dc9"
checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c"
dependencies = [
"der",
"elliptic-curve",
@@ -1108,16 +1164,18 @@ checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
[[package]]
name = "elliptic-curve"
version = "0.11.12"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25b477563c2bfed38a3b7a60964c49e058b2510ad3f12ba3483fd8f62c2306d6"
checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3"
dependencies = [
"base16ct",
"crypto-bigint",
"der",
"ff 0.11.1",
"digest 0.10.6",
"ff 0.12.1",
"generic-array 0.14.7",
"group 0.11.0",
"group 0.12.1",
"pkcs8",
"rand_core 0.6.4",
"sec1",
"subtle 2.4.1",
@@ -1232,6 +1290,16 @@ dependencies = [
"subtle 2.4.1",
]
[[package]]
name = "ff"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160"
dependencies = [
"rand_core 0.6.4",
"subtle 2.4.1",
]
[[package]]
name = "flate2"
version = "1.0.26"
@@ -1524,6 +1592,17 @@ dependencies = [
"subtle 2.4.1",
]
[[package]]
name = "group"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7"
dependencies = [
"ff 0.12.1",
"rand_core 0.6.4",
"subtle 2.4.1",
]
[[package]]
name = "h2"
version = "0.3.19"
@@ -1978,15 +2057,14 @@ dependencies = [
[[package]]
name = "k256"
version = "0.10.4"
version = "0.11.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19c3a5e0a0b8450278feda242592512e09f61c72e018b8cd5c859482802daf2d"
checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b"
dependencies = [
"cfg-if 1.0.0",
"ecdsa",
"elliptic-curve",
"sec1",
"sha2 0.9.9",
"sha2 0.10.6",
"sha3",
]
@@ -2484,6 +2562,17 @@ dependencies = [
"zeroize",
]
[[package]]
name = "nym-ephemera-common"
version = "0.1.0"
dependencies = [
"cosmwasm-std",
"cw-utils",
"nym-contracts-common",
"schemars",
"serde",
]
[[package]]
name = "nym-gateway-client"
version = "0.1.0"
@@ -2540,6 +2629,8 @@ dependencies = [
name = "nym-group-contract-common"
version = "0.1.0"
dependencies = [
"cosmwasm-schema",
"cw-controllers",
"cw4",
"schemars",
"serde",
@@ -2556,7 +2647,7 @@ dependencies = [
"nym-contracts-common",
"schemars",
"serde",
"serde-json-wasm",
"serde-json-wasm 0.4.1",
"serde_repr",
"thiserror",
"time",
@@ -2566,7 +2657,9 @@ dependencies = [
name = "nym-multisig-contract-common"
version = "0.1.0"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw-storage-plus",
"cw-utils",
"cw3",
"cw4",
@@ -2879,6 +2972,7 @@ dependencies = [
"nym-coconut-interface",
"nym-config",
"nym-contracts-common",
"nym-ephemera-common",
"nym-group-contract-common",
"nym-mixnet-contract-common",
"nym-multisig-contract-common",
@@ -3081,11 +3175,11 @@ checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79"
[[package]]
name = "pbkdf2"
version = "0.9.0"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f05894bce6a1ba4be299d0c5f29563e08af2bc18bb7d48313113bed71e904739"
checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917"
dependencies = [
"crypto-mac 0.11.1",
"digest 0.10.6",
]
[[package]]
@@ -3210,13 +3304,12 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkcs8"
version = "0.8.0"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cabda3fb821068a9a4fab19a683eac3af12edf0f34b94a8be53c4972b8149d0"
checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba"
dependencies = [
"der",
"spki",
"zeroize",
]
[[package]]
@@ -3545,12 +3638,12 @@ dependencies = [
[[package]]
name = "rfc6979"
version = "0.1.0"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96ef608575f6392792f9ecf7890c00086591d29a83910939d430753f7c050525"
checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb"
dependencies = [
"crypto-bigint",
"hmac 0.11.0",
"hmac 0.12.1",
"zeroize",
]
@@ -3569,6 +3662,15 @@ dependencies = [
"winapi",
]
[[package]]
name = "ripemd"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f"
dependencies = [
"digest 0.10.6",
]
[[package]]
name = "ripemd160"
version = "0.9.1"
@@ -3738,10 +3840,11 @@ dependencies = [
[[package]]
name = "sec1"
version = "0.2.1"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08da66b8b0965a5555b6bd6639e68ccba85e1e2506f5fbb089e93f8a04e1a2d1"
checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928"
dependencies = [
"base16ct",
"der",
"generic-array 0.14.7",
"pkcs8",
@@ -3814,6 +3917,15 @@ dependencies = [
"serde",
]
[[package]]
name = "serde-json-wasm"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16a62a1fad1e1828b24acac8f2b468971dade7b8c3c2e672bcadefefb1f8c137"
dependencies = [
"serde",
]
[[package]]
name = "serde-wasm-bindgen"
version = "0.5.0"
@@ -3949,14 +4061,12 @@ dependencies = [
[[package]]
name = "sha3"
version = "0.9.1"
version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809"
checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60"
dependencies = [
"block-buffer 0.9.0",
"digest 0.9.0",
"digest 0.10.6",
"keccak",
"opaque-debug 0.3.0",
]
[[package]]
@@ -3970,11 +4080,11 @@ dependencies = [
[[package]]
name = "signature"
version = "1.4.0"
version = "1.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02658e48d89f2bec991f9a78e69cfa4c316f8d6a6c4ec12fae1aeb263d486788"
checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c"
dependencies = [
"digest 0.9.0",
"digest 0.10.6",
"rand_core 0.6.4",
]
@@ -4044,9 +4154,9 @@ dependencies = [
[[package]]
name = "spki"
version = "0.5.4"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27"
checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b"
dependencies = [
"base64ct",
"der",
@@ -4331,9 +4441,9 @@ dependencies = [
[[package]]
name = "tendermint"
version = "0.23.7"
version = "0.23.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ca881fa4dedd2b46334f13be7fbc8cc1549ba4be5a833fe4e73d1a1baaf7949"
checksum = "a199518e0366ba0aeb0d0e0a59dbd99ea0bdc14280f414ecc758c9228a454ad8"
dependencies = [
"async-trait",
"bytes",
@@ -4362,9 +4472,9 @@ dependencies = [
[[package]]
name = "tendermint-config"
version = "0.23.7"
version = "0.23.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6c56ee93f4e9b7e7daba86d171f44572e91b741084384d0ae00df7991873dfd"
checksum = "c6d8f6a64ae3b59ea3c73efad727271ee085b544b817d7f46901817ca6bb1773"
dependencies = [
"flex-error",
"serde",
@@ -4376,9 +4486,9 @@ dependencies = [
[[package]]
name = "tendermint-proto"
version = "0.23.7"
version = "0.23.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b71f925d74903f4abbdc4af0110635a307b3cb05b175fdff4a7247c14a4d0874"
checksum = "1b303d6387aaea38cea7ef924476d1f798573044e7b4f6ddd1166ac5184b2281"
dependencies = [
"bytes",
"flex-error",
@@ -4394,9 +4504,9 @@ dependencies = [
[[package]]
name = "tendermint-rpc"
version = "0.23.7"
version = "0.23.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a13e63f57ee05a1e927887191c76d1b139de9fa40c180b9f8727ee44377242a6"
checksum = "3036f0b65baa11e767dabd22a0663e842b595b0a1903f149b7b8b1e09b2b443d"
dependencies = [
"async-trait",
"bytes",
@@ -13,6 +13,7 @@ colored = "2.0"
nym-coconut-dkg-common = { path = "../../cosmwasm-smart-contracts/coconut-dkg" }
nym-contracts-common = { path = "../../cosmwasm-smart-contracts/contracts-common" }
nym-ephemera-common = { path = "../../cosmwasm-smart-contracts/ephemera" }
nym-mixnet-contract-common = { path = "../../cosmwasm-smart-contracts/mixnet-contract" }
nym-vesting-contract-common = { path = "../../cosmwasm-smart-contracts/vesting-contract" }
nym-coconut-bandwidth-contract-common = { path = "../../cosmwasm-smart-contracts/coconut-bandwidth-contract" }
@@ -41,7 +42,7 @@ nym-api-requests = { path = "../../../nym-api/nym-api-requests" }
async-trait = { workspace = true, optional = true }
bip39 = { workspace = true, features = ["rand"], optional = true }
nym-config = { path = "../../config", optional = true }
cosmrs = { git = "https://github.com/neacsu/cosmos-rust", branch = "neacsu/feegrant_support", features = ["rpc", "bip32", "cosmwasm"], optional = true }
cosmrs = { workspace = true, features = ["rpc", "bip32", "cosmwasm"], optional = true }
# note that this has the same version as used by cosmrs
eyre = { version = "0.6", optional = true }
cw3 = { workspace = true, optional = true }
@@ -55,7 +56,7 @@ cosmwasm-std = { workspace = true, optional = true }
[dev-dependencies]
bip39 = { workspace = true }
cosmrs = { git = "https://github.com/neacsu/cosmos-rust", branch = "neacsu/feegrant_support", features = ["rpc", "bip32"] }
cosmrs = { workspace = true, features = ["rpc", "bip32"] }
tokio = { version = "1.24.1", features = ["rt-multi-thread", "macros"] }
ts-rs = "6.1.2"
@@ -17,7 +17,7 @@ pub use nym_mixnet_contract_common::{
use url::Url;
#[cfg(feature = "nyxd-client")]
use crate::nyxd::traits::{DkgQueryClient, MixnetQueryClient};
use crate::nyxd::traits::{DkgQueryClient, EphemeraQueryClient, MixnetQueryClient};
#[cfg(feature = "nyxd-client")]
use crate::nyxd::{self, CosmWasmClient, NyxdClient, QueryNyxdClient, SigningNyxdClient};
#[cfg(feature = "nyxd-client")]
@@ -29,6 +29,8 @@ use nym_coconut_dkg_common::{types::EpochId, verification_key::ContractVKShare};
#[cfg(feature = "nyxd-client")]
use nym_coconut_interface::Base58;
#[cfg(feature = "nyxd-client")]
use nym_ephemera_common::types::JsonPeerInfo;
#[cfg(feature = "nyxd-client")]
use nym_mixnet_contract_common::{
families::{Family, FamilyHead},
mixnode::MixNodeBond,
@@ -569,6 +571,26 @@ impl<C> Client<C> {
Ok(events)
}
pub async fn get_all_ephemera_peers(&self) -> Result<Vec<JsonPeerInfo>, ValidatorClientError>
where
C: CosmWasmClient + Sync + Send,
{
let mut peers = Vec::new();
let mut start_after = None;
loop {
let mut paged_response = self.get_peers_paged(start_after.take(), None).await?;
peers.append(&mut paged_response.peers);
if let Some(start_after_res) = paged_response.start_next_after {
start_after = Some(start_after_res.to_string())
} else {
break;
}
}
Ok(peers)
}
}
// validator-api wrappers
@@ -127,7 +127,7 @@ impl GasAdjustable for Gas {
mod sealed {
use cosmrs::tx::{self, Gas};
use cosmrs::Coin as CosmosCoin;
use cosmrs::{AccountId, Decimal as CosmosDecimal, Denom as CosmosDenom};
use cosmrs::{AccountId, Denom as CosmosDenom};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
fn cosmos_denom_inner_getter(val: &CosmosDenom) -> String {
@@ -144,29 +144,11 @@ mod sealed {
}
}
fn cosmos_decimal_inner_getter(val: &CosmosDecimal) -> u64 {
// haha, this code is so disgusting. I'll make a PR on cosmrs to slightly alleviate those issues...
// note: unwrap here is fine as the to_string is just returning a stringified u64 which, well, is a valid u64
val.to_string().parse().unwrap()
}
// at the time of writing it the current cosmrs' Decimal is extremely limited...
#[derive(Serialize, Deserialize)]
#[serde(remote = "CosmosDecimal")]
struct Decimal(#[serde(getter = "cosmos_decimal_inner_getter")] u64);
impl From<Decimal> for CosmosDecimal {
fn from(val: Decimal) -> Self {
val.0.into()
}
}
#[derive(Serialize, Deserialize, Clone)]
struct Coin {
#[serde(with = "Denom")]
denom: CosmosDenom,
#[serde(with = "Decimal")]
amount: CosmosDecimal,
amount: u128,
}
impl From<Coin> for CosmosCoin {
@@ -39,7 +39,7 @@ pub use cosmrs::tendermint::validator::Info as TendermintValidatorInfo;
pub use cosmrs::tendermint::Time as TendermintTime;
pub use cosmrs::tx::{self, Gas};
pub use cosmrs::Coin as CosmosCoin;
pub use cosmrs::{bip32, AccountId, Decimal, Denom};
pub use cosmrs::{bip32, AccountId, Denom};
use cosmwasm_std::Addr;
pub use cosmwasm_std::Coin as CosmWasmCoin;
pub use fee::{gas_price::GasPrice, GasAdjustable, GasAdjustment};
@@ -67,6 +67,7 @@ pub struct Config {
pub(crate) group_contract_address: Option<AccountId>,
pub(crate) multisig_contract_address: Option<AccountId>,
pub(crate) coconut_dkg_contract_address: Option<AccountId>,
pub(crate) ephemera_contract_address: Option<AccountId>,
pub(crate) service_provider_contract_address: Option<AccountId>,
pub(crate) name_service_contract_address: Option<AccountId>,
// TODO: add this in later commits
@@ -133,6 +134,10 @@ impl Config {
details.contracts.coconut_dkg_contract_address.as_ref(),
prefix,
)?,
ephemera_contract_address: Self::parse_optional_account(
details.contracts.ephemera_contract_address.as_ref(),
prefix,
)?,
service_provider_contract_address: Self::parse_optional_account(
details
.contracts
@@ -263,6 +268,10 @@ impl<C> NyxdClient<C> {
self.config.service_provider_contract_address = Some(address);
}
pub fn set_ephemera_contract_address(&mut self, address: AccountId) {
self.config.ephemera_contract_address = Some(address);
}
// TODO: this should get changed into Result<&AccountId, NyxdError> (or Option<&AccountId> in future commits
// note: what unwrap is doing here is just moving a failure that would have normally
// occurred in `connect` when attempting to parse an empty address,
@@ -321,6 +330,14 @@ impl<C> NyxdClient<C> {
self.config.coconut_dkg_contract_address.as_ref().unwrap()
}
// TODO: this should get changed into Result<&AccountId, NyxdError> (or Option<&AccountId> in future commits
// note: what unwrap is doing here is just moving a failure that would have normally
// occurred in `connect` when attempting to parse an empty address,
// so it's not introducing new source of failure (just moves it)
pub fn ephemera_contract_address(&self) -> &AccountId {
self.config.ephemera_contract_address.as_ref().unwrap()
}
// The service provider directory contract is optional, so we return an Option not a Result
pub fn service_provider_contract_address(&self) -> Option<&AccountId> {
self.config.service_provider_contract_address.as_ref()
@@ -0,0 +1,53 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::nyxd::error::NyxdError;
use crate::nyxd::{CosmWasmClient, NyxdClient};
use async_trait::async_trait;
use nym_ephemera_common::msg::QueryMsg as EphemeraQueryMsg;
use nym_ephemera_common::peers::PagedPeerResponse;
use serde::Deserialize;
#[async_trait]
pub trait EphemeraQueryClient {
async fn query_ephemera_contract<T>(&self, query: EphemeraQueryMsg) -> Result<T, NyxdError>
where
for<'a> T: Deserialize<'a>;
async fn get_peers_paged(
&self,
start_after: Option<String>,
limit: Option<u32>,
) -> Result<PagedPeerResponse, NyxdError> {
let request = EphemeraQueryMsg::GetPeers { start_after, limit };
self.query_ephemera_contract(request).await
}
}
#[async_trait]
impl<C> EphemeraQueryClient for NyxdClient<C>
where
C: CosmWasmClient + Send + Sync,
{
async fn query_ephemera_contract<T>(&self, query: EphemeraQueryMsg) -> Result<T, NyxdError>
where
for<'a> T: Deserialize<'a>,
{
self.client
.query_contract_smart(self.ephemera_contract_address(), &query)
.await
}
}
#[async_trait]
impl<C> EphemeraQueryClient for crate::Client<C>
where
C: CosmWasmClient + Sync + Send,
{
async fn query_ephemera_contract<T>(&self, query: EphemeraQueryMsg) -> Result<T, NyxdError>
where
for<'a> T: Deserialize<'a>,
{
self.nyxd.query_ephemera_contract(query).await
}
}
@@ -0,0 +1,43 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::nyxd::cosmwasm_client::types::ExecuteResult;
use crate::nyxd::error::NyxdError;
use crate::nyxd::{Fee, NyxdClient, SigningCosmWasmClient};
use async_trait::async_trait;
use nym_ephemera_common::msg::ExecuteMsg as EphemeraExecuteMsg;
use nym_ephemera_common::types::JsonPeerInfo;
#[async_trait]
pub trait EphemeraSigningClient {
async fn register_as_peer(
&self,
peer_info: JsonPeerInfo,
fee: Option<Fee>,
) -> Result<ExecuteResult, NyxdError>;
}
#[async_trait]
impl<C> EphemeraSigningClient for NyxdClient<C>
where
C: SigningCosmWasmClient + Send + Sync,
{
async fn register_as_peer(
&self,
peer_info: JsonPeerInfo,
fee: Option<Fee>,
) -> Result<ExecuteResult, NyxdError> {
let req = EphemeraExecuteMsg::RegisterPeer { peer_info };
self.client
.execute(
self.address(),
self.ephemera_contract_address(),
&req,
fee.unwrap_or_default(),
format!("registering {} as an ephemera peer", self.address()),
vec![],
)
.await
}
}
@@ -5,6 +5,8 @@
mod coconut_bandwidth_query_client;
mod dkg_query_client;
mod ephemera_query_client;
mod ephemera_signing_client;
mod group_query_client;
mod mixnet_query_client;
mod multisig_query_client;
@@ -24,6 +26,7 @@ mod name_service_signing_client;
pub use coconut_bandwidth_query_client::CoconutBandwidthQueryClient;
pub use dkg_query_client::DkgQueryClient;
pub use ephemera_query_client::EphemeraQueryClient;
pub use group_query_client::GroupQueryClient;
pub use mixnet_query_client::MixnetQueryClient;
pub use multisig_query_client::MultisigQueryClient;
@@ -33,6 +36,7 @@ pub use vesting_query_client::VestingQueryClient;
pub use coconut_bandwidth_signing_client::CoconutBandwidthSigningClient;
pub use dkg_signing_client::DkgSigningClient;
pub use ephemera_signing_client::EphemeraSigningClient;
pub use mixnet_signing_client::MixnetSigningClient;
pub use multisig_signing_client::MultisigSigningClient;
pub use name_service_signing_client::NameServiceSigningClient;
+2 -2
View File
@@ -14,7 +14,7 @@ clap = { version = "4.0", features = ["derive"] }
cw-utils = { workspace = true }
handlebars = "3.0.1"
humantime-serde = "1.0"
k256 = { version = "0.10", features = ["ecdsa", "sha256"] }
k256 = { workspace = true, features = ["ecdsa", "sha256"] }
log = { workspace = true }
rand = {version = "0.6", features = ["std"] }
serde = { version = "1.0", features = ["derive"] }
@@ -25,7 +25,7 @@ toml = "0.5.6"
url = "2.2"
tap = "1"
cosmrs = { git = "https://github.com/neacsu/cosmos-rust", branch = "neacsu/feegrant_support" }
cosmrs = { workspace = true }
cosmwasm-std = { workspace = true }
nym-validator-client = { path = "../client-libs/validator-client", features = ["nyxd-client"] }
@@ -56,6 +56,8 @@ pub async fn generate(args: Args) {
.expect("threshold can't be converted to Decimal"),
},
max_voting_period: Duration::Time(args.max_voting_period),
executor: None,
proposal_deposit: None,
coconut_bandwidth_contract_address: coconut_bandwidth_contract_address.to_string(),
coconut_dkg_contract_address: coconut_dkg_contract_address.to_string(),
};
+1
View File
@@ -17,6 +17,7 @@ pub mod helpers;
pub mod legacy_helpers;
pub const NYM_DIR: &str = ".nym";
pub const DEFAULT_NYM_APIS_DIR: &str = "nym-api";
pub const DEFAULT_CONFIG_DIR: &str = "config";
pub const DEFAULT_DATA_DIR: &str = "data";
pub const DEFAULT_CONFIG_FILENAME: &str = "config.toml";
@@ -14,7 +14,7 @@ pub struct InstantiateMsg {
pub mix_denom: String,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ExecuteMsg {
DepositFunds { data: DepositData },
@@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize};
use crate::msg::ExecuteMsg;
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
pub struct SpendCredentialData {
funds: Coin,
blinded_serial_number: String,
@@ -43,7 +43,7 @@ pub enum SpendCredentialStatus {
Spent,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct SpendCredential {
funds: Coin,
blinded_serial_number: String,
@@ -74,7 +74,7 @@ impl SpendCredential {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct PagedSpendCredentialResponse {
pub spend_credentials: Vec<SpendCredential>,
pub per_page: usize,
@@ -95,7 +95,7 @@ impl PagedSpendCredentialResponse {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct SpendCredentialResponse {
pub spend_credential: Option<SpendCredential>,
}
@@ -15,7 +15,7 @@ pub type Nonce = u32;
// define this type explicitly for [hopefully] better usability
// (so you wouldn't need to worry about whether you should use bytes, bs58, etc.)
#[derive(Clone, Debug, PartialEq, JsonSchema)]
#[derive(Clone, Debug, PartialEq, Eq, JsonSchema)]
pub struct MessageSignature(Vec<u8>);
impl MessageSignature {
@@ -0,0 +1,14 @@
[package]
name = "nym-ephemera-common"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
cosmwasm-std = { workspace = true }
cw-utils = { workspace = true }
schemars = "0.8"
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
contracts-common = { path = "../contracts-common", package = "nym-contracts-common" }
@@ -0,0 +1,3 @@
pub mod msg;
pub mod peers;
pub mod types;
@@ -0,0 +1,31 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::types::JsonPeerInfo;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
pub struct InstantiateMsg {
pub group_addr: String,
pub mix_denom: String,
}
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ExecuteMsg {
RegisterPeer { peer_info: JsonPeerInfo },
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum QueryMsg {
GetPeers {
limit: Option<u32>,
start_after: Option<String>,
},
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub struct MigrateMsg {}
@@ -0,0 +1,24 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::types::JsonPeerInfo;
use cosmwasm_std::Addr;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub struct PagedPeerResponse {
pub peers: Vec<JsonPeerInfo>,
pub per_page: usize,
pub start_next_after: Option<Addr>,
}
impl PagedPeerResponse {
pub fn new(peers: Vec<JsonPeerInfo>, per_page: usize, start_next_after: Option<Addr>) -> Self {
PagedPeerResponse {
peers,
per_page,
start_next_after,
}
}
}
@@ -0,0 +1,30 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use cosmwasm_std::Addr;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema)]
pub struct JsonPeerInfo {
/// The cosmos address of the peer, used in interacting with the chain.
pub cosmos_address: Addr,
/// The TCP/IP address of the peer.
/// Expected formats:
/// 1. `<IP>:<PORT>`
/// 2. `/ip4/<IP>/tcp/<PORT>` - this is the format used by libp2p multiaddr
pub ip_address: String,
///Serialized public key.
pub public_key: String,
}
impl JsonPeerInfo {
#[must_use]
pub fn new(cosmos_address: Addr, ip_address: String, public_key: String) -> Self {
Self {
cosmos_address,
ip_address,
public_key,
}
}
}
@@ -6,6 +6,8 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
cosmwasm-schema = { workspace = true }
cw4 = { workspace = true }
cw-controllers = { workspace = true }
schemars = "0.8"
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
@@ -1,13 +1,7 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use cosmwasm_schema::{cw_serde, QueryResponses};
use cw4::Member;
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
pub struct InstantiateMsg {
/// The admin is the only account that can update the group state.
/// Omit it to make the group immutable.
@@ -15,8 +9,7 @@ pub struct InstantiateMsg {
pub members: Vec<Member>,
}
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
pub enum ExecuteMsg {
/// Change the admin
UpdateAdmin { admin: Option<String> },
@@ -32,23 +25,24 @@ pub enum ExecuteMsg {
RemoveHook { addr: String },
}
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, JsonSchema, Debug)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
#[derive(QueryResponses)]
pub enum QueryMsg {
/// Return AdminResponse
#[returns(cw_controllers::AdminResponse)]
Admin {},
/// Return TotalWeightResponse
TotalWeight {},
/// Returns MembersListResponse
#[returns(cw4::TotalWeightResponse)]
TotalWeight { at_height: Option<u64> },
#[returns(cw4::MemberListResponse)]
ListMembers {
start_after: Option<String>,
limit: Option<u32>,
},
/// Returns MemberResponse
#[returns(cw4::MemberResponse)]
Member {
addr: String,
at_height: Option<u64>,
},
/// Shows all registered hooks. Returns HooksResponse.
/// Shows all registered hooks.
#[returns(cw_controllers::HooksResponse)]
Hooks {},
}
@@ -37,7 +37,7 @@ pub fn generate_owner_storage_subkey(
}
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, JsonSchema)]
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, JsonSchema)]
pub struct Delegation {
/// Address of the owner of this delegation.
pub owner: Addr,
@@ -114,7 +114,7 @@ impl Delegation {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct PagedMixNodeDelegationsResponse {
pub delegations: Vec<Delegation>,
pub start_next_after: Option<OwnerProxySubKey>,
@@ -129,7 +129,7 @@ impl PagedMixNodeDelegationsResponse {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct PagedDelegatorDelegationsResponse {
pub delegations: Vec<Delegation>,
pub start_next_after: Option<(MixId, OwnerProxySubKey)>,
@@ -147,7 +147,7 @@ impl PagedDelegatorDelegationsResponse {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct MixNodeDelegationResponse {
pub delegation: Option<Delegation>,
pub mixnode_still_bonded: bool,
@@ -162,7 +162,7 @@ impl MixNodeDelegationResponse {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct PagedAllDelegationsResponse {
pub delegations: Vec<Delegation>,
pub start_next_after: Option<StorageKey>,
@@ -23,7 +23,7 @@ pub struct Gateway {
pub version: String,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct GatewayBond {
pub pledge_amount: Coin,
pub owner: Addr,
@@ -132,7 +132,7 @@ impl GatewayConfigUpdate {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct PagedGatewayResponse {
pub nodes: Vec<GatewayBond>,
pub per_page: usize,
@@ -153,13 +153,13 @@ impl PagedGatewayResponse {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct GatewayOwnershipResponse {
pub address: Addr,
pub gateway: Option<GatewayBond>,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct GatewayBondResponse {
pub identity: IdentityKey,
pub gateway: Option<GatewayBond>,
@@ -489,7 +489,7 @@ impl CurrentIntervalResponse {
}
}
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct PendingEpochEventsResponse {
pub seconds_until_executable: i64,
pub events: Vec<PendingEpochEvent>,
@@ -510,7 +510,7 @@ impl PendingEpochEventsResponse {
}
}
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct PendingIntervalEventsResponse {
pub seconds_until_executable: i64,
pub events: Vec<PendingIntervalEvent>,
@@ -33,7 +33,7 @@ impl RewardedSetNodeStatus {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct MixNodeDetails {
pub bond_information: MixNodeBond,
pub rewarding_details: MixNodeRewarding,
@@ -86,7 +86,7 @@ impl MixNodeDetails {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct MixNodeRewarding {
/// Information provided by the operator that influence the cost function.
pub cost_params: MixNodeCostParams,
@@ -465,7 +465,7 @@ impl MixNodeRewarding {
}
// operator information + data assigned by the contract(s)
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct MixNodeBond {
/// Unique id assigned to the bonded mixnode.
pub mix_id: MixId,
@@ -559,7 +559,7 @@ pub struct MixNode {
pub version: String,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct MixNodeCostParams {
pub profit_margin_percent: Percent,
@@ -686,7 +686,7 @@ impl MixNodeConfigUpdate {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct PagedMixnodeBondsResponse {
pub nodes: Vec<MixNodeBond>,
pub per_page: usize,
@@ -703,7 +703,7 @@ impl PagedMixnodeBondsResponse {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct PagedMixnodesDetailsResponse {
pub nodes: Vec<MixNodeDetails>,
pub per_page: usize,
@@ -745,19 +745,19 @@ impl PagedUnbondedMixnodesResponse {
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct MixOwnershipResponse {
pub address: Addr,
pub mixnode_details: Option<MixNodeDetails>,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct MixnodeDetailsResponse {
pub mix_id: MixId,
pub mixnode_details: Option<MixNodeDetails>,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, JsonSchema)]
pub struct MixnodeRewardingDetailsResponse {
pub mix_id: MixId,
pub rewarding_details: Option<MixNodeRewarding>,
@@ -7,19 +7,19 @@ use crate::{BlockHeight, EpochEventId, IntervalEventId, MixId};
use cosmwasm_std::{Addr, Coin};
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct PendingEpochEvent {
pub id: EpochEventId,
pub event: PendingEpochEventData,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct PendingEpochEventData {
pub created_at: BlockHeight,
pub kind: PendingEpochEventKind,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub enum PendingEpochEventKind {
// can't just pass the `Delegation` struct here as it's impossible to determine
// `cumulative_reward_ratio` ahead of time
@@ -68,19 +68,19 @@ impl From<(EpochEventId, PendingEpochEventData)> for PendingEpochEvent {
}
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct PendingIntervalEvent {
pub id: IntervalEventId,
pub event: PendingIntervalEventData,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct PendingIntervalEventData {
pub created_at: BlockHeight,
pub kind: PendingIntervalEventKind,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub enum PendingIntervalEventKind {
ChangeMixCostParams {
mix_id: MixId,
@@ -35,7 +35,7 @@ pub struct RewardDistribution {
pub delegates: Decimal,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize, JsonSchema, PartialEq)]
#[derive(Clone, Debug, Default, Deserialize, Serialize, JsonSchema, PartialEq, Eq)]
pub struct PendingRewardResponse {
pub amount_staked: Option<Coin>,
pub amount_earned: Option<Coin>,
@@ -46,7 +46,7 @@ pub struct PendingRewardResponse {
pub mixnode_still_fully_bonded: bool,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize, JsonSchema, PartialEq)]
#[derive(Clone, Debug, Default, Deserialize, Serialize, JsonSchema, PartialEq, Eq)]
pub struct EstimatedCurrentEpochRewardResponse {
pub original_stake: Option<Coin>,
@@ -22,7 +22,7 @@ pub type EpochEventId = u32;
pub type IntervalEventId = u32;
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema, PartialEq)]
#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema, PartialEq, Eq)]
pub struct LayerAssignment {
mix_id: MixId,
layer: Layer,
@@ -118,7 +118,7 @@ impl Index<Layer> for LayerDistribution {
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
pub struct ContractState {
pub owner: Addr, // only the owner account can update state
pub rewarding_validator_address: Addr,
@@ -130,7 +130,7 @@ pub struct ContractState {
pub params: ContractStateParams,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
pub struct ContractStateParams {
/// Minimum amount a delegator must stake in orders for his delegation to get accepted.
pub minimum_mixnode_delegation: Option<Coin>,
@@ -9,6 +9,8 @@ edition = "2021"
cw-utils = { workspace = true }
cw3 = { workspace = true }
cw4 = { workspace= true }
cw-storage-plus = { workspace = true }
cosmwasm-schema = { workspace = true }
cosmwasm-std = { workspace = true }
schemars = "0.8"
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
@@ -2,7 +2,8 @@
// SPDX-License-Identifier: Apache-2.0
use cosmwasm_std::StdError;
use cw_utils::ThresholdError;
use cw3::DepositError;
use cw_utils::{PaymentError, ThresholdError};
use thiserror::Error;
@@ -17,9 +18,6 @@ pub enum ContractError {
#[error("Group contract invalid address '{addr}'")]
InvalidGroup { addr: String },
#[error("Coconut bandwidth contract address not found")]
InvalidCoconutBandwidth {},
#[error("Unauthorized")]
Unauthorized {},
@@ -43,4 +41,10 @@ pub enum ContractError {
#[error("Cannot close completed or passed proposals")]
WrongCloseStatus {},
#[error("{0}")]
Payment(#[from] PaymentError),
#[error("{0}")]
Deposit(#[from] DepositError),
}
@@ -1,2 +1,3 @@
pub mod error;
pub mod msg;
pub mod state;
@@ -1,15 +1,15 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use cosmwasm_schema::{cw_serde, QueryResponses};
use cosmwasm_std::{CosmosMsg, Empty};
use cw3::Vote;
use cw3::{UncheckedDepositInfo, Vote};
use cw4::MemberChangedHookMsg;
use cw_utils::{Duration, Expiration, Threshold};
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
use crate::state::Executor;
#[cw_serde]
pub struct InstantiateMsg {
// this is the group contract that contains the member list
pub group_addr: String,
@@ -17,11 +17,15 @@ pub struct InstantiateMsg {
pub coconut_dkg_contract_address: String,
pub threshold: Threshold,
pub max_voting_period: Duration,
// who is able to execute passed proposals
// None means that anyone can execute
pub executor: Option<Executor>,
/// The cost of creating a proposal (if any).
pub proposal_deposit: Option<UncheckedDepositInfo>,
}
// TODO: add some T variants? Maybe good enough as fixed Empty for now
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
pub enum ExecuteMsg {
Propose {
title: String,
@@ -45,41 +49,44 @@ pub enum ExecuteMsg {
}
// We can also add this as a cw3 extension
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, JsonSchema, Debug)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
#[derive(QueryResponses)]
pub enum QueryMsg {
/// Return ThresholdResponse
#[returns(cw_utils::ThresholdResponse)]
Threshold {},
/// Returns ProposalResponse
#[returns(cw3::ProposalResponse)]
Proposal { proposal_id: u64 },
/// Returns ProposalListResponse
#[returns(cw3::ProposalListResponse)]
ListProposals {
start_after: Option<u64>,
limit: Option<u32>,
},
/// Returns ProposalListResponse
#[returns(cw3::ProposalListResponse)]
ReverseProposals {
start_before: Option<u64>,
limit: Option<u32>,
},
/// Returns VoteResponse
#[returns(cw3::VoteResponse)]
Vote { proposal_id: u64, voter: String },
/// Returns VoteListResponse
#[returns(cw3::VoteListResponse)]
ListVotes {
proposal_id: u64,
start_after: Option<String>,
limit: Option<u32>,
},
/// Returns VoterInfo
#[returns(cw3::VoterResponse)]
Voter { address: String },
/// Returns VoterListResponse
#[returns(cw3::VoterListResponse)]
ListVoters {
start_after: Option<String>,
limit: Option<u32>,
},
/// Gets the current configuration.
#[returns(crate::state::Config)]
Config {},
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[cw_serde]
pub struct MigrateMsg {
pub coconut_bandwidth_address: String,
pub coconut_dkg_address: String,
@@ -0,0 +1,59 @@
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{Addr, QuerierWrapper};
use cw3::DepositInfo;
use cw4::Cw4Contract;
use cw_storage_plus::Item;
use cw_utils::{Duration, Threshold};
use crate::error::ContractError;
/// Defines who is able to execute proposals once passed
#[cw_serde]
pub enum Executor {
/// Any member of the voting group, even with 0 points
Member,
/// Only the given address
Only(Addr),
}
#[cw_serde]
pub struct Config {
pub threshold: Threshold,
pub max_voting_period: Duration,
// Total weight and voters are queried from this contract
pub group_addr: Cw4Contract,
pub coconut_bandwidth_addr: Addr,
pub coconut_dkg_addr: Addr,
// who is able to execute passed proposals
// None means that anyone can execute
pub executor: Option<Executor>,
/// The price, if any, of creating a new proposal.
pub proposal_deposit: Option<DepositInfo>,
}
impl Config {
// Executor can be set in 3 ways:
// - Member: any member of the voting group is authorized
// - Only: only passed address is authorized
// - None: Everyone are authorized
pub fn authorize(&self, querier: &QuerierWrapper, sender: &Addr) -> Result<(), ContractError> {
if let Some(executor) = &self.executor {
match executor {
Executor::Member => {
self.group_addr
.is_member(querier, sender, None)?
.ok_or(ContractError::Unauthorized {})?;
}
Executor::Only(addr) => {
if addr != sender {
return Err(ContractError::Unauthorized {});
}
}
}
}
Ok(())
}
}
// unique items
pub const CONFIG: Item<Config> = Item::new("config");
@@ -28,7 +28,7 @@ pub enum Period {
After,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
pub struct PledgeData {
pub amount: Coin,
pub block_time: Timestamp,
@@ -49,7 +49,7 @@ impl PledgeData {
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
pub enum PledgeCap {
Percent(Percent),
Absolute(Uint128), // This has to be in unym
@@ -77,7 +77,7 @@ impl Default for PledgeCap {
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
pub struct OriginalVestingResponse {
pub amount: Coin,
pub number_of_periods: usize,
@@ -55,7 +55,7 @@ impl VestingSpecification {
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ExecuteMsg {
// Families
+1 -1
View File
@@ -7,7 +7,7 @@ edition = "2021"
[dependencies]
bls12_381 = { version = "0.5", default-features = false, features = ["pairings", "alloc", "experimental"] }
cosmrs = { git = "https://github.com/neacsu/cosmos-rust", branch = "neacsu/feegrant_support" }
cosmrs = { workspace = true }
thiserror = "1.0"
# I guess temporarily until we get serde support in coconut up and running
+2 -1
View File
@@ -27,7 +27,7 @@ thiserror = "1.0.37"
zeroize = { workspace = true, optional = true, features = ["zeroize_derive"] }
# internal
nym-sphinx-types = { path = "../nymsphinx/types", version = "0.2.0" }
nym-sphinx-types = { path = "../nymsphinx/types", version = "0.2.0", default-features = false }
nym-pemstore = { path = "../../common/pemstore", version = "0.3.0" }
[dev-dependencies]
@@ -38,3 +38,4 @@ serde = ["serde_crate", "serde_bytes", "ed25519-dalek/serde", "x25519-dalek/serd
asymmetric = ["x25519-dalek", "ed25519-dalek", "zeroize"]
hashing = ["blake3", "digest", "hkdf", "hmac", "generic-array"]
symmetric = ["aes", "ctr", "cipher", "generic-array"]
wasm-contract = ["nym-sphinx-types/wasm-contract"]
+2 -2
View File
@@ -6,8 +6,8 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
bip32 = "0.3.0"
k256 = "0.10.4"
bip32 = "0.4.0"
k256 = { workspace = true }
ledger-transport = "0.10.0"
ledger-transport-hid = "0.10.0"
thiserror = "1"
+11
View File
@@ -30,6 +30,7 @@ pub struct NymContracts {
pub group_contract_address: Option<String>,
pub multisig_contract_address: Option<String>,
pub coconut_dkg_contract_address: Option<String>,
pub ephemera_contract_address: Option<String>,
pub service_provider_directory_contract_address: Option<String>,
pub name_service_contract_address: Option<String>,
}
@@ -129,6 +130,9 @@ impl NymNetworkDetails {
.with_coconut_dkg_contract(Some(
var(var_names::COCONUT_DKG_CONTRACT_ADDRESS).expect("coconut dkg contract not set"),
))
.with_ephemera_contract(Some(
var(var_names::EPHEMERA_CONTRACT_ADDRESS).expect("ephemera contract not set"),
))
.with_service_provider_directory_contract(get_optional_env(
var_names::SERVICE_PROVIDER_DIRECTORY_CONTRACT_ADDRESS,
))
@@ -162,6 +166,7 @@ impl NymNetworkDetails {
coconut_dkg_contract_address: parse_optional_str(
mainnet::COCONUT_DKG_CONTRACT_ADDRESS,
),
ephemera_contract_address: parse_optional_str(mainnet::EPHEMERA_CONTRACT_ADDRESS),
service_provider_directory_contract_address: None,
name_service_contract_address: None,
},
@@ -246,6 +251,12 @@ impl NymNetworkDetails {
self
}
#[must_use]
pub fn with_ephemera_contract<S: Into<String>>(mut self, contract: Option<S>) -> Self {
self.contracts.ephemera_contract_address = contract.map(Into::into);
self
}
#[must_use]
pub fn with_service_provider_directory_contract<S: Into<String>>(
mut self,
+9
View File
@@ -20,6 +20,7 @@ pub(crate) const COCONUT_BANDWIDTH_CONTRACT_ADDRESS: &str =
pub(crate) const GROUP_CONTRACT_ADDRESS: &str = "n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0";
pub(crate) const MULTISIG_CONTRACT_ADDRESS: &str = "n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0";
pub(crate) const COCONUT_DKG_CONTRACT_ADDRESS: &str = "n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0";
pub(crate) const EPHEMERA_CONTRACT_ADDRESS: &str = "n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0";
pub(crate) const REWARDING_VALIDATOR_ADDRESS: &str = "n10yyd98e2tuwu0f7ypz9dy3hhjw7v772q6287gy";
pub const STATISTICS_SERVICE_DOMAIN_ADDRESS: &str = "https://mainnet-stats.nymte.ch:8090/";
@@ -87,6 +88,10 @@ pub fn export_to_env() {
var_names::COCONUT_DKG_CONTRACT_ADDRESS,
COCONUT_DKG_CONTRACT_ADDRESS,
);
set_var_to_default(
var_names::EPHEMERA_CONTRACT_ADDRESS,
EPHEMERA_CONTRACT_ADDRESS,
);
set_var_to_default(
var_names::REWARDING_VALIDATOR_ADDRESS,
REWARDING_VALIDATOR_ADDRESS,
@@ -132,6 +137,10 @@ pub fn export_to_env_if_not_set() {
var_names::COCONUT_DKG_CONTRACT_ADDRESS,
COCONUT_DKG_CONTRACT_ADDRESS,
);
set_var_conditionally_to_default(
var_names::EPHEMERA_CONTRACT_ADDRESS,
EPHEMERA_CONTRACT_ADDRESS,
);
set_var_conditionally_to_default(
var_names::REWARDING_VALIDATOR_ADDRESS,
REWARDING_VALIDATOR_ADDRESS,
+1
View File
@@ -17,6 +17,7 @@ pub const COCONUT_BANDWIDTH_CONTRACT_ADDRESS: &str = "COCONUT_BANDWIDTH_CONTRACT
pub const GROUP_CONTRACT_ADDRESS: &str = "GROUP_CONTRACT_ADDRESS";
pub const MULTISIG_CONTRACT_ADDRESS: &str = "MULTISIG_CONTRACT_ADDRESS";
pub const COCONUT_DKG_CONTRACT_ADDRESS: &str = "COCONUT_DKG_CONTRACT_ADDRESS";
pub const EPHEMERA_CONTRACT_ADDRESS: &str = "EPHEMERA_CONTRACT_ADDRESS";
pub const REWARDING_VALIDATOR_ADDRESS: &str = "REWARDING_VALIDATOR_ADDRESS";
pub const STATISTICS_SERVICE_DOMAIN_ADDRESS: &str = "STATISTICS_SERVICE_DOMAIN_ADDRESS";
pub const SERVICE_PROVIDER_DIRECTORY_CONTRACT_ADDRESS: &str =
+5 -1
View File
@@ -9,5 +9,9 @@ repository = { workspace = true }
[dependencies]
sphinx-packet = { version = "0.1.0" }
nym-outfox = { path = "../../../nym-outfox" }
nym-outfox = { path = "../../../nym-outfox", optional = true }
thiserror = "1"
[features]
default = ["nym-outfox"]
wasm-contract = []
+5
View File
@@ -1,11 +1,13 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
#[cfg(not(feature = "wasm-contract"))]
pub use nym_outfox::{
constants::MIN_PACKET_SIZE, constants::MIX_PARAMS_LEN, constants::OUTFOX_PACKET_OVERHEAD,
error::OutfoxError,
};
// re-exporting types and constants available in sphinx
#[cfg(not(feature = "wasm-contract"))]
use nym_outfox::packet::{OutfoxPacket, OutfoxProcessedPacket};
pub use sphinx_packet::{
constants::{
@@ -30,6 +32,7 @@ pub enum NymPacketError {
Sphinx(#[from] sphinx_packet::Error),
#[error("Outfox error: {0}")]
#[cfg(not(feature = "wasm-contract"))]
Outfox(#[from] nym_outfox::error::OutfoxError),
#[error("{0}")]
@@ -39,11 +42,13 @@ pub enum NymPacketError {
#[allow(clippy::large_enum_variant)]
pub enum NymPacket {
Sphinx(SphinxPacket),
#[cfg(not(feature = "wasm-contract"))]
Outfox(OutfoxPacket),
}
pub enum NymProcessedPacket {
Sphinx(ProcessedPacket),
#[cfg(not(feature = "wasm-contract"))]
Outfox(OutfoxProcessedPacket),
}
@@ -78,7 +78,7 @@ impl SocksRequest {
where
R: AsyncRead + Unpin,
{
log::info!("read from stream socks5");
log::trace!("read from stream socks5");
let mut packet = [0u8; 4];
// Read a byte from the stream and determine the version being requested
+1 -1
View File
@@ -30,7 +30,7 @@ enum TaskError {
}
// TODO: possibly we should create a `Status` trait instead of reusing `Error`
#[derive(thiserror::Error, Debug)]
#[derive(thiserror::Error, Debug, PartialEq, Eq)]
pub enum TaskStatus {
#[error("Ready")]
Ready,
+1 -1
View File
@@ -20,7 +20,7 @@ url = "2.2"
ts-rs = "6.1.2"
cosmwasm-std = { workspace = true }
cosmrs = { git = "https://github.com/neacsu/cosmos-rust", branch = "neacsu/feegrant_support" }
cosmrs = { workspace = true }
nym-validator-client = { path = "../../common/client-libs/validator-client", features = [
"nyxd-client",
+200 -297
View File
@@ -2,16 +2,6 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "aead"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0"
dependencies = [
"crypto-common",
"generic-array 0.14.6",
]
[[package]]
name = "aes"
version = "0.7.5"
@@ -19,7 +9,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8"
dependencies = [
"cfg-if",
"cipher 0.3.0",
"cipher",
"cpufeatures",
"ctr",
"opaque-debug 0.3.0",
@@ -48,12 +38,6 @@ version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545"
[[package]]
name = "arrayvec"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
[[package]]
name = "autocfg"
version = "1.1.0"
@@ -102,20 +86,6 @@ dependencies = [
"opaque-debug 0.2.3",
]
[[package]]
name = "blake3"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ae2468a89544a466886840aa467a25b766499f4f04bf7d9fcd10ecee9fccef"
dependencies = [
"arrayref",
"arrayvec",
"cc",
"cfg-if",
"constant_time_eq",
"digest 0.10.7",
]
[[package]]
name = "block-buffer"
version = "0.9.0"
@@ -189,30 +159,6 @@ dependencies = [
"keystream",
]
[[package]]
name = "chacha20"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818"
dependencies = [
"cfg-if",
"cipher 0.4.4",
"cpufeatures",
]
[[package]]
name = "chacha20poly1305"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35"
dependencies = [
"aead",
"chacha20",
"cipher 0.4.4",
"poly1305",
"zeroize",
]
[[package]]
name = "cipher"
version = "0.3.0"
@@ -222,17 +168,6 @@ dependencies = [
"generic-array 0.14.6",
]
[[package]]
name = "cipher"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
dependencies = [
"crypto-common",
"inout",
"zeroize",
]
[[package]]
name = "coconut-test"
version = "0.1.0"
@@ -260,23 +195,17 @@ dependencies = [
[[package]]
name = "const-oid"
version = "0.7.1"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3"
[[package]]
name = "constant_time_eq"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13418e745008f7349ec7e449155f419a61b92b58a99cc3616942b926825ec76b"
checksum = "520fbf3c07483f94e3e3ca9d0cfd913d7718ef2483d2cfd91c0d9e91474ab913"
[[package]]
name = "cosmwasm-crypto"
version = "1.0.0"
version = "1.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5eb0afef2325df81aadbf9be1233f522ed8f6e91df870c764bc44cca2b1415bd"
checksum = "75836a10cb9654c54e77ee56da94d592923092a10b369cdb0dbd56acefc16340"
dependencies = [
"digest 0.9.0",
"digest 0.10.7",
"ed25519-zebra",
"k256",
"rand_core 0.6.4",
@@ -285,45 +214,62 @@ dependencies = [
[[package]]
name = "cosmwasm-derive"
version = "1.0.0"
version = "1.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b36e527620a2a3e00e46b6e731ab6c9b68d11069c986f7d7be8eba79ef081a4"
checksum = "1c9f7f0e51bfc7295f7b2664fe8513c966428642aa765dad8a74acdab5e0c773"
dependencies = [
"syn 1.0.109",
]
[[package]]
name = "cosmwasm-schema"
version = "1.0.0"
version = "1.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "772e80bbad231a47a2068812b723a1ff81dd4a0d56c9391ac748177bea3a61da"
checksum = "0f00b363610218eea83f24bbab09e1a7c3920b79f068334fdfcc62f6129ef9fc"
dependencies = [
"cosmwasm-schema-derive",
"schemars",
"serde",
"serde_json",
"thiserror",
]
[[package]]
name = "cosmwasm-schema-derive"
version = "1.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae38f909b2822d32b275c9e2db9728497aa33ffe67dd463bc67c6a3b7092785c"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "cosmwasm-std"
version = "1.0.0"
version = "1.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "875994993c2082a6fcd406937bf0fca21c349e4a624f3810253a14fa83a3a195"
checksum = "a49b85345e811c8e80ec55d0d091e4fcb4f00f97ab058f9be5f614c444a730cb"
dependencies = [
"base64 0.13.1",
"cosmwasm-crypto",
"cosmwasm-derive",
"derivative",
"forward_ref",
"hex",
"schemars",
"serde",
"serde-json-wasm",
"serde-json-wasm 0.5.1",
"sha2 0.10.6",
"thiserror",
"uint",
]
[[package]]
name = "cosmwasm-storage"
version = "1.0.0"
version = "1.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d18403b07304d15d304dad11040d45bbcaf78d603b4be3fb5e2685c16f9229b5"
checksum = "a3737a3aac48f5ed883b5b73bfb731e77feebd8fc6b43419844ec2971072164d"
dependencies = [
"cosmwasm-std",
"serde",
@@ -338,49 +284,6 @@ dependencies = [
"libc",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
dependencies = [
"cfg-if",
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695"
dependencies = [
"autocfg",
"cfg-if",
"crossbeam-utils",
"memoffset",
"scopeguard",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
dependencies = [
"cfg-if",
]
[[package]]
name = "crunchy"
version = "0.2.2"
@@ -389,9 +292,9 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]]
name = "crypto-bigint"
version = "0.3.2"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21"
checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef"
dependencies = [
"generic-array 0.14.6",
"rand_core 0.6.4",
@@ -406,7 +309,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array 0.14.6",
"rand_core 0.6.4",
"typenum",
]
@@ -436,7 +338,7 @@ version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea"
dependencies = [
"cipher 0.3.0",
"cipher",
]
[[package]]
@@ -454,10 +356,11 @@ dependencies = [
[[package]]
name = "cw-controllers"
version = "0.13.4"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f0bc6019b4d3d81e11f5c384bcce7173e2210bd654d75c6c9668e12cca05dfa"
checksum = "91440ce8ec4f0642798bc8c8cb6b9b53c1926c6dadaf0eed267a5145cd529071"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw-storage-plus",
"cw-utils",
@@ -468,17 +371,17 @@ dependencies = [
[[package]]
name = "cw-multi-test"
version = "0.13.4"
version = "0.16.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3f9a8ab7c3c29ec93cb7a39ce4b14a05e053153b4a17ef7cf2246af1b7c087e"
checksum = "2a18afd2e201221c6d72a57f0886ef2a22151bbc9e6db7af276fde8a91081042"
dependencies = [
"anyhow",
"cosmwasm-std",
"cosmwasm-storage",
"cw-storage-plus",
"cw-utils",
"derivative",
"itertools",
"k256",
"prost",
"schemars",
"serde",
@@ -487,9 +390,9 @@ dependencies = [
[[package]]
name = "cw-storage-plus"
version = "0.13.4"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "648b1507290bbc03a8d88463d7cd9b04b1fa0155e5eef366c4fa052b9caaac7a"
checksum = "053a5083c258acd68386734f428a5a171b29f7d733151ae83090c6fcc9417ffa"
dependencies = [
"cosmwasm-std",
"schemars",
@@ -498,22 +401,26 @@ dependencies = [
[[package]]
name = "cw-utils"
version = "0.13.4"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dbaecb78c8e8abfd6b4258c7f4fbeb5c49a5e45ee4d910d3240ee8e1d714e1b"
checksum = "c80e93d1deccb8588db03945016a292c3c631e6325d349ebb35d2db6f4f946f7"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw2",
"schemars",
"semver",
"serde",
"thiserror",
]
[[package]]
name = "cw2"
version = "0.13.4"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04cf4639517490dd36b333bbd6c4fbd92e325fd0acf4683b41753bc5eb63bfc1"
checksum = "8fb70cee2cf0b4a8ff7253e6bc6647107905e8eb37208f87d54f67810faa62f8"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw-storage-plus",
"schemars",
@@ -521,11 +428,12 @@ dependencies = [
]
[[package]]
name = "cw3"
version = "0.13.4"
name = "cw20"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe19462a7f644ba60c19d3443cb90d00c50d9b6b3b0a3a7fca93df8261af979b"
checksum = "91666da6c7b40c8dd5ff94df655a28114efc10c79b70b4d06f13c31e37d60609"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw-utils",
"schemars",
@@ -533,11 +441,45 @@ dependencies = [
]
[[package]]
name = "cw3-fixed-multisig"
version = "0.13.4"
name = "cw20-base"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df54aa54c13f405ec4ab36b6217538bc957d439eee58f89312db05a79caf6706"
checksum = "afcd279230b08ed8afd8be5828221622bd5b9ce25d0b01d58bad626c6ce0169c"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw-storage-plus",
"cw-utils",
"cw2",
"cw20",
"schemars",
"semver",
"serde",
"thiserror",
]
[[package]]
name = "cw3"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fe0b587008aa221cd2a2579a21990a28c4347dc53ad43167c68ad765f5b6efa"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw-utils",
"cw20",
"schemars",
"serde",
"thiserror",
]
[[package]]
name = "cw3-fixed-multisig"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e9e2415adb201e5e89dab34edf59d7dc166bc558526de009a49ae66276c9119a"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw-storage-plus",
"cw-utils",
@@ -550,14 +492,15 @@ dependencies = [
[[package]]
name = "cw3-flex-multisig"
version = "0.13.1"
version = "1.0.0"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw-multi-test",
"cw-storage-plus",
"cw-utils",
"cw2",
"cw20",
"cw20-base",
"cw3",
"cw3-fixed-multisig",
"cw4",
@@ -565,15 +508,15 @@ dependencies = [
"nym-group-contract-common",
"nym-multisig-contract-common",
"schemars",
"serde",
]
[[package]]
name = "cw4"
version = "0.13.4"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0acc3549d5ce11c6901b3a676f2e2628684722197054d97cd0101ea174ed5cbd"
checksum = "2c236e0bae02ce97e89235a681dd0e07d099524b369f1ef908d704db3e6b049b"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw-storage-plus",
"schemars",
@@ -582,7 +525,7 @@ dependencies = [
[[package]]
name = "cw4-group"
version = "0.13.4"
version = "1.0.0"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
@@ -599,11 +542,12 @@ dependencies = [
[[package]]
name = "der"
version = "0.5.1"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c"
checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de"
dependencies = [
"const-oid",
"zeroize",
]
[[package]]
@@ -654,9 +598,9 @@ checksum = "68b0cf012f1230e43cd00ebb729c6bb58707ecfa8ad08b52ef3a4ccd2697fc30"
[[package]]
name = "ecdsa"
version = "0.13.4"
version = "0.14.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0d69ae62e0ce582d56380743515fefaf1a8c70cec685d9677636d7e30ae9dc9"
checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c"
dependencies = [
"der",
"elliptic-curve",
@@ -683,7 +627,7 @@ dependencies = [
"ed25519",
"rand 0.7.3",
"serde",
"sha2",
"sha2 0.9.9",
"zeroize",
]
@@ -698,7 +642,7 @@ dependencies = [
"hex",
"rand_core 0.6.4",
"serde",
"sha2",
"sha2 0.9.9",
"zeroize",
]
@@ -710,16 +654,18 @@ checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
[[package]]
name = "elliptic-curve"
version = "0.11.12"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25b477563c2bfed38a3b7a60964c49e058b2510ad3f12ba3483fd8f62c2306d6"
checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3"
dependencies = [
"base16ct",
"crypto-bigint",
"der",
"digest 0.10.7",
"ff",
"generic-array 0.14.6",
"group",
"pkcs8",
"rand_core 0.6.4",
"sec1",
"subtle 2.4.1",
@@ -778,9 +724,9 @@ dependencies = [
[[package]]
name = "ff"
version = "0.11.1"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "131655483be284720a17d74ff97592b8e76576dc25563148601df2d7c9080924"
checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160"
dependencies = [
"rand_core 0.6.4",
"subtle 2.4.1",
@@ -941,10 +887,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
dependencies = [
"cfg-if",
"js-sys",
"libc",
"wasi 0.11.0+wasi-snapshot-preview1",
"wasm-bindgen",
]
[[package]]
@@ -974,9 +918,9 @@ dependencies = [
[[package]]
name = "group"
version = "0.11.0"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc5ac374b108929de78460075f3dc439fa66df9d8fc77e8f12caa5165fcf0c89"
checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7"
dependencies = [
"ff",
"rand_core 0.6.4",
@@ -992,15 +936,6 @@ dependencies = [
"ahash",
]
[[package]]
name = "hermit-abi"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
dependencies = [
"libc",
]
[[package]]
name = "hermit-abi"
version = "0.3.1"
@@ -1020,7 +955,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01706d578d5c281058480e673ae4086a9f4710d8df1ad80a5b03e39ece5f886b"
dependencies = [
"digest 0.9.0",
"hmac",
"hmac 0.11.0",
]
[[package]]
@@ -1033,6 +968,15 @@ dependencies = [
"digest 0.9.0",
]
[[package]]
name = "hmac"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
dependencies = [
"digest 0.10.7",
]
[[package]]
name = "humantime"
version = "2.1.0"
@@ -1059,15 +1003,6 @@ dependencies = [
"unicode-normalization",
]
[[package]]
name = "inout"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
dependencies = [
"generic-array 0.14.6",
]
[[package]]
name = "instant"
version = "0.1.12"
@@ -1083,7 +1018,7 @@ version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
dependencies = [
"hermit-abi 0.3.1",
"hermit-abi",
"libc",
"windows-sys 0.48.0",
]
@@ -1123,15 +1058,14 @@ dependencies = [
[[package]]
name = "k256"
version = "0.10.4"
version = "0.11.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19c3a5e0a0b8450278feda242592512e09f61c72e018b8cd5c859482802daf2d"
checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b"
dependencies = [
"cfg-if",
"ecdsa",
"elliptic-curve",
"sec1",
"sha2",
"sha2 0.10.6",
]
[[package]]
@@ -1215,15 +1149,6 @@ version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "memoffset"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"
dependencies = [
"autocfg",
]
[[package]]
name = "mixnet-vesting-integration-tests"
version = "0.1.0"
@@ -1250,16 +1175,6 @@ dependencies = [
"libm",
]
[[package]]
name = "num_cpus"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
dependencies = [
"hermit-abi 0.2.6",
"libc",
]
[[package]]
name = "nym-coconut-bandwidth"
version = "0.1.0"
@@ -1343,10 +1258,43 @@ dependencies = [
"zeroize",
]
[[package]]
name = "nym-ephemera"
version = "0.1.0"
dependencies = [
"cosmwasm-std",
"cosmwasm-storage",
"cw-controllers",
"cw-multi-test",
"cw-storage-plus",
"cw4",
"cw4-group",
"lazy_static",
"nym-ephemera-common",
"nym-group-contract-common",
"rusty-fork",
"schemars",
"serde",
"thiserror",
]
[[package]]
name = "nym-ephemera-common"
version = "0.1.0"
dependencies = [
"cosmwasm-std",
"cw-utils",
"nym-contracts-common",
"schemars",
"serde",
]
[[package]]
name = "nym-group-contract-common"
version = "0.1.0"
dependencies = [
"cosmwasm-schema",
"cw-controllers",
"cw4",
"schemars",
"serde",
@@ -1387,7 +1335,7 @@ dependencies = [
"nym-contracts-common",
"schemars",
"serde",
"serde-json-wasm",
"serde-json-wasm 0.4.1",
"serde_repr",
"thiserror",
"time",
@@ -1397,7 +1345,9 @@ dependencies = [
name = "nym-multisig-contract-common"
version = "0.1.0"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cw-storage-plus",
"cw-utils",
"cw3",
"cw4",
@@ -1436,23 +1386,6 @@ dependencies = [
"serde",
]
[[package]]
name = "nym-outfox"
version = "0.1.0"
dependencies = [
"blake3",
"chacha20",
"chacha20poly1305",
"curve25519-dalek",
"getrandom 0.2.10",
"log",
"rand 0.7.3",
"rayon",
"sphinx-packet",
"thiserror",
"zeroize",
]
[[package]]
name = "nym-pemstore"
version = "0.3.0"
@@ -1500,7 +1433,6 @@ dependencies = [
name = "nym-sphinx-types"
version = "0.2.0"
dependencies = [
"nym-outfox",
"sphinx-packet",
"thiserror",
]
@@ -1588,13 +1520,12 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkcs8"
version = "0.8.0"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cabda3fb821068a9a4fab19a683eac3af12edf0f34b94a8be53c4972b8149d0"
checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba"
dependencies = [
"der",
"spki",
"zeroize",
]
[[package]]
@@ -1603,17 +1534,6 @@ version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
[[package]]
name = "poly1305"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf"
dependencies = [
"cpufeatures",
"opaque-debug 0.3.0",
"universal-hash",
]
[[package]]
name = "ppv-lite86"
version = "0.2.17"
@@ -1772,28 +1692,6 @@ dependencies = [
"rand_core 0.5.1",
]
[[package]]
name = "rayon"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-utils",
"num_cpus",
]
[[package]]
name = "redox_syscall"
version = "0.3.5"
@@ -1820,12 +1718,12 @@ checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c"
[[package]]
name = "rfc6979"
version = "0.1.0"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96ef608575f6392792f9ecf7890c00086591d29a83910939d430753f7c050525"
checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb"
dependencies = [
"crypto-bigint",
"hmac",
"hmac 0.12.1",
"zeroize",
]
@@ -1926,18 +1824,13 @@ dependencies = [
"syn 1.0.109",
]
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "sec1"
version = "0.2.1"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08da66b8b0965a5555b6bd6639e68ccba85e1e2506f5fbb089e93f8a04e1a2d1"
checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928"
dependencies = [
"base16ct",
"der",
"generic-array 0.14.6",
"pkcs8",
@@ -1969,6 +1862,15 @@ dependencies = [
"serde",
]
[[package]]
name = "serde-json-wasm"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16a62a1fad1e1828b24acac8f2b468971dade7b8c3c2e672bcadefefb1f8c137"
dependencies = [
"serde",
]
[[package]]
name = "serde_derive"
version = "1.0.160"
@@ -2027,12 +1929,23 @@ dependencies = [
]
[[package]]
name = "signature"
version = "1.4.0"
name = "sha2"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02658e48d89f2bec991f9a78e69cfa4c316f8d6a6c4ec12fae1aeb263d486788"
checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0"
dependencies = [
"digest 0.9.0",
"cfg-if",
"cpufeatures",
"digest 0.10.7",
]
[[package]]
name = "signature"
version = "1.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c"
dependencies = [
"digest 0.10.7",
"rand_core 0.6.4",
]
@@ -2060,20 +1973,20 @@ dependencies = [
"curve25519-dalek",
"digest 0.9.0",
"hkdf",
"hmac",
"hmac 0.11.0",
"lioness",
"log",
"rand 0.7.3",
"rand_distr",
"sha2",
"sha2 0.9.9",
"subtle 2.4.1",
]
[[package]]
name = "spki"
version = "0.5.4"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27"
checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b"
dependencies = [
"base64ct",
"der",
@@ -2242,16 +2155,6 @@ dependencies = [
"tinyvec",
]
[[package]]
name = "universal-hash"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea"
dependencies = [
"crypto-common",
"subtle 2.4.1",
]
[[package]]
name = "url"
version = "2.3.1"
+15 -13
View File
@@ -3,6 +3,7 @@ members = [
"coconut-bandwidth",
"coconut-dkg",
"coconut-test",
"ephemera",
"mixnet",
"mixnet-vesting-integration-tests",
"multisig/cw3-flex-multisig",
@@ -32,16 +33,17 @@ incremental = false
overflow-checks = true
[workspace.dependencies]
cosmwasm-crypto = "=1.0.0"
cosmwasm-derive = "=1.0.0"
cosmwasm-schema = "=1.0.0"
cosmwasm-std = "=1.0.0"
cosmwasm-storage = "=1.0.0"
cw-controllers = "=0.13.4"
cw-multi-test = "=0.13.4"
cw-storage-plus = "=0.13.4"
cw-utils = "=0.13.4"
cw2 = "=0.13.4"
cw3 = "=0.13.4"
cw3-fixed-multisig = "=0.13.4"
cw4 = "=0.13.4"
cosmwasm-crypto = "=1.2.5"
cosmwasm-derive = "=1.2.5"
cosmwasm-schema = "=1.2.5"
cosmwasm-std = "=1.2.5"
cosmwasm-storage = "=1.2.5"
cw-controllers = "=1.0.1"
cw-multi-test = "=0.16.4"
cw-storage-plus = "=1.0.1"
cw-utils = "=1.0.1"
cw2 = "=1.0.1"
cw3 = "=1.0.1"
cw3-fixed-multisig = "=1.0.1"
cw4 = "=1.0.1"
cw20 = "=1.0.1"
@@ -30,7 +30,7 @@ impl<'a> IndexList<ContractVKShare> for VkShareIndex<'a> {
pub(crate) fn vk_shares<'a>() -> IndexedMap<'a, VKShareKey<'a>, ContractVKShare, VkShareIndex<'a>> {
let indexes = VkShareIndex {
epoch_id: MultiIndex::new(
|d| d.epoch_id,
|_pk, d| d.epoch_id,
VK_SHARES_PK_NAMESPACE,
VK_SHARES_EPOCH_ID_IDX_NAMESPACE,
),
+1 -1
View File
@@ -2,9 +2,9 @@
// SPDX-License-Identifier: Apache-2.0
use cosmwasm_std::{entry_point, Addr, Coin, DepsMut, Empty, Env, Response};
use cw3_flex_multisig::state::CONFIG;
use cw_multi_test::{App, AppBuilder, Contract, ContractWrapper};
use nym_multisig_contract_common::error::ContractError;
use nym_multisig_contract_common::state::CONFIG;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
@@ -45,6 +45,8 @@ fn spend_credential_creates_proposal() {
threshold: Threshold::AbsolutePercentage {
percentage: Decimal::from_ratio(2u128, 3u128),
},
executor: None,
proposal_deposit: None,
max_voting_period: Duration::Height(1000),
coconut_bandwidth_contract_address: TEST_COCONUT_BANDWIDTH_CONTRACT_ADDRESS.to_string(),
coconut_dkg_contract_address: TEST_COCONUT_DKG_CONTRACT_ADDRESS.to_string(),
@@ -52,6 +52,8 @@ fn dkg_proposal() {
threshold: Threshold::AbsolutePercentage {
percentage: Decimal::from_ratio(1u128, 1u128),
},
executor: None,
proposal_deposit: None,
max_voting_period: Duration::Time(1000),
coconut_bandwidth_contract_address: TEST_COCONUT_BANDWIDTH_CONTRACT_ADDRESS.to_string(),
coconut_dkg_contract_address: TEST_COCONUT_DKG_CONTRACT_ADDRESS.to_string(),
+29
View File
@@ -0,0 +1,29 @@
[package]
name = "nym-ephemera"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
crate-type = ["cdylib", "rlib"]
[dependencies]
nym-ephemera-common = { path = "../../common/cosmwasm-smart-contracts/ephemera" }
cosmwasm-std = { workspace = true }
cosmwasm-storage = { workspace = true }
cw-storage-plus = { workspace = true }
cw-controllers = { workspace = true }
cw4 = { workspace = true }
schemars = "0.8"
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
thiserror = "1.0.23"
[dev-dependencies]
cw-multi-test = { workspace = true }
cw4-group = { path = "../multisig/cw4-group" }
nym-group-contract-common = { path = "../../common/cosmwasm-smart-contracts/group-contract" }
lazy_static = "1.4"
rusty-fork = "0.3"
+68
View File
@@ -0,0 +1,68 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::error::ContractError;
use crate::peers::queries::query_peers_paged;
use crate::peers::transactions::try_register_peer;
use crate::state::{State, STATE};
use cosmwasm_std::{
entry_point, to_binary, Deps, DepsMut, Env, MessageInfo, QueryResponse, Response,
};
use cw4::Cw4Contract;
use nym_ephemera_common::msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg};
/// Instantiate the contract.
///
/// `deps` contains Storage, API and Querier
/// `env` contains block, message and contract info
/// `msg` is the contract initialization message, sort of like a constructor call.
#[entry_point]
pub fn instantiate(
deps: DepsMut<'_>,
_env: Env,
_info: MessageInfo,
msg: InstantiateMsg,
) -> Result<Response, ContractError> {
let group_addr = Cw4Contract(deps.api.addr_validate(&msg.group_addr).map_err(|_| {
ContractError::InvalidGroup {
addr: msg.group_addr.clone(),
}
})?);
let state = State {
group_addr,
mix_denom: msg.mix_denom,
};
STATE.save(deps.storage, &state)?;
Ok(Response::default())
}
/// Handle an incoming message
#[entry_point]
pub fn execute(
deps: DepsMut<'_>,
_env: Env,
info: MessageInfo,
msg: ExecuteMsg,
) -> Result<Response, ContractError> {
match msg {
ExecuteMsg::RegisterPeer { peer_info } => try_register_peer(deps, info, peer_info),
}
}
#[entry_point]
pub fn query(deps: Deps<'_>, _env: Env, msg: QueryMsg) -> Result<QueryResponse, ContractError> {
let response = match msg {
QueryMsg::GetPeers { limit, start_after } => {
to_binary(&query_peers_paged(deps, start_after, limit)?)?
}
};
Ok(response)
}
#[entry_point]
pub fn migrate(_deps: DepsMut<'_>, _env: Env, _msg: MigrateMsg) -> Result<Response, ContractError> {
Ok(Default::default())
}
+18
View File
@@ -0,0 +1,18 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use cosmwasm_std::StdError;
use thiserror::Error;
/// Custom errors for contract failure conditions.
#[derive(Error, Debug, PartialEq)]
pub enum ContractError {
#[error(transparent)]
Std(#[from] StdError),
#[error("Group contract invalid address '{addr}'")]
InvalidGroup { addr: String },
#[error("This sender is already registered")]
AlreadyRegistered,
}
+7
View File
@@ -0,0 +1,7 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
pub mod contract;
pub mod error;
mod peers;
mod state;
+6
View File
@@ -0,0 +1,6 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
pub mod queries;
pub mod storage;
pub mod transactions;
+35
View File
@@ -0,0 +1,35 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::peers::storage::{PEERS, PEERS_PAGE_DEFAULT_LIMIT, PEERS_PAGE_MAX_LIMIT};
use cosmwasm_std::{Deps, Order, StdResult};
use cw_storage_plus::Bound;
use nym_ephemera_common::peers::PagedPeerResponse;
pub fn query_peers_paged(
deps: Deps<'_>,
start_after: Option<String>,
limit: Option<u32>,
) -> StdResult<PagedPeerResponse> {
let limit = limit
.unwrap_or(PEERS_PAGE_DEFAULT_LIMIT)
.min(PEERS_PAGE_MAX_LIMIT) as usize;
let addr = start_after
.map(|addr| deps.api.addr_validate(&addr))
.transpose()?;
let start = addr.map(Bound::exclusive);
let peers = PEERS
.range(deps.storage, start, None, Order::Ascending)
.take(limit)
.map(|res| res.map(|item| item.1))
.collect::<StdResult<Vec<_>>>()?;
let start_next_after = peers
.last()
.map(|peer_info| peer_info.cosmos_address.clone());
Ok(PagedPeerResponse::new(peers, limit, start_next_after))
}
+11
View File
@@ -0,0 +1,11 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use cosmwasm_std::Addr;
use cw_storage_plus::Map;
use nym_ephemera_common::types::JsonPeerInfo;
pub(crate) const PEERS_PAGE_MAX_LIMIT: u32 = 75;
pub(crate) const PEERS_PAGE_DEFAULT_LIMIT: u32 = 50;
pub(crate) const PEERS: Map<'_, Addr, JsonPeerInfo> = Map::new("prs");
@@ -0,0 +1,20 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::error::ContractError;
use crate::peers::storage::PEERS;
use cosmwasm_std::{DepsMut, MessageInfo, Response};
use nym_ephemera_common::types::JsonPeerInfo;
pub fn try_register_peer(
deps: DepsMut<'_>,
info: MessageInfo,
peer_info: JsonPeerInfo,
) -> Result<Response, ContractError> {
if PEERS.may_load(deps.storage, info.sender.clone())?.is_none() {
PEERS.save(deps.storage, info.sender, &peer_info)?;
} else {
return Err(ContractError::AlreadyRegistered);
}
Ok(Default::default())
}
+16
View File
@@ -0,0 +1,16 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use cw4::Cw4Contract;
use cw_storage_plus::Item;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
// unique items
pub const STATE: Item<State> = Item::new("state");
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
pub struct State {
pub mix_denom: String,
pub group_addr: Cw4Contract,
}
@@ -22,7 +22,7 @@ nym-mixnet-contract = { path = "../mixnet" }
nym-vesting-contract = { path = "../vesting" }
# other local dependencies
nym-crypto = { path = "../../common/crypto", features = ["asymmetric", "rand"] }
nym-crypto = { path = "../../common/crypto", features = ["asymmetric", "rand", "wasm-contract"] }
# external dependencies
rand_chacha = "0.2"
+1 -1
View File
@@ -42,7 +42,7 @@ semver = { version = "1.0.16", default-features = false }
[dev-dependencies]
cosmwasm-schema = { workspace = true }
rand_chacha = "0.2"
nym-crypto = { path = "../../common/crypto", features = ["asymmetric", "rand"] }
nym-crypto = { path = "../../common/crypto", features = ["asymmetric", "rand", "wasm-contract"] }
[build-dependencies]
vergen = { version = "=7.4.3", default-features = false, features = ["build", "git", "rustc"] }
+1 -1
View File
@@ -520,7 +520,7 @@ mod tests {
.delegations
.iter()
.filter(|d| d.proxy.is_some())
.all(|d| d.proxy.as_ref().unwrap() == &vesting_contract));
.all(|d| d.proxy.as_ref().unwrap() == vesting_contract));
// now make sure that if we do it in paged manner, we'll get exactly the same result
let per_page = Some(15);
+2 -2
View File
@@ -27,12 +27,12 @@ impl<'a> IndexList<Delegation> for DelegationIndex<'a> {
pub(crate) fn delegations<'a>() -> IndexedMap<'a, PrimaryKey, Delegation, DelegationIndex<'a>> {
let indexes = DelegationIndex {
owner: MultiIndex::new(
|d| d.owner.clone(),
|_pk, d| d.owner.clone(),
DELEGATION_PK_NAMESPACE,
DELEGATION_OWNER_IDX_NAMESPACE,
),
mixnode: MultiIndex::new(
|d| d.mix_id,
|_pk, d| d.mix_id,
DELEGATION_PK_NAMESPACE,
DELEGATION_MIXNODE_IDX_NAMESPACE,
),
+2 -2
View File
@@ -39,12 +39,12 @@ pub(crate) fn unbonded_mixnodes<'a>(
) -> IndexedMap<'a, MixId, UnbondedMixnode, UnbondedMixnodeIndex<'a>> {
let indexes = UnbondedMixnodeIndex {
owner: MultiIndex::new(
|d| d.owner.clone(),
|_pk, d| d.owner.clone(),
UNBONDED_MIXNODES_PK_NAMESPACE,
UNBONDED_MIXNODES_OWNER_IDX_NAMESPACE,
),
identity_key: MultiIndex::new(
|d| d.identity_key.clone(),
|_pk, d| d.identity_key.clone(),
UNBONDED_MIXNODES_PK_NAMESPACE,
UNBONDED_MIXNODES_IDENTITY_IDX_NAMESPACE,
),
+2 -2
View File
@@ -185,7 +185,7 @@ pub(crate) fn _try_withdraw_operator_reward(
// we can only attempt to send the message to the vesting contract if the proxy IS the vesting contract
// otherwise, we don't care
let vesting_contract = mixnet_params_storage::vesting_contract_address(deps.storage)?;
if proxy == &vesting_contract {
if proxy == vesting_contract {
let msg = VestingContractExecuteMsg::TrackReward {
amount: reward.clone(),
address: owner.clone().into_string(),
@@ -271,7 +271,7 @@ pub(crate) fn _try_withdraw_delegator_reward(
// we can only attempt to send the message to the vesting contract if the proxy IS the vesting contract
// otherwise, we don't care
let vesting_contract = mixnet_params_storage::vesting_contract_address(deps.storage)?;
if proxy == &vesting_contract {
if proxy == vesting_contract {
let msg = VestingContractExecuteMsg::TrackReward {
amount: reward.clone(),
address: owner.clone().into_string(),
+2 -2
View File
@@ -298,7 +298,7 @@ pub(crate) fn ensure_is_authorized(
sender: &Addr,
storage: &dyn Storage,
) -> Result<(), MixnetContractError> {
if sender != &crate::mixnet_contract_settings::storage::rewarding_validator_address(storage)? {
if sender != crate::mixnet_contract_settings::storage::rewarding_validator_address(storage)? {
return Err(MixnetContractError::Unauthorized);
}
Ok(())
@@ -309,7 +309,7 @@ pub(crate) fn ensure_can_advance_epoch(
storage: &dyn Storage,
) -> Result<EpochStatus, MixnetContractError> {
let epoch_status = crate::interval::storage::current_epoch_status(storage)?;
if sender != &epoch_status.being_advanced_by {
if sender != epoch_status.being_advanced_by {
// well, we know we're going to throw an error now,
// but we might as well also check if we're even a validator
// to return a possibly better error message
@@ -1,8 +1,8 @@
[package]
name = "cw3-flex-multisig"
version = "0.13.1"
version = "1.0.0"
authors = ["Ethan Frey <ethanfrey@users.noreply.github.com>"]
edition = "2018"
edition = "2021"
description = "Implementing cw3 with multiple voting patterns and dynamic groups"
license = "Apache-2.0"
repository = "https://github.com/CosmWasm/cw-plus"
@@ -13,6 +13,7 @@ documentation = "https://docs.cosmwasm.com"
crate-type = ["cdylib", "rlib"]
[features]
backtraces = ["cosmwasm-std/backtraces"]
# use library feature to disable all instantiate/execute/query exports
library = []
@@ -22,15 +23,15 @@ cw2 = { workspace = true }
cw3 = { workspace = true }
cw3-fixed-multisig = { workspace = true, features = ["library"] }
cw4 = { workspace = true }
cw20 = { workspace = true }
cw-storage-plus = { workspace = true }
cosmwasm-std = { workspace = true }
schemars = "0.8.1"
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
nym-group-contract-common = { path = "../../../common/cosmwasm-smart-contracts/group-contract" }
nym-multisig-contract-common = { path= "../../../common/cosmwasm-smart-contracts/multisig-contract" }
[dev-dependencies]
cosmwasm-schema = { version = "1.0.0" }
cw4-group = { path = "../cw4-group", version = "0.13.4" }
cw4-group = { path = "../cw4-group", version = "1.0.0" }
cw-multi-test = { workspace = true }
cw20-base = "1.0.0"
File diff suppressed because it is too large Load Diff
@@ -1,2 +1,25 @@
/*!
This builds on [`cw3_fixed_multisig`] with a more
powerful implementation of the [cw3 spec](https://github.com/CosmWasm/cw-plus/blob/main/packages/cw3/README.md).
It is a multisig contract that is backed by a
[cw4 (group)](https://github.com/CosmWasm/cw-plus/blob/main/packages/cw4/README.md) contract, which independently
maintains the voter set.
This provides 2 main advantages:
* You can create two different multisigs with different voting thresholds
backed by the same group. Thus, you can have a 50% vote, and a 67% vote
that always use the same voter set, but can take other actions.
* TODO: It allows dynamic multisig groups.
In addition to the dynamic voting set, the main difference with the native
Cosmos SDK multisig, is that it aggregates the signatures on chain, with
visible proposals (like `x/gov` in the Cosmos SDK), rather than requiring
signers to share signatures off chain.
For more information on this contract, please check out the
[README](https://github.com/CosmWasm/cw-plus/blob/main/contracts/cw3-flex-multisig/README.md).
*/
pub mod contract;
pub mod state;
@@ -1,20 +0,0 @@
use cosmwasm_std::Addr;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use cw4::Cw4Contract;
use cw_storage_plus::Item;
use cw_utils::{Duration, Threshold};
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
pub struct Config {
pub threshold: Threshold,
pub max_voting_period: Duration,
// Total weight and voters are queried from this contract
pub group_addr: Cw4Contract,
pub coconut_bandwidth_addr: Addr,
pub coconut_dkg_addr: Addr,
}
// unique items
pub const CONFIG: Item<Config> = Item::new("config");
+3 -3
View File
@@ -1,5 +1,5 @@
[alias]
wasm = "build --release --target wasm32-unknown-unknown"
wasm-debug = "build --target wasm32-unknown-unknown"
wasm = "build --release --lib --target wasm32-unknown-unknown"
wasm-debug = "build --lib --target wasm32-unknown-unknown"
unit-test = "test --lib"
schema = "run --example schema"
schema = "run --bin schema"
+5 -5
View File
@@ -1,8 +1,8 @@
[package]
name = "cw4-group"
version = "0.13.4"
version = "1.0.0"
authors = ["Ethan Frey <ethanfrey@users.noreply.github.com>"]
edition = "2018"
edition = "2021"
description = "Simple cw4 implementation of group membership controlled by admin "
license = "Apache-2.0"
repository = "https://github.com/CosmWasm/cw-plus"
@@ -20,6 +20,8 @@ exclude = [
crate-type = ["cdylib", "rlib"]
[features]
# for more explicit tests, cargo test --features=backtraces
backtraces = ["cosmwasm-std/backtraces"]
# use library feature to disable all instantiate/execute/query exports
library = []
@@ -31,10 +33,8 @@ cw2 = { workspace = true }
cw4 = { workspace = true }
cw-controllers = { workspace = true }
cw-storage-plus = { workspace = true }
cosmwasm-schema = { workspace = true }
cosmwasm-std = { workspace = true }
schemars = "0.8.1"
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
thiserror = { version = "1.0.23" }
[dev-dependencies]
cosmwasm-schema = { workspace = true }
+32 -367
View File
@@ -2,7 +2,7 @@
use cosmwasm_std::entry_point;
use cosmwasm_std::{
attr, to_binary, Addr, Binary, Deps, DepsMut, Env, MessageInfo, Order, Response, StdResult,
SubMsg,
SubMsg, Uint64,
};
use cw2::set_contract_version;
use cw4::{
@@ -13,6 +13,7 @@ use cw_storage_plus::Bound;
use cw_utils::maybe_addr;
use crate::error::ContractError;
use crate::helpers::validate_unique_members;
use crate::state::{ADMIN, HOOKS, MEMBERS, TOTAL};
use nym_group_contract_common::msg::{ExecuteMsg, InstantiateMsg, QueryMsg};
@@ -39,21 +40,25 @@ pub fn instantiate(
pub fn create(
mut deps: DepsMut,
admin: Option<String>,
members: Vec<Member>,
mut members: Vec<Member>,
height: u64,
) -> Result<(), ContractError> {
validate_unique_members(&mut members)?;
let members = members; // let go of mutability
let admin_addr = admin
.map(|admin| deps.api.addr_validate(&admin))
.transpose()?;
ADMIN.set(deps.branch(), admin_addr)?;
let mut total = 0u64;
let mut total = Uint64::zero();
for member in members.into_iter() {
total += member.weight;
let member_weight = Uint64::from(member.weight);
total = total.checked_add(member_weight)?;
let member_addr = deps.api.addr_validate(&member.addr)?;
MEMBERS.save(deps.storage, &member_addr, &member.weight, height)?;
MEMBERS.save(deps.storage, &member_addr, &member_weight.u64(), height)?;
}
TOTAL.save(deps.storage, &total)?;
TOTAL.save(deps.storage, &total.u64(), height)?;
Ok(())
}
@@ -115,20 +120,23 @@ pub fn update_members(
deps: DepsMut,
height: u64,
sender: Addr,
to_add: Vec<Member>,
mut to_add: Vec<Member>,
to_remove: Vec<String>,
) -> Result<MemberChangedHookMsg, ContractError> {
validate_unique_members(&mut to_add)?;
let to_add = to_add; // let go of mutability
ADMIN.assert_admin(deps.as_ref(), &sender)?;
let mut total = TOTAL.load(deps.storage)?;
let mut total = Uint64::from(TOTAL.load(deps.storage)?);
let mut diffs: Vec<MemberDiff> = vec![];
// add all new members and update total
for add in to_add.into_iter() {
let add_addr = deps.api.addr_validate(&add.addr)?;
MEMBERS.update(deps.storage, &add_addr, height, |old| -> StdResult<_> {
total -= old.unwrap_or_default();
total += add.weight;
total = total.checked_sub(Uint64::from(old.unwrap_or_default()))?;
total = total.checked_add(Uint64::from(add.weight))?;
diffs.push(MemberDiff::new(add.addr, old, Some(add.weight)));
Ok(add.weight)
})?;
@@ -140,12 +148,12 @@ pub fn update_members(
// Only process this if they were actually in the list before
if let Some(weight) = old {
diffs.push(MemberDiff::new(remove, Some(weight), None));
total -= weight;
total = total.checked_sub(Uint64::from(weight))?;
MEMBERS.remove(deps.storage, &remove_addr, height)?;
}
}
TOTAL.save(deps.storage, &total)?;
TOTAL.save(deps.storage, &total.u64(), height)?;
Ok(MemberChangedHookMsg { diffs })
}
@@ -157,20 +165,26 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
at_height: height,
} => to_binary(&query_member(deps, addr, height)?),
QueryMsg::ListMembers { start_after, limit } => {
to_binary(&list_members(deps, start_after, limit)?)
to_binary(&query_list_members(deps, start_after, limit)?)
}
QueryMsg::TotalWeight { at_height: height } => {
to_binary(&query_total_weight(deps, height)?)
}
QueryMsg::TotalWeight {} => to_binary(&query_total_weight(deps)?),
QueryMsg::Admin {} => to_binary(&ADMIN.query_admin(deps)?),
QueryMsg::Hooks {} => to_binary(&HOOKS.query_hooks(deps)?),
}
}
fn query_total_weight(deps: Deps) -> StdResult<TotalWeightResponse> {
let weight = TOTAL.load(deps.storage)?;
pub fn query_total_weight(deps: Deps, height: Option<u64>) -> StdResult<TotalWeightResponse> {
let weight = match height {
Some(h) => TOTAL.may_load_at_height(deps.storage, h),
None => TOTAL.may_load(deps.storage),
}?
.unwrap_or_default();
Ok(TotalWeightResponse { weight })
}
fn query_member(deps: Deps, addr: String, height: Option<u64>) -> StdResult<MemberResponse> {
pub fn query_member(deps: Deps, addr: String, height: Option<u64>) -> StdResult<MemberResponse> {
let addr = deps.api.addr_validate(&addr)?;
let weight = match height {
Some(h) => MEMBERS.may_load_at_height(deps.storage, &addr, h),
@@ -183,7 +197,7 @@ fn query_member(deps: Deps, addr: String, height: Option<u64>) -> StdResult<Memb
const MAX_LIMIT: u32 = 30;
const DEFAULT_LIMIT: u32 = 10;
fn list_members(
pub fn query_list_members(
deps: Deps,
start_after: Option<String>,
limit: Option<u32>,
@@ -205,352 +219,3 @@ fn list_members(
Ok(MemberListResponse { members })
}
#[cfg(test)]
mod tests {
use super::*;
use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info};
use cosmwasm_std::{from_slice, Api, OwnedDeps, Querier, Storage};
use cw4::{member_key, TOTAL_KEY};
use cw_controllers::{AdminError, HookError};
const INIT_ADMIN: &str = "juan";
const USER1: &str = "somebody";
const USER2: &str = "else";
const USER3: &str = "funny";
fn do_instantiate(deps: DepsMut) {
let msg = InstantiateMsg {
admin: Some(INIT_ADMIN.into()),
members: vec![
Member {
addr: USER1.into(),
weight: 11,
},
Member {
addr: USER2.into(),
weight: 6,
},
],
};
let info = mock_info("creator", &[]);
instantiate(deps, mock_env(), info, msg).unwrap();
}
#[test]
fn proper_instantiation() {
let mut deps = mock_dependencies();
do_instantiate(deps.as_mut());
// it worked, let's query the state
let res = ADMIN.query_admin(deps.as_ref()).unwrap();
assert_eq!(Some(INIT_ADMIN.into()), res.admin);
let res = query_total_weight(deps.as_ref()).unwrap();
assert_eq!(17, res.weight);
}
#[test]
fn try_member_queries() {
let mut deps = mock_dependencies();
do_instantiate(deps.as_mut());
let member1 = query_member(deps.as_ref(), USER1.into(), None).unwrap();
assert_eq!(member1.weight, Some(11));
let member2 = query_member(deps.as_ref(), USER2.into(), None).unwrap();
assert_eq!(member2.weight, Some(6));
let member3 = query_member(deps.as_ref(), USER3.into(), None).unwrap();
assert_eq!(member3.weight, None);
let members = list_members(deps.as_ref(), None, None).unwrap();
assert_eq!(members.members.len(), 2);
// TODO: assert the set is proper
}
fn assert_users<S: Storage, A: Api, Q: Querier>(
deps: &OwnedDeps<S, A, Q>,
user1_weight: Option<u64>,
user2_weight: Option<u64>,
user3_weight: Option<u64>,
height: Option<u64>,
) {
let member1 = query_member(deps.as_ref(), USER1.into(), height).unwrap();
assert_eq!(member1.weight, user1_weight);
let member2 = query_member(deps.as_ref(), USER2.into(), height).unwrap();
assert_eq!(member2.weight, user2_weight);
let member3 = query_member(deps.as_ref(), USER3.into(), height).unwrap();
assert_eq!(member3.weight, user3_weight);
// this is only valid if we are not doing a historical query
if height.is_none() {
// compute expected metrics
let weights = vec![user1_weight, user2_weight, user3_weight];
let sum: u64 = weights.iter().map(|x| x.unwrap_or_default()).sum();
let count = weights.iter().filter(|x| x.is_some()).count();
// TODO: more detailed compare?
let members = list_members(deps.as_ref(), None, None).unwrap();
assert_eq!(count, members.members.len());
let total = query_total_weight(deps.as_ref()).unwrap();
assert_eq!(sum, total.weight); // 17 - 11 + 15 = 21
}
}
#[test]
fn add_new_remove_old_member() {
let mut deps = mock_dependencies();
do_instantiate(deps.as_mut());
// add a new one and remove existing one
let add = vec![Member {
addr: USER3.into(),
weight: 15,
}];
let remove = vec![USER1.into()];
// non-admin cannot update
let height = mock_env().block.height;
let err = update_members(
deps.as_mut(),
height + 5,
Addr::unchecked(USER1),
add.clone(),
remove.clone(),
)
.unwrap_err();
assert_eq!(err, AdminError::NotAdmin {}.into());
// Test the values from instantiate
assert_users(&deps, Some(11), Some(6), None, None);
// Note all values were set at height, the beginning of that block was all None
assert_users(&deps, None, None, None, Some(height));
// This will get us the values at the start of the block after instantiate (expected initial values)
assert_users(&deps, Some(11), Some(6), None, Some(height + 1));
// admin updates properly
update_members(
deps.as_mut(),
height + 10,
Addr::unchecked(INIT_ADMIN),
add,
remove,
)
.unwrap();
// updated properly
assert_users(&deps, None, Some(6), Some(15), None);
// snapshot still shows old value
assert_users(&deps, Some(11), Some(6), None, Some(height + 1));
}
#[test]
fn add_old_remove_new_member() {
// add will over-write and remove have no effect
let mut deps = mock_dependencies();
do_instantiate(deps.as_mut());
// add a new one and remove existing one
let add = vec![Member {
addr: USER1.into(),
weight: 4,
}];
let remove = vec![USER3.into()];
// admin updates properly
let height = mock_env().block.height;
update_members(
deps.as_mut(),
height,
Addr::unchecked(INIT_ADMIN),
add,
remove,
)
.unwrap();
assert_users(&deps, Some(4), Some(6), None, None);
}
#[test]
fn add_and_remove_same_member() {
// add will over-write and remove have no effect
let mut deps = mock_dependencies();
do_instantiate(deps.as_mut());
// USER1 is updated and remove in the same call, we should remove this an add member3
let add = vec![
Member {
addr: USER1.into(),
weight: 20,
},
Member {
addr: USER3.into(),
weight: 5,
},
];
let remove = vec![USER1.into()];
// admin updates properly
let height = mock_env().block.height;
update_members(
deps.as_mut(),
height,
Addr::unchecked(INIT_ADMIN),
add,
remove,
)
.unwrap();
assert_users(&deps, None, Some(6), Some(5), None);
}
#[test]
fn add_remove_hooks() {
// add will over-write and remove have no effect
let mut deps = mock_dependencies();
do_instantiate(deps.as_mut());
let hooks = HOOKS.query_hooks(deps.as_ref()).unwrap();
assert!(hooks.hooks.is_empty());
let contract1 = String::from("hook1");
let contract2 = String::from("hook2");
let add_msg = ExecuteMsg::AddHook {
addr: contract1.clone(),
};
// non-admin cannot add hook
let user_info = mock_info(USER1, &[]);
let err = execute(
deps.as_mut(),
mock_env(),
user_info.clone(),
add_msg.clone(),
)
.unwrap_err();
assert_eq!(err, HookError::Admin(AdminError::NotAdmin {}).into());
// admin can add it, and it appears in the query
let admin_info = mock_info(INIT_ADMIN, &[]);
let _ = execute(
deps.as_mut(),
mock_env(),
admin_info.clone(),
add_msg.clone(),
)
.unwrap();
let hooks = HOOKS.query_hooks(deps.as_ref()).unwrap();
assert_eq!(hooks.hooks, vec![contract1.clone()]);
// cannot remove a non-registered contract
let remove_msg = ExecuteMsg::RemoveHook {
addr: contract2.clone(),
};
let err = execute(deps.as_mut(), mock_env(), admin_info.clone(), remove_msg).unwrap_err();
assert_eq!(err, HookError::HookNotRegistered {}.into());
// add second contract
let add_msg2 = ExecuteMsg::AddHook {
addr: contract2.clone(),
};
let _ = execute(deps.as_mut(), mock_env(), admin_info.clone(), add_msg2).unwrap();
let hooks = HOOKS.query_hooks(deps.as_ref()).unwrap();
assert_eq!(hooks.hooks, vec![contract1.clone(), contract2.clone()]);
// cannot re-add an existing contract
let err = execute(deps.as_mut(), mock_env(), admin_info.clone(), add_msg).unwrap_err();
assert_eq!(err, HookError::HookAlreadyRegistered {}.into());
// non-admin cannot remove
let remove_msg = ExecuteMsg::RemoveHook { addr: contract1 };
let err = execute(deps.as_mut(), mock_env(), user_info, remove_msg.clone()).unwrap_err();
assert_eq!(err, HookError::Admin(AdminError::NotAdmin {}).into());
// remove the original
let _ = execute(deps.as_mut(), mock_env(), admin_info, remove_msg).unwrap();
let hooks = HOOKS.query_hooks(deps.as_ref()).unwrap();
assert_eq!(hooks.hooks, vec![contract2]);
}
#[test]
fn hooks_fire() {
let mut deps = mock_dependencies();
do_instantiate(deps.as_mut());
let hooks = HOOKS.query_hooks(deps.as_ref()).unwrap();
assert!(hooks.hooks.is_empty());
let contract1 = String::from("hook1");
let contract2 = String::from("hook2");
// register 2 hooks
let admin_info = mock_info(INIT_ADMIN, &[]);
let add_msg = ExecuteMsg::AddHook {
addr: contract1.clone(),
};
let add_msg2 = ExecuteMsg::AddHook {
addr: contract2.clone(),
};
for msg in vec![add_msg, add_msg2] {
let _ = execute(deps.as_mut(), mock_env(), admin_info.clone(), msg).unwrap();
}
// make some changes - add 3, remove 2, and update 1
// USER1 is updated and remove in the same call, we should remove this an add member3
let add = vec![
Member {
addr: USER1.into(),
weight: 20,
},
Member {
addr: USER3.into(),
weight: 5,
},
];
let remove = vec![USER2.into()];
let msg = ExecuteMsg::UpdateMembers { remove, add };
// admin updates properly
assert_users(&deps, Some(11), Some(6), None, None);
let res = execute(deps.as_mut(), mock_env(), admin_info, msg).unwrap();
assert_users(&deps, Some(20), None, Some(5), None);
// ensure 2 messages for the 2 hooks
assert_eq!(res.messages.len(), 2);
// same order as in the message (adds first, then remove)
let diffs = vec![
MemberDiff::new(USER1, Some(11), Some(20)),
MemberDiff::new(USER3, None, Some(5)),
MemberDiff::new(USER2, Some(6), None),
];
let hook_msg = MemberChangedHookMsg { diffs };
let msg1 = SubMsg::new(hook_msg.clone().into_cosmos_msg(contract1).unwrap());
let msg2 = SubMsg::new(hook_msg.into_cosmos_msg(contract2).unwrap());
assert_eq!(res.messages, vec![msg1, msg2]);
}
#[test]
fn raw_queries_work() {
// add will over-write and remove have no effect
let mut deps = mock_dependencies();
do_instantiate(deps.as_mut());
// get total from raw key
let total_raw = deps.storage.get(TOTAL_KEY.as_bytes()).unwrap();
let total: u64 = from_slice(&total_raw).unwrap();
assert_eq!(17, total);
// get member votes from raw key
let member2_raw = deps.storage.get(&member_key(USER2)).unwrap();
let member2: u64 = from_slice(&member2_raw).unwrap();
assert_eq!(6, member2);
// and execute misses
let member3_raw = deps.storage.get(&member_key(USER3));
assert_eq!(None, member3_raw);
}
}
+10 -4
View File
@@ -1,19 +1,25 @@
use cosmwasm_std::StdError;
use cosmwasm_std::{OverflowError, StdError};
use thiserror::Error;
use cw_controllers::{AdminError, HookError};
#[derive(Error, Debug, PartialEq)]
pub enum ContractError {
#[error(transparent)]
#[error("{0}")]
Std(#[from] StdError),
#[error(transparent)]
#[error("{0}")]
Hook(#[from] HookError),
#[error(transparent)]
#[error("{0}")]
Admin(#[from] AdminError),
#[error("{0}")]
Overflow(#[from] OverflowError),
#[error("Unauthorized")]
Unauthorized {},
#[error("Message contained duplicate member: {member}")]
DuplicateMember { member: String },
}
+17 -3
View File
@@ -1,17 +1,17 @@
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::ops::Deref;
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{to_binary, Addr, CosmosMsg, StdResult, WasmMsg};
use cw4::{Cw4Contract, Member};
use crate::ContractError;
use nym_group_contract_common::msg::ExecuteMsg;
/// Cw4GroupContract is a wrapper around Cw4Contract that provides a lot of helpers
/// for working with cw4-group contracts.
///
/// It extends Cw4Contract to add the extra calls from cw4-group.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[cw_serde]
pub struct Cw4GroupContract(pub Cw4Contract);
impl Deref for Cw4GroupContract {
@@ -41,3 +41,17 @@ impl Cw4GroupContract {
self.encode_msg(msg)
}
}
/// Sorts the slice and verifies all member addresses are unique.
pub fn validate_unique_members(members: &mut [Member]) -> Result<(), ContractError> {
members.sort_by(|a, b| a.addr.cmp(&b.addr));
for (a, b) in members.iter().zip(members.iter().skip(1)) {
if a.addr == b.addr {
return Err(ContractError::DuplicateMember {
member: a.addr.clone(),
});
}
}
Ok(())
}
+19
View File
@@ -1,6 +1,25 @@
/*!
This is a basic implementation of the [cw4 spec](https://github.com/CosmWasm/cw-plus/blob/main/packages/cw4/README.md).
It fulfills all elements of the spec, including the raw query lookups,
and it designed to be used as a backing storage for
[cw3 compliant contracts](https://github.com/CosmWasm/cw-plus/blob/main/packages/cw3/README.md).
It stores a set of members along with an admin, and allows the admin to
update the state. Raw queries (intended for cross-contract queries)
can check a given member address and the total weight. Smart queries (designed
for client API) can do the same, and also query the admin address as well as
paginate over all members.
For more information on this contract, please check out the
[README](https://github.com/CosmWasm/cw-plus/blob/main/contracts/cw4-group/README.md).
*/
pub mod contract;
pub mod error;
pub mod helpers;
pub mod state;
pub use crate::error::ContractError;
#[cfg(test)]
mod tests;
+16 -8
View File
@@ -1,16 +1,24 @@
use cosmwasm_std::Addr;
use cw4::TOTAL_KEY;
use cw4::{
MEMBERS_CHANGELOG, MEMBERS_CHECKPOINTS, MEMBERS_KEY, TOTAL_KEY, TOTAL_KEY_CHANGELOG,
TOTAL_KEY_CHECKPOINTS,
};
use cw_controllers::{Admin, Hooks};
use cw_storage_plus::{Item, SnapshotMap, Strategy};
use cw_storage_plus::{SnapshotItem, SnapshotMap, Strategy};
pub const ADMIN: Admin = Admin::new("admin");
pub const HOOKS: Hooks = Hooks::new("cw4-hooks");
pub const TOTAL: Item<u64> = Item::new(TOTAL_KEY);
pub const MEMBERS: SnapshotMap<&Addr, u64> = SnapshotMap::new(
cw4::MEMBERS_KEY,
cw4::MEMBERS_CHECKPOINTS,
cw4::MEMBERS_CHANGELOG,
pub const TOTAL: SnapshotItem<u64> = SnapshotItem::new(
TOTAL_KEY,
TOTAL_KEY_CHECKPOINTS,
TOTAL_KEY_CHANGELOG,
Strategy::EveryBlock,
);
pub const MEMBERS: SnapshotMap<&Addr, u64> = SnapshotMap::new(
MEMBERS_KEY,
MEMBERS_CHECKPOINTS,
MEMBERS_CHANGELOG,
Strategy::EveryBlock,
);
+439
View File
@@ -0,0 +1,439 @@
use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info};
use cosmwasm_std::{from_slice, Addr, Api, DepsMut, OwnedDeps, Querier, Storage, SubMsg};
use cw4::{member_key, Member, MemberChangedHookMsg, MemberDiff, TOTAL_KEY};
use cw_controllers::{AdminError, HookError};
use crate::contract::{
execute, instantiate, query_list_members, query_member, query_total_weight, update_members,
};
use crate::state::{ADMIN, HOOKS};
use crate::ContractError;
use nym_group_contract_common::msg::{ExecuteMsg, InstantiateMsg};
const INIT_ADMIN: &str = "juan";
const USER1: &str = "somebody";
const USER2: &str = "else";
const USER3: &str = "funny";
fn set_up(deps: DepsMut) {
let msg = InstantiateMsg {
admin: Some(INIT_ADMIN.into()),
members: vec![
Member {
addr: USER1.into(),
weight: 11,
},
Member {
addr: USER2.into(),
weight: 6,
},
],
};
let info = mock_info("creator", &[]);
instantiate(deps, mock_env(), info, msg).unwrap();
}
#[test]
fn proper_instantiation() {
let mut deps = mock_dependencies();
set_up(deps.as_mut());
// it worked, let's query the state
let res = ADMIN.query_admin(deps.as_ref()).unwrap();
assert_eq!(Some(INIT_ADMIN.into()), res.admin);
let res = query_total_weight(deps.as_ref(), None).unwrap();
assert_eq!(17, res.weight);
}
#[test]
fn try_member_queries() {
let mut deps = mock_dependencies();
set_up(deps.as_mut());
let member1 = query_member(deps.as_ref(), USER1.into(), None).unwrap();
assert_eq!(member1.weight, Some(11));
let member2 = query_member(deps.as_ref(), USER2.into(), None).unwrap();
assert_eq!(member2.weight, Some(6));
let member3 = query_member(deps.as_ref(), USER3.into(), None).unwrap();
assert_eq!(member3.weight, None);
let members = query_list_members(deps.as_ref(), None, None).unwrap();
assert_eq!(members.members.len(), 2);
// TODO: assert the set is proper
}
#[test]
fn duplicate_members_instantiation() {
let mut deps = mock_dependencies();
let msg = InstantiateMsg {
admin: Some(INIT_ADMIN.into()),
members: vec![
Member {
addr: USER1.into(),
weight: 5,
},
Member {
addr: USER2.into(),
weight: 6,
},
Member {
addr: USER1.into(),
weight: 6,
},
],
};
let info = mock_info("creator", &[]);
let err = instantiate(deps.as_mut(), mock_env(), info, msg).unwrap_err();
assert_eq!(
err,
ContractError::DuplicateMember {
member: USER1.to_string()
}
);
}
#[test]
fn duplicate_members_execution() {
let mut deps = mock_dependencies();
set_up(deps.as_mut());
let add = vec![
Member {
addr: USER3.into(),
weight: 15,
},
Member {
addr: USER3.into(),
weight: 11,
},
];
let height = mock_env().block.height;
let err = update_members(
deps.as_mut(),
height + 5,
Addr::unchecked(INIT_ADMIN),
add,
vec![],
)
.unwrap_err();
assert_eq!(
err,
ContractError::DuplicateMember {
member: USER3.to_string()
}
);
}
fn assert_users<S: Storage, A: Api, Q: Querier>(
deps: &OwnedDeps<S, A, Q>,
user1_weight: Option<u64>,
user2_weight: Option<u64>,
user3_weight: Option<u64>,
height: Option<u64>,
) {
let member1 = query_member(deps.as_ref(), USER1.into(), height).unwrap();
assert_eq!(member1.weight, user1_weight);
let member2 = query_member(deps.as_ref(), USER2.into(), height).unwrap();
assert_eq!(member2.weight, user2_weight);
let member3 = query_member(deps.as_ref(), USER3.into(), height).unwrap();
assert_eq!(member3.weight, user3_weight);
// this is only valid if we are not doing a historical query
if height.is_none() {
// compute expected metrics
let weights = vec![user1_weight, user2_weight, user3_weight];
let sum: u64 = weights.iter().map(|x| x.unwrap_or_default()).sum();
let count = weights.iter().filter(|x| x.is_some()).count();
// TODO: more detailed compare?
let members = query_list_members(deps.as_ref(), None, None).unwrap();
assert_eq!(count, members.members.len());
let total = query_total_weight(deps.as_ref(), None).unwrap();
assert_eq!(sum, total.weight); // 17 - 11 + 15 = 21
}
}
#[test]
fn add_new_remove_old_member() {
let mut deps = mock_dependencies();
set_up(deps.as_mut());
// add a new one and remove existing one
let add = vec![Member {
addr: USER3.into(),
weight: 15,
}];
let remove = vec![USER1.into()];
// non-admin cannot update
let height = mock_env().block.height;
let err = update_members(
deps.as_mut(),
height + 5,
Addr::unchecked(USER1),
add.clone(),
remove.clone(),
)
.unwrap_err();
assert_eq!(err, AdminError::NotAdmin {}.into());
// Test the values from instantiate
assert_users(&deps, Some(11), Some(6), None, None);
// Note all values were set at height, the beginning of that block was all None
assert_users(&deps, None, None, None, Some(height));
// This will get us the values at the start of the block after instantiate (expected initial values)
assert_users(&deps, Some(11), Some(6), None, Some(height + 1));
// admin updates properly
update_members(
deps.as_mut(),
height + 10,
Addr::unchecked(INIT_ADMIN),
add,
remove,
)
.unwrap();
// updated properly
assert_users(&deps, None, Some(6), Some(15), None);
// snapshot still shows old value
assert_users(&deps, Some(11), Some(6), None, Some(height + 1));
}
#[test]
fn add_old_remove_new_member() {
// add will over-write and remove have no effect
let mut deps = mock_dependencies();
set_up(deps.as_mut());
// add a new one and remove existing one
let add = vec![Member {
addr: USER1.into(),
weight: 4,
}];
let remove = vec![USER3.into()];
// admin updates properly
let height = mock_env().block.height;
update_members(
deps.as_mut(),
height,
Addr::unchecked(INIT_ADMIN),
add,
remove,
)
.unwrap();
assert_users(&deps, Some(4), Some(6), None, None);
}
#[test]
fn add_and_remove_same_member() {
// add will over-write and remove have no effect
let mut deps = mock_dependencies();
set_up(deps.as_mut());
// USER1 is updated and remove in the same call, we should remove this an add member3
let add = vec![
Member {
addr: USER1.into(),
weight: 20,
},
Member {
addr: USER3.into(),
weight: 5,
},
];
let remove = vec![USER1.into()];
// admin updates properly
let height = mock_env().block.height;
update_members(
deps.as_mut(),
height,
Addr::unchecked(INIT_ADMIN),
add,
remove,
)
.unwrap();
assert_users(&deps, None, Some(6), Some(5), None);
}
#[test]
fn add_remove_hooks() {
// add will over-write and remove have no effect
let mut deps = mock_dependencies();
set_up(deps.as_mut());
let hooks = HOOKS.query_hooks(deps.as_ref()).unwrap();
assert!(hooks.hooks.is_empty());
let contract1 = String::from("hook1");
let contract2 = String::from("hook2");
let add_msg = ExecuteMsg::AddHook {
addr: contract1.clone(),
};
// non-admin cannot add hook
let user_info = mock_info(USER1, &[]);
let err = execute(
deps.as_mut(),
mock_env(),
user_info.clone(),
add_msg.clone(),
)
.unwrap_err();
assert_eq!(err, HookError::Admin(AdminError::NotAdmin {}).into());
// admin can add it, and it appears in the query
let admin_info = mock_info(INIT_ADMIN, &[]);
let _ = execute(
deps.as_mut(),
mock_env(),
admin_info.clone(),
add_msg.clone(),
)
.unwrap();
let hooks = HOOKS.query_hooks(deps.as_ref()).unwrap();
assert_eq!(hooks.hooks, vec![contract1.clone()]);
// cannot remove a non-registered contract
let remove_msg = ExecuteMsg::RemoveHook {
addr: contract2.clone(),
};
let err = execute(deps.as_mut(), mock_env(), admin_info.clone(), remove_msg).unwrap_err();
assert_eq!(err, HookError::HookNotRegistered {}.into());
// add second contract
let add_msg2 = ExecuteMsg::AddHook {
addr: contract2.clone(),
};
let _ = execute(deps.as_mut(), mock_env(), admin_info.clone(), add_msg2).unwrap();
let hooks = HOOKS.query_hooks(deps.as_ref()).unwrap();
assert_eq!(hooks.hooks, vec![contract1.clone(), contract2.clone()]);
// cannot re-add an existing contract
let err = execute(deps.as_mut(), mock_env(), admin_info.clone(), add_msg).unwrap_err();
assert_eq!(err, HookError::HookAlreadyRegistered {}.into());
// non-admin cannot remove
let remove_msg = ExecuteMsg::RemoveHook { addr: contract1 };
let err = execute(deps.as_mut(), mock_env(), user_info, remove_msg.clone()).unwrap_err();
assert_eq!(err, HookError::Admin(AdminError::NotAdmin {}).into());
// remove the original
let _ = execute(deps.as_mut(), mock_env(), admin_info, remove_msg).unwrap();
let hooks = HOOKS.query_hooks(deps.as_ref()).unwrap();
assert_eq!(hooks.hooks, vec![contract2]);
}
#[test]
fn hooks_fire() {
let mut deps = mock_dependencies();
set_up(deps.as_mut());
let hooks = HOOKS.query_hooks(deps.as_ref()).unwrap();
assert!(hooks.hooks.is_empty());
let contract1 = String::from("hook1");
let contract2 = String::from("hook2");
// register 2 hooks
let admin_info = mock_info(INIT_ADMIN, &[]);
let add_msg = ExecuteMsg::AddHook {
addr: contract1.clone(),
};
let add_msg2 = ExecuteMsg::AddHook {
addr: contract2.clone(),
};
for msg in vec![add_msg, add_msg2] {
let _ = execute(deps.as_mut(), mock_env(), admin_info.clone(), msg).unwrap();
}
// make some changes - add 3, remove 2, and update 1
// USER1 is updated and remove in the same call, we should remove this an add member3
let add = vec![
Member {
addr: USER1.into(),
weight: 20,
},
Member {
addr: USER3.into(),
weight: 5,
},
];
let remove = vec![USER2.into()];
let msg = ExecuteMsg::UpdateMembers { remove, add };
// admin updates properly
assert_users(&deps, Some(11), Some(6), None, None);
let res = execute(deps.as_mut(), mock_env(), admin_info, msg).unwrap();
assert_users(&deps, Some(20), None, Some(5), None);
// ensure 2 messages for the 2 hooks
assert_eq!(res.messages.len(), 2);
// same order as in the message (adds first, then remove)
// order of added users is not guaranteed to be preserved
let diffs = vec![
MemberDiff::new(USER3, None, Some(5)),
MemberDiff::new(USER1, Some(11), Some(20)),
MemberDiff::new(USER2, Some(6), None),
];
let hook_msg = MemberChangedHookMsg { diffs };
let msg1 = SubMsg::new(hook_msg.clone().into_cosmos_msg(contract1).unwrap());
let msg2 = SubMsg::new(hook_msg.into_cosmos_msg(contract2).unwrap());
dbg!(&res.messages);
dbg!(&msg1);
dbg!(&msg2);
assert_eq!(res.messages, vec![msg1, msg2]);
}
#[test]
fn raw_queries_work() {
// add will over-write and remove have no effect
let mut deps = mock_dependencies();
set_up(deps.as_mut());
// get total from raw key
let total_raw = deps.storage.get(TOTAL_KEY.as_bytes()).unwrap();
let total: u64 = from_slice(&total_raw).unwrap();
assert_eq!(17, total);
// get member votes from raw key
let member2_raw = deps.storage.get(&member_key(USER2)).unwrap();
let member2: u64 = from_slice(&member2_raw).unwrap();
assert_eq!(6, member2);
// and execute misses
let member3_raw = deps.storage.get(&member_key(USER3));
assert_eq!(None, member3_raw);
}
#[test]
fn total_at_height() {
let mut deps = mock_dependencies();
set_up(deps.as_mut());
let height = mock_env().block.height;
// Test the values from instantiate
let total = query_total_weight(deps.as_ref(), None).unwrap();
assert_eq!(17, total.weight);
// Note all values were set at height, the beginning of that block was all None
let total = query_total_weight(deps.as_ref(), Some(height)).unwrap();
assert_eq!(0, total.weight);
// This will get us the values at the start of the block after instantiate (expected initial values)
let total = query_total_weight(deps.as_ref(), Some(height + 1)).unwrap();
assert_eq!(17, total.weight);
}
+2 -2
View File
@@ -30,12 +30,12 @@ fn names<'a>() -> IndexedMap<'a, NameId, RegisteredName, NameIndex<'a>> {
let indexes = NameIndex {
name: UniqueIndex::new(|d| d.name.to_string(), NAMES_NAME_IDX_NAMESPACE),
address: MultiIndex::new(
|d| d.address.to_string(),
|_pk, d| d.address.to_string(),
NAMES_PK_NAMESPACE,
NAMES_ADDRESS_IDX_NAMESPACE,
),
owner: MultiIndex::new(
|d| d.owner.clone(),
|_pk, d| d.owner.clone(),
NAMES_PK_NAMESPACE,
NAMES_OWNER_IDX_NAMESPACE,
),
@@ -25,6 +25,6 @@ vergen = { version = "=7.4.3", default-features = false, features = ["build", "g
[dev-dependencies]
anyhow = "1.0.40"
cw-multi-test = { workspace = true }
nym-crypto = { path = "../../common/crypto", features = ["asymmetric", "rand"] }
nym-crypto = { path = "../../common/crypto", features = ["asymmetric", "rand", "wasm-contract"] }
rand_chacha = "0.2"
rstest = "0.17.0"
@@ -26,12 +26,12 @@ impl<'a> IndexList<Service> for ServiceIndex<'a> {
fn services<'a>() -> IndexedMap<'a, ServiceId, Service, ServiceIndex<'a>> {
let indexes = ServiceIndex {
nym_address: MultiIndex::new(
|d| d.service.nym_address.to_string(),
|_pk, d| d.service.nym_address.to_string(),
SERVICES_PK_NAMESPACE,
SERVICES_NYM_ADDRESS_IDX_NAMESPACE,
),
announcer: MultiIndex::new(
|d| d.announcer.clone(),
|_pk, d| d.announcer.clone(),
SERVICES_PK_NAMESPACE,
SERVICES_ANNOUNCER_IDX_NAMESPACE,
),
+1 -1
View File
@@ -25,7 +25,7 @@ fn generate_storage_key(storage: &mut dyn Storage) -> Result<AccountStorageKey,
Ok(key)
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
pub struct Account {
pub owner_address: Addr,
pub staking_address: Option<Addr>,
@@ -593,10 +593,19 @@ nyxd tx slashing unjail
### Upgrading your validator
Upgrading from `v0.26.0` -> `v0.31.1` doesn't require many modifications, simply grab a binary from the [`nyxd` releases page](https://github.com/nymtech/nyxd/releases) and once the chain has halted at the decided upon haltheight, stop your `nyxd` process, replace your binaries, and restart your process.
Upgrading from `v0.26.0` -> `v0.31.1` process is fairly simple. Grab the v0.31.1 release tarball from the [`nyxd` releases page](https://github.com/nymtech/nyxd/releases), and untar it. Inside are two files:
- the new validator (`nyxd`) v0.31.1
- the new wasmvm (it depends on your platform, but most common filename is `libwasmvm.x86_64.so`)
Before the upgrade height, copy `libwasmvm.x86_64.so` to the default LD_LIBRARY_PATH on your system (on Ubuntu 20.04 this is `/lib/x86_64-linux-gnu/`):
Then just swap in your new `nyxd` binary and restart once the halt height is reached.
You can also use something like [Cosmovisor](https://github.com/cosmos/cosmos-sdk/tree/main/tools/cosmovisor) - grab the relevant information from the current upgrade proposal [here](https://nym.explorers.guru/proposal/8).
Note: Cosmovisor will swap the `nyxd` binary, but you'll need to already have the `libwasmvm.x86_64.so` in place. Luckily, the name of the wasmvm in v0.26.1 was `libwasmvm.so`, and the new name is `libwasmvm.x86_64.so`, so you can have it already sitting there without disrupting service.
#### Common reasons for your validator being jailed
The most common reason for your validator being jailed is that your validator is out of memory because of bloated syslogs.
+1
View File
@@ -16,6 +16,7 @@ COCONUT_BANDWIDTH_CONTRACT_ADDRESS=n1lp5zex6685kd22agzskhqsylpnssxnweyuvsz4edr4p
GROUP_CONTRACT_ADDRESS=n1rw8fw2mpcpzzq3jpa4e52ufawnmj5a4u68p35umvgskewuw0nlzsaa5w4m
MULTISIG_CONTRACT_ADDRESS=n1rw8fw2mpcpzzq3jpa4e52ufawnmj5a4u68p35umvgskewuw0nlzsaa5w4m
COCONUT_DKG_CONTRACT_ADDRESS=n1vwtgazgpancsfel04y7syc95ausmat47cjtldqzkdmx6phyrwx2qvkv32p
EPHEMERA_CONTRACT_ADDRESS=n1vwtgazgpancsfel04y7syc95ausmat47cjtldqzkdmx6phyrwx2qvkv32p
REWARDING_VALIDATOR_ADDRESS=n1tfzd4qz3a45u8p4mr5zmzv66457uwjgcl05jdq
STATISTICS_SERVICE_DOMAIN_ADDRESS="http://0.0.0.0"
NYXD="http://127.0.0.1:26657"
+1
View File
@@ -16,6 +16,7 @@ COCONUT_BANDWIDTH_CONTRACT_ADDRESS=n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0
GROUP_CONTRACT_ADDRESS=n1rw8fw2mpcpzzq3jpa4e52ufawnmj5a4u68p35umvgskewuw0nlzsaa5w4m
MULTISIG_CONTRACT_ADDRESS=n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0
COCONUT_DKG_CONTRACT_ADDRESS=n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0
EPHEMERA_CONTRACT_ADDRESS=n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0
REWARDING_VALIDATOR_ADDRESS=n10yyd98e2tuwu0f7ypz9dy3hhjw7v772q6287gy
STATISTICS_SERVICE_DOMAIN_ADDRESS="https://mainnet-stats.nymte.ch:8090"
NYXD="https://rpc.nymtech.net"
+1
View File
@@ -16,6 +16,7 @@ COCONUT_BANDWIDTH_CONTRACT_ADDRESS=n19d2nwj7fdhxqmyvgy8lf3ad49a6vmww4shryhrkj2mq
GROUP_CONTRACT_ADDRESS=n1fqquzw4mk0pkamgr2ywt2v7h2j9nuyjjn4gvpy8zlpp6xn0uyuzqfm28l5
MULTISIG_CONTRACT_ADDRESS=n1gaq3666chd5348apj8cka8t2mckv7azp9espyr7wgpxyuzur5d0sazpysy
COCONUT_DKG_CONTRACT_ADDRESS=n18yadscxw8v35dds7ksv3j0svmjh3h6e7tmxpadk96mvgz27zygkshuf4vs
EPHEMERA_CONTRACT_ADDRESS=n18yadscxw8v35dds7ksv3j0svmjh3h6e7tmxpadk96mvgz27zygkshuf4vs
REWARDING_VALIDATOR_ADDRESS=n10yyd98e2tuwu0f7ypz9dy3hhjw7v772q6287gy
SERVICE_PROVIDER_DIRECTORY_CONTRACT_ADDRESS=n1qsn2655eflc0nx2uwqtwyv5kad5dwm4c0gn72yr4q4de5r3jaz2slvqjgt
NAME_SERVICE_CONTRACT_ADDRESS=n1cm2u5vfjd3zalfw0p65xyh4tcrw3hjlm0960gzhewga449h4mgas77mjkl
+1
View File
@@ -16,6 +16,7 @@ COCONUT_BANDWIDTH_CONTRACT_ADDRESS=n1ghd753shjuwexxywmgs4xz7x2q732vcn7ty4yw
GROUP_CONTRACT_ADDRESS=n1rw8fw2mpcpzzq3jpa4e52ufawnmj5a4u68p35umvgskewuw0nlzsaa5w4m
MULTISIG_CONTRACT_ADDRESS=n17p9rzwnnfxcjp32un9ug7yhhzgtkhvl988qccs
COCONUT_DKG_CONTRACT_ADDRESS=n17p9rzwnnfxcjp32un9ug7yhhzgtkhvl988qccs
EPHEMERA_CONTRACT_ADDRESS=n17p9rzwnnfxcjp32un9ug7yhhzgtkhvl988qccs
REWARDING_VALIDATOR_ADDRESS=n1tfzd4qz3a45u8p4mr5zmzv66457uwjgcl05jdq
STATISTICS_SERVICE_DOMAIN_ADDRESS="http://0.0.0.0"
NYXD="https://qa-validator.nymtech.net"
+1
View File
@@ -17,6 +17,7 @@ BANDWIDTH_CLAIM_CONTRACT_ADDRESS="nymt1rhmk9udessnv3r8f3eh2s03f45svnjaczpmcqz"
MULTISIG_CONTRACT_ADDRESS="nymt142dkm8xe9f0ytyarp7ww4kvclva65705jphxsk9exn3nqdsm8jkqnp06ac"
COCONUT_BANDWIDTH_CONTRACT_ADDRESS="nymt1ty0frysegskh6ndm3v96z5xdq66qzcu0aw7xcxlgp54jg0mjwlgqplc6v0"
COCONUT_DKG_CONTRACT_ADDRESS="nymt1gwk6muhmzeuxje7df7rjvqwl2vex0kj4t2hwuzmyx5k62kfusu5qk4k5z4"
EPHEMERA_CONTRACT_ADDRESS="nymt1gwk6muhmzeuxje7df7rjvqwl2vex0kj4t2hwuzmyx5k62kfusu5qk4k5z4"
GROUP_CONTRACT_ADDRESS="nymt14ry36mwauycz08v8ndcujghxz4hmua5epxcn0mamlr3suqe0l2qsqx5ya2"
STATISTICS_SERVICE_DOMAIN_ADDRESS="http://0.0.0.0"
+65
View File
@@ -0,0 +1,65 @@
[package]
name = "ephemera"
version = "0.1.0"
edition = "2021"
[[bin]]
name = "ephemera"
path = "bin/main.rs"
[dependencies]
## internal
nym-task = { path = "../common/task" }
actix-web = "4"
anyhow = { version = "1.0.66", features = ["backtrace"] }
array-bytes = "6.0.0"
async-trait = "0.1.59"
asynchronous-codec = "0.6.1"
blake2 = "0.10.6"
bs58 = "0.4.0"
bytes = "1.3.0"
cfg-if = "1.0.0"
chrono = { version = "0.4.24", default-features = false, features = ["clock"] }
clap = { version = "4.0.32", features = ["derive"] }
config = { version = "0.13", default-features = false, features = ["toml"] }
digest = "0.10.6"
dirs = "5.0.0"
futures = "0.3.18"
futures-util = "0.3.25"
lazy_static = "1.4.0"
libp2p = { version = "0.51.3", default-features = false, features = ["dns", "gossipsub", "kad", "macros", "noise", "request-response", "serde", "tcp", "tokio", "yamux"] }
libp2p-identity = "0.1.0"
log = "0.4.14"
lru = "0.10.0"
nym-config = { path = "../common/config" }
nym-ephemera-common = { path = "../common/cosmwasm-smart-contracts/ephemera" }
pretty_env_logger = "0.4"
refinery = { version = "0.8.7", features = ["rusqlite"], optional = true }
reqwest = { version = "0.11.6", features = ["json"] }
rocksdb = { version = "0.20.1", optional = true }
rusqlite = { version = "0.27.0", features = ["bundled"], optional = true }
serde = { version = "1.0", features = ["derive"] }
serde_derive = "1.0.149"
serde_json = "1.0.91"
thiserror = "1.0.37"
tokio = { version = "1", features = ["macros", "net","rt-multi-thread"] }
tokio-tungstenite = "0.18.0"
tokio-util = { version = "0.7.4", features = ["full"] }
toml = "0.7.0"
unsigned-varint = "0.7.1"
utoipa = { version = "3.0.1", features = ["actix_extras"] }
utoipa-swagger-ui = { version = "3.0.2", features = ["actix-web"] }
uuid = { version = "1.2.2", features = ["v4"] }
# Temporary fix to https://github.com/bluejekyll/trust-dns/issues/1946
enum-as-inner = "=0.5.1"
[dev-dependencies]
assert_matches = "1.5.0"
rand = "0.8.5"
[features]
default = ["sqlite_storage"]
rocksdb_storage = ["rocksdb"]
sqlite_storage = ["rusqlite", "refinery"]
+142
View File
@@ -0,0 +1,142 @@
# Ephemera - reliable broadcast protocol implementation
Ephemera does reliable broadcast for blocks.
## Short Overview
All Ephemera nodes accept messages submitted by clients. Node then gossips these to other nodes in the cluster. After certain interval,
a node collects messages and produces a block. Then it does reliable broadcast for the block with other nodes in the cluster.
Ephemera doesn't have the concept of (decentralised) leader at the moment. It's up to an _Application_ to decide which block to use.
For example in case of Nym-Api, it is the first block submitted to a "Smart Contract".
At the same time, the purpose of blocks is to reach consensus about which messages are included. It's just that Ephemera doesn't make the final decision,
instead it leaves that to an _Application_.
## Main concepts
- **Node** - a single instance of Ephemera.
- **Cluster** - a set of nodes participating in reliable broadcast.
- **EphemeraMessage** - a message submitted by a client.
- **Block** - a set of messages collected by a node.
- **Application(ABCI)** - a trait which Ephemera users implement to accept messages and blocks.
- check_tx
- check_block
- accept_block
## How to run
[README](../scripts/README.md)
## HTTP API
See [Rust](src/api/http/mod.rs)
### Endpoints
**NODE**
- `/ephemera/node/health`
- `/ephemera/node/config`
**BLOCKS**
- `/ephemera/broadcast/block/{hash}`
- `/ephemera/broadcast/block/height/{height}`
- `/ephemera/broadcast/blocks/last`
- `/ephemera/broadcast/block/certificates/{hash}`
- `/ephemera/broadcast/block/broadcast_info/{hash}`
**GROUP**
- `/ephemera/broadcast/group/info`
**MESSAGES**
- `/ephemera/broadcast/submit_message`
**DHT**
- `/ephemera/dht/query/{key}`
- `/ephemera/dht/store`
## Rust API
Almost identical to HTTP API.
See [Rust](src/api/mod.rs)
## Application(Ephemera ABCI)
Cosmos style ABCI application hook
- `check_tx`
- `check_block`
- `deliver_block`
See [Rust](src/api/application.rs)
## Examples
### Ephemera HTTP and WS external interfaces example/tests
See [README.md](../examples/http-ws-sync/README.md)
### Nym Api simulation
See [README.md](../examples/nym-api/README.md)
### http API example/tests
See [README.md](../examples/cluster-http-api/README.md)
### Membership over HTTP API example/tests
See [README.md](../examples/members_provider_http/README.md)
## About reliable broadcast and consensus
In blockchain technology blocks have two main purposes:
1. To maintain chain of blocks, so that the validity of each block can be cryptographically verified by the previous blocks
2. As a unit of consensus, each block contains a set of transactions/messages/actions that are agreed upon by
the network. This set of transactions is chosen from the global set of all possible transactions that are pending.
We call the set of transactions in a block consensus because the set of nodes trying to achieve global shared state
agreed on this particular set of transactions.
Ephemera is not a blockchain. But it uses blocks to agree on the set of transactions in a block.
But at the same time it doesn't behave like a blockchain consensus algorithm.
We may say that it allows each application that uses Ephemera to "propose" something what can be
afterwards to be used to achieve consensus.
### In Summary
1. Ephemera provides functionality to reach agreement on a single value between a set of nodes.
2. Ephemera also provides the concept of a block, which application can take advantage of to reach consensus externally.
### Reliable broadcast, consensus and blocks
In distributed systems(including byzantine), we try to solve the problem of reaching to a commons state between a set of nodes.
One way to define this problem is using the following properties:
1.
1) Agreement: All nodes agree on the same value.(TODO clarify)
2) Consensus: All nodes agree on the same value.(TODO clarify)
2. Validity: All nodes agree on a value that is valid.
3. Termination: All nodes eventually agree on a value.
Reliable broadcast ensures the properties of 1.1 and 1.2. It's left to a particular consensus algorithm to ensure the termination property.
One important feature of consensus in blockchain is that it guarantees total ordering of transactions.
Reliable broadcast with blocks helps to ensure this total ordering.
### Ephemera specific properties
Because Ephemera doesn't use the idea of leader, we can say that it solves consensus partially.
It allows each instance to create a block. And then it's up to an application to decide which block to use.
Also, as it doesn't implement a full consensus algorithm, it doesn't ensure the termination.
There's no algorithm in place what tries to reach a consensus about a single block globally and sequentially
in time.
When a block contains a single message, then it's semantically equivalent to a reliable broadcast.
But when a block contains multiple messages, then it can be part of a consensus process. Except that in Ephemera each node
can create a block. To achieve consensus in a more traditional sense, it needs an application help if more strict
consensus is required.
For example, Nym-Api allows each node to create a block but uses external coordinator(a smart contract)
to decide which block to use.
+12
View File
@@ -0,0 +1,12 @@
use clap::Parser;
use ephemera::cli::Cli;
use ephemera::logging;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
logging::init();
Cli::parse().execute().await?;
Ok(())
}
+24
View File
@@ -0,0 +1,24 @@
CREATE TABLE IF NOT EXISTS blocks (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
block_hash TEXT NOT NULL UNIQUE,
height TEXT NOT NULL UNIQUE,
block BLOB NOT NULL
);
CREATE TABLE IF NOT EXISTS block_certificates (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
block_hash TEXT NOT NULL UNIQUE,
certificates BLOB NOT NULL
);
CREATE TABLE IF NOT EXISTS block_broadcast_group (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
block_hash TEXT NOT NULL UNIQUE,
members BLOB NOT NULL
);
CREATE TABLE IF NOT EXISTS block_merkle_tree (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
block_hash TEXT NOT NULL UNIQUE,
merkle_tree BLOB NOT NULL
);

Some files were not shown because too many files have changed in this diff Show More