Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: account seq #164

Merged
merged 9 commits into from
Jun 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion contract/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::{
InstantiateMsg,
QueryMsg,
},
state::TOKEN,
state::{CHAIN_ID, TOKEN},
};

// version info for migration info
Expand All @@ -30,6 +30,7 @@ pub fn instantiate(
set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;
TOKEN.save(deps.storage, &msg.token)?;
OWNER.save(deps.storage, &deps.api.addr_validate(&msg.owner)?)?;
CHAIN_ID.save(deps.storage, &msg.chain_id)?;
PENDING_OWNER.save(deps.storage, &None)?;
let init_config = StakingConfig {
minimum_stake_to_register: Uint128::new(INITIAL_MINIMUM_STAKE_TO_REGISTER),
Expand Down
5 changes: 5 additions & 0 deletions contract/src/msgs/data_requests/execute/commit_result.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::*;
use crate::state::{inc_get_seq, CHAIN_ID};

#[cw_serde]
pub struct Execute {
Expand All @@ -11,12 +12,16 @@ pub struct Execute {
impl Execute {
/// Posts a data result of a data request with an attached hash of the answer and salt.
pub fn execute(self, deps: DepsMut, env: Env, info: MessageInfo) -> Result<Response, ContractError> {
let chain_id = CHAIN_ID.load(deps.storage)?;
// compute message hash
let message_hash = hash([
"commit_data_result".as_bytes(),
&self.dr_id,
&env.block.height.to_be_bytes(),
&self.commitment,
chain_id.as_bytes(),
env.contract.address.as_str().as_bytes(),
&inc_get_seq(deps.storage, &self.public_key)?.to_be_bytes(),
]);

// verify the proof
Expand Down
6 changes: 1 addition & 5 deletions contract/src/msgs/data_requests/execute/post_request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,7 @@ impl Execute {
return Err(ContractError::DataRequestAlreadyExists);
}

// TODO: verify the payback address... it's not a seda addr right?
// let Ok(addr) = Addr::from_slice(&self.payback_address) else {
// return Err(ContractError::InvalidPaybackAddr);
// };

// TODO: verify the payback non seda address...
// TODO: review this event
let res = Response::new()
.add_attribute("action", "post_data_request")
Expand Down
6 changes: 6 additions & 0 deletions contract/src/msgs/data_requests/execute/reveal_result.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::*;
use crate::state::{inc_get_seq, CHAIN_ID};

#[cw_serde]
pub struct Execute {
Expand All @@ -12,6 +13,8 @@ impl Execute {
/// Posts a data result of a data request with an attached result.
/// This removes the data request from the pool and creates a new entry in the data results.
pub fn execute(self, deps: DepsMut, env: Env, info: MessageInfo) -> Result<Response, ContractError> {
let chain_id = CHAIN_ID.load(deps.storage)?;

// compute hash of reveal body
let reveal_body_hash = self.reveal_body.hash();

Expand All @@ -21,6 +24,9 @@ impl Execute {
&self.dr_id,
&env.block.height.to_be_bytes(),
&reveal_body_hash,
chain_id.as_bytes(),
env.contract.address.as_str().as_bytes(),
&inc_get_seq(deps.storage, &self.public_key)?.to_be_bytes(),
]);

// verify the proof
Expand Down
8 changes: 8 additions & 0 deletions contract/src/msgs/data_requests/test_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,15 @@ impl TestInfo {
msg_height: Option<u64>,
env_height: Option<u64>,
) -> Result<(), ContractError> {
let seq = self.get_account_sequence(sender.pub_key());
let msg_hash = hash([
"commit_data_result".as_bytes(),
&dr_id,
&msg_height.unwrap_or_default().to_be_bytes(),
&commitment,
self.chain_id(),
self.contract_addr_bytes(),
&seq.to_be_bytes(),
]);

let msg = commit_result::Execute {
Expand All @@ -132,11 +136,15 @@ impl TestInfo {
msg_height: Option<u64>,
env_height: Option<u64>,
) -> Result<(), ContractError> {
let seq = self.get_account_sequence(sender.pub_key());
let msg_hash = hash([
"reveal_data_result".as_bytes(),
&dr_id,
&msg_height.unwrap_or_default().to_be_bytes(),
&reveal_body.hash(),
self.chain_id(),
self.contract_addr_bytes(),
&seq.to_be_bytes(),
]);

let msg = reveal_result::Execute {
Expand Down
5 changes: 3 additions & 2 deletions contract/src/msgs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ impl QueryMsg {

#[cw_serde]
pub struct InstantiateMsg {
pub token: String,
pub owner: String,
pub token: String,
pub owner: String,
pub chain_id: String,
}
18 changes: 12 additions & 6 deletions contract/src/msgs/staking/execute/increase_stake.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use self::staking::owner::utils::is_staker_allowed;
use super::{state::STAKERS, *};
use super::*;
use crate::{
crypto::{hash, verify_proof},
state::TOKEN,
state::{inc_get_seq, CHAIN_ID, TOKEN},
utils::get_attached_funds,
};

Expand All @@ -14,12 +14,18 @@ pub struct Execute {

impl Execute {
/// Deposits and stakes tokens for an already existing staker.
pub fn execute(self, deps: DepsMut, _env: Env, info: MessageInfo) -> Result<Response, ContractError> {
pub fn execute(self, deps: DepsMut, env: Env, info: MessageInfo) -> Result<Response, ContractError> {
let token = TOKEN.load(deps.storage)?;
let amount = get_attached_funds(&info.funds, &token)?;
let chain_id = CHAIN_ID.load(deps.storage)?;

// compute message hash
let message_hash = hash(["increase_stake".as_bytes()]);
let message_hash = hash([
"increase_stake".as_bytes(),
chain_id.as_bytes(),
env.contract.address.as_str().as_bytes(),
&inc_get_seq(deps.storage, &self.public_key)?.to_be_bytes(),
]);

// verify the proof
verify_proof(&self.public_key, &self.proof, message_hash)?;
Expand All @@ -28,9 +34,9 @@ impl Execute {
is_staker_allowed(&deps, &self.public_key)?;

// update staked tokens for executor
let mut executor = STAKERS.load(deps.storage, &self.public_key)?;
let mut executor = state::STAKERS.load(deps.storage, &self.public_key)?;
executor.tokens_staked += amount;
STAKERS.save(deps.storage, &self.public_key, &executor)?;
state::STAKERS.save(deps.storage, &self.public_key, &executor)?;

let mut event = Event::new("seda-data-request-executor").add_attributes([
("version", CONTRACT_VERSION.to_string()),
Expand Down
4 changes: 2 additions & 2 deletions contract/src/msgs/staking/execute/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ impl ExecuteMsg {
use self::*;

match self {
ExecuteMsg::RegisterAndStake(msg) => msg.execute(deps, info),
ExecuteMsg::RegisterAndStake(msg) => msg.execute(deps, env, info),
ExecuteMsg::IncreaseStake(msg) => msg.execute(deps, env, info),
ExecuteMsg::Unstake(msg) => msg.execute(deps, env, info),
ExecuteMsg::Withdraw(msg) => msg.execute(deps, env, info),
ExecuteMsg::Unregister(msg) => msg.execute(deps, info),
ExecuteMsg::Unregister(msg) => msg.execute(deps, env, info),
ExecuteMsg::SetStakingConfig(msg) => msg.execute(deps, env, info),
}
}
Expand Down
22 changes: 13 additions & 9 deletions contract/src/msgs/staking/execute/register_and_stake.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
use self::staking::owner::utils::is_staker_allowed;
use super::{
state::{CONFIG, STAKERS},
*,
};
use super::*;
use crate::{
crypto::{hash, verify_proof},
msgs::staking::Staker,
state::TOKEN,
state::{inc_get_seq, CHAIN_ID, TOKEN},
types::{Hasher, PublicKey},
utils::get_attached_funds,
};
Expand All @@ -20,9 +17,16 @@ pub struct Execute {

impl Execute {
/// Registers a staker with an optional p2p multi address, requiring a token deposit.
pub fn execute(self, deps: DepsMut, info: MessageInfo) -> Result<Response, ContractError> {
pub fn execute(self, deps: DepsMut, env: Env, info: MessageInfo) -> Result<Response, ContractError> {
let chain_id = CHAIN_ID.load(deps.storage)?;
// compute message hash
let message_hash = hash(["register_and_stake".as_bytes(), &self.memo.hash()]);
let message_hash = hash([
"register_and_stake".as_bytes(),
&self.memo.hash(),
chain_id.as_bytes(),
env.contract.address.as_str().as_bytes(),
&inc_get_seq(deps.storage, &self.public_key)?.to_be_bytes(),
]);

// verify the proof
verify_proof(&self.public_key, &self.proof, message_hash)?;
Expand All @@ -34,7 +38,7 @@ impl Execute {
let token = TOKEN.load(deps.storage)?;
let amount = get_attached_funds(&info.funds, &token)?;

let minimum_stake_to_register = CONFIG.load(deps.storage)?.minimum_stake_to_register;
let minimum_stake_to_register = state::CONFIG.load(deps.storage)?.minimum_stake_to_register;
if amount < minimum_stake_to_register {
return Err(ContractError::InsufficientFunds(minimum_stake_to_register, amount));
}
Expand All @@ -44,7 +48,7 @@ impl Execute {
tokens_staked: amount,
tokens_pending_withdrawal: Uint128::zero(),
};
STAKERS.save(deps.storage, &self.public_key, &executor)?;
state::STAKERS.save(deps.storage, &self.public_key, &executor)?;

let mut event = Event::new("seda-register-and-stake").add_attributes([
("version", CONTRACT_VERSION.to_string()),
Expand Down
21 changes: 15 additions & 6 deletions contract/src/msgs/staking/execute/unregister.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use super::{state::STAKERS, *};
use crate::crypto::{hash, verify_proof};
use super::*;
use crate::{
crypto::{hash, verify_proof},
state::{inc_get_seq, CHAIN_ID},
};

#[cw_serde]
pub struct Execute {
Expand All @@ -9,20 +12,26 @@ pub struct Execute {

impl Execute {
/// Unregisters a staker, with the requirement that no tokens are staked or pending withdrawal.
pub fn execute(self, deps: DepsMut, _info: MessageInfo) -> Result<Response, ContractError> {
pub fn execute(self, deps: DepsMut, env: Env, _info: MessageInfo) -> Result<Response, ContractError> {
let chain_id = CHAIN_ID.load(deps.storage)?;
// compute message hash
let message_hash = hash(["unregister".as_bytes()]);
let message_hash = hash([
"unregister".as_bytes(),
chain_id.as_bytes(),
env.contract.address.as_str().as_bytes(),
&inc_get_seq(deps.storage, &self.public_key)?.to_be_bytes(),
]);

// verify the proof
verify_proof(&self.public_key, &self.proof, message_hash)?;

// require that the executor has no staked or tokens pending withdrawal
let executor = STAKERS.load(deps.storage, &self.public_key)?;
let executor = state::STAKERS.load(deps.storage, &self.public_key)?;
if executor.tokens_staked > Uint128::zero() || executor.tokens_pending_withdrawal > Uint128::zero() {
return Err(ContractError::ExecutorHasTokens);
}

STAKERS.remove(deps.storage, &self.public_key);
state::STAKERS.remove(deps.storage, &self.public_key);

Ok(Response::new().add_attribute("action", "unregister").add_event(
Event::new("seda-unregister").add_attributes([
Expand Down
22 changes: 16 additions & 6 deletions contract/src/msgs/staking/execute/unstake.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use super::{state::STAKERS, *};
use crate::crypto::{hash, verify_proof};
use super::*;
use crate::{
crypto::{hash, verify_proof},
state::{inc_get_seq, CHAIN_ID},
};

#[cw_serde]
pub struct Execute {
Expand All @@ -10,23 +13,30 @@ pub struct Execute {

impl Execute {
/// Unstakes tokens from a given staker, to be withdrawn after a delay.
pub fn execute(self, deps: DepsMut, _env: Env, _info: MessageInfo) -> Result<Response, ContractError> {
pub fn execute(self, deps: DepsMut, env: Env, _info: MessageInfo) -> Result<Response, ContractError> {
let chain_id = CHAIN_ID.load(deps.storage)?;
// compute message hash
let message_hash = hash(["unstake".as_bytes(), &self.amount.to_be_bytes()]);
let message_hash = hash([
"unstake".as_bytes(),
&self.amount.to_be_bytes(),
chain_id.as_bytes(),
env.contract.address.as_str().as_bytes(),
&inc_get_seq(deps.storage, &self.public_key)?.to_be_bytes(),
]);

// verify the proof
verify_proof(&self.public_key, &self.proof, message_hash)?;

// error if amount is greater than staked tokens
let mut executor = STAKERS.load(deps.storage, &self.public_key)?;
let mut executor = state::STAKERS.load(deps.storage, &self.public_key)?;
if self.amount > executor.tokens_staked {
return Err(ContractError::InsufficientFunds(executor.tokens_staked, self.amount));
}

// update the executor
executor.tokens_staked -= self.amount;
executor.tokens_pending_withdrawal += self.amount;
STAKERS.save(deps.storage, &self.public_key, &executor)?;
state::STAKERS.save(deps.storage, &self.public_key, &executor)?;

// TODO: emit when pending tokens can be withdrawn

Expand Down
19 changes: 13 additions & 6 deletions contract/src/msgs/staking/execute/withdraw.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use cosmwasm_std::{coins, BankMsg};

use super::{state::STAKERS, *};
use super::*;
use crate::{
crypto::{hash, verify_proof},
state::TOKEN,
state::{inc_get_seq, CHAIN_ID, TOKEN},
};

#[cw_serde]
Expand All @@ -15,9 +15,16 @@ pub struct Execute {

impl Execute {
/// Sends tokens back to the sender that are marked as pending withdrawal.
pub fn execute(self, deps: DepsMut, _env: Env, info: MessageInfo) -> Result<Response, ContractError> {
pub fn execute(self, deps: DepsMut, env: Env, info: MessageInfo) -> Result<Response, ContractError> {
let chain_id = CHAIN_ID.load(deps.storage)?;
// compute message hash
let message_hash = hash(["withdraw".as_bytes(), &self.amount.to_be_bytes()]);
let message_hash = hash([
"withdraw".as_bytes(),
&self.amount.to_be_bytes(),
chain_id.as_bytes(),
env.contract.address.as_str().as_bytes(),
&inc_get_seq(deps.storage, &self.public_key)?.to_be_bytes(),
]);

// verify the proof
verify_proof(&self.public_key, &self.proof, message_hash)?;
Expand All @@ -26,7 +33,7 @@ impl Execute {
let token = TOKEN.load(deps.storage)?;

// error if amount is greater than pending tokens
let mut executor = STAKERS.load(deps.storage, &self.public_key)?;
let mut executor = state::STAKERS.load(deps.storage, &self.public_key)?;
if self.amount > executor.tokens_pending_withdrawal {
return Err(ContractError::InsufficientFunds(
executor.tokens_pending_withdrawal,
Expand All @@ -36,7 +43,7 @@ impl Execute {

// update the executor
executor.tokens_pending_withdrawal -= self.amount;
STAKERS.save(deps.storage, &self.public_key, &executor)?;
state::STAKERS.save(deps.storage, &self.public_key, &executor)?;

// send the tokens back to the executor
let bank_msg = BankMsg::Send {
Expand Down
Loading