Skip to content

Commit

Permalink
Add randomness using Nois
Browse files Browse the repository at this point in the history
  • Loading branch information
nenadalm committed Aug 1, 2023
1 parent 8556be8 commit f06e5a1
Show file tree
Hide file tree
Showing 6 changed files with 193 additions and 33 deletions.
41 changes: 41 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ komple-framework-metadata-module = { version = "1.1.1-beta", features = ["librar
komple-framework-mint-module = { version = "1.1.1-beta", features = ["library"] }
komple-framework-token-module = { version = "1.1.1-beta", features = ["library"] }
komple-framework-types = "1.1.1-beta"
nois = "0.7.0"
schemars = "0.8.10"
serde = { version = "1.0.145", default-features = false, features = ["derive"] }
thiserror = { version = "1.0.31" }
Expand Down
35 changes: 26 additions & 9 deletions scripts/deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,24 @@ shopt -s inherit_errexit

ADMIN="${1:-juno1zk4c4aamef42cgjexlmksypac8j5xw7n3s4wrd}"
KOMPLE_MINT_ADDR="${KOMPLE_MINT_ADDR:-juno17rth4jstxs7cmrusvyluwlnt34l80cxaz7nufpjfntts00pk79asjxelgs}"
NOIS_PROXY="${NOIS_PROXY:-juno17xgzprnr0j4cs72t7xfsr2lsmw8guwj640tr8e96nld524f0gmhq0hewqc}"

# https://docs.nois.network/node_operators/testnet_005.html#uni-6
# leave NOIS_PROXY empty to not use randomness
# NOIS_PROXY="${NOIS_PROXY:-juno1pjpntyvkxeuxd709jlupuea3xzxlzsfq574kqefv77fr2kcg4mcqvwqedq}"
NOIS_PROXY=

JUNOFARMS_PATH='../junofarms'

# https://stackoverflow.com/questions/44792241/constructing-a-json-object-from-a-bash-associative-array#answer-44792751
function json_stringify_object {
local -n json_stringify_object__ref="${1}"

for k in "${!json_stringify_object__ref[@]}"; do
echo "${k}"
echo "${json_stringify_object__ref[$k]}"
done | jq -nR 'reduce inputs as $i ({}; . + {($i): input})'
}

function update_contract_address {
local new_address="${1}"

Expand Down Expand Up @@ -85,19 +99,22 @@ function upload_noise_code {
function instantiate {
local code_id="${1}"

local msg
msg=$(cat <<END
{
"admin": "${ADMIN}",
"komple_mint_addr": "${KOMPLE_MINT_ADDR}"
}
END
local -A data=(
[admin]="${ADMIN}"
[komple_mint_addr]="${KOMPLE_MINT_ADDR}"
)

if [[ -n "${NOIS_PROXY}" ]]; then
data[nois_proxy]="${NOIS_PROXY}"
fi

local msg
msg="$(json_stringify_object data)"

echo "[DEBUG] Instantiating with: ${msg}" >&2

local response
response=$(junod --chain-id uni-6 --node https://juno-testnet-rpc.polkachu.com:443 tx wasm instantiate "${code_id}" "${msg}" --from "${ADMIN}" --admin "${ADMIN}" --gas-prices 0.075ujunox --gas auto --gas-adjustment 1.1 --label " " -o json -y)
response=$(junod --chain-id uni-6 --node https://juno-testnet-rpc.polkachu.com:443 tx wasm instantiate "${code_id}" "${msg}" --from "${ADMIN}" --admin "${ADMIN}" --gas-prices 0.075ujunox --gas auto --gas-adjustment 2 --label " " -o json -y)
assert_response_success "${response}" "Instantiating failed"

local tx_hash
Expand Down
133 changes: 109 additions & 24 deletions src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,69 @@ use std::collections::HashMap;
#[cfg(not(feature = "library"))]
use cosmwasm_std::entry_point;
use cosmwasm_std::{
to_binary, Binary, CosmosMsg, Deps, DepsMut, Env, MessageInfo, Order, Response, StdResult,
WasmMsg,
ensure_eq, to_binary, Binary, CosmosMsg, Deps, DepsMut, Env, MessageInfo, Order, Response,
StdResult, Storage, WasmMsg,
};
use cw2::set_contract_version;
use komple_framework_mint_module::msg::ExecuteMsg as KompleMintExecuteMsg;
use nois::{int_in_range, NoisCallback, ProxyExecuteMsg};

use crate::error::ContractError;
use crate::farm::KomplePlant;
use crate::msg::{ContractInformation, ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg};

use crate::helpers::throw_err;
use crate::receive::receive;
use crate::state::{farm_profile_dto, points, FarmProfile, Points, FARM_PROFILES, INFORMATION};
use crate::state::{
farm_profile_dto, points, FarmProfile, NoiseJob, Points, FARM_PROFILES, INFORMATION, NOIS_JOBS,
NOIS_PROXY,
};

const CONTRACT_NAME: &str = "crates.io:farm_template";
const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION");

fn mint_seeds(
plant: KomplePlant,
recipient: String,
seeds: i32,
storage: &dyn Storage,
) -> Result<Vec<CosmosMsg>, ContractError> {
let information = INFORMATION.load(storage)?;
let admin_mint_nft = match information.komple_mint_addr {
None => Err(throw_err("Komple mint addr missing.")),
Some(komple_mint_addr) => Ok(WasmMsg::Execute {
contract_addr: komple_mint_addr,
msg: to_binary::<KompleMintExecuteMsg>(&KompleMintExecuteMsg::AdminMint {
collection_id: plant.collection_id,
recipient,
metadata_id: Some(plant.metadata_id),
})?,
funds: vec![],
}),
}?;

let mut messages: Vec<CosmosMsg> = vec![];
for _i in 0..seeds {
messages.push(admin_mint_nft.clone().into());
}

Ok(messages)
}

fn noise_job(
noise_job: NoiseJob,
randomness: [u8; 32],
storage: &dyn Storage,
) -> Result<Vec<CosmosMsg>, ContractError> {
match noise_job {
NoiseJob::MintSeeds { plant, recipient } => {
let seeds = int_in_range(randomness, 2, 5);

mint_seeds(plant, recipient, seeds, storage)
}
}
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn instantiate(
deps: DepsMut,
Expand All @@ -39,6 +86,14 @@ pub fn instantiate(
},
)?;

match msg.nois_proxy {
None => (),
Some(addr) => {
let nois_proxy_addr = deps.api.addr_validate(&addr)?;
NOIS_PROXY.save(deps.storage, &nois_proxy_addr)?;
}
}

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

Expand Down Expand Up @@ -110,6 +165,25 @@ pub fn execute(

ExecuteMsg::ReceiveNft(msg) => receive(deps, env, info, msg),

ExecuteMsg::NoisReceive { callback } => {
let proxy = NOIS_PROXY.load(deps.storage)?;
ensure_eq!(info.sender, proxy, throw_err("Unauthorized sender"));

let NoisCallback {
job_id, randomness, ..
} = callback;

let randomness: [u8; 32] = randomness
.to_array()
.map_err(|_| throw_err("Invalid randomness"))?;

let job = NOIS_JOBS.load(deps.storage, &job_id)?;
NOIS_JOBS.remove(deps.storage, &job_id);
let messages = noise_job(job, randomness, deps.storage)?;

Ok(Response::new().add_messages(messages))
}

ExecuteMsg::WaterPlant { x, y } => {
let sender = info.sender.to_string();
let farm: Option<FarmProfile> =
Expand Down Expand Up @@ -142,30 +216,41 @@ pub fn execute(
x, y
))),
Some(plant) => {
let information = INFORMATION.load(deps.storage)?;
let admin_mint_nft = match information.komple_mint_addr {
None => Err(throw_err("Komple mint addr missing.")),
Some(komple_mint_addr) => match plant.komple {
None => Err(throw_err("Plant komple missing.")),
Some(komple) => Ok(WasmMsg::Execute {
contract_addr: komple_mint_addr,
msg: to_binary::<KompleMintExecuteMsg>(
&KompleMintExecuteMsg::AdminMint {
collection_id: komple.collection_id,
let messages = match plant.komple {
None => Err(throw_err("Plant komple missing.")),
Some(komple) => {
let nois_proxy = NOIS_PROXY.may_load(deps.storage)?;
match nois_proxy {
None => mint_seeds(
komple,
info.sender.into_string(),
2,
deps.storage,
),
Some(nois_proxy) => {
let job = NoiseJob::MintSeeds {
plant: komple,
recipient: info.sender.into_string(),
metadata_id: Some(komple.metadata_id),
},
)?,
funds: vec![],
}),
},
};
NOIS_JOBS.save(deps.storage, "val", &job)?;

let mut messages: Vec<CosmosMsg> = vec![];
let msg = WasmMsg::Execute {
contract_addr: nois_proxy.into(),
msg: to_binary(
&ProxyExecuteMsg::GetNextRandomness {
job_id: "val".into(), // todo: uuid?
},
)?,
funds: info.funds.clone(),
};
messages.push(msg.into());
Ok(messages)
}
}
}
}?;

let mut messages: Vec<CosmosMsg> = vec![];
for _i in 0..2 {
messages.push(admin_mint_nft.clone().into());
}

let harvested = farm.harvest(x.into(), y.into(), env.block.height)?;
let mut pts = match points().may_load(deps.storage, sender.as_str())? {
None => Points {
Expand Down
5 changes: 5 additions & 0 deletions src/msg.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
use cosmwasm_schema::{cw_serde, QueryResponses};
use cosmwasm_std::Addr;
use cw721::Cw721ReceiveMsg;
use nois::NoisCallback;

use crate::state::{FarmProfile, FarmProfileDto};

#[cw_serde]
pub struct InstantiateMsg {
pub admin: Option<String>,
pub komple_mint_addr: Option<String>,
pub nois_proxy: Option<String>,
}

#[cw_serde]
Expand Down Expand Up @@ -37,6 +39,9 @@ pub enum ExecuteMsg {
contract_information: ContractInformation,
},
ReceiveNft(Cw721ReceiveMsg),
NoisReceive {
callback: NoisCallback,
},
}

#[cw_serde]
Expand Down
11 changes: 11 additions & 0 deletions src/state.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::collections::HashMap;

use cosmwasm_schema::cw_serde;
use cosmwasm_std::Addr;
use cw_storage_plus::{Index, IndexList, IndexedMap, Item, Map, MultiIndex};

use crate::{
Expand Down Expand Up @@ -78,8 +79,18 @@ pub struct FarmProfileDto {
blocks: u64,
}

#[cw_serde]
pub enum NoiseJob {
MintSeeds {
plant: KomplePlant,
recipient: String,
},
}

pub const FARM_PROFILES: Map<&str, FarmProfile> = Map::new("farm_profiles");
pub const INFORMATION: Item<ContractInformation> = Item::new("info");
pub const NOIS_PROXY: Item<Addr> = Item::new("nois_proxy");
pub const NOIS_JOBS: Map<&str, NoiseJob> = Map::new("nois_jobs");

#[cw_serde]
pub struct Points {
Expand Down

0 comments on commit f06e5a1

Please sign in to comment.