Skip to content

Commit

Permalink
XCS: PFM validation (attempt 2) (#5987)
Browse files Browse the repository at this point in the history
* initial pfm changes. Committing to context switch

* added initial path validation boilerplate

* added pfm validation

* lints

* experimenting with pfm checks in tests

* require forwarding to be setup

* removed replace

* x86 bytecode

* moved "osmosis" into a const

* extracted "osmosis" into a const

* rename

* bytecode

* reset rust version updated by dependabot

* update rust version again

* ensure pfm flag cannot be overriden

* bytecode

* cleanup and avoid race conditions

* make linter happy

* clippy

* bytecode

* Revert "make linter happy"

This reverts commit a8cce36.

* ignore new lint

* typo

* nits and typos

* new bytecode

* fix Boss's comments

* bytecode

* removed proper validation temporarily

* lints

* tests and x86 bytecode
  • Loading branch information
nicolaslara authored Aug 15, 2023
1 parent b94dbe6 commit f4705d9
Show file tree
Hide file tree
Showing 19 changed files with 673 additions and 115 deletions.
65 changes: 51 additions & 14 deletions cosmwasm/contracts/crosschain-registry/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,21 @@ use cosmwasm_std::{to_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response,
use cw2::set_contract_version;

use crate::error::ContractError;
use crate::msg::{ExecuteMsg, GetAddressFromAliasResponse, InstantiateMsg, QueryMsg};
use crate::state::{Config, CONFIG, CONTRACT_ALIAS_MAP};
use crate::{execute, query};
use crate::msg::{
ExecuteMsg, GetAddressFromAliasResponse, IBCLifecycleComplete, InstantiateMsg, QueryMsg,
SudoMsg,
};
use crate::state::{ChainPFM, Config, CHAIN_PFM_MAP, CONFIG, CONTRACT_ALIAS_MAP};
use crate::{execute, ibc_lifecycle, query};
use registry::Registry;

// version info for migration
const CONTRACT_NAME: &str = "crates.io:crosschain-registry";
const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION");

// The name of the chain on which this contract is instantiated
pub const CONTRACT_CHAIN: &str = "osmosis";

#[cfg_attr(not(feature = "imported"), entry_point)]
pub fn instantiate(
deps: DepsMut,
Expand All @@ -27,6 +33,15 @@ pub fn instantiate(
let state = Config { owner };
CONFIG.save(deps.storage, &state)?;

CHAIN_PFM_MAP.save(
deps.storage,
CONTRACT_CHAIN,
&ChainPFM {
acknowledged: true,
validated: true,
},
)?;

Ok(Response::new().add_attribute("method", "instantiate"))
}

Expand Down Expand Up @@ -73,12 +88,16 @@ pub fn execute(
env.block.time,
with_memo,
None,
false,
)?;
deps.api.debug(&format!("transfer_msg: {transfer_msg:?}"));
Ok(Response::new()
.add_message(transfer_msg)
.add_attribute("method", "unwrap_coin"))
}

ExecuteMsg::ProposePFM { chain } => execute::propose_pfm((deps, env, info), chain),
ExecuteMsg::ValidatePFM { chain } => execute::validate_pfm((deps, env, info), chain),
}
}

Expand Down Expand Up @@ -120,6 +139,24 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
QueryMsg::GetChainNameFromBech32Prefix { prefix } => {
to_binary(&query::query_chain_name_from_bech32_prefix(deps, prefix)?)
}
QueryMsg::HasPacketForwarding { chain } => {
to_binary(&query::query_chain_has_pfm(deps, chain))
}
}
}

#[cfg_attr(not(feature = "imported"), entry_point)]
pub fn sudo(deps: DepsMut, _env: Env, msg: SudoMsg) -> Result<Response, ContractError> {
match msg {
SudoMsg::IBCLifecycleComplete(IBCLifecycleComplete::IBCAck {
channel,
sequence,
ack,
success,
}) => ibc_lifecycle::receive_ack(deps, channel, sequence, ack, success),
SudoMsg::IBCLifecycleComplete(IBCLifecycleComplete::IBCTimeout { channel, sequence }) => {
ibc_lifecycle::receive_timeout(deps, channel, sequence)
}
}
}

Expand Down Expand Up @@ -211,7 +248,7 @@ mod test {
deps.as_ref(),
mock_env(),
QueryMsg::GetChannelFromChainPair {
source_chain: "osmosis".to_string(),
source_chain: CONTRACT_CHAIN.to_string(),
destination_chain: "juno".to_string(),
},
)
Expand All @@ -224,7 +261,7 @@ mod test {
deps.as_ref(),
mock_env(),
QueryMsg::GetDestinationChainFromSourceChainViaChannel {
on_chain: "osmosis".to_string(),
on_chain: CONTRACT_CHAIN.to_string(),
via_channel: "channel-42".to_string(),
},
)
Expand All @@ -237,7 +274,7 @@ mod test {
deps.as_ref(),
mock_env(),
QueryMsg::GetChannelFromChainPair {
source_chain: "osmosis".to_string(),
source_chain: CONTRACT_CHAIN.to_string(),
destination_chain: "stargaze".to_string(),
},
)
Expand All @@ -250,7 +287,7 @@ mod test {
deps.as_ref(),
mock_env(),
QueryMsg::GetDestinationChainFromSourceChainViaChannel {
on_chain: "osmosis".to_string(),
on_chain: CONTRACT_CHAIN.to_string(),
via_channel: "channel-75".to_string(),
},
)
Expand All @@ -264,7 +301,7 @@ mod test {
mock_env(),
QueryMsg::GetChannelFromChainPair {
source_chain: "stargaze".to_string(),
destination_chain: "osmosis".to_string(),
destination_chain: CONTRACT_CHAIN.to_string(),
},
)
.unwrap();
Expand All @@ -282,14 +319,14 @@ mod test {
)
.unwrap();
let destination_chain: String = from_binary(&destination_chain).unwrap();
assert_eq!("osmosis", destination_chain);
assert_eq!(CONTRACT_CHAIN, destination_chain);

// Attempt to retrieve a link that doesn't exist and check that we get an error
let channel_binary = query(
deps.as_ref(),
mock_env(),
QueryMsg::GetChannelFromChainPair {
source_chain: "osmosis".to_string(),
source_chain: CONTRACT_CHAIN.to_string(),
destination_chain: "cerberus".to_string(),
},
);
Expand All @@ -299,7 +336,7 @@ mod test {
let msg = ExecuteMsg::ModifyChainChannelLinks {
operations: vec![ConnectionInput {
operation: execute::FullOperation::Disable,
source_chain: "OSMOSIS".to_string(),
source_chain: CONTRACT_CHAIN.to_string(),
destination_chain: "JUNO".to_string(),
channel_id: Some("CHANNEL-42".to_string()),
new_source_chain: None,
Expand All @@ -316,7 +353,7 @@ mod test {
deps.as_ref(),
mock_env(),
QueryMsg::GetChannelFromChainPair {
source_chain: "osmosis".to_string(),
source_chain: CONTRACT_CHAIN.to_string(),
destination_chain: "juno".to_string(),
},
);
Expand All @@ -326,7 +363,7 @@ mod test {
let msg = ExecuteMsg::ModifyChainChannelLinks {
operations: vec![ConnectionInput {
operation: execute::FullOperation::Enable,
source_chain: "OSMOSIS".to_string(),
source_chain: CONTRACT_CHAIN.to_string(),
destination_chain: "JUNO".to_string(),
channel_id: Some("CHANNEL-42".to_string()),
new_source_chain: None,
Expand All @@ -342,7 +379,7 @@ mod test {
deps.as_ref(),
mock_env(),
QueryMsg::GetChannelFromChainPair {
source_chain: "osmosis".to_string(),
source_chain: CONTRACT_CHAIN.to_string(),
destination_chain: "juno".to_string(),
},
)
Expand Down
24 changes: 23 additions & 1 deletion cosmwasm/contracts/crosschain-registry/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,34 @@ pub enum ContractError {
#[error("{0}")]
Payment(#[from] cw_utils::PaymentError),

#[error("Unauthorized")]
#[error("unauthorized")]
Unauthorized {},

#[error("chain validation not started for {chain}")]
ValidationNotFound { chain: String },

#[error("coin from invalid chain. It belongs to {supplied_chain} and should be from {expected_chain}")]
CoinFromInvalidChain {
supplied_chain: String,
expected_chain: String,
},

#[error(
"only messages initialized by the address of this contract in another chain are allowed. Expected {expected_sender} but got {actual_sender}"
)]
InvalidSender {
expected_sender: String,
actual_sender: String,
},

#[error("contract alias already exists: {alias:?}")]
AliasAlreadyExists { alias: String },

#[error(
"PFM validation already in progress for {chain:?}. Wait for the ibc lifecycle to complete"
)]
PFMValidationAlreadyInProgress { chain: String },

#[error("authorized address already exists for source chain: {source_chain:?}")]
ChainAuthorizedAddressAlreadyExists { source_chain: String },

Expand Down
Loading

0 comments on commit f4705d9

Please sign in to comment.