From 69fc688077585a1ca263bfef2d6b7c60e6017875 Mon Sep 17 00:00:00 2001 From: Giacomo Encicliati Date: Fri, 10 Nov 2023 22:52:09 +0100 Subject: [PATCH 1/2] Msg type implementation and msgs condition --- Cargo.lock | 44 +++++++--- contracts/warp-account/src/contract.rs | 28 ++++-- contracts/warp-controller/src/contract.rs | 3 - contracts/warp-controller/src/error.rs | 3 + .../warp-controller/src/execute/controller.rs | 4 +- contracts/warp-controller/src/execute/job.rs | 45 ++++++---- contracts/warp-resolver/Cargo.toml | 4 +- contracts/warp-resolver/src/contract.rs | 25 ++++-- contracts/warp-resolver/src/tests.rs | 33 ++++--- contracts/warp-resolver/src/util/variable.rs | 87 ++++++++++++++++--- packages/account/src/lib.rs | 12 +++ packages/controller/src/job.rs | 4 +- packages/resolver/src/lib.rs | 4 +- 13 files changed, 215 insertions(+), 81 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8e23f20c..929a4dc6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -636,9 +636,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.56" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" dependencies = [ "unicode-ident", ] @@ -691,9 +691,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.26" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -803,13 +803,22 @@ checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" [[package]] name = "serde" -version = "1.0.160" +version = "1.0.192" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" +checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" dependencies = [ "serde_derive", ] +[[package]] +name = "serde-cw-value" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75d32da6b8ed758b7d850b6c3c08f1d7df51a4df3cb201296e63e34a78e99d4" +dependencies = [ + "serde", +] + [[package]] name = "serde-json-wasm" version = "0.4.1" @@ -828,15 +837,24 @@ dependencies = [ "serde", ] +[[package]] +name = "serde-json-wasm" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83c37d03f3b0f6b5f77c11af1e7c772de1c9af83e50bef7bb6069601900ba67b" +dependencies = [ + "serde", +] + [[package]] name = "serde_derive" -version = "1.0.160" +version = "1.0.192" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" +checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.39", ] [[package]] @@ -949,9 +967,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.15" +version = "2.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" dependencies = [ "proc-macro2", "quote", @@ -1080,6 +1098,7 @@ dependencies = [ name = "warp-resolver" version = "0.1.0" dependencies = [ + "account", "base64", "controller", "cosmwasm-schema", @@ -1094,7 +1113,8 @@ dependencies = [ "json-codec-wasm", "resolver", "schemars", - "serde-json-wasm 0.4.1", + "serde-cw-value", + "serde-json-wasm 1.0.0", "thiserror", ] diff --git a/contracts/warp-account/src/contract.rs b/contracts/warp-account/src/contract.rs index daa191d5..9daa93dd 100644 --- a/contracts/warp-account/src/contract.rs +++ b/contracts/warp-account/src/contract.rs @@ -2,7 +2,7 @@ use crate::state::CONFIG; use crate::ContractError; use account::{ Config, ExecuteMsg, IbcTransferMsg, InstantiateMsg, MigrateMsg, QueryMsg, TimeoutBlock, - WithdrawAssetsMsg, + WarpMsgsMsg, WithdrawAssetsMsg, }; use controller::account::{AssetInfo, Cw721ExecuteMsg}; use cosmwasm_std::CosmosMsg::Stargate; @@ -52,7 +52,8 @@ pub fn execute( .add_messages(data.msgs) .add_attribute("action", "generic")), ExecuteMsg::WithdrawAssets(data) => withdraw_assets(deps, env, info, data), - ExecuteMsg::IbcTransfer(data) => ibc_transfer(deps, env, info, data), + ExecuteMsg::IbcTransfer(data) => ibc_transfer(env, data), + ExecuteMsg::WarpMsgs(data) => execute_warp_msgs(env, data), } } @@ -71,12 +72,7 @@ pub fn migrate(_deps: DepsMut, _env: Env, _msg: MigrateMsg) -> Result Result { +pub fn ibc_transfer(env: Env, msg: IbcTransferMsg) -> Result { let mut transfer_msg = msg.transfer_msg.clone(); if msg.timeout_block_delta.is_some() && msg.transfer_msg.timeout_block.is_some() { @@ -104,6 +100,22 @@ pub fn ibc_transfer( })) } +pub fn execute_warp_msgs(env: Env, msg: WarpMsgsMsg) -> Result { + let msgs = msg + .msgs + .into_iter() + .map(|msg| -> Result { + match msg { + account::WarpMsgType::Generic(msg) => Ok(msg), + account::WarpMsgType::IbcTransfer(msg) => ibc_transfer(env.clone(), msg) + .map(|val| val.messages.first().unwrap().msg.clone()), + } + }) + .collect::, ContractError>>()?; + + Ok(Response::new().add_messages(msgs)) +} + pub fn withdraw_assets( deps: DepsMut, env: Env, diff --git a/contracts/warp-controller/src/contract.rs b/contracts/warp-controller/src/contract.rs index 84f1d691..cc667a2e 100644 --- a/contracts/warp-controller/src/contract.rs +++ b/contracts/warp-controller/src/contract.rs @@ -85,11 +85,8 @@ pub fn execute( ExecuteMsg::UpdateJob(data) => execute::job::update_job(deps, env, info, data), ExecuteMsg::ExecuteJob(data) => execute::job::execute_job(deps, env, info, data), ExecuteMsg::EvictJob(data) => execute::job::evict_job(deps, env, info, data), - ExecuteMsg::CreateAccount(data) => execute::account::create_account(deps, env, info, data), - ExecuteMsg::UpdateConfig(data) => execute::controller::update_config(deps, env, info, data), - ExecuteMsg::MigrateAccounts(data) => { execute::controller::migrate_accounts(deps, env, info, data) } diff --git a/contracts/warp-controller/src/error.rs b/contracts/warp-controller/src/error.rs index 174fc4f2..9d698e96 100644 --- a/contracts/warp-controller/src/error.rs +++ b/contracts/warp-controller/src/error.rs @@ -81,6 +81,9 @@ pub enum ContractError { #[error("Eviction period not elapsed.")] EvictionPeriodNotElapsed {}, + + #[error("No msgs to trigger")] + NoMsgToTrigger {}, } impl From for ContractError { diff --git a/contracts/warp-controller/src/execute/controller.rs b/contracts/warp-controller/src/execute/controller.rs index 221ec294..ea6e94b5 100644 --- a/contracts/warp-controller/src/execute/controller.rs +++ b/contracts/warp-controller/src/execute/controller.rs @@ -280,7 +280,7 @@ pub fn migrate_pending_jobs( description: v1_job.description, labels: v1_job.labels, status: v1_job.status, - condition: serde_json_wasm::to_string(&v1_job.condition)?, + condition: Some(serde_json_wasm::to_string(&v1_job.condition)?), terminate_condition: None, msgs: new_msgs.to_string(), vars: serde_json_wasm::to_string(&new_vars)?, @@ -382,7 +382,7 @@ pub fn migrate_finished_jobs( description: v1_job.description, labels: v1_job.labels, status: v1_job.status, - condition: serde_json_wasm::to_string(&v1_job.condition)?, + condition: Some(serde_json_wasm::to_string(&v1_job.condition)?), terminate_condition: None, msgs: new_msgs, vars: serde_json_wasm::to_string(&new_vars)?, diff --git a/contracts/warp-controller/src/execute/job.rs b/contracts/warp-controller/src/execute/job.rs index fe104dda..4778ab91 100644 --- a/contracts/warp-controller/src/execute/job.rs +++ b/contracts/warp-controller/src/execute/job.rs @@ -1,7 +1,7 @@ use crate::state::{ACCOUNTS, CONFIG, FINISHED_JOBS, PENDING_JOBS, STATE}; use crate::ContractError; use crate::ContractError::EvictionPeriodNotElapsed; -use account::GenericMsg; +use account::{GenericMsg, WarpMsgType, WarpMsgsMsg}; use controller::job::{ CreateJobMsg, DeleteJobMsg, EvictJobMsg, ExecuteJobMsg, Job, JobStatus, UpdateJobMsg, }; @@ -333,13 +333,17 @@ pub fn execute_job( }), )?; - let resolution: StdResult = deps.querier.query_wasm_smart( - config.resolver_address.clone(), - &resolver::QueryMsg::QueryResolveCondition(resolver::QueryResolveConditionMsg { - condition: job.condition, - vars: vars.clone(), - }), - ); + // Match condition and try to resolve in case it has been provided + let resolution: StdResult = match job.condition { + Some(condition) => deps.querier.query_wasm_smart( + config.resolver_address.clone(), + &resolver::QueryMsg::QueryResolveCondition(resolver::QueryResolveConditionMsg { + condition, + vars: vars.clone(), + }), + ), + None => Ok(true), + }; let mut attrs = vec![]; let mut submsgs = vec![]; @@ -387,14 +391,23 @@ pub fn execute_job( id: job.id.u64(), msg: CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: account.account.to_string(), - msg: to_binary(&account::ExecuteMsg::Generic(GenericMsg { - msgs: deps.querier.query_wasm_smart( - config.resolver_address, - &resolver::QueryMsg::QueryHydrateMsgs(QueryHydrateMsgsMsg { - msgs: job.msgs, - vars, - }), - )?, + msg: to_binary(&account::ExecuteMsg::WarpMsgs(WarpMsgsMsg { + msgs: deps + .querier + .query_wasm_smart::>( + config.resolver_address, + &resolver::QueryMsg::QueryHydrateMsgs(QueryHydrateMsgsMsg { + msgs: job.msgs, + vars, + }), + ) + .map(|msgs| { + if msgs.is_empty() { + Err(ContractError::NoMsgToTrigger {}) + } else { + Ok(msgs) + } + })??, }))?, funds: vec![], }), diff --git a/contracts/warp-resolver/Cargo.toml b/contracts/warp-resolver/Cargo.toml index 2e2456c6..bbc32d76 100644 --- a/contracts/warp-resolver/Cargo.toml +++ b/contracts/warp-resolver/Cargo.toml @@ -41,9 +41,11 @@ cw20 = "0.16" cw721 = "0.16.0" resolver = { path = "../../packages/resolver", default-features = false, version = "*" } controller = { path = "../../packages/controller", default-features = false, version = "*" } +account = { path = "../../packages/account", default-features = false, version = "*" } schemars = "0.8" +serde-cw-value = "0.7.0" thiserror = "1" -serde-json-wasm = "0.4.1" +serde-json-wasm = "1.0.0" json-codec-wasm = "0.1.0" [dev-dependencies] diff --git a/contracts/warp-resolver/src/contract.rs b/contracts/warp-resolver/src/contract.rs index 769f65a9..26a3acd6 100644 --- a/contracts/warp-resolver/src/contract.rs +++ b/contracts/warp-resolver/src/contract.rs @@ -4,9 +4,9 @@ use crate::util::variable::{ vars_valid, }; use crate::ContractError; +use account::WarpMsgType; use cosmwasm_std::{ - entry_point, to_binary, Binary, CosmosMsg, Deps, DepsMut, Env, MessageInfo, Response, StdError, - StdResult, + entry_point, to_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult, }; use resolver::condition::Condition; @@ -192,8 +192,11 @@ fn query_validate_job_creation( _env: Env, data: QueryValidateJobCreationMsg, ) -> StdResult { - let _condition: Condition = serde_json_wasm::from_str(&data.condition) - .map_err(|e| StdError::generic_err(format!("Condition input invalid: {}", e)))?; + // Try deserialize condition only if provided + if let Some(condition) = &data.condition { + serde_json_wasm::from_str::(condition) + .map_err(|e| StdError::generic_err(format!("Condition input invalid: {}", e)))?; + } let terminate_condition_str = data.terminate_condition.clone().unwrap_or("".to_string()); if !terminate_condition_str.is_empty() { let _terminate_condition: Condition = serde_json_wasm::from_str(&terminate_condition_str) @@ -216,7 +219,11 @@ fn query_validate_job_creation( )); } - if !(string_vars_in_vector(&vars, &data.condition) + // Check condition contains vars only if condition is provided + if !(data + .condition + .map(|condition| string_vars_in_vector(&vars, &condition)) + .unwrap_or(true) && string_vars_in_vector(&vars, &terminate_condition_str) && string_vars_in_vector(&vars, &data.msgs)) { @@ -268,14 +275,14 @@ fn query_apply_var_fn(deps: Deps, env: Env, data: QueryApplyVarFnMsg) -> StdResu } fn query_hydrate_msgs( - _deps: Deps, - _env: Env, + deps: Deps, + env: Env, data: QueryHydrateMsgsMsg, -) -> StdResult> { +) -> StdResult> { let vars: Vec = serde_json_wasm::from_str(&data.vars).map_err(|e| StdError::generic_err(e.to_string()))?; - hydrate_msgs(data.msgs, vars).map_err(|e| StdError::generic_err(e.to_string())) + hydrate_msgs(deps, env, data.msgs, vars).map_err(|e| StdError::generic_err(e.to_string())) } pub fn query_simulate_query( diff --git a/contracts/warp-resolver/src/tests.rs b/contracts/warp-resolver/src/tests.rs index cff5e899..e563ba3e 100644 --- a/contracts/warp-resolver/src/tests.rs +++ b/contracts/warp-resolver/src/tests.rs @@ -1,3 +1,4 @@ +use account::WarpMsgType; use schemars::_serde_json::json; use crate::util::variable::{hydrate_msgs, hydrate_vars}; @@ -20,7 +21,7 @@ fn test() { let _info = mock_info("vlad", &[]); let env = mock_env(); let msg = QueryValidateJobCreationMsg { - condition: "{\"expr\":{\"decimal\":{\"op\":\"gte\",\"left\":{\"ref\":\"$warp.variable.return_amount\"},\"right\":{\"simple\":\"620000\"}}}}".parse().unwrap(), + condition: Some("{\"expr\":{\"decimal\":{\"op\":\"gte\",\"left\":{\"ref\":\"$warp.variable.return_amount\"},\"right\":{\"simple\":\"620000\"}}}}".parse().unwrap()), terminate_condition: None, vars: "[{\"query\":{\"kind\":\"decimal\",\"name\":\"return_amount\",\"init_fn\":{\"query\":{\"wasm\":{\"smart\":{\"msg\":\"eyJzaW11bGF0aW9uIjp7Im9mZmVyX2Fzc2V0Ijp7ImFtb3VudCI6IjEwMDAwMDAiLCJpbmZvIjp7Im5hdGl2ZV90b2tlbiI6eyJkZW5vbSI6ImliYy9CMzUwNEUwOTI0NTZCQTYxOENDMjhBQzY3MUE3MUZCMDhDNkNBMEZEMEJFN0M4QTVCNUEzRTJERDkzM0NDOUU0In19fX19\",\"contract_addr\":\"terra1fd68ah02gr2y8ze7tm9te7m70zlmc7vjyyhs6xlhsdmqqcjud4dql4wpxr\"}}},\"selector\":\"$.return_amount\"},\"reinitialize\":false,\"encode\":false}}]".to_string(), msgs: "[{\"wasm\":{\"execute\":{\"contract_addr\":\"terra1fd68ah02gr2y8ze7tm9te7m70zlmc7vjyyhs6xlhsdmqqcjud4dql4wpxr\",\"msg\":\"eyJzd2FwIjp7Im9mZmVyX2Fzc2V0Ijp7ImluZm8iOnsibmF0aXZlX3Rva2VuIjp7ImRlbm9tIjoiaWJjL0IzNTA0RTA5MjQ1NkJBNjE4Q0MyOEFDNjcxQTcxRkIwOEM2Q0EwRkQwQkU3QzhBNUI1QTNFMkREOTMzQ0M5RTQifX0sImFtb3VudCI6IjEwMDAwMDAifSwibWF4X3NwcmVhZCI6IjAuNSIsImJlbGllZl9wcmljZSI6IjAuNjEwMzg3MzI3MzgyNDYzODE2In19\",\"funds\":[{\"denom\":\"ibc/B3504E092456BA618CC28AC671A71FB08C6CA0FD0BE7C8A5B5A3E2DD933CC9E4\",\"amount\":\"1000000\"}]}}}]".to_string(), @@ -28,16 +29,13 @@ fn test() { let obj = serde_json_wasm::to_string(&vec!["{\"wasm\":{\"execute\":{\"contract_addr\":\"terra1fd68ah02gr2y8ze7tm9te7m70zlmc7vjyyhs6xlhsdmqqcjud4dql4wpxr\",\"msg\":\"eyJzd2FwIjp7Im9mZmVyX2Fzc2V0Ijp7ImluZm8iOnsibmF0aXZlX3Rva2VuIjp7ImRlbm9tIjoiaWJjL0IzNTA0RTA5MjQ1NkJBNjE4Q0MyOEFDNjcxQTcxRkIwOEM2Q0EwRkQwQkU3QzhBNUI1QTNFMkREOTMzQ0M5RTQifX0sImFtb3VudCI6IjEwMDAwMDAifSwibWF4X3NwcmVhZCI6IjAuNSIsImJlbGllZl9wcmljZSI6IjAuNjEwMzg3MzI3MzgyNDYzODE2In19\",\"funds\":[{\"denom\":\"ibc/B3504E092456BA618CC28AC671A71FB08C6CA0FD0BE7C8A5B5A3E2DD933CC9E4\",\"amount\":\"1000000\"}]}}}"]).unwrap(); let _msg1 = QueryValidateJobCreationMsg { - condition: "{\"expr\":{\"decimal\":{\"op\":\"gte\",\"left\":{\"ref\":\"$warp.variable.return_amount\"},\"right\":{\"simple\":\"620000\"}}}}".parse().unwrap(), + condition: Some("{\"expr\":{\"decimal\":{\"op\":\"gte\",\"left\":{\"ref\":\"$warp.variable.return_amount\"},\"right\":{\"simple\":\"620000\"}}}}".parse().unwrap()), terminate_condition: None, vars: "[{\"query\":{\"kind\":\"decimal\",\"name\":\"return_amount\",\"init_fn\":{\"query\":{\"wasm\":{\"smart\":{\"msg\":\"eyJzaW11bGF0aW9uIjp7Im9mZmVyX2Fzc2V0Ijp7ImFtb3VudCI6IjEwMDAwMDAiLCJpbmZvIjp7Im5hdGl2ZV90b2tlbiI6eyJkZW5vbSI6ImliYy9CMzUwNEUwOTI0NTZCQTYxOENDMjhBQzY3MUE3MUZCMDhDNkNBMEZEMEJFN0M4QTVCNUEzRTJERDkzM0NDOUU0In19fX19\",\"contract_addr\":\"terra1fd68ah02gr2y8ze7tm9te7m70zlmc7vjyyhs6xlhsdmqqcjud4dql4wpxr\"}}},\"selector\":\"$.return_amount\"},\"reinitialize\":false,\"encode\":false}}]".to_string(), msgs: obj.clone(), }; - println!("{}", serde_json_wasm::to_string(&obj).unwrap()); - - let test = query(deps.as_ref(), env, QueryMsg::QueryValidateJobCreation(msg)).unwrap(); - println!("{}", test) + query(deps.as_ref(), env, QueryMsg::QueryValidateJobCreation(msg)).unwrap(); } #[test] @@ -379,7 +377,7 @@ fn test_hydrate_static_nested_vars_and_hydrate_msgs() { }); let vars = vec![var1, var3]; - let hydrated_vars = hydrate_vars(deps.as_ref(), env, vars, None).unwrap(); + let hydrated_vars = hydrate_vars(deps.as_ref(), env.clone(), vars, None).unwrap(); let hydrated_var3 = hydrated_vars[1].clone(); match hydrated_var3.clone() { Variable::Static(static_var) => { @@ -398,32 +396,39 @@ fn test_hydrate_static_nested_vars_and_hydrate_msgs() { {"wasm":{"execute":{"contract_addr":"$warp.variable.var3","msg":"$warp.variable.var3","funds":[]}}}]"# .to_string(); - let hydrated_msgs = - hydrate_msgs(msgs, vec![hydrated_var1, hydrated_var2, hydrated_var3]).unwrap(); + let hydrated_msgs = hydrate_msgs( + deps.as_ref(), + env, + msgs, + vec![hydrated_var1, hydrated_var2, hydrated_var3], + ) + .unwrap(); assert_eq!( hydrated_msgs[0], - CosmosMsg::Wasm(WasmMsg::Execute { + WarpMsgType::Generic(CosmosMsg::Wasm(WasmMsg::Execute { // Because var1.encode = false, contract_addr should use the plain text value contract_addr: "static_value_1".to_string(), msg: Binary::from(raw_str.as_bytes()), funds: vec![] - }) + })) ); assert_eq!( hydrated_msgs[1], - CosmosMsg::Wasm(WasmMsg::Execute { + WarpMsgType::Generic(CosmosMsg::Wasm(WasmMsg::Execute { // Because var3.encode = true, contract_addr should use the encoded value contract_addr: encoded_val, // msg is not Binary::from(encoded_val.as_bytes()) appears to be a cosmos msg thing, not a warp thing msg: Binary::from(raw_str.as_bytes()), funds: vec![] - }) + })) ) + + // new MsgType } #[test] fn test_test() { - println! {"{}", "[\"{\\\"wasm\\\":{\\\"execute\\\":{\\\"contract_addr\\\":\\\"terra1na348k6rvwxje9jj6ftpsapfeyaejxjeq6tuzdmzysps20l6z23smnlv64\\\",\\\"msg\\\":\\\"eyJleGVjdXRlX3N3YXBfb3BlcmF0aW9ucyI6eyJtYXhfc3ByZWFkIjoiMC4xNSIsIm9wZXJhdGlvbnMiOlt7ImFzdHJvX3N3YXAiOnsib2ZmZXJfYXNzZXRfaW5mbyI6eyJuYXRpdmVfdG9rZW4iOnsiZGVub20iOiJ1bHVuYSJ9fSwiYXNrX2Fzc2V0X2luZm8iOnsidG9rZW4iOnsiY29udHJhY3RfYWRkciI6InRlcnJhMXhndnA2cDBxbWw1M3JlcWR5eGdjbDh0dGwwcGtoMG4ybXR4Mm43dHpmYWhuNmUwdmNhN3MwZzdzZzYifX19fSx7ImFzdHJvX3N3YXAiOnsib2ZmZXJfYXNzZXRfaW5mbyI6eyJ0b2tlbiI6eyJjb250cmFjdF9hZGRyIjoidGVycmExeGd2cDZwMHFtbDUzcmVxZHl4Z2NsOHR0bDBwa2gwbjJtdHgybjd0emZhaG42ZTB2Y2E3czBnN3NnNiJ9fSwiYXNrX2Fzc2V0X2luZm8iOnsidG9rZW4iOnsiY29udHJhY3RfYWRkciI6InRlcnJhMTY3ZHNxa2gyYWx1cng5OTd3bXljdzl5ZGt5dTU0Z3lzd2UzeWdtcnM0bHd1bWUzdm13a3M4cnVxbnYifX19fV0sIm1pbmltdW1fcmVjZWl2ZSI6IjIzNTM2NjEifX0=\\\",\\\"funds\\\":[{\\\"denom\\\":\\\"uluna\\\",\\\"amount\\\":\\\"10000\\\"}]}}}\"]".replace("\\\\", "")} + // println! {"{}", "[\"{\\\"wasm\\\":{\\\"execute\\\":{\\\"contract_addr\\\":\\\"terra1na348k6rvwxje9jj6ftpsapfeyaejxjeq6tuzdmzysps20l6z23smnlv64\\\",\\\"msg\\\":\\\"eyJleGVjdXRlX3N3YXBfb3BlcmF0aW9ucyI6eyJtYXhfc3ByZWFkIjoiMC4xNSIsIm9wZXJhdGlvbnMiOlt7ImFzdHJvX3N3YXAiOnsib2ZmZXJfYXNzZXRfaW5mbyI6eyJuYXRpdmVfdG9rZW4iOnsiZGVub20iOiJ1bHVuYSJ9fSwiYXNrX2Fzc2V0X2luZm8iOnsidG9rZW4iOnsiY29udHJhY3RfYWRkciI6InRlcnJhMXhndnA2cDBxbWw1M3JlcWR5eGdjbDh0dGwwcGtoMG4ybXR4Mm43dHpmYWhuNmUwdmNhN3MwZzdzZzYifX19fSx7ImFzdHJvX3N3YXAiOnsib2ZmZXJfYXNzZXRfaW5mbyI6eyJ0b2tlbiI6eyJjb250cmFjdF9hZGRyIjoidGVycmExeGd2cDZwMHFtbDUzcmVxZHl4Z2NsOHR0bDBwa2gwbjJtdHgybjd0emZhaG42ZTB2Y2E3czBnN3NnNiJ9fSwiYXNrX2Fzc2V0X2luZm8iOnsidG9rZW4iOnsiY29udHJhY3RfYWRkciI6InRlcnJhMTY3ZHNxa2gyYWx1cng5OTd3bXljdzl5ZGt5dTU0Z3lzd2UzeWdtcnM0bHd1bWUzdm13a3M4cnVxbnYifX19fV0sIm1pbmltdW1fcmVjZWl2ZSI6IjIzNTM2NjEifX0=\\\",\\\"funds\\\":[{\\\"denom\\\":\\\"uluna\\\",\\\"amount\\\":\\\"10000\\\"}]}}}\"]".replace("\\\\", "")} } diff --git a/contracts/warp-resolver/src/util/variable.rs b/contracts/warp-resolver/src/util/variable.rs index fcf29fb5..1b280f9b 100644 --- a/contracts/warp-resolver/src/util/variable.rs +++ b/contracts/warp-resolver/src/util/variable.rs @@ -4,16 +4,21 @@ use crate::util::condition::{ resolve_query_expr_string, resolve_query_expr_uint, resolve_ref_bool, }; use crate::ContractError; +use account::WarpMsgType; use cosmwasm_schema::serde::de::DeserializeOwned; use cosmwasm_schema::serde::Serialize; use cosmwasm_std::{ - Binary, CosmosMsg, Decimal256, Deps, Env, QueryRequest, Uint128, Uint256, WasmQuery, + Binary, CosmosMsg, Decimal256, Deps, Env, QueryRequest, StdError, Uint128, Uint256, WasmQuery, }; +use resolver::condition::Condition; +use serde_cw_value::Value; use std::str::FromStr; use controller::job::{ExternalInput, JobStatus}; use resolver::variable::{QueryExpr, UpdateFnValue, Variable, VariableKind}; +use super::condition::resolve_cond; + pub fn hydrate_vars( deps: Deps, env: Env, @@ -134,20 +139,78 @@ pub fn hydrate_vars( Ok(hydrated_vars) } -pub fn hydrate_msgs(msgs: String, vars: Vec) -> Result, ContractError> { - let mut replaced_msgs = msgs; - for var in &vars { - let (name, replacement) = get_replacement_in_struct(var)?; - replaced_msgs = - replaced_msgs.replace(&format!("\"$warp.variable.{}\"", name), &replacement); - if replacement.contains("$warp.variable") { - return Err(ContractError::HydrationError { - msg: "Attempt to inject warp variable.".to_string(), - }); +pub fn hydrate_msgs( + deps: Deps, + env: Env, + msgs: String, + vars: Vec, +) -> Result, ContractError> { + let mut finalized_msgs: Vec = vec![]; + + // split msgs + for msg in serde_json_wasm::from_str::>(&msgs)? { + let (condition, msg) = match msg.clone() { + Value::Map(map) => { + // check if condition is a key + let condition = map + .get(&Value::String("condition".to_string())) + .map(|condition_as_value| serde_json_wasm::to_string(condition_as_value)) + .transpose()?; + + println!("{condition:?}"); + + // if msg is a key, parse back the msg to string, otherwise parse the whole msg for retrocompatibility + let msg = map + .get(&Value::String("msg".to_string())) + .map(|msg_as_value| serde_json_wasm::to_string(&msg_as_value)) + .unwrap_or(serde_json_wasm::to_string(&msg))?; + (condition, msg) + } + + _ => { + return Err(ContractError::Std(StdError::generic_err(format!( + "msg as Value should be a map type - value: {msg:#?}" + )))) + } + }; + + // if condition is Some, try to resolve it + if let Some(condition) = condition { + let condition: Condition = serde_json_wasm::from_str(&condition) + .map_err(|e| StdError::generic_err(e.to_string()))?; + + // id condition is not resolved, skip to next msg + if let Err(_) = resolve_cond(deps.clone(), env.clone(), condition, &vars) { + continue; + } + } + + let mut replaced_msg = msg; + + // substitute vars + for var in &vars { + let (name, replacement) = get_replacement_in_struct(var)?; + replaced_msg = + replaced_msg.replace(&format!("\"$warp.variable.{}\"", name), &replacement); + if replacement.contains("$warp.variable") { + return Err(ContractError::HydrationError { + msg: "Attempt to inject warp variable.".to_string(), + }); + } + } + + // try deserialize the replaced msg in CosmosMsg (for retrocompatibility) or in WasmMsgType + + match serde_json_wasm::from_str::(&replaced_msg) { + Ok(msg) => finalized_msgs.push(WarpMsgType::Generic(msg)), + Err(_) => match serde_json_wasm::from_str::(&replaced_msg) { + Ok(msg) => finalized_msgs.push(msg), + Err(_) => return Err(ContractError::Std(StdError::generic_err(format!("Error during deserialize msg as string into CosmosMsg | WarpMsgType - value: {replaced_msg}")))) + }, } } - Ok(serde_json_wasm::from_str::>(&replaced_msgs)?) + Ok(finalized_msgs) } fn get_replacement_in_struct(var: &Variable) -> Result<(String, String), ContractError> { diff --git a/packages/account/src/lib.rs b/packages/account/src/lib.rs index 2674516b..186c13e0 100644 --- a/packages/account/src/lib.rs +++ b/packages/account/src/lib.rs @@ -22,6 +22,7 @@ pub enum ExecuteMsg { Generic(GenericMsg), WithdrawAssets(WithdrawAssetsMsg), IbcTransfer(IbcTransferMsg), + WarpMsgs(WarpMsgsMsg), } #[cw_serde] @@ -29,6 +30,11 @@ pub struct GenericMsg { pub msgs: Vec, } +#[cw_serde] +pub struct WarpMsgsMsg { + pub msgs: Vec, +} + #[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, prost::Message)] pub struct Coin { #[prost(string, tag = "1")] @@ -93,3 +99,9 @@ pub enum QueryMsg { #[cw_serde] pub struct MigrateMsg {} + +#[cw_serde] +pub enum WarpMsgType { + Generic(CosmosMsg), + IbcTransfer(IbcTransferMsg), +} diff --git a/packages/controller/src/job.rs b/packages/controller/src/job.rs index 37939f30..528a5210 100644 --- a/packages/controller/src/job.rs +++ b/packages/controller/src/job.rs @@ -28,7 +28,7 @@ pub struct Job { pub description: String, pub labels: Vec, pub status: JobStatus, - pub condition: String, + pub condition: Option, pub terminate_condition: Option, pub msgs: String, pub vars: String, @@ -58,7 +58,7 @@ pub struct CreateJobMsg { pub name: String, pub description: String, pub labels: Vec, - pub condition: String, + pub condition: Option, pub terminate_condition: Option, pub msgs: String, pub vars: String, diff --git a/packages/resolver/src/lib.rs b/packages/resolver/src/lib.rs index 8030e6ea..ab26b89c 100644 --- a/packages/resolver/src/lib.rs +++ b/packages/resolver/src/lib.rs @@ -68,7 +68,7 @@ pub struct ExecuteApplyVarFnMsg { #[cw_serde] pub struct ExecuteValidateJobCreationMsg { - pub condition: String, + pub condition: Option, pub terminate_condition: Option, pub vars: String, pub msgs: String, @@ -76,7 +76,7 @@ pub struct ExecuteValidateJobCreationMsg { #[cw_serde] pub struct QueryValidateJobCreationMsg { - pub condition: String, + pub condition: Option, pub terminate_condition: Option, pub vars: String, pub msgs: String, From 6a20f856978b372f854f4087de6dfe1f8469ff1e Mon Sep 17 00:00:00 2001 From: Giacomo Encicliati Date: Fri, 10 Nov 2023 23:02:08 +0100 Subject: [PATCH 2/2] Code cleanup --- contracts/warp-account/src/contract.rs | 11 +++++------ contracts/warp-controller/src/execute/job.rs | 11 +++++------ contracts/warp-resolver/src/contract.rs | 4 ++-- contracts/warp-resolver/src/tests.rs | 6 +++--- contracts/warp-resolver/src/util/variable.rs | 10 +++++----- packages/account/src/lib.rs | 12 ++++-------- 6 files changed, 24 insertions(+), 30 deletions(-) diff --git a/contracts/warp-account/src/contract.rs b/contracts/warp-account/src/contract.rs index 9daa93dd..b81e9cab 100644 --- a/contracts/warp-account/src/contract.rs +++ b/contracts/warp-account/src/contract.rs @@ -2,7 +2,7 @@ use crate::state::CONFIG; use crate::ContractError; use account::{ Config, ExecuteMsg, IbcTransferMsg, InstantiateMsg, MigrateMsg, QueryMsg, TimeoutBlock, - WarpMsgsMsg, WithdrawAssetsMsg, + WarpMsg, WithdrawAssetsMsg, }; use controller::account::{AssetInfo, Cw721ExecuteMsg}; use cosmwasm_std::CosmosMsg::Stargate; @@ -100,14 +100,13 @@ pub fn ibc_transfer(env: Env, msg: IbcTransferMsg) -> Result Result { - let msgs = msg - .msgs +pub fn execute_warp_msgs(env: Env, msgs: Vec) -> Result { + let msgs = msgs .into_iter() .map(|msg| -> Result { match msg { - account::WarpMsgType::Generic(msg) => Ok(msg), - account::WarpMsgType::IbcTransfer(msg) => ibc_transfer(env.clone(), msg) + account::WarpMsg::Generic(msg) => Ok(msg), + account::WarpMsg::IbcTransfer(msg) => ibc_transfer(env.clone(), msg) .map(|val| val.messages.first().unwrap().msg.clone()), } }) diff --git a/contracts/warp-controller/src/execute/job.rs b/contracts/warp-controller/src/execute/job.rs index 4778ab91..367c0827 100644 --- a/contracts/warp-controller/src/execute/job.rs +++ b/contracts/warp-controller/src/execute/job.rs @@ -1,7 +1,7 @@ use crate::state::{ACCOUNTS, CONFIG, FINISHED_JOBS, PENDING_JOBS, STATE}; use crate::ContractError; use crate::ContractError::EvictionPeriodNotElapsed; -use account::{GenericMsg, WarpMsgType, WarpMsgsMsg}; +use account::{GenericMsg, WarpMsg}; use controller::job::{ CreateJobMsg, DeleteJobMsg, EvictJobMsg, ExecuteJobMsg, Job, JobStatus, UpdateJobMsg, }; @@ -391,10 +391,9 @@ pub fn execute_job( id: job.id.u64(), msg: CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: account.account.to_string(), - msg: to_binary(&account::ExecuteMsg::WarpMsgs(WarpMsgsMsg { - msgs: deps - .querier - .query_wasm_smart::>( + msg: to_binary(&account::ExecuteMsg::WarpMsgs( + deps.querier + .query_wasm_smart::>( config.resolver_address, &resolver::QueryMsg::QueryHydrateMsgs(QueryHydrateMsgsMsg { msgs: job.msgs, @@ -408,7 +407,7 @@ pub fn execute_job( Ok(msgs) } })??, - }))?, + ))?, funds: vec![], }), gas_limit: None, diff --git a/contracts/warp-resolver/src/contract.rs b/contracts/warp-resolver/src/contract.rs index 26a3acd6..9e17d26d 100644 --- a/contracts/warp-resolver/src/contract.rs +++ b/contracts/warp-resolver/src/contract.rs @@ -4,7 +4,7 @@ use crate::util::variable::{ vars_valid, }; use crate::ContractError; -use account::WarpMsgType; +use account::WarpMsg; use cosmwasm_std::{ entry_point, to_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult, }; @@ -278,7 +278,7 @@ fn query_hydrate_msgs( deps: Deps, env: Env, data: QueryHydrateMsgsMsg, -) -> StdResult> { +) -> StdResult> { let vars: Vec = serde_json_wasm::from_str(&data.vars).map_err(|e| StdError::generic_err(e.to_string()))?; diff --git a/contracts/warp-resolver/src/tests.rs b/contracts/warp-resolver/src/tests.rs index e563ba3e..66e44c9d 100644 --- a/contracts/warp-resolver/src/tests.rs +++ b/contracts/warp-resolver/src/tests.rs @@ -1,4 +1,4 @@ -use account::WarpMsgType; +use account::WarpMsg; use schemars::_serde_json::json; use crate::util::variable::{hydrate_msgs, hydrate_vars}; @@ -406,7 +406,7 @@ fn test_hydrate_static_nested_vars_and_hydrate_msgs() { assert_eq!( hydrated_msgs[0], - WarpMsgType::Generic(CosmosMsg::Wasm(WasmMsg::Execute { + WarpMsg::Generic(CosmosMsg::Wasm(WasmMsg::Execute { // Because var1.encode = false, contract_addr should use the plain text value contract_addr: "static_value_1".to_string(), msg: Binary::from(raw_str.as_bytes()), @@ -416,7 +416,7 @@ fn test_hydrate_static_nested_vars_and_hydrate_msgs() { assert_eq!( hydrated_msgs[1], - WarpMsgType::Generic(CosmosMsg::Wasm(WasmMsg::Execute { + WarpMsg::Generic(CosmosMsg::Wasm(WasmMsg::Execute { // Because var3.encode = true, contract_addr should use the encoded value contract_addr: encoded_val, // msg is not Binary::from(encoded_val.as_bytes()) appears to be a cosmos msg thing, not a warp thing diff --git a/contracts/warp-resolver/src/util/variable.rs b/contracts/warp-resolver/src/util/variable.rs index 1b280f9b..83dee9b1 100644 --- a/contracts/warp-resolver/src/util/variable.rs +++ b/contracts/warp-resolver/src/util/variable.rs @@ -4,7 +4,7 @@ use crate::util::condition::{ resolve_query_expr_string, resolve_query_expr_uint, resolve_ref_bool, }; use crate::ContractError; -use account::WarpMsgType; +use account::WarpMsg; use cosmwasm_schema::serde::de::DeserializeOwned; use cosmwasm_schema::serde::Serialize; use cosmwasm_std::{ @@ -144,8 +144,8 @@ pub fn hydrate_msgs( env: Env, msgs: String, vars: Vec, -) -> Result, ContractError> { - let mut finalized_msgs: Vec = vec![]; +) -> Result, ContractError> { + let mut finalized_msgs: Vec = vec![]; // split msgs for msg in serde_json_wasm::from_str::>(&msgs)? { @@ -202,8 +202,8 @@ pub fn hydrate_msgs( // try deserialize the replaced msg in CosmosMsg (for retrocompatibility) or in WasmMsgType match serde_json_wasm::from_str::(&replaced_msg) { - Ok(msg) => finalized_msgs.push(WarpMsgType::Generic(msg)), - Err(_) => match serde_json_wasm::from_str::(&replaced_msg) { + Ok(msg) => finalized_msgs.push(WarpMsg::Generic(msg)), + Err(_) => match serde_json_wasm::from_str::(&replaced_msg) { Ok(msg) => finalized_msgs.push(msg), Err(_) => return Err(ContractError::Std(StdError::generic_err(format!("Error during deserialize msg as string into CosmosMsg | WarpMsgType - value: {replaced_msg}")))) }, diff --git a/packages/account/src/lib.rs b/packages/account/src/lib.rs index 186c13e0..ed8d3d0e 100644 --- a/packages/account/src/lib.rs +++ b/packages/account/src/lib.rs @@ -22,7 +22,7 @@ pub enum ExecuteMsg { Generic(GenericMsg), WithdrawAssets(WithdrawAssetsMsg), IbcTransfer(IbcTransferMsg), - WarpMsgs(WarpMsgsMsg), + WarpMsgs(Vec), } #[cw_serde] @@ -31,8 +31,9 @@ pub struct GenericMsg { } #[cw_serde] -pub struct WarpMsgsMsg { - pub msgs: Vec, +pub enum WarpMsg { + Generic(CosmosMsg), + IbcTransfer(IbcTransferMsg), } #[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, prost::Message)] @@ -100,8 +101,3 @@ pub enum QueryMsg { #[cw_serde] pub struct MigrateMsg {} -#[cw_serde] -pub enum WarpMsgType { - Generic(CosmosMsg), - IbcTransfer(IbcTransferMsg), -}