Skip to content

Commit

Permalink
Merge pull request #66 from osmosis-labs/boss/migrate
Browse files Browse the repository at this point in the history
  • Loading branch information
iboss-ptk authored Jul 5, 2022
2 parents cb10163 + f8bda67 commit 75d5121
Show file tree
Hide file tree
Showing 15 changed files with 662 additions and 18 deletions.
81 changes: 81 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,87 @@ beaker wasm deploy counter --signer-account test1 --no-wasm-opt

You can find references for [`beaker wasm` subcommand here](./docs/commands/beaker_wasm.md).

### Contract Upgrade

Contract upgrade in CosmWasm goes through the following steps:

1. store new code on to the chain
2. broadcast migrate msg, targeting the contract address that wanted to be upgraded with the newly stored code

To make a contract migratable, the contract needs to have proper entrypoint and admin designated.

To create the contract entrypoint for migration, first, define `MigrateMsg` in `msg.rs`, this could have any information you want to pass for migration.

```rust
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct MigrateMsg {}
```

With MigrateMsg defined we need to update `contract.rs`. First update the import from `crate::msg` to include `MigrateMsg`:

```rust
use crate::msg::{CountResponse, ExecuteMsg, InstantiateMsg, QueryMsg, MigrateMsg};
```

```rust
#[cfg_attr(not(feature = "library"), entry_point)]
pub fn migrate(_deps: DepsMut, _env: Env, _msg: MigrateMsg) -> StdResult<Response> {
// perform state update or anything neccessary for the migration
Ok(Response::default())
}
```

Now deploy the contract with admin assigned

```sh
# `--admin signer` use signer address (test1's address in this case) as designated admin
# raw address could be passed in as well
beaker wasm deploy counter --signer-account test1 --no-wasm-opt --raw '{ "count": 0 }' --admin signer
```

Now try to change the execute logic a bit to see if the upgrade works:

```rust
pub fn try_increment(deps: DepsMut) -> Result<Response, ContractError> {
STATE.update(deps.storage, |mut state| -> Result<_, ContractError> {
state.count += 1000000000; // 1 -> 1000000000
Ok(state)
})?;

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

With admin as `test1`, only `test1` can upgrade the contract

```sh
beaker wasm upgrade counter --signer-account test1 --raw '{}' --no-wasm-opt
```

Similar to `deploy`, `upgrade` is basiaclly running sequences of commands behind the scene:

```sh
beaker wasm build --no-wasm-opt
beaker wasm store-code counter --signer-account test1 --no-wasm-opt
beaker wasm migrate counter --signer-account test1 --raw '{}'
```

And, like before, `--no-wasm-opt` only means for developement. For mainnet, use:

```sh
beaker wasm upgrade counter --signer-account test1 --raw '{}' --network mainnet
```

Migrate message can be stored for later use:

```sh
mkdir contracts/counter/migrate-msgs
echo '{}' > contracts/counter/migrate-msgs/default.json
beaker wasm upgrade counter --signer-account test1 --no-wasm-opt
```

You can find more information about their options [here](./docs/commands/beaker_wasm.md).

### Console

After deployed, you can play with the deployed contract using:
Expand Down
72 changes: 72 additions & 0 deletions docs/commands/beaker_wasm.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ Arguments:

* `-r/--raw <raw>`: Raw json string to use as instantiate msg

* `--admin <admin>`: Specifying admin required for contract migration. Use "signer" for setting tx signer as admin. Use bech32 address (eg. "osmo1cyyzpxplxdzkeea7kwsydadg87357qnahakaks") for custom admin

* `-f/--funds <funds>`: Funds to send to instantiated contract

* `-n/--network <network>`: Name of the network to broadcast transaction to, the actual endpoint / chain-id are defined in config (default: `local`)
Expand All @@ -108,6 +110,38 @@ Arguments:

---

### `beaker wasm migrate`

Migrated instanitate contract to use other code stored on chain

Arguments:

* `--help`: Print help information

* `--version`: Print version information

* ` <contract-name>`Name of the contract to instantiate

* `-l/--label <label>`: Label for the instantiated contract for selcting migration target (default: `default`)

* `-r/--raw <raw>`: Raw json string to use as instantiate msg

* `-n/--network <network>`: Name of the network to broadcast transaction to, the actual endpoint / chain-id are defined in config (default: `local`)

* `--gas <gas>`: Coin (amount and denom) you are willing to pay as gas eg. `1000uosmo`

* `--gas-limit <gas-limit>`: Limit to how much gas amount allowed to be consumed

* `--signer-account <signer-account>`: Specifies predefined account as a tx signer

* `--signer-mnemonic <signer-mnemonic>`: Specifies mnemonic as a tx signer

* `--signer-private-key <signer-private-key>`: Specifies private_key as a tx signer (base64 encoded string)

* `-t/--timeout-height <timeout-height>`: Specifies a block timeout height to prevent the tx from being committed past a certain height (default: `0`)

---

### `beaker wasm deploy`

Build, Optimize, Store code, and instantiate contract
Expand All @@ -124,6 +158,8 @@ Arguments:

* `-r/--raw <raw>`: Raw json string to use as instantiate msg

* `--admin <admin>`: Specifying admin required for contract migration. Use "signer" for setting tx signer as admin. Use bech32 address (eg. "osmo1cyyzpxplxdzkeea7kwsydadg87357qnahakaks") for custom admin

* `-f/--funds <funds>`: Funds to send to instantiated contract

* `--no-rebuild`: Use existing .wasm file to deploy if set to true
Expand All @@ -146,6 +182,42 @@ Arguments:

---

### `beaker wasm upgrade`

Build, Optimize, Store code, and migrate contract

Arguments:

* `--help`: Print help information

* `--version`: Print version information

* ` <contract-name>`Name of the contract to deploy

* `-l/--label <label>`: Label for the instantiated contract for later reference (default: `default`)

* `-r/--raw <raw>`: Raw json string to use as instantiate msg

* `--no-rebuild`: Use existing .wasm file to deploy if set to true

* `--no-wasm-opt`: If set, skip wasm-opt and store the unoptimized code (only use in dev)

* `-n/--network <network>`: Name of the network to broadcast transaction to, the actual endpoint / chain-id are defined in config (default: `local`)

* `--gas <gas>`: Coin (amount and denom) you are willing to pay as gas eg. `1000uosmo`

* `--gas-limit <gas-limit>`: Limit to how much gas amount allowed to be consumed

* `--signer-account <signer-account>`: Specifies predefined account as a tx signer

* `--signer-mnemonic <signer-mnemonic>`: Specifies mnemonic as a tx signer

* `--signer-private-key <signer-private-key>`: Specifies private_key as a tx signer (base64 encoded string)

* `-t/--timeout-height <timeout-height>`: Specifies a block timeout height to prevent the tx from being committed past a certain height (default: `0`)

---

### `beaker wasm proposal`

[\> `beaker wasm proposal`'s subcommands](./beaker_wasm_proposal.md)
Expand Down
12 changes: 10 additions & 2 deletions docs/commands/beaker_wasm_proposal.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,20 @@ Arguments:

* ` <contract-name>`Name of the contract to store

* `--title <title>`: Proposal title
* `-p/--proposal <proposal>`: Path to proposal file, could be either yaml / toml format

* `-d/--description <description>`: Proposal decsription
* `--title <title>`: Proposal title (default: ``)

* `--description <description>`: Proposal decsription (default: ``)

* `--deposit <deposit>`: Proposal deposit to activate voting

* `--repo <repo>`: Public repository of the code (default: ``)

* `--rust-flags <rust-flags>`: RUST_FLAGS that passed while compiling to wasm If building with Beaker, it's usually "-C link-arg=-s"

* `--optimizer <optimizer>`: Type and version of the [optimizer](https://github.com/CosmWasm/rust-optimizer), either: rust-optimizer:<version> or workspace-optimizer:<version>. Beaker use workspace-optimizer, the version, if not manually configured, can be found in `wasm` config doc

* `-n/--network <network>`: Name of the network to broadcast transaction to, the actual endpoint / chain-id are defined in config (default: `local`)

* `--gas <gas>`: Coin (amount and denom) you are willing to pay as gas eg. `1000uosmo`
Expand Down
3 changes: 3 additions & 0 deletions packages/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,13 @@ prost = "0.10.3"
regex = "1.5.6"
serde = "1.0.137"
serde_json = "1.0.81"
serde_yaml = "0.8"
tokio = {version = "1.18.2", features = ["full"]}
toml = "0.5.9"

[dev_dependencies]
assert_fs = "1.0.7"
cargo_toml = "0.11.5"
predicates = "2.1.1"
pretty_assertions = "1.2.1"
serial_test = "0.6.0"
1 change: 1 addition & 0 deletions packages/cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub struct Cli {
// === APP DEFINITION ===
// Could potentially move all this to macro
#[derive(Subcommand)]
#[allow(clippy::large_enum_variant)]
pub enum Commands {
#[clap(flatten)]
Workspace(WorkspaceCmd),
Expand Down
106 changes: 106 additions & 0 deletions packages/cli/src/modules/wasm/entrypoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,21 @@ pub enum WasmCmd {
#[clap(flatten)]
base_tx_args: BaseTxArgs,
},
/// Migrated instanitate contract to use other code stored on chain
Migrate {
/// Name of the contract to instantiate
contract_name: String,
/// Label for the instantiated contract for selcting migration target
#[clap(short, long, default_value = "default")]
label: String,

/// Raw json string to use as instantiate msg
#[clap(short, long)]
raw: Option<String>,

#[clap(flatten)]
base_tx_args: BaseTxArgs,
},
/// Build, Optimize, Store code, and instantiate contract
Deploy {
/// Name of the contract to deploy
Expand Down Expand Up @@ -102,6 +117,30 @@ pub enum WasmCmd {
#[clap(flatten)]
base_tx_args: BaseTxArgs,
},
/// Build, Optimize, Store code, and migrate contract
Upgrade {
/// Name of the contract to deploy
contract_name: String,

/// Label for the instantiated contract for later reference
#[clap(short, long, default_value = "default")]
label: String,

/// Raw json string to use as instantiate msg
#[clap(short, long)]
raw: Option<String>,

/// Use existing .wasm file to deploy if set to true
#[clap(long)]
no_rebuild: bool,

/// If set, skip wasm-opt and store the unoptimized code (only use in dev)
#[clap(long)]
no_wasm_opt: bool,

#[clap(flatten)]
base_tx_args: BaseTxArgs,
},
Proposal {
#[clap(subcommand)]
cmd: ProposalCmd,
Expand Down Expand Up @@ -189,6 +228,37 @@ impl<'a> Module<'a, WasmConfig, WasmCmd, anyhow::Error> for WasmModule {
)?;
Ok(())
}
WasmCmd::Migrate {
contract_name,
label,
raw,
base_tx_args,
} => {
let BaseTxArgs {
network,
signer_args,
gas_args,
timeout_height,
}: &BaseTxArgs = base_tx_args;
ops::migrate(
&ctx,
contract_name,
label.as_str(),
raw.as_ref(),
network,
timeout_height,
{
let global_conf = ctx.global_config()?;
&Gas::from_args(
gas_args,
global_conf.gas_price(),
global_conf.gas_adjustment(),
)?
},
signer_args.private_key(&ctx.global_config()?)?,
)?;
Ok(())
}
WasmCmd::Deploy {
contract_name,
label,
Expand Down Expand Up @@ -229,6 +299,42 @@ impl<'a> Module<'a, WasmConfig, WasmCmd, anyhow::Error> for WasmModule {
)?;
Ok(())
}
WasmCmd::Upgrade {
contract_name,
label,
raw,
no_rebuild,
no_wasm_opt,
base_tx_args,
} => {
let BaseTxArgs {
network,
signer_args,
gas_args,
timeout_height,
}: &BaseTxArgs = base_tx_args;
ops::upgrade(
&ctx,
contract_name,
label.as_str(),
raw.as_ref(),
network,
timeout_height,
{
let global_conf = ctx.global_config()?;
&Gas::from_args(
gas_args,
global_conf.gas_price(),
global_conf.gas_adjustment(),
)?
},
signer_args.private_key(&ctx.global_config()?)?,
signer_args.private_key(&ctx.global_config()?)?,
no_rebuild,
no_wasm_opt,
)?;
Ok(())
}
WasmCmd::Proposal { cmd } => proposal::entrypoint::execute(ctx, cmd),
}
}
Expand Down
Loading

0 comments on commit 75d5121

Please sign in to comment.