Skip to content

Commit

Permalink
Structured publish response
Browse files Browse the repository at this point in the history
  • Loading branch information
lxfind committed Mar 15, 2022
1 parent df4bbfa commit 63b92d3
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 188 deletions.
65 changes: 18 additions & 47 deletions sui/src/unit_tests/cli_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -923,70 +923,41 @@ async fn test_package_publish_command() -> Result<(), anyhow::Error> {
// Print it out to CLI/logs
resp.print(true);

let dumy_obj = Object::with_id_owner_for_testing(ObjectID::random(), address);
// Get the created objects
let (mut created_obj1, mut created_obj2) = (
dumy_obj.compute_object_reference(),
dumy_obj.compute_object_reference(),
);

if let WalletCommandResult::Publish(
_,
TransactionEffects {
created: new_objs, ..
},
) = resp
{
(created_obj1, created_obj2) = (new_objs.get(0).unwrap().0, new_objs.get(1).unwrap().0);
let (package, created_obj) = if let WalletCommandResult::Publish(resppnse) = resp {
(
resppnse.package,
resppnse.created_objects[0].compute_object_reference(),
)
} else {
// Fail this way because Panic! causes test issues
assert!(false);
unreachable!("Invaldi response");
};

// One is the actual module, while the other is the object created at init
retry_assert!(
logs_contain(&format!("{:02X}", created_obj1.0)),
logs_contain(&format!("{}", package.0)),
Duration::from_millis(5000)
);
retry_assert!(
logs_contain(&format!("{:02X}", created_obj2.0)),
logs_contain(&format!("{}", created_obj.0)),
Duration::from_millis(5000)
);

// Check the objects
// Init with some value to satisfy the type checker
let mut cr_obj1 = dumy_obj.clone();

let resp = WalletCommands::Object { id: created_obj1.0 }
let resp = WalletCommands::Object { id: package.0 }
.execute(&mut context)
.await?;
if let WalletCommandResult::Object(ObjectRead::Exists(_, object, _)) = resp {
cr_obj1 = object;
} else {
// Fail this way because Panic! causes test issues
assert!(false)
};
assert!(matches!(
resp,
WalletCommandResult::Object(ObjectRead::Exists(..))
));

let mut cr_obj2 = dumy_obj;

let resp = WalletCommands::Object { id: created_obj2.0 }
let resp = WalletCommands::Object { id: created_obj.0 }
.execute(&mut context)
.await?;
if let WalletCommandResult::Object(ObjectRead::Exists(_, object, _)) = resp {
cr_obj2 = object;
} else {
// Fail this way because Panic! causes test issues
assert!(false)
};

let (pkg, obj) = if cr_obj1.is_package() {
(cr_obj1, cr_obj2)
} else {
(cr_obj2, cr_obj1)
};

assert!(pkg.is_package());
assert!(!obj.is_package());
assert!(matches!(
resp,
WalletCommandResult::Object(ObjectRead::Exists(..))
));

network.abort();
Ok(())
Expand Down
17 changes: 8 additions & 9 deletions sui/src/wallet_commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ use structopt::clap::AppSettings;
use structopt::StructOpt;
use tracing::info;

use sui_core::gateway_state::gateway_responses::{MergeCoinResponse, SplitCoinResponse};
use sui_core::gateway_state::gateway_responses::{
MergeCoinResponse, PublishResponse, SplitCoinResponse,
};
use sui_core::gateway_state::{AsyncTransactionSigner, GatewayClient};
use sui_framework::build_move_package_to_bytes;
use sui_types::base_types::{decode_bytes_hex, ObjectID, ObjectRef, SuiAddress};
Expand Down Expand Up @@ -222,7 +224,7 @@ impl WalletCommands {
let gas_obj_ref = gas_object.compute_object_reference();

let compiled_modules = build_move_package_to_bytes(Path::new(path))?;
let (cert, effects) = context
let response = context
.gateway
.publish(
sender,
Expand All @@ -233,10 +235,7 @@ impl WalletCommands {
)
.await?;

if matches!(effects.status, ExecutionStatus::Failure { .. }) {
return Err(anyhow!("Error publishing module: {:#?}", effects.status));
};
WalletCommandResult::Publish(cert, effects)
WalletCommandResult::Publish(response)
}

WalletCommands::Object { id } => {
Expand Down Expand Up @@ -459,8 +458,8 @@ impl Display for WalletCommandResult {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let mut writer = String::new();
match self {
WalletCommandResult::Publish(cert, effects) => {
write!(writer, "{}", write_cert_and_effects(cert, effects)?)?;
WalletCommandResult::Publish(response) => {
write!(writer, "{}", response)?;
}
WalletCommandResult::Object(object_read) => {
let object = object_read.object().map_err(fmt::Error::custom)?;
Expand Down Expand Up @@ -569,7 +568,7 @@ impl WalletCommandResult {
#[derive(Serialize)]
#[serde(untagged)]
pub enum WalletCommandResult {
Publish(CertifiedTransaction, TransactionEffects),
Publish(PublishResponse),
Object(ObjectRead),
Call(CertifiedTransaction, TransactionEffects),
Transfer(
Expand Down
2 changes: 1 addition & 1 deletion sui_core/src/authority_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ impl AuthorityServer {
Err(RecvError::Lagged(number_skipped)) => {
// We tell the client they are too slow to consume, and
// stop.
return Err(SuiError::SubscriptionItemsDropedError(number_skipped));
return Err(SuiError::SubscriptionItemsDroppedError(number_skipped));
}
}
}
Expand Down
64 changes: 57 additions & 7 deletions sui_core/src/gateway_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use std::{
pin::Pin,
};

use self::gateway_responses::{MergeCoinResponse, SplitCoinResponse};
use self::gateway_responses::*;

/// A trait for supplying transaction signature asynchronously.
///
Expand Down Expand Up @@ -191,7 +191,7 @@ pub trait GatewayAPI {
gas_object_ref: ObjectRef,
gas_budget: u64,
tx_signer: StableSyncTransactionSigner,
) -> Result<(CertifiedTransaction, TransactionEffects), anyhow::Error>;
) -> Result<PublishResponse, anyhow::Error>;

/// Split the coin object (identified by `coin_object_ref`) into
/// multiple new coins. The amount of each new coin is specified in
Expand Down Expand Up @@ -731,12 +731,56 @@ where
gas_object_ref: ObjectRef,
gas_budget: u64,
tx_signer: StableSyncTransactionSigner,
) -> Result<(CertifiedTransaction, TransactionEffects), anyhow::Error> {
) -> Result<PublishResponse, anyhow::Error> {
let data = TransactionData::new_module(signer, gas_object_ref, package_bytes, gas_budget);
let signature = tx_signer.sign(&signer, data.clone()).await?;

self.execute_transaction(Transaction::new(data, signature))
.await
let (certificate, effects) = self
.execute_transaction(Transaction::new(data, signature))
.await?;
if let ExecutionStatus::Failure { gas_used: _, error } = effects.status {
return Err(error.into());
}
fp_ensure!(
effects.mutated.len() == 1,
SuiError::InconsistentGatewayResult {
error: format!(
"Expecting only one object mutated (the gas), seeing {} mutated",
effects.mutated.len()
),
}
.into()
);
let updated_gas = self
.get_object_info(gas_object_ref.0)
.await?
.into_object()?;
let mut package = None;
let mut created_objects = vec![];
for (obj_ref, _) in effects.created {
let object = self.get_object_info(obj_ref.0).await?.into_object()?;
if object.is_package() {
fp_ensure!(
package.is_none(),
SuiError::InconsistentGatewayResult {
error: "More than one package created".to_owned(),
}
.into()
);
package = Some(obj_ref);
} else {
created_objects.push(object);
}
}
let package = package.ok_or(SuiError::InconsistentGatewayResult {
error: "No package created".to_owned(),
})?;
Ok(PublishResponse {
certificate,
package,
created_objects,
updated_gas,
})
}

async fn split_coin(
Expand Down Expand Up @@ -783,7 +827,10 @@ where
effects.mutated.len() == 2 // coin and gas
&& created.len() == split_amounts.len()
&& created.iter().all(|(_, owner)| owner == &signer),
SuiError::IncorrectGasSplit.into()
SuiError::InconsistentGatewayResult {
error: "Unexpected split outcome".to_owned()
}
.into()
);
let updated_coin = self
.get_object_info(coin_object_ref.0)
Expand Down Expand Up @@ -843,7 +890,10 @@ where
}
fp_ensure!(
effects.mutated.len() == 2, // coin and gas
SuiError::IncorrectGasMerge.into()
SuiError::InconsistentGatewayResult {
error: "Unexpected split outcome".to_owned()
}
.into()
);
let updated_coin = self.get_object_info(primary_coin.0).await?.into_object()?;
let updated_gas = self.get_object_info(gas_payment.0).await?.into_object()?;
Expand Down
37 changes: 37 additions & 0 deletions sui_core/src/gateway_state/gateway_responses.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use serde::Serialize;
use std::fmt;
use std::fmt::Write;
use std::fmt::{Display, Formatter};
use sui_types::base_types::ObjectRef;
use sui_types::gas_coin::GasCoin;
use sui_types::messages::CertifiedTransaction;
use sui_types::object::Object;
Expand Down Expand Up @@ -71,3 +72,39 @@ impl Display for MergeCoinResponse {
write!(f, "{}", writer)
}
}

#[derive(Serialize)]
pub struct PublishResponse {
/// Certificate of the transaction
pub certificate: CertifiedTransaction,
/// The newly published package object reference.
pub package: ObjectRef,
/// List of Move objects created as part of running the module initializers in the package
pub created_objects: Vec<Object>,
/// The updated gas payment object after deducting payment
pub updated_gas: Object,
}

impl Display for PublishResponse {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let mut writer = String::new();
writeln!(writer, "----- Certificate ----")?;
write!(writer, "{}", self.certificate)?;
writeln!(writer, "----- Publish Results ----")?;
writeln!(
writer,
"The newly published package object: {:?}",
self.package
)?;
writeln!(
writer,
"List of objects created by running module initializers:"
)?;
for obj in &self.created_objects {
writeln!(writer, "{}", obj)?;
}
let gas_coin = GasCoin::try_from(&self.updated_gas).map_err(fmt::Error::custom)?;
writeln!(writer, "Updated Gas : {}", gas_coin)?;
write!(f, "{}", writer)
}
}
Loading

0 comments on commit 63b92d3

Please sign in to comment.