Skip to content

Commit

Permalink
[transactional tests] Add support for PT Publish and Upgrade commands (
Browse files Browse the repository at this point in the history
…MystenLabs#11206)

## Description 

- Factored out some shared publishing/upgrading logic
- Added a "staging" command for publish to compile a package but use it
in a later command
- Added a set-address command that sets the address via a value or an
object ID
- Added support for `Publish` and `Upgrade` commands

## Test Plan 

- Example tests

---
If your changes are not user-facing and not a breaking change, you can
skip the following section. Otherwise, please indicate what changed, and
then add to the Release Notes section as highlighted during the release
process.

### Type of Change (Check all that apply)

- [ ] user-visible impact
- [ ] breaking change for a client SDKs
- [ ] breaking change for FNs (FN binary must upgrade)
- [ ] breaking change for validators or node operators (must upgrade
binaries)
- [ ] breaking change for on-chain data layout
- [ ] necessitate either a data wipe or data migration

### Release notes
  • Loading branch information
tnowacki authored Apr 29, 2023
1 parent d05b26c commit e78f315
Show file tree
Hide file tree
Showing 11 changed files with 624 additions and 149 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
processed 9 tasks

init:
A: object(0,0)

task 3 'programmable'. lines 27-32:
created: object(3,0), object(3,1), object(3,2), object(3,3), object(3,4)
mutated: object(0,0)
gas summary: computation_cost: 1000000, storage_cost: 8876800, storage_rebate: 0, non_refundable_storage_fee: 0

task 6 'programmable'. lines 38-40:
mutated: object(0,0)
gas summary: computation_cost: 1000000, storage_cost: 988000, storage_rebate: 978120, non_refundable_storage_fee: 9880

task 7 'publish'. lines 42-47:
created: object(7,0)
mutated: object(0,1)
gas summary: computation_cost: 1000000, storage_cost: 5221200, storage_rebate: 0, non_refundable_storage_fee: 0

task 8 'run'. lines 49-49:
mutated: object(0,1)
gas summary: computation_cost: 1000000, storage_cost: 988000, storage_rebate: 978120, non_refundable_storage_fee: 9880
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

// simple test of publish

//# init --addresses p=0x0 q=0x0 r=0x0 --accounts A

//# stage-package
module p::m {
public fun foo(x: u64) {
p::n::bar(x)
}
}
module p::n {
public fun bar(x: u64) {
assert!(x == 0, 0);
}
}


//# stage-package
module q::m {
public fun x(): u64 { 0 }
}


//# programmable --sender A --inputs 10 @A
//> 0: SplitCoins(Gas, [Input(0)]);
//> 1: Publish(q, []);
//> 2: TransferObjects([Result(0)], Input(1));
//> 3: Publish(p, []);
//> TransferObjects([Result(1), Result(3)], Input(1))

//# set-address p object(3,1)

//# set-address q object(3,0)

//# programmable --sender A
//> 0: q::m::x();
//> p::m::foo(Result(0))

//# publish --dependencies p q
module r::all {
public fun foo_x() {
p::m::foo(q::m::x())
}
}

//# run r::all::foo_x
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
processed 11 tasks

init:
A: object(0,0)

task 1 'publish'. lines 8-18:
created: object(1,0)
mutated: object(0,1)
gas summary: computation_cost: 1000000, storage_cost: 4354800, storage_rebate: 0, non_refundable_storage_fee: 0

task 2 'publish'. lines 20-23:
created: object(2,0), object(2,1)
mutated: object(0,0)
gas summary: computation_cost: 1000000, storage_cost: 5076800, storage_rebate: 0, non_refundable_storage_fee: 0

task 3 'publish'. lines 25-28:
created: object(3,0)
mutated: object(0,1)
gas summary: computation_cost: 1000000, storage_cost: 3442800, storage_rebate: 978120, non_refundable_storage_fee: 9880

task 5 'programmable'. lines 36-41:
created: object(5,0), object(5,1)
mutated: object(0,0), object(2,1)
gas summary: computation_cost: 1000000, storage_cost: 7052800, storage_rebate: 2595780, non_refundable_storage_fee: 26220

task 6 'programmable'. lines 43-45:
Error: Transaction Effects Status: Move Runtime Abort. Location: p::n::bar (function index 0) at offset 6, Abort Code: 0
Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: MoveAbort(MoveLocation { module: ModuleId { address: p, name: Identifier("n") }, function: 0, instruction: 6, function_name: Some("bar") }, 0), source: Some(VMError { major_status: ABORTED, sub_status: Some(0), message: Some("p::n::bar at offset 6"), exec_state: Some(ExecutionState { stack_trace: [(Some(ModuleId { address: p, name: Identifier("m") }), FunctionDefinitionIndex(0), 1)] }), location: Module(ModuleId { address: p, name: Identifier("n") }), indices: [], offsets: [(FunctionDefinitionIndex(0), 6)] }), command: Some(1) } }

task 8 'programmable'. lines 49-51:
mutated: object(0,0)
gas summary: computation_cost: 1000000, storage_cost: 988000, storage_rebate: 978120, non_refundable_storage_fee: 9880

task 9 'publish'. lines 53-58:
created: object(9,0)
mutated: object(0,1)
gas summary: computation_cost: 1000000, storage_cost: 5768400, storage_rebate: 978120, non_refundable_storage_fee: 9880

task 10 'run'. lines 60-60:
mutated: object(0,1)
gas summary: computation_cost: 1000000, storage_cost: 988000, storage_rebate: 978120, non_refundable_storage_fee: 9880
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

// simple test of upgrade

//# init --addresses p=0x0 q=0x0 q_2=0x0 r=0x0 s=0x0 --accounts A

//# publish
module p::m {
public fun foo(x: u64) {
p::n::bar(x)
}
}
module p::n {
public fun bar(x: u64) {
assert!(x == 1, 0);
}
}

//# publish --upgradeable --sender A
module q::m {
public fun x(): u64 { 0 }
}

//# publish
module r::m {
public fun y(): u64 { 0 }
}

//# stage-package --dependencies r
module q_2::m {
public fun x(): u64 { y() + 1 }
public fun y(): u64 { r::m::y() }
}

//# programmable --sender A --inputs 10 @A object(2,1) 0u8 digest(q_2)
//> 0: sui::package::authorize_upgrade(Input(2), Input(3), Input(4));
//> 1: SplitCoins(Gas, [Input(0)]);
//> 2: Upgrade(q_2, [sui,std,r], q, Result(0));
//> TransferObjects([Result(1)], Input(1));
//> sui::package::commit_upgrade(Input(2), Result(2))

//# programmable --sender A
//> 0: q::m::x();
//> p::m::foo(Result(0))

//# set-address q_2 object(5,0)

//# programmable --sender A
//> 0: q_2::m::x();
//> p::m::foo(Result(0))

//# publish --dependencies p q_2 r
module s::all {
public fun foo_x() {
p::m::foo(q::m::x())
}
}

//# run s::all::foo_x
1 change: 1 addition & 0 deletions crates/sui-transactional-test-runner/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ clap = { version = "3.1.8", features = ["derive"] }
once_cell = "1.16"
rand = "0.8.5"
prometheus = "0.13.3"
tempfile = "3.2.0"

fastcrypto.workspace = true
move-binary-format.workspace = true
Expand Down
64 changes: 56 additions & 8 deletions crates/sui-transactional-test-runner/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use move_command_line_common::{parser::Parser as MoveCLParser, values::ValueToke
use move_core_types::identifier::Identifier;
use move_core_types::u256::U256;
use move_core_types::value::{MoveStruct, MoveValue};
use move_symbol_pool::Symbol;
use move_transactional_test_runner::tasks::SyntaxChoice;
use sui_types::base_types::SuiAddress;
use sui_types::messages::{Argument, CallArg, ObjectArg};
Expand Down Expand Up @@ -121,6 +122,25 @@ pub struct UpgradePackageCommand {
pub policy: u8,
}

#[derive(Debug, clap::Parser)]
pub struct StagePackageCommand {
#[clap(long = "syntax")]
pub syntax: Option<SyntaxChoice>,
#[clap(
long = "dependencies",
multiple_values(true),
multiple_occurrences(false)
)]
pub dependencies: Vec<String>,
}

#[derive(Debug, clap::Parser)]
pub struct SetAddressCommand {
pub address: String,
#[clap(parse(try_from_str = ParsedValue::parse))]
pub input: ParsedValue<SuiExtraValueArgs>,
}

#[derive(Debug, clap::Parser)]
pub enum SuiSubcommand {
#[clap(name = "view-object")]
Expand All @@ -133,21 +153,27 @@ pub enum SuiSubcommand {
ProgrammableTransaction(ProgrammableTransactionCommand),
#[clap(name = "upgrade")]
UpgradePackage(UpgradePackageCommand),
#[clap(name = "stage-package")]
StagePackage(StagePackageCommand),
#[clap(name = "set-address")]
SetAddress(SetAddressCommand),
}

#[derive(Debug)]
pub enum SuiExtraValueArgs {
Object(FakeID),
Digest(String),
}

pub enum SuiValue {
MoveValue(MoveValue),
Object(FakeID),
ObjVec(Vec<FakeID>),
Digest(String),
}

impl SuiExtraValueArgs {
fn parse_value_impl<'a, I: Iterator<Item = (ValueToken, &'a str)>>(
fn parse_object_value<'a, I: Iterator<Item = (ValueToken, &'a str)>>(
parser: &mut MoveCLParser<'a, ValueToken, I>,
) -> anyhow::Result<Self> {
let contents = parser.advance(ValueToken::Ident)?;
Expand All @@ -172,6 +198,17 @@ impl SuiExtraValueArgs {
parser.advance(ValueToken::RParen)?;
Ok(SuiExtraValueArgs::Object(fake_id))
}

fn parse_digest_value<'a, I: Iterator<Item = (ValueToken, &'a str)>>(
parser: &mut MoveCLParser<'a, ValueToken, I>,
) -> anyhow::Result<Self> {
let contents = parser.advance(ValueToken::Ident)?;
ensure!(contents == "digest");
parser.advance(ValueToken::LParen)?;
let package = parser.advance(ValueToken::Ident)?;
parser.advance(ValueToken::RParen)?;
Ok(SuiExtraValueArgs::Digest(package.to_owned()))
}
}

impl SuiValue {
Expand All @@ -180,6 +217,7 @@ impl SuiValue {
SuiValue::MoveValue(v) => v,
SuiValue::Object(_) => panic!("unexpected nested Sui object in args"),
SuiValue::ObjVec(_) => panic!("unexpected nested Sui object vector in args"),
SuiValue::Digest(_) => panic!("unexpected nested Sui package digest in args"),
}
}

Expand All @@ -188,6 +226,7 @@ impl SuiValue {
SuiValue::MoveValue(_) => panic!("unexpected nested non-object value in args"),
SuiValue::Object(v) => v,
SuiValue::ObjVec(_) => panic!("unexpected nested Sui object vector in args"),
SuiValue::Digest(_) => panic!("unexpected nested Sui package digest in args"),
}
}

Expand Down Expand Up @@ -220,6 +259,13 @@ impl SuiValue {
SuiValue::Object(fake_id) => CallArg::Object(Self::object_arg(fake_id, test_adapter)?),
SuiValue::MoveValue(v) => CallArg::Pure(v.simple_serialize().unwrap()),
SuiValue::ObjVec(_) => bail!("obj vec is not supported as an input"),
SuiValue::Digest(pkg) => {
let pkg = Symbol::from(pkg);
let Some(staged) = test_adapter.staged_modules.get(&pkg) else {
bail!("Unbound staged package '{pkg}'")
};
CallArg::Pure(bcs::to_bytes(&staged.digest).unwrap())
}
})
}

Expand All @@ -228,17 +274,17 @@ impl SuiValue {
builder: &mut ProgrammableTransactionBuilder,
test_adapter: &SuiTestAdapter,
) -> anyhow::Result<Argument> {
Ok(match self {
SuiValue::Object(fake_id) => builder.obj(Self::object_arg(fake_id, test_adapter)?)?,
match self {
SuiValue::ObjVec(vec) => builder.make_obj_vec(
vec.iter()
.map(|fake_id| Self::object_arg(*fake_id, test_adapter))
.collect::<Result<Vec<ObjectArg>, _>>()?,
)?,
SuiValue::MoveValue(v) => {
builder.input(CallArg::Pure(v.simple_serialize().unwrap()))?
),
value => {
let call_arg = value.into_call_arg(test_adapter)?;
builder.input(call_arg)
}
})
}
}
}

Expand All @@ -249,7 +295,8 @@ impl ParsableValue for SuiExtraValueArgs {
parser: &mut MoveCLParser<'a, ValueToken, I>,
) -> Option<anyhow::Result<Self>> {
match parser.peek()? {
(ValueToken::Ident, "object") => Some(Self::parse_value_impl(parser)),
(ValueToken::Ident, "object") => Some(Self::parse_object_value(parser)),
(ValueToken::Ident, "digest") => Some(Self::parse_digest_value(parser)),
_ => None,
}
}
Expand Down Expand Up @@ -292,6 +339,7 @@ impl ParsableValue for SuiExtraValueArgs {
) -> anyhow::Result<Self::ConcreteValue> {
match self {
SuiExtraValueArgs::Object(id) => Ok(SuiValue::Object(id)),
SuiExtraValueArgs::Digest(pkg) => Ok(SuiValue::Digest(pkg)),
}
}
}
Expand Down
Loading

0 comments on commit e78f315

Please sign in to comment.