Skip to content

Commit

Permalink
RPC Mock Data Generation Improvement (MystenLabs#2040)
Browse files Browse the repository at this point in the history
* replace ids, digests, signatures with consts

* add publish response

* refactored start_rpc_network, to be reused in sample generation

* add error tx response

* add owned object json file for explorer test
  • Loading branch information
patrickkuo authored Jun 7, 2022
1 parent c92bc8d commit f1c82de
Show file tree
Hide file tree
Showing 12 changed files with 1,522 additions and 105 deletions.
4 changes: 4 additions & 0 deletions Cargo.lock

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

3 changes: 2 additions & 1 deletion crates/generate-json-rpc-spec/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ tokio = { version = "1.18.2", features = ["full"] }

sui = { path = "../sui" }
sui-core = { path = "../sui-core" }
sui-config = { path = "../sui-config" }
sui-gateway = { path = "../sui-gateway" }
sui-json = { path = "../sui-json" }
sui-types = { path = "../sui-types" }
sui-config = { path = "../sui-config" }
test-utils = { path = "../test-utils" }
hyper = { version = "0.14.18", features = ["full"] }
workspace-hack = { path = "../workspace-hack"}
134 changes: 114 additions & 20 deletions crates/generate-json-rpc-spec/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,38 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

use std::collections::BTreeMap;

use clap::ArgEnum;
use clap::Parser;
use hyper::body::Buf;
use hyper::{Body, Client, Method, Request};
use pretty_assertions::assert_str_eq;
use serde::Serialize;
use serde_json::json;
use serde_json::{json, Map, Value};

use std::fs::File;
use std::io::Write;

use sui::wallet_commands::{WalletCommandResult, WalletCommands, WalletContext};
use sui::wallet_commands::{EXAMPLE_NFT_DESCRIPTION, EXAMPLE_NFT_NAME, EXAMPLE_NFT_URL};
use sui_config::genesis_config::GenesisConfig;
use sui_config::SUI_WALLET_CONFIG;
use sui_core::gateway_types::{
GetObjectDataResponse, SuiObjectInfo, TransactionEffectsResponse, TransactionResponse,
};
use sui_gateway::api::SuiRpcModule;
use sui_gateway::api::RpcGatewayApiClient;
use sui_gateway::api::RpcReadApiClient;
use sui_gateway::api::RpcTransactionBuilderClient;
use sui_gateway::api::{SuiRpcModule, TransactionBytes};
use sui_gateway::bcs_api::BcsApiImpl;
use sui_gateway::json_rpc::sui_rpc_doc;
use sui_gateway::read_api::{FullNodeApi, ReadApi};
use sui_gateway::rpc_gateway::{GatewayReadApiImpl, RpcGatewayImpl, TransactionBuilderImpl};
use sui_json::SuiJsonValue;
use sui_types::base_types::{ObjectID, SuiAddress};
use sui_types::sui_serde::{Base64, Encoding};
use sui_types::SUI_FRAMEWORK_ADDRESS;
use test_utils::network::start_test_network;
use test_utils::network::{start_rpc_test_network, TestNetwork};

#[derive(Debug, Parser, Clone, Copy, ArgEnum)]
enum Action {
Expand Down Expand Up @@ -57,6 +66,11 @@ const TRANSACTION_SAMPLE_FILE_PATH: &str = concat!(
"/../sui-open-rpc/samples/transactions.json",
);

const OWNED_OBJECT_SAMPLE_FILE_PATH: &str = concat!(
env!("CARGO_MANIFEST_DIR"),
"/../sui-open-rpc/samples/owned_objects.json",
);

#[tokio::main]
async fn main() {
let options = Options::parse();
Expand All @@ -73,21 +87,25 @@ async fn main() {
Action::Print => {
let content = serde_json::to_string_pretty(&open_rpc).unwrap();
println!("{content}");
let (objects, txs) = create_response_sample().await.unwrap();
let (objects, txs, addresses) = create_response_sample().await.unwrap();
println!("{}", serde_json::to_string_pretty(&objects).unwrap());
println!("{}", serde_json::to_string_pretty(&txs).unwrap());
println!("{}", serde_json::to_string_pretty(&addresses).unwrap());
}
Action::Record => {
let content = serde_json::to_string_pretty(&open_rpc).unwrap();
let mut f = File::create(FILE_PATH).unwrap();
writeln!(f, "{content}").unwrap();
let (objects, txs) = create_response_sample().await.unwrap();
let (objects, txs, addresses) = create_response_sample().await.unwrap();
let content = serde_json::to_string_pretty(&objects).unwrap();
let mut f = File::create(OBJECT_SAMPLE_FILE_PATH).unwrap();
writeln!(f, "{content}").unwrap();
let content = serde_json::to_string_pretty(&txs).unwrap();
let mut f = File::create(TRANSACTION_SAMPLE_FILE_PATH).unwrap();
writeln!(f, "{content}").unwrap();
let content = serde_json::to_string_pretty(&addresses).unwrap();
let mut f = File::create(OWNED_OBJECT_SAMPLE_FILE_PATH).unwrap();
writeln!(f, "{content}").unwrap();
}
Action::Test => {
let reference = std::fs::read_to_string(FILE_PATH).unwrap();
Expand All @@ -97,10 +115,17 @@ async fn main() {
}
}

async fn create_response_sample(
) -> Result<(ObjectResponseSample, TransactionResponseSample), anyhow::Error> {
let network = start_test_network(None).await?;
let config = network.dir().join(SUI_WALLET_CONFIG);
async fn create_response_sample() -> Result<
(
ObjectResponseSample,
TransactionResponseSample,
BTreeMap<SuiAddress, Vec<SuiObjectInfo>>,
),
anyhow::Error,
> {
let network = start_rpc_test_network(Some(GenesisConfig::custom_genesis(1, 4, 30))).await?;
let working_dir = network.network.dir();
let config = working_dir.join(SUI_WALLET_CONFIG);

let mut context = WalletContext::new(&config)?;
let address = context.config.accounts.first().cloned().unwrap();
Expand All @@ -118,10 +143,22 @@ async fn create_response_sample(
.await?;

let (example_nft_tx, example_nft) = get_nft_response(&mut context).await?;
let move_package = create_package_object_response(&mut context).await?;
let hero = create_hero_response(&mut context, &coins).await?;
let (move_package, publish) = create_package_object_response(&mut context).await?;
let (hero_package, hero) = create_hero_response(&mut context, &coins).await?;
let transfer = create_transfer_response(&mut context, address, &coins).await?;
let coin_split = create_coin_split_response(&mut context, &coins).await?;
let error = create_error_response(address, hero_package, context, &network).await?;

// address and owned objects
let mut owned_objects = BTreeMap::new();
for account in network.accounts {
network.http_client.sync_account_state(account).await?;
let objects: Vec<SuiObjectInfo> = network
.http_client
.get_objects_owned_by_address(account)
.await?;
owned_objects.insert(account, objects);
}

let objects = ObjectResponseSample {
example_nft,
Expand All @@ -134,14 +171,16 @@ async fn create_response_sample(
move_call: example_nft_tx,
transfer,
coin_split,
publish,
error,
};

Ok((objects, txs))
Ok((objects, txs, owned_objects))
}

async fn create_package_object_response(
context: &mut WalletContext,
) -> Result<GetObjectDataResponse, anyhow::Error> {
) -> Result<(GetObjectDataResponse, TransactionResponse), anyhow::Error> {
let result = WalletCommands::Publish {
path: "sui_programmability/examples/move_tutorial".to_string(),
gas: None,
Expand All @@ -150,10 +189,13 @@ async fn create_package_object_response(
.execute(context)
.await?;
if let WalletCommandResult::Publish(response) = result {
Ok(context
.gateway
.get_object(response.package.object_id)
.await?)
Ok((
context
.gateway
.get_object(response.package.object_id)
.await?,
TransactionResponse::PublishResponse(response),
))
} else {
panic!()
}
Expand Down Expand Up @@ -187,7 +229,7 @@ async fn create_transfer_response(
async fn create_hero_response(
context: &mut WalletContext,
coins: &[SuiObjectInfo],
) -> Result<GetObjectDataResponse, anyhow::Error> {
) -> Result<(ObjectID, GetObjectDataResponse), anyhow::Error> {
// Create hero response
let result = WalletCommands::Publish {
path: "sui_programmability/examples/games".to_string(),
Expand Down Expand Up @@ -220,7 +262,10 @@ async fn create_hero_response(

if let WalletCommandResult::Call(_, effect) = result {
let hero = effect.created.first().unwrap();
Ok(context.gateway.get_object(hero.reference.object_id).await?)
Ok((
package_id,
context.gateway.get_object(hero.reference.object_id).await?,
))
} else {
panic!()
}
Expand All @@ -229,6 +274,53 @@ async fn create_hero_response(
}
}

async fn create_error_response(
address: SuiAddress,
hero_package: ObjectID,
context: WalletContext,
network: &TestNetwork,
) -> Result<Value, anyhow::Error> {
// Cannot use wallet command as it will return Err if tx status is Error
// Using hyper to get the raw response instead
let response: TransactionBytes = network
.http_client
.move_call(
address,
hero_package,
"Hero".to_string(),
"new_game".to_string(),
vec![],
vec![],
None,
100,
)
.await?;

let signature = context
.keystore
.sign(&address, &response.tx_bytes.to_vec()?)?;
let signature_byte = Base64::encode(signature.signature_bytes());
let pub_key = Base64::encode(signature.public_key_bytes());
let tx_data = response.tx_bytes.encoded();

let client = Client::new();
let request = Request::builder()
.uri(network.rpc_url.clone())
.method(Method::POST)
.header("Content-Type", "application/json")
.body(Body::from(format!(
"{{ \"jsonrpc\": \"2.0\",\"method\": \"sui_executeTransaction\",\"params\": [\"{}\", \"{}\", \"{}\"],\"id\": 1 }}",
tx_data,
signature_byte,
pub_key
)))?;

let res = client.request(request).await?;
let body = hyper::body::aggregate(res).await?;
let result: Map<String, Value> = serde_json::from_reader(body.reader())?;
Ok(result["result"].clone())
}

async fn create_coin_split_response(
context: &mut WalletContext,
coins: &[SuiObjectInfo],
Expand Down Expand Up @@ -303,4 +395,6 @@ struct TransactionResponseSample {
pub move_call: TransactionResponse,
pub transfer: TransactionResponse,
pub coin_split: TransactionResponse,
pub publish: TransactionResponse,
pub error: Value,
}
2 changes: 1 addition & 1 deletion crates/sui-config/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ impl<R: ::rand::RngCore + ::rand::CryptoRng> ConfigBuilder<R> {

let initial_accounts_config = self
.initial_accounts_config
.unwrap_or_else(|| GenesisConfig::for_local_testing().unwrap());
.unwrap_or_else(GenesisConfig::for_local_testing);
let (account_keys, objects) = initial_accounts_config
.generate_accounts(&mut self.rng)
.unwrap();
Expand Down
8 changes: 4 additions & 4 deletions crates/sui-config/src/genesis_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ const DEFAULT_NUMBER_OF_ACCOUNT: usize = 5;
const DEFAULT_NUMBER_OF_OBJECT_PER_ACCOUNT: usize = 5;

impl GenesisConfig {
pub fn for_local_testing() -> Result<Self, anyhow::Error> {
pub fn for_local_testing() -> Self {
Self::custom_genesis(
DEFAULT_NUMBER_OF_AUTHORITIES,
DEFAULT_NUMBER_OF_ACCOUNT,
Expand All @@ -183,7 +183,7 @@ impl GenesisConfig {
num_authorities: usize,
num_accounts: usize,
num_objects_per_account: usize,
) -> Result<Self, anyhow::Error> {
) -> Self {
assert!(
num_authorities > 0,
"num_authorities should be larger than 0"
Expand All @@ -205,10 +205,10 @@ impl GenesisConfig {
})
}

Ok(Self {
Self {
accounts,
..Default::default()
})
}
}
}

Expand Down
Loading

0 comments on commit f1c82de

Please sign in to comment.