Initial logic for adding new dealer
contains bunch of placeholder assumptions
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::types::{EncodedBTEPublicKeyWithProof, EncodedEd25519PublicKey};
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
@@ -10,7 +11,13 @@ pub struct InstantiateMsg {}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum ExecuteMsg {}
|
||||
pub enum ExecuteMsg {
|
||||
RegisterDealer {
|
||||
ed25519_key: EncodedEd25519PublicKey,
|
||||
bte_key_with_proof: EncodedBTEPublicKeyWithProof,
|
||||
owner_signature: String,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
|
||||
@@ -4,20 +4,54 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
pub type BlockHeight = u64;
|
||||
pub type EncodedEd25519PublicKey = String;
|
||||
pub type EncodedEd25519PublicKeyRef<'a> = &'a str;
|
||||
pub type EncodedBTEPublicKeyWithProof = String;
|
||||
pub type NodeIndex = u64;
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub struct DealerDetails {
|
||||
pub joined_at: BlockHeight,
|
||||
pub left_at: Option<BlockHeight>,
|
||||
pub blacklisting: Option<Blacklisting>,
|
||||
pub ed25519_public_key: EncodedEd25519PublicKey,
|
||||
pub bte_public_key_with_proof: EncodedBTEPublicKeyWithProof,
|
||||
pub assigned_index: NodeIndex,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub struct Blacklisting {
|
||||
reason: BlacklistingReason,
|
||||
height: u64,
|
||||
pub reason: BlacklistingReason,
|
||||
pub height: BlockHeight,
|
||||
pub expiration: Option<BlockHeight>,
|
||||
}
|
||||
|
||||
impl Blacklisting {
|
||||
pub fn has_expired(&self, current_block: BlockHeight) -> bool {
|
||||
self.expiration
|
||||
.map(|expiration| expiration <= current_block)
|
||||
.unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Blacklisting {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"blacklisted at block height {}. reason given: {}",
|
||||
self.height, self.height
|
||||
)
|
||||
if let Some(expiration) = self.expiration {
|
||||
write!(
|
||||
f,
|
||||
"blacklisted at block height {}. reason given: {}. Expires at: {}",
|
||||
self.height, self.height, expiration
|
||||
)
|
||||
} else {
|
||||
write!(
|
||||
f,
|
||||
"blacklisted at block height {}. reason given: {}",
|
||||
self.height, self.height
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +59,10 @@ impl Display for Blacklisting {
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum BlacklistingReason {
|
||||
InactiveForConsecutiveEpochs,
|
||||
MalformedBTEPublicKey,
|
||||
InvalidBTEPublicKey,
|
||||
MalformedEd25519PublicKey,
|
||||
Ed25519PossessionVerificationFailure,
|
||||
}
|
||||
|
||||
impl Display for BlacklistingReason {
|
||||
@@ -33,6 +71,64 @@ impl Display for BlacklistingReason {
|
||||
BlacklistingReason::InactiveForConsecutiveEpochs => {
|
||||
write!(f, "has been inactive for multiple consecutive epochs")
|
||||
}
|
||||
BlacklistingReason::MalformedBTEPublicKey => {
|
||||
write!(f, "provided malformed BTE Public Key")
|
||||
}
|
||||
BlacklistingReason::InvalidBTEPublicKey => write!(f, "provided invalid BTE Public Key"),
|
||||
BlacklistingReason::MalformedEd25519PublicKey => {
|
||||
write!(f, "provided malformed ed25519 Public Key")
|
||||
}
|
||||
BlacklistingReason::Ed25519PossessionVerificationFailure => {
|
||||
write!(
|
||||
f,
|
||||
"failed to verify possession of provided ed25519 Public Key"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub struct Epoch {
|
||||
pub id: u64,
|
||||
pub state: EpochState,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum EpochState {
|
||||
InProgress {
|
||||
begun_at: BlockHeight,
|
||||
// not entirely sure about that one yet. we'll see how it works out when we get to epoch transition
|
||||
finish_by: Option<BlockHeight>,
|
||||
},
|
||||
PublicKeySubmission {
|
||||
begun_at: BlockHeight,
|
||||
finish_by: BlockHeight,
|
||||
},
|
||||
DealingExchange {
|
||||
begun_at: BlockHeight,
|
||||
finish_by: BlockHeight,
|
||||
},
|
||||
ComplaintSubmission {
|
||||
begun_at: BlockHeight,
|
||||
finish_by: BlockHeight,
|
||||
},
|
||||
ComplaintVoting {
|
||||
begun_at: BlockHeight,
|
||||
finish_by: BlockHeight,
|
||||
},
|
||||
VerificationKeySubmission {
|
||||
begun_at: BlockHeight,
|
||||
finish_by: BlockHeight,
|
||||
},
|
||||
VerificationKeyMismatchSubmission {
|
||||
begun_at: BlockHeight,
|
||||
finish_by: BlockHeight,
|
||||
},
|
||||
VerificationKeyMismatchVoting {
|
||||
begun_at: BlockHeight,
|
||||
finish_by: BlockHeight,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ cfg_if::cfg_if! {
|
||||
if #[cfg(network = "mainnet")] {
|
||||
pub const DEFAULT_NETWORK: all::Network = all::Network::MAINNET;
|
||||
pub const DENOM: &str = mainnet::DENOM;
|
||||
pub const STAKE_DENOM: &str = mainnet::STAKE_DENOM;
|
||||
|
||||
pub const ETH_CONTRACT_ADDRESS: [u8; 20] = mainnet::_ETH_CONTRACT_ADDRESS;
|
||||
pub const ETH_ERC20_CONTRACT_ADDRESS: [u8; 20] = mainnet::_ETH_ERC20_CONTRACT_ADDRESS;
|
||||
@@ -25,6 +26,7 @@ cfg_if::cfg_if! {
|
||||
} else if #[cfg(network = "qa")] {
|
||||
pub const DEFAULT_NETWORK: all::Network = all::Network::QA;
|
||||
pub const DENOM: &str = qa::DENOM;
|
||||
pub const STAKE_DENOM: &str = qa::STAKE_DENOM;
|
||||
|
||||
pub const ETH_CONTRACT_ADDRESS: [u8; 20] = qa::_ETH_CONTRACT_ADDRESS;
|
||||
pub const ETH_ERC20_CONTRACT_ADDRESS: [u8; 20] = qa::_ETH_ERC20_CONTRACT_ADDRESS;
|
||||
@@ -32,6 +34,7 @@ cfg_if::cfg_if! {
|
||||
} else if #[cfg(network = "sandbox")] {
|
||||
pub const DEFAULT_NETWORK: all::Network = all::Network::SANDBOX;
|
||||
pub const DENOM: &str = sandbox::DENOM;
|
||||
pub const STAKE_DENOM: &str = sandbox::STAKE_DENOM;
|
||||
|
||||
pub const ETH_CONTRACT_ADDRESS: [u8; 20] = sandbox::_ETH_CONTRACT_ADDRESS;
|
||||
pub const ETH_ERC20_CONTRACT_ADDRESS: [u8; 20] = sandbox::_ETH_ERC20_CONTRACT_ADDRESS;
|
||||
|
||||
@@ -5,6 +5,7 @@ use crate::ValidatorDetails;
|
||||
|
||||
pub(crate) const BECH32_PREFIX: &str = "n";
|
||||
pub const DENOM: &str = "unym";
|
||||
pub const STAKE_DENOM: &str = "unyx";
|
||||
|
||||
pub(crate) const MIXNET_CONTRACT_ADDRESS: &str =
|
||||
"n14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9sjyvg3g";
|
||||
|
||||
@@ -5,6 +5,7 @@ use crate::ValidatorDetails;
|
||||
|
||||
pub(crate) const BECH32_PREFIX: &str = "nymt";
|
||||
pub const DENOM: &str = "unymt";
|
||||
pub const STAKE_DENOM: &str = "unyxt";
|
||||
|
||||
pub(crate) const MIXNET_CONTRACT_ADDRESS: &str = "nymt17x6pt4msccvawgxjeg5nmnygttu56tftg5l6j3";
|
||||
pub(crate) const VESTING_CONTRACT_ADDRESS: &str = "nymt1t4dmskxea0avvrj8xtmu66hv7dkyg9s8059t3c";
|
||||
|
||||
@@ -5,6 +5,7 @@ use crate::ValidatorDetails;
|
||||
|
||||
pub(crate) const BECH32_PREFIX: &str = "nymt";
|
||||
pub const DENOM: &str = "unymt";
|
||||
pub const STAKE_DENOM: &str = "unyxt";
|
||||
|
||||
pub(crate) const MIXNET_CONTRACT_ADDRESS: &str = "nymt1ghd753shjuwexxywmgs4xz7x2q732vcnstz02j";
|
||||
pub(crate) const VESTING_CONTRACT_ADDRESS: &str = "nymt14ejqjyq8um4p3xfqj74yld5waqljf88fn549lh";
|
||||
|
||||
Generated
+1
@@ -217,6 +217,7 @@ dependencies = [
|
||||
name = "coconut-dkg"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bs58",
|
||||
"coconut-dkg-common",
|
||||
"config",
|
||||
"cosmwasm-std",
|
||||
|
||||
@@ -12,6 +12,7 @@ crate-type = ["cdylib", "rlib"]
|
||||
coconut-dkg-common = { path = "../../common/cosmwasm-smart-contracts/coconut-dkg-contract" }
|
||||
config = { path = "../../common/config"}
|
||||
|
||||
bs58 = "0.4"
|
||||
cosmwasm-std = { version = "1.0.0-beta8", features = ["staking"] }
|
||||
cosmwasm-storage = "1.0.0-beta8"
|
||||
cw-storage-plus = "0.13.2"
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use cosmwasm_std::Uint128;
|
||||
|
||||
// to be determined whether those should be constants or exist as contract state
|
||||
pub(crate) const MINIMUM_DEPOSIT: Uint128 = Uint128::new(1_000_000_000);
|
||||
|
||||
// if submitted invalid keys/signatures, get blacklisted for approximately 1 day (with ~5s per block)
|
||||
pub(crate) const INVALID_ED25519_BLACKLISTING_EXPIRATION: u64 = 17280;
|
||||
@@ -2,26 +2,46 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use coconut_dkg_common::types::Blacklisting;
|
||||
use cosmwasm_std::StdError;
|
||||
use config::defaults::STAKE_DENOM;
|
||||
use cosmwasm_std::{StdError, VerificationError};
|
||||
use thiserror::Error;
|
||||
|
||||
use config::defaults::DENOM;
|
||||
|
||||
/// Custom errors for contract failure conditions.
|
||||
#[derive(Error, Debug, PartialEq)]
|
||||
pub enum ContractError {
|
||||
#[error("{0}")]
|
||||
Std(#[from] StdError),
|
||||
|
||||
#[error("No coin was sent for the deposit, you must send {}", STAKE_DENOM)]
|
||||
NoDepositFound,
|
||||
|
||||
#[error("Received multiple coin types")]
|
||||
MultipleDenoms,
|
||||
|
||||
#[error("Wrong coin denomination, you must send {}", DENOM)]
|
||||
#[error("Wrong coin denomination, you must send {}", STAKE_DENOM)]
|
||||
WrongDenom,
|
||||
|
||||
#[error("Not enough funds sent for deposit. (received {received}, minimum {minimum})")]
|
||||
InsufficientDeposit { received: u128, minimum: u128 },
|
||||
|
||||
#[error("Failed to recover ed25519 public key from its base58 representation - {0}. This dealer will be temporarily blacklisted now.")]
|
||||
MalformedEd25519PublicKey(bs58::decode::Error),
|
||||
|
||||
#[error("Failed to recover ed25519 signature from its base58 representation - {0}. This dealer will be temporarily blacklisted now.")]
|
||||
MalformedEd25519Signature(bs58::decode::Error),
|
||||
|
||||
#[error("Failed to perform ed25519 signature verification - {0}. This dealer will be temporarily blacklisted now.")]
|
||||
Ed25519VerificationError(#[from] VerificationError),
|
||||
|
||||
#[error("Provided ed25519 signature did not verify correctly. This dealer will be temporarily blacklisted now.")]
|
||||
InvalidEd25519Signature,
|
||||
|
||||
#[error("This dealer has been blacklisted - {reason}")]
|
||||
BlacklistedDealer { reason: Blacklisting },
|
||||
|
||||
#[error("This potential dealer is not a validator")]
|
||||
NotAValidator,
|
||||
|
||||
#[error("This sender is already a dealer for the epoch")]
|
||||
AlreadyADealer,
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ use crate::error::ContractError;
|
||||
use coconut_dkg_common::msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg};
|
||||
use cosmwasm_std::{entry_point, Deps, DepsMut, Env, MessageInfo, QueryResponse, Response};
|
||||
|
||||
mod constants;
|
||||
mod error;
|
||||
mod queries;
|
||||
mod storage;
|
||||
@@ -29,16 +30,25 @@ pub fn instantiate(
|
||||
/// Handle an incoming message
|
||||
#[entry_point]
|
||||
pub fn execute(
|
||||
_deps: DepsMut<'_>,
|
||||
_env: Env,
|
||||
_info: MessageInfo,
|
||||
deps: DepsMut<'_>,
|
||||
env: Env,
|
||||
info: MessageInfo,
|
||||
msg: ExecuteMsg,
|
||||
) -> Result<Response, ContractError> {
|
||||
match msg {
|
||||
_ => (),
|
||||
ExecuteMsg::RegisterDealer {
|
||||
ed25519_key,
|
||||
bte_key_with_proof,
|
||||
owner_signature,
|
||||
} => transactions::try_add_dealer(
|
||||
deps,
|
||||
env,
|
||||
info,
|
||||
ed25519_key,
|
||||
bte_key_with_proof,
|
||||
owner_signature,
|
||||
),
|
||||
}
|
||||
|
||||
Ok(Default::default())
|
||||
}
|
||||
|
||||
#[entry_point]
|
||||
|
||||
@@ -1,8 +1,23 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use coconut_dkg_common::types::Blacklisting;
|
||||
use cosmwasm_std::Addr;
|
||||
use cw_storage_plus::Map;
|
||||
use coconut_dkg_common::types::{Blacklisting, DealerDetails, NodeIndex};
|
||||
use cosmwasm_std::{Addr, StdResult, Storage};
|
||||
use cw_storage_plus::{Item, Map};
|
||||
|
||||
pub(crate) const BLACKLISTED_DEALERS: Map<'_, &'_ Addr, Blacklisting> = Map::new("bld");
|
||||
|
||||
pub(crate) const NODE_INDEX_COUNTER: Item<NodeIndex> = Item::new("node_index_counter");
|
||||
|
||||
// TODO: this is an interesting question: should dealers be addressed by their addresses
|
||||
// or maybe node indices?
|
||||
// perhaps this should be UniqueIndex?
|
||||
pub(crate) const CURRENT_DEALERS: Map<'_, &'_ Addr, DealerDetails> = Map::new("crd");
|
||||
pub(crate) const PAST_DEALERS: Map<'_, &'_ Addr, DealerDetails> = Map::new("ptd");
|
||||
|
||||
pub(crate) fn next_node_index(store: &mut dyn Storage) -> StdResult<NodeIndex> {
|
||||
// make sure we don't start from 0!
|
||||
let id: NodeIndex = NODE_INDEX_COUNTER.may_load(store)?.unwrap_or_default() + 1;
|
||||
NODE_INDEX_COUNTER.save(store, &id)?;
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
@@ -1,19 +1,42 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::storage::BLACKLISTED_DEALERS;
|
||||
use crate::constants::{INVALID_ED25519_BLACKLISTING_EXPIRATION, MINIMUM_DEPOSIT};
|
||||
use crate::storage::{next_node_index, BLACKLISTED_DEALERS, CURRENT_DEALERS, PAST_DEALERS};
|
||||
use crate::ContractError;
|
||||
use cosmwasm_std::{ensure, Addr, Deps, DepsMut, Env, MessageInfo, Response, Storage};
|
||||
use coconut_dkg_common::types::{
|
||||
Blacklisting, BlacklistingReason, BlockHeight, DealerDetails, EncodedBTEPublicKeyWithProof,
|
||||
EncodedEd25519PublicKey, EncodedEd25519PublicKeyRef,
|
||||
};
|
||||
use config::defaults::STAKE_DENOM;
|
||||
use cosmwasm_std::{Addr, Coin, Deps, DepsMut, Env, MessageInfo, Response};
|
||||
|
||||
// currently we only require that
|
||||
// a) it's a validator
|
||||
// b) it wasn't blacklisted
|
||||
fn verify_dealer(deps: Deps<'_>, dealer: &Addr) -> Result<(), ContractError> {
|
||||
// c) it isn't already a dealer
|
||||
fn verify_dealer(
|
||||
deps: DepsMut<'_>,
|
||||
current_height: BlockHeight,
|
||||
dealer: &Addr,
|
||||
) -> Result<(), ContractError> {
|
||||
if let Some(blacklisting) = BLACKLISTED_DEALERS.may_load(deps.storage, dealer)? {
|
||||
return Err(ContractError::BlacklistedDealer {
|
||||
reason: blacklisting,
|
||||
});
|
||||
// TODO: perhaps whenever we touch anything to do with blacklisting, each should check for
|
||||
// expiration and auto-magically clear stale ones
|
||||
if !blacklisting.has_expired(current_height) {
|
||||
return Err(ContractError::BlacklistedDealer {
|
||||
reason: blacklisting,
|
||||
});
|
||||
} else {
|
||||
// remove the expired blacklisting
|
||||
BLACKLISTED_DEALERS.remove(deps.storage, dealer)
|
||||
}
|
||||
}
|
||||
|
||||
if CURRENT_DEALERS.has(deps.storage, dealer) {
|
||||
return Err(ContractError::AlreadyADealer);
|
||||
}
|
||||
|
||||
let all_validators = deps.querier.query_all_validators()?;
|
||||
if !all_validators
|
||||
.iter()
|
||||
@@ -25,12 +48,114 @@ fn verify_dealer(deps: Deps<'_>, dealer: &Addr) -> Result<(), ContractError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn validate_dealer_deposit(mut deposit: Vec<Coin>) -> Result<Coin, ContractError> {
|
||||
// check if anything was put as deposit
|
||||
if deposit.is_empty() {
|
||||
return Err(ContractError::NoDepositFound);
|
||||
}
|
||||
|
||||
if deposit.len() > 1 {
|
||||
return Err(ContractError::MultipleDenoms);
|
||||
}
|
||||
|
||||
// check that the denomination is correct
|
||||
if deposit[0].denom != STAKE_DENOM {
|
||||
return Err(ContractError::WrongDenom {});
|
||||
}
|
||||
|
||||
// check that we have at least MINIMUM_DEPOSIT coins in our deposit
|
||||
if deposit[0].amount < MINIMUM_DEPOSIT {
|
||||
return Err(ContractError::InsufficientDeposit {
|
||||
received: deposit[0].amount.into(),
|
||||
minimum: MINIMUM_DEPOSIT.into(),
|
||||
});
|
||||
}
|
||||
|
||||
// the unwrap would have been safe here under all circumstances, since we checked whether the vector is empty
|
||||
// but in case something did change, change option into an error
|
||||
deposit.pop().ok_or(ContractError::NoDepositFound)
|
||||
}
|
||||
|
||||
pub(crate) fn validate_key_possession_signature(
|
||||
deps: Deps<'_>,
|
||||
owner: &Addr,
|
||||
signature: String,
|
||||
encoded_key: EncodedEd25519PublicKeyRef<'_>,
|
||||
) -> Result<(), ContractError> {
|
||||
let mut key_bytes = [0u8; 32];
|
||||
let mut signature_bytes = [0u8; 64];
|
||||
|
||||
bs58::decode(encoded_key)
|
||||
.into(&mut key_bytes)
|
||||
.map_err(ContractError::MalformedEd25519PublicKey)?;
|
||||
bs58::decode(signature)
|
||||
.into(&mut signature_bytes)
|
||||
.map_err(ContractError::MalformedEd25519Signature)?;
|
||||
|
||||
let res = deps
|
||||
.api
|
||||
.ed25519_verify(owner.as_bytes(), &signature_bytes, &key_bytes)?;
|
||||
|
||||
if !res {
|
||||
Err(ContractError::InvalidEd25519Signature)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_add_dealer(
|
||||
deps: DepsMut<'_>,
|
||||
mut deps: DepsMut<'_>,
|
||||
env: Env,
|
||||
info: MessageInfo,
|
||||
ed25519_key: EncodedEd25519PublicKey,
|
||||
bte_key_with_proof: EncodedBTEPublicKeyWithProof,
|
||||
owner_signature: String,
|
||||
) -> Result<Response, ContractError> {
|
||||
verify_dealer(deps.as_ref(), &info.sender)?;
|
||||
// check whether this sender is eligible to become a dealer
|
||||
verify_dealer(deps.branch(), env.block.height, &info.sender)?;
|
||||
|
||||
todo!()
|
||||
// check if this dealer actually has control of his ed25519 key
|
||||
// (BTE key has a proof assigned so if a malformed key is provided, somebody should complaint
|
||||
// and then get this dealers deposit for themselves)
|
||||
if let Err(err) = validate_key_possession_signature(
|
||||
deps.as_ref(),
|
||||
&info.sender,
|
||||
owner_signature,
|
||||
&ed25519_key,
|
||||
) {
|
||||
// TODO: it looks like blacklisting could use a constructor
|
||||
let blacklisting = Blacklisting {
|
||||
reason: BlacklistingReason::Ed25519PossessionVerificationFailure,
|
||||
height: env.block.height,
|
||||
expiration: Some(env.block.height + INVALID_ED25519_BLACKLISTING_EXPIRATION),
|
||||
};
|
||||
BLACKLISTED_DEALERS.save(deps.storage, &info.sender, &blacklisting)?;
|
||||
return Err(err);
|
||||
}
|
||||
|
||||
// validate and extract sent deposit
|
||||
let _deposit = validate_dealer_deposit(info.funds)?;
|
||||
|
||||
// if it was already a dealer in the past, assign the same node index
|
||||
let node_index =
|
||||
if let Some(prior_details) = PAST_DEALERS.may_load(deps.storage, &info.sender)? {
|
||||
// since this dealer is going to become active now, remove it from the past dealers
|
||||
PAST_DEALERS.remove(deps.storage, &info.sender);
|
||||
prior_details.assigned_index
|
||||
} else {
|
||||
next_node_index(deps.storage)?
|
||||
};
|
||||
|
||||
// save the dealer into the storage
|
||||
let dealer_details = DealerDetails {
|
||||
joined_at: env.block.height,
|
||||
left_at: None,
|
||||
blacklisting: None,
|
||||
ed25519_public_key: ed25519_key,
|
||||
bte_public_key_with_proof: bte_key_with_proof,
|
||||
assigned_index: node_index,
|
||||
};
|
||||
CURRENT_DEALERS.save(deps.storage, &info.sender, &dealer_details)?;
|
||||
|
||||
Ok(Response::new().set_data(node_index.to_be_bytes()))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user