From f44b9da0f0e191b46c1d94c29f97b7b6da0349f7 Mon Sep 17 00:00:00 2001 From: Eugene Boguslavsky Date: Fri, 24 May 2024 22:48:06 -0700 Subject: [PATCH 001/324] Revert "Revert "[native-bridge] - add e2e test to test Sui bridge pause."" (#17933) Reverts MystenLabs/sui#17926 Turns out not to be an issue at all, sorry for all the reverts! --- crates/sui-bridge/src/e2e_tests/basic.rs | 190 +++++++++--------- crates/sui-bridge/src/e2e_tests/complex.rs | 132 ++++++++++++ crates/sui-bridge/src/e2e_tests/mod.rs | 1 + crates/sui-bridge/src/e2e_tests/test_utils.rs | 42 +++- 4 files changed, 267 insertions(+), 98 deletions(-) create mode 100644 crates/sui-bridge/src/e2e_tests/complex.rs diff --git a/crates/sui-bridge/src/e2e_tests/basic.rs b/crates/sui-bridge/src/e2e_tests/basic.rs index d71790aa3a7de..072d8e6a99304 100644 --- a/crates/sui-bridge/src/e2e_tests/basic.rs +++ b/crates/sui-bridge/src/e2e_tests/basic.rs @@ -3,6 +3,7 @@ use crate::abi::{eth_sui_bridge, EthBridgeEvent, EthSuiBridge}; use crate::client::bridge_authority_aggregator::BridgeAuthorityAggregator; +use crate::e2e_tests::test_utils::BridgeTestCluster; use crate::e2e_tests::test_utils::{get_signatures, BridgeTestClusterBuilder}; use crate::events::{ SuiBridgeEvent, SuiToEthTokenBridgeV1, TokenTransferApproved, TokenTransferClaimed, @@ -20,6 +21,7 @@ use std::collections::{HashMap, HashSet}; use std::path::Path; +use anyhow::anyhow; use std::sync::Arc; use sui_json_rpc_types::{ SuiExecutionStatus, SuiTransactionBlockEffectsAPI, SuiTransactionBlockResponse, @@ -31,6 +33,7 @@ use sui_types::bridge::{BridgeChainId, BridgeTokenMetadata, BRIDGE_MODULE_NAME, use sui_types::programmable_transaction_builder::ProgrammableTransactionBuilder; use sui_types::transaction::{ObjectArg, TransactionData}; use sui_types::{TypeTag, BRIDGE_PACKAGE_ID}; +use tap::TapFallible; use tracing::info; #[tokio::test(flavor = "multi_thread", worker_threads = 8)] @@ -46,31 +49,18 @@ async fn test_bridge_from_eth_to_sui_to_eth() { .build() .await; - let (eth_signer, eth_address) = bridge_test_cluster + let (eth_signer, _) = bridge_test_cluster .get_eth_signer_and_address() .await .unwrap(); - let sui_client = bridge_test_cluster.sui_client(); - let sui_bridge_client = bridge_test_cluster.sui_bridge_client().await.unwrap(); let sui_address = bridge_test_cluster.sui_user_address(); let amount = 42; let sui_amount = amount * 100_000_000; - initiate_bridge_eth_to_sui( - &sui_bridge_client, - ð_signer, - bridge_test_cluster.contracts().sui_bridge, - sui_address, - eth_address, - eth_chain_id, - sui_chain_id, - amount, - sui_amount, - TOKEN_ID_ETH, - 0, - ) - .await; + initiate_bridge_eth_to_sui(&bridge_test_cluster, amount, sui_amount, TOKEN_ID_ETH, 0) + .await + .unwrap(); let events = bridge_test_cluster .new_bridge_events( HashSet::from_iter([ @@ -83,7 +73,8 @@ async fn test_bridge_from_eth_to_sui_to_eth() { // There are exactly 1 approved and 1 claimed event assert_eq!(events.len(), 2); - let eth_coin = sui_client + let eth_coin = bridge_test_cluster + .sui_client() .coin_read_api() .get_all_coins(sui_address, None, None) .await @@ -97,28 +88,17 @@ async fn test_bridge_from_eth_to_sui_to_eth() { // Now let the recipient send the coin back to ETH let eth_address_1 = EthAddress::random(); - let bridge_obj_arg = sui_bridge_client - .get_mutable_bridge_object_arg_must_succeed() - .await; let nonce = 0; - let sui_token_type_tags = sui_bridge_client.get_token_id_map().await.unwrap(); - let sui_to_eth_bridge_action = initiate_bridge_sui_to_eth( - &sui_bridge_client, - &sui_client, - sui_address, - bridge_test_cluster.wallet_mut(), - eth_chain_id, - sui_chain_id, + &bridge_test_cluster, eth_address_1, eth_coin.object_ref(), nonce, - bridge_obj_arg, sui_amount, - &sui_token_type_tags, ) - .await; + .await + .unwrap(); let events = bridge_test_cluster .new_bridge_events( HashSet::from_iter([ @@ -133,7 +113,8 @@ async fn test_bridge_from_eth_to_sui_to_eth() { assert_eq!(events.len(), 2); // Test `get_parsed_token_transfer_message` - let parsed_msg = sui_bridge_client + let parsed_msg = bridge_test_cluster + .bridge_client() .get_parsed_token_transfer_message(sui_chain_id, nonce) .await .unwrap() @@ -153,7 +134,7 @@ async fn test_bridge_from_eth_to_sui_to_eth() { assert_eq!(parsed_msg.parsed_payload.amount, sui_amount); let message = eth_sui_bridge::Message::from(sui_to_eth_bridge_action); - let signatures = get_signatures(&sui_bridge_client, nonce, sui_chain_id).await; + let signatures = get_signatures(bridge_test_cluster.bridge_client(), nonce, sui_chain_id).await; let eth_sui_bridge = EthSuiBridge::new( bridge_test_cluster.contracts().sui_bridge, @@ -195,8 +176,6 @@ async fn test_add_new_coins_on_sui() { ) .await; - let sui_bridge_client = bridge_test_cluster.sui_bridge_client().await.unwrap(); - info!("Starting bridge cluster"); bridge_test_cluster.set_approved_governance_actions_for_next_start(vec![ @@ -212,7 +191,8 @@ async fn test_add_new_coins_on_sui() { info!("Bridge cluster is up"); let bridge_committee = Arc::new( - sui_bridge_client + bridge_test_cluster + .bridge_client() .get_bridge_committee() .await .expect("Failed to get bridge committee"), @@ -245,7 +225,11 @@ async fn test_add_new_coins_on_sui() { info!("Approved new token"); // Assert new token is correctly added - let treasury_summary = sui_bridge_client.get_treasury_summary().await.unwrap(); + let treasury_summary = bridge_test_cluster + .bridge_client() + .get_treasury_summary() + .await + .unwrap(); assert_eq!(treasury_summary.id_token_type_map.len(), 5); // 4 + 1 new token let (id, _type) = treasury_summary .id_token_type_map @@ -272,29 +256,29 @@ pub(crate) async fn deposit_native_eth_to_sol_contract( signer: &EthSigner, contract_address: EthAddress, sui_recipient_address: SuiAddress, - sui_chain_id: u8, + sui_chain_id: BridgeChainId, amount: u64, ) -> ContractCall { let contract = EthSuiBridge::new(contract_address, signer.clone().into()); let sui_recipient_address = sui_recipient_address.to_vec().into(); let amount = U256::from(amount) * U256::exp10(18); // 1 ETH contract - .bridge_eth(sui_recipient_address, sui_chain_id) + .bridge_eth(sui_recipient_address, sui_chain_id as u8) .value(amount) } async fn deposit_eth_to_sui_package( sui_client: &SuiClient, sui_address: SuiAddress, - wallet_context: &mut WalletContext, - target_chain: u8, + wallet_context: &WalletContext, + target_chain: BridgeChainId, target_address: EthAddress, token: ObjectRef, bridge_object_arg: ObjectArg, sui_token_type_tags: &HashMap, -) -> SuiTransactionBlockResponse { +) -> Result { let mut builder = ProgrammableTransactionBuilder::new(); - let arg_target_chain = builder.pure(target_chain).unwrap(); + let arg_target_chain = builder.pure(target_chain as u8).unwrap(); let arg_target_address = builder.pure(target_address.as_bytes()).unwrap(); let arg_token = builder.obj(ObjectArg::ImmOrOwnedObject(token)).unwrap(); let arg_bridge = builder.obj(bridge_object_arg).unwrap(); @@ -325,26 +309,29 @@ async fn deposit_eth_to_sui_package( .unwrap(), ); let tx = wallet_context.sign_transaction(&tx_data); - wallet_context.execute_transaction_must_succeed(tx).await + wallet_context.execute_transaction_may_fail(tx).await } -async fn initiate_bridge_eth_to_sui( - sui_bridge_client: &SuiBridgeClient, - eth_signer: &EthSigner, - sui_bridge_contract_address: EthAddress, - sui_address: SuiAddress, - eth_address: EthAddress, - eth_chain_id: u8, - sui_chain_id: u8, +pub async fn initiate_bridge_eth_to_sui( + bridge_test_cluster: &BridgeTestCluster, amount: u64, sui_amount: u64, token_id: u8, nonce: u64, -) { +) -> Result<(), anyhow::Error> { info!("Depositing Eth to Solidity contract"); + let (eth_signer, eth_address) = bridge_test_cluster + .get_eth_signer_and_address() + .await + .unwrap(); + + let sui_address = bridge_test_cluster.sui_user_address(); + let sui_chain_id = bridge_test_cluster.sui_chain_id(); + let eth_chain_id = bridge_test_cluster.eth_chain_id(); + let eth_tx = deposit_native_eth_to_sol_contract( - eth_signer, - sui_bridge_contract_address, + ð_signer, + bridge_test_cluster.contracts().sui_bridge, sui_address, sui_chain_id, amount, @@ -364,9 +351,9 @@ async fn initiate_bridge_eth_to_sui( unreachable!(); }; // assert eth log matches - assert_eq!(eth_bridge_event.source_chain_id, eth_chain_id); + assert_eq!(eth_bridge_event.source_chain_id, eth_chain_id as u8); assert_eq!(eth_bridge_event.nonce, nonce); - assert_eq!(eth_bridge_event.destination_chain_id, sui_chain_id); + assert_eq!(eth_bridge_event.destination_chain_id, sui_chain_id as u8); assert_eq!(eth_bridge_event.token_id, token_id); assert_eq!(eth_bridge_event.sui_adjusted_amount, sui_amount); assert_eq!(eth_bridge_event.sender_address, eth_address); @@ -374,40 +361,58 @@ async fn initiate_bridge_eth_to_sui( info!("Deposited Eth to Solidity contract"); wait_for_transfer_action_status( - sui_bridge_client, + bridge_test_cluster.bridge_client(), eth_chain_id, - 0, + nonce, BridgeActionStatus::Claimed, ) - .await; - info!("Eth to Sui bridge transfer claimed"); + .await + .tap_ok(|_| { + info!("Eth to Sui bridge transfer claimed"); + }) } -async fn initiate_bridge_sui_to_eth( - sui_bridge_client: &SuiBridgeClient, - sui_client: &SuiClient, - sui_address: SuiAddress, - wallet_context: &mut WalletContext, - eth_chain_id: u8, - sui_chain_id: u8, +pub async fn initiate_bridge_sui_to_eth( + bridge_test_cluster: &BridgeTestCluster, eth_address: EthAddress, token: ObjectRef, nonce: u64, - bridge_object_arg: ObjectArg, sui_amount: u64, - sui_token_type_tags: &HashMap, -) -> SuiToEthBridgeAction { - let resp = deposit_eth_to_sui_package( +) -> Result { + let bridge_object_arg = bridge_test_cluster + .bridge_client() + .get_mutable_bridge_object_arg_must_succeed() + .await; + let sui_client = bridge_test_cluster.sui_client(); + let token_types = bridge_test_cluster + .bridge_client() + .get_token_id_map() + .await + .unwrap(); + let sui_address = bridge_test_cluster.sui_user_address(); + + let resp = match deposit_eth_to_sui_package( sui_client, sui_address, - wallet_context, - eth_chain_id, + bridge_test_cluster.wallet(), + bridge_test_cluster.eth_chain_id(), eth_address, token, bridge_object_arg, - sui_token_type_tags, + &token_types, ) - .await; + .await + { + Ok(resp) => { + if !resp.status_ok().unwrap() { + return Err(anyhow!("Sui TX error")); + } else { + resp + } + } + Err(e) => return Err(e), + }; + let sui_events = resp.events.unwrap().data; let bridge_event = sui_events .iter() @@ -426,12 +431,12 @@ async fn initiate_bridge_sui_to_eth( info!("Deposited Eth to move package"); assert_eq!(bridge_event.sui_bridge_event.nonce, nonce); assert_eq!( - bridge_event.sui_bridge_event.sui_chain_id as u8, - sui_chain_id + bridge_event.sui_bridge_event.sui_chain_id, + bridge_test_cluster.sui_chain_id() ); assert_eq!( - bridge_event.sui_bridge_event.eth_chain_id as u8, - eth_chain_id + bridge_event.sui_bridge_event.eth_chain_id, + bridge_test_cluster.eth_chain_id() ); assert_eq!(bridge_event.sui_bridge_event.sui_address, sui_address); assert_eq!(bridge_event.sui_bridge_event.eth_address, eth_address); @@ -443,38 +448,39 @@ async fn initiate_bridge_sui_to_eth( // Wait for the bridge action to be approved wait_for_transfer_action_status( - sui_bridge_client, - sui_chain_id, + bridge_test_cluster.bridge_client(), + bridge_test_cluster.sui_chain_id(), nonce, BridgeActionStatus::Approved, ) - .await; + .await + .unwrap(); info!("Sui to Eth bridge transfer approved"); - bridge_event + Ok(bridge_event) } async fn wait_for_transfer_action_status( sui_bridge_client: &SuiBridgeClient, - chain_id: u8, + chain_id: BridgeChainId, nonce: u64, status: BridgeActionStatus, -) { +) -> Result<(), anyhow::Error> { // Wait for the bridge action to be approved let now = std::time::Instant::now(); loop { let res = sui_bridge_client - .get_token_transfer_action_onchain_status_until_success(chain_id, nonce) + .get_token_transfer_action_onchain_status_until_success(chain_id as u8, nonce) .await; if res == status { - break; + return Ok(()); } if now.elapsed().as_secs() > 30 { - panic!( - "Timeout waiting for token transfer action to be {:?}. chain_id: {chain_id}, nonce: {nonce}. Time elapsed: {:?}", + return Err(anyhow!( + "Timeout waiting for token transfer action to be {:?}. chain_id: {chain_id:?}, nonce: {nonce}. Time elapsed: {:?}", status, now.elapsed(), - ); + )); } tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; } diff --git a/crates/sui-bridge/src/e2e_tests/complex.rs b/crates/sui-bridge/src/e2e_tests/complex.rs new file mode 100644 index 0000000000000..4c59c7f645631 --- /dev/null +++ b/crates/sui-bridge/src/e2e_tests/complex.rs @@ -0,0 +1,132 @@ +// Copyright (c) Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +use crate::client::bridge_authority_aggregator::BridgeAuthorityAggregator; +use crate::e2e_tests::basic::initiate_bridge_eth_to_sui; +use crate::e2e_tests::basic::initiate_bridge_sui_to_eth; +use crate::e2e_tests::test_utils::BridgeTestClusterBuilder; +use crate::sui_transaction_builder::build_sui_transaction; +use crate::types::{BridgeAction, EmergencyAction}; +use crate::types::{BridgeActionStatus, EmergencyActionType}; +use ethers::types::Address as EthAddress; +use std::sync::Arc; +use sui_json_rpc_types::SuiExecutionStatus; +use sui_json_rpc_types::SuiTransactionBlockEffectsAPI; +use sui_types::bridge::{BridgeChainId, TOKEN_ID_ETH}; +use tracing::info; + +#[tokio::test] +async fn test_sui_bridge_paused() { + telemetry_subscribers::init_for_testing(); + + // approve pause action in bridge nodes + let pause_action = BridgeAction::EmergencyAction(EmergencyAction { + nonce: 0, + chain_id: BridgeChainId::SuiCustom, + action_type: EmergencyActionType::Pause, + }); + + let unpause_action = BridgeAction::EmergencyAction(EmergencyAction { + nonce: 1, + chain_id: BridgeChainId::SuiCustom, + action_type: EmergencyActionType::Unpause, + }); + + // Setup bridge test env + let bridge_test_cluster = BridgeTestClusterBuilder::new() + .with_eth_env(true) + .with_approved_governance_actions(vec![ + vec![pause_action.clone(), unpause_action.clone()], + vec![pause_action.clone(), unpause_action.clone()], + vec![pause_action.clone(), unpause_action.clone()], + vec![], + ]) + .with_bridge_cluster(true) + .build() + .await; + + let bridge_client = bridge_test_cluster.bridge_client(); + let sui_address = bridge_test_cluster.sui_user_address(); + let sui_token_type_tags = bridge_client.get_token_id_map().await.unwrap(); + + // verify bridge are not paused + assert!(!bridge_client.get_bridge_summary().await.unwrap().is_frozen); + + // try bridge from eth and verify it works on sui + initiate_bridge_eth_to_sui(&bridge_test_cluster, 10, 10 * 100_000_000, TOKEN_ID_ETH, 0) + .await + .unwrap(); + // verify Eth was transferred to Sui address + let eth_coin_type = sui_token_type_tags.get(&TOKEN_ID_ETH).unwrap(); + let eth_coin = bridge_client + .sui_client() + .coin_read_api() + .get_coins(sui_address, Some(eth_coin_type.to_string()), None, None) + .await + .unwrap() + .data; + assert_eq!(1, eth_coin.len()); + + // get pause bridge signatures from committee + let bridge_committee = Arc::new(bridge_client.get_bridge_committee().await.unwrap()); + let agg = BridgeAuthorityAggregator::new(bridge_committee); + let certified_action = agg + .request_committee_signatures(pause_action) + .await + .unwrap(); + + // execute pause bridge on sui + let gas = bridge_test_cluster + .wallet() + .get_one_gas_object_owned_by_address(sui_address) + .await + .unwrap() + .unwrap(); + + let tx = build_sui_transaction( + sui_address, + &gas, + certified_action, + bridge_client + .get_mutable_bridge_object_arg_must_succeed() + .await, + &sui_token_type_tags, + 1000, + ) + .unwrap(); + + let response = bridge_test_cluster.sign_and_execute_transaction(&tx).await; + assert_eq!( + response.effects.unwrap().status(), + &SuiExecutionStatus::Success + ); + info!("Bridge paused"); + + // verify bridge paused + assert!(bridge_client.get_bridge_summary().await.unwrap().is_frozen); + + // Transfer from eth to sui should fail on Sui + let eth_to_sui_bridge_action = + initiate_bridge_eth_to_sui(&bridge_test_cluster, 10, 10 * 100_000_000, TOKEN_ID_ETH, 1) + .await; + assert!(eth_to_sui_bridge_action.is_err()); + // message should not be recorded on Sui when the bridge is paused + let res = bridge_test_cluster + .bridge_client() + .get_token_transfer_action_onchain_status_until_success( + bridge_test_cluster.eth_chain_id() as u8, + 1, + ) + .await; + assert_eq!(BridgeActionStatus::NotFound, res); + // Transfer from Sui to eth should fail + let sui_to_eth_bridge_action = initiate_bridge_sui_to_eth( + &bridge_test_cluster, + EthAddress::random(), + eth_coin.first().unwrap().object_ref(), + 0, + 10, + ) + .await; + assert!(sui_to_eth_bridge_action.is_err()) +} diff --git a/crates/sui-bridge/src/e2e_tests/mod.rs b/crates/sui-bridge/src/e2e_tests/mod.rs index 0f30720708fdd..26ee8f143271a 100644 --- a/crates/sui-bridge/src/e2e_tests/mod.rs +++ b/crates/sui-bridge/src/e2e_tests/mod.rs @@ -2,4 +2,5 @@ // SPDX-License-Identifier: Apache-2.0 mod basic; +mod complex; pub mod test_utils; diff --git a/crates/sui-bridge/src/e2e_tests/test_utils.rs b/crates/sui-bridge/src/e2e_tests/test_utils.rs index 43be5d62176fa..a69fb5d60341f 100644 --- a/crates/sui-bridge/src/e2e_tests/test_utils.rs +++ b/crates/sui-bridge/src/e2e_tests/test_utils.rs @@ -72,16 +72,21 @@ pub const TEST_PK: &str = "0x4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1 /// structs that are needed for testing. pub struct BridgeTestCluster { pub test_cluster: TestCluster, + bridge_client: SuiBridgeClient, eth_environment: EthBridgeEnvironment, bridge_node_handles: Option>>, approved_governance_actions_for_next_start: Option>>, bridge_tx_cursor: Option, + eth_chain_id: BridgeChainId, + sui_chain_id: BridgeChainId, } pub struct BridgeTestClusterBuilder { with_eth_env: bool, with_bridge_cluster: bool, approved_governance_actions: Option>>, + eth_chain_id: BridgeChainId, + sui_chain_id: BridgeChainId, } impl Default for BridgeTestClusterBuilder { @@ -96,6 +101,8 @@ impl BridgeTestClusterBuilder { with_eth_env: false, with_bridge_cluster: false, approved_governance_actions: None, + eth_chain_id: BridgeChainId::EthCustom, + sui_chain_id: BridgeChainId::SuiCustom, } } @@ -117,6 +124,16 @@ impl BridgeTestClusterBuilder { self } + pub fn with_sui_chain_id(mut self, chain_id: BridgeChainId) -> Self { + self.sui_chain_id = chain_id; + self + } + + pub fn with_eth_chain_id(mut self, chain_id: BridgeChainId) -> Self { + self.eth_chain_id = chain_id; + self + } + pub async fn build(self) -> BridgeTestCluster { init_all_struct_tags(); std::env::set_var("__TEST_ONLY_CONSENSUS_USE_LONG_MIN_ROUND_DELAY", "1"); @@ -145,13 +162,18 @@ impl BridgeTestClusterBuilder { .await, ); } - + let bridge_client = SuiBridgeClient::new(&test_cluster.fullnode_handle.rpc_url) + .await + .unwrap(); BridgeTestCluster { test_cluster, + bridge_client, eth_environment, bridge_node_handles, approved_governance_actions_for_next_start: self.approved_governance_actions, bridge_tx_cursor: None, + sui_chain_id: self.sui_chain_id, + eth_chain_id: self.eth_chain_id, } } @@ -199,18 +221,26 @@ impl BridgeTestCluster { Ok((eth_signer, eth_address)) } - pub async fn sui_bridge_client(&self) -> anyhow::Result { - SuiBridgeClient::new(&self.test_cluster.fullnode_handle.rpc_url).await + pub fn bridge_client(&self) -> &SuiBridgeClient { + &self.bridge_client } - pub fn sui_client(&self) -> SuiClient { - self.test_cluster.fullnode_handle.sui_client.clone() + pub fn sui_client(&self) -> &SuiClient { + &self.test_cluster.fullnode_handle.sui_client } pub fn sui_user_address(&self) -> SuiAddress { self.test_cluster.get_address_0() } + pub fn sui_chain_id(&self) -> BridgeChainId { + self.sui_chain_id + } + + pub fn eth_chain_id(&self) -> BridgeChainId { + self.eth_chain_id + } + pub fn contracts(&self) -> &DeployedSolContracts { self.eth_environment.contracts() } @@ -223,7 +253,7 @@ impl BridgeTestCluster { self.test_cluster.wallet_mut() } - pub fn wallet(&mut self) -> &WalletContext { + pub fn wallet(&self) -> &WalletContext { &self.test_cluster.wallet } From 04ed3b62103cf5cef07bba9416679cf55715c22b Mon Sep 17 00:00:00 2001 From: Dario Russi <113150618+dariorussi@users.noreply.github.com> Date: Sat, 25 May 2024 12:38:15 +0200 Subject: [PATCH 002/324] =?UTF-8?q?Revert=20"Add=20quantity=5Fmin=5Ftick?= =?UTF-8?q?=20to=20DeepBook.=20Quantity=20must=20be=20divisible=E2=80=A6?= =?UTF-8?q?=20(#17927)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit … by this amount, rather than lot_size. (#17335)" This reverts commit d2425d62253189ea81660a7964150e14531a1814. ## Description Describe the changes or additions included in this PR. ## Test plan How did you test the new or updated feature? --- ## Release notes Check each box that your changes affect. If none of the boxes relate to your changes, release notes aren't required. For each box you select, include information after the relevant heading that describes the impact of your changes that a user might notice and any actions they must take to implement updates. - [ ] Protocol: - [ ] Nodes (Validators and Full nodes): - [ ] Indexer: - [ ] JSON-RPC: - [ ] GraphQL: - [ ] CLI: - [ ] Rust SDK: --------- Co-authored-by: Timothy Zakian --- crates/sui-framework/docs/deepbook/clob_v2.md | 69 +- .../packages/deepbook/sources/clob_v2.move | 70 +- .../packages/deepbook/tests/clob_tests.move | 675 +++++++----------- .../deepbook/tests/order_query_tests.move | 6 +- .../tests/objects/enum_data.exp | 326 ++++----- .../tests/packages/datatypes.exp | 4 +- .../tests/packages/enums.exp | 62 +- ..._populated_genesis_snapshot_matches-2.snap | 28 +- 8 files changed, 539 insertions(+), 701 deletions(-) diff --git a/crates/sui-framework/docs/deepbook/clob_v2.md b/crates/sui-framework/docs/deepbook/clob_v2.md index 2b23bac7715fc..a27130f823c94 100644 --- a/crates/sui-framework/docs/deepbook/clob_v2.md +++ b/crates/sui-framework/docs/deepbook/clob_v2.md @@ -1176,11 +1176,11 @@ do not have this capability: - + -
const EInvalidTickSizeMinSize: u64 = 20;
+
const EInvalidTickSizeLotSize: u64 = 20;
 
@@ -1203,15 +1203,6 @@ do not have this capability: - - - - -
const LOT_SIZE: u64 = 1000;
-
- - - @@ -1437,7 +1428,7 @@ Destroy the given pool_owner_cap object -
fun create_pool_<BaseAsset, QuoteAsset>(taker_fee_rate: u64, maker_rebate_rate: u64, tick_size: u64, min_size: u64, creation_fee: balance::Balance<sui::SUI>, ctx: &mut tx_context::TxContext)
+
fun create_pool_<BaseAsset, QuoteAsset>(taker_fee_rate: u64, maker_rebate_rate: u64, tick_size: u64, lot_size: u64, creation_fee: balance::Balance<sui::SUI>, ctx: &mut tx_context::TxContext)
 
@@ -1450,7 +1441,7 @@ Destroy the given pool_owner_cap object taker_fee_rate: u64, maker_rebate_rate: u64, tick_size: u64, - min_size: u64, + lot_size: u64, creation_fee: Balance<SUI>, ctx: &mut TxContext, ) { @@ -1458,7 +1449,7 @@ Destroy the given pool_owner_cap object taker_fee_rate, maker_rebate_rate, tick_size, - min_size, + lot_size, creation_fee, ctx ); @@ -1478,7 +1469,7 @@ Destroy the given pool_owner_cap object -
public fun create_pool<BaseAsset, QuoteAsset>(tick_size: u64, min_size: u64, creation_fee: coin::Coin<sui::SUI>, ctx: &mut tx_context::TxContext)
+
public fun create_pool<BaseAsset, QuoteAsset>(tick_size: u64, lot_size: u64, creation_fee: coin::Coin<sui::SUI>, ctx: &mut tx_context::TxContext)
 
@@ -1489,13 +1480,13 @@ Destroy the given pool_owner_cap object
public fun create_pool<BaseAsset, QuoteAsset>(
     tick_size: u64,
-    min_size: u64,
+    lot_size: u64,
     creation_fee: Coin<SUI>,
     ctx: &mut TxContext,
 ) {
     create_customized_pool<BaseAsset, QuoteAsset>(
         tick_size,
-        min_size,
+        lot_size,
         REFERENCE_TAKER_FEE_RATE,
         REFERENCE_MAKER_REBATE_RATE,
         creation_fee,
@@ -1517,7 +1508,7 @@ The taker_fee_rate should be greater than or equal to the maker_rebate_rate, and
 Taker_fee_rate of 0.25% should be 2_500_000 for example
 
 
-
public fun create_customized_pool<BaseAsset, QuoteAsset>(tick_size: u64, min_size: u64, taker_fee_rate: u64, maker_rebate_rate: u64, creation_fee: coin::Coin<sui::SUI>, ctx: &mut tx_context::TxContext)
+
public fun create_customized_pool<BaseAsset, QuoteAsset>(tick_size: u64, lot_size: u64, taker_fee_rate: u64, maker_rebate_rate: u64, creation_fee: coin::Coin<sui::SUI>, ctx: &mut tx_context::TxContext)
 
@@ -1528,7 +1519,7 @@ Taker_fee_rate of 0.25% should be 2_500_000 for example
public fun create_customized_pool<BaseAsset, QuoteAsset>(
     tick_size: u64,
-    min_size: u64,
+    lot_size: u64,
     taker_fee_rate: u64,
     maker_rebate_rate: u64,
     creation_fee: Coin<SUI>,
@@ -1538,7 +1529,7 @@ Taker_fee_rate of 0.25% should be 2_500_000 for example
         taker_fee_rate,
         maker_rebate_rate,
         tick_size,
-        min_size,
+        lot_size,
         coin::into_balance(creation_fee),
         ctx
     )
@@ -1556,7 +1547,7 @@ Taker_fee_rate of 0.25% should be 2_500_000 for example
 Helper function that all the create pools now call to create pools.
 
 
-
fun create_pool_with_return_<BaseAsset, QuoteAsset>(taker_fee_rate: u64, maker_rebate_rate: u64, tick_size: u64, min_size: u64, creation_fee: balance::Balance<sui::SUI>, ctx: &mut tx_context::TxContext): (clob_v2::Pool<BaseAsset, QuoteAsset>, clob_v2::PoolOwnerCap)
+
fun create_pool_with_return_<BaseAsset, QuoteAsset>(taker_fee_rate: u64, maker_rebate_rate: u64, tick_size: u64, lot_size: u64, creation_fee: balance::Balance<sui::SUI>, ctx: &mut tx_context::TxContext): (clob_v2::Pool<BaseAsset, QuoteAsset>, clob_v2::PoolOwnerCap)
 
@@ -1569,7 +1560,7 @@ Helper function that all the create pools now call to create pools. taker_fee_rate: u64, maker_rebate_rate: u64, tick_size: u64, - min_size: u64, + lot_size: u64, creation_fee: Balance<SUI>, ctx: &mut TxContext, ): (Pool<BaseAsset, QuoteAsset>, PoolOwnerCap) { @@ -1578,7 +1569,7 @@ Helper function that all the create pools now call to create pools. let base_type_name = type_name::get<BaseAsset>(); let quote_type_name = type_name::get<QuoteAsset>(); - assert!(clob_math::unsafe_mul(min_size, tick_size) > 0, EInvalidTickSizeMinSize); + assert!(clob_math::unsafe_mul(lot_size, tick_size) > 0, EInvalidTickSizeLotSize); assert!(base_type_name != quote_type_name, EInvalidPair); assert!(taker_fee_rate >= maker_rebate_rate, EInvalidFeeRateRebateRate); @@ -1597,7 +1588,7 @@ Helper function that all the create pools now call to create pools. taker_fee_rate, maker_rebate_rate, tick_size, - lot_size: min_size, + lot_size, }); (Pool<BaseAsset, QuoteAsset> { id: pool_uid, @@ -1609,7 +1600,7 @@ Helper function that all the create pools now call to create pools. taker_fee_rate, maker_rebate_rate, tick_size, - lot_size: min_size, + lot_size, base_custodian: custodian::new<BaseAsset>(ctx), quote_custodian: custodian::new<QuoteAsset>(ctx), creation_fee, @@ -1630,7 +1621,7 @@ Helper function that all the create pools now call to create pools. Function for creating an external pool. This API can be used to wrap deepbook pools into other objects. -
public fun create_pool_with_return<BaseAsset, QuoteAsset>(tick_size: u64, min_size: u64, creation_fee: coin::Coin<sui::SUI>, ctx: &mut tx_context::TxContext): clob_v2::Pool<BaseAsset, QuoteAsset>
+
public fun create_pool_with_return<BaseAsset, QuoteAsset>(tick_size: u64, lot_size: u64, creation_fee: coin::Coin<sui::SUI>, ctx: &mut tx_context::TxContext): clob_v2::Pool<BaseAsset, QuoteAsset>
 
@@ -1641,13 +1632,13 @@ Function for creating an external pool. This API can be used to wrap deepbook po
public fun create_pool_with_return<BaseAsset, QuoteAsset>(
     tick_size: u64,
-    min_size: u64,
+    lot_size: u64,
     creation_fee: Coin<SUI>,
     ctx: &mut TxContext,
 ): Pool<BaseAsset, QuoteAsset> {
     create_customized_pool_with_return<BaseAsset, QuoteAsset>(
         tick_size,
-        min_size,
+        lot_size,
         REFERENCE_TAKER_FEE_RATE,
         REFERENCE_MAKER_REBATE_RATE,
         creation_fee,
@@ -1669,7 +1660,7 @@ The taker_fee_rate should be greater than or equal to the maker_rebate_rate, and
 Taker_fee_rate of 0.25% should be 2_500_000 for example
 
 
-
public fun create_customized_pool_with_return<BaseAsset, QuoteAsset>(tick_size: u64, min_size: u64, taker_fee_rate: u64, maker_rebate_rate: u64, creation_fee: coin::Coin<sui::SUI>, ctx: &mut tx_context::TxContext): clob_v2::Pool<BaseAsset, QuoteAsset>
+
public fun create_customized_pool_with_return<BaseAsset, QuoteAsset>(tick_size: u64, lot_size: u64, taker_fee_rate: u64, maker_rebate_rate: u64, creation_fee: coin::Coin<sui::SUI>, ctx: &mut tx_context::TxContext): clob_v2::Pool<BaseAsset, QuoteAsset>
 
@@ -1680,7 +1671,7 @@ Taker_fee_rate of 0.25% should be 2_500_000 for example
public fun create_customized_pool_with_return<BaseAsset, QuoteAsset>(
     tick_size: u64,
-    min_size: u64,
+    lot_size: u64,
     taker_fee_rate: u64,
     maker_rebate_rate: u64,
     creation_fee: Coin<SUI>,
@@ -1690,7 +1681,7 @@ Taker_fee_rate of 0.25% should be 2_500_000 for example
         taker_fee_rate,
         maker_rebate_rate,
         tick_size,
-        min_size,
+        lot_size,
         coin::into_balance(creation_fee),
         ctx
     );
@@ -1712,7 +1703,7 @@ If a user wants to create a pool and then destroy/lock the pool_owner_cap one ca
 so with this function.
 
 
-
public fun create_customized_pool_v2<BaseAsset, QuoteAsset>(tick_size: u64, min_size: u64, taker_fee_rate: u64, maker_rebate_rate: u64, creation_fee: coin::Coin<sui::SUI>, ctx: &mut tx_context::TxContext): (clob_v2::Pool<BaseAsset, QuoteAsset>, clob_v2::PoolOwnerCap)
+
public fun create_customized_pool_v2<BaseAsset, QuoteAsset>(tick_size: u64, lot_size: u64, taker_fee_rate: u64, maker_rebate_rate: u64, creation_fee: coin::Coin<sui::SUI>, ctx: &mut tx_context::TxContext): (clob_v2::Pool<BaseAsset, QuoteAsset>, clob_v2::PoolOwnerCap)
 
@@ -1723,7 +1714,7 @@ so with this function.
public fun create_customized_pool_v2<BaseAsset, QuoteAsset>(
     tick_size: u64,
-    min_size: u64,
+    lot_size: u64,
     taker_fee_rate: u64,
     maker_rebate_rate: u64,
     creation_fee: Coin<SUI>,
@@ -1733,7 +1724,7 @@ so with this function.
         taker_fee_rate,
         maker_rebate_rate,
         tick_size,
-        min_size,
+        lot_size,
         coin::into_balance(creation_fee),
         ctx
     )
@@ -2178,8 +2169,8 @@ so with this function.
                         filled_quote_quantity_without_commission,
                         maker_order.price
                     );
-                    let filled_base_lot = filled_base_quantity / LOT_SIZE;
-                    filled_base_quantity = filled_base_lot * LOT_SIZE;
+                    let filled_base_lot = filled_base_quantity / pool.lot_size;
+                    filled_base_quantity = filled_base_lot * pool.lot_size;
                     // filled_quote_quantity_without_commission = 0 is permitted here since filled_base_quantity could be 0
                     filled_quote_quantity_without_commission = clob_math::unsafe_mul(
                         filled_base_quantity,
@@ -2802,8 +2793,7 @@ Place a market order to the order book.
     // We start with the bid PriceLevel with the highest price by calling max_leaf on the bids Critbit Tree.
     // The inner loop for iterating over the open orders in ascending orders of order id is the same as above.
     // Then iterate over the price levels in descending order until the market order is completely filled.
-    let min_size = pool.lot_size;
-    assert!(quantity >= min_size && quantity % LOT_SIZE == 0, EInvalidQuantity);
+    assert!(quantity % pool.lot_size == 0, EInvalidQuantity);
     assert!(quantity != 0, EInvalidQuantity);
     let metadata;
     if (is_bid) {
@@ -3094,8 +3084,7 @@ So please check that boolean value first before using the order id.
     assert!(quantity > 0, EInvalidQuantity);
     assert!(price > 0, EInvalidPrice);
     assert!(price % pool.tick_size == 0, EInvalidPrice);
-    let min_size = pool.lot_size;
-    assert!(quantity >= min_size && quantity % LOT_SIZE == 0, EInvalidQuantity);
+    assert!(quantity % pool.lot_size == 0, EInvalidQuantity);
     assert!(expire_timestamp > clock::timestamp_ms(clock), EInvalidExpireTimestamp);
     let owner = account_owner(account_cap);
     let original_quantity = quantity;
diff --git a/crates/sui-framework/packages/deepbook/sources/clob_v2.move b/crates/sui-framework/packages/deepbook/sources/clob_v2.move
index 102c4f0999a35..1fac57595f7cf 100644
--- a/crates/sui-framework/packages/deepbook/sources/clob_v2.move
+++ b/crates/sui-framework/packages/deepbook/sources/clob_v2.move
@@ -36,7 +36,7 @@ module deepbook::clob_v2 {
     const EInvalidPair: u64 = 16;
     const EInvalidFee: u64 = 18;
     const EInvalidExpireTimestamp: u64 = 19;
-    const EInvalidTickSizeMinSize: u64 = 20;
+    const EInvalidTickSizeLotSize: u64 = 20;
     const EInvalidSelfMatchingPreventionArg: u64 = 21;
 
     // <<<<<<<<<<<<<<<<<<<<<<<< Error codes <<<<<<<<<<<<<<<<<<<<<<<<
@@ -58,8 +58,6 @@ module deepbook::clob_v2 {
     const MIN_ASK_ORDER_ID: u64 = 1 << 63;
     const MIN_PRICE: u64 = 0;
     const MAX_PRICE: u64 = (1u128 << 64 - 1) as u64;
-    // Trade quantities must be in multiples of 1000. The lot_size in the pool structs is used as min_size.
-    const LOT_SIZE: u64 = 1000;
     #[test_only]
     const TIMESTAMP_INF: u64 = (1u128 << 64 - 1) as u64;
     const REFERENCE_TAKER_FEE_RATE: u64 = 2_500_000;
@@ -82,7 +80,7 @@ module deepbook::clob_v2 {
         // 10^9 scaling
         maker_rebate_rate: u64,
         tick_size: u64,
-        lot_size: u64, // lot_size in this context is the minimum trade size.
+        lot_size: u64,
     }
 
     /// Emitted when a maker order is injected into the order book.
@@ -253,7 +251,7 @@ module deepbook::clob_v2 {
         // 10^9 scaling
         maker_rebate_rate: u64,
         tick_size: u64,
-        lot_size: u64, // lot_size in this context is the minimum trade size.
+        lot_size: u64,
         // other pool info
         base_custodian: Custodian,
         quote_custodian: Custodian,
@@ -344,7 +342,7 @@ module deepbook::clob_v2 {
         taker_fee_rate: u64,
         maker_rebate_rate: u64,
         tick_size: u64,
-        min_size: u64,
+        lot_size: u64,
         creation_fee: Balance,
         ctx: &mut TxContext,
     ) {
@@ -352,7 +350,7 @@ module deepbook::clob_v2 {
             taker_fee_rate,
             maker_rebate_rate,
             tick_size,
-            min_size,
+            lot_size,
             creation_fee,
             ctx
         );
@@ -363,13 +361,13 @@ module deepbook::clob_v2 {
 
     public fun create_pool(
         tick_size: u64,
-        min_size: u64,
+        lot_size: u64,
         creation_fee: Coin,
         ctx: &mut TxContext,
     ) {
         create_customized_pool(
             tick_size,
-            min_size,
+            lot_size,
             REFERENCE_TAKER_FEE_RATE,
             REFERENCE_MAKER_REBATE_RATE,
             creation_fee,
@@ -382,7 +380,7 @@ module deepbook::clob_v2 {
     /// Taker_fee_rate of 0.25% should be 2_500_000 for example
     public fun create_customized_pool(
         tick_size: u64,
-        min_size: u64,
+        lot_size: u64,
         taker_fee_rate: u64,
         maker_rebate_rate: u64,
         creation_fee: Coin,
@@ -392,7 +390,7 @@ module deepbook::clob_v2 {
             taker_fee_rate,
             maker_rebate_rate,
             tick_size,
-            min_size,
+            lot_size,
             coin::into_balance(creation_fee),
             ctx
         )
@@ -403,7 +401,7 @@ module deepbook::clob_v2 {
         taker_fee_rate: u64,
         maker_rebate_rate: u64,
         tick_size: u64,
-        min_size: u64,
+        lot_size: u64,
         creation_fee: Balance,
         ctx: &mut TxContext,
     ): (Pool, PoolOwnerCap) {
@@ -412,7 +410,7 @@ module deepbook::clob_v2 {
         let base_type_name = type_name::get();
         let quote_type_name = type_name::get();
 
-        assert!(clob_math::unsafe_mul(min_size, tick_size) > 0, EInvalidTickSizeMinSize);
+        assert!(clob_math::unsafe_mul(lot_size, tick_size) > 0, EInvalidTickSizeLotSize);
         assert!(base_type_name != quote_type_name, EInvalidPair);
         assert!(taker_fee_rate >= maker_rebate_rate, EInvalidFeeRateRebateRate);
 
@@ -431,7 +429,7 @@ module deepbook::clob_v2 {
             taker_fee_rate,
             maker_rebate_rate,
             tick_size,
-            lot_size: min_size,
+            lot_size,
         });
         (Pool {
             id: pool_uid,
@@ -443,7 +441,7 @@ module deepbook::clob_v2 {
             taker_fee_rate,
             maker_rebate_rate,
             tick_size,
-            lot_size: min_size,
+            lot_size,
             base_custodian: custodian::new(ctx),
             quote_custodian: custodian::new(ctx),
             creation_fee,
@@ -455,13 +453,13 @@ module deepbook::clob_v2 {
     /// Function for creating an external pool. This API can be used to wrap deepbook pools into other objects.
     public fun create_pool_with_return(
         tick_size: u64,
-        min_size: u64,
+        lot_size: u64,
         creation_fee: Coin,
         ctx: &mut TxContext,
     ): Pool {
         create_customized_pool_with_return(
             tick_size,
-            min_size,
+            lot_size,
             REFERENCE_TAKER_FEE_RATE,
             REFERENCE_MAKER_REBATE_RATE,
             creation_fee,
@@ -475,7 +473,7 @@ module deepbook::clob_v2 {
     /// Taker_fee_rate of 0.25% should be 2_500_000 for example
     public fun create_customized_pool_with_return(
         tick_size: u64,
-        min_size: u64,
+        lot_size: u64,
         taker_fee_rate: u64,
         maker_rebate_rate: u64,
         creation_fee: Coin,
@@ -485,7 +483,7 @@ module deepbook::clob_v2 {
             taker_fee_rate,
             maker_rebate_rate,
             tick_size,
-            min_size,
+            lot_size,
             coin::into_balance(creation_fee),
             ctx
         );
@@ -498,7 +496,7 @@ module deepbook::clob_v2 {
     /// so with this function.
     public fun create_customized_pool_v2(
         tick_size: u64,
-        min_size: u64,
+        lot_size: u64,
         taker_fee_rate: u64,
         maker_rebate_rate: u64,
         creation_fee: Coin,
@@ -508,7 +506,7 @@ module deepbook::clob_v2 {
             taker_fee_rate,
             maker_rebate_rate,
             tick_size,
-            min_size,
+            lot_size,
             coin::into_balance(creation_fee),
             ctx
         )
@@ -776,8 +774,8 @@ module deepbook::clob_v2 {
                             filled_quote_quantity_without_commission,
                             maker_order.price
                         );
-                        let filled_base_lot = filled_base_quantity / LOT_SIZE;
-                        filled_base_quantity = filled_base_lot * LOT_SIZE;
+                        let filled_base_lot = filled_base_quantity / pool.lot_size;
+                        filled_base_quantity = filled_base_lot * pool.lot_size;
                         // filled_quote_quantity_without_commission = 0 is permitted here since filled_base_quantity could be 0
                         filled_quote_quantity_without_commission = clob_math::unsafe_mul(
                             filled_base_quantity,
@@ -1300,8 +1298,7 @@ module deepbook::clob_v2 {
         // We start with the bid PriceLevel with the highest price by calling max_leaf on the bids Critbit Tree.
         // The inner loop for iterating over the open orders in ascending orders of order id is the same as above.
         // Then iterate over the price levels in descending order until the market order is completely filled.
-        let min_size = pool.lot_size;
-        assert!(quantity >= min_size && quantity % LOT_SIZE == 0, EInvalidQuantity);
+        assert!(quantity % pool.lot_size == 0, EInvalidQuantity);
         assert!(quantity != 0, EInvalidQuantity);
         let metadata;
         if (is_bid) {
@@ -1512,8 +1509,7 @@ module deepbook::clob_v2 {
         assert!(quantity > 0, EInvalidQuantity);
         assert!(price > 0, EInvalidPrice);
         assert!(price % pool.tick_size == 0, EInvalidPrice);
-        let min_size = pool.lot_size;
-        assert!(quantity >= min_size && quantity % LOT_SIZE == 0, EInvalidQuantity);
+        assert!(quantity % pool.lot_size == 0, EInvalidQuantity);
         assert!(expire_timestamp > clock::timestamp_ms(clock), EInvalidExpireTimestamp);
         let owner = account_owner(account_cap);
         let original_quantity = quantity;
@@ -2244,12 +2240,12 @@ module deepbook::clob_v2 {
     #[test_only] public struct USD {}
 
     #[test_only]
-    public fun setup_test_with_tick_min(
+    public fun setup_test_with_tick_lot(
         taker_fee_rate: u64,
         maker_rebate_rate: u64,
         // tick size with scaling
         tick_size: u64,
-        min_size: u64,
+        lot_size: u64,
         scenario: &mut Scenario,
         sender: address,
     ) {
@@ -2264,7 +2260,7 @@ module deepbook::clob_v2 {
                 taker_fee_rate,
                 maker_rebate_rate,
                 tick_size,
-                min_size,
+                lot_size,
                 balance::create_for_testing(FEE_AMOUNT_FOR_CREATE_POOL),
                 test_scenario::ctx(scenario)
             );
@@ -2286,12 +2282,12 @@ module deepbook::clob_v2 {
     }
 
     #[test_only]
-    public fun setup_test_with_tick_min_and_wrapped_pool(
+    public fun setup_test_with_tick_lot_and_wrapped_pool(
         taker_fee_rate: u64,
         maker_rebate_rate: u64,
         // tick size with scaling
         tick_size: u64,
-        min_size: u64,
+        lot_size: u64,
         scenario: &mut Scenario,
         sender: address,
     ) {
@@ -2306,7 +2302,7 @@ module deepbook::clob_v2 {
                 taker_fee_rate,
                 maker_rebate_rate,
                 tick_size,
-                min_size,
+                lot_size,
                 balance::create_for_testing(FEE_AMOUNT_FOR_CREATE_POOL),
                 test_scenario::ctx(scenario)
             );
@@ -2325,7 +2321,7 @@ module deepbook::clob_v2 {
         scenario: &mut Scenario,
         sender: address,
     ) {
-        setup_test_with_tick_min(
+        setup_test_with_tick_lot(
             taker_fee_rate,
             maker_rebate_rate,
             1 * FLOAT_SCALING,
@@ -2342,7 +2338,7 @@ module deepbook::clob_v2 {
         scenario: &mut Scenario,
         sender: address,
     ) {
-        setup_test_with_tick_min_and_wrapped_pool(
+        setup_test_with_tick_lot_and_wrapped_pool(
             taker_fee_rate,
             maker_rebate_rate,
             1 * FLOAT_SCALING,
@@ -3173,8 +3169,8 @@ module deepbook::clob_v2 {
     }
 
     #[test]
-    #[expected_failure(abort_code = EInvalidTickSizeMinSize)]
-    fun test_create_pool_invalid_tick_size_min_size() {
+    #[expected_failure(abort_code = EInvalidTickSizeLotSize)]
+    fun test_create_pool_invalid_tick_size_lot_size() {
         let owner: address = @0xAAAA;
         let mut test = test_scenario::begin(owner);
         test_scenario::next_tx(&mut test, owner);
diff --git a/crates/sui-framework/packages/deepbook/tests/clob_tests.move b/crates/sui-framework/packages/deepbook/tests/clob_tests.move
index 58563a1673fb5..f2771a2cdce98 100644
--- a/crates/sui-framework/packages/deepbook/tests/clob_tests.move
+++ b/crates/sui-framework/packages/deepbook/tests/clob_tests.move
@@ -65,12 +65,6 @@ module deepbook::clob_test {
     #[test] fun test_inject_and_match_taker_bid_with_quote_quantity_partial_lot(
     ) { let _ = test_inject_and_match_taker_bid_with_quote_quantity_partial_lot_(scenario()); }
 
-    #[test] fun test_swap_exact_base_for_quote_min_size(
-    ) { let _ = test_swap_exact_base_for_quote_min_size_(scenario()); }
-
-    #[test, expected_failure(abort_code = clob::EInvalidQuantity)] fun test_place_order_less_than_min_size_error(
-    ) { let _ = test_place_order_less_than_min_size_error_(scenario()); }
-
     #[test] fun test_inject_and_match_taker_bid() { let _ = test_inject_and_match_taker_bid_(scenario()); }
 
     #[test] fun test_inject_and_match_taker_bid_with_skip_self_matching() { let _ = test_inject_and_match_taker_bid_with_skipping_self_matching_(scenario()); }
@@ -1241,8 +1235,8 @@ module deepbook::clob_test {
             let account_cap = test::take_from_sender(&test);
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_mut_custodian(&mut pool);
-            custodian::deposit(base_custodian, mint_for_testing(10000, ctx(&mut test)), account_cap_user);
-            custodian::deposit(quote_custodian, mint_for_testing(100000, ctx(&mut test)), account_cap_user);
+            custodian::deposit(base_custodian, mint_for_testing(1000, ctx(&mut test)), account_cap_user);
+            custodian::deposit(quote_custodian, mint_for_testing(10000, ctx(&mut test)), account_cap_user);
             test::return_shared(pool);
             test::return_to_sender(&test, account_cap);
         };
@@ -1257,7 +1251,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 5 * FLOAT_SCALING,
-                2000,
+                200,
                 CANCEL_OLDEST,
                 true,
                 TIMESTAMP_INF,
@@ -1270,7 +1264,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 5 * FLOAT_SCALING,
-                3000,
+                300,
                 CANCEL_OLDEST,
                 true,
                 TIMESTAMP_INF,
@@ -1283,7 +1277,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 2 * FLOAT_SCALING,
-                10000,
+                1000,
                 CANCEL_OLDEST,
                 true,
                 TIMESTAMP_INF,
@@ -1296,7 +1290,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 20 * FLOAT_SCALING,
-                10000,
+                1000,
                 CANCEL_OLDEST,
                 false,
                 TIMESTAMP_INF,
@@ -1310,13 +1304,13 @@ module deepbook::clob_test {
             assert!(next_ask_order_id == clob::order_id_for_test(1, false));
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_custodian(&pool);
-            custodian::assert_user_balance(base_custodian, account_cap_user, 0, 10000);
-            custodian::assert_user_balance(quote_custodian, account_cap_user, 55000, 45000);
+            custodian::assert_user_balance(base_custodian, account_cap_user, 0, 1000);
+            custodian::assert_user_balance(quote_custodian, account_cap_user, 5500, 4500);
             let (base_avail, base_locked, quote_avail, quote_locked) = account_balance(&pool, &account_cap);
             assert!(base_avail == 0);
-            assert!(base_locked == 10000);
-            assert!(quote_avail == 55000);
-            assert!(quote_locked == 45000);
+            assert!(base_locked == 1000);
+            assert!(quote_avail == 5500);
+            assert!(quote_locked == 4500);
             test::return_shared(pool);
             test::return_shared(clock);
             test::return_to_address(alice, account_cap);
@@ -1336,14 +1330,14 @@ module deepbook::clob_test {
             let mut pool = test::take_shared>(&test);
             let clock = test::take_shared(&test);
             let account_cap = test::take_from_address(&test, bob);
-            let (coin1, coin2) = clob::place_market_order(&mut pool, &account_cap, CLIENT_ID_BOB, 6000,
+            let (coin1, coin2) = clob::place_market_order(&mut pool, &account_cap, CLIENT_ID_BOB, 600,
                 false,
-                mint_for_testing(6000, ctx(&mut test)),
+                mint_for_testing(600, ctx(&mut test)),
                 mint_for_testing(0, ctx(&mut test)),
                 &clock,
                 ctx(&mut test));
             assert!(coin::value(&coin1) == 0);
-            assert!(coin::value(&coin2) == 27000 - 135);
+            assert!(coin::value(&coin2) == 2700 - 14);
             burn_for_testing(coin1);
             burn_for_testing(coin2);
             test::return_shared(pool);
@@ -1359,14 +1353,14 @@ module deepbook::clob_test {
             let mut pool = test::take_shared>(&test);
             let clock = test::take_shared(&test);
             let account_cap = test::take_from_address(&test, bob);
-            let (coin1, coin2) =clob::place_market_order(&mut pool, &account_cap, CLIENT_ID_BOB, 1000,
+            let (coin1, coin2) =clob::place_market_order(&mut pool, &account_cap, CLIENT_ID_BOB, 100,
                 false,
-                mint_for_testing(6000, ctx(&mut test)),
+                mint_for_testing(600, ctx(&mut test)),
                 mint_for_testing(0, ctx(&mut test)),
                 &clock,
                 ctx(&mut test));
-            assert!(coin::value(&coin1) == 5000);
-            assert!(coin::value(&coin2) == 1990);
+            assert!(coin::value(&coin1) == 500);
+            assert!(coin::value(&coin2) == 199);
             burn_for_testing(coin1);
             burn_for_testing(coin2);
             test::return_shared(pool);
@@ -1399,8 +1393,8 @@ module deepbook::clob_test {
             let account_cap = test::take_from_sender(&test);
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_mut_custodian(&mut pool);
-            custodian::deposit(base_custodian, mint_for_testing(10000, ctx(&mut test)), account_cap_user);
-            custodian::deposit(quote_custodian, mint_for_testing(100000, ctx(&mut test)), account_cap_user);
+            custodian::deposit(base_custodian, mint_for_testing(1000, ctx(&mut test)), account_cap_user);
+            custodian::deposit(quote_custodian, mint_for_testing(10000, ctx(&mut test)), account_cap_user);
             test::return_shared(pool);
             test::return_to_sender(&test, account_cap);
         };
@@ -1415,7 +1409,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 5 * FLOAT_SCALING,
-                2000,
+                200,
                 CANCEL_OLDEST,
                 true,
                 TIMESTAMP_INF,
@@ -1428,7 +1422,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 5 * FLOAT_SCALING,
-                3000,
+                300,
                 CANCEL_OLDEST,
                 true,
                 TIMESTAMP_INF,
@@ -1441,7 +1435,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 2 * FLOAT_SCALING,
-                10000,
+                1000,
                 CANCEL_OLDEST,
                 true,
                 TIMESTAMP_INF,
@@ -1454,7 +1448,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 20 * FLOAT_SCALING,
-                10000,
+                1000,
                 CANCEL_OLDEST,
                 false,
                 TIMESTAMP_INF,
@@ -1468,13 +1462,13 @@ module deepbook::clob_test {
             assert!(next_ask_order_id == clob::order_id_for_test(1, false));
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_custodian(&pool);
-            custodian::assert_user_balance(base_custodian, account_cap_user, 0, 10000);
-            custodian::assert_user_balance(quote_custodian, account_cap_user, 55000, 45000);
+            custodian::assert_user_balance(base_custodian, account_cap_user, 0, 1000);
+            custodian::assert_user_balance(quote_custodian, account_cap_user, 5500, 4500);
             let (base_avail, base_locked, quote_avail, quote_locked) = account_balance(&pool, &account_cap);
             assert!(base_avail == 0);
-            assert!(base_locked == 10000);
-            assert!(quote_avail == 55000);
-            assert!(quote_locked == 45000);
+            assert!(base_locked == 1000);
+            assert!(quote_avail == 5500);
+            assert!(quote_locked == 4500);
             test::return_shared(pool);
             test::return_shared(clock);
             test::return_to_address(alice, account_cap);
@@ -1486,8 +1480,8 @@ module deepbook::clob_test {
             let account_cap = test::take_from_sender(&test);
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_mut_custodian(&mut pool);
-            custodian::deposit(base_custodian, mint_for_testing(10000, ctx(&mut test)), account_cap_user);
-            custodian::deposit(quote_custodian, mint_for_testing(100000, ctx(&mut test)), account_cap_user);
+            custodian::deposit(base_custodian, mint_for_testing(1000, ctx(&mut test)), account_cap_user);
+            custodian::deposit(quote_custodian, mint_for_testing(10000, ctx(&mut test)), account_cap_user);
             test::return_shared(pool);
             test::return_to_sender(&test, account_cap);
         };
@@ -1502,7 +1496,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_BOB,
                 4 * FLOAT_SCALING,
-                4000,
+                400,
                 CANCEL_OLDEST,
                 false,
                 TIMESTAMP_INF,
@@ -1511,8 +1505,8 @@ module deepbook::clob_test {
                 &account_cap,
                 ctx(&mut test)
             );
-            assert!(base_quantity_filled == 4000);
-            assert!(quote_quantity_filled == 19900);
+            assert!(base_quantity_filled == 400);
+            assert!(quote_quantity_filled == 1990);
             assert!(is_placed == false);
             assert!(order_id == 0);
 
@@ -1529,9 +1523,9 @@ module deepbook::clob_test {
             let clock = test::take_shared(&test);
 
             let  (base_avail, base_locked, quote_avail, quote_locked) = account_balance(&pool, &account_cap);
-            assert!(base_avail == 6000);
+            assert!(base_avail == 600);
             assert!(base_locked == 0);
-            assert!(quote_avail == 119900);
+            assert!(quote_avail == 11990);
             assert!(quote_locked == 0);
 
             test::return_shared(pool);
@@ -1564,8 +1558,8 @@ module deepbook::clob_test {
             let account_cap = test::take_from_sender(&test);
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_mut_custodian(&mut pool);
-            custodian::deposit(base_custodian, mint_for_testing(10000, ctx(&mut test)), account_cap_user);
-            custodian::deposit(quote_custodian, mint_for_testing(100000, ctx(&mut test)), account_cap_user);
+            custodian::deposit(base_custodian, mint_for_testing(1000, ctx(&mut test)), account_cap_user);
+            custodian::deposit(quote_custodian, mint_for_testing(10000, ctx(&mut test)), account_cap_user);
             test::return_shared(pool);
             test::return_to_sender(&test, account_cap);
         };
@@ -1580,7 +1574,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 5 * FLOAT_SCALING,
-                2000,
+                200,
                 CANCEL_OLDEST,
                 true,
                 TIMESTAMP_INF,
@@ -1593,7 +1587,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 5 * FLOAT_SCALING,
-                3000,
+                300,
                 CANCEL_OLDEST,
                 true,
                 TIMESTAMP_INF,
@@ -1606,7 +1600,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 2 * FLOAT_SCALING,
-                10000,
+                1000,
                 CANCEL_OLDEST,
                 true,
                 TIMESTAMP_INF,
@@ -1619,7 +1613,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 20 * FLOAT_SCALING,
-                10000,
+                1000,
                 CANCEL_OLDEST,
                 false,
                 TIMESTAMP_INF,
@@ -1633,13 +1627,13 @@ module deepbook::clob_test {
             assert!(next_ask_order_id == clob::order_id_for_test(1, false));
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_custodian(&pool);
-            custodian::assert_user_balance(base_custodian, account_cap_user, 0, 10000);
-            custodian::assert_user_balance(quote_custodian, account_cap_user, 55000, 45000);
+            custodian::assert_user_balance(base_custodian, account_cap_user, 0, 1000);
+            custodian::assert_user_balance(quote_custodian, account_cap_user, 5500, 4500);
             let (base_avail, base_locked, quote_avail, quote_locked) = account_balance(&pool, &account_cap);
             assert!(base_avail == 0);
-            assert!(base_locked == 10000);
-            assert!(quote_avail == 55000);
-            assert!(quote_locked == 45000);
+            assert!(base_locked == 1000);
+            assert!(quote_avail == 5500);
+            assert!(quote_locked == 4500);
             test::return_shared(pool);
             test::return_shared(clock);
             test::return_to_address(alice, account_cap);
@@ -1651,8 +1645,8 @@ module deepbook::clob_test {
             let account_cap = test::take_from_sender(&test);
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_mut_custodian(&mut pool);
-            custodian::deposit(base_custodian, mint_for_testing(10000, ctx(&mut test)), account_cap_user);
-            custodian::deposit(quote_custodian, mint_for_testing(100000, ctx(&mut test)), account_cap_user);
+            custodian::deposit(base_custodian, mint_for_testing(1000, ctx(&mut test)), account_cap_user);
+            custodian::deposit(quote_custodian, mint_for_testing(10000, ctx(&mut test)), account_cap_user);
             test::return_shared(pool);
             test::return_to_sender(&test, account_cap);
         };
@@ -1667,7 +1661,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_BOB,
                 6 * FLOAT_SCALING,
-                4000,
+                400,
                 CANCEL_OLDEST,
                 false,
                 TIMESTAMP_INF,
@@ -1694,9 +1688,9 @@ module deepbook::clob_test {
             let clock = test::take_shared(&test);
 
             let  (base_avail, base_locked, quote_avail, quote_locked) = account_balance(&pool, &account_cap);
-            assert!(base_avail == 6000);
-            assert!(base_locked == 4000);
-            assert!(quote_avail == 100000);
+            assert!(base_avail == 600);
+            assert!(base_locked == 400);
+            assert!(quote_avail == 10000);
             assert!(quote_locked == 0);
 
             test::return_shared(pool);
@@ -1712,7 +1706,7 @@ module deepbook::clob_test {
         let owner: address = @0xF;
         next_tx(&mut test, owner);
         {
-            clob::setup_test_with_tick_min(5000000, 2500000, 1_00_000_000, 10, &mut test, owner);
+            clob::setup_test_with_tick_lot(5000000, 2500000, 1_00_000_000, 10, &mut test, owner);
         };
         next_tx(&mut test, alice);
         {
@@ -1728,8 +1722,8 @@ module deepbook::clob_test {
             let account_cap = test::take_from_sender(&test);
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_mut_custodian(&mut pool);
-            custodian::deposit(base_custodian, mint_for_testing(10000, ctx(&mut test)), account_cap_user);
-            custodian::deposit(quote_custodian, mint_for_testing(100000, ctx(&mut test)), account_cap_user);
+            custodian::deposit(base_custodian, mint_for_testing(1000, ctx(&mut test)), account_cap_user);
+            custodian::deposit(quote_custodian, mint_for_testing(10000, ctx(&mut test)), account_cap_user);
             test::return_shared(pool);
             test::return_to_sender(&test, account_cap);
         };
@@ -1744,7 +1738,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 5 * FLOAT_SCALING,
-                2000,
+                200,
                 CANCEL_OLDEST,
                 true,
                 TIMESTAMP_INF,
@@ -1757,7 +1751,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 5 * FLOAT_SCALING,
-                3000,
+                300,
                 CANCEL_OLDEST,
                 true,
                 TIMESTAMP_INF,
@@ -1770,7 +1764,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 2 * FLOAT_SCALING,
-                10000,
+                1000,
                 CANCEL_OLDEST,
                 true,
                 TIMESTAMP_INF,
@@ -1783,7 +1777,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 20 * FLOAT_SCALING,
-                10000,
+                1000,
                 CANCEL_OLDEST,
                 false,
                 TIMESTAMP_INF,
@@ -1793,17 +1787,17 @@ module deepbook::clob_test {
                 ctx(&mut test)
             );
             let (next_bid_order_id, next_ask_order_id, _, _) = clob::get_pool_stat(&pool);
-            assert!(next_bid_order_id == clob::order_id_for_test(3, true));
-            assert!(next_ask_order_id == clob::order_id_for_test(1, false));
+            assert!(next_bid_order_id == clob::order_id_for_test(3, true), 0);
+            assert!(next_ask_order_id == clob::order_id_for_test(1, false), 0);
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_custodian(&pool);
-            custodian::assert_user_balance(base_custodian, account_cap_user, 0, 10000);
-            custodian::assert_user_balance(quote_custodian, account_cap_user, 55000, 45000);
+            custodian::assert_user_balance(base_custodian, account_cap_user, 0, 1000);
+            custodian::assert_user_balance(quote_custodian, account_cap_user, 5500, 4500);
             let (base_avail, base_locked, quote_avail, quote_locked) = account_balance(&pool, &account_cap);
-            assert!(base_avail == 0);
-            assert!(base_locked == 10000);
-            assert!(quote_avail == 55000);
-            assert!(quote_locked == 45000);
+            assert!(base_avail == 0, 0);
+            assert!(base_locked == 1000, 0);
+            assert!(quote_avail == 5500, 0);
+            assert!(quote_locked == 4500, 0);
             test::return_shared(pool);
             test::return_shared(clock);
             test::return_to_address(alice, account_cap);
@@ -1815,13 +1809,13 @@ module deepbook::clob_test {
             let mut pool = test::take_shared>(&test);
             let clock = test::take_shared(&test);
             let account_cap = test::take_from_address(&test, bob);
-            let (coin1, coin2) = clob::place_market_order(&mut pool, &account_cap, CLIENT_ID_BOB, 20000, false,
-                mint_for_testing(20000, ctx(&mut test)),
+            let (coin1, coin2) = clob::place_market_order(&mut pool, &account_cap, CLIENT_ID_BOB, 2000, false,
+                mint_for_testing(2000, ctx(&mut test)),
                 mint_for_testing(0, ctx(&mut test)),
                 &clock,
                 ctx(&mut test));
-            assert!(coin::value(&coin1) == 5000);
-            assert!(coin::value(&coin2) == 44775);
+            assert!(coin::value(&coin1) == 500, 0);
+            assert!(coin::value(&coin2) == 4477, 0);
             burn_for_testing(coin1);
             burn_for_testing(coin2);
             test::return_shared(pool);
@@ -1837,7 +1831,7 @@ module deepbook::clob_test {
         // setup pool and custodian
         next_tx(&mut test, owner);
         {
-            clob::setup_test_with_tick_min(5000000, 2500000, 1_00_000_000, 10, &mut test, owner);
+            clob::setup_test_with_tick_lot(5000000, 2500000, 1_00_000_000, 10, &mut test, owner);
         };
         next_tx(&mut test, alice);
         {
@@ -1853,8 +1847,8 @@ module deepbook::clob_test {
             let account_cap = test::take_from_sender(&test);
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_mut_custodian(&mut pool);
-            custodian::deposit(base_custodian, mint_for_testing(100000, ctx(&mut test)), account_cap_user);
-            custodian::deposit(quote_custodian, mint_for_testing(100000, ctx(&mut test)), account_cap_user);
+            custodian::deposit(base_custodian, mint_for_testing(10000, ctx(&mut test)), account_cap_user);
+            custodian::deposit(quote_custodian, mint_for_testing(10000, ctx(&mut test)), account_cap_user);
             test::return_shared(pool);
             test::return_to_sender(&test, account_cap);
         };
@@ -1869,7 +1863,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 5 * FLOAT_SCALING,
-                5000,
+                500,
                 CANCEL_OLDEST,
                 false,
                 TIMESTAMP_INF,
@@ -1882,7 +1876,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 5 * FLOAT_SCALING,
-                5000,
+                500,
                 CANCEL_OLDEST,
                 false,
                 TIMESTAMP_INF,
@@ -1895,7 +1889,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 2 * FLOAT_SCALING,
-                10000,
+                1000,
                 CANCEL_OLDEST,
                 false,
                 TIMESTAMP_INF,
@@ -1908,7 +1902,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 1 * FLOAT_SCALING,
-                10000,
+                1000,
                 CANCEL_OLDEST,
                 true,
                 TIMESTAMP_INF,
@@ -1922,13 +1916,13 @@ module deepbook::clob_test {
             assert!(next_ask_order_id == clob::order_id_for_test(3, false));
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_custodian(&pool);
-            custodian::assert_user_balance(base_custodian, account_cap_user, 80000, 20000);
-            custodian::assert_user_balance(quote_custodian, account_cap_user, 90000, 10000);
+            custodian::assert_user_balance(base_custodian, account_cap_user, 8000, 2000);
+            custodian::assert_user_balance(quote_custodian, account_cap_user, 9000, 1000);
             let (base_avail, base_locked, quote_avail, quote_locked) = account_balance(&pool, &account_cap);
-            assert!(base_avail == 80000);
-            assert!(base_locked == 20000);
-            assert!(quote_avail == 90000);
-            assert!(quote_locked == 10000);
+            assert!(base_avail == 8000);
+            assert!(base_locked == 2000);
+            assert!(quote_avail == 9000);
+            assert!(quote_locked == 1000);
             test::return_shared(pool);
             test::return_shared(clock);
             test::return_to_address(alice, account_cap);
@@ -1940,13 +1934,13 @@ module deepbook::clob_test {
             let mut pool = test::take_shared>(&test);
             let clock = test::take_shared(&test);
             let account_cap = test::take_from_address(&test, bob);
-            let (coin1, coin2) = clob::place_market_order(&mut pool, &account_cap, CLIENT_ID_BOB, 50000, true,
-                mint_for_testing(100000, ctx(&mut test)),
-                mint_for_testing(100000, ctx(&mut test)),
+            let (coin1, coin2) = clob::place_market_order(&mut pool, &account_cap, CLIENT_ID_BOB, 5000, true,
+                mint_for_testing(10000, ctx(&mut test)),
+                mint_for_testing(10000, ctx(&mut test)),
                 &clock,
                 ctx(&mut test));
-            assert!(coin::value(&coin1) == 120000);
-            assert!(coin::value(&coin2) == 100000 - (70000 + 350));
+            assert!(coin::value(&coin1) == 12000);
+            assert!(coin::value(&coin2) == 10000 - (7000 + 36));
             burn_for_testing(coin1);
             burn_for_testing(coin2);
             test::return_shared(pool);
@@ -1978,17 +1972,17 @@ module deepbook::clob_test {
             let account_cap = test::take_from_address(&test, alice);
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_mut_custodian(&mut pool);
-            let alice_deposit_WSUI: u64 = 100000;
-            let alice_deposit_USDC: u64 = 100000;
+            let alice_deposit_WSUI: u64 = 10000;
+            let alice_deposit_USDC: u64 = 10000;
             custodian::test_increase_user_available_balance(base_custodian, account_cap_user, alice_deposit_WSUI);
             custodian::test_increase_user_available_balance(quote_custodian, account_cap_user, alice_deposit_USDC);
-            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 5000, 5000, false,
+            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 500, 500, false,
                 CANCEL_OLDEST, &account_cap, ctx(&mut test));
-            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 5000, 5000, false,
+            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 500, 500, false,
                 CANCEL_OLDEST, &account_cap, ctx(&mut test));
-            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 2 * FLOAT_SCALING, 10000, 10000, false,
+            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 2 * FLOAT_SCALING, 1000, 1000, false,
                 CANCEL_OLDEST, &account_cap, ctx(&mut test));
-            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE,1 * FLOAT_SCALING, 100000, 100000, true,
+            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE,1 * FLOAT_SCALING, 10000, 10000, true,
                 CANCEL_OLDEST, &account_cap, ctx(&mut test));
 
             test::return_shared(pool);
@@ -2004,13 +1998,13 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_BOB,
                 &account_cap,
-                45000,
+                4500,
                 &clock,
-                mint_for_testing(45000, ctx(&mut test)),
+                mint_for_testing(4500, ctx(&mut test)),
                 ctx(&mut test)
             );
-            assert!(coin::value(&base_coin) == 10000 + 4000);
-            assert!(coin::value("e_coin) == 4800);
+            assert!(coin::value(&base_coin) == 1000 + 495);
+            assert!(coin::value("e_coin) == 2);
             burn_for_testing(base_coin);
             burn_for_testing(quote_coin);
 
@@ -2048,17 +2042,17 @@ module deepbook::clob_test {
             let account_cap = test::take_from_address(&test, alice);
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_mut_custodian(&mut pool);
-            let alice_deposit_WSUI: u64 = 100000;
-            let alice_deposit_USDC: u64 = 100000;
+            let alice_deposit_WSUI: u64 = 10000;
+            let alice_deposit_USDC: u64 = 10000;
             custodian::test_increase_user_available_balance(base_custodian, account_cap_user, alice_deposit_WSUI);
             custodian::test_increase_user_available_balance(quote_custodian, account_cap_user, alice_deposit_USDC);
-            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE,5 * FLOAT_SCALING, 5000, 5000, true,
+            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE,5 * FLOAT_SCALING, 500, 500, true,
                 CANCEL_OLDEST, &account_cap, ctx(&mut test));
-            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE,5 * FLOAT_SCALING, 5000, 5000, true,
+            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE,5 * FLOAT_SCALING, 500, 500, true,
                 CANCEL_OLDEST, &account_cap, ctx(&mut test));
-            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE,2 * FLOAT_SCALING, 10000, 10000, true,
+            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE,2 * FLOAT_SCALING, 1000, 1000, true,
                 CANCEL_OLDEST, &account_cap, ctx(&mut test));
-            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE,10 * FLOAT_SCALING, 100000, 100000, false,
+            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE,10 * FLOAT_SCALING, 10000, 10000, false,
                 CANCEL_OLDEST, &account_cap, ctx(&mut test));
             test::return_shared(pool);
             test::return_to_address(alice, account_cap);
@@ -2073,8 +2067,8 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_BOB,
                 &account_cap,
-                15000,
-                mint_for_testing(15000, ctx(&mut test)),
+                1500,
+                mint_for_testing(1500, ctx(&mut test)),
                 mint_for_testing(0,  ctx(&mut test)),
                 &clock,
                 ctx(&mut test)
@@ -2084,7 +2078,7 @@ module deepbook::clob_test {
             clob::check_balance_invariants_for_account(&alice_account_cap, quote_custodian, base_custodian, &pool);
 
             assert!(coin::value(&base_coin) == 0);
-            assert!(coin::value("e_coin) == 59700);
+            assert!(coin::value("e_coin) == 5969);
             burn_for_testing(base_coin);
             burn_for_testing(quote_coin);
 
@@ -2667,7 +2661,7 @@ module deepbook::clob_test {
         {
             let mut pool = test::take_shared>(&test);
             let account_cap = test::take_from_address(&test, bob);
-            let (base_quantity_filled, quote_quantity_filled) = clob::test_match_bid_with_quote_quantity(&mut pool, &account_cap, CLIENT_ID_BOB, 5000, MAX_PRICE, 0);
+            let (base_quantity_filled, quote_quantity_filled) = clob::test_match_bid_with_quote_quantity(&mut pool, &account_cap, CLIENT_ID_BOB, 500, MAX_PRICE, 0);
             assert_eq(base_quantity_filled, 0);
             assert_eq(quote_quantity_filled, 0);
             test::return_to_address(bob, account_cap);
@@ -2679,17 +2673,17 @@ module deepbook::clob_test {
             let account_cap = test::take_from_address(&test, alice);
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_mut_custodian(&mut pool);
-            let alice_deposit_WSUI: u64 = 100000;
-            let alice_deposit_USDC: u64 = 100000;
+            let alice_deposit_WSUI: u64 = 10000;
+            let alice_deposit_USDC: u64 = 10000;
             custodian::test_increase_user_available_balance(base_custodian, account_cap_user, alice_deposit_WSUI);
             custodian::test_increase_user_available_balance(quote_custodian, account_cap_user, alice_deposit_USDC);
-            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 5000, 5000, false,
+            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 500, 500, false,
                 CANCEL_OLDEST, &account_cap, ctx(&mut test));
-            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 5000, 5000, false,
+            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 500, 500, false,
                 CANCEL_OLDEST, &account_cap, ctx(&mut test));
-            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE,  2 * FLOAT_SCALING, 10000, 10000, false,
+            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE,  2 * FLOAT_SCALING, 1000, 1000, false,
                 CANCEL_OLDEST, &account_cap, ctx(&mut test));
-            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE,  1 * FLOAT_SCALING, 100000, 100000, true,
+            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE,  1 * FLOAT_SCALING, 10000, 10000, true,
                 CANCEL_OLDEST, &account_cap, ctx(&mut test));
             test::return_shared(pool);
             test::return_to_address(alice, account_cap);
@@ -2703,8 +2697,8 @@ module deepbook::clob_test {
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_custodian(&pool);
 
-            custodian::assert_user_balance(quote_custodian, account_cap_user, 0, 100000);
-            custodian::assert_user_balance(base_custodian, account_cap_user, 80000, 20000);
+            custodian::assert_user_balance(quote_custodian, account_cap_user, 0, 10000);
+            custodian::assert_user_balance(base_custodian, account_cap_user, 8000, 2000);
             let (next_bid_order_id, next_ask_order_id, _, _) = clob::get_pool_stat(&pool);
             assert!(next_bid_order_id == clob::order_id_for_test(1, true));
             assert!(next_ask_order_id == clob::order_id_for_test(3, false));
@@ -2713,11 +2707,11 @@ module deepbook::clob_test {
                 let mut open_orders = vector::empty();
                 vector::push_back(
                     &mut open_orders,
-                    clob::test_construct_order(0, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 5000, 5000, false, account_cap_user)
+                    clob::test_construct_order(0, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 500, 500, false, account_cap_user)
                 );
                 vector::push_back(
                     &mut open_orders,
-                    clob::test_construct_order(1, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 5000, 5000, false, account_cap_user)
+                    clob::test_construct_order(1, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 500, 500, false, account_cap_user)
                 );
                 let (_, _, _, asks) = get_pool_stat(&pool);
                 clob::check_tick_level(asks, 5 * FLOAT_SCALING, &open_orders);
@@ -2727,7 +2721,7 @@ module deepbook::clob_test {
                 let mut open_orders = vector::empty();
                 vector::push_back(
                     &mut open_orders,
-                    clob::test_construct_order(2, CLIENT_ID_ALICE, 2 * FLOAT_SCALING, 10000, 10000, false, account_cap_user)
+                    clob::test_construct_order(2, CLIENT_ID_ALICE, 2 * FLOAT_SCALING, 1000, 1000, false, account_cap_user)
                 );
                 let (_, _, _, asks) = get_pool_stat(&pool);
                 clob::check_tick_level(asks, 2 * FLOAT_SCALING, &open_orders);
@@ -2737,7 +2731,7 @@ module deepbook::clob_test {
                 let mut open_orders = vector::empty();
                 vector::push_back(
                     &mut open_orders,
-                    clob::test_construct_order(0, CLIENT_ID_ALICE, 1 * FLOAT_SCALING, 100000, 100000, true, account_cap_user)
+                    clob::test_construct_order(0, CLIENT_ID_ALICE, 1 * FLOAT_SCALING, 10000, 10000, true, account_cap_user)
                 );
                 let (_, _, bid, _) = get_pool_stat(&pool);
                 clob::check_tick_level(bid, 1 * FLOAT_SCALING, &open_orders);
@@ -2755,17 +2749,17 @@ module deepbook::clob_test {
                 &mut pool,
                 &account_cap,
                 CLIENT_ID_BOB,
-                45000,
+                4500,
                 MAX_PRICE,
                 0,
             );
-            assert!(base_quantity_filled == 10000 + 4000);
-            assert!(quote_quantity_filled == 40200);
+            assert!(base_quantity_filled == 1000 + 495);
+            assert!(quote_quantity_filled == 4498);
             let (base_quantity_filled, quote_quantity_filled) = clob::test_match_bid_with_quote_quantity(
                 &mut pool,
                 &account_cap,
                 CLIENT_ID_BOB,
-                5000,
+                500,
                 0,
                 0,
             );
@@ -2781,8 +2775,8 @@ module deepbook::clob_test {
             let account_cap_user_alice = account_owner(&account_cap_alice);
             let (base_custodian, quote_custodian) = clob::borrow_custodian(&pool);
 
-            custodian::assert_user_balance(quote_custodian, account_cap_user_alice, 40200 - 100 - 100 + 50 + 50, 100000);
-            custodian::assert_user_balance(base_custodian, account_cap_user_alice, 80000, 6000);
+            custodian::assert_user_balance(quote_custodian, account_cap_user_alice, 4498 - 10 - 13 + 5 + 6, 10000);
+            custodian::assert_user_balance(base_custodian, account_cap_user_alice, 8000, 500 + 5);
             {
                 let (_, _, _, asks) = get_pool_stat(&pool);
                 clob::check_empty_tick_level(asks, 2 * FLOAT_SCALING);
@@ -2791,11 +2785,11 @@ module deepbook::clob_test {
                 let mut open_orders = vector::empty();
                 vector::push_back(
                     &mut open_orders,
-                    clob::test_construct_order(0, CLIENT_ID_ALICE,  5 * FLOAT_SCALING, 5000, 1000, false, account_cap_user_alice)
+                    clob::test_construct_order(0, CLIENT_ID_ALICE,  5 * FLOAT_SCALING, 5, 5, false, account_cap_user_alice)
                 );
                 vector::push_back(
                     &mut open_orders,
-                    clob::test_construct_order(1, CLIENT_ID_ALICE,  5 * FLOAT_SCALING, 5000, 5000, false, account_cap_user_alice)
+                    clob::test_construct_order(1, CLIENT_ID_ALICE,  5 * FLOAT_SCALING, 500, 500, false, account_cap_user_alice)
                 );
                 let (_, _, _, asks) = get_pool_stat(&pool);
                 clob::check_tick_level(asks, 5 * FLOAT_SCALING, &open_orders);
@@ -2805,7 +2799,7 @@ module deepbook::clob_test {
                 let mut open_orders = vector::empty();
                 vector::push_back(
                     &mut open_orders,
-                    clob::test_construct_order(0, CLIENT_ID_ALICE, 1 * FLOAT_SCALING, 100000, 100000, true, account_cap_user_alice)
+                    clob::test_construct_order(0, CLIENT_ID_ALICE, 1 * FLOAT_SCALING, 10000, 10000, true, account_cap_user_alice)
                 );
                 let (_, _, bid, _) = get_pool_stat(&pool);
                 clob::check_tick_level(bid, 1 * FLOAT_SCALING, &open_orders);
@@ -2815,15 +2809,15 @@ module deepbook::clob_test {
             let mut open_orders_cmp = vector::empty();
             vector::push_back(
                 &mut open_orders_cmp,
-                clob::test_construct_order(0, CLIENT_ID_ALICE,  5 * FLOAT_SCALING, 5000, 1000, false, account_cap_user_alice)
+                clob::test_construct_order(0, CLIENT_ID_ALICE,  5 * FLOAT_SCALING, 500, 5, false, account_cap_user_alice)
             );
             vector::push_back(
                 &mut open_orders_cmp,
-                clob::test_construct_order(1, CLIENT_ID_ALICE,  5 * FLOAT_SCALING, 5000, 5000, false, account_cap_user_alice)
+                clob::test_construct_order(1, CLIENT_ID_ALICE,  5 * FLOAT_SCALING, 500, 500, false, account_cap_user_alice)
             );
             vector::push_back(
                 &mut open_orders_cmp,
-                clob::test_construct_order(0, CLIENT_ID_ALICE, 1 * FLOAT_SCALING, 100000, 100000, true, account_cap_user_alice)
+                clob::test_construct_order(0, CLIENT_ID_ALICE, 1 * FLOAT_SCALING, 10000, 10000, true, account_cap_user_alice)
             );
             assert!(open_orders == open_orders_cmp);
             test::return_shared(pool);
@@ -2839,12 +2833,12 @@ module deepbook::clob_test {
                 &mut pool,
                &account_cap,
                 CLIENT_ID_BOB,
-                40000,
+                3000,
                 MAX_PRICE,
                 0,
             );
-            assert_eq(base_quantity_filled, 6000);
-            assert_eq(quote_quantity_filled, 30150);
+            assert_eq(base_quantity_filled, 505);
+            assert_eq(quote_quantity_filled, 2539);
             test::return_shared(pool);
             test::return_to_address(bob, account_cap);
         };
@@ -2873,7 +2867,7 @@ module deepbook::clob_test {
         // setup pool and custodian
         next_tx(&mut test, owner);
         {
-            clob::setup_test_with_tick_min(5000000, 2500000, 1 * FLOAT_SCALING, 100, &mut test, owner);
+            clob::setup_test_with_tick_lot(5000000, 2500000, 1 * FLOAT_SCALING, 100, &mut test, owner);
         };
         next_tx(&mut test, alice);
         {
@@ -2996,7 +2990,7 @@ module deepbook::clob_test {
         // setup pool and custodian
         next_tx(&mut test, owner);
         {
-            clob::setup_test_with_tick_min(5000000, 2500000, 1 * FLOAT_SCALING, 10, &mut test, owner);
+            clob::setup_test_with_tick_lot(5000000, 2500000, 1 * FLOAT_SCALING, 10, &mut test, owner);
         };
         next_tx(&mut test, alice);
         {
@@ -3012,17 +3006,17 @@ module deepbook::clob_test {
             let account_cap = test::take_from_address(&test, alice);
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_mut_custodian(&mut pool);
-            let alice_deposit_WSUI: u64 = 100000;
-            let alice_deposit_USDC: u64 = 100000;
+            let alice_deposit_WSUI: u64 = 10000;
+            let alice_deposit_USDC: u64 = 10000;
             custodian::test_increase_user_available_balance(base_custodian, account_cap_user, alice_deposit_WSUI);
             custodian::test_increase_user_available_balance(quote_custodian, account_cap_user, alice_deposit_USDC);
-            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 5000, 5000, false,
+            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 500, 500, false,
                 CANCEL_OLDEST, &account_cap, ctx(&mut test));
-            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 5000, 5000, false,
+            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 500, 500, false,
                 CANCEL_OLDEST, &account_cap, ctx(&mut test));
-            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 2 * FLOAT_SCALING, 10000, 10000, false,
+            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 2 * FLOAT_SCALING, 1000, 1000, false,
                 CANCEL_OLDEST, &account_cap, ctx(&mut test));
-            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 1 * FLOAT_SCALING, 100000, 100000, true,
+            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 1 * FLOAT_SCALING, 10000, 10000, true,
                 CANCEL_OLDEST, &account_cap, ctx(&mut test));
             test::return_shared(pool);
             test::return_to_address(alice, account_cap);
@@ -3035,12 +3029,12 @@ module deepbook::clob_test {
                 &mut pool,
                 &account_cap,
                 CLIENT_ID_BOB,
-                45000,
+                4500,
                 MAX_PRICE,
                 0,
             );
-            assert!(base_quantity_filled == 10000 + 4000);
-            assert!(quote_quantity_filled == 40200);
+            assert!(base_quantity_filled == 1000 + 490);
+            assert!(quote_quantity_filled == 4473);
             test::return_shared(pool);
             test::return_to_address(bob, account_cap);
         };
@@ -3051,8 +3045,8 @@ module deepbook::clob_test {
             let account_cap_user_alice = account_owner(&account_cap_alice);
             let (base_custodian, quote_custodian) = clob::borrow_custodian(&pool);
 
-            custodian::assert_user_balance(quote_custodian, account_cap_user_alice, 40200 - 100 - 100 + 50 + 50, 100000);
-            custodian::assert_user_balance(base_custodian, account_cap_user_alice, 80000, 5000 + 1000);
+            custodian::assert_user_balance(quote_custodian, account_cap_user_alice, 4473 - 10 - 13 + 5 + 6, 10000);
+            custodian::assert_user_balance(base_custodian, account_cap_user_alice, 8000, 500 + 10);
             {
                 let (_, _, _, asks) = get_pool_stat(&pool);
                 clob::check_empty_tick_level(asks, 2 * FLOAT_SCALING);
@@ -3061,11 +3055,11 @@ module deepbook::clob_test {
                 let mut open_orders = vector::empty();
                 vector::push_back(
                     &mut open_orders,
-                    clob::test_construct_order(0, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 5000, 1000, false, account_cap_user_alice)
+                    clob::test_construct_order(0, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 10, 10, false, account_cap_user_alice)
                 );
                 vector::push_back(
                     &mut open_orders,
-                    clob::test_construct_order(1, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 5000, 5000, false, account_cap_user_alice)
+                    clob::test_construct_order(1, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 500, 500, false, account_cap_user_alice)
                 );
                 let (_, _, _, asks) = get_pool_stat(&pool);
                 clob::check_tick_level(asks, 5 * FLOAT_SCALING, &open_orders);
@@ -3075,7 +3069,7 @@ module deepbook::clob_test {
                 let mut open_orders = vector::empty();
                 vector::push_back(
                     &mut open_orders,
-                    clob::test_construct_order(0, CLIENT_ID_ALICE, 1 * FLOAT_SCALING, 100000, 100000, true, account_cap_user_alice)
+                    clob::test_construct_order(0, CLIENT_ID_ALICE, 1 * FLOAT_SCALING, 10000, 10000, true, account_cap_user_alice)
                 );
                 let (_, _, bid, _) = get_pool_stat(&pool);
                 clob::check_tick_level(bid, 1 * FLOAT_SCALING, &open_orders);
@@ -3085,15 +3079,15 @@ module deepbook::clob_test {
             let mut open_orders_cmp = vector::empty();
             vector::push_back(
                 &mut open_orders_cmp,
-                clob::test_construct_order(0, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 5000, 1000, false, account_cap_user_alice)
+                clob::test_construct_order(0, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 500, 10, false, account_cap_user_alice)
             );
             vector::push_back(
                 &mut open_orders_cmp,
-                clob::test_construct_order(1, CLIENT_ID_ALICE, 5 * FLOAT_SCALING,5000, 5000, false, account_cap_user_alice)
+                clob::test_construct_order(1, CLIENT_ID_ALICE, 5 * FLOAT_SCALING,500, 500, false, account_cap_user_alice)
             );
             vector::push_back(
                 &mut open_orders_cmp,
-                clob::test_construct_order(0, CLIENT_ID_ALICE, 1 * FLOAT_SCALING, 100000, 100000, true, account_cap_user_alice)
+                clob::test_construct_order(0, CLIENT_ID_ALICE, 1 * FLOAT_SCALING, 10000, 10000, true, account_cap_user_alice)
             );
             assert!(open_orders == open_orders_cmp);
             test::return_shared(pool);
@@ -3102,147 +3096,6 @@ module deepbook::clob_test {
         end(test)
     }
 
-    // This scenario tests a user trying to place an order that's greater than lot_size but less than min_size.
-    fun test_place_order_less_than_min_size_error_(mut test: Scenario): TransactionEffects {
-        let (alice, _) = people();
-        let owner: address = @0xF;
-        let min_size = 100000000; // 0.1 SUI
-        // setup pool and custodian
-        next_tx(&mut test, owner);
-        {
-            clob::setup_test_with_tick_min(0, 0, 1 * FLOAT_SCALING, min_size, &mut test, owner);
-        };
-        next_tx(&mut test, alice);
-        {
-            mint_account_cap_transfer(alice, test::ctx(&mut test));
-        };
-        next_tx(&mut test, alice);
-        {
-            let mut pool = test::take_shared>(&test);
-            let account_cap = test::take_from_sender(&test);
-            let account_cap_user = account_owner(&account_cap);
-            let (base_custodian, quote_custodian) = clob::borrow_mut_custodian(&mut pool);
-            custodian::deposit(base_custodian, mint_for_testing(10000000, ctx(&mut test)), account_cap_user);
-            custodian::deposit(quote_custodian, mint_for_testing(10000000, ctx(&mut test)), account_cap_user);
-            test::return_shared(pool);
-            test::return_to_sender(&test, account_cap);
-        };
-
-        // alice places limit orders
-        next_tx(&mut test, alice);
-        {
-            let mut pool = test::take_shared>(&test);
-            let account_cap = test::take_from_address(&test, alice);
-            let clock = test::take_shared(&test);
-            clob::place_limit_order(
-                &mut pool,
-                CLIENT_ID_ALICE,
-                5 * FLOAT_SCALING,
-                10000000,
-                CANCEL_OLDEST,
-                true,
-                TIMESTAMP_INF,
-                0,
-                &clock,
-                &account_cap,
-                ctx(&mut test)
-            );
-            test::return_shared(pool);
-            test::return_shared(clock);
-            test::return_to_address(alice, account_cap);
-        };
-        end(test)
-    }
-
-    fun test_swap_exact_base_for_quote_min_size_(mut test: Scenario): TransactionEffects {
-        let (alice, bob) = people();
-        let owner = @0xF;
-        let min_size = 100000000; // 0.1 SUI
-        let lot_size = 1000;
-        // setup pool and custodian
-        next_tx(&mut test, owner);
-        {
-            clob::setup_test_with_tick_min(0, 0, 1 * FLOAT_SCALING, min_size, &mut test, owner);
-        };
-        next_tx(&mut test, alice);
-        {
-            mint_account_cap_transfer(alice, test::ctx(&mut test));
-        };
-        next_tx(&mut test, bob);
-        {
-            mint_account_cap_transfer(bob, test::ctx(&mut test));
-        };
-        next_tx(&mut test, alice);
-        {
-            // assuming 9 decimal points, alice gets 5 SUI and 5 USDC
-            // alice places a limit buy of 0.2 SUI at $4, costing her 0.8 USDC
-            // alice places a limit sell of 0.2 SUI at $5, costing her 0.2 SUI
-            let mut pool = test::take_shared>(&test);
-            let account_cap = test::take_from_address(&test, alice);
-            let account_cap_user = account_owner(&account_cap);
-            let (base_custodian, quote_custodian) = clob::borrow_mut_custodian(&mut pool);
-            let alice_deposit_WSUI: u64 = 50 * min_size;
-            let alice_deposit_USDC: u64 = 50 * min_size;
-            custodian::test_increase_user_available_balance(base_custodian, account_cap_user, alice_deposit_WSUI);
-            custodian::test_increase_user_available_balance(quote_custodian, account_cap_user, alice_deposit_USDC);
-            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 4 * FLOAT_SCALING, 2 * min_size, 2 * min_size, true,
-                CANCEL_OLDEST, &account_cap, ctx(&mut test));
-            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 2 * min_size, 2 * min_size, false,
-                CANCEL_OLDEST, &account_cap, ctx(&mut test));
-            test::return_shared(pool);
-            test::return_to_address(alice, account_cap);
-        };
-        next_tx(&mut test, bob);
-        {
-            let pool = test::take_shared>(&test);
-            let account_cap_alice = test::take_from_address(&test, alice);
-            let account_cap_user_alice = account_owner(&account_cap_alice);
-            let (base_custodian, quote_custodian) = clob::borrow_custodian(&pool);
-
-            // alice has 4.2 USDC available and 0.8 USDC locked
-            custodian::assert_user_balance(quote_custodian, account_cap_user_alice, 4_200_000_000, 800_000_000);
-            // alice has 4.8 SUI available and 0.2 SUI locked
-            custodian::assert_user_balance(base_custodian, account_cap_user_alice, 4_800_000_000, 200_000_000);
-            test::return_shared(pool);
-            test::return_to_address(alice, account_cap_alice);
-        };
-        next_tx(&mut test, bob);
-        {
-            // bob pays 0.5001 USDC to buy as much SUI from the market as possible. He is matched against alice's $5 limit order.
-            let mut pool = test::take_shared>(&test);
-            let account_cap = test::take_from_address(&test, bob);
-            let (base_quantity_filled, quote_quantity_filled) = clob::test_match_bid_with_quote_quantity(
-                &mut pool,
-                &account_cap,
-                CLIENT_ID_BOB,
-                500_100_000,
-                MAX_PRICE,
-                0,
-            );
-            // bob's 0.5 USDC fills the minimum of 0.1 SUI and an additional 20 lots, 0.0002 at $5.
-            assert!(base_quantity_filled == 1 * min_size + (20 * lot_size));
-            // all of bob's quote asset was filled.
-            assert!(quote_quantity_filled == 500_100_000);
-            test::return_shared(pool);
-            test::return_to_address(bob, account_cap);
-        };
-        next_tx(&mut test, bob);
-        {
-            let pool = test::take_shared>(&test);
-            let account_cap_alice = test::take_from_address(&test, alice);
-            let account_cap_user_alice = account_owner(&account_cap_alice);
-            let (base_custodian, quote_custodian) = clob::borrow_custodian(&pool);
-
-            // alice received bob's 0.5001 USDC, increasing the available balance to 4.7001 USDC
-            custodian::assert_user_balance(quote_custodian, account_cap_user_alice, 4_700_100_000, 800_000_000);
-            // alice's locked SUI was reduced by 0.10002 SUI
-            custodian::assert_user_balance(base_custodian, account_cap_user_alice, 4_800_000_000, 99_980_000);
-            test::return_shared(pool);
-            test::return_to_address(alice, account_cap_alice);
-        };
-        end(test)
-    }
-
     fun test_inject_and_match_taker_bid_(mut test: Scenario): TransactionEffects {
         let (alice, bob) = people();
         let owner = @0xF;
@@ -3705,16 +3558,16 @@ module deepbook::clob_test {
             let account_cap = test::take_from_address(&test, alice);
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_mut_custodian(&mut pool);
-            let alice_deposit_WSUI: u64 = 100000;
-            let alice_deposit_USDC: u64 = 100000;
+            let alice_deposit_WSUI: u64 = 10000;
+            let alice_deposit_USDC: u64 = 10000;
             custodian::test_increase_user_available_balance(base_custodian, account_cap_user, alice_deposit_WSUI);
             custodian::test_increase_user_available_balance(quote_custodian, account_cap_user, alice_deposit_USDC);
             clob::test_inject_limit_order_with_expiration(
                 &mut pool,
                 CLIENT_ID_ALICE,
                 5 * FLOAT_SCALING,
-                5000,
-                5000,
+                500,
+                500,
                 false,
                 CANCEL_OLDEST,
                 TIMESTAMP_INF,
@@ -3725,8 +3578,8 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 2 * FLOAT_SCALING,
-                5000,
-                5000,
+                500,
+                500,
                 false,
                 CANCEL_OLDEST,
                 0,
@@ -3737,8 +3590,8 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 2 * FLOAT_SCALING,
-                10000,
-                10000,
+                1000,
+                1000,
                 false,
                 CANCEL_OLDEST,
                 TIMESTAMP_INF,
@@ -3749,8 +3602,8 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 1 * FLOAT_SCALING,
-                100000,
-                100000,
+                10000,
+                10000,
                 true,
                 CANCEL_OLDEST,
                 0,
@@ -3767,8 +3620,8 @@ module deepbook::clob_test {
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_custodian(&pool);
 
-            custodian::assert_user_balance(quote_custodian, account_cap_user, 0, 100000);
-            custodian::assert_user_balance(base_custodian, account_cap_user, 80000, 20000);
+            custodian::assert_user_balance(quote_custodian, account_cap_user, 0, 10000);
+            custodian::assert_user_balance(base_custodian, account_cap_user, 8000, 2000);
             let (next_bid_order_id, next_ask_order_id, _, _) = clob::get_pool_stat(&pool);
             assert!(next_bid_order_id == clob::order_id_for_test(1, true));
             assert!(next_ask_order_id == clob::order_id_for_test(3, false));
@@ -3781,8 +3634,8 @@ module deepbook::clob_test {
                         0,
                         CLIENT_ID_ALICE,
                         5 * FLOAT_SCALING,
-                        5000,
-                        5000,
+                        500,
+                        500,
                         false,
                         account_cap_user,
                         TIMESTAMP_INF
@@ -3796,7 +3649,7 @@ module deepbook::clob_test {
                 let mut open_orders = vector::empty();
                 vector::push_back(
                     &mut open_orders,
-                    clob::test_construct_order_with_expiration(1, CLIENT_ID_ALICE, 2 * FLOAT_SCALING, 5000, 5000, false, account_cap_user, 0)
+                    clob::test_construct_order_with_expiration(1, CLIENT_ID_ALICE, 2 * FLOAT_SCALING, 500, 500, false, account_cap_user, 0)
                 );
                 vector::push_back(
                     &mut open_orders,
@@ -3804,8 +3657,8 @@ module deepbook::clob_test {
                         2,
                         CLIENT_ID_ALICE,
                         2 * FLOAT_SCALING,
-                        10000,
-                        10000,
+                        1000,
+                        1000,
                         false,
                         account_cap_user,
                         TIMESTAMP_INF
@@ -3819,7 +3672,7 @@ module deepbook::clob_test {
                 let mut open_orders = vector::empty();
                 vector::push_back(
                     &mut open_orders,
-                    clob::test_construct_order(0, CLIENT_ID_ALICE, 1 * FLOAT_SCALING, 100000, 100000, true, account_cap_user)
+                    clob::test_construct_order(0, CLIENT_ID_ALICE, 1 * FLOAT_SCALING, 10000, 10000, true, account_cap_user)
                 );
                 let (_, _, bid, _) = get_pool_stat(&pool);
                 clob::check_tick_level(bid, 1 * FLOAT_SCALING, &open_orders);
@@ -3837,12 +3690,12 @@ module deepbook::clob_test {
                 &mut pool,
                 &account_cap,
                 CLIENT_ID_BOB,
-                45000,
+                4500,
                 MAX_PRICE,
                 1,
             );
-            assert!(base_quantity_filled == 10000 + 4000);
-            assert!(quote_quantity_filled == 40200);
+            assert!(base_quantity_filled == 1000 + 495);
+            assert!(quote_quantity_filled == 4498);
             test::return_shared(pool);
             test::return_to_address(bob, account_cap);
         };
@@ -3853,8 +3706,8 @@ module deepbook::clob_test {
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_custodian(&pool);
             // rebate fee in base asset 3
-            custodian::assert_user_balance(quote_custodian, account_cap_user, 40200 - 100 - 100 + 50 + 50, 100000);
-            custodian::assert_user_balance(base_custodian, account_cap_user, 85000, 1000);
+            custodian::assert_user_balance(quote_custodian, account_cap_user, 4498 - 10 - 13 + 5 + 6, 10000);
+            custodian::assert_user_balance(base_custodian, account_cap_user, 8500, 5);
             {
                 let (_, _, _, asks) = get_pool_stat(&pool);
                 clob::check_empty_tick_level(asks, 2 * FLOAT_SCALING);
@@ -3863,7 +3716,7 @@ module deepbook::clob_test {
                 let mut open_orders = vector::empty();
                 vector::push_back(
                     &mut open_orders,
-                    clob::test_construct_order(0, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 5000, 1000, false, account_cap_user)
+                    clob::test_construct_order(0, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 5, 5, false, account_cap_user)
                 );
                 let (_, _, _, asks) = get_pool_stat(&pool);
                 clob::check_tick_level(asks, 5 * FLOAT_SCALING, &open_orders);
@@ -3873,7 +3726,7 @@ module deepbook::clob_test {
                 let mut open_orders = vector::empty();
                 vector::push_back(
                     &mut open_orders,
-                    clob::test_construct_order(0, CLIENT_ID_ALICE, 1 * FLOAT_SCALING, 100000, 100000, true, account_cap_user)
+                    clob::test_construct_order(0, CLIENT_ID_ALICE, 1 * FLOAT_SCALING, 10000, 10000, true, account_cap_user)
                 );
                 let (_, _, bid, _) = get_pool_stat(&pool);
                 clob::check_tick_level(bid, 1 * FLOAT_SCALING, &open_orders);
@@ -5087,8 +4940,8 @@ module deepbook::clob_test {
             let account_cap = test::take_from_sender(&test);
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_mut_custodian(&mut pool);
-            custodian::deposit(base_custodian, mint_for_testing(10000, ctx(&mut test)), account_cap_user);
-            custodian::deposit(quote_custodian, mint_for_testing(100000, ctx(&mut test)), account_cap_user);
+            custodian::deposit(base_custodian, mint_for_testing(1000, ctx(&mut test)), account_cap_user);
+            custodian::deposit(quote_custodian, mint_for_testing(10000, ctx(&mut test)), account_cap_user);
             test::return_shared(pool);
             test::return_to_sender(&test, account_cap);
         };
@@ -5103,7 +4956,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 5 * FLOAT_SCALING,
-                2000,
+                200,
                 CANCEL_OLDEST,
                 true,
                 TIMESTAMP_INF,
@@ -5116,7 +4969,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 5 * FLOAT_SCALING,
-                3000,
+                300,
                 CANCEL_OLDEST,
                 true,
                 TIMESTAMP_INF,
@@ -5129,7 +4982,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 2 * FLOAT_SCALING,
-                10000,
+                1000,
                 CANCEL_OLDEST,
                 true,
                 TIMESTAMP_INF,
@@ -5142,7 +4995,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 20 * FLOAT_SCALING,
-                10000,
+                1000,
                 CANCEL_OLDEST,
                 false,
                 TIMESTAMP_INF,
@@ -5156,13 +5009,13 @@ module deepbook::clob_test {
             assert!(next_ask_order_id == clob::order_id_for_test(1, false));
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_custodian(&pool);
-            custodian::assert_user_balance(base_custodian, account_cap_user, 0, 10000);
-            custodian::assert_user_balance(quote_custodian, account_cap_user, 55000, 45000);
+            custodian::assert_user_balance(base_custodian, account_cap_user, 0, 1000);
+            custodian::assert_user_balance(quote_custodian, account_cap_user, 5500, 4500);
             let (base_avail, base_locked, quote_avail, quote_locked) = account_balance(&pool, &account_cap);
             assert!(base_avail == 0);
-            assert!(base_locked == 10000);
-            assert!(quote_avail == 55000);
-            assert!(quote_locked == 45000);
+            assert!(base_locked == 1000);
+            assert!(quote_avail == 5500);
+            assert!(quote_locked == 4500);
             test::return_shared(pool);
             test::return_shared(clock);
             test::return_to_address(alice, account_cap);
@@ -5174,21 +5027,21 @@ module deepbook::clob_test {
             let mut pool = test::take_shared>(&test);
             let clock = test::take_shared(&test);
             let account_cap = test::take_from_address(&test, alice);
-            let (coin1, coin2) =clob::place_market_order(&mut pool, &account_cap, CLIENT_ID_ALICE, 6000,
+            let (coin1, coin2) =clob::place_market_order(&mut pool, &account_cap, CLIENT_ID_ALICE, 600,
                 false,
-                mint_for_testing(6000, ctx(&mut test)),
+                mint_for_testing(600, ctx(&mut test)),
                 mint_for_testing(0, ctx(&mut test)),
                 &clock,
                 ctx(&mut test));
-            assert!(coin::value(&coin1) == 6000);
+            assert!(coin::value(&coin1) == 600);
             assert!(coin::value(&coin2) == 0);
             burn_for_testing(coin1);
             burn_for_testing(coin2);
 
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_custodian(&pool);
-            custodian::assert_user_balance(base_custodian, account_cap_user, 0, 10000);
-            custodian::assert_user_balance(quote_custodian, account_cap_user, 100000, 0);
+            custodian::assert_user_balance(base_custodian, account_cap_user, 0, 1000);
+            custodian::assert_user_balance(quote_custodian, account_cap_user, 10000, 0);
             test::return_shared(pool);
             test::return_shared(clock);
             test::return_to_address(alice, account_cap);
@@ -5220,8 +5073,8 @@ module deepbook::clob_test {
             let account_cap = test::take_from_sender(&test);
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_mut_custodian(&mut pool);
-            custodian::deposit(base_custodian, mint_for_testing(15000, ctx(&mut test)), account_cap_user);
-            custodian::deposit(quote_custodian, mint_for_testing(100000, ctx(&mut test)), account_cap_user);
+            custodian::deposit(base_custodian, mint_for_testing(1500, ctx(&mut test)), account_cap_user);
+            custodian::deposit(quote_custodian, mint_for_testing(10000, ctx(&mut test)), account_cap_user);
             test::return_shared(pool);
             test::return_to_sender(&test, account_cap);
         };
@@ -5236,7 +5089,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 5 * FLOAT_SCALING,
-                2000,
+                200,
                 CANCEL_OLDEST,
                 false,
                 TIMESTAMP_INF,
@@ -5249,7 +5102,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 5 * FLOAT_SCALING,
-                3000,
+                300,
                 CANCEL_OLDEST,
                 false,
                 TIMESTAMP_INF,
@@ -5262,7 +5115,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 2 * FLOAT_SCALING,
-                10000,
+                1000,
                 CANCEL_OLDEST,
                 false,
                 TIMESTAMP_INF,
@@ -5275,7 +5128,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 1 * FLOAT_SCALING,
-                10000,
+                1000,
                 CANCEL_OLDEST,
                 true,
                 TIMESTAMP_INF,
@@ -5289,13 +5142,13 @@ module deepbook::clob_test {
             assert!(next_ask_order_id == clob::order_id_for_test(3, false));
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_custodian(&pool);
-            custodian::assert_user_balance(base_custodian, account_cap_user, 0, 15000);
-            custodian::assert_user_balance(quote_custodian, account_cap_user, 90000, 10000);
+            custodian::assert_user_balance(base_custodian, account_cap_user, 0, 1500);
+            custodian::assert_user_balance(quote_custodian, account_cap_user, 9000, 1000);
             let (base_avail, base_locked, quote_avail, quote_locked) = account_balance(&pool, &account_cap);
             assert!(base_avail == 0);
-            assert!(base_locked == 15000);
-            assert!(quote_avail == 90000);
-            assert!(quote_locked == 10000);
+            assert!(base_locked == 1500);
+            assert!(quote_avail == 9000);
+            assert!(quote_locked == 1000);
             test::return_shared(pool);
             test::return_shared(clock);
             test::return_to_address(alice, account_cap);
@@ -5307,21 +5160,21 @@ module deepbook::clob_test {
             let mut pool = test::take_shared>(&test);
             let clock = test::take_shared(&test);
             let account_cap = test::take_from_address(&test, alice);
-            let (coin1, coin2) =clob::place_market_order(&mut pool, &account_cap, CLIENT_ID_ALICE, 1000,
+            let (coin1, coin2) =clob::place_market_order(&mut pool, &account_cap, CLIENT_ID_ALICE, 1,
                 true,
                 mint_for_testing(0, ctx(&mut test)),
-                mint_for_testing(1000, ctx(&mut test)),
+                mint_for_testing(1, ctx(&mut test)),
                 &clock,
                 ctx(&mut test));
             assert!(coin::value(&coin1) == 0);
-            assert!(coin::value(&coin2) == 1000);
+            assert!(coin::value(&coin2) == 1);
             burn_for_testing(coin1);
             burn_for_testing(coin2);
 
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_custodian(&pool);
-            custodian::assert_user_balance(base_custodian, account_cap_user, 15000, 0);
-            custodian::assert_user_balance(quote_custodian, account_cap_user, 90000, 10000);
+            custodian::assert_user_balance(base_custodian, account_cap_user, 1500, 0);
+            custodian::assert_user_balance(quote_custodian, account_cap_user, 9000, 1000);
             test::return_shared(pool);
             test::return_shared(clock);
             test::return_to_address(alice, account_cap);
@@ -5353,8 +5206,8 @@ module deepbook::clob_test {
             let account_cap = test::take_from_sender(&test);
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_mut_custodian(&mut pool);
-            custodian::deposit(base_custodian, mint_for_testing(10000, ctx(&mut test)), account_cap_user);
-            custodian::deposit(quote_custodian, mint_for_testing(100000, ctx(&mut test)), account_cap_user);
+            custodian::deposit(base_custodian, mint_for_testing(1000, ctx(&mut test)), account_cap_user);
+            custodian::deposit(quote_custodian, mint_for_testing(10000, ctx(&mut test)), account_cap_user);
             test::return_shared(pool);
             test::return_to_sender(&test, account_cap);
         };
@@ -5368,7 +5221,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 5 * FLOAT_SCALING,
-                2000,
+                200,
                 CANCEL_OLDEST,
                 true,
                 TIMESTAMP_INF,
@@ -5381,7 +5234,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 5 * FLOAT_SCALING,
-                3000,
+                300,
                 CANCEL_OLDEST,
                 true,
                 TIMESTAMP_INF,
@@ -5394,7 +5247,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 2 * FLOAT_SCALING,
-                10000,
+                1000,
                 CANCEL_OLDEST,
                 true,
                 TIMESTAMP_INF,
@@ -5407,7 +5260,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 20 * FLOAT_SCALING,
-                10000,
+                1000,
                 CANCEL_OLDEST,
                 false,
                 TIMESTAMP_INF,
@@ -5421,13 +5274,13 @@ module deepbook::clob_test {
             assert!(next_ask_order_id == clob::order_id_for_test(1, false));
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_custodian(&pool);
-            custodian::assert_user_balance(base_custodian, account_cap_user, 0, 10000);
-            custodian::assert_user_balance(quote_custodian, account_cap_user, 55000, 45000);
+            custodian::assert_user_balance(base_custodian, account_cap_user, 0, 1000);
+            custodian::assert_user_balance(quote_custodian, account_cap_user, 5500, 4500);
             let (base_avail, base_locked, quote_avail, quote_locked) = account_balance(&pool, &account_cap);
             assert!(base_avail == 0);
-            assert!(base_locked == 10000);
-            assert!(quote_avail == 55000);
-            assert!(quote_locked == 45000);
+            assert!(base_locked == 1000);
+            assert!(quote_avail == 5500);
+            assert!(quote_locked == 4500);
             test::return_shared(pool);
             test::return_shared(clock);
             test::return_to_address(alice, account_cap);
@@ -5438,7 +5291,7 @@ module deepbook::clob_test {
             let account_cap = test::take_from_sender(&test);
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, _) = clob::borrow_mut_custodian(&mut pool);
-            custodian::deposit(base_custodian, mint_for_testing(4000, ctx(&mut test)), account_cap_user);
+            custodian::deposit(base_custodian, mint_for_testing(400, ctx(&mut test)), account_cap_user);
             test::return_shared(pool);
             test::return_to_sender(&test, account_cap);
         };
@@ -5452,7 +5305,7 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 4 * FLOAT_SCALING,
-                4000,
+                400,
                 CANCEL_OLDEST,
                 false,
                 TIMESTAMP_INF,
@@ -5480,9 +5333,9 @@ module deepbook::clob_test {
 
             let  (base_avail, base_locked, quote_avail, quote_locked) = account_balance(&pool, &account_cap);
             assert!(base_avail == 0);
-            assert!(base_locked == 10000 + 4000);
-            assert!(quote_avail == 80000);
-            assert!(quote_locked == 20000);
+            assert!(base_locked == 1000 + 400);
+            assert!(quote_avail == 8000);
+            assert!(quote_locked == 2000);
 
             test::return_shared(pool);
             test::return_shared(clock);
@@ -5511,17 +5364,17 @@ module deepbook::clob_test {
             let account_cap = test::take_from_address(&test, alice);
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_mut_custodian(&mut pool);
-            let alice_deposit_WSUI: u64 = 100000;
-            let alice_deposit_USDC: u64 = 100000;
+            let alice_deposit_WSUI: u64 = 10000;
+            let alice_deposit_USDC: u64 = 10000;
             custodian::test_increase_user_available_balance(base_custodian, account_cap_user, alice_deposit_WSUI);
             custodian::test_increase_user_available_balance(quote_custodian, account_cap_user, alice_deposit_USDC);
-            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 5000, 5000, false,
+            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 500, 500, false,
                 CANCEL_OLDEST, &account_cap, ctx(&mut test));
-            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 5000, 5000, false,
+            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 500, 500, false,
                 CANCEL_OLDEST, &account_cap, ctx(&mut test));
-            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 2 * FLOAT_SCALING, 10000, 10000, false,
+            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 2 * FLOAT_SCALING, 1000, 1000, false,
                 CANCEL_OLDEST, &account_cap, ctx(&mut test));
-            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE,1 * FLOAT_SCALING, 100000, 100000, true,
+            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE,1 * FLOAT_SCALING, 10000, 10000, true,
                 CANCEL_OLDEST, &account_cap, ctx(&mut test));
             test::return_shared(pool);
             test::return_to_address(alice, account_cap);
@@ -5536,20 +5389,20 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 &account_cap,
-                45000,
+                4500,
                 &clock,
-                mint_for_testing(45000, ctx(&mut test)),
+                mint_for_testing(4500, ctx(&mut test)),
                 ctx(&mut test)
             );
             assert!(coin::value(&base_coin) == 0);
-            assert!(coin::value("e_coin) == 45000);
+            assert!(coin::value("e_coin) == 4500);
             burn_for_testing(base_coin);
             burn_for_testing(quote_coin);
 
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_custodian(&pool);
-            custodian::assert_user_balance(base_custodian, account_cap_user, 100000, 0);
-            custodian::assert_user_balance(quote_custodian, account_cap_user, 0, 100000);
+            custodian::assert_user_balance(base_custodian, account_cap_user, 10000, 0);
+            custodian::assert_user_balance(quote_custodian, account_cap_user, 0, 10000);
 
             test::return_shared(clock);
             test::return_shared(pool);
@@ -6095,11 +5948,11 @@ module deepbook::clob_test {
             let account_cap = test::take_from_address(&test, alice);
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_mut_custodian(&mut pool);
-            let alice_deposit_WSUI: u64 = 100000;
-            let alice_deposit_USDC: u64 = 100000;
+            let alice_deposit_WSUI: u64 = 10000;
+            let alice_deposit_USDC: u64 = 10000;
             custodian::test_increase_user_available_balance(base_custodian, account_cap_user, alice_deposit_WSUI);
             custodian::test_increase_user_available_balance(quote_custodian, account_cap_user, alice_deposit_USDC);
-            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 50000, 50000, false,
+            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 500, 500, false,
                 CANCEL_OLDEST, &account_cap, ctx(&mut test));
             test::return_shared(pool);
             test::return_to_address(alice, account_cap);
@@ -6114,16 +5967,16 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_BOB,
                 &account_cap,
-                50000,
+                5000,
                 &clock,
-                mint_for_testing(50000, ctx(&mut test)),
+                mint_for_testing(5000, ctx(&mut test)),
                 ctx(&mut test)
             );
 
             let of_event = vector::borrow(&of_events, 0);
             let (_, _, is_bid, _, _, base_asset_quantity_filled, price, _ , _) = clob::matched_order_metadata_info(of_event);
             assert!(is_bid == false);
-            assert!(base_asset_quantity_filled == 9000);
+            assert!(base_asset_quantity_filled == 500);
             assert!(price == 5 * FLOAT_SCALING);
 
             burn_for_testing(base_coin);
@@ -6157,11 +6010,11 @@ module deepbook::clob_test {
             let account_cap = test::take_from_address(&test, alice);
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_mut_custodian(&mut pool);
-            let alice_deposit_WSUI: u64 = 100000;
-            let alice_deposit_USDC: u64 = 100000;
+            let alice_deposit_WSUI: u64 = 10000;
+            let alice_deposit_USDC: u64 = 10000;
             custodian::test_increase_user_available_balance(base_custodian, account_cap_user, alice_deposit_WSUI);
             custodian::test_increase_user_available_balance(quote_custodian, account_cap_user, alice_deposit_USDC);
-            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 5000, 5000, true,
+            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 500, 500, true,
                 CANCEL_OLDEST, &account_cap, ctx(&mut test));
             test::return_shared(pool);
             test::return_to_address(alice, account_cap);
@@ -6176,8 +6029,8 @@ module deepbook::clob_test {
                 &mut pool,
                 CLIENT_ID_BOB,
                 &account_cap,
-                5000,
-                mint_for_testing(5000, ctx(&mut test)),
+                500,
+                mint_for_testing(500, ctx(&mut test)),
                 mint_for_testing(0, ctx(&mut test)),
                 &clock,
                 ctx(&mut test)
@@ -6186,7 +6039,7 @@ module deepbook::clob_test {
             let of_event = vector::borrow(&of_events, 0);
             let (_, _, is_bid, _, _, base_asset_quantity_filled, price, _ , _) = clob::matched_order_metadata_info(of_event);
             assert!(is_bid == true);
-            assert!(base_asset_quantity_filled == 5000);
+            assert!(base_asset_quantity_filled == 500);
             assert!(price == 5 * FLOAT_SCALING);
 
             burn_for_testing(base_coin);
@@ -6220,11 +6073,11 @@ module deepbook::clob_test {
             let account_cap = test::take_from_address(&test, alice);
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_mut_custodian(&mut pool);
-            let alice_deposit_WSUI: u64 = 100000;
-            let alice_deposit_USDC: u64 = 100000;
+            let alice_deposit_WSUI: u64 = 10000;
+            let alice_deposit_USDC: u64 = 10000;
             custodian::test_increase_user_available_balance(base_custodian, account_cap_user, alice_deposit_WSUI);
             custodian::test_increase_user_available_balance(quote_custodian, account_cap_user, alice_deposit_USDC);
-            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 5000, 5000, true,
+            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 500, 500, true,
                 CANCEL_OLDEST, &account_cap, ctx(&mut test));
             test::return_shared(pool);
             test::return_to_address(alice, account_cap);
@@ -6239,9 +6092,9 @@ module deepbook::clob_test {
                 &mut pool,
                 &account_cap,
                 CLIENT_ID_BOB,
-                5000,
+                500,
                 false,
-                mint_for_testing(5000, ctx(&mut test)),
+                mint_for_testing(500, ctx(&mut test)),
                 mint_for_testing(0, ctx(&mut test)),
                 &clock,
                 ctx(&mut test)
@@ -6250,7 +6103,7 @@ module deepbook::clob_test {
             let of_event = vector::borrow(&of_events, 0);
             let (_, _, is_bid, _, _, base_asset_quantity_filled, price, _ , _) = clob::matched_order_metadata_info(of_event);
             assert!(is_bid == true);
-            assert!(base_asset_quantity_filled == 5000);
+            assert!(base_asset_quantity_filled == 500);
             assert!(price == 5 * FLOAT_SCALING);
 
             burn_for_testing(base_coin);
@@ -6284,11 +6137,11 @@ module deepbook::clob_test {
             let account_cap = test::take_from_address(&test, alice);
             let account_cap_user = account_owner(&account_cap);
             let (base_custodian, quote_custodian) = clob::borrow_mut_custodian(&mut pool);
-            let alice_deposit_WSUI: u64 = 100000;
-            let alice_deposit_USDC: u64 = 100000;
+            let alice_deposit_WSUI: u64 = 10000;
+            let alice_deposit_USDC: u64 = 10000;
             custodian::test_increase_user_available_balance(base_custodian, account_cap_user, alice_deposit_WSUI);
             custodian::test_increase_user_available_balance(quote_custodian, account_cap_user, alice_deposit_USDC);
-            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 5000, 5000, true,
+            clob::test_inject_limit_order(&mut pool, CLIENT_ID_ALICE, 5 * FLOAT_SCALING, 500, 500, true,
                 CANCEL_OLDEST, &account_cap, ctx(&mut test));
             test::return_shared(pool);
             test::return_to_address(alice, account_cap);
@@ -6299,14 +6152,14 @@ module deepbook::clob_test {
             let mut pool = test::take_shared>(&test);
             let clock = test::take_shared(&test);
             let account_cap = test::take_from_address(&test, bob);
-            let bob_deposit_WSUI: u64 = 100000;
+            let bob_deposit_WSUI: u64 = 10000;
             let (base_custodian, _) = clob::borrow_mut_custodian(&mut pool);
             custodian::test_increase_user_available_balance(base_custodian, account_owner(&account_cap), bob_deposit_WSUI);
             let (_, _, _, _, of_events) = clob::place_limit_order_with_metadata(
                 &mut pool,
                 CLIENT_ID_BOB,
                 5 * FLOAT_SCALING,
-                5000,
+                500,
                 CANCEL_OLDEST,
                 false,
                 TIMESTAMP_INF,
@@ -6319,7 +6172,7 @@ module deepbook::clob_test {
             let of_event = vector::borrow(&of_events, 0);
             let (_, _, is_bid, _, _, base_asset_quantity_filled, price, _ , _) = clob::matched_order_metadata_info(of_event);
             assert!(is_bid == true);
-            assert!(base_asset_quantity_filled == 5000);
+            assert!(base_asset_quantity_filled == 500);
             assert!(price == 5 * FLOAT_SCALING);
 
             test::return_shared(clock);
diff --git a/crates/sui-framework/packages/deepbook/tests/order_query_tests.move b/crates/sui-framework/packages/deepbook/tests/order_query_tests.move
index bb0adc6d3067e..e280b2708684e 100644
--- a/crates/sui-framework/packages/deepbook/tests/order_query_tests.move
+++ b/crates/sui-framework/packages/deepbook/tests/order_query_tests.move
@@ -306,10 +306,10 @@ module deepbook::order_query_tests {
         let account_cap = test_scenario::take_from_sender(&scenario);
         let account_cap_user = account_owner(&account_cap);
         let (base_custodian, quote_custodian) = clob_v2::borrow_mut_custodian(&mut pool);
-        custodian_v2::deposit(base_custodian, mint_for_testing(10000000, ctx(&mut scenario)), account_cap_user);
+        custodian_v2::deposit(base_custodian, mint_for_testing(1000000, ctx(&mut scenario)), account_cap_user);
         custodian_v2::deposit(
             quote_custodian,
-            mint_for_testing(100000000, ctx(&mut scenario)),
+            mint_for_testing(10000000, ctx(&mut scenario)),
             account_cap_user
         );
         test_scenario::return_shared(pool);
@@ -334,7 +334,7 @@ module deepbook::order_query_tests {
                 &mut pool,
                 CLIENT_ID_ALICE,
                 price,
-                2000,
+                200,
                 CANCEL_OLDEST,
                 true,
                 timestamp,
diff --git a/crates/sui-graphql-e2e-tests/tests/objects/enum_data.exp b/crates/sui-graphql-e2e-tests/tests/objects/enum_data.exp
index ff5945a544e22..11db5c57d3e05 100644
--- a/crates/sui-graphql-e2e-tests/tests/objects/enum_data.exp
+++ b/crates/sui-graphql-e2e-tests/tests/objects/enum_data.exp
@@ -30,7 +30,7 @@ Response: {
                     "asMoveObject": {
                       "contents": {
                         "type": {
-                          "repr": "0x0000000000000000000000000000000000000000000000000000000000000002::coin::Coin<0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI>"
+                          "repr": "0x2b27451fe08307117ecc1d172f7bb24b81bfdb774592d8d11ba196a76edaddd6::m::Foo"
                         },
                         "data": {
                           "Struct": [
@@ -38,111 +38,38 @@ Response: {
                               "name": "id",
                               "value": {
                                 "UID": [
-                                  26,
-                                  81,
-                                  115,
-                                  93,
-                                  169,
-                                  35,
-                                  41,
-                                  133,
-                                  14,
-                                  27,
-                                  79,
-                                  142,
+                                  56,
+                                  223,
+                                  62,
+                                  4,
+                                  221,
+                                  43,
                                   163,
-                                  22,
-                                  195,
-                                  52,
-                                  250,
-                                  101,
-                                  183,
-                                  195,
-                                  178,
-                                  66,
-                                  100,
-                                  67,
-                                  178,
-                                  248,
-                                  49,
-                                  160,
-                                  240,
-                                  34,
-                                  83,
-                                  232
-                                ]
-                              }
-                            },
-                            {
-                              "name": "balance",
-                              "value": {
-                                "Struct": [
-                                  {
-                                    "name": "value",
-                                    "value": {
-                                      "Number": "299999995967600"
-                                    }
-                                  }
-                                ]
-                              }
-                            }
-                          ]
-                        },
-                        "json": {
-                          "id": "0x1a51735da92329850e1b4f8ea316c334fa65b7c3b2426443b2f831a0f02253e8",
-                          "balance": {
-                            "value": "299999995967600"
-                          }
-                        }
-                      }
-                    }
-                  }
-                },
-                {
-                  "outputState": {
-                    "asMoveObject": {
-                      "contents": {
-                        "type": {
-                          "repr": "0x72e81da69722659259d5c5f16bbc054e22b79cbac6d37ee5e5cb2daee5c8fb09::m::Foo"
-                        },
-                        "data": {
-                          "Struct": [
-                            {
-                              "name": "id",
-                              "value": {
-                                "UID": [
-                                  157,
-                                  173,
-                                  112,
-                                  54,
-                                  108,
-                                  35,
-                                  60,
-                                  245,
+                                  179,
+                                  9,
+                                  17,
                                   185,
-                                  230,
-                                  102,
-                                  44,
                                   146,
-                                  218,
-                                  239,
-                                  145,
-                                  206,
-                                  199,
+                                  193,
+                                  146,
                                   56,
-                                  163,
-                                  234,
-                                  212,
-                                  215,
-                                  238,
-                                  138,
-                                  204,
-                                  11,
-                                  227,
-                                  124,
-                                  231,
-                                  239,
-                                  231
+                                  28,
+                                  179,
+                                  90,
+                                  243,
+                                  178,
+                                  100,
+                                  107,
+                                  65,
+                                  162,
+                                  152,
+                                  189,
+                                  57,
+                                  216,
+                                  209,
+                                  61,
+                                  42,
+                                  215
                                 ]
                               }
                             },
@@ -150,38 +77,38 @@ Response: {
                               "name": "f0",
                               "value": {
                                 "ID": [
-                                  157,
-                                  173,
-                                  112,
-                                  54,
-                                  108,
-                                  35,
-                                  60,
-                                  245,
+                                  56,
+                                  223,
+                                  62,
+                                  4,
+                                  221,
+                                  43,
+                                  163,
+                                  179,
+                                  9,
+                                  17,
                                   185,
-                                  230,
-                                  102,
-                                  44,
                                   146,
-                                  218,
-                                  239,
-                                  145,
-                                  206,
-                                  199,
+                                  193,
+                                  146,
                                   56,
-                                  163,
-                                  234,
-                                  212,
-                                  215,
-                                  238,
-                                  138,
-                                  204,
-                                  11,
-                                  227,
-                                  124,
-                                  231,
-                                  239,
-                                  231
+                                  28,
+                                  179,
+                                  90,
+                                  243,
+                                  178,
+                                  100,
+                                  107,
+                                  65,
+                                  162,
+                                  152,
+                                  189,
+                                  57,
+                                  216,
+                                  209,
+                                  61,
+                                  42,
+                                  215
                                 ]
                               }
                             },
@@ -221,38 +148,38 @@ Response: {
                                 "Vector": [
                                   {
                                     "Address": [
-                                      157,
-                                      173,
-                                      112,
-                                      54,
-                                      108,
-                                      35,
-                                      60,
-                                      245,
+                                      56,
+                                      223,
+                                      62,
+                                      4,
+                                      221,
+                                      43,
+                                      163,
+                                      179,
+                                      9,
+                                      17,
                                       185,
-                                      230,
-                                      102,
-                                      44,
                                       146,
-                                      218,
-                                      239,
-                                      145,
-                                      206,
-                                      199,
+                                      193,
+                                      146,
                                       56,
-                                      163,
-                                      234,
-                                      212,
-                                      215,
-                                      238,
-                                      138,
-                                      204,
-                                      11,
-                                      227,
-                                      124,
-                                      231,
-                                      239,
-                                      231
+                                      28,
+                                      179,
+                                      90,
+                                      243,
+                                      178,
+                                      100,
+                                      107,
+                                      65,
+                                      162,
+                                      152,
+                                      189,
+                                      57,
+                                      216,
+                                      209,
+                                      61,
+                                      42,
+                                      215
                                     ]
                                   }
                                 ]
@@ -319,15 +246,15 @@ Response: {
                           ]
                         },
                         "json": {
-                          "id": "0x9dad70366c233cf5b9e6662c92daef91cec738a3ead4d7ee8acc0be37ce7efe7",
-                          "f0": "0x9dad70366c233cf5b9e6662c92daef91cec738a3ead4d7ee8acc0be37ce7efe7",
+                          "id": "0x38df3e04dd2ba3b30911b992c192381cb35af3b2646b41a298bd39d8d13d2ad7",
+                          "f0": "0x38df3e04dd2ba3b30911b992c192381cb35af3b2646b41a298bd39d8d13d2ad7",
                           "f1": true,
                           "f2": 42,
                           "f3": "43",
                           "f4": "hello",
                           "f5": "world",
                           "f6": [
-                            "0x9dad70366c233cf5b9e6662c92daef91cec738a3ead4d7ee8acc0be37ce7efe7"
+                            "0x38df3e04dd2ba3b30911b992c192381cb35af3b2646b41a298bd39d8d13d2ad7"
                           ],
                           "f7": 44,
                           "f8": {
@@ -350,6 +277,79 @@ Response: {
                       }
                     }
                   }
+                },
+                {
+                  "outputState": {
+                    "asMoveObject": {
+                      "contents": {
+                        "type": {
+                          "repr": "0x0000000000000000000000000000000000000000000000000000000000000002::coin::Coin<0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI>"
+                        },
+                        "data": {
+                          "Struct": [
+                            {
+                              "name": "id",
+                              "value": {
+                                "UID": [
+                                  74,
+                                  63,
+                                  69,
+                                  149,
+                                  223,
+                                  0,
+                                  225,
+                                  254,
+                                  133,
+                                  114,
+                                  233,
+                                  29,
+                                  11,
+                                  223,
+                                  12,
+                                  229,
+                                  83,
+                                  83,
+                                  236,
+                                  108,
+                                  28,
+                                  82,
+                                  187,
+                                  116,
+                                  23,
+                                  108,
+                                  228,
+                                  45,
+                                  4,
+                                  45,
+                                  150,
+                                  20
+                                ]
+                              }
+                            },
+                            {
+                              "name": "balance",
+                              "value": {
+                                "Struct": [
+                                  {
+                                    "name": "value",
+                                    "value": {
+                                      "Number": "299999995967600"
+                                    }
+                                  }
+                                ]
+                              }
+                            }
+                          ]
+                        },
+                        "json": {
+                          "id": "0x4a3f4595df00e1fe8572e91d0bdf0ce55353ec6c1c52bb74176ce42d042d9614",
+                          "balance": {
+                            "value": "299999995967600"
+                          }
+                        }
+                      }
+                    }
+                  }
                 }
               ]
             }
diff --git a/crates/sui-graphql-e2e-tests/tests/packages/datatypes.exp b/crates/sui-graphql-e2e-tests/tests/packages/datatypes.exp
index 56ab8833f4c41..e022382e6ee45 100644
--- a/crates/sui-graphql-e2e-tests/tests/packages/datatypes.exp
+++ b/crates/sui-graphql-e2e-tests/tests/packages/datatypes.exp
@@ -150,7 +150,7 @@ task 5 'run-graphql'. lines 72-96:
 Response: {
   "data": {
     "object": {
-      "address": "0x01b935b13fa784b3a048ac895a13e13335bc6d3717fba0401c70767d17e1ade0",
+      "address": "0x4ad90f4ed98d545600c66a80334410db765366c41e8e716766bd72822a77500d",
       "asMovePackage": {
         "module": {
           "datatypes": {
@@ -184,7 +184,7 @@ task 6 'run-graphql'. lines 98-143:
 Response: {
   "data": {
     "object": {
-      "address": "0x01b935b13fa784b3a048ac895a13e13335bc6d3717fba0401c70767d17e1ade0",
+      "address": "0x4ad90f4ed98d545600c66a80334410db765366c41e8e716766bd72822a77500d",
       "asMovePackage": {
         "module": {
           "datatypes": {
diff --git a/crates/sui-graphql-e2e-tests/tests/packages/enums.exp b/crates/sui-graphql-e2e-tests/tests/packages/enums.exp
index a89aa01e61f85..b7d17815e3731 100644
--- a/crates/sui-graphql-e2e-tests/tests/packages/enums.exp
+++ b/crates/sui-graphql-e2e-tests/tests/packages/enums.exp
@@ -22,7 +22,19 @@ Response: {
               "nodes": [
                 {
                   "outputState": {
-                    "address": "0x112d4659bb80e2ded2e45dfdbf4f854369fb693de67ca32850b7e11fc00d3ce6",
+                    "address": "0x53b63659f4910b0563575a85dca3254f1eb41bd6f8235cf2508ee6c18f4293ab",
+                    "asMovePackage": null
+                  }
+                },
+                {
+                  "outputState": {
+                    "address": "0xcfe25a7e8b161ad78e604ecadb0e36787e46626bd2f8456ef76327771e685e6a",
+                    "asMovePackage": null
+                  }
+                },
+                {
+                  "outputState": {
+                    "address": "0xe1b0f83fd53dd4e358f7fd0d7a54eca9ad604dd7dc7ff46ef35a4dd69917bebd",
                     "asMovePackage": {
                       "module": {
                         "enum": {
@@ -78,18 +90,6 @@ Response: {
                       }
                     }
                   }
-                },
-                {
-                  "outputState": {
-                    "address": "0x3561764b908eb3006b0e693986992e0016784a4a1a1e2db7369ce2c91a13d45f",
-                    "asMovePackage": null
-                  }
-                },
-                {
-                  "outputState": {
-                    "address": "0xe03c0451ba8cef4f2264641b8727be33acb49e6b31b46583bd44e1c56a385cc3",
-                    "asMovePackage": null
-                  }
                 }
               ]
             }
@@ -119,19 +119,25 @@ Response: {
               "nodes": [
                 {
                   "outputState": {
-                    "address": "0x3561764b908eb3006b0e693986992e0016784a4a1a1e2db7369ce2c91a13d45f",
+                    "address": "0x53b63659f4910b0563575a85dca3254f1eb41bd6f8235cf2508ee6c18f4293ab",
                     "asMovePackage": null
                   }
                 },
                 {
                   "outputState": {
-                    "address": "0x7a22e858ed54197e5216c32eb6ffe7987930248811b87dcddf4af08fcd272b5b",
+                    "address": "0xcfe25a7e8b161ad78e604ecadb0e36787e46626bd2f8456ef76327771e685e6a",
+                    "asMovePackage": null
+                  }
+                },
+                {
+                  "outputState": {
+                    "address": "0xfbcdbd13ea73e8f64987b7f222043422842ccb47cee8bac7d6eeea1274954abf",
                     "asMovePackage": {
                       "module": {
                         "s": {
                           "module": {
                             "package": {
-                              "address": "0x112d4659bb80e2ded2e45dfdbf4f854369fb693de67ca32850b7e11fc00d3ce6"
+                              "address": "0xe1b0f83fd53dd4e358f7fd0d7a54eca9ad604dd7dc7ff46ef35a4dd69917bebd"
                             }
                           },
                           "name": "S",
@@ -186,7 +192,7 @@ Response: {
                         "t": {
                           "module": {
                             "package": {
-                              "address": "0x7a22e858ed54197e5216c32eb6ffe7987930248811b87dcddf4af08fcd272b5b"
+                              "address": "0xfbcdbd13ea73e8f64987b7f222043422842ccb47cee8bac7d6eeea1274954abf"
                             }
                           },
                           "name": "T",
@@ -216,12 +222,12 @@ Response: {
                                 {
                                   "name": "s",
                                   "type": {
-                                    "repr": "0x112d4659bb80e2ded2e45dfdbf4f854369fb693de67ca32850b7e11fc00d3ce6::m::S",
+                                    "repr": "0xe1b0f83fd53dd4e358f7fd0d7a54eca9ad604dd7dc7ff46ef35a4dd69917bebd::m::S",
                                     "signature": {
                                       "ref": null,
                                       "body": {
                                         "datatype": {
-                                          "package": "0x112d4659bb80e2ded2e45dfdbf4f854369fb693de67ca32850b7e11fc00d3ce6",
+                                          "package": "0xe1b0f83fd53dd4e358f7fd0d7a54eca9ad604dd7dc7ff46ef35a4dd69917bebd",
                                           "module": "m",
                                           "type": "S",
                                           "typeParameters": []
@@ -255,7 +261,7 @@ Response: {
                                 {
                                   "name": "t",
                                   "type": {
-                                    "repr": "0x112d4659bb80e2ded2e45dfdbf4f854369fb693de67ca32850b7e11fc00d3ce6::m::T<0x112d4659bb80e2ded2e45dfdbf4f854369fb693de67ca32850b7e11fc00d3ce6::m::S>"
+                                    "repr": "0xe1b0f83fd53dd4e358f7fd0d7a54eca9ad604dd7dc7ff46ef35a4dd69917bebd::m::T<0xe1b0f83fd53dd4e358f7fd0d7a54eca9ad604dd7dc7ff46ef35a4dd69917bebd::m::S>"
                                   }
                                 }
                               ]
@@ -265,12 +271,6 @@ Response: {
                       }
                     }
                   }
-                },
-                {
-                  "outputState": {
-                    "address": "0xe03c0451ba8cef4f2264641b8727be33acb49e6b31b46583bd44e1c56a385cc3",
-                    "asMovePackage": null
-                  }
                 }
               ]
             }
@@ -295,6 +295,11 @@ Response: {
                     "asMovePackage": null
                   }
                 },
+                {
+                  "outputState": {
+                    "asMovePackage": null
+                  }
+                },
                 {
                   "outputState": {
                     "asMovePackage": {
@@ -314,11 +319,6 @@ Response: {
                       }
                     }
                   }
-                },
-                {
-                  "outputState": {
-                    "asMovePackage": null
-                  }
                 }
               ]
             }
diff --git a/crates/sui-swarm-config/tests/snapshots/snapshot_tests__populated_genesis_snapshot_matches-2.snap b/crates/sui-swarm-config/tests/snapshots/snapshot_tests__populated_genesis_snapshot_matches-2.snap
index ff24328f46a0e..9f83ffa863588 100644
--- a/crates/sui-swarm-config/tests/snapshots/snapshot_tests__populated_genesis_snapshot_matches-2.snap
+++ b/crates/sui-swarm-config/tests/snapshots/snapshot_tests__populated_genesis_snapshot_matches-2.snap
@@ -240,13 +240,13 @@ validators:
         next_epoch_worker_address: ~
         extra_fields:
           id:
-            id: "0x8279da17522014cd461ed69bb70863cbb230273a636a44b89e78147a91d19bdb"
+            id: "0xb0c661436faacc2576f8e52ed34f47d8b83e7fadd493307bc0208a0b75ff3d31"
           size: 0
       voting_power: 10000
-      operation_cap_id: "0x895df73349784ee3f4699659f334b1d8512b47201c840f5a13e1e9e5cbf933ee"
+      operation_cap_id: "0xaed58e45bcdb3a5a767a5e185a42712118ea000432e1596c4d089ae25bea9fa1"
       gas_price: 1000
       staking_pool:
-        id: "0xe398b0b4a968005db18b9dfa9900904d974e27d8eeece9ff42d17b616d6d66a6"
+        id: "0xd65fc099b2677baad81f5293db8fce1d3ab4f36bcec5180ea5fbcac9527314c1"
         activation_epoch: 0
         deactivation_epoch: ~
         sui_balance: 20000000000000000
@@ -254,14 +254,14 @@ validators:
           value: 0
         pool_token_balance: 20000000000000000
         exchange_rates:
-          id: "0x8bdccf4bd70329feb452371dd895730ee292e47762cb69f737f5979e78a5ca03"
+          id: "0x02a133ee415297e148857207d37cc1a3dd8d16fd5ed5d6e27d90b0af45f4034c"
           size: 1
         pending_stake: 0
         pending_total_sui_withdraw: 0
         pending_pool_token_withdraw: 0
         extra_fields:
           id:
-            id: "0x9fe706f15d8e496b71ad15115744d4843aef463a93301ccb729123e5174449e3"
+            id: "0x5e19f1996afaeb561a904cede5c9733e08fbcf4969430e55602ca1341046c6a6"
           size: 0
       commission_rate: 200
       next_epoch_stake: 20000000000000000
@@ -269,27 +269,27 @@ validators:
       next_epoch_commission_rate: 200
       extra_fields:
         id:
-          id: "0x786b66e3bda515d9a277b324ec937f8733484477cf473a0dcceafc05a5347663"
+          id: "0xa9885026f915def336ce0a470aa4d8faf77e8fcc44e3160480f65aae237e6712"
         size: 0
   pending_active_validators:
     contents:
-      id: "0x6debc7aead82b4ba0bf5c6a78dea0fc11e83a87ff78f1b3874e93277435ebf29"
+      id: "0xc4a8b7fc920b5a796b6f2d4f6893d2066aaf6fe1eb8ec0111f95e7783dde1562"
       size: 0
   pending_removals: []
   staking_pool_mappings:
-    id: "0x4d59858c49c2a491aaefe5b4c381eeeab1b0d7552f63454c519e44d3d2fc3d2c"
+    id: "0xe12bfe23f7b641d8d33861c4f267928ffafb913f2cee399a0942e4465ac8499c"
     size: 1
   inactive_validators:
-    id: "0x608ed71119388fae8c8adcf8028544db909b60490aba7f3404b4aded0e3600e6"
+    id: "0xa2cbdf8b4e759c5d4585c16b0db4053a21cbb839452eb8c0f8e68f5790412d48"
     size: 0
   validator_candidates:
-    id: "0xfb614f9979e5a3cb8aae57615e5ed6f426ac4504fd67a4e11bcdf0e25f7aeede"
+    id: "0xb5437e5d6602194c31fb8be2507f6703cffefde03c8c5bb6a53845b23978ea57"
     size: 0
   at_risk_validators:
     contents: []
   extra_fields:
     id:
-      id: "0xeefe3fa37466888a55530f5ebcace867c459c82c702987657c3e97fbfdd1eb38"
+      id: "0xbf6350f26cfb2d3b9e5e34cfdd64b524a17475447e290e6dff3bdc2ebac11940"
     size: 0
 storage_fund:
   total_object_storage_rebates:
@@ -306,7 +306,7 @@ parameters:
   validator_low_stake_grace_period: 7
   extra_fields:
     id:
-      id: "0xb075362d7b743eeac2c5d32e46e03831c15772fd845e45756d5bb59628324b41"
+      id: "0x4c4a6bd6b6bf6fe19956b0bde2bda6eaec022d1dcecaa14ea2b7e0b9b43e7838"
     size: 0
 reference_gas_price: 1000
 validator_report_records:
@@ -320,7 +320,7 @@ stake_subsidy:
   stake_subsidy_decrease_rate: 1000
   extra_fields:
     id:
-      id: "0x92cebae487984d960a85b00403c3d0c1baa9f6e204c8ba3ed3856b03368354c7"
+      id: "0x009afa088a20521b05b55a115e0f5cac473bacfec65423f58e74574ed1d85741"
     size: 0
 safe_mode: false
 safe_mode_storage_rewards:
@@ -332,6 +332,6 @@ safe_mode_non_refundable_storage_fee: 0
 epoch_start_timestamp_ms: 10
 extra_fields:
   id:
-    id: "0xfbdaf248b5324a169d89eb88583f02cc3b12077f6bd90fa7ec1558858fb017ca"
+    id: "0x5cb39a638bbeaf07dccf4c9b3acd27f4c3e83eacc49aa05d92307b3d82bea119"
   size: 0
 

From 04e120dc43a6f6cfde040b4e0fa0553d6a1310af Mon Sep 17 00:00:00 2001
From: Zhe Wu 
Date: Sun, 26 May 2024 12:01:34 -0700
Subject: [PATCH 003/324] Track cancelled transaction count (#17910)

## Description

Adding a metric to track cancelled txn count.

## Test plan

How did you test the new or updated feature?

---

## Release notes

Check each box that your changes affect. If none of the boxes relate to
your changes, release notes aren't required.

For each box you select, include information after the relevant heading
that describes the impact of your changes that a user might notice and
any actions they must take to implement updates.

- [ ] Protocol:
- [ ] Nodes (Validators and Full nodes):
- [ ] Indexer:
- [ ] JSON-RPC:
- [ ] GraphQL:
- [ ] CLI:
- [ ] Rust SDK:
---
 crates/sui-core/src/authority.rs                           | 6 ++++++
 crates/sui-core/src/authority/authority_per_epoch_store.rs | 3 +++
 2 files changed, 9 insertions(+)

diff --git a/crates/sui-core/src/authority.rs b/crates/sui-core/src/authority.rs
index 8ff3c85e01958..27a487921522d 100644
--- a/crates/sui-core/src/authority.rs
+++ b/crates/sui-core/src/authority.rs
@@ -271,6 +271,7 @@ pub struct AuthorityMetrics {
     pub consensus_handler_scores: IntGaugeVec,
     pub consensus_handler_deferred_transactions: IntCounter,
     pub consensus_handler_congested_transactions: IntCounter,
+    pub consensus_handler_cancelled_transactions: IntCounter,
     pub consensus_committed_subdags: IntCounterVec,
     pub consensus_committed_messages: IntGaugeVec,
     pub consensus_committed_user_transactions: IntGaugeVec,
@@ -664,6 +665,11 @@ impl AuthorityMetrics {
                 "Number of transactions deferred by consensus handler due to congestion",
                 registry,
             ).unwrap(),
+            consensus_handler_cancelled_transactions: register_int_counter_with_registry!(
+                "consensus_handler_cancelled_transactions",
+                "Number of transactions cancelled by consensus handler",
+                registry,
+            ).unwrap(),
             consensus_committed_subdags: register_int_counter_vec_with_registry!(
                 "consensus_committed_subdags",
                 "Number of committed subdags, sliced by author",
diff --git a/crates/sui-core/src/authority/authority_per_epoch_store.rs b/crates/sui-core/src/authority/authority_per_epoch_store.rs
index d63ff17bfdffe..db53337e24947 100644
--- a/crates/sui-core/src/authority/authority_per_epoch_store.rs
+++ b/crates/sui-core/src/authority/authority_per_epoch_store.rs
@@ -2925,6 +2925,9 @@ impl AuthorityPerEpochStore {
         authority_metrics
             .consensus_handler_deferred_transactions
             .inc_by(total_deferred_txns as u64);
+        authority_metrics
+            .consensus_handler_cancelled_transactions
+            .inc_by(cancelled_txns.len() as u64);
 
         if randomness_state_updated {
             if let Some(randomness_manager) = randomness_manager.as_mut() {

From e42c8c5f75769285678b4b9dc4da01df946a4dab Mon Sep 17 00:00:00 2001
From: Alexandros Tzimas 
Date: Mon, 27 May 2024 10:07:56 +0300
Subject: [PATCH 004/324] [suiop] Build suiop-cli binaries workflow dispatch
 (#17911)

## Description

Create a workflow dispatch that will cause a github action to trigger on
`Mystenlabs/sui-operations` which will generates binary builds for
`suiop-cli` on different architectures.

Relative PR to sui operations:
https://github.com/MystenLabs/sui-operations/pull/3769

## Test plan

- Create a dummy PR to `Mystenlabs/sui`, that contains a change in the
`crates/suiop-cli/` directory or its subdirectories.
- Check if the gh action is triggered in
https://github.com/MystenLabs/sui-operations.

---

## Release notes

Check each box that your changes affect. If none of the boxes relate to
your changes, release notes aren't required.

For each box you select, include information after the relevant heading
that describes the impact of your changes that a user might notice and
any actions they must take to implement updates.

- [ ] Protocol:
- [ ] Nodes (Validators and Full nodes):
- [ ] Indexer:
- [ ] JSON-RPC:
- [ ] GraphQL:
- [ ] CLI:
- [ ] Rust SDK:
---
 .github/workflows/build-suiop-cli.yml | 28 +++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)
 create mode 100644 .github/workflows/build-suiop-cli.yml

diff --git a/.github/workflows/build-suiop-cli.yml b/.github/workflows/build-suiop-cli.yml
new file mode 100644
index 0000000000000..06fb1b36b1915
--- /dev/null
+++ b/.github/workflows/build-suiop-cli.yml
@@ -0,0 +1,28 @@
+name: Build suiop-cli binaries
+on:
+  push:
+    paths:
+      - 'crates/suiop-cli/**'
+  pull_request:
+    paths:
+      - 'crates/suiop-cli/**'
+
+# Do not run the same workflow concurrenctly
+# for the same branch.
+concurrency: ${{ github.workflow }}-${{ github.ref }}
+
+jobs:
+  release:
+    runs-on: ubuntu-latest
+    steps:
+      # Trigger a gh action in MystenLabs/sui-operations
+      - name: Dispatch Build To Operations Repo
+        uses: peter-evans/repository-dispatch@ff45666b9427631e3450c54a1bcbee4d9ff4d7c0 # pin@v3.0.0
+        with:
+          repository: MystenLabs/sui-operations
+          # Using the changeset's token for now,
+          # we could generate a different secret for this
+          # for separation of concerns:
+          token: ${{ secrets.CHANGESETS_DEPLOY_DISPATCH }}
+          event-type: build-binaries
+          client-payload: '{"ref": "${{ github.ref }}", "sha": "${{ github.sha }}"}'

From 7b19a355d09dbb3d7806aa86c74f12f542f20c6b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Lindstr=C3=B8m?= 
Date: Mon, 27 May 2024 15:27:43 +0200
Subject: [PATCH 005/324] Add VDF to sui framework (#16196)

## Description

This adds a VDF verifier (Wesolowski's construction based on imaginary
class groups) to the Sui framework. It can be used to generate on-chain
randomness in an 1-out-of-n trust model (see for example [this
paper](https://crypto.stanford.edu/~dabo/pubs/papers/VDFsurvey.pdf) for
an explanation).

This PR also includes an example of a lottery using VDF to generate it's
randomness.

Boilerplate code and snapshots will be added after the review.

Closing #7222.

## Test Plan

Unit tests.

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

- [X] protocol change
- [X] user-visible impact
- [X] breaking change for a client SDKs
- [X] breaking change for FNs (FN binary must upgrade)
- [X] 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

Add verifiable delay functions (VDFs) to the Sui framework. The VDF is
based on Wesolowski's construction over imaginary class groups. Note
that this is supported in Devnet only.

---------

Co-authored-by: Todd Nowacki 
Co-authored-by: Ashok Menon 
---
 Cargo.lock                                    |  48 +++-
 Cargo.toml                                    |   1 +
 .../docs/sui-framework/group_ops.md           |  12 +-
 .../sui-framework/docs/sui-framework/vdf.md   | 137 ++++++++++
 .../sui-framework/sources/crypto/vdf.move     |  35 +++
 .../sui-framework/tests/crypto/vdf_tests.move |  71 +++++
 crates/sui-framework/published_api.txt        |  12 +
 .../tests/objects/enum_data.exp               | 250 +++++++++---------
 .../tests/packages/datatypes.exp              |   4 +-
 .../tests/packages/enums.exp                  |  42 +--
 crates/sui-open-rpc/spec/openrpc.json         |   5 +-
 crates/sui-protocol-config/src/lib.rs         |  24 ++
 ...sui_protocol_config__test__version_48.snap |   3 +
 ..._populated_genesis_snapshot_matches-2.snap |  28 +-
 .../latest/sui-move-natives/Cargo.toml        |   1 +
 .../latest/sui-move-natives/src/crypto/mod.rs |   1 +
 .../latest/sui-move-natives/src/crypto/vdf.rs | 172 ++++++++++++
 .../latest/sui-move-natives/src/lib.rs        |  22 ++
 .../games/sources/vdf_based_lottery.move      | 160 +++++++++++
 .../games/tests/vdf_based_lottery_tests.move  | 173 ++++++++++++
 20 files changed, 1031 insertions(+), 170 deletions(-)
 create mode 100644 crates/sui-framework/docs/sui-framework/vdf.md
 create mode 100644 crates/sui-framework/packages/sui-framework/sources/crypto/vdf.move
 create mode 100644 crates/sui-framework/packages/sui-framework/tests/crypto/vdf_tests.move
 create mode 100644 sui-execution/latest/sui-move-natives/src/crypto/vdf.rs
 create mode 100644 sui_programmability/examples/games/sources/vdf_based_lottery.move
 create mode 100644 sui_programmability/examples/games/tests/vdf_based_lottery_tests.move

diff --git a/Cargo.lock b/Cargo.lock
index 90d9819857a16..901015c02ad2d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4420,6 +4420,24 @@ dependencies = [
  "typenum",
 ]
 
+[[package]]
+name = "fastcrypto-vdf"
+version = "0.1.0"
+source = "git+https://github.com/MystenLabs/fastcrypto?rev=c101a5176799db3eb9c801b844e7add92153d291#c101a5176799db3eb9c801b844e7add92153d291"
+dependencies = [
+ "bcs",
+ "fastcrypto",
+ "lazy_static",
+ "num-bigint 0.4.4",
+ "num-integer",
+ "num-prime",
+ "num-traits",
+ "rand 0.8.5",
+ "rand_chacha 0.3.1",
+ "serde",
+ "serde_with",
+]
+
 [[package]]
 name = "fastcrypto-zkp"
 version = "0.1.3"
@@ -8136,6 +8154,33 @@ dependencies = [
  "num-traits",
 ]
 
+[[package]]
+name = "num-modular"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64a5fe11d4135c3bcdf3a95b18b194afa9608a5f6ff034f5d857bc9a27fb0119"
+dependencies = [
+ "num-bigint 0.4.4",
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "num-prime"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f4e3bc495f6e95bc15a6c0c55ac00421504a5a43d09e3cc455d1fea7015581d"
+dependencies = [
+ "bitvec 1.0.1",
+ "either",
+ "lru 0.7.8",
+ "num-bigint 0.4.4",
+ "num-integer",
+ "num-modular",
+ "num-traits",
+ "rand 0.8.5",
+]
+
 [[package]]
 name = "num-rational"
 version = "0.4.1"
@@ -13035,6 +13080,7 @@ dependencies = [
  "bcs",
  "better_any",
  "fastcrypto",
+ "fastcrypto-vdf",
  "fastcrypto-zkp",
  "indexmap 2.1.0",
  "move-binary-format",
@@ -15411,7 +15457,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
 dependencies = [
  "cfg-if",
- "rand 0.8.5",
+ "rand 0.7.3",
  "static_assertions",
 ]
 
diff --git a/Cargo.toml b/Cargo.toml
index db44bdac33d11..31a1615150ec2 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -567,6 +567,7 @@ move-abstract-stack = { path = "external-crates/move/crates/move-abstract-stack"
 fastcrypto = { git = "https://github.com/MystenLabs/fastcrypto", rev = "c101a5176799db3eb9c801b844e7add92153d291" }
 fastcrypto-tbls = { git = "https://github.com/MystenLabs/fastcrypto", rev = "c101a5176799db3eb9c801b844e7add92153d291" }
 fastcrypto-zkp = { git = "https://github.com/MystenLabs/fastcrypto", rev = "c101a5176799db3eb9c801b844e7add92153d291", package = "fastcrypto-zkp" }
+fastcrypto-vdf = { git = "https://github.com/MystenLabs/fastcrypto", rev = "c101a5176799db3eb9c801b844e7add92153d291", features = ["experimental"] }
 
 # anemo dependencies
 anemo = { git = "https://github.com/mystenlabs/anemo.git", rev = "26d415eb9aa6a2417be3c03c57d6e93c30bd1ad7" }
diff --git a/crates/sui-framework/docs/sui-framework/group_ops.md b/crates/sui-framework/docs/sui-framework/group_ops.md
index 18f14e6f9e234..a64caad164d36 100644
--- a/crates/sui-framework/docs/sui-framework/group_ops.md
+++ b/crates/sui-framework/docs/sui-framework/group_ops.md
@@ -66,29 +66,29 @@ Generic Move and native functions for group operations.
 ## Constants
 
 
-
+
 
 
 
-
const EInputTooLong: u64 = 2;
+
const EInvalidInput: u64 = 1;
 
- + -
const EInvalidBufferLength: u64 = 3;
+
const EInputTooLong: u64 = 2;
 
- + -
const EInvalidInput: u64 = 1;
+
const EInvalidBufferLength: u64 = 3;
 
diff --git a/crates/sui-framework/docs/sui-framework/vdf.md b/crates/sui-framework/docs/sui-framework/vdf.md new file mode 100644 index 0000000000000..7ad5a218e4597 --- /dev/null +++ b/crates/sui-framework/docs/sui-framework/vdf.md @@ -0,0 +1,137 @@ +--- +title: Module `0x2::vdf` +--- + + + +- [Constants](#@Constants_0) +- [Function `hash_to_input`](#0x2_vdf_hash_to_input) +- [Function `hash_to_input_internal`](#0x2_vdf_hash_to_input_internal) +- [Function `vdf_verify`](#0x2_vdf_vdf_verify) +- [Function `vdf_verify_internal`](#0x2_vdf_vdf_verify_internal) + + +
+ + + + + +## Constants + + + + + + +
const EInvalidInput: u64 = 0;
+
+ + + + + +## Function `hash_to_input` + +Hash an arbitrary binary message to a class group element to be used as input for vdf_verify. + + +
public fun hash_to_input(message: &vector<u8>): vector<u8>
+
+ + + +
+Implementation + + +
public fun hash_to_input(message: &vector<u8>): vector<u8> {
+    hash_to_input_internal(message)
+}
+
+ + + +
+ + + +## Function `hash_to_input_internal` + +The internal functions for hash_to_input. + + +
fun hash_to_input_internal(message: &vector<u8>): vector<u8>
+
+ + + +
+Implementation + + +
native fun hash_to_input_internal(message: &vector<u8>): vector<u8>;
+
+ + + +
+ + + +## Function `vdf_verify` + +Verify the output and proof of a VDF with the given number of iterations. The input, output and proof +are all class group elements represented by triples (a,b,c) such that b^2 - 4ac = discriminant. The are expected +to be encoded as a BCS encoding of a triple of byte arrays, each being the big-endian twos-complement encoding of +a, b and c in that order. + +This uses Wesolowski's VDF construction over imaginary class groups as described in Wesolowski (2020), +'Efficient Verifiable Delay Functions.', J. Cryptol. 33, and is compatible with the VDF implementation in +fastcrypto. + +The discriminant for the class group is pre-computed and fixed. See how this was generated in the fastcrypto-vdf +crate. The final selection of the discriminant for Mainnet will be computed and announced under a nothing-up-my-sleeve +process. + + +
public fun vdf_verify(input: &vector<u8>, output: &vector<u8>, proof: &vector<u8>, iterations: u64): bool
+
+ + + +
+Implementation + + +
public fun vdf_verify(input: &vector<u8>, output: &vector<u8>, proof: &vector<u8>, iterations: u64): bool {
+    vdf_verify_internal(input, output, proof, iterations)
+}
+
+ + + +
+ + + +## Function `vdf_verify_internal` + +The internal functions for vdf_verify_internal. + + +
fun vdf_verify_internal(input: &vector<u8>, output: &vector<u8>, proof: &vector<u8>, iterations: u64): bool
+
+ + + +
+Implementation + + +
native fun vdf_verify_internal(input: &vector<u8>, output: &vector<u8>, proof: &vector<u8>, iterations: u64): bool;
+
+ + + +
diff --git a/crates/sui-framework/packages/sui-framework/sources/crypto/vdf.move b/crates/sui-framework/packages/sui-framework/sources/crypto/vdf.move new file mode 100644 index 0000000000000..0bb9a70aeb63e --- /dev/null +++ b/crates/sui-framework/packages/sui-framework/sources/crypto/vdf.move @@ -0,0 +1,35 @@ +// Copyright (c) Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +module sui::vdf { + + #[allow(unused_const)] + const EInvalidInput: u64 = 0; + + /// Hash an arbitrary binary `message` to a class group element to be used as input for `vdf_verify`. + public fun hash_to_input(message: &vector): vector { + hash_to_input_internal(message) + } + + /// The internal functions for `hash_to_input`. + native fun hash_to_input_internal(message: &vector): vector; + + /// Verify the output and proof of a VDF with the given number of iterations. The `input`, `output` and `proof` + /// are all class group elements represented by triples `(a,b,c)` such that `b^2 - 4ac = discriminant`. The are expected + /// to be encoded as a BCS encoding of a triple of byte arrays, each being the big-endian twos-complement encoding of + /// a, b and c in that order. + /// + /// This uses Wesolowski's VDF construction over imaginary class groups as described in Wesolowski (2020), + /// 'Efficient Verifiable Delay Functions.', J. Cryptol. 33, and is compatible with the VDF implementation in + /// fastcrypto. + /// + /// The discriminant for the class group is pre-computed and fixed. See how this was generated in the fastcrypto-vdf + /// crate. The final selection of the discriminant for Mainnet will be computed and announced under a nothing-up-my-sleeve + /// process. + public fun vdf_verify(input: &vector, output: &vector, proof: &vector, iterations: u64): bool { + vdf_verify_internal(input, output, proof, iterations) + } + + /// The internal functions for `vdf_verify_internal`. + native fun vdf_verify_internal(input: &vector, output: &vector, proof: &vector, iterations: u64): bool; +} diff --git a/crates/sui-framework/packages/sui-framework/tests/crypto/vdf_tests.move b/crates/sui-framework/packages/sui-framework/tests/crypto/vdf_tests.move new file mode 100644 index 0000000000000..89ccef6607fae --- /dev/null +++ b/crates/sui-framework/packages/sui-framework/tests/crypto/vdf_tests.move @@ -0,0 +1,71 @@ +// Copyright (c) Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +#[test_only] +module sui::vdf_tests { + use sui::vdf::hash_to_input; + use sui::vdf::vdf_verify; + + #[test] + fun test_hash_to_input() { + let seed = b"seed"; + let expected = x"bb0102ed9d7af1f184a7542c36ae40e7bf3cd3953dfdc1aab84c7137f33614a87a443be6b57eb28e33f661bbd7088c6fae16a4550997d05a1631ebf5ec886440ac82cdfbff978efe1d53c672e25374627a2e9cc15baaf19042a83044099ce13612ff2b0926fe2185a3920b34e607d580a8474c3ec6f3961303c76babfcbde4a2df5243784048649edd19cdd52fd0cfe5b304c6da8240e04d054c97fa6fe0799e711197d7b31c4a2f2e3984ae9cd4c6ea20e2190cec9ef8d32f3d03034fe90209d296ce18b5e8203ccbcfc05897dbede2cd84ebfe493a8d4f1f5f07e75a0dd61920dd8bb5fbca1db92f0d99572010f66034155c667dd9d2cb8ffece37cf3bfcfb712654cf99b07042903be494570a66cb9357ea33b4332e2117256cbbb9cab3a3c44b402c13b672f3e226073b96f604863b247f801acc9efb8d613fee7a648e0e3b5c4da791d8bdf5d097c254ed7ed885af0ab78535d0aedde4ad5817a5230372e64080caa56ada2debbf6ed8131c939b66d02fc49e3f188156ac49a88298fae6ad2f4efa068f613d522a4efacd5aa3dc84046684fa337f38238d51ec92a46aab01d00b95444f20f544d6fc38af9b6bd63a0654ba98aa7480c52a833a47c3466ff518c78717d7f72b04889e0ce64bff5d558291a0aaad673fe6958d5a4aadfefaa16eea8a4407a0930dd86c44d1ad97b464064bc8d17499d9248e729a75d8469223700f080ddafb981af5a12f08f5f2f09c96d69d4a17fb7bcce368fa4b88351db270186806cb75c79704083ccd2eae77a02efcd283a47f715ff24264c89c1a9f01fbcdb5c551f7607a20300cc85b41d131687632fbebf93226eb91d8136be471824f90d17e4ed4c0702c85345814b4095a0a7227d4836bfd5b284ffde26e7d03caf588c2f371255fbe439b1094d1dd4c7e0dadb53a546c6d406e2d106277cd22139aa71c91411537312fa216ea90d790d6c230ee7a9b743f559a2287acd1fd2b8dec38549bd625c33616ac96ef76eb12b327b4c49a87b4a46134c4e3829eaf0f1821847fdf9edf4c6d23b8a9ee7b6d95a98ba05e6dcaa921326a79b3d10fb2e407d095191c9f8afc2e64810109ff2bc1e34f999f6faac05c2b6295ee4799d0ce7b268c6bac3d3285116ed0b821d9463d05cb349ac309223123e176ec8f6898ef420e87e74aaabd3c247b2312ff7f49e90054af6f871c7e37c61986e3572ff201bc8b205f0924897b206ca9613216daa12fbbda5c668ae8eb26e717a5c813c965cc906bea52ab281c240b6d4bb65e097e7cc924bbdcc6efbd8e8c4366c65989c6f5ab2d5f1d1fe5ee7865e9f6d468d63d7f548a4e02507dbd18fefa777c5163c6d15bc36979de551d8cdc19601ee861c674bafa5f62bc203eea1c50e7c25c3db98063a0774c7c2dbfdcae651d6484f62c3970085fe8cd841d44c857edae7e5e413008060fe384df6773d4edbc211cccf33e0cd63dac177dc435395452b187d634d6581a5db81998ef64d43c3b64d7909a79abfc70981bc7bda06a3caf2273123568"; + let actual = hash_to_input(&seed); + assert!(actual == expected, 0); + + let other_seed = b"other seed"; + let actual = hash_to_input(&other_seed); + assert!(actual != expected, 1); + } + + #[test] + fun test_vdf_verify() { + let input_seed = x"2ef29e01809053dcfc89e7acad77e13c2bf03b5a9a0bbfea555a1423f1f1ae23"; + let input_bytes = hash_to_input(&input_seed); + let input_bytes_expected = x"bc01009ed67199c633da0faa75a8ed0ff5c3ae7c278c79aad85953cdf86d57101b1ee941e5239b7d614e5b16eac269c460f16d57a12c75b52c48fac643a1c4918fab86805fe08fcd6b38093a17143cca7550fd018b8bc6871fb441b406bec7a7f3a61c3b2a5aa9daca5f9a6fa474b270688de643323de1acc8073a3418bc1681a614c1abb5fa56b61a7d6df4260547c9f613c5f0dbd7cb91a478ac94b1cce6b1f4784dc161ec3c85bf02cf99fd460b0b25a44d1990dacd1fe7a43b797611ea0210645fef3905f7e1accf97bd3b868a8a99d4a1a546e5a55e20f343fc2724829f1770591b50a73c93ec9b8c01ce1fa6b84eddd5a7ddd077110e21b8e058bf2fed2592a5449db177ec0e32595b20bda5779c2f346b01df8c0d277d9d3a7fe0a04e67b210be60334efdadb7abc5ac001b71509c2d487d9d26443527c1b8b02dfcffc50ef98020f569cdf6fffca5870b0e502493fceee35b79eed99e2c758a0aff4c86b2af0dd223e270ecf84eb7405fe35a9e37d6b080efa3c59806c2ceffa82f38502f9d37b6c298cf07534347cd9ee436406784bd7e0a57d380dd3923ddca13d86f3b2c83a135f125f9429a6802247a0e926b54144d74e4e8f66f0303cdc91843ce7e1fb9c6276c000512c0709c7fbfde2b80e66db77222447ef6b4da4a698e011c6de95ad88738aea465c158288a54223c7f7152577cc48691af57e2631e3224b7c94e2a4c5034db35bbf9e807753fa51da8798bf63b7e6ebd857ca4cf01fcab7a33e63fa89eb386e2ef98046c44491bdf8d62ede2af4ab79ccac88e404abb649b92f49c9f9abcf2216bb628e96400a75a66c12b6ff1c6dae498dd4183ad989921ebc6a1be73127741333671eb72cd25eabc69fecc3c50da06b4a3af155264d4e39e8c681b8c5555d4cab748ed15d119527820e01854fa203c2deba3a67620d47733919e8c71d659e60e86db69905ebdc4dbeda67f77291c2202b2116a05f227f963a97eb8c87104b2df349f01f251aa22bbd41541998ce755309b98d9597d7ee26b6acaef1869885c775e6ceb710c36c07e401e17a8ccb838e33f64e43e4db3491b5cef6e800c4e494610ab81a8b489263b86976160d7d0106cab79bf2a2fce5b01e8f9d1fb069a98e814c94f10d9917b7ea27209bc822b35741f56a9aeadb75a7eae6a8cbd7df08e079db64fd48655f42c24c14bb6c72e744206a3e15deee45cab74d589deb1055e0e69fe508a2ef356dc4e2caaaf89f44a520722490374eade8573429d0d6d16e3c681853f96759cc6e3ea3aaad55284282abd40686281ff944c6a507086143cf76d0f7f93b486d552fa4698656cff8a325fea84943333645b29ee11c99555b2076a09466f6e602db663e1bd45c523a12a7fcd2328d5139d14b25561b94f62f69d436c5d4c92b01ae3a91baa1b5781bd0bf2156e1d0042ab2cbc6e10f4389868fc41d05b19bfe3dfcaacb0478b3dce887da8435c9d49f457fd54e129133e5ce87c39acb9206213daec867fca35e6b612c523fb9fba959542a777ea74"; + assert!(input_bytes == input_bytes_expected, 0); + + let output_bytes = x"c001503be6eff558a40ba145da5aa9d1270367f32cde44c1601846cdd3d0911abce8ab6adb6b82682b45107545e9ae1efca44dd6f3ba8d95a687652b94f479f6b1a37156c44194d6bc5f266098b75251b12de6fa67de6aea14250c0481694db5f24db5e3c89da3354aafc10c4bd0371f9a175d1b5b193190c4c1089ed7a95dc07f1ce29021b55f3aaa7eb65725d61277f0996b783c005a919ba121d81f211f63d188ac525056235504fe4858765dc6498362d98e8540287a0ff78424c18de53abe46c0014f847bd49f599960fe3c3b7cfc571cd854c7d21b0e9984070f7e168c872a6e6480d8fd37d30602f57a237b83ae961e6a4acb94b78c32d04f06058bda037d6ad313c81f823db25c53c265b02a29008f727f95010c82b0cf8745e77a7f4000dac929ba83a4594482b4e6ff59c93a78df5c816f244914329c145e288fd3fd4800a1cc2df23f386112e569608e6de40ee65fe870960b4e3fee4bb188d8db0dd5df3c2384eb24a797eb20cf8524d563663ccde866a405e2713cfafdb760e50c77a797c10100a31fc5ca0a91aa788d5f5df17a1433f1a0e6e4da440ce935b1b48dc6868c8fc00d7ee725ce21797a6c4440af02570466081479e99eee1a5b509a3e1ac2e000ed386c35d9fadd130df2a292fa5f9aa2c195c48c9d11e58ac98c8dbd2169721ed2d2c9f5544de17deeaa9655360ed7baa46820f5e008af1e3f028d819dee3fee50ab55b266385dfc8f65f7f0c1b6149e5295bfefb83b14db3a30b2cefd1495ba4e5ae39d2b729f9644fc28764d03243fad3e61145ed83cbf2708b60c0b7cac7148"; + let proof_bytes = x"0101010180032cf35709e1301d02b40a0dbe3dadfe6ec1eeba8fb8060a1decd0c7a126ea3f27fadcad81435601b0e0abca5c89173ef639e5a88043aa29801e6799e430b509e479b57af981f9ddd48d3a8d5919f99258081557a08270bb441233c78030a01e03ec199b5e3eef5ccc9b1a3d4841cbe4ff529c22a8cd1b1b0075338d864e3890942df6b007d2c3e3a8ef1ce7490c6bbec5372adfcbf8704a1ffc9a69db8d9cdc54762f019036e450e457325eef74b794f3f16ff327d68079a5b9de49163d7323937374f8a785a8f9afe84d6a71b336e4de00f239ee3af1d7604a3985e610e1603bd0e1a4998e19fa0c8920ffd8d61b0a87eeee50ac7c03ff7c4708a34f3bc92fd0103758c954ee34032cee2c78ad8cdc79a35dbc810196b7bf6833e1c45c83b09c0d1b78bc6f8753e10770e7045b08d50b4aa16a75b27a096d5ec1331f1fd0a44e95a8737c20240c90307b5497d3470393c2a00da0649e86d13e820591296c644fc1eef9e7c6ca4967c5e19df3153cd7fbd598c271e11c10397349ddc8cc8452ec"; + assert!(vdf_verify(&input_bytes, &output_bytes, &proof_bytes, 100), 1); + + // Try with output from 101 iterations of the VDF instead + let other_output_bytes = x"c0015011855f4d75bbd3c52c439c8c94ac523090a0cfd3ce04132ea8091c7893fb173a9f5e305d515f5e94fd7a23697bd3a6fba9ebb80c7b9fcece3b42b83605c3b94207bcfd135d90e2ad1b0a2c98c2a0e57d7499cfa3ecddea4fd733c2e437a6d1e707ae2a38cca2c65daa08c1c26cb7078d5b05f9d721e457c94d0fd1c8793eac8370eb8167b47492444403ab9c1d1ff37d75c2c4ae2271a86e6af59f31d07243bd3134bcafcfb1716085eca27d248611732563df5832c35672880d69301869adc00106c9d5439af4d4dfa21e75e3966af4905b7cd97711bd217605043778626ed51be43a5d188356df1f260ed60a1f90b7ffbb7c3c416de92fdd8358480e5b938afd6143053b1736b316503d18b9e5b024299cbdbc17d9b1f825d97b74b3fb09d1ddab4fa60a420db4cc11b93c9166152c38f7ea175dee2293ce3fafc8fd271bae814bcef963bdcb0a1e0cf6404e6a0b63e44321c54041d2a704aaa4fa5836774499dcdc2e8255cb9f907a6c6edef5d7290e4fe2bc3307bb136da05c705ea16419fdc101008fdcd8a6d77bf0f7efed3258549419d564c91cd4682c6465105c966f1fbf73f11ee123f9f292d2d04c63adfc21e8146f108779e7e781424989393d8677e142f2b9c8115d98fc2a81d826bb252c0b3152f4cd290062ff583066f263ffa399da76159c4adb007cd8a1ba6f41f119909e9336a0d0205272101ab79753712ba031094f2be571929d4d0c478a5893f9673d593279ba6b92db14c23dff795d084e1bd913f32279c4c252afe11da7371945be9e9907ca6864cf3137364677c1b5757566"; + let other_proof_bytes = x"0101010180032cf35709e1301d02b40a0dbe3dadfe6ec1eeba8fb8060a1decd0c7a126ea3f27fadcad81435601b0e0abca5c89173ef639e5a88043aa29801e6799e430b509e479b57af981f9ddd48d3a8d5919f99258081557a08270bb441233c78030a01e03ec199b5e3eef5ccc9b1a3d4841cbe4ff529c22a8cd1b1b0075338d864e3890942df6b007d2c3e3a8ef1ce7490c6bbec5372adfcbf8704a1ffc9a69db8d9cdc54762f019036e450e457325eef74b794f3f16ff327d68079a5b9de49163d7323937374f8a785a8f9afe84d6a71b336e4de00f239ee3af1d7604a3985e610e1603bd0e1a4998e19fa0c8920ffd8d61b0a87eeee50ac7c03ff7c4708a34f3bc92fd0103758c954ee34032cee2c78ad8cdc79a35dbc810196b7bf6833e1c45c83b09c0d1b78bc6f8753e10770e7045b08d50b4aa16a75b27a096d5ec1331f1fd0a44e95a8737c20240c90307b5497d3470393c2a00da0649e86d13e820591296c644fc1eef9e7c6ca4967c5e19df3153cd7fbd598c271e11c10397349ddc8cc8452ec"; + assert!(!vdf_verify(&input_bytes, &other_output_bytes, &other_proof_bytes, 100), 2); + assert!(vdf_verify(&input_bytes, &other_output_bytes, &other_proof_bytes, 101), 3); + + // Try with valid input, output and proof but from a different group + let input_bytes_wrong_group = x"01020101800315cb487a5d538968cd37b6643d73e7ae67713bcdd98c98dc10dcb36fec3559a0fc2e2a40f0c7647c2f3cc1890606edf7082614238eedeec8a30c04b69a446a4a52114d4b80333d81373d1b8466e59eb5b5f1088853888a415e522facd50986f533bba84ab4359f9a6d17d29096541d4d90348a23dfc728e4fe44bf359fc137ba22754df67873ff7ab5cb183cf2958c672b88528c093f5a769b68676d1f3ba1337e5ae5e71db52f2fe3f9aab1ea709e8f65a10f72e88e5213553feee9a3812dd4f29285016bce48b47f15f69510bd915c688464d644d4e0d674bbe3593b4e200a5a08c8d58598e2017b753fdfebddf7f77ee70c9c5e890eaf3cbe8e8e936592030594833dea222df12ed4113b3bb92792c2b3025f4c04debb9699a3633b0dd20271f9151e9b07ed2709c654e167a97cddcb906a85d91309a667512260cf4093307b7a79aca85c4f550fdaedac4e19314152fe86990f6ed44492a55b48369cb188dc887d190faa0c65deb2ede6884f91cec9c200023ad63e27fed4b8de961a7ddb"; + let output_bytes_wrong_group = x"c0012b597511d34d7f852a3608f1b3bd2333005ad09b096d6bb181e39a8695aabc321e6f78f1a0e4792f37eca51d02610eb77a5513059fd00856bf69d64ccb0d09fe967f07f65e9b3dd236c08d219ae7e78551d1100e468c580944459daa31f0a6a5a2c6371c9976118d4ef845f4a84e79501d6f501ceb1b107099089fa985a837fdf7acae642ac211c9b44f9ca7b5d62fc0b04041ccf509a5bd7bda5b0a2c96508ae2a8b61cf75d2b3cc5724b813b9627fc42e2bb6f4fb2e20866aa4f5baa2478c2c001110d9be2918a11962e3349d4f6a2f2b5c1511ea754422ea325d54e42f1e255283c0fe652f62fc16b7affcbe6733afada9b1d748716c85fbca6b959d008afcacad3759c1b37a8485c39acead2e3db0b7eb325e7c331fde1c4148f286cae1c7723db4e3310246917ca22d5dc2bdc67b55386b3f45ffe30b6cf09b4352ddf3e70a51814ebb6079186e2592f1c15f585a247c6de175fa4a7876c89e2ec1c40c04cc066bc1ba2f3527673e3054905cd0b7a478c4a145da5bb015ed27b4b9a710ea88fc101010316392f7a0d2aee08c80b1811e9e3a9700fc976caba58179ab6e046f28b8d0d73f5a68fc298516932296215717354b67384aca578d351f930dd8c34488231633db1694082550cc3eb87ca9ed938dfe9fe811fd4afbcec9ebf823f7e885167dbf9f90b2afc793a44fd055932842f1fcd08618fcfba8121c8279a920b8dbd681be7781c593212aa03208d3f61d181567e5dfe374ed7221f7c10392288c990296b581dba86610e3c31063151b0204c6c4c8e2f90fbbab10f493ecf7c89a879a537"; + let proof_bytes_wrong_group = x"0101010180032b9690f4baa712d19a6f6cc87ae7cf5ccee2779bb31931b821b966dfd86ab341f85c5481e18ec8f85e7983120c0ddbee104c28471ddbdd914618096d3488d494a4229a9700667b026e7a3708cdcb3d6b6be21110a7111482bca45f59aa130dea67775095686b3f34da2fa5212ca83a9b20691447bf8e51c9fc897e6b3f826f7444ea9becf0e7fef56b963079e52b18ce5710a518127eb4ed36d0ceda3e774266fcb5cbce3b6a5e5fc7f35563d4e13d1ecb421ee5d11ca426aa7fddd347025ba9e5250a02d79c9168fe2bed2a217b22b8d108c9ac89a9c1ace977c6b2769c4014b41191ab0b31c402f6ea7fbfd7bbefeefdce1938bd121d5e797d1d1d26cb24060b29067bd4445be25da8227677724f25856604be9809bd772d3346c6761ba404e3f22a3d360fda4e138ca9c2cf52f9bb9720d50bb226134ccea244c19e812660f6f4f35950b89eaa1fb5db589c326282a5fd0d321edda889254ab6906d396311b910fa321f5418cbbd65dbcd109f239d9384000475ac7c4ffda971bd2c34fbb6"; + assert!(!vdf_verify(&input_bytes_wrong_group, &output_bytes_wrong_group, &proof_bytes_wrong_group, 100), 4); + } + + #[test] + #[expected_failure(abort_code = sui::vdf::EInvalidInput)] + fun test_vdf_verify_with_invalid_input() { + let invalid_input_bytes = x"abcd"; + let output_bytes = x"c001503be6eff558a40ba145da5aa9d1270367f32cde44c1601846cdd3d0911abce8ab6adb6b82682b45107545e9ae1efca44dd6f3ba8d95a687652b94f479f6b1a37156c44194d6bc5f266098b75251b12de6fa67de6aea14250c0481694db5f24db5e3c89da3354aafc10c4bd0371f9a175d1b5b193190c4c1089ed7a95dc07f1ce29021b55f3aaa7eb65725d61277f0996b783c005a919ba121d81f211f63d188ac525056235504fe4858765dc6498362d98e8540287a0ff78424c18de53abe46c0014f847bd49f599960fe3c3b7cfc571cd854c7d21b0e9984070f7e168c872a6e6480d8fd37d30602f57a237b83ae961e6a4acb94b78c32d04f06058bda037d6ad313c81f823db25c53c265b02a29008f727f95010c82b0cf8745e77a7f4000dac929ba83a4594482b4e6ff59c93a78df5c816f244914329c145e288fd3fd4800a1cc2df23f386112e569608e6de40ee65fe870960b4e3fee4bb188d8db0dd5df3c2384eb24a797eb20cf8524d563663ccde866a405e2713cfafdb760e50c77a797c10100a31fc5ca0a91aa788d5f5df17a1433f1a0e6e4da440ce935b1b48dc6868c8fc00d7ee725ce21797a6c4440af02570466081479e99eee1a5b509a3e1ac2e000ed386c35d9fadd130df2a292fa5f9aa2c195c48c9d11e58ac98c8dbd2169721ed2d2c9f5544de17deeaa9655360ed7baa46820f5e008af1e3f028d819dee3fee50ab55b266385dfc8f65f7f0c1b6149e5295bfefb83b14db3a30b2cefd1495ba4e5ae39d2b729f9644fc28764d03243fad3e61145ed83cbf2708b60c0b7cac7148"; + let proof_bytes = x"0101010180032cf35709e1301d02b40a0dbe3dadfe6ec1eeba8fb8060a1decd0c7a126ea3f27fadcad81435601b0e0abca5c89173ef639e5a88043aa29801e6799e430b509e479b57af981f9ddd48d3a8d5919f99258081557a08270bb441233c78030a01e03ec199b5e3eef5ccc9b1a3d4841cbe4ff529c22a8cd1b1b0075338d864e3890942df6b007d2c3e3a8ef1ce7490c6bbec5372adfcbf8704a1ffc9a69db8d9cdc54762f019036e450e457325eef74b794f3f16ff327d68079a5b9de49163d7323937374f8a785a8f9afe84d6a71b336e4de00f239ee3af1d7604a3985e610e1603bd0e1a4998e19fa0c8920ffd8d61b0a87eeee50ac7c03ff7c4708a34f3bc92fd0103758c954ee34032cee2c78ad8cdc79a35dbc810196b7bf6833e1c45c83b09c0d1b78bc6f8753e10770e7045b08d50b4aa16a75b27a096d5ec1331f1fd0a44e95a8737c20240c90307b5497d3470393c2a00da0649e86d13e820591296c644fc1eef9e7c6ca4967c5e19df3153cd7fbd598c271e11c10397349ddc8cc8452ec"; + let _ = vdf_verify(&invalid_input_bytes, &output_bytes, &proof_bytes, 100); + } + + #[test] + #[expected_failure(abort_code = sui::vdf::EInvalidInput)] + fun test_vdf_verify_with_invalid_output() { + let input_bytes = x"bc01009ed67199c633da0faa75a8ed0ff5c3ae7c278c79aad85953cdf86d57101b1ee941e5239b7d614e5b16eac269c460f16d57a12c75b52c48fac643a1c4918fab86805fe08fcd6b38093a17143cca7550fd018b8bc6871fb441b406bec7a7f3a61c3b2a5aa9daca5f9a6fa474b270688de643323de1acc8073a3418bc1681a614c1abb5fa56b61a7d6df4260547c9f613c5f0dbd7cb91a478ac94b1cce6b1f4784dc161ec3c85bf02cf99fd460b0b25a44d1990dacd1fe7a43b797611ea0210645fef3905f7e1accf97bd3b868a8a99d4a1a546e5a55e20f343fc2724829f1770591b50a73c93ec9b8c01ce1fa6b84eddd5a7ddd077110e21b8e058bf2fed2592a5449db177ec0e32595b20bda5779c2f346b01df8c0d277d9d3a7fe0a04e67b210be60334efdadb7abc5ac001b71509c2d487d9d26443527c1b8b02dfcffc50ef98020f569cdf6fffca5870b0e502493fceee35b79eed99e2c758a0aff4c86b2af0dd223e270ecf84eb7405fe35a9e37d6b080efa3c59806c2ceffa82f38502f9d37b6c298cf07534347cd9ee436406784bd7e0a57d380dd3923ddca13d86f3b2c83a135f125f9429a6802247a0e926b54144d74e4e8f66f0303cdc91843ce7e1fb9c6276c000512c0709c7fbfde2b80e66db77222447ef6b4da4a698e011c6de95ad88738aea465c158288a54223c7f7152577cc48691af57e2631e3224b7c94e2a4c5034db35bbf9e807753fa51da8798bf63b7e6ebd857ca4cf01fcab7a33e63fa89eb386e2ef98046c44491bdf8d62ede2af4ab79ccac88e404abb649b92f49c9f9abcf2216bb628e96400a75a66c12b6ff1c6dae498dd4183ad989921ebc6a1be73127741333671eb72cd25eabc69fecc3c50da06b4a3af155264d4e39e8c681b8c5555d4cab748ed15d119527820e01854fa203c2deba3a67620d47733919e8c71d659e60e86db69905ebdc4dbeda67f77291c2202b2116a05f227f963a97eb8c87104b2df349f01f251aa22bbd41541998ce755309b98d9597d7ee26b6acaef1869885c775e6ceb710c36c07e401e17a8ccb838e33f64e43e4db3491b5cef6e800c4e494610ab81a8b489263b86976160d7d0106cab79bf2a2fce5b01e8f9d1fb069a98e814c94f10d9917b7ea27209bc822b35741f56a9aeadb75a7eae6a8cbd7df08e079db64fd48655f42c24c14bb6c72e744206a3e15deee45cab74d589deb1055e0e69fe508a2ef356dc4e2caaaf89f44a520722490374eade8573429d0d6d16e3c681853f96759cc6e3ea3aaad55284282abd40686281ff944c6a507086143cf76d0f7f93b486d552fa4698656cff8a325fea84943333645b29ee11c99555b2076a09466f6e602db663e1bd45c523a12a7fcd2328d5139d14b25561b94f62f69d436c5d4c92b01ae3a91baa1b5781bd0bf2156e1d0042ab2cbc6e10f4389868fc41d05b19bfe3dfcaacb0478b3dce887da8435c9d49f457fd54e129133e5ce87c39acb9206213daec867fca35e6b612c523fb9fba959542a777ea74"; + let invalid_output_bytes = x"abcd"; + let proof_bytes = x"0101010180032cf35709e1301d02b40a0dbe3dadfe6ec1eeba8fb8060a1decd0c7a126ea3f27fadcad81435601b0e0abca5c89173ef639e5a88043aa29801e6799e430b509e479b57af981f9ddd48d3a8d5919f99258081557a08270bb441233c78030a01e03ec199b5e3eef5ccc9b1a3d4841cbe4ff529c22a8cd1b1b0075338d864e3890942df6b007d2c3e3a8ef1ce7490c6bbec5372adfcbf8704a1ffc9a69db8d9cdc54762f019036e450e457325eef74b794f3f16ff327d68079a5b9de49163d7323937374f8a785a8f9afe84d6a71b336e4de00f239ee3af1d7604a3985e610e1603bd0e1a4998e19fa0c8920ffd8d61b0a87eeee50ac7c03ff7c4708a34f3bc92fd0103758c954ee34032cee2c78ad8cdc79a35dbc810196b7bf6833e1c45c83b09c0d1b78bc6f8753e10770e7045b08d50b4aa16a75b27a096d5ec1331f1fd0a44e95a8737c20240c90307b5497d3470393c2a00da0649e86d13e820591296c644fc1eef9e7c6ca4967c5e19df3153cd7fbd598c271e11c10397349ddc8cc8452ec"; + let _ = vdf_verify(&input_bytes, &invalid_output_bytes, &proof_bytes, 100); + } + + #[test] + #[expected_failure(abort_code = sui::vdf::EInvalidInput)] + fun test_vdf_verify_with_invalid_proof() { + let input_bytes = x"bc01009ed67199c633da0faa75a8ed0ff5c3ae7c278c79aad85953cdf86d57101b1ee941e5239b7d614e5b16eac269c460f16d57a12c75b52c48fac643a1c4918fab86805fe08fcd6b38093a17143cca7550fd018b8bc6871fb441b406bec7a7f3a61c3b2a5aa9daca5f9a6fa474b270688de643323de1acc8073a3418bc1681a614c1abb5fa56b61a7d6df4260547c9f613c5f0dbd7cb91a478ac94b1cce6b1f4784dc161ec3c85bf02cf99fd460b0b25a44d1990dacd1fe7a43b797611ea0210645fef3905f7e1accf97bd3b868a8a99d4a1a546e5a55e20f343fc2724829f1770591b50a73c93ec9b8c01ce1fa6b84eddd5a7ddd077110e21b8e058bf2fed2592a5449db177ec0e32595b20bda5779c2f346b01df8c0d277d9d3a7fe0a04e67b210be60334efdadb7abc5ac001b71509c2d487d9d26443527c1b8b02dfcffc50ef98020f569cdf6fffca5870b0e502493fceee35b79eed99e2c758a0aff4c86b2af0dd223e270ecf84eb7405fe35a9e37d6b080efa3c59806c2ceffa82f38502f9d37b6c298cf07534347cd9ee436406784bd7e0a57d380dd3923ddca13d86f3b2c83a135f125f9429a6802247a0e926b54144d74e4e8f66f0303cdc91843ce7e1fb9c6276c000512c0709c7fbfde2b80e66db77222447ef6b4da4a698e011c6de95ad88738aea465c158288a54223c7f7152577cc48691af57e2631e3224b7c94e2a4c5034db35bbf9e807753fa51da8798bf63b7e6ebd857ca4cf01fcab7a33e63fa89eb386e2ef98046c44491bdf8d62ede2af4ab79ccac88e404abb649b92f49c9f9abcf2216bb628e96400a75a66c12b6ff1c6dae498dd4183ad989921ebc6a1be73127741333671eb72cd25eabc69fecc3c50da06b4a3af155264d4e39e8c681b8c5555d4cab748ed15d119527820e01854fa203c2deba3a67620d47733919e8c71d659e60e86db69905ebdc4dbeda67f77291c2202b2116a05f227f963a97eb8c87104b2df349f01f251aa22bbd41541998ce755309b98d9597d7ee26b6acaef1869885c775e6ceb710c36c07e401e17a8ccb838e33f64e43e4db3491b5cef6e800c4e494610ab81a8b489263b86976160d7d0106cab79bf2a2fce5b01e8f9d1fb069a98e814c94f10d9917b7ea27209bc822b35741f56a9aeadb75a7eae6a8cbd7df08e079db64fd48655f42c24c14bb6c72e744206a3e15deee45cab74d589deb1055e0e69fe508a2ef356dc4e2caaaf89f44a520722490374eade8573429d0d6d16e3c681853f96759cc6e3ea3aaad55284282abd40686281ff944c6a507086143cf76d0f7f93b486d552fa4698656cff8a325fea84943333645b29ee11c99555b2076a09466f6e602db663e1bd45c523a12a7fcd2328d5139d14b25561b94f62f69d436c5d4c92b01ae3a91baa1b5781bd0bf2156e1d0042ab2cbc6e10f4389868fc41d05b19bfe3dfcaacb0478b3dce887da8435c9d49f457fd54e129133e5ce87c39acb9206213daec867fca35e6b612c523fb9fba959542a777ea74"; + let output_bytes = x"c001503be6eff558a40ba145da5aa9d1270367f32cde44c1601846cdd3d0911abce8ab6adb6b82682b45107545e9ae1efca44dd6f3ba8d95a687652b94f479f6b1a37156c44194d6bc5f266098b75251b12de6fa67de6aea14250c0481694db5f24db5e3c89da3354aafc10c4bd0371f9a175d1b5b193190c4c1089ed7a95dc07f1ce29021b55f3aaa7eb65725d61277f0996b783c005a919ba121d81f211f63d188ac525056235504fe4858765dc6498362d98e8540287a0ff78424c18de53abe46c0014f847bd49f599960fe3c3b7cfc571cd854c7d21b0e9984070f7e168c872a6e6480d8fd37d30602f57a237b83ae961e6a4acb94b78c32d04f06058bda037d6ad313c81f823db25c53c265b02a29008f727f95010c82b0cf8745e77a7f4000dac929ba83a4594482b4e6ff59c93a78df5c816f244914329c145e288fd3fd4800a1cc2df23f386112e569608e6de40ee65fe870960b4e3fee4bb188d8db0dd5df3c2384eb24a797eb20cf8524d563663ccde866a405e2713cfafdb760e50c77a797c10100a31fc5ca0a91aa788d5f5df17a1433f1a0e6e4da440ce935b1b48dc6868c8fc00d7ee725ce21797a6c4440af02570466081479e99eee1a5b509a3e1ac2e000ed386c35d9fadd130df2a292fa5f9aa2c195c48c9d11e58ac98c8dbd2169721ed2d2c9f5544de17deeaa9655360ed7baa46820f5e008af1e3f028d819dee3fee50ab55b266385dfc8f65f7f0c1b6149e5295bfefb83b14db3a30b2cefd1495ba4e5ae39d2b729f9644fc28764d03243fad3e61145ed83cbf2708b60c0b7cac7148"; + let invalid_proof_bytes = x"abcd"; + let _ = vdf_verify(&input_bytes, &output_bytes, &invalid_proof_bytes, 100); + } +} diff --git a/crates/sui-framework/published_api.txt b/crates/sui-framework/published_api.txt index 3b070cfed52f2..d68accca9240f 100644 --- a/crates/sui-framework/published_api.txt +++ b/crates/sui-framework/published_api.txt @@ -1033,6 +1033,18 @@ blake2b256 keccak256 public fun 0x2::hash +hash_to_input + public fun + 0x2::vdf +hash_to_input_internal + fun + 0x2::vdf +vdf_verify + public fun + 0x2::vdf +vdf_verify_internal + fun + 0x2::vdf encode public fun 0x2::hex diff --git a/crates/sui-graphql-e2e-tests/tests/objects/enum_data.exp b/crates/sui-graphql-e2e-tests/tests/objects/enum_data.exp index 11db5c57d3e05..7b0d472906fc6 100644 --- a/crates/sui-graphql-e2e-tests/tests/objects/enum_data.exp +++ b/crates/sui-graphql-e2e-tests/tests/objects/enum_data.exp @@ -30,7 +30,7 @@ Response: { "asMoveObject": { "contents": { "type": { - "repr": "0x2b27451fe08307117ecc1d172f7bb24b81bfdb774592d8d11ba196a76edaddd6::m::Foo" + "repr": "0xc6c3c93403b514bc534bb5eb5f18ad994caa414f6d178d3c71ef677f343fed7f::m::Foo" }, "data": { "Struct": [ @@ -38,38 +38,38 @@ Response: { "name": "id", "value": { "UID": [ - 56, - 223, - 62, - 4, - 221, - 43, - 163, - 179, - 9, - 17, - 185, - 146, - 193, - 146, - 56, - 28, - 179, - 90, - 243, + 38, + 208, + 191, + 88, + 204, + 210, + 143, + 164, + 241, 178, - 100, - 107, - 65, - 162, - 152, - 189, - 57, - 216, - 209, + 35, 61, - 42, - 215 + 136, + 222, + 125, + 75, + 118, + 15, + 229, + 217, + 229, + 13, + 97, + 94, + 19, + 200, + 52, + 115, + 126, + 208, + 219, + 38 ] } }, @@ -77,38 +77,38 @@ Response: { "name": "f0", "value": { "ID": [ - 56, - 223, - 62, - 4, - 221, - 43, - 163, - 179, - 9, - 17, - 185, - 146, - 193, - 146, - 56, - 28, - 179, - 90, - 243, + 38, + 208, + 191, + 88, + 204, + 210, + 143, + 164, + 241, 178, - 100, - 107, - 65, - 162, - 152, - 189, - 57, - 216, - 209, + 35, 61, - 42, - 215 + 136, + 222, + 125, + 75, + 118, + 15, + 229, + 217, + 229, + 13, + 97, + 94, + 19, + 200, + 52, + 115, + 126, + 208, + 219, + 38 ] } }, @@ -148,38 +148,38 @@ Response: { "Vector": [ { "Address": [ - 56, - 223, - 62, - 4, - 221, - 43, - 163, - 179, - 9, - 17, - 185, - 146, - 193, - 146, - 56, - 28, - 179, - 90, - 243, + 38, + 208, + 191, + 88, + 204, + 210, + 143, + 164, + 241, 178, - 100, - 107, - 65, - 162, - 152, - 189, - 57, - 216, - 209, + 35, 61, - 42, - 215 + 136, + 222, + 125, + 75, + 118, + 15, + 229, + 217, + 229, + 13, + 97, + 94, + 19, + 200, + 52, + 115, + 126, + 208, + 219, + 38 ] } ] @@ -246,15 +246,15 @@ Response: { ] }, "json": { - "id": "0x38df3e04dd2ba3b30911b992c192381cb35af3b2646b41a298bd39d8d13d2ad7", - "f0": "0x38df3e04dd2ba3b30911b992c192381cb35af3b2646b41a298bd39d8d13d2ad7", + "id": "0x26d0bf58ccd28fa4f1b2233d88de7d4b760fe5d9e50d615e13c834737ed0db26", + "f0": "0x26d0bf58ccd28fa4f1b2233d88de7d4b760fe5d9e50d615e13c834737ed0db26", "f1": true, "f2": 42, "f3": "43", "f4": "hello", "f5": "world", "f6": [ - "0x38df3e04dd2ba3b30911b992c192381cb35af3b2646b41a298bd39d8d13d2ad7" + "0x26d0bf58ccd28fa4f1b2233d88de7d4b760fe5d9e50d615e13c834737ed0db26" ], "f7": 44, "f8": { @@ -291,38 +291,38 @@ Response: { "name": "id", "value": { "UID": [ - 74, - 63, - 69, - 149, - 223, - 0, - 225, - 254, - 133, - 114, - 233, - 29, - 11, - 223, - 12, - 229, - 83, - 83, - 236, - 108, + 242, + 188, + 8, + 146, + 91, + 93, + 199, + 88, + 48, + 87, + 226, + 103, + 228, + 118, + 197, + 119, + 77, + 235, + 253, + 112, + 65, 28, - 82, 187, - 116, - 23, - 108, - 228, - 45, - 4, - 45, - 150, - 20 + 56, + 82, + 102, + 118, + 60, + 147, + 142, + 46, + 97 ] } }, @@ -342,7 +342,7 @@ Response: { ] }, "json": { - "id": "0x4a3f4595df00e1fe8572e91d0bdf0ce55353ec6c1c52bb74176ce42d042d9614", + "id": "0xf2bc08925b5dc7583057e267e476c5774debfd70411cbb385266763c938e2e61", "balance": { "value": "299999995967600" } diff --git a/crates/sui-graphql-e2e-tests/tests/packages/datatypes.exp b/crates/sui-graphql-e2e-tests/tests/packages/datatypes.exp index e022382e6ee45..d2bbe304fc3fd 100644 --- a/crates/sui-graphql-e2e-tests/tests/packages/datatypes.exp +++ b/crates/sui-graphql-e2e-tests/tests/packages/datatypes.exp @@ -150,7 +150,7 @@ task 5 'run-graphql'. lines 72-96: Response: { "data": { "object": { - "address": "0x4ad90f4ed98d545600c66a80334410db765366c41e8e716766bd72822a77500d", + "address": "0x0a95d2ec15ae1074b8a4ab8707a4525292cc69047ad4c4a98d6482e751f9d278", "asMovePackage": { "module": { "datatypes": { @@ -184,7 +184,7 @@ task 6 'run-graphql'. lines 98-143: Response: { "data": { "object": { - "address": "0x4ad90f4ed98d545600c66a80334410db765366c41e8e716766bd72822a77500d", + "address": "0x0a95d2ec15ae1074b8a4ab8707a4525292cc69047ad4c4a98d6482e751f9d278", "asMovePackage": { "module": { "datatypes": { diff --git a/crates/sui-graphql-e2e-tests/tests/packages/enums.exp b/crates/sui-graphql-e2e-tests/tests/packages/enums.exp index b7d17815e3731..276d723ffcbe2 100644 --- a/crates/sui-graphql-e2e-tests/tests/packages/enums.exp +++ b/crates/sui-graphql-e2e-tests/tests/packages/enums.exp @@ -22,19 +22,7 @@ Response: { "nodes": [ { "outputState": { - "address": "0x53b63659f4910b0563575a85dca3254f1eb41bd6f8235cf2508ee6c18f4293ab", - "asMovePackage": null - } - }, - { - "outputState": { - "address": "0xcfe25a7e8b161ad78e604ecadb0e36787e46626bd2f8456ef76327771e685e6a", - "asMovePackage": null - } - }, - { - "outputState": { - "address": "0xe1b0f83fd53dd4e358f7fd0d7a54eca9ad604dd7dc7ff46ef35a4dd69917bebd", + "address": "0x2d9c1eb67a4b66df6a47dc2152d703a565288f2ee475270ff1ce440104dc3bf6", "asMovePackage": { "module": { "enum": { @@ -90,6 +78,18 @@ Response: { } } } + }, + { + "outputState": { + "address": "0x86977b4dfcf9e54527721bbceb6929cf8f29a913b2ef9acde85906b14f5c1401", + "asMovePackage": null + } + }, + { + "outputState": { + "address": "0x8a8a244a30cb837389ea50533ae6bbdcc6203cfd3193fb0ee1979d93fed56a5a", + "asMovePackage": null + } } ] } @@ -119,25 +119,25 @@ Response: { "nodes": [ { "outputState": { - "address": "0x53b63659f4910b0563575a85dca3254f1eb41bd6f8235cf2508ee6c18f4293ab", + "address": "0x86977b4dfcf9e54527721bbceb6929cf8f29a913b2ef9acde85906b14f5c1401", "asMovePackage": null } }, { "outputState": { - "address": "0xcfe25a7e8b161ad78e604ecadb0e36787e46626bd2f8456ef76327771e685e6a", + "address": "0x8a8a244a30cb837389ea50533ae6bbdcc6203cfd3193fb0ee1979d93fed56a5a", "asMovePackage": null } }, { "outputState": { - "address": "0xfbcdbd13ea73e8f64987b7f222043422842ccb47cee8bac7d6eeea1274954abf", + "address": "0xd42dcb64198dbe5099a4b4a2b4d7e9c95bfd8c67bf27497e0b81eca639025397", "asMovePackage": { "module": { "s": { "module": { "package": { - "address": "0xe1b0f83fd53dd4e358f7fd0d7a54eca9ad604dd7dc7ff46ef35a4dd69917bebd" + "address": "0x2d9c1eb67a4b66df6a47dc2152d703a565288f2ee475270ff1ce440104dc3bf6" } }, "name": "S", @@ -192,7 +192,7 @@ Response: { "t": { "module": { "package": { - "address": "0xfbcdbd13ea73e8f64987b7f222043422842ccb47cee8bac7d6eeea1274954abf" + "address": "0xd42dcb64198dbe5099a4b4a2b4d7e9c95bfd8c67bf27497e0b81eca639025397" } }, "name": "T", @@ -222,12 +222,12 @@ Response: { { "name": "s", "type": { - "repr": "0xe1b0f83fd53dd4e358f7fd0d7a54eca9ad604dd7dc7ff46ef35a4dd69917bebd::m::S", + "repr": "0x2d9c1eb67a4b66df6a47dc2152d703a565288f2ee475270ff1ce440104dc3bf6::m::S", "signature": { "ref": null, "body": { "datatype": { - "package": "0xe1b0f83fd53dd4e358f7fd0d7a54eca9ad604dd7dc7ff46ef35a4dd69917bebd", + "package": "0x2d9c1eb67a4b66df6a47dc2152d703a565288f2ee475270ff1ce440104dc3bf6", "module": "m", "type": "S", "typeParameters": [] @@ -261,7 +261,7 @@ Response: { { "name": "t", "type": { - "repr": "0xe1b0f83fd53dd4e358f7fd0d7a54eca9ad604dd7dc7ff46ef35a4dd69917bebd::m::T<0xe1b0f83fd53dd4e358f7fd0d7a54eca9ad604dd7dc7ff46ef35a4dd69917bebd::m::S>" + "repr": "0x2d9c1eb67a4b66df6a47dc2152d703a565288f2ee475270ff1ce440104dc3bf6::m::T<0x2d9c1eb67a4b66df6a47dc2152d703a565288f2ee475270ff1ce440104dc3bf6::m::S>" } } ] diff --git a/crates/sui-open-rpc/spec/openrpc.json b/crates/sui-open-rpc/spec/openrpc.json index a21c89e523c06..018f17bd39c95 100644 --- a/crates/sui-open-rpc/spec/openrpc.json +++ b/crates/sui-open-rpc/spec/openrpc.json @@ -1379,6 +1379,7 @@ "enable_group_ops_native_functions": false, "enable_jwk_consensus_updates": false, "enable_poseidon": false, + "enable_vdf": false, "end_of_epoch_transaction_supported": false, "hardened_otw_check": false, "include_consensus_digest_in_prologue": false, @@ -1958,7 +1959,9 @@ }, "validator_validate_metadata_data_cost_per_byte": { "u64": "2" - } + }, + "vdf_hash_to_input_cost": null, + "vdf_verify_vdf_cost": null } } } diff --git a/crates/sui-protocol-config/src/lib.rs b/crates/sui-protocol-config/src/lib.rs index 21d0b49aedd40..392595c42daf3 100644 --- a/crates/sui-protocol-config/src/lib.rs +++ b/crates/sui-protocol-config/src/lib.rs @@ -133,6 +133,7 @@ const MAX_PROTOCOL_VERSION: u64 = 48; // Resolve Move abort locations to the package id instead of the runtime module ID. // Enable random beacon in testnet. // Version 48: Enable Move enums on devnet. +// Enable VDF in devnet #[derive(Copy, Clone, Debug, Hash, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] pub struct ProtocolVersion(u64); @@ -450,6 +451,10 @@ struct FeatureFlags { // a flag as it will lead to checkpoint forks. #[serde(skip_serializing_if = "is_false")] mysticeti_use_committed_subdag_digest: bool, + + // Enable VDF + #[serde(skip_serializing_if = "is_false")] + enable_vdf: bool, } fn is_false(b: &bool) -> bool { @@ -1038,6 +1043,9 @@ pub struct ProtocolConfig { // zklogin::check_zklogin_issuer check_zklogin_issuer_cost_base: Option, + vdf_verify_vdf_cost: Option, + vdf_hash_to_input_cost: Option, + // Const params for consensus scoring decision // The scaling factor property for the MED outlier detection scoring_decision_mad_divisor: Option, @@ -1350,6 +1358,10 @@ impl ProtocolConfig { pub fn mysticeti_use_committed_subdag_digest(&self) -> bool { self.feature_flags.mysticeti_use_committed_subdag_digest } + + pub fn enable_vdf(&self) -> bool { + self.feature_flags.enable_vdf + } } #[cfg(not(msim))] @@ -1760,6 +1772,9 @@ impl ProtocolConfig { // zklogin::check_zklogin_issuer check_zklogin_issuer_cost_base: None, + vdf_verify_vdf_cost: None, + vdf_hash_to_input_cost: None, + max_size_written_objects: None, max_size_written_objects_system_tx: None, @@ -2259,6 +2274,15 @@ impl ProtocolConfig { if chain != Chain::Testnet && chain != Chain::Mainnet { cfg.move_binary_format_version = Some(7); } + + // enable vdf in devnet + if chain != Chain::Mainnet && chain != Chain::Testnet { + cfg.feature_flags.enable_vdf = true; + // Set to 30x and 2x the cost of a signature verification for now. This + // should be updated along with other native crypto functions. + cfg.vdf_verify_vdf_cost = Some(1500); + cfg.vdf_hash_to_input_cost = Some(100); + } } // Use this template when making changes: // diff --git a/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__version_48.snap b/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__version_48.snap index b7b943320e701..02f8367ed5531 100644 --- a/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__version_48.snap +++ b/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__version_48.snap @@ -54,6 +54,7 @@ feature_flags: reshare_at_same_initial_version: true resolve_abort_locations_to_package_id: true mysticeti_use_committed_subdag_digest: true + enable_vdf: true max_tx_size_bytes: 131072 max_input_objects: 2048 max_size_written_objects: 5000000 @@ -267,6 +268,8 @@ hmac_hmac_sha3_256_input_cost_per_byte: 2 hmac_hmac_sha3_256_input_cost_per_block: 2 check_zklogin_id_cost_base: 200 check_zklogin_issuer_cost_base: 200 +vdf_verify_vdf_cost: 1500 +vdf_hash_to_input_cost: 100 scoring_decision_mad_divisor: 2.3 scoring_decision_cutoff_value: 2.5 execution_version: 3 diff --git a/crates/sui-swarm-config/tests/snapshots/snapshot_tests__populated_genesis_snapshot_matches-2.snap b/crates/sui-swarm-config/tests/snapshots/snapshot_tests__populated_genesis_snapshot_matches-2.snap index 9f83ffa863588..1dde74f38315d 100644 --- a/crates/sui-swarm-config/tests/snapshots/snapshot_tests__populated_genesis_snapshot_matches-2.snap +++ b/crates/sui-swarm-config/tests/snapshots/snapshot_tests__populated_genesis_snapshot_matches-2.snap @@ -240,13 +240,13 @@ validators: next_epoch_worker_address: ~ extra_fields: id: - id: "0xb0c661436faacc2576f8e52ed34f47d8b83e7fadd493307bc0208a0b75ff3d31" + id: "0xa1ff06590dbd12f617e8f2c9d8e2e0aa66b936ddef0753ec821e3a84814cc8f0" size: 0 voting_power: 10000 - operation_cap_id: "0xaed58e45bcdb3a5a767a5e185a42712118ea000432e1596c4d089ae25bea9fa1" + operation_cap_id: "0xe1c23dae44530859cd66d5b3c4dd40f2887fb28b9791679426675fda6b0219c7" gas_price: 1000 staking_pool: - id: "0xd65fc099b2677baad81f5293db8fce1d3ab4f36bcec5180ea5fbcac9527314c1" + id: "0x35465e5265fe7f26eba1ef5cd90fd376a3db04e6c6017f06621475adacee2b26" activation_epoch: 0 deactivation_epoch: ~ sui_balance: 20000000000000000 @@ -254,14 +254,14 @@ validators: value: 0 pool_token_balance: 20000000000000000 exchange_rates: - id: "0x02a133ee415297e148857207d37cc1a3dd8d16fd5ed5d6e27d90b0af45f4034c" + id: "0xf290a4149d6a2d52c2a3ce4cc6f9ec84de672725c2fe5519de4269b53a2d9bb3" size: 1 pending_stake: 0 pending_total_sui_withdraw: 0 pending_pool_token_withdraw: 0 extra_fields: id: - id: "0x5e19f1996afaeb561a904cede5c9733e08fbcf4969430e55602ca1341046c6a6" + id: "0x2e90cb4042988b751f8d1a6592aedc3afcd8156acd8d014de080c074a1b2222e" size: 0 commission_rate: 200 next_epoch_stake: 20000000000000000 @@ -269,27 +269,27 @@ validators: next_epoch_commission_rate: 200 extra_fields: id: - id: "0xa9885026f915def336ce0a470aa4d8faf77e8fcc44e3160480f65aae237e6712" + id: "0x257c49f82dfc6f179ede2fda03e25fe73a58c97ef1d9d2d2ca77db710aed40f2" size: 0 pending_active_validators: contents: - id: "0xc4a8b7fc920b5a796b6f2d4f6893d2066aaf6fe1eb8ec0111f95e7783dde1562" + id: "0xe5f6f96f60533c64ec4f45c76604572f68920bf59ed2be37b34948003ef816c4" size: 0 pending_removals: [] staking_pool_mappings: - id: "0xe12bfe23f7b641d8d33861c4f267928ffafb913f2cee399a0942e4465ac8499c" + id: "0x6c81f9fa2cf110470cd10e3ab483ae7c619c4d8315004015686080d24c728071" size: 1 inactive_validators: - id: "0xa2cbdf8b4e759c5d4585c16b0db4053a21cbb839452eb8c0f8e68f5790412d48" + id: "0xddebffbd50a286218b14af21c40725c01506a943ed6b947c50095244a4725b92" size: 0 validator_candidates: - id: "0xb5437e5d6602194c31fb8be2507f6703cffefde03c8c5bb6a53845b23978ea57" + id: "0x73c69366fd5d9c54e27ffef93f4ad77808edfd0a943733e386a7c30c941dbb69" size: 0 at_risk_validators: contents: [] extra_fields: id: - id: "0xbf6350f26cfb2d3b9e5e34cfdd64b524a17475447e290e6dff3bdc2ebac11940" + id: "0xa830113361022b2604e40277bc1f213a7da7d94c84e7a81bf281027ebbc4d0cf" size: 0 storage_fund: total_object_storage_rebates: @@ -306,7 +306,7 @@ parameters: validator_low_stake_grace_period: 7 extra_fields: id: - id: "0x4c4a6bd6b6bf6fe19956b0bde2bda6eaec022d1dcecaa14ea2b7e0b9b43e7838" + id: "0xc3e4654ee934b89a348699087e7f541d9209dd530b707b278e7a419b01958b0e" size: 0 reference_gas_price: 1000 validator_report_records: @@ -320,7 +320,7 @@ stake_subsidy: stake_subsidy_decrease_rate: 1000 extra_fields: id: - id: "0x009afa088a20521b05b55a115e0f5cac473bacfec65423f58e74574ed1d85741" + id: "0x01152bba9266a8d45c9745e85808d002f675ea02ea2010ffc645d6ec318fbeed" size: 0 safe_mode: false safe_mode_storage_rewards: @@ -332,6 +332,6 @@ safe_mode_non_refundable_storage_fee: 0 epoch_start_timestamp_ms: 10 extra_fields: id: - id: "0x5cb39a638bbeaf07dccf4c9b3acd27f4c3e83eacc49aa05d92307b3d82bea119" + id: "0x44e0d138ebb8a4d52a7bf50ad94d3b6b3141eb68db7eb414dbac6abebc077ad6" size: 0 diff --git a/sui-execution/latest/sui-move-natives/Cargo.toml b/sui-execution/latest/sui-move-natives/Cargo.toml index 1cd8caaf0573e..9295aeeccd89c 100644 --- a/sui-execution/latest/sui-move-natives/Cargo.toml +++ b/sui-execution/latest/sui-move-natives/Cargo.toml @@ -15,6 +15,7 @@ smallvec.workspace = true rand = { workspace = true, features = ["small_rng"] } fastcrypto-zkp.workspace = true +fastcrypto-vdf.workspace = true fastcrypto.workspace = true move-binary-format.workspace = true move-core-types.workspace = true diff --git a/sui-execution/latest/sui-move-natives/src/crypto/mod.rs b/sui-execution/latest/sui-move-natives/src/crypto/mod.rs index d52776c94d45a..c77afbd81f24e 100644 --- a/sui-execution/latest/sui-move-natives/src/crypto/mod.rs +++ b/sui-execution/latest/sui-move-natives/src/crypto/mod.rs @@ -11,4 +11,5 @@ pub mod group_ops; pub mod hash; pub mod hmac; pub mod poseidon; +pub mod vdf; pub mod zklogin; diff --git a/sui-execution/latest/sui-move-natives/src/crypto/vdf.rs b/sui-execution/latest/sui-move-natives/src/crypto/vdf.rs new file mode 100644 index 0000000000000..88616e037cd56 --- /dev/null +++ b/sui-execution/latest/sui-move-natives/src/crypto/vdf.rs @@ -0,0 +1,172 @@ +// Copyright (c) Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 +use crate::object_runtime::ObjectRuntime; +use crate::NativesCostTable; +use fastcrypto_vdf::class_group::discriminant::DISCRIMINANT_3072; +use fastcrypto_vdf::class_group::QuadraticForm; +use fastcrypto_vdf::vdf::wesolowski::DefaultVDF; +use fastcrypto_vdf::vdf::VDF; +use move_binary_format::errors::PartialVMResult; +use move_core_types::gas_algebra::InternalGas; +use move_core_types::vm_status::StatusCode; +use move_vm_runtime::{native_charge_gas_early_exit, native_functions::NativeContext}; +use move_vm_types::natives::function::PartialVMError; +use move_vm_types::{ + loaded_data::runtime_types::Type, + natives::function::NativeResult, + pop_arg, + values::{Value, VectorRef}, +}; +use smallvec::smallvec; +use std::collections::VecDeque; + +pub const INVALID_INPUT_ERROR: u64 = 0; +pub const NOT_SUPPORTED_ERROR: u64 = 1; + +fn is_supported(context: &NativeContext) -> bool { + context + .extensions() + .get::() + .protocol_config + .enable_vdf() +} + +#[derive(Clone)] +pub struct VDFCostParams { + pub vdf_verify_cost: Option, + pub hash_to_input_cost: Option, +} + +/*************************************************************************************************** + * native fun vdf_verify_internal + * + * Implementation of the Move native function `vdf::verify_vdf_internal( + * input: &vector, + * output: &vector, + * proof: &vector, + * iterations: u64): bool` + * + * Gas cost: verify_vdf_cost + **************************************************************************************************/ +pub fn vdf_verify_internal( + context: &mut NativeContext, + ty_args: Vec, + mut args: VecDeque, +) -> PartialVMResult { + let cost = context.gas_used(); + if !is_supported(context) { + return Ok(NativeResult::err(cost, NOT_SUPPORTED_ERROR)); + } + + // Load the cost parameters from the protocol config + let cost_params = &context + .extensions() + .get::() + .vdf_cost_params + .clone(); + + // Charge the base cost for this operation + native_charge_gas_early_exit!( + context, + cost_params + .vdf_verify_cost + .ok_or_else( + || PartialVMError::new(StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR) + .with_message("Gas cost for vdf_verify not available".to_string()) + )? + ); + + debug_assert!(ty_args.is_empty()); + debug_assert!(args.len() == 4); + + // The input is a reference to a vector of vector's + let iterations = pop_arg!(args, u64); + let proof_bytes = pop_arg!(args, VectorRef); + let output_bytes = pop_arg!(args, VectorRef); + let input_bytes = pop_arg!(args, VectorRef); + + let input = match bcs::from_bytes::(&input_bytes.as_bytes_ref()) { + Ok(input) => input, + Err(_) => return Ok(NativeResult::err(context.gas_used(), INVALID_INPUT_ERROR)), + }; + + let proof = match bcs::from_bytes::(&proof_bytes.as_bytes_ref()) { + Ok(proof) => proof, + Err(_) => return Ok(NativeResult::err(context.gas_used(), INVALID_INPUT_ERROR)), + }; + + let output = match bcs::from_bytes::(&output_bytes.as_bytes_ref()) { + Ok(output) => output, + Err(_) => return Ok(NativeResult::err(context.gas_used(), INVALID_INPUT_ERROR)), + }; + + // We use the default VDF construction: Wesolowski's construction using a strong Fiat-Shamir + // construction and a windowed scalar multiplier to speed up the proof verification. + let vdf = DefaultVDF::new(DISCRIMINANT_3072.clone(), iterations); + let verified = vdf.verify(&input, &output, &proof).is_ok(); + + Ok(NativeResult::ok( + context.gas_used(), + smallvec![Value::bool(verified)], + )) +} + +/*************************************************************************************************** + * native fun hash_to_input_internal + * + * Implementation of the Move native function `vdf::hash_to_input_internal(message: &vector): vector` + * + * Gas cost: hash_to_input_cost + **************************************************************************************************/ +pub fn hash_to_input_internal( + context: &mut NativeContext, + ty_args: Vec, + mut args: VecDeque, +) -> PartialVMResult { + let cost = context.gas_used(); + if !is_supported(context) { + return Ok(NativeResult::err(cost, NOT_SUPPORTED_ERROR)); + } + + // Load the cost parameters from the protocol config + let cost_params = &context + .extensions() + .get::() + .vdf_cost_params + .clone(); + + // Charge the base cost for this operation + native_charge_gas_early_exit!( + context, + cost_params + .hash_to_input_cost + .ok_or_else( + || PartialVMError::new(StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR) + .with_message("Gas cost for hash_to_input not available".to_string()) + )? + ); + + debug_assert!(ty_args.is_empty()); + debug_assert!(args.len() == 1); + + let message = pop_arg!(args, VectorRef); + + let output = match QuadraticForm::hash_to_group_with_default_parameters( + &message.as_bytes_ref(), + &DISCRIMINANT_3072, + ) { + Ok(output) => output, + Err(_) => return Ok(NativeResult::err(context.gas_used(), INVALID_INPUT_ERROR)), + }; + + let output_bytes = match bcs::to_bytes(&output) { + Ok(bytes) => bytes, + // This should only fail on extremely large inputs, so we treat it as an invalid input error + Err(_) => return Ok(NativeResult::err(context.gas_used(), INVALID_INPUT_ERROR)), + }; + + Ok(NativeResult::ok( + context.gas_used(), + smallvec![Value::vector_u8(output_bytes)], + )) +} diff --git a/sui-execution/latest/sui-move-natives/src/lib.rs b/sui-execution/latest/sui-move-natives/src/lib.rs index e2ab78ea511e3..20c7ecb7f61f4 100644 --- a/sui-execution/latest/sui-move-natives/src/lib.rs +++ b/sui-execution/latest/sui-move-natives/src/lib.rs @@ -40,6 +40,7 @@ use crate::crypto::poseidon::PoseidonBN254CostParams; use crate::crypto::zklogin; use crate::crypto::zklogin::{CheckZkloginIdCostParams, CheckZkloginIssuerCostParams}; use better_any::{Tid, TidAble}; +use crypto::vdf::{self, VDFCostParams}; use move_binary_format::errors::{PartialVMError, PartialVMResult}; use move_core_types::{ annotated_value as A, @@ -152,6 +153,9 @@ pub struct NativesCostTable { // group ops pub group_ops_cost_params: GroupOpsCostParams, + // vdf + pub vdf_cost_params: VDFCostParams, + // zklogin pub check_zklogin_id_cost_params: CheckZkloginIdCostParams, pub check_zklogin_issuer_cost_params: CheckZkloginIssuerCostParams, @@ -610,6 +614,14 @@ impl NativesCostTable { .group_ops_bls12381_pairing_cost_as_option() .map(Into::into), }, + vdf_cost_params: VDFCostParams { + vdf_verify_cost: protocol_config + .vdf_verify_vdf_cost_as_option() + .map(Into::into), + hash_to_input_cost: protocol_config + .vdf_hash_to_input_cost_as_option() + .map(Into::into), + }, } } } @@ -883,6 +895,16 @@ pub fn all_natives(silent: bool) -> NativeFunctionTable { "poseidon_bn254_internal", make_native!(poseidon::poseidon_bn254_internal), ), + ( + "vdf", + "vdf_verify_internal", + make_native!(vdf::vdf_verify_internal), + ), + ( + "vdf", + "hash_to_input_internal", + make_native!(vdf::hash_to_input_internal), + ), ]; let sui_framework_natives_iter = sui_framework_natives diff --git a/sui_programmability/examples/games/sources/vdf_based_lottery.move b/sui_programmability/examples/games/sources/vdf_based_lottery.move new file mode 100644 index 0000000000000..2df7aa6c0f61c --- /dev/null +++ b/sui_programmability/examples/games/sources/vdf_based_lottery.move @@ -0,0 +1,160 @@ +// Copyright (c) Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +/// A basic lottery game that depends on user-provided randomness which is processed by a verifiable delay function (VDF) +/// to make sure that it is unbiasable. +/// +/// During the submission phase, players can buy tickets. When buying a ticket, a user must provide some randomness `r`. This +/// randomness is added to the combined randomness of the lottery, `h`, as `h = Sha2_256(h, r)`. +/// +/// After the submission phase has ended, the combined randomness is used to generate an input to the VDF. Anyone may now +/// compute the output and submit it along with a proof of correctness to the `complete` function. If the output and proof +/// verifies, the game ends, and the hash of the output is used to pick a winner. +/// +/// The outcome is guaranteed to be fair if: +/// 1) At least one player contributes true randomness, +/// 2) The number of iterations is defined such that it takes at least `submission_phase_length` to compute the VDF. +module games::vdf_based_lottery { + use games::drand_lib::safe_selection; + use sui::clock::Clock; + use std::hash::sha2_256; + use sui::vdf::{hash_to_input, vdf_verify}; + + /// Error codes + const EGameNotInProgress: u64 = 0; + const EGameAlreadyCompleted: u64 = 1; + const EInvalidTicket: u64 = 2; + const ESubmissionPhaseInProgress: u64 = 3; + const EInvalidVdfProof: u64 = 4; + const ESubmissionPhaseFinished: u64 = 5; + const EInvalidRandomness: u64 = 6; + + /// Game status + const IN_PROGRESS: u8 = 0; + const COMPLETED: u8 = 1; + + /// Other constants + const RANDOMNESS_LENGTH: u64 = 16; + + /// Game represents a set of parameters of a single game. + /// This game can be extended to require ticket purchase, reward winners, etc. + /// + public struct Game has key, store { + id: UID, + iterations: u64, + status: u8, + timestamp_start: u64, + submission_phase_length: u64, + participants: u64, + vdf_input_seed: vector, + winner: Option, + } + + /// Ticket represents a participant in a single game. + /// Can be deconstructed only by the owner. + public struct Ticket has key, store { + id: UID, + game_id: ID, + participant_index: u64, + } + + /// GameWinner represents a participant that won in a specific game. + /// Can be deconstructed only by the owner. + public struct GameWinner has key, store { + id: UID, + game_id: ID, + } + + /// Create a shared-object Game. + public fun create(iterations: u64, submission_phase_length: u64, clock: &Clock, ctx: &mut TxContext) { + let game = Game { + id: object::new(ctx), + iterations, + status: IN_PROGRESS, + timestamp_start: clock.timestamp_ms(), + submission_phase_length, + vdf_input_seed: vector::empty(), + participants: 0, + winner: option::none(), + }; + transfer::public_share_object(game); + } + + /// Anyone can participate in the game and receive a ticket. + public fun participate(self: &mut Game, my_randomness: vector, clock: &Clock, ctx: &mut TxContext): Ticket { + assert!(self.status == IN_PROGRESS, EGameNotInProgress); + assert!(clock.timestamp_ms() - self.timestamp_start < self.submission_phase_length, ESubmissionPhaseFinished); + + // Update combined randomness by concatenating the provided randomness and hashing it + assert!(my_randomness.length() == RANDOMNESS_LENGTH, EInvalidRandomness); + self.vdf_input_seed.append(my_randomness); + self.vdf_input_seed = sha2_256(self.vdf_input_seed); + + // Assign index to this participant + let participant_index = self.participants; + self.participants = self.participants + 1; + + Ticket { + id: object::new(ctx), + game_id: object::id(self), + participant_index, + } + } + + /// Complete this lottery by sending VDF output and proof for the seed created from the + /// contributed randomness. Anyone can call this. + public fun complete(self: &mut Game, vdf_output: vector, vdf_proof: vector, clock: &Clock) { + assert!(self.status != COMPLETED, EGameAlreadyCompleted); + assert!(clock.timestamp_ms() - self.timestamp_start >= self.submission_phase_length, ESubmissionPhaseInProgress); + + // Hash combined randomness to vdf input + let vdf_input = hash_to_input(&self.vdf_input_seed); + + // Verify output and proof + assert!(vdf_verify(&vdf_input, &vdf_output, &vdf_proof, self.iterations), EInvalidVdfProof); + + // The randomness is derived from the VDF output by passing it through a hash function with uniformly distributed + // output to make it uniform. Any hash function with uniformly distributed output can be used. + let randomness = sha2_256(vdf_output); + + // Set winner and mark lottery completed + self.winner = option::some(safe_selection(self.participants, &randomness)); + self.status = COMPLETED; + } + + /// The winner can redeem its ticket. + public fun redeem(self: &Game, ticket: &Ticket, ctx: &mut TxContext): GameWinner { + assert!(self.status == COMPLETED, ESubmissionPhaseInProgress); + assert!(object::id(self) == ticket.game_id, EInvalidTicket); + assert!(self.winner.contains(&ticket.participant_index), EInvalidTicket); + + GameWinner { + id: object::new(ctx), + game_id: ticket.game_id, + } + } + + // Note that a ticket can be deleted before the game was completed. + public use fun delete_ticket as Ticket.delete; + public fun delete_ticket(ticket: Ticket) { + let Ticket { id, game_id: _, participant_index: _} = ticket; + object::delete(id); + } + + public use fun delete_game_winner as GameWinner.delete; + public fun delete_game_winner(ticket: GameWinner) { + let GameWinner { id, game_id: _} = ticket; + object::delete(id); + } + + public use fun ticket_game_id as Ticket.game_id; + public fun ticket_game_id(ticket: &Ticket): &ID { + &ticket.game_id + } + + public use fun game_winner_game_id as GameWinner.game_id; + public fun game_winner_game_id(ticket: &GameWinner): &ID { + &ticket.game_id + } + +} diff --git a/sui_programmability/examples/games/tests/vdf_based_lottery_tests.move b/sui_programmability/examples/games/tests/vdf_based_lottery_tests.move new file mode 100644 index 0000000000000..61631f420d55f --- /dev/null +++ b/sui_programmability/examples/games/tests/vdf_based_lottery_tests.move @@ -0,0 +1,173 @@ +// Copyright (c) Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +#[test_only] +module games::vdf_based_lottery_tests { + use sui::test_scenario as ts; + use sui::clock; + use games::vdf_based_lottery::{Self, Game, GameWinner}; + + #[test] + #[expected_failure(abort_code = games::vdf_based_lottery::ESubmissionPhaseInProgress)] + fun test_complete_too_early() { + let user1 = @0x0; + + let mut ts = ts::begin(user1); + let mut clock = clock::create_for_testing(ts.ctx()); + + vdf_based_lottery::create(1000, 1000, &clock, ts.ctx()); + ts.next_tx(user1); + let mut game = ts.take_shared(); + + // User1 buys a ticket. + ts.next_tx(user1); + let t1 = game.participate(b"user1 randomness", &clock, ts.ctx()); + + // Increment time but still in submission phase + clock.increment_for_testing(500); + + // User1 tries to complete the lottery too early. + ts.next_tx(user1); + game.complete( + x"c0014d00b5e624fe10d1cc1e593c0ffb8c3084e49bb70efc4337640a73990bb29dfb430b55710475bcc7524c77627d8067415fffa63e0e84b1204225520fea384999719c66dbdc6e91863d99c64674af971631b56e22b7cc780765bf12d53edea1dadf566f80a62769e287a1e195596d4894b2e1360e451cbf06864762275b4d5063871d45627dea2e42ab93d5345bf172b9724216627abbf295b35a8e64e13e585bca54848a90212c9f7a3adffc25c3b87eefa7d4ab1660b523bf6410b9a9ea0e00c001327d73bebc768d150beb2a1b0de9e80c69ed594ae7787d548af44eb1e0a03616100133146c9c1202ea3a35c331864f3bfe59ffa3c88d6acb8af7a4b1b5ea842c4c4c88d415539389e614876d738d80217a3ad16d001f2de60f62b04a9d8de7ccb4716c3368f0d42e3e719dbb07bdb4355f0e5569714fbcc130f30ac7b49a5b207a444c7e00a0c27edae10c28b05f87545f337283f90c4e4ed69639683154d6a89e6589db4d18702d3a29705b434dc32e10fcbd3c62d1da20b45dba511bcecdf7c101009db7911c39f3937785dd8bd0e9db56c94777bdd867897493f82e0931e0e5facb730c3aa400f815f3d2f61de94373209dcbf9210c5e1f179b675adce2be7159238cb5f89c568004ccfc75d1b3de99a060255bcd6c9dd9a674844251ec27c48119b870f4ce63cac2081541c4269bbfa60148f9dbf2c60c76099a6538a33e88c24ce092e6aad9bdfff330470ffb87b01b666dd98e44843b41896f2be688361fe062692b441b4dd8f8ecfa96948d13daf486259bb8934cab7e9d9788da0eac7edf56", + x"c0010f1ea16b16f3fc46eb0b00a516092a6ab389e259a3013eee5e39e130702de85954b8aac435e724ad0bfd210ab7789fb91b54ac4352154f3251e0a87ccfd2c9a57d26468a384f527e129fc82b33c04b3ebbec3a99967798a95b39820c35ea015fdf4c81e143004b34b99e63462cf350689b2abdd6c3903adcbe55781d3a89c89dc571c312f9a80911a9d64884747319574b3a4ded25478e6d64b9cfb25d9c67366bc25d9ac99bcdba16665158da50a2ba179893292c4b7e76502ecaba1337d693c001fb3867669e0d4e45aa43d959dbe33c3d35b00e8414d1cf1bb9552726bb95bafa0a2c12a014a3b8fb0bd5ab9a40430ff59364b19d58d80665fee0bfee272a38c45413a3688832bf9bcacf7b5723436c120878f85ce084e72b13246ecfec7cd6a5d79e13296bbb51af785c10afe6c4f07f43a5bc711dc398271185d700b1695310d8e428ad3bc6b81a4faac2f5009b723460dbd260c940dfac06e34854d204dc779f94ab3f67847a7b90855dadc3962871c022e172e96b39a08648e045e14dad87c10102f976797f14be801a441f19771a4835640a74cf7c6ad216f18d9cdaf461bb56a897b804e053cd6cc68d659bd9f0ed985f094932d306c1bd76450bd349db3a81008d7591bc826a36583c3c361add7a8f245d18007d79704d79ae27eb08b52a44af17e2f23b441919049f061d69bac3a09c3e15074e4d75cf82f42dbff1c62ddc94fe6167ccb7265e7eab0def7d30d97be441ad763705dd30d4040815996e34643bf6d7a4f06c22aa5d6d5dd30253ea8aa59607724bb71f5425a5e7fee03b7e9fe8", + &clock + ); + + t1.delete(); + + sui::clock::destroy_for_testing(clock); + ts::return_shared(game); + ts.end(); + } + + #[test] + fun test_play_vdf_lottery() { + let user1 = @0x0; + let user2 = @0x1; + let user3 = @0x2; + let user4 = @0x3; + + let mut ts = ts::begin(user1); + let mut clock = clock::create_for_testing(ts.ctx()); + + vdf_based_lottery::create(1000, 1000, &clock, ts.ctx()); + ts.next_tx(user1); + let mut game = ts.take_shared(); + + // User1 buys a ticket. + ts.next_tx(user1); + let t1 = game.participate(b"user1 randomness", &clock, ts.ctx()); + // User2 buys a ticket. + ts.next_tx(user2); + let t2 = game.participate(b"user2 randomness", &clock, ts.ctx()); + // User3 buys a ticket + ts.next_tx(user3); + let t3 = game.participate(b"user3 randomness", &clock, ts.ctx()); + // User4 buys a ticket + ts.next_tx(user4); + let t4 = game.participate(b"user4 randomness", &clock, ts.ctx()); + + // Increment time to after submission phase has ended + clock.increment_for_testing(1000); + + // User3 completes by submitting output and proof of the VDF + ts.next_tx(user3); + game.complete( + x"c0014d00b5e624fe10d1cc1e593c0ffb8c3084e49bb70efc4337640a73990bb29dfb430b55710475bcc7524c77627d8067415fffa63e0e84b1204225520fea384999719c66dbdc6e91863d99c64674af971631b56e22b7cc780765bf12d53edea1dadf566f80a62769e287a1e195596d4894b2e1360e451cbf06864762275b4d5063871d45627dea2e42ab93d5345bf172b9724216627abbf295b35a8e64e13e585bca54848a90212c9f7a3adffc25c3b87eefa7d4ab1660b523bf6410b9a9ea0e00c001327d73bebc768d150beb2a1b0de9e80c69ed594ae7787d548af44eb1e0a03616100133146c9c1202ea3a35c331864f3bfe59ffa3c88d6acb8af7a4b1b5ea842c4c4c88d415539389e614876d738d80217a3ad16d001f2de60f62b04a9d8de7ccb4716c3368f0d42e3e719dbb07bdb4355f0e5569714fbcc130f30ac7b49a5b207a444c7e00a0c27edae10c28b05f87545f337283f90c4e4ed69639683154d6a89e6589db4d18702d3a29705b434dc32e10fcbd3c62d1da20b45dba511bcecdf7c101009db7911c39f3937785dd8bd0e9db56c94777bdd867897493f82e0931e0e5facb730c3aa400f815f3d2f61de94373209dcbf9210c5e1f179b675adce2be7159238cb5f89c568004ccfc75d1b3de99a060255bcd6c9dd9a674844251ec27c48119b870f4ce63cac2081541c4269bbfa60148f9dbf2c60c76099a6538a33e88c24ce092e6aad9bdfff330470ffb87b01b666dd98e44843b41896f2be688361fe062692b441b4dd8f8ecfa96948d13daf486259bb8934cab7e9d9788da0eac7edf56", + x"c0010f1ea16b16f3fc46eb0b00a516092a6ab389e259a3013eee5e39e130702de85954b8aac435e724ad0bfd210ab7789fb91b54ac4352154f3251e0a87ccfd2c9a57d26468a384f527e129fc82b33c04b3ebbec3a99967798a95b39820c35ea015fdf4c81e143004b34b99e63462cf350689b2abdd6c3903adcbe55781d3a89c89dc571c312f9a80911a9d64884747319574b3a4ded25478e6d64b9cfb25d9c67366bc25d9ac99bcdba16665158da50a2ba179893292c4b7e76502ecaba1337d693c001fb3867669e0d4e45aa43d959dbe33c3d35b00e8414d1cf1bb9552726bb95bafa0a2c12a014a3b8fb0bd5ab9a40430ff59364b19d58d80665fee0bfee272a38c45413a3688832bf9bcacf7b5723436c120878f85ce084e72b13246ecfec7cd6a5d79e13296bbb51af785c10afe6c4f07f43a5bc711dc398271185d700b1695310d8e428ad3bc6b81a4faac2f5009b723460dbd260c940dfac06e34854d204dc779f94ab3f67847a7b90855dadc3962871c022e172e96b39a08648e045e14dad87c10102f976797f14be801a441f19771a4835640a74cf7c6ad216f18d9cdaf461bb56a897b804e053cd6cc68d659bd9f0ed985f094932d306c1bd76450bd349db3a81008d7591bc826a36583c3c361add7a8f245d18007d79704d79ae27eb08b52a44af17e2f23b441919049f061d69bac3a09c3e15074e4d75cf82f42dbff1c62ddc94fe6167ccb7265e7eab0def7d30d97be441ad763705dd30d4040815996e34643bf6d7a4f06c22aa5d6d5dd30253ea8aa59607724bb71f5425a5e7fee03b7e9fe8", + &clock + ); + + // User1 is the winner since the mod of the hash results in 0. + ts.next_tx(user1); + assert!(!ts::has_most_recent_for_address(user1), 1); + let winner = game.redeem(&t1, ts.ctx()); + + // Make sure User1 now has a winner ticket for the right game id. + ts.next_tx(user1); + assert!(winner.game_id() == t1.game_id(), 1); + + t1.delete(); + t2.delete(); + t3.delete(); + t4.delete(); + winner.delete(); + + clock.destroy_for_testing(); + ts::return_shared(game); + ts.end(); + } + + #[test] + #[expected_failure(abort_code = games::vdf_based_lottery::EInvalidVdfProof)] + fun test_invalid_vdf_output() { + let user1 = @0x0; + let user2 = @0x1; + let user3 = @0x2; + let user4 = @0x3; + + let mut ts = ts::begin(user1); + let mut clock = clock::create_for_testing(ts.ctx()); + + vdf_based_lottery::create(1000, 1000, &clock, ts.ctx()); + ts.next_tx(user1); + let mut game = ts.take_shared(); + + // User1 buys a ticket. + ts.next_tx(user1); + let t1 = game.participate(b"user1 randomness", &clock, ts.ctx()); + // User2 buys a ticket. + ts.next_tx(user2); + let t2 = game.participate(b"user2 randomness", &clock, ts.ctx()); + // User3 buys a ticket + ts.next_tx(user3); + let t3 = game.participate(b"user3 randomness", &clock, ts.ctx()); + // User4 buys a ticket + ts.next_tx(user4); + let t4 = game.participate(b"user4 randomness", &clock, ts.ctx()); + + // Increment time to after submission phase has ended + clock.increment_for_testing(1000); + + // User3 completes by submitting output and proof of the VDF + ts.next_tx(user3); + game.complete( + x"c001503be6eff558a40ba145da5aa9d1270367f32cde44c1601846cdd3d0911abce8ab6adb6b82682b45107545e9ae1efca44dd6f3ba8d95a687652b94f479f6b1a37156c44194d6bc5f266098b75251b12de6fa67de6aea14250c0481694db5f24db5e3c89da3354aafc10c4bd0371f9a175d1b5b193190c4c1089ed7a95dc07f1ce29021b55f3aaa7eb65725d61277f0996b783c005a919ba121d81f211f63d188ac525056235504fe4858765dc6498362d98e8540287a0ff78424c18de53abe46c0014f847bd49f599960fe3c3b7cfc571cd854c7d21b0e9984070f7e168c872a6e6480d8fd37d30602f57a237b83ae961e6a4acb94b78c32d04f06058bda037d6ad313c81f823db25c53c265b02a29008f727f95010c82b0cf8745e77a7f4000dac929ba83a4594482b4e6ff59c93a78df5c816f244914329c145e288fd3fd4800a1cc2df23f386112e569608e6de40ee65fe870960b4e3fee4bb188d8db0dd5df3c2384eb24a797eb20cf8524d563663ccde866a405e2713cfafdb760e50c77a797c10100a31fc5ca0a91aa788d5f5df17a1433f1a0e6e4da440ce935b1b48dc6868c8fc00d7ee725ce21797a6c4440af02570466081479e99eee1a5b509a3e1ac2e000ed386c35d9fadd130df2a292fa5f9aa2c195c48c9d11e58ac98c8dbd2169721ed2d2c9f5544de17deeaa9655360ed7baa46820f5e008af1e3f028d819dee3fee50ab55b266385dfc8f65f7f0c1b6149e5295bfefb83b14db3a30b2cefd1495ba4e5ae39d2b729f9644fc28764d03243fad3e61145ed83cbf2708b60c0b7cac7148", + x"0101010180032cf35709e1301d02b40a0dbe3dadfe6ec1eeba8fb8060a1decd0c7a126ea3f27fadcad81435601b0e0abca5c89173ef639e5a88043aa29801e6799e430b509e479b57af981f9ddd48d3a8d5919f99258081557a08270bb441233c78030a01e03ec199b5e3eef5ccc9b1a3d4841cbe4ff529c22a8cd1b1b0075338d864e3890942df6b007d2c3e3a8ef1ce7490c6bbec5372adfcbf8704a1ffc9a69db8d9cdc54762f019036e450e457325eef74b794f3f16ff327d68079a5b9de49163d7323937374f8a785a8f9afe84d6a71b336e4de00f239ee3af1d7604a3985e610e1603bd0e1a4998e19fa0c8920ffd8d61b0a87eeee50ac7c03ff7c4708a34f3bc92fd0103758c954ee34032cee2c78ad8cdc79a35dbc810196b7bf6833e1c45c83b09c0d1b78bc6f8753e10770e7045b08d50b4aa16a75b27a096d5ec1331f1fd0a44e95a8737c20240c90307b5497d3470393c2a00da0649e86d13e820591296c644fc1eef9e7c6ca4967c5e19df3153cd7fbd598c271e11c10397349ddc8cc8452ec", + &clock + ); + + t1.delete(); + t2.delete(); + t3.delete(); + t4.delete(); + + clock.destroy_for_testing(); + ts::return_shared(game); + ts.end(); + } + + #[test] + #[expected_failure(abort_code = games::vdf_based_lottery::EInvalidRandomness)] + fun test_empty_randomness() { + let user1 = @0x0; + + let mut ts = ts::begin(user1); + let clock = clock::create_for_testing(ts.ctx()); + + vdf_based_lottery::create(1000, 1000, &clock, ts.ctx()); + ts.next_tx(user1); + let mut game = ts.take_shared(); + + // User1 buys a ticket, but with wrong randomness length. + ts.next_tx(user1); + let t1 = game.participate(b"abcd", &clock, ts.ctx()); + + t1.delete(); + + sui::clock::destroy_for_testing(clock); + ts::return_shared(game); + ts.end(); + } +} From 60aed80bd7bb1b1a853295ca5f5477d64e34ddf6 Mon Sep 17 00:00:00 2001 From: Andrew Schran Date: Mon, 27 May 2024 23:14:27 -0400 Subject: [PATCH 006/324] Move DKG message size limit check into SuiTxValidator (#17735) --- .../authority/authority_per_epoch_store.rs | 40 ++++++------------- crates/sui-core/src/consensus_validator.rs | 22 ++++++++-- crates/sui-types/src/error.rs | 2 + 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/crates/sui-core/src/authority/authority_per_epoch_store.rs b/crates/sui-core/src/authority/authority_per_epoch_store.rs index db53337e24947..9bbd3f4a30deb 100644 --- a/crates/sui-core/src/authority/authority_per_epoch_store.rs +++ b/crates/sui-core/src/authority/authority_per_epoch_store.rs @@ -3283,22 +3283,13 @@ impl AuthorityPerEpochStore { "Received RandomnessDkgMessage from {:?}", authority.concise() ); - if bytes.len() > dkg::DKG_MESSAGES_MAX_SIZE { - warn!( - "Ignoring RandomnessDkgMessage from {:?} because it is too large", - authority.concise() - ); - } else { - match bcs::from_bytes(bytes) { - Ok(message) => { - randomness_manager.add_message(authority, message)? - } - Err(e) => { - warn!( + match bcs::from_bytes(bytes) { + Ok(message) => randomness_manager.add_message(authority, message)?, + Err(e) => { + warn!( "Failed to deserialize RandomnessDkgMessage from {:?}: {e:?}", authority.concise(), ); - } } } } else { @@ -3325,24 +3316,17 @@ impl AuthorityPerEpochStore { "Received RandomnessDkgConfirmation from {:?}", authority.concise() ); - if bytes.len() > dkg::DKG_MESSAGES_MAX_SIZE { - warn!( - "Ignoring RandomnessDkgConfirmation from {:?} because it is too large", - authority.concise() - ); - } else { - match bcs::from_bytes(bytes) { - Ok(confirmation) => randomness_manager.add_confirmation( - batch, - authority, - confirmation, - )?, - Err(e) => { - warn!( + match bcs::from_bytes(bytes) { + Ok(confirmation) => randomness_manager.add_confirmation( + batch, + authority, + confirmation, + )?, + Err(e) => { + warn!( "Failed to deserialize RandomnessDkgMessage from {:?}: {e:?}", authority.concise(), ); - } } } } else { diff --git a/crates/sui-core/src/consensus_validator.rs b/crates/sui-core/src/consensus_validator.rs index f8271ced94aa0..9f7c55d994200 100644 --- a/crates/sui-core/src/consensus_validator.rs +++ b/crates/sui-core/src/consensus_validator.rs @@ -5,12 +5,16 @@ use std::sync::Arc; use consensus_core::{TransactionVerifier, ValidationError}; use eyre::WrapErr; +use fastcrypto_tbls::dkg; use mysten_metrics::monitored_scope; use narwhal_types::{validate_batch_version, BatchAPI}; use narwhal_worker::TransactionValidator; use prometheus::{register_int_counter_with_registry, IntCounter, Registry}; use sui_protocol_config::ProtocolConfig; -use sui_types::messages_consensus::{ConsensusTransaction, ConsensusTransactionKind}; +use sui_types::{ + error::SuiError, + messages_consensus::{ConsensusTransaction, ConsensusTransactionKind}, +}; use tap::TapFallible; use tracing::{info, warn}; @@ -69,12 +73,22 @@ impl SuiTxValidator { ckpt_messages.push(signature.clone()); ckpt_batch.push(signature.summary); } + ConsensusTransactionKind::RandomnessDkgMessage(_, bytes) => { + if bytes.len() > dkg::DKG_MESSAGES_MAX_SIZE { + warn!("batch verification error: DKG Message too large"); + return Err(SuiError::InvalidDkgMessageSize.into()); + } + } + ConsensusTransactionKind::RandomnessDkgConfirmation(_, bytes) => { + if bytes.len() > dkg::DKG_MESSAGES_MAX_SIZE { + warn!("batch verification error: DKG Confirmation too large"); + return Err(SuiError::InvalidDkgMessageSize.into()); + } + } ConsensusTransactionKind::EndOfPublish(_) | ConsensusTransactionKind::CapabilityNotification(_) | ConsensusTransactionKind::NewJWKFetched(_, _, _) - | ConsensusTransactionKind::RandomnessStateUpdate(_, _) - | ConsensusTransactionKind::RandomnessDkgMessage(_, _) - | ConsensusTransactionKind::RandomnessDkgConfirmation(_, _) => {} + | ConsensusTransactionKind::RandomnessStateUpdate(_, _) => {} } } diff --git a/crates/sui-types/src/error.rs b/crates/sui-types/src/error.rs index 3e37304353644..a68d8c6537138 100644 --- a/crates/sui-types/src/error.rs +++ b/crates/sui-types/src/error.rs @@ -407,6 +407,8 @@ pub enum SuiError { #[error("Invalid digest length. Expected {expected}, got {actual}")] InvalidDigestLength { expected: usize, actual: usize }, + #[error("Invalid DKG message size")] + InvalidDkgMessageSize, #[error("Unexpected message.")] UnexpectedMessage, From 71c997eee711b64c0a6c198fa683be5cdee38bff Mon Sep 17 00:00:00 2001 From: Anastasios Kichidis Date: Tue, 28 May 2024 15:47:01 +0100 Subject: [PATCH 007/324] [Consensus 2.0] Small refactoring in scores for CommittedSubDag (#17768) ## Description Initialise the consensus scores in committed sub dag during construction. Also always pre-sort the blocks , that should be the default anyways either during commit or recover. ## Test plan CI --- ## Release notes Check each box that your changes affect. If none of the boxes relate to your changes, release notes aren't required. For each box you select, include information after the relevant heading that describes the impact of your changes that a user might notice and any actions they must take to implement updates. - [ ] Protocol: - [ ] Nodes (Validators and Full nodes): - [ ] Indexer: - [ ] JSON-RPC: - [ ] GraphQL: - [ ] CLI: - [ ] Rust SDK: --- consensus/core/src/commit.rs | 12 +-- consensus/core/src/commit_observer.rs | 37 +++----- consensus/core/src/core.rs | 3 +- consensus/core/src/dag_state.rs | 7 +- consensus/core/src/leader_schedule.rs | 14 ++- consensus/core/src/leader_scoring.rs | 1 + consensus/core/src/linearizer.rs | 126 +++++++++++++++++++++++-- consensus/core/src/test_dag_builder.rs | 1 + 8 files changed, 156 insertions(+), 45 deletions(-) diff --git a/consensus/core/src/commit.rs b/consensus/core/src/commit.rs index 7913f4686ed94..919491590a676 100644 --- a/consensus/core/src/commit.rs +++ b/consensus/core/src/commit.rs @@ -312,19 +312,16 @@ impl CommittedSubDag { blocks: Vec, timestamp_ms: BlockTimestampMs, commit_ref: CommitRef, + reputation_scores_desc: Vec<(AuthorityIndex, u64)>, ) -> Self { Self { leader, blocks, timestamp_ms, commit_ref, - reputation_scores_desc: vec![], + reputation_scores_desc, } } - - pub(crate) fn update_scores(&mut self, reputation_scores_desc: Vec<(AuthorityIndex, u64)>) { - self.reputation_scores_desc = reputation_scores_desc; - } } // Sort the blocks of the sub-dag blocks by round number then authority index. Any @@ -372,6 +369,7 @@ impl fmt::Debug for CommittedSubDag { pub fn load_committed_subdag_from_store( store: &dyn Store, commit: TrustedCommit, + reputation_scores_desc: Vec<(AuthorityIndex, u64)>, ) -> CommittedSubDag { let mut leader_block_idx = None; let commit_blocks = store @@ -396,6 +394,7 @@ pub fn load_committed_subdag_from_store( blocks, commit.timestamp_ms(), commit.reference(), + reputation_scores_desc, ) } @@ -668,7 +667,7 @@ mod tests { leader_ref, blocks.clone(), ); - let subdag = load_committed_subdag_from_store(store.as_ref(), commit.clone()); + let subdag = load_committed_subdag_from_store(store.as_ref(), commit.clone(), vec![]); assert_eq!(subdag.leader, leader_ref); assert_eq!(subdag.timestamp_ms, leader_block.timestamp_ms()); assert_eq!( @@ -676,6 +675,7 @@ mod tests { (num_authorities * wave_length) as usize + 1 ); assert_eq!(subdag.commit_ref, commit.reference()); + assert_eq!(subdag.reputation_scores_desc, vec![]); } #[tokio::test] diff --git a/consensus/core/src/commit_observer.rs b/consensus/core/src/commit_observer.rs index 5242efb3efa03..4f46a47964f5c 100644 --- a/consensus/core/src/commit_observer.rs +++ b/consensus/core/src/commit_observer.rs @@ -50,7 +50,7 @@ impl CommitObserver { ) -> Self { let mut observer = Self { context, - commit_interpreter: Linearizer::new(dag_state.clone()), + commit_interpreter: Linearizer::new(dag_state.clone(), leader_schedule.clone()), sender: commit_consumer.sender, store, leader_schedule, @@ -74,17 +74,7 @@ impl CommitObserver { let committed_sub_dags = self.commit_interpreter.handle_commit(committed_leaders); let mut sent_sub_dags = vec![]; - let reputation_scores_desc = self - .leader_schedule - .leader_swap_table - .read() - .reputation_scores_desc - .clone(); - for mut committed_sub_dag in committed_sub_dags.into_iter() { - // TODO: Only update scores after a leader schedule change - // On handle commit the current scores that were used to elect the - // leader of the subdag will be added to the subdag and sent to sui. - committed_sub_dag.update_scores(reputation_scores_desc.clone()); + for committed_sub_dag in committed_sub_dags.into_iter() { // Failures in sender.send() are assumed to be permanent if let Err(err) = self.sender.send(committed_sub_dag.clone()) { tracing::error!( @@ -134,21 +124,22 @@ impl CommitObserver { for (index, commit) in unsent_commits.into_iter().enumerate() { // Commit index must be continuous. assert_eq!(commit.index(), last_sent_commit_index + 1); - let mut committed_sub_dag = - load_committed_subdag_from_store(self.store.as_ref(), commit); // On recovery leader schedule will be updated with the current scores // and the scores will be passed along with the last commit sent to // sui so that the current scores are available for submission. - if index == num_unsent_commits - 1 { - committed_sub_dag.update_scores( - self.leader_schedule - .leader_swap_table - .read() - .reputation_scores_desc - .clone(), - ); - } + let reputation_scores = if index == num_unsent_commits - 1 { + self.leader_schedule + .leader_swap_table + .read() + .reputation_scores_desc + .clone() + } else { + vec![] + }; + + let committed_sub_dag = + load_committed_subdag_from_store(self.store.as_ref(), commit, reputation_scores); self.sender.send(committed_sub_dag).unwrap_or_else(|e| { panic!( "Failed to send commit during recovery, probably due to shutdown: {:?}", diff --git a/consensus/core/src/core.rs b/consensus/core/src/core.rs index 2a4e74c8ca918..54e35e1707c68 100644 --- a/consensus/core/src/core.rs +++ b/consensus/core/src/core.rs @@ -484,8 +484,7 @@ impl Core { tracing::info!( "Leader schedule change triggered at commit index {last_commit_index}" ); - self.leader_schedule - .update_leader_schedule(self.dag_state.clone()); + self.leader_schedule.update_leader_schedule(&self.dag_state); commits_until_update = self .leader_schedule .commits_until_leader_schedule_update(self.dag_state.clone()); diff --git a/consensus/core/src/dag_state.rs b/consensus/core/src/dag_state.rs index e9fad75068666..2dd50189f360f 100644 --- a/consensus/core/src/dag_state.rs +++ b/consensus/core/src/dag_state.rs @@ -129,8 +129,11 @@ impl DagState { .protocol_config .mysticeti_leader_scoring_and_schedule() { - let committed_subdag = - load_committed_subdag_from_store(store.as_ref(), commit.clone()); + let committed_subdag = load_committed_subdag_from_store( + store.as_ref(), + commit.clone(), + vec![], + ); // We don't need to recover reputation scores for unscored_committed_subdags unscored_committed_subdags.push(committed_subdag); } }); diff --git a/consensus/core/src/leader_schedule.rs b/consensus/core/src/leader_schedule.rs index c123e280f6b29..64426096197db 100644 --- a/consensus/core/src/leader_schedule.rs +++ b/consensus/core/src/leader_schedule.rs @@ -114,7 +114,15 @@ impl LeaderSchedule { .unwrap() as usize } - pub(crate) fn update_leader_schedule(&self, dag_state: Arc>) { + /// Checks whether the dag state unscored sub dags list is empty. If yes then that means that + /// either (1) the system has just started and there is no unscored sub dag available (2) the + /// schedule has updated - new scores have been calculated. Both cases we consider as valid cases + /// where the schedule has been updated. + pub(crate) fn leader_schedule_updated(&self, dag_state: &RwLock) -> bool { + dag_state.read().unscored_committed_subdags_count() == 0 + } + + pub(crate) fn update_leader_schedule(&self, dag_state: &RwLock) { let _s = self .context .metrics @@ -841,6 +849,7 @@ mod tests { vec![], context.clock.timestamp_utc_ms(), CommitRef::new(1, CommitDigest::MIN), + vec![], )]; dag_state .write() @@ -938,6 +947,7 @@ mod tests { blocks, context.clock.timestamp_utc_ms(), last_commit.reference(), + vec![], )]; let mut dag_state_write = dag_state.write(); @@ -950,7 +960,7 @@ mod tests { AuthorityIndex::new_for_test(0) ); - leader_schedule.update_leader_schedule(dag_state.clone()); + leader_schedule.update_leader_schedule(&dag_state); let leader_swap_table = leader_schedule.leader_swap_table.read(); assert_eq!(leader_swap_table.good_nodes.len(), 1); diff --git a/consensus/core/src/leader_scoring.rs b/consensus/core/src/leader_scoring.rs index c5e6a2491f326..4fb7cb20f8762 100644 --- a/consensus/core/src/leader_scoring.rs +++ b/consensus/core/src/leader_scoring.rs @@ -441,6 +441,7 @@ mod tests { blocks, context.clock.timestamp_utc_ms(), CommitRef::new(1, CommitDigest::MIN), + vec![], )]; let scoring_strategy = VoteScoringStrategy {}; let mut calculator = diff --git a/consensus/core/src/linearizer.rs b/consensus/core/src/linearizer.rs index 0ca20527a8f58..1267a6e579116 100644 --- a/consensus/core/src/linearizer.rs +++ b/consensus/core/src/linearizer.rs @@ -3,9 +3,11 @@ use std::{collections::HashSet, sync::Arc}; +use consensus_config::AuthorityIndex; use parking_lot::RwLock; use crate::commit::sort_sub_dag_blocks; +use crate::leader_schedule::LeaderSchedule; use crate::{ block::{BlockAPI, VerifiedBlock}, commit::{Commit, CommittedSubDag, TrustedCommit}, @@ -17,11 +19,18 @@ use crate::{ pub(crate) struct Linearizer { /// In memory block store representing the dag state dag_state: Arc>, + leader_schedule: Arc, } impl Linearizer { - pub(crate) fn new(dag_state: Arc>) -> Self { - Self { dag_state } + pub(crate) fn new( + dag_state: Arc>, + leader_schedule: Arc, + ) -> Self { + Self { + dag_state, + leader_schedule, + } } /// Collect the sub-dag and the corresponding commit from a specific leader excluding any duplicates or @@ -29,6 +38,7 @@ impl Linearizer { fn collect_sub_dag_and_commit( &mut self, leader_block: VerifiedBlock, + reputation_scores_desc: Vec<(AuthorityIndex, u64)>, ) -> (CommittedSubDag, TrustedCommit) { // Grab latest commit state from dag state let dag_state = self.dag_state.read(); @@ -100,6 +110,7 @@ impl Linearizer { to_commit, timestamp_ms, commit.reference(), + reputation_scores_desc, ); (sub_dag, commit) @@ -112,10 +123,31 @@ impl Linearizer { &mut self, committed_leaders: Vec, ) -> Vec { + if committed_leaders.is_empty() { + return vec![]; + } + + // We check whether the leader schedule has been updated. If yes, then we'll send the scores as + // part of the first sub dag. + let schedule_updated = self + .leader_schedule + .leader_schedule_updated(&self.dag_state); + let mut committed_sub_dags = vec![]; - for leader_block in committed_leaders { + for (i, leader_block) in committed_leaders.into_iter().enumerate() { + let reputation_scores_desc = if schedule_updated && i == 0 { + self.leader_schedule + .leader_swap_table + .read() + .reputation_scores_desc + .clone() + } else { + vec![] + }; + // Collect the sub-dag generated using each of these leaders and the corresponding commit. - let (sub_dag, commit) = self.collect_sub_dag_and_commit(leader_block); + let (sub_dag, commit) = + self.collect_sub_dag_and_commit(leader_block, reputation_scores_desc); // Buffer commit in dag state for persistence later. // This also updates the last committed rounds. @@ -129,9 +161,8 @@ impl Linearizer { // Commit metadata can be persisted more lazily because they are recoverable. Uncommitted // blocks can wait to persist too. // But for simplicity, all unpersisted blocks and commits are flushed to storage. - if !committed_sub_dags.is_empty() { - self.dag_state.write().flush(); - } + self.dag_state.write().flush(); + committed_sub_dags } } @@ -157,7 +188,11 @@ mod tests { context.clone(), Arc::new(MemStore::new()), ))); - let mut linearizer = Linearizer::new(dag_state.clone()); + let leader_schedule = Arc::new(LeaderSchedule::new( + context.clone(), + LeaderSwapTable::default(), + )); + let mut linearizer = Linearizer::new(dag_state.clone(), leader_schedule); // Populate fully connected test blocks for round 0 ~ 10, authorities 0 ~ 3. let num_rounds: u32 = 10; @@ -193,6 +228,74 @@ mod tests { } } + #[tokio::test] + async fn test_handle_commit_with_schedule_update() { + telemetry_subscribers::init_for_testing(); + let num_authorities = 4; + let context = Arc::new(Context::new_for_test(num_authorities).0); + let dag_state = Arc::new(RwLock::new(DagState::new( + context.clone(), + Arc::new(MemStore::new()), + ))); + const NUM_OF_COMMITS_PER_SCHEDULE: u64 = 10; + let leader_schedule = Arc::new( + LeaderSchedule::new(context.clone(), LeaderSwapTable::default()) + .with_num_commits_per_schedule(NUM_OF_COMMITS_PER_SCHEDULE), + ); + let mut linearizer = Linearizer::new(dag_state.clone(), leader_schedule.clone()); + + // Populate fully connected test blocks for round 0 ~ 20, authorities 0 ~ 3. + let num_rounds: u32 = 20; + let mut dag_builder = DagBuilder::new(context.clone()); + dag_builder + .layers(1..=num_rounds) + .build() + .persist_layers(dag_state.clone()); + + // Take the first 10 leaders + let leaders = dag_builder + .leader_blocks(1..=10) + .into_iter() + .map(Option::unwrap) + .collect::>(); + + // Create some commits + let commits = linearizer.handle_commit(leaders.clone()); + + // Write them in DagState + dag_state.write().add_unscored_committed_subdags(commits); + + // Now update the leader schedule + leader_schedule.update_leader_schedule(&dag_state); + + assert!( + leader_schedule.leader_schedule_updated(&dag_state), + "Leader schedule should have been updated" + ); + + // Try to commit now the rest of the 10 leaders + let leaders = dag_builder + .leader_blocks(11..=20) + .into_iter() + .map(Option::unwrap) + .collect::>(); + + // Now on the commits only the first one should contain the updated scores, the other should be empty + let commits = linearizer.handle_commit(leaders.clone()); + assert_eq!(commits.len(), 10); + let scores = vec![ + (AuthorityIndex::new_for_test(2), 9), + (AuthorityIndex::new_for_test(1), 8), + (AuthorityIndex::new_for_test(0), 8), + (AuthorityIndex::new_for_test(3), 8), + ]; + assert_eq!(commits[0].reputation_scores_desc, scores); + + for commit in commits.into_iter().skip(1) { + assert_eq!(commit.reputation_scores_desc, vec![]); + } + } + #[tokio::test] async fn test_handle_already_committed() { telemetry_subscribers::init_for_testing(); @@ -202,8 +305,11 @@ mod tests { context.clone(), Arc::new(MemStore::new()), ))); - let leader_schedule = LeaderSchedule::new(context.clone(), LeaderSwapTable::default()); - let mut linearizer = Linearizer::new(dag_state.clone()); + let leader_schedule = Arc::new(LeaderSchedule::new( + context.clone(), + LeaderSwapTable::default(), + )); + let mut linearizer = Linearizer::new(dag_state.clone(), leader_schedule.clone()); let wave_length = DEFAULT_WAVE_LENGTH; let leader_round_wave_1 = 3; diff --git a/consensus/core/src/test_dag_builder.rs b/consensus/core/src/test_dag_builder.rs index 0dc8a81cdacbb..d1d05da728071 100644 --- a/consensus/core/src/test_dag_builder.rs +++ b/consensus/core/src/test_dag_builder.rs @@ -178,6 +178,7 @@ impl DagBuilder { to_commit, timestamp_ms, commit.reference(), + vec![], ); (sub_dag, commit) From da973038d6a1e06846309ec2044520b94669c7b6 Mon Sep 17 00:00:00 2001 From: Xun Li Date: Tue, 28 May 2024 07:54:39 -0700 Subject: [PATCH 008/324] [core] Cleanup protocol version cheecks in transaction validity check (#17530) ## Description This PR consolidates protocol version support checks on transactions during validity check. Specifically, it breaks down the protocol config version checks from authority_server into two pieces: 1. User signature related version checks. These are moved to a single function and called from validity_chec(). 2. Transaction data related version checks. This is the randomness check, and is moved to check_version_supported() of TransactionData. One notable change is that the randomness check now only checks the protocol config feature, without checking whether the randomness object exists. I believe this is fine because if the randomness object does not exist, it will fail latter when loading input objects anyway. But worth double check @aschran ## Test plan CI --- ## Release notes Check each box that your changes affect. If none of the boxes relate to your changes, release notes aren't required. For each box you select, include information after the relevant heading that describes the impact of your changes that a user might notice and any actions they must take to implement updates. - [ ] Protocol: - [ ] Nodes (Validators and Full nodes): - [ ] Indexer: - [ ] JSON-RPC: - [ ] GraphQL: - [ ] CLI: - [ ] Rust SDK: --- crates/sui-core/src/authority.rs | 6 +-- .../authority/authority_per_epoch_store.rs | 7 ++- crates/sui-core/src/authority_server.rs | 40 ++++------------ crates/sui-core/src/consensus_handler.rs | 2 +- crates/sui-transaction-checks/src/lib.rs | 2 +- crates/sui-types/src/effects/mod.rs | 2 +- crates/sui-types/src/message_envelope.rs | 10 ++-- crates/sui-types/src/transaction.rs | 48 +++++++++++++------ 8 files changed, 60 insertions(+), 57 deletions(-) diff --git a/crates/sui-core/src/authority.rs b/crates/sui-core/src/authority.rs index 27a487921522d..ed095b7f114fe 100644 --- a/crates/sui-core/src/authority.rs +++ b/crates/sui-core/src/authority.rs @@ -1517,7 +1517,7 @@ impl AuthorityState { // Cheap validity checks for a transaction, including input size limits. let tx_data = certificate.data().transaction_data(); - tx_data.check_version_supported(epoch_store.protocol_config())?; + tx_data.check_version_and_features_supported(epoch_store.protocol_config())?; tx_data.validity_check(epoch_store.protocol_config())?; // The cost of partially re-auditing a transaction before execution is tolerated. @@ -1645,7 +1645,7 @@ impl AuthorityState { Option, )> { // Cheap validity checks for a transaction, including input size limits. - transaction.check_version_supported(epoch_store.protocol_config())?; + transaction.check_version_and_features_supported(epoch_store.protocol_config())?; transaction.validity_check_no_gas_check(epoch_store.protocol_config())?; let input_object_kinds = transaction.input_objects()?; @@ -1865,7 +1865,7 @@ impl AuthorityState { vec![] }; - transaction.check_version_supported(protocol_config)?; + transaction.check_version_and_features_supported(protocol_config)?; transaction.validity_check_no_gas_check(protocol_config)?; let input_object_kinds = transaction.input_objects()?; diff --git a/crates/sui-core/src/authority/authority_per_epoch_store.rs b/crates/sui-core/src/authority/authority_per_epoch_store.rs index 9bbd3f4a30deb..b2a2eea984cb3 100644 --- a/crates/sui-core/src/authority/authority_per_epoch_store.rs +++ b/crates/sui-core/src/authority/authority_per_epoch_store.rs @@ -1605,7 +1605,7 @@ impl AuthorityPerEpochStore { if !dkg_failed && !generating_randomness && self.randomness_state_enabled() - && cert.uses_randomness() + && cert.transaction_data().uses_randomness() { let deferred_from_round = previously_deferred_tx_digests .get(cert.digest()) @@ -3185,7 +3185,10 @@ impl AuthorityPerEpochStore { return Ok(deferral_result); } - if dkg_failed && self.randomness_state_enabled() && certificate.uses_randomness() { + if dkg_failed + && self.randomness_state_enabled() + && certificate.transaction_data().uses_randomness() + { // TODO: Cancel these immediately instead of waiting until end of epoch. debug!( "Ignoring randomness-using certificate for transaction {:?} because DKG failed", diff --git a/crates/sui-core/src/authority_server.rs b/crates/sui-core/src/authority_server.rs index 39db2d5bfa68b..f4a4c82c64428 100644 --- a/crates/sui-core/src/authority_server.rs +++ b/crates/sui-core/src/authority_server.rs @@ -333,7 +333,7 @@ impl ValidatorService { // CRITICAL: DO NOT ADD ANYTHING BEFORE THIS CHECK. // This must be the first thing to check before anything else, because the transaction // may not even be valid to access for any other checks. - Self::transaction_validity_check(&epoch_store, transaction.data())?; + transaction.validity_check(epoch_store.protocol_config(), epoch_store.epoch())?; // When authority is overloaded and decide to reject this tx, we still lock the object // and ask the client to retry in the future. This is because without locking, the @@ -568,10 +568,6 @@ impl ValidatorService { ) -> Result, tonic::Status> { let epoch_store = self.state.load_epoch_store_one_call_per_task(); let certificate = request.into_inner(); - // CRITICAL: DO NOT ADD ANYTHING BEFORE THIS CHECK. - // This must be the first thing to check before anything else, because the transaction - // may not even be valid to access for any other checks. - // We need to check this first because we haven't verified the cert signature. Self::transaction_validity_check(&epoch_store, certificate.data())?; let span = error_span!("submit_certificate", tx_digest = ?certificate.digest()); @@ -598,10 +594,6 @@ impl ValidatorService { ) -> Result, tonic::Status> { let epoch_store = self.state.load_epoch_store_one_call_per_task(); let certificate = request.into_inner(); - // CRITICAL: DO NOT ADD ANYTHING BEFORE THIS CHECK. - // This must be the first thing to check before anything else, because the transaction - // may not even be valid to access for any other checks. - // We need to check this first because we haven't verified the cert signature. Self::transaction_validity_check(&epoch_store, certificate.data())?; let span = error_span!("handle_certificate", tx_digest = ?certificate.digest()); @@ -631,11 +623,8 @@ impl ValidatorService { ) -> Result, tonic::Status> { let epoch_store = self.state.load_epoch_store_one_call_per_task(); let request = request.into_inner(); - // CRITICAL: DO NOT ADD ANYTHING BEFORE THIS CHECK. - // This must be the first thing to check before anything else, because the transaction - // may not even be valid to access for any other checks. - // We need to check this first because we haven't verified the cert signature. Self::transaction_validity_check(&epoch_store, request.certificate.data())?; + let span = error_span!("handle_certificate_v3", tx_digest = ?request.certificate.digest()); self.handle_certificate(request, &epoch_store, true) @@ -655,29 +644,18 @@ impl ValidatorService { transaction: &SenderSignedData, ) -> SuiResult<()> { let config = epoch_store.protocol_config(); - // CRITICAL: DO NOT ADD ANYTHING BEFORE THIS CHECK. - // This must be the first thing to check because the transaction may not even be valid to - // access for any other checks. transaction.validity_check(config, epoch_store.epoch())?; - - if !config.zklogin_auth() && transaction.has_zklogin_sig() { - return Err(SuiError::UnsupportedFeatureError { - error: "zklogin is not enabled on this network".to_string(), - }); - } - - if !config.supports_upgraded_multisig() && transaction.has_upgraded_multisig() { - return Err(SuiError::UnsupportedFeatureError { - error: "upgraded multisig format not enabled on this network".to_string(), - }); - } - - if !epoch_store.randomness_state_enabled() && transaction.uses_randomness() { + // TODO: The following check should be moved into + // TransactionData::check_version_and_features_supported. + // However that's blocked by some tests that uses randomness features + // even when the protocol feature is not enabled. + if !epoch_store.randomness_state_enabled() + && transaction.transaction_data().uses_randomness() + { return Err(SuiError::UnsupportedFeatureError { error: "randomness is not enabled on this network".to_string(), }); } - Ok(()) } diff --git a/crates/sui-core/src/consensus_handler.rs b/crates/sui-core/src/consensus_handler.rs index 43b9c77dd1253..d8e7ee4018aee 100644 --- a/crates/sui-core/src/consensus_handler.rs +++ b/crates/sui-core/src/consensus_handler.rs @@ -733,7 +733,7 @@ impl SequencedConsensusTransaction { else { return false; }; - certificate.uses_randomness() + certificate.transaction_data().uses_randomness() } pub fn as_shared_object_txn(&self) -> Option<&SenderSignedData> { diff --git a/crates/sui-transaction-checks/src/lib.rs b/crates/sui-transaction-checks/src/lib.rs index 8fabbb3a3d6be..3160e8337d622 100644 --- a/crates/sui-transaction-checks/src/lib.rs +++ b/crates/sui-transaction-checks/src/lib.rs @@ -187,7 +187,7 @@ mod checked { gas_override: &[ObjectRef], ) -> SuiResult { // Cheap validity checks that is ok to run multiple times during processing. - transaction.check_version_supported(protocol_config)?; + transaction.check_version_and_features_supported(protocol_config)?; let gas = if gas_override.is_empty() { transaction.validity_check(protocol_config)?; transaction.gas() diff --git a/crates/sui-types/src/effects/mod.rs b/crates/sui-types/src/effects/mod.rs index b047c4bed90f0..c650d0c5a490d 100644 --- a/crates/sui-types/src/effects/mod.rs +++ b/crates/sui-types/src/effects/mod.rs @@ -69,7 +69,7 @@ impl VersionedProtocolMessage for TransactionEffects { }) } - fn check_version_supported(&self, protocol_config: &ProtocolConfig) -> SuiResult { + fn check_version_and_features_supported(&self, protocol_config: &ProtocolConfig) -> SuiResult { match self { Self::V1(_) => Ok(()), Self::V2(_) => { diff --git a/crates/sui-types/src/message_envelope.rs b/crates/sui-types/src/message_envelope.rs index 7554d6189ce4b..6e487a79b5e99 100644 --- a/crates/sui-types/src/message_envelope.rs +++ b/crates/sui-types/src/message_envelope.rs @@ -92,8 +92,9 @@ impl Envelope { } impl VersionedProtocolMessage for Envelope { - fn check_version_supported(&self, protocol_config: &ProtocolConfig) -> SuiResult { - self.data.check_version_supported(protocol_config) + fn check_version_and_features_supported(&self, protocol_config: &ProtocolConfig) -> SuiResult { + self.data + .check_version_and_features_supported(protocol_config) } } @@ -299,8 +300,9 @@ impl VerifiedEnvelope { } impl VersionedProtocolMessage for VerifiedEnvelope { - fn check_version_supported(&self, protocol_config: &ProtocolConfig) -> SuiResult { - self.inner().check_version_supported(protocol_config) + fn check_version_and_features_supported(&self, protocol_config: &ProtocolConfig) -> SuiResult { + self.inner() + .check_version_and_features_supported(protocol_config) } } diff --git a/crates/sui-types/src/transaction.rs b/crates/sui-types/src/transaction.rs index 587cf0bd35f8f..4a4ffad20490d 100644 --- a/crates/sui-types/src/transaction.rs +++ b/crates/sui-types/src/transaction.rs @@ -445,7 +445,7 @@ impl EndOfEpochTransactionKind { } impl VersionedProtocolMessage for TransactionKind { - fn check_version_supported(&self, protocol_config: &ProtocolConfig) -> SuiResult { + fn check_version_and_features_supported(&self, protocol_config: &ProtocolConfig) -> SuiResult { // When adding new cases, they must be guarded by a feature flag and return // UnsupportedFeatureError if the flag is not set. match &self { @@ -1541,7 +1541,7 @@ impl VersionedProtocolMessage for TransactionData { }) } - fn check_version_supported(&self, protocol_config: &ProtocolConfig) -> SuiResult { + fn check_version_and_features_supported(&self, protocol_config: &ProtocolConfig) -> SuiResult { // First check the gross version let (message_version, supported) = match self { Self::V1(_) => (1, SupportedProtocolVersions::new_for_message(1, u64::MAX)), @@ -1563,7 +1563,8 @@ impl VersionedProtocolMessage for TransactionData { } // Now check interior versioned data - self.kind().check_version_supported(protocol_config)?; + self.kind() + .check_version_and_features_supported(protocol_config)?; Ok(()) } @@ -1948,6 +1949,12 @@ impl TransactionData { self.gas_data().payment.clone(), ) } + + pub fn uses_randomness(&self) -> bool { + self.shared_input_objects() + .iter() + .any(|obj| obj.id() == SUI_RANDOMNESS_STATE_OBJECT_ID) + } } #[enum_dispatch] @@ -2306,13 +2313,6 @@ impl SenderSignedData { .any(|sig| sig.is_upgraded_multisig()) } - pub fn uses_randomness(&self) -> bool { - self.transaction_data() - .shared_input_objects() - .iter() - .any(|obj| obj.id() == SUI_RANDOMNESS_STATE_OBJECT_ID) - } - #[cfg(test)] pub fn intent_message_mut_for_testing(&mut self) -> &mut IntentMessage { &mut self.inner_mut().intent_message @@ -2336,8 +2336,27 @@ impl SenderSignedData { }) } + fn check_user_signature_protocol_compatibility(&self, config: &ProtocolConfig) -> SuiResult { + if !config.zklogin_auth() && self.has_zklogin_sig() { + return Err(SuiError::UnsupportedFeatureError { + error: "zklogin is not enabled on this network".to_string(), + }); + } + + if !config.supports_upgraded_multisig() && self.has_upgraded_multisig() { + return Err(SuiError::UnsupportedFeatureError { + error: "upgraded multisig format not enabled on this network".to_string(), + }); + } + + Ok(()) + } + /// Validate untrusted user transaction, including its size, input count, command count, etc. pub fn validity_check(&self, config: &ProtocolConfig, epoch: EpochId) -> SuiResult { + // Check that the features used by the user signatures are enabled on the network. + self.check_user_signature_protocol_compatibility(config)?; + // CRITICAL!! // Users cannot send system transactions. let tx_data = &self.transaction_data(); @@ -2374,7 +2393,7 @@ impl SenderSignedData { ); tx_data - .check_version_supported(config) + .check_version_and_features_supported(config) .map_err(Into::::into)?; tx_data .validity_check(config) @@ -2389,9 +2408,9 @@ impl VersionedProtocolMessage for SenderSignedData { self.transaction_data().message_version() } - fn check_version_supported(&self, protocol_config: &ProtocolConfig) -> SuiResult { + fn check_version_and_features_supported(&self, protocol_config: &ProtocolConfig) -> SuiResult { self.transaction_data() - .check_version_supported(protocol_config)?; + .check_version_and_features_supported(protocol_config)?; // This code does nothing right now. Its purpose is to cause a compiler error when a // new signature type is added. @@ -2790,7 +2809,8 @@ pub trait VersionedProtocolMessage { } /// Check that the version of the message is the correct one to use at this protocol version. - fn check_version_supported(&self, protocol_config: &ProtocolConfig) -> SuiResult; + /// Also checks whether the feauures used by the message are supported by the protocol config. + fn check_version_and_features_supported(&self, protocol_config: &ProtocolConfig) -> SuiResult; } #[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize, PartialOrd, Ord, Hash)] From b5a7a30ef522879d89e824ccacc617860505335c Mon Sep 17 00:00:00 2001 From: howtosui <96097578+howtosui@users.noreply.github.com> Date: Wed, 29 May 2024 00:46:42 +0800 Subject: [PATCH 009/324] [CLI] Optimize `sui keytool decode-multi-sig` command response (#17950) ## Description [CLI] Optimize `sui keytool decode-multi-sig` command response image ## Test plan How did you test the new or updated feature? --- ## Release notes Check each box that your changes affect. If none of the boxes relate to your changes, release notes aren't required. For each box you select, include information after the relevant heading that describes the impact of your changes that a user might notice and any actions they must take to implement updates. - [ ] Protocol: - [ ] Nodes (Validators and Full nodes): - [ ] Indexer: - [ ] JSON-RPC: - [ ] GraphQL: - [x] CLI: Updated the `sui keytool decode-multi-sig` command: renamed output field `transactionResult` to `sigVerifyResult`, and improved its output text. This is a breaking change if you're using this command in a script or otherwise parsing the result and expecting a `transactionResult` field. - [ ] Rust SDK: --------- Co-authored-by: bityoume Co-authored-by: Ashok Menon --- crates/sui/src/keytool.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/crates/sui/src/keytool.rs b/crates/sui/src/keytool.rs index ed6c82a352ef7..24f86bd2cd2b5 100644 --- a/crates/sui/src/keytool.rs +++ b/crates/sui/src/keytool.rs @@ -316,7 +316,7 @@ pub struct DecodedMultiSigOutput { participating_keys_signatures: Vec, pub_keys: Vec, threshold: usize, - transaction_result: String, + sig_verify_result: String, } #[derive(Serialize)] @@ -517,7 +517,7 @@ impl KeyToolCommand { participating_keys_signatures: vec![], pub_keys, threshold, - transaction_result: "".to_string(), + sig_verify_result: "".to_string(), }; for (sig, i) in sigs.iter().zip(bitmap) { @@ -543,7 +543,11 @@ impl KeyToolCommand { &VerifyParams::default(), Arc::new(VerifiedDigestCache::new_empty()), ); - output.transaction_result = format!("{:?}", res); + + match res { + Ok(()) => output.sig_verify_result = "OK".to_string(), + Err(e) => output.sig_verify_result = format!("{:?}", e), + }; }; CommandOutput::DecodeMultiSig(output) From 2cb06206c613dbd174332863b7ec166761e8d129 Mon Sep 17 00:00:00 2001 From: Dario Russi <113150618+dariorussi@users.noreply.github.com> Date: Tue, 28 May 2024 19:01:28 +0200 Subject: [PATCH 010/324] Change protocol versions and fix snapshots (#17947) ## Description Bump protocol versions to account for the hotfix and cherry-pick in v1.25 and v1.26 ## Test plan Existing test --- ## Release notes Check each box that your changes affect. If none of the boxes relate to your changes, release notes aren't required. For each box you select, include information after the relevant heading that describes the impact of your changes that a user might notice and any actions they must take to implement updates. - [ ] Protocol: - [ ] Nodes (Validators and Full nodes): - [ ] Indexer: - [ ] JSON-RPC: - [ ] GraphQL: - [ ] CLI: - [ ] Rust SDK: --- ...000000000000000000000000000000000000000002 | Bin 59438 -> 59226 bytes ...00000000000000000000000000000000000000dee9 | Bin 33394 -> 33346 bytes ...000000000000000000000000000000000000000001 | Bin 0 -> 6995 bytes ...000000000000000000000000000000000000000002 | Bin 0 -> 59438 bytes ...000000000000000000000000000000000000000003 | Bin 0 -> 41886 bytes ...00000000000000000000000000000000000000000b | Bin 0 -> 19538 bytes ...00000000000000000000000000000000000000dee9 | Bin 0 -> 33346 bytes crates/sui-framework-snapshot/manifest.json | 12 +- .../tests/objects/enum_data.exp | 340 +++++++++--------- .../tests/packages/datatypes.exp | 4 +- .../tests/packages/enums.exp | 82 ++--- crates/sui-open-rpc/spec/openrpc.json | 2 +- crates/sui-protocol-config/src/lib.rs | 12 +- ...ocol_config__test__Mainnet_version_47.snap | 3 - ...ocol_config__test__Mainnet_version_49.snap | 271 ++++++++++++++ ...ocol_config__test__Testnet_version_47.snap | 7 - ...ocol_config__test__Testnet_version_49.snap | 278 ++++++++++++++ ...sui_protocol_config__test__version_47.snap | 4 +- ...sui_protocol_config__test__version_48.snap | 5 +- ...sui_protocol_config__test__version_49.snap | 285 +++++++++++++++ ...ests__genesis_config_snapshot_matches.snap | 2 +- ..._populated_genesis_snapshot_matches-2.snap | 30 +- 22 files changed, 1084 insertions(+), 253 deletions(-) create mode 100644 crates/sui-framework-snapshot/bytecode_snapshot/48/0x0000000000000000000000000000000000000000000000000000000000000001 create mode 100644 crates/sui-framework-snapshot/bytecode_snapshot/48/0x0000000000000000000000000000000000000000000000000000000000000002 create mode 100644 crates/sui-framework-snapshot/bytecode_snapshot/48/0x0000000000000000000000000000000000000000000000000000000000000003 create mode 100644 crates/sui-framework-snapshot/bytecode_snapshot/48/0x000000000000000000000000000000000000000000000000000000000000000b create mode 100644 crates/sui-framework-snapshot/bytecode_snapshot/48/0x000000000000000000000000000000000000000000000000000000000000dee9 create mode 100644 crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__Mainnet_version_49.snap create mode 100644 crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__Testnet_version_49.snap create mode 100644 crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__version_49.snap diff --git a/crates/sui-framework-snapshot/bytecode_snapshot/47/0x0000000000000000000000000000000000000000000000000000000000000002 b/crates/sui-framework-snapshot/bytecode_snapshot/47/0x0000000000000000000000000000000000000000000000000000000000000002 index 768f02d09185ba9ee643f735acd52552f76258e8..5caa284e0462f9038d041965a7dd128ac89aa188 100644 GIT binary patch delta 626 zcmY+BziSjh6vy9t^K*A*cJKD~_U@8Pf`y89rnw*yBB+(v+;O%4fIlyN8WHPkC5Rwe zsNf-NVVBBUL{Llw4Yq<-A*2!CTxaw7&iBnQ^WJynAH~53@%Hq1=be5w{N*$N1O!dm zi{hrdU#JH-H3#?t?O)o`d!kG~3FGz!`ETM0g=0n8i6ZD=h9#gu0SE^976r(rMUj@P z0&*EiN;BKWGE)=R2_`5mgEuJ~qa0H!-bR@d0=l4?0di(ROv*jiC8d;8Lf&!Z{WWsO!C1f6Y+J6&D;h+z_5J+K|$!)Zkf1 z8@8EGUsu?02jtDKcaEfPUmt%<1aaj~^Vmjc= z;$+flN0%0zDE%V7fO=3d+e@1%O9=z!a>b-pk1N#c@-_`t;*ZHp_R6YMvfD5FL3X^A z{j%#zUo?+yU&7|goh#VkE@bME<4h2ViUd}g(Y;q#ug}I9>W8xtx|nZFwBDaBi$HmO TJUfT2`qcJ$Y&X}pf6o2^oBL5j delta 829 zcmY*XJ!lkB5PmcJesr}!l;K<7WPU=Wg%9AHWtCc!p?bD1l;2L=9_uDvoqiOdf>e}^j@D{-g>Hb z$A1~g7_-16%FwIy`D18_=dh~&!h7)dy;*tW)$}8-%oC2`HvfqBv&85?BCA6T83P3# z1EzpJBN&jVpu>Q&9!t1G6q2y2d_tpKtRaBw9+QDPYLzDRg&|ae4gpUP7=%_5Ml2z$ zAt4$~8B9W|Vj59fjs{cIXnlbdq!J>=e&mPckL4u~lrE=MF6!V`e`9^^cJJY!+*nys zs^8n}^#{WbE0b^@63Yr%sE`^Jew#-kuwdCd7J=XfFmQu;hD|fn6vgGy)hWGH92V*H3K4Gz#_2J?^L>MihC{sX+OTCR9LsW}ebcjTyHSmYR_gv>s9kSVz7E zM>P{UvMP2Is?iHNNu4s4s-tGbH3GTV%!n#2O;~45!tsm{(*|WQuTvFU6V7!W^Ssum z37+NkJmR&`=gnF(YvznMGT>QQ539q@-3yQ=#~!S0-n?_aHyGa7xCG_SGhL;h<=U;9 z(RDzq2JFP}-MyD^1=s9;i_8k~i+TpXN( K%J9M9``{ma8Dw<; diff --git a/crates/sui-framework-snapshot/bytecode_snapshot/47/0x000000000000000000000000000000000000000000000000000000000000dee9 b/crates/sui-framework-snapshot/bytecode_snapshot/47/0x000000000000000000000000000000000000000000000000000000000000dee9 index acaa7a720277b61401550136f902954aa508bba1..d6568ff2626faa32de6303366338f09330d01be9 100644 GIT binary patch delta 1180 zcmZ{jO>7%Q6vsWYGoIaf&+Bz!@7i(V#KegcK8m5jnG~tQQ4W-n3RG3p1PYA}rE*h3 zDu`%7IZ!Gg5F7@mPBX66NT9!+*&63}yq=0bn%zvDK2g-ypByLsTI~7M zM)Bu+u2FJApWJ(pzUFA0E0W*z*xbA1w7xhuJ^Ukaag)4D^vc9UG8<-QWhqE!%_}h> zvVE(gF17l|bv@ZCnsaxxI%ek=t)VS3b6BLC>wc5U!Y2da>tOsWQih%k--g1zU!u$n^2kH??1 zcN5~q&a>wT@!|{np0ZJX|1}aVNM}`JVM7D+c&{#X`olcG4H5)A0)hY`f>(jDt@@Ep zG?u~)$`l7FJvFAbK?XdEG~c1$>EtI759P4&bGM4!#&_x~^U-pXx2#xmkZUE2 zpenu0qZmpDbCR>;#FWWos2;#yiAbDMYT!u9Ee7%>4(@=XDK&UTRi^W%ldF3b`DBQ)b^2euD_N`d=HO zGJAu{po=N9KM4PO10lTXnop1e$J{?N4tM}+7PA)TLe?A%LS)PAZOY%LU3DT=mCm#b zD(tjLTBj{R2GRdQ)_l6PuK3jR71N-4Wnt9Vesf{ac5Bb#b2fM6(CsETb!eZ>`7b_X zbIq4NG|e+U#L$@Q>Eu##z=SMqr8%YxfK&TH-9gY@UGd6Nt=|Kp=Fzr;2h_}{v7e5x zy{ii@EmaNv&!zJg|MAPm%y{?VaL~=t`$!_;GO#~6t=qXJa&^#TJl#HgnR_6B#P=R~ GK>Q2KQo7;* delta 1377 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 a@kdu#u>0M;1;xE^Vyv|I)HIkmWB&{IDd^n* literal 0 HcmV?d00001 diff --git a/crates/sui-framework-snapshot/bytecode_snapshot/48/0x0000000000000000000000000000000000000000000000000000000000000002 b/crates/sui-framework-snapshot/bytecode_snapshot/48/0x0000000000000000000000000000000000000000000000000000000000000002 new file mode 100644 index 0000000000000000000000000000000000000000..768f02d09185ba9ee643f735acd52552f76258e8 GIT binary patch literal 59438 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 S1(HTz`%HI(Yu(d#^Zy5ln}Hqx literal 0 HcmV?d00001 diff --git a/crates/sui-framework-snapshot/bytecode_snapshot/48/0x000000000000000000000000000000000000000000000000000000000000000b b/crates/sui-framework-snapshot/bytecode_snapshot/48/0x000000000000000000000000000000000000000000000000000000000000000b new file mode 100644 index 0000000000000000000000000000000000000000..bcf65aa63c2d2ff276672cce51e5b1a1c8f60e84 GIT binary patch literal 19538 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 KZb8)K{P{F9AT=e4yJWlkZ-7~dy=7BsJeR+ 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 PWp#XPBmzHGwf(;VQFa?y literal 0 HcmV?d00001 diff --git a/crates/sui-framework-snapshot/bytecode_snapshot/48/0x000000000000000000000000000000000000000000000000000000000000dee9 b/crates/sui-framework-snapshot/bytecode_snapshot/48/0x000000000000000000000000000000000000000000000000000000000000dee9 new file mode 100644 index 0000000000000000000000000000000000000000..d6568ff2626faa32de6303366338f09330d01be9 GIT binary patch literal 33346 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ˈp`w;Dcw~u(su6h5*!rk&2tjk=>$W8Ef3H+7; zuluhn0TCS>9ikgH=Xzt*clUDXAT}b~ZV!@%)ez7^6;0Q2J!XkjZZLH-XA7tf zx#DmpSF*|+mX%a(g7teb;m{A|)DRo?z=3q`k;Ifz>(JAoBzk;-tttz!NE8&o`hthZeJ8F}{Mq1D7X|I+JG? zmnW*(92&|lvLBZxYS^8CUR<7N8A~QTxV%EYm*Dbb3nnVxMu{7|BFiS$*C=~mgUdsL zLkA)&yWuo+17zM;wt6P7efGYeP|mNbk9+#J{NGpZ*TUZ}dEY<$F9!T?9C|+Y8;3t) zhre~p|6)f!a=qOBmajlpDcWB^FZ-mZ8~Vop0rL`o9g}QD@y&cLV@=-(2$R! zH2XgLrL{L{bglUxO*$Lbz(CeTD$#?_N(Z~TE(_4y0OX{GG<$U79DFQJoIbJ z%$gEfjhQSuI<=nBsf}d#IigeRYu^ftwk->Iqf;9Po)r&jD~}#+VIZAPOAY4J zUnIKds(y`mPV8S$23KhPN;=(I_j%mvJrrOZhve4Xu~D(TD{rjZ3&uJT7bWRE`I1<7 z7L0XA!Fb+ZHc=j^80)XAswnbWzpAP-nOk2}19h=~S`A2LtUsfg=KIg8rup7rKE-=I zwJr~vukTYJ2l4&50&9rwDBBo%HZNQ;|nz zjCFXwv3^9&9&o%l#d`UUJH^`N+$Glj)cQ-xG1|eGQtL0YKR?m7-@N-C%X&*Cla}=tjrk#Ce%hGJ z33dN4hY1|UNsQ076CF(suvU3vljYHzF%Pb9;C}oKQ5b&WjjNbTAEx12oxdb_#H~x` zFt?5QYWPmv?|DOfKB}9B(aA-CS7Kad`z9g8hz%3WuN|#x*zww+hRWZ zEGsVig%7cevFxj`hy7~!E}VZ=ZHv#>)iN7%=aqAlmh*E;%)e&LpI7IuT6*^7O;J3) zxQKb-WrU@EufK-*6KWC5eTV-f>c{8bLx8vP3f1s_Qr$ z@ZI1AVt>Bl`yNMp2T@+a5_?4GgmqoK%r^T9o{WYtoW~} zdrw$}v5%Tqh1pY5Okw_2DW;H|k{k=KhEHP^e?UFztGM`MihB8_FQ`XOSRYU)-%=;< zS-5!Sr8C=S!-Wqi@58DTEL?ibTX^BI3yT-dY&`W~@IiI*sl}(xytw${nRsD+@zUax ziyP0apSg7A$uk>E8_z$zxN-jJGlL7m3rnr~!V8NpE#4O_w;l*i1y|2LH~Grhm(RX) z@rlLOnbzXu!oh{t&OSf+J?i8e=iWHGdG?{;;o#n2B_p2doiQ4n|kp*$kZx+ zs48;elzMyqkcw*D*>mWRaAT8$hhNBvR%3*YaFcJ8Dv4s8sek*!Zs);Px$RCaR@qO82BDjY&(w zPPS5$v_Ujf+C}~tqJDi{CTUy~2aHrZXX9x)s<&cxPi4B!EJv;_(rWFHSh~5VSv~dW zq>>7QyC$)86E_c8BT?lry5H3_2wnAqV*JJ`}Le3h<>|^EhTnJ zA#;?)^RR?y>q-zi8Z;Mr+LXCPW4udP`X6m@*=}`O&yh+X%GQpkw~O|+sE@ZvM%rqo zJ}#vZs}n}Hut1PQy*{lTHwA{`Fmvh%sJe2EGA@3So&@}pD*FMOKH-lx+f$=K^PQ?_ z6R`mc&>~?6c6egh#*_{xFwMkdgi~@N%@7Wkm}Web{f6t;0g*NQGKESG$``e6B7#id zuqH2F?Q%g6%2&>?3Nd7Kh>x2l*&{q)TP}&Qc1ShDYc{+A&7ZTpwscDA@aTeWX!b3v;J!<*_%d*0ZluUPL=Aj z6eLbF&xKN=HYM(r{r#V`;eGAixz(bTZ#vk6z4v{mg^31#+Q~bYW{T=7vbS-*sc&i+ zM(Szz&Q7Vh$&+5qSWos5;szx#1Ry}h9aK+wL|9gM+pr5!BvyxF!rCbw0MCp@fht|o z{YE;chKP%-p*uT~Os0Na13{BZN0yI#NST*yk|B0peB_T~8xe<`pvuS&Qt6Sl1t38{ zSSt9y5zx3=J0#7FOCFOdXb1mm@#_882V6)~w1p<3Su)Sk_uv-F3u|kSiXQydsZ2fpI-gS; zm#?6eyuO`1we)R44)N(!fqX$;>ft4(Uc^J~VbMWut(a0DZf!5~PQ&usghBKIAFhKs z!~%PGRFs8J@#4_i$35hqYCkMwYWwydh`RnH?0;e+UX>TFZumsXx4}d-F7O!0`qEX= zl@@qFTYG$~cwuc7?(681XD5Xzd?ErwvEE7p`_B%qfl}17qeOX8>oVH%D@&p;KDe_t zr;3v|2r+8%o2~7uo9oxZGg>CorA9lg(Maz}kez2<>%X)kxZ}Hi$T`qHJ11SjPnqlZh$Yj{sp-|Ip9PKq~?!{I*AO10|-TH^Yx-}Z*@^k8@xlb z$`ex^gvE_8Dg)P{R%rD0uIqh`gvk192V_hAda#S+G`@p(Usf3+CNKkDAVND~V~SU< zo?lzNAh?(Ht&6SAKPgsb>_#A(CG&#cpBPHh+-j{|1ewLULEhq(x1*R3fWzdrTD;h` z8E?JFt5Qqp1B2#0D803Dx%GAsIMX-8=A>w-j3zfm>h$K&kKyUhAw~4$QvgpkFx&W^ z{`u|Op?*Sx`Z4&o8vua(jFN8$`jbAq*sjqvmq!`=hsTUF=i5O74P1i^VnPSMHhitG zfSuaqrr4p}D?sNqHoGVxgU#xP5Ou!{z*E@WybAfJ2`G{~68Y=ifc@z}i$u9p{(3=1 zqEjb-ppsJuu1tBw@#WsdC-yILz7>f7Tgth`Symrb?uQhwnSDw*ivXDX>wH0vQ;-qh zU*O`3*L>R-dqSq3Ph~DZee=SZx&55vd2j9(Lv>7*-|SqQf(YU%FEx)k6^c7N{fXML z+$$Q~l;mBFRrx)(JX`k=SBTXxMP_lzCxwxF`5oMaSymAp>lEe0Q%){#6?v%dfgGAI ze?%o{F35wTlEPeudPCl@=xE7fqT-oCnk2nWMDr2#QL=penSxGYZ)C!}dW42WaT--> z(Y{7!I<(8rbo8U9^ng1k+TG=86nWxFJ?2izXF+rz!BS1Tv+{{Xo?Ct|+UHUEeWJ%H zA08iXf?YySwL-q4-i=}%sZjlLDppeDu`V|$$v-Xvo7kO(;;vBHDwVD!1IJO+Q3P%em4=}1RqogSaJs(ZS<4;kl@gDF@# zkAj_K7pmZJl_B-GUH)UH*U1Fw(XcYdZkS?WDb@}&A9d-eWhVq(?RH@vPuG`MVXqN% ziqTGlQ9U3p0R7O7+h@Q88r6Eyb6vgtyI7j2;rar3FvW=`t`sL4of;^dG*CqROJ6_} z*U&oV^{#j>5g1@DM&a|Q8xNegoharn-W?9iCo|fBEO_yZL%@18lk5j}HlNJK2jjy* zJb&VHCwkLFAJ>P&!=c_2`|d3PB=hwL9bgX!lLPUg@KDK1=92kZyw^Anj_cpI#TD*N z4#i{P7&@i#Xb|tm71Tm^kA9kK&p7WskJ|QQc!sqJRN3?TbKHCFH{(Y9Ogc~(VC5hy?Qqn@ zDZeY82q)+*pkU9&v-)RLG~1(oI~z_!vvtsMbK&@uW|A0>hoTAKYNPR>`@7U}KAiJJ zEi?!0@ZD*SXg>2Yo4^jeS`&2GVCwyhfZVcz4rrbvJJ3_mfp9oFPzU8GQBbCSCZ3E& z!@)*88qI}6jTmKiWQggD!Q@ChlAi$~<;44pR1oj{zHl-eu7heB#m|oRCAX-29Wd9e zqAx1~N7U}6kEsyFG{Q;XBcA@Uo!^~BFu~DaG!zXtqRHgw>D#0I`sZvI&izF?tRq<_ zVDv!$6Fb}+?`aeFSUeR@CCRw{U+rkh(BJ(HT$GK9ywoo_9_~qQSK*(4sT?&M?~xAIW^BA)*tpSV<1E77XgH0~&(}lY3@L@F-?H;ErVZDpOg$9M0CW|Oo(2Tt z!w(?YdN~>psQy_yoI)n1v^W+|GDP6$FW8I)B-)hw>J;LRN?Fxg!<-co3d!j+Z z<$_Gz3#WVf8+J4Smq+fuw*`0z@({yr!sTy%s52Mr0ozzl1`LM>ee=MC5$xLF^|E=u za5(e8srbN-lfYa!&m0NT?I6<;Rrq%d*YE%wj`nny!^H`Q|E4XThQmk0QQ^Ol08SVc z4%d71Irnjy1fDS*J_-+{lfdWUaESyCVH9SC<8~P?kr>gg)~K>CIN-qI~tffLK#Q50fhR&YeoZ@^Jss2H0;x#GxGgM?Xc&O zP$S=eB^?bZ-8!S;XFH?e%bn36)j+8sHB3xEzN7PC~H2`;rHc&H=yh!1W)m7q5j5tJB6F zecFAbFUQ<8DI8Kfh(It+@CHq;F^D2Rc_=P`hm435rMdF1ZAtP?&PD~^29U*e(H^0F zA5^c0e)%z;n|49I%9i6@f~;hv&ocvwz@Zpk?7^_Q>`ZtY`5GGJs}u2}WAX^G7@!h) zC*-Ru$g6ZKXC8UYqtcS&$E#?#Am;9gi{O|*W!d}}B#&0YWRaTk>T)777Ahx?k+Tu< zyhaQ*Eia%Gwt3!hFA)?Em}>cHk9BG%Z(#??6UmeA6(N$WO7gHQK+NP^6x*Z17uS)V z76c*i1yYs>LqTqqQfqNQkr3G*NGlVpQD1a^B%}hh_epI8}$P-@pr0sqV zfSaKwtdNHly%joqZ4B^|06JB9Tu@_u7+`)}juwW< zm7oU$OtO9qumBVV0}PyyK{919z|R`^F9wT{XJgl_0O%z*Ih}$&`Smiv2PeSgj67m@ z{=7X!@BM&EQNSz{4GMUfMUa!6&rrY=E-2sw0;Xf$bO5vq3YgVR9}3tJ6tFBCQxq`! zpbQ1PhyMCO^%)tbW+TI|5YTfeOrS!~wQ<1ho~zJv13jCSSeAVk#`X6qajeK9w}cA} zEuB~fzdFv?%Dap(DSF+!-z!S=haMaVF{OF3729CmtqN*VhNXG3729SF74-0o|VeOQfyWRWgp0o z9LBOj{vkp3$Ff4U_tHO~Ry?ZG?jN3BH}Xw5tKR9K&H(Q&P2y(9GadwKJQo<|yDF$0qxc8^7<^MZka;Kq;st%d{iZz-&XgOmE% zsLCp{#B`U!7$3zp{L0$yp18sS`Q7atLQbH0$f?BBHYslXBDUdK7Mo38l&C`msG;91 z)PxGPlnR22g$i|EemL!ZSUwQUCPs1?3o^J^kRgW!89Xe=;A26C01GmNSdf9`6@r2z z+4jJ7<2=CS{OQY4vAZH*tumQbnK=QX{HkJ}C>WwlLzEv!A?ogC^$Gy)a2PygUScc26A1L7WqRw9@K;;^+H{CJGI^Vb@zSJv=VcU{v?ZAAyd7VOg#A_WcsWjQ`9suAX7ah zQ#~b9Jtb2;B~v{mljH@NB)7LsCeD&oN~6EaB}kh_`=HTh)I}psyb~Zr(m$pYUWiIs zhb;}PD zm`I#|r08=_Cp3-4D2h=K!+_EA;^I6|)0NBh8FnV$vRKGhq?K;ZWq2)seQAL>EAU+y5^FU#~VK=x(H3#U_FEzePP-5E6e;D&*< zPqH7-rza&IcM}{&^uyYpOAB|GnYoqATQOAhz_)E0{c~;8q^D>a&r9vr=HNeTwQ13w zHmKjFw`q4@)8xk@(x%A|N%S?1^~~F9nq={|nl=ZiKChU=N$^668?sJ+!S?dhki4w` zcW01ySPq6Yyx4`j`~8r2;vDOPyz|oo){n3%ka8VpPGV?(xt*L~VS|AdWGx ztYeHb>lh=>I#v>+ECvrjSjTw&!8%rxpOG4<@td!t;j-+QYahv+fqjcOS%|Vhv2V@X ze$BoubLVRIQE>~0yU98+gJiwVk1D3Q0T&d!mt;YW?c-25WO9hsY~@66mF z{O-!!Va>ifa|bp1p0=CcY<${20j!cMGARH9`C^HDu|&RDB3~@J2?P0JiF~n)eBnVI zhCYv=n~NldR-gkf;Ac@$Pj&+*u+5^MUZ-c-BL_ae?Ex6d=ao(#I?wt1P^!g+uv`qg z3%P~TLV2OGP+h1k3@p?anhS#qLm-z%7DgAw7IrO+FMx@%ey;P{05_J5hkeeGuPWYw z8+Sio^Aoz?az5qwZ+Xw>{v~gg{9CUY|99`d>imC>eO?NPtb&^0;Ex|lL?PW$tkwiU z33`&>BM}58*YtFW=D7{|-4UyvLLmoIt06x$!o3}@1BkE~)7%}8iZSW)a_Te&GjiSr zT*`5sSg~KU*hk<$&hH{BiKZkPKW*3qO*c5e&wAKH#vEygdykk-vCM6yQ?0UGaB9Zf zRp9>7*;~TY>F+7({0Kh^#xnz>Rk4Og#0sOqpvj)R5ex*CTDexL4G&jqwc5z=(D3MR zJ;?ExfYAWwLK&&v{RfW9B2X(hx5r!D3Lzv25)dHb;1Wzc8 zyH9hZI~437F$1fbs)CEAzsWqc<);_;%|mh}69HJHSQT-}`vyQ$P>nY)9SD|!coJfg zNHW4Y?+Ij1;;G)}>3j9F`&6+5qouvL{6fp9TL({OZ^*Y*ox5+R@9?XMnVxR1hHmGF zZL{~w27to!+V%Khcwt z7mm~4Cydv69@O@)`$0o31$3XO&YSX5Ex^^4qWO~i+Ap4qPT|d-u zD0&R)v3zuIkxe*z)v#Pl6lQ^WhU+O&266YY<4xr0t+oeJ&8+Y%sp5*sxvebl-OCvf zVpaYc8z%EZX8brAHyCveo;Ytr1%rnUdBw=$_qlLUpHQ);jpF7B!NQwAj-tBzv`G|6 zb`=`Z+U_=FH-}9#ft(TPud=fjEP`3JY zPKS9TSWYH9Zs)iitCyqGMRtgF#j{(k`K3J51W4)rC0fl#By^P>n`wir>yY(uOo55K zWEpj$f=s=" }, "data": { "Struct": [ @@ -38,38 +38,111 @@ Response: { "name": "id", "value": { "UID": [ + 41, + 104, + 155, + 111, + 140, + 100, + 98, + 155, + 81, + 21, + 140, + 96, + 67, + 55, + 18, + 108, + 14, + 26, + 245, + 14, + 169, + 188, + 248, + 220, + 130, + 95, + 174, + 189, + 105, + 90, + 43, + 79 + ] + } + }, + { + "name": "balance", + "value": { + "Struct": [ + { + "name": "value", + "value": { + "Number": "299999995967600" + } + } + ] + } + } + ] + }, + "json": { + "id": "0x29689b6f8c64629b51158c604337126c0e1af50ea9bcf8dc825faebd695a2b4f", + "balance": { + "value": "299999995967600" + } + } + } + } + } + }, + { + "outputState": { + "asMoveObject": { + "contents": { + "type": { + "repr": "0xacedab07045872863accfbec2ec7d364e28bb343420a5fe7f98e9095553a225f::m::Foo" + }, + "data": { + "Struct": [ + { + "name": "id", + "value": { + "UID": [ + 252, + 194, + 91, + 121, + 212, + 42, + 29, + 162, + 27, 38, - 208, - 191, - 88, - 204, - 210, - 143, - 164, - 241, - 178, - 35, - 61, - 136, - 222, - 125, - 75, - 118, - 15, - 229, - 217, - 229, - 13, - 97, - 94, - 19, - 200, - 52, - 115, - 126, - 208, - 219, - 38 + 92, + 103, + 209, + 216, + 254, + 110, + 85, + 3, + 149, + 92, + 173, + 63, + 148, + 218, + 110, + 8, + 180, + 8, + 213, + 152, + 121, + 16 ] } }, @@ -77,38 +150,38 @@ Response: { "name": "f0", "value": { "ID": [ + 252, + 194, + 91, + 121, + 212, + 42, + 29, + 162, + 27, 38, - 208, - 191, - 88, - 204, - 210, - 143, - 164, - 241, - 178, - 35, - 61, - 136, - 222, - 125, - 75, - 118, - 15, - 229, - 217, - 229, - 13, - 97, - 94, - 19, - 200, - 52, - 115, - 126, - 208, - 219, - 38 + 92, + 103, + 209, + 216, + 254, + 110, + 85, + 3, + 149, + 92, + 173, + 63, + 148, + 218, + 110, + 8, + 180, + 8, + 213, + 152, + 121, + 16 ] } }, @@ -148,38 +221,38 @@ Response: { "Vector": [ { "Address": [ + 252, + 194, + 91, + 121, + 212, + 42, + 29, + 162, + 27, 38, - 208, - 191, - 88, - 204, - 210, - 143, - 164, - 241, - 178, - 35, - 61, - 136, - 222, - 125, - 75, - 118, - 15, - 229, - 217, - 229, - 13, - 97, - 94, - 19, - 200, - 52, - 115, - 126, - 208, - 219, - 38 + 92, + 103, + 209, + 216, + 254, + 110, + 85, + 3, + 149, + 92, + 173, + 63, + 148, + 218, + 110, + 8, + 180, + 8, + 213, + 152, + 121, + 16 ] } ] @@ -246,15 +319,15 @@ Response: { ] }, "json": { - "id": "0x26d0bf58ccd28fa4f1b2233d88de7d4b760fe5d9e50d615e13c834737ed0db26", - "f0": "0x26d0bf58ccd28fa4f1b2233d88de7d4b760fe5d9e50d615e13c834737ed0db26", + "id": "0xfcc25b79d42a1da21b265c67d1d8fe6e5503955cad3f94da6e08b408d5987910", + "f0": "0xfcc25b79d42a1da21b265c67d1d8fe6e5503955cad3f94da6e08b408d5987910", "f1": true, "f2": 42, "f3": "43", "f4": "hello", "f5": "world", "f6": [ - "0x26d0bf58ccd28fa4f1b2233d88de7d4b760fe5d9e50d615e13c834737ed0db26" + "0xfcc25b79d42a1da21b265c67d1d8fe6e5503955cad3f94da6e08b408d5987910" ], "f7": 44, "f8": { @@ -277,79 +350,6 @@ Response: { } } } - }, - { - "outputState": { - "asMoveObject": { - "contents": { - "type": { - "repr": "0x0000000000000000000000000000000000000000000000000000000000000002::coin::Coin<0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI>" - }, - "data": { - "Struct": [ - { - "name": "id", - "value": { - "UID": [ - 242, - 188, - 8, - 146, - 91, - 93, - 199, - 88, - 48, - 87, - 226, - 103, - 228, - 118, - 197, - 119, - 77, - 235, - 253, - 112, - 65, - 28, - 187, - 56, - 82, - 102, - 118, - 60, - 147, - 142, - 46, - 97 - ] - } - }, - { - "name": "balance", - "value": { - "Struct": [ - { - "name": "value", - "value": { - "Number": "299999995967600" - } - } - ] - } - } - ] - }, - "json": { - "id": "0xf2bc08925b5dc7583057e267e476c5774debfd70411cbb385266763c938e2e61", - "balance": { - "value": "299999995967600" - } - } - } - } - } } ] } diff --git a/crates/sui-graphql-e2e-tests/tests/packages/datatypes.exp b/crates/sui-graphql-e2e-tests/tests/packages/datatypes.exp index d2bbe304fc3fd..799757ac51090 100644 --- a/crates/sui-graphql-e2e-tests/tests/packages/datatypes.exp +++ b/crates/sui-graphql-e2e-tests/tests/packages/datatypes.exp @@ -150,7 +150,7 @@ task 5 'run-graphql'. lines 72-96: Response: { "data": { "object": { - "address": "0x0a95d2ec15ae1074b8a4ab8707a4525292cc69047ad4c4a98d6482e751f9d278", + "address": "0xedf6e233f33449f4300343e53d4d299378884daa9f57542a878b17470f98648b", "asMovePackage": { "module": { "datatypes": { @@ -184,7 +184,7 @@ task 6 'run-graphql'. lines 98-143: Response: { "data": { "object": { - "address": "0x0a95d2ec15ae1074b8a4ab8707a4525292cc69047ad4c4a98d6482e751f9d278", + "address": "0xedf6e233f33449f4300343e53d4d299378884daa9f57542a878b17470f98648b", "asMovePackage": { "module": { "datatypes": { diff --git a/crates/sui-graphql-e2e-tests/tests/packages/enums.exp b/crates/sui-graphql-e2e-tests/tests/packages/enums.exp index 276d723ffcbe2..ccd2e1c1fa2fe 100644 --- a/crates/sui-graphql-e2e-tests/tests/packages/enums.exp +++ b/crates/sui-graphql-e2e-tests/tests/packages/enums.exp @@ -22,7 +22,19 @@ Response: { "nodes": [ { "outputState": { - "address": "0x2d9c1eb67a4b66df6a47dc2152d703a565288f2ee475270ff1ce440104dc3bf6", + "address": "0x1b38b133dc9169e70d62e15808097530ff69ae0b64a9fedeea261f34daf981b8", + "asMovePackage": null + } + }, + { + "outputState": { + "address": "0x8eb33e5615087bbfb4e9f90ebae065d58d9f2237b5367be68c9590bde22c0091", + "asMovePackage": null + } + }, + { + "outputState": { + "address": "0xb2a541308be23fdde5ed0e9e61e5ae54df1733f93c68a2415b314158b96f1e77", "asMovePackage": { "module": { "enum": { @@ -78,18 +90,6 @@ Response: { } } } - }, - { - "outputState": { - "address": "0x86977b4dfcf9e54527721bbceb6929cf8f29a913b2ef9acde85906b14f5c1401", - "asMovePackage": null - } - }, - { - "outputState": { - "address": "0x8a8a244a30cb837389ea50533ae6bbdcc6203cfd3193fb0ee1979d93fed56a5a", - "asMovePackage": null - } } ] } @@ -119,25 +119,13 @@ Response: { "nodes": [ { "outputState": { - "address": "0x86977b4dfcf9e54527721bbceb6929cf8f29a913b2ef9acde85906b14f5c1401", - "asMovePackage": null - } - }, - { - "outputState": { - "address": "0x8a8a244a30cb837389ea50533ae6bbdcc6203cfd3193fb0ee1979d93fed56a5a", - "asMovePackage": null - } - }, - { - "outputState": { - "address": "0xd42dcb64198dbe5099a4b4a2b4d7e9c95bfd8c67bf27497e0b81eca639025397", + "address": "0x083ecfe550093498f9486af3e70df8230bb99034ce253061c72a44cd6a7d8e12", "asMovePackage": { "module": { "s": { "module": { "package": { - "address": "0x2d9c1eb67a4b66df6a47dc2152d703a565288f2ee475270ff1ce440104dc3bf6" + "address": "0xb2a541308be23fdde5ed0e9e61e5ae54df1733f93c68a2415b314158b96f1e77" } }, "name": "S", @@ -192,7 +180,7 @@ Response: { "t": { "module": { "package": { - "address": "0xd42dcb64198dbe5099a4b4a2b4d7e9c95bfd8c67bf27497e0b81eca639025397" + "address": "0x083ecfe550093498f9486af3e70df8230bb99034ce253061c72a44cd6a7d8e12" } }, "name": "T", @@ -222,12 +210,12 @@ Response: { { "name": "s", "type": { - "repr": "0x2d9c1eb67a4b66df6a47dc2152d703a565288f2ee475270ff1ce440104dc3bf6::m::S", + "repr": "0xb2a541308be23fdde5ed0e9e61e5ae54df1733f93c68a2415b314158b96f1e77::m::S", "signature": { "ref": null, "body": { "datatype": { - "package": "0x2d9c1eb67a4b66df6a47dc2152d703a565288f2ee475270ff1ce440104dc3bf6", + "package": "0xb2a541308be23fdde5ed0e9e61e5ae54df1733f93c68a2415b314158b96f1e77", "module": "m", "type": "S", "typeParameters": [] @@ -261,7 +249,7 @@ Response: { { "name": "t", "type": { - "repr": "0x2d9c1eb67a4b66df6a47dc2152d703a565288f2ee475270ff1ce440104dc3bf6::m::T<0x2d9c1eb67a4b66df6a47dc2152d703a565288f2ee475270ff1ce440104dc3bf6::m::S>" + "repr": "0xb2a541308be23fdde5ed0e9e61e5ae54df1733f93c68a2415b314158b96f1e77::m::T<0xb2a541308be23fdde5ed0e9e61e5ae54df1733f93c68a2415b314158b96f1e77::m::S>" } } ] @@ -271,6 +259,18 @@ Response: { } } } + }, + { + "outputState": { + "address": "0x1b38b133dc9169e70d62e15808097530ff69ae0b64a9fedeea261f34daf981b8", + "asMovePackage": null + } + }, + { + "outputState": { + "address": "0x8eb33e5615087bbfb4e9f90ebae065d58d9f2237b5367be68c9590bde22c0091", + "asMovePackage": null + } } ] } @@ -290,16 +290,6 @@ Response: { "effects": { "objectChanges": { "nodes": [ - { - "outputState": { - "asMovePackage": null - } - }, - { - "outputState": { - "asMovePackage": null - } - }, { "outputState": { "asMovePackage": { @@ -319,6 +309,16 @@ Response: { } } } + }, + { + "outputState": { + "asMovePackage": null + } + }, + { + "outputState": { + "asMovePackage": null + } } ] } diff --git a/crates/sui-open-rpc/spec/openrpc.json b/crates/sui-open-rpc/spec/openrpc.json index 018f17bd39c95..33855bc2e6bce 100644 --- a/crates/sui-open-rpc/spec/openrpc.json +++ b/crates/sui-open-rpc/spec/openrpc.json @@ -1359,7 +1359,7 @@ "name": "Result", "value": { "minSupportedProtocolVersion": "1", - "maxSupportedProtocolVersion": "48", + "maxSupportedProtocolVersion": "49", "protocolVersion": "6", "featureFlags": { "accept_zklogin_in_multisig": false, diff --git a/crates/sui-protocol-config/src/lib.rs b/crates/sui-protocol-config/src/lib.rs index 392595c42daf3..ec9d7f105b6ec 100644 --- a/crates/sui-protocol-config/src/lib.rs +++ b/crates/sui-protocol-config/src/lib.rs @@ -13,7 +13,7 @@ use tracing::{info, warn}; /// The minimum and maximum protocol versions supported by this build. const MIN_PROTOCOL_VERSION: u64 = 1; -const MAX_PROTOCOL_VERSION: u64 = 48; +const MAX_PROTOCOL_VERSION: u64 = 49; // Record history of protocol version allocations here: // @@ -129,10 +129,11 @@ const MAX_PROTOCOL_VERSION: u64 = 48; // Enable Leader Scoring & Schedule Change for Mysticeti consensus. // Version 46: Enable native bridge in testnet // Enable resharing at the same initial shared version. -// Version 47: Use tonic networking for Mysticeti. +// Version 47: Deepbook changes (framework update) +// Version 48: Use tonic networking for Mysticeti. // Resolve Move abort locations to the package id instead of the runtime module ID. // Enable random beacon in testnet. -// Version 48: Enable Move enums on devnet. +// Version 49: Enable Move enums on devnet. // Enable VDF in devnet #[derive(Copy, Clone, Debug, Hash, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] @@ -2252,7 +2253,8 @@ impl ProtocolConfig { // Enable resharing at same initial version cfg.feature_flags.reshare_at_same_initial_version = true; } - 47 => { + 47 => {} + 48 => { // Use tonic networking for Mysticeti. cfg.feature_flags.consensus_network = ConsensusNetwork::Tonic; @@ -2270,7 +2272,7 @@ impl ProtocolConfig { // Enable the committed sub dag digest inclusion on the commit output cfg.feature_flags.mysticeti_use_committed_subdag_digest = true; } - 48 => { + 49 => { if chain != Chain::Testnet && chain != Chain::Mainnet { cfg.move_binary_format_version = Some(7); } diff --git a/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__Mainnet_version_47.snap b/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__Mainnet_version_47.snap index 9b3a1102bd752..b1b44bf0da3dd 100644 --- a/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__Mainnet_version_47.snap +++ b/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__Mainnet_version_47.snap @@ -43,11 +43,8 @@ feature_flags: enable_coin_deny_list: true enable_group_ops_native_functions: true reject_mutable_random_on_entry_functions: true - consensus_network: Tonic zklogin_max_epoch_upper_bound_delta: 30 reshare_at_same_initial_version: true - resolve_abort_locations_to_package_id: true - mysticeti_use_committed_subdag_digest: true max_tx_size_bytes: 131072 max_input_objects: 2048 max_size_written_objects: 5000000 diff --git a/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__Mainnet_version_49.snap b/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__Mainnet_version_49.snap new file mode 100644 index 0000000000000..6dcb4477fc0d6 --- /dev/null +++ b/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__Mainnet_version_49.snap @@ -0,0 +1,271 @@ +--- +source: crates/sui-protocol-config/src/lib.rs +expression: "ProtocolConfig::get_for_version(cur, *chain_id)" +--- +version: 49 +feature_flags: + package_upgrades: true + commit_root_state_digest: true + advance_epoch_start_time_in_safe_mode: true + loaded_child_objects_fixed: true + missing_type_is_compatibility_error: true + scoring_decision_with_validity_cutoff: true + consensus_order_end_of_epoch_last: true + disallow_adding_abilities_on_upgrade: true + disable_invariant_violation_check_in_swap_loc: true + advance_to_highest_supported_protocol_version: true + ban_entry_init: true + package_digest_hash_module: true + disallow_change_struct_type_params_on_upgrade: true + no_extraneous_module_bytes: true + narwhal_versioned_metadata: true + zklogin_auth: true + consensus_transaction_ordering: ByGasPrice + simplified_unwrap_then_delete: true + upgraded_multisig_supported: true + txn_base_cost_as_multiplier: true + shared_object_deletion: true + narwhal_new_leader_election_schedule: true + loaded_child_object_format: true + enable_jwk_consensus_updates: true + end_of_epoch_transaction_supported: true + simple_conservation_checks: true + loaded_child_object_format_type: true + receive_objects: true + enable_effects_v2: true + narwhal_certificate_v2: true + verify_legacy_zklogin_address: true + recompute_has_public_transfer_in_execution: true + accept_zklogin_in_multisig: true + include_consensus_digest_in_prologue: true + hardened_otw_check: true + allow_receiving_object_id: true + enable_coin_deny_list: true + enable_group_ops_native_functions: true + reject_mutable_random_on_entry_functions: true + consensus_network: Tonic + zklogin_max_epoch_upper_bound_delta: 30 + reshare_at_same_initial_version: true + resolve_abort_locations_to_package_id: true + mysticeti_use_committed_subdag_digest: true +max_tx_size_bytes: 131072 +max_input_objects: 2048 +max_size_written_objects: 5000000 +max_size_written_objects_system_tx: 50000000 +max_serialized_tx_effects_size_bytes: 524288 +max_serialized_tx_effects_size_bytes_system_tx: 8388608 +max_gas_payment_objects: 256 +max_modules_in_publish: 64 +max_package_dependencies: 32 +max_arguments: 512 +max_type_arguments: 16 +max_type_argument_depth: 16 +max_pure_argument_size: 16384 +max_programmable_tx_commands: 1024 +move_binary_format_version: 6 +min_move_binary_format_version: 6 +binary_module_handles: 100 +binary_struct_handles: 300 +binary_function_handles: 1500 +binary_function_instantiations: 750 +binary_signatures: 1000 +binary_constant_pool: 4000 +binary_identifiers: 10000 +binary_address_identifiers: 100 +binary_struct_defs: 200 +binary_struct_def_instantiations: 100 +binary_function_defs: 1000 +binary_field_handles: 500 +binary_field_instantiations: 250 +binary_friend_decls: 100 +max_move_object_size: 256000 +max_move_package_size: 102400 +max_publish_or_upgrade_per_ptb: 5 +max_tx_gas: 50000000000 +max_gas_price: 100000 +max_gas_computation_bucket: 5000000 +gas_rounding_step: 1000 +max_loop_depth: 5 +max_generic_instantiation_length: 32 +max_function_parameters: 128 +max_basic_blocks: 1024 +max_value_stack_size: 1024 +max_type_nodes: 256 +max_push_size: 10000 +max_struct_definitions: 200 +max_function_definitions: 1000 +max_fields_in_struct: 32 +max_dependency_depth: 100 +max_num_event_emit: 1024 +max_num_new_move_object_ids: 2048 +max_num_new_move_object_ids_system_tx: 32768 +max_num_deleted_move_object_ids: 2048 +max_num_deleted_move_object_ids_system_tx: 32768 +max_num_transferred_move_object_ids: 2048 +max_num_transferred_move_object_ids_system_tx: 32768 +max_event_emit_size: 256000 +max_event_emit_size_total: 65536000 +max_move_vector_len: 262144 +max_move_identifier_len: 128 +max_move_value_depth: 128 +max_back_edges_per_function: 10000 +max_back_edges_per_module: 10000 +max_verifier_meter_ticks_per_function: 16000000 +max_meter_ticks_per_module: 16000000 +max_meter_ticks_per_package: 16000000 +object_runtime_max_num_cached_objects: 1000 +object_runtime_max_num_cached_objects_system_tx: 16000 +object_runtime_max_num_store_entries: 1000 +object_runtime_max_num_store_entries_system_tx: 16000 +base_tx_cost_fixed: 1000 +package_publish_cost_fixed: 1000 +base_tx_cost_per_byte: 0 +package_publish_cost_per_byte: 80 +obj_access_cost_read_per_byte: 15 +obj_access_cost_mutate_per_byte: 40 +obj_access_cost_delete_per_byte: 40 +obj_access_cost_verify_per_byte: 200 +gas_model_version: 8 +obj_data_cost_refundable: 100 +obj_metadata_cost_non_refundable: 50 +storage_rebate_rate: 9900 +storage_fund_reinvest_rate: 500 +reward_slashing_rate: 10000 +storage_gas_price: 76 +max_transactions_per_checkpoint: 10000 +max_checkpoint_size_bytes: 31457280 +buffer_stake_for_protocol_upgrade_bps: 5000 +address_from_bytes_cost_base: 52 +address_to_u256_cost_base: 52 +address_from_u256_cost_base: 52 +dynamic_field_hash_type_and_key_cost_base: 100 +dynamic_field_hash_type_and_key_type_cost_per_byte: 2 +dynamic_field_hash_type_and_key_value_cost_per_byte: 2 +dynamic_field_hash_type_and_key_type_tag_cost_per_byte: 2 +dynamic_field_add_child_object_cost_base: 100 +dynamic_field_add_child_object_type_cost_per_byte: 10 +dynamic_field_add_child_object_value_cost_per_byte: 10 +dynamic_field_add_child_object_struct_tag_cost_per_byte: 10 +dynamic_field_borrow_child_object_cost_base: 100 +dynamic_field_borrow_child_object_child_ref_cost_per_byte: 10 +dynamic_field_borrow_child_object_type_cost_per_byte: 10 +dynamic_field_remove_child_object_cost_base: 100 +dynamic_field_remove_child_object_child_cost_per_byte: 2 +dynamic_field_remove_child_object_type_cost_per_byte: 2 +dynamic_field_has_child_object_cost_base: 100 +dynamic_field_has_child_object_with_ty_cost_base: 100 +dynamic_field_has_child_object_with_ty_type_cost_per_byte: 2 +dynamic_field_has_child_object_with_ty_type_tag_cost_per_byte: 2 +event_emit_cost_base: 52 +event_emit_value_size_derivation_cost_per_byte: 2 +event_emit_tag_size_derivation_cost_per_byte: 5 +event_emit_output_cost_per_byte: 10 +object_borrow_uid_cost_base: 52 +object_delete_impl_cost_base: 52 +object_record_new_uid_cost_base: 52 +transfer_transfer_internal_cost_base: 52 +transfer_freeze_object_cost_base: 52 +transfer_share_object_cost_base: 52 +transfer_receive_object_cost_base: 52 +tx_context_derive_id_cost_base: 52 +types_is_one_time_witness_cost_base: 52 +types_is_one_time_witness_type_tag_cost_per_byte: 2 +types_is_one_time_witness_type_cost_per_byte: 2 +validator_validate_metadata_cost_base: 52 +validator_validate_metadata_data_cost_per_byte: 2 +crypto_invalid_arguments_cost: 100 +bls12381_bls12381_min_sig_verify_cost_base: 52 +bls12381_bls12381_min_sig_verify_msg_cost_per_byte: 2 +bls12381_bls12381_min_sig_verify_msg_cost_per_block: 2 +bls12381_bls12381_min_pk_verify_cost_base: 52 +bls12381_bls12381_min_pk_verify_msg_cost_per_byte: 2 +bls12381_bls12381_min_pk_verify_msg_cost_per_block: 2 +ecdsa_k1_ecrecover_keccak256_cost_base: 52 +ecdsa_k1_ecrecover_keccak256_msg_cost_per_byte: 2 +ecdsa_k1_ecrecover_keccak256_msg_cost_per_block: 2 +ecdsa_k1_ecrecover_sha256_cost_base: 52 +ecdsa_k1_ecrecover_sha256_msg_cost_per_byte: 2 +ecdsa_k1_ecrecover_sha256_msg_cost_per_block: 2 +ecdsa_k1_decompress_pubkey_cost_base: 52 +ecdsa_k1_secp256k1_verify_keccak256_cost_base: 52 +ecdsa_k1_secp256k1_verify_keccak256_msg_cost_per_byte: 2 +ecdsa_k1_secp256k1_verify_keccak256_msg_cost_per_block: 2 +ecdsa_k1_secp256k1_verify_sha256_cost_base: 52 +ecdsa_k1_secp256k1_verify_sha256_msg_cost_per_byte: 2 +ecdsa_k1_secp256k1_verify_sha256_msg_cost_per_block: 2 +ecdsa_r1_ecrecover_keccak256_cost_base: 52 +ecdsa_r1_ecrecover_keccak256_msg_cost_per_byte: 2 +ecdsa_r1_ecrecover_keccak256_msg_cost_per_block: 2 +ecdsa_r1_ecrecover_sha256_cost_base: 52 +ecdsa_r1_ecrecover_sha256_msg_cost_per_byte: 2 +ecdsa_r1_ecrecover_sha256_msg_cost_per_block: 2 +ecdsa_r1_secp256r1_verify_keccak256_cost_base: 52 +ecdsa_r1_secp256r1_verify_keccak256_msg_cost_per_byte: 2 +ecdsa_r1_secp256r1_verify_keccak256_msg_cost_per_block: 2 +ecdsa_r1_secp256r1_verify_sha256_cost_base: 52 +ecdsa_r1_secp256r1_verify_sha256_msg_cost_per_byte: 2 +ecdsa_r1_secp256r1_verify_sha256_msg_cost_per_block: 2 +ecvrf_ecvrf_verify_cost_base: 52 +ecvrf_ecvrf_verify_alpha_string_cost_per_byte: 2 +ecvrf_ecvrf_verify_alpha_string_cost_per_block: 2 +ed25519_ed25519_verify_cost_base: 52 +ed25519_ed25519_verify_msg_cost_per_byte: 2 +ed25519_ed25519_verify_msg_cost_per_block: 2 +groth16_prepare_verifying_key_bls12381_cost_base: 52 +groth16_prepare_verifying_key_bn254_cost_base: 52 +groth16_verify_groth16_proof_internal_bls12381_cost_base: 52 +groth16_verify_groth16_proof_internal_bls12381_cost_per_public_input: 2 +groth16_verify_groth16_proof_internal_bn254_cost_base: 52 +groth16_verify_groth16_proof_internal_bn254_cost_per_public_input: 2 +groth16_verify_groth16_proof_internal_public_input_cost_per_byte: 2 +hash_blake2b256_cost_base: 52 +hash_blake2b256_data_cost_per_byte: 2 +hash_blake2b256_data_cost_per_block: 2 +hash_keccak256_cost_base: 52 +hash_keccak256_data_cost_per_byte: 2 +hash_keccak256_data_cost_per_block: 2 +group_ops_bls12381_decode_scalar_cost: 52 +group_ops_bls12381_decode_g1_cost: 52 +group_ops_bls12381_decode_g2_cost: 52 +group_ops_bls12381_decode_gt_cost: 52 +group_ops_bls12381_scalar_add_cost: 52 +group_ops_bls12381_g1_add_cost: 52 +group_ops_bls12381_g2_add_cost: 52 +group_ops_bls12381_gt_add_cost: 52 +group_ops_bls12381_scalar_sub_cost: 52 +group_ops_bls12381_g1_sub_cost: 52 +group_ops_bls12381_g2_sub_cost: 52 +group_ops_bls12381_gt_sub_cost: 52 +group_ops_bls12381_scalar_mul_cost: 52 +group_ops_bls12381_g1_mul_cost: 52 +group_ops_bls12381_g2_mul_cost: 52 +group_ops_bls12381_gt_mul_cost: 52 +group_ops_bls12381_scalar_div_cost: 52 +group_ops_bls12381_g1_div_cost: 52 +group_ops_bls12381_g2_div_cost: 52 +group_ops_bls12381_gt_div_cost: 52 +group_ops_bls12381_g1_hash_to_base_cost: 52 +group_ops_bls12381_g2_hash_to_base_cost: 52 +group_ops_bls12381_g1_hash_to_cost_per_byte: 2 +group_ops_bls12381_g2_hash_to_cost_per_byte: 2 +group_ops_bls12381_g1_msm_base_cost: 52 +group_ops_bls12381_g2_msm_base_cost: 52 +group_ops_bls12381_g1_msm_base_cost_per_input: 52 +group_ops_bls12381_g2_msm_base_cost_per_input: 52 +group_ops_bls12381_msm_max_len: 32 +group_ops_bls12381_pairing_cost: 52 +hmac_hmac_sha3_256_cost_base: 52 +hmac_hmac_sha3_256_input_cost_per_byte: 2 +hmac_hmac_sha3_256_input_cost_per_block: 2 +check_zklogin_id_cost_base: 200 +check_zklogin_issuer_cost_base: 200 +scoring_decision_mad_divisor: 2.3 +scoring_decision_cutoff_value: 2.5 +execution_version: 3 +consensus_bad_nodes_stake_threshold: 20 +max_jwk_votes_per_validator_per_epoch: 240 +max_age_of_jwk_in_epochs: 1 +random_beacon_reduction_allowed_delta: 800 +consensus_max_transaction_size_bytes: 262144 +consensus_max_transactions_in_block_bytes: 6291456 + diff --git a/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__Testnet_version_47.snap b/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__Testnet_version_47.snap index ee85db339582b..58ab6f88d4a36 100644 --- a/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__Testnet_version_47.snap +++ b/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__Testnet_version_47.snap @@ -32,7 +32,6 @@ feature_flags: simple_conservation_checks: true loaded_child_object_format_type: true receive_objects: true - random_beacon: true bridge: true enable_effects_v2: true narwhal_certificate_v2: true @@ -46,12 +45,9 @@ feature_flags: enable_group_ops_native_functions: true reject_mutable_random_on_entry_functions: true consensus_choice: SwapEachEpoch - consensus_network: Tonic zklogin_max_epoch_upper_bound_delta: 30 mysticeti_leader_scoring_and_schedule: true reshare_at_same_initial_version: true - resolve_abort_locations_to_package_id: true - mysticeti_use_committed_subdag_digest: true max_tx_size_bytes: 131072 max_input_objects: 2048 max_size_written_objects: 5000000 @@ -270,9 +266,6 @@ consensus_bad_nodes_stake_threshold: 20 max_jwk_votes_per_validator_per_epoch: 240 max_age_of_jwk_in_epochs: 1 random_beacon_reduction_allowed_delta: 800 -random_beacon_reduction_lower_bound: 1600 -random_beacon_dkg_timeout_round: 3000 -random_beacon_min_round_interval_ms: 200 consensus_max_transaction_size_bytes: 262144 consensus_max_transactions_in_block_bytes: 6291456 diff --git a/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__Testnet_version_49.snap b/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__Testnet_version_49.snap new file mode 100644 index 0000000000000..7c36fd5a94dc7 --- /dev/null +++ b/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__Testnet_version_49.snap @@ -0,0 +1,278 @@ +--- +source: crates/sui-protocol-config/src/lib.rs +expression: "ProtocolConfig::get_for_version(cur, *chain_id)" +--- +version: 49 +feature_flags: + package_upgrades: true + commit_root_state_digest: true + advance_epoch_start_time_in_safe_mode: true + loaded_child_objects_fixed: true + missing_type_is_compatibility_error: true + scoring_decision_with_validity_cutoff: true + consensus_order_end_of_epoch_last: true + disallow_adding_abilities_on_upgrade: true + disable_invariant_violation_check_in_swap_loc: true + advance_to_highest_supported_protocol_version: true + ban_entry_init: true + package_digest_hash_module: true + disallow_change_struct_type_params_on_upgrade: true + no_extraneous_module_bytes: true + narwhal_versioned_metadata: true + zklogin_auth: true + consensus_transaction_ordering: ByGasPrice + simplified_unwrap_then_delete: true + upgraded_multisig_supported: true + txn_base_cost_as_multiplier: true + shared_object_deletion: true + narwhal_new_leader_election_schedule: true + loaded_child_object_format: true + enable_jwk_consensus_updates: true + end_of_epoch_transaction_supported: true + simple_conservation_checks: true + loaded_child_object_format_type: true + receive_objects: true + random_beacon: true + bridge: true + enable_effects_v2: true + narwhal_certificate_v2: true + verify_legacy_zklogin_address: true + recompute_has_public_transfer_in_execution: true + accept_zklogin_in_multisig: true + include_consensus_digest_in_prologue: true + hardened_otw_check: true + allow_receiving_object_id: true + enable_coin_deny_list: true + enable_group_ops_native_functions: true + reject_mutable_random_on_entry_functions: true + consensus_choice: SwapEachEpoch + consensus_network: Tonic + zklogin_max_epoch_upper_bound_delta: 30 + mysticeti_leader_scoring_and_schedule: true + reshare_at_same_initial_version: true + resolve_abort_locations_to_package_id: true + mysticeti_use_committed_subdag_digest: true +max_tx_size_bytes: 131072 +max_input_objects: 2048 +max_size_written_objects: 5000000 +max_size_written_objects_system_tx: 50000000 +max_serialized_tx_effects_size_bytes: 524288 +max_serialized_tx_effects_size_bytes_system_tx: 8388608 +max_gas_payment_objects: 256 +max_modules_in_publish: 64 +max_package_dependencies: 32 +max_arguments: 512 +max_type_arguments: 16 +max_type_argument_depth: 16 +max_pure_argument_size: 16384 +max_programmable_tx_commands: 1024 +move_binary_format_version: 6 +min_move_binary_format_version: 6 +binary_module_handles: 100 +binary_struct_handles: 300 +binary_function_handles: 1500 +binary_function_instantiations: 750 +binary_signatures: 1000 +binary_constant_pool: 4000 +binary_identifiers: 10000 +binary_address_identifiers: 100 +binary_struct_defs: 200 +binary_struct_def_instantiations: 100 +binary_function_defs: 1000 +binary_field_handles: 500 +binary_field_instantiations: 250 +binary_friend_decls: 100 +max_move_object_size: 256000 +max_move_package_size: 102400 +max_publish_or_upgrade_per_ptb: 5 +max_tx_gas: 50000000000 +max_gas_price: 100000 +max_gas_computation_bucket: 5000000 +gas_rounding_step: 1000 +max_loop_depth: 5 +max_generic_instantiation_length: 32 +max_function_parameters: 128 +max_basic_blocks: 1024 +max_value_stack_size: 1024 +max_type_nodes: 256 +max_push_size: 10000 +max_struct_definitions: 200 +max_function_definitions: 1000 +max_fields_in_struct: 32 +max_dependency_depth: 100 +max_num_event_emit: 1024 +max_num_new_move_object_ids: 2048 +max_num_new_move_object_ids_system_tx: 32768 +max_num_deleted_move_object_ids: 2048 +max_num_deleted_move_object_ids_system_tx: 32768 +max_num_transferred_move_object_ids: 2048 +max_num_transferred_move_object_ids_system_tx: 32768 +max_event_emit_size: 256000 +max_event_emit_size_total: 65536000 +max_move_vector_len: 262144 +max_move_identifier_len: 128 +max_move_value_depth: 128 +max_back_edges_per_function: 10000 +max_back_edges_per_module: 10000 +max_verifier_meter_ticks_per_function: 16000000 +max_meter_ticks_per_module: 16000000 +max_meter_ticks_per_package: 16000000 +object_runtime_max_num_cached_objects: 1000 +object_runtime_max_num_cached_objects_system_tx: 16000 +object_runtime_max_num_store_entries: 1000 +object_runtime_max_num_store_entries_system_tx: 16000 +base_tx_cost_fixed: 1000 +package_publish_cost_fixed: 1000 +base_tx_cost_per_byte: 0 +package_publish_cost_per_byte: 80 +obj_access_cost_read_per_byte: 15 +obj_access_cost_mutate_per_byte: 40 +obj_access_cost_delete_per_byte: 40 +obj_access_cost_verify_per_byte: 200 +gas_model_version: 8 +obj_data_cost_refundable: 100 +obj_metadata_cost_non_refundable: 50 +storage_rebate_rate: 9900 +storage_fund_reinvest_rate: 500 +reward_slashing_rate: 10000 +storage_gas_price: 76 +max_transactions_per_checkpoint: 10000 +max_checkpoint_size_bytes: 31457280 +buffer_stake_for_protocol_upgrade_bps: 5000 +address_from_bytes_cost_base: 52 +address_to_u256_cost_base: 52 +address_from_u256_cost_base: 52 +dynamic_field_hash_type_and_key_cost_base: 100 +dynamic_field_hash_type_and_key_type_cost_per_byte: 2 +dynamic_field_hash_type_and_key_value_cost_per_byte: 2 +dynamic_field_hash_type_and_key_type_tag_cost_per_byte: 2 +dynamic_field_add_child_object_cost_base: 100 +dynamic_field_add_child_object_type_cost_per_byte: 10 +dynamic_field_add_child_object_value_cost_per_byte: 10 +dynamic_field_add_child_object_struct_tag_cost_per_byte: 10 +dynamic_field_borrow_child_object_cost_base: 100 +dynamic_field_borrow_child_object_child_ref_cost_per_byte: 10 +dynamic_field_borrow_child_object_type_cost_per_byte: 10 +dynamic_field_remove_child_object_cost_base: 100 +dynamic_field_remove_child_object_child_cost_per_byte: 2 +dynamic_field_remove_child_object_type_cost_per_byte: 2 +dynamic_field_has_child_object_cost_base: 100 +dynamic_field_has_child_object_with_ty_cost_base: 100 +dynamic_field_has_child_object_with_ty_type_cost_per_byte: 2 +dynamic_field_has_child_object_with_ty_type_tag_cost_per_byte: 2 +event_emit_cost_base: 52 +event_emit_value_size_derivation_cost_per_byte: 2 +event_emit_tag_size_derivation_cost_per_byte: 5 +event_emit_output_cost_per_byte: 10 +object_borrow_uid_cost_base: 52 +object_delete_impl_cost_base: 52 +object_record_new_uid_cost_base: 52 +transfer_transfer_internal_cost_base: 52 +transfer_freeze_object_cost_base: 52 +transfer_share_object_cost_base: 52 +transfer_receive_object_cost_base: 52 +tx_context_derive_id_cost_base: 52 +types_is_one_time_witness_cost_base: 52 +types_is_one_time_witness_type_tag_cost_per_byte: 2 +types_is_one_time_witness_type_cost_per_byte: 2 +validator_validate_metadata_cost_base: 52 +validator_validate_metadata_data_cost_per_byte: 2 +crypto_invalid_arguments_cost: 100 +bls12381_bls12381_min_sig_verify_cost_base: 52 +bls12381_bls12381_min_sig_verify_msg_cost_per_byte: 2 +bls12381_bls12381_min_sig_verify_msg_cost_per_block: 2 +bls12381_bls12381_min_pk_verify_cost_base: 52 +bls12381_bls12381_min_pk_verify_msg_cost_per_byte: 2 +bls12381_bls12381_min_pk_verify_msg_cost_per_block: 2 +ecdsa_k1_ecrecover_keccak256_cost_base: 52 +ecdsa_k1_ecrecover_keccak256_msg_cost_per_byte: 2 +ecdsa_k1_ecrecover_keccak256_msg_cost_per_block: 2 +ecdsa_k1_ecrecover_sha256_cost_base: 52 +ecdsa_k1_ecrecover_sha256_msg_cost_per_byte: 2 +ecdsa_k1_ecrecover_sha256_msg_cost_per_block: 2 +ecdsa_k1_decompress_pubkey_cost_base: 52 +ecdsa_k1_secp256k1_verify_keccak256_cost_base: 52 +ecdsa_k1_secp256k1_verify_keccak256_msg_cost_per_byte: 2 +ecdsa_k1_secp256k1_verify_keccak256_msg_cost_per_block: 2 +ecdsa_k1_secp256k1_verify_sha256_cost_base: 52 +ecdsa_k1_secp256k1_verify_sha256_msg_cost_per_byte: 2 +ecdsa_k1_secp256k1_verify_sha256_msg_cost_per_block: 2 +ecdsa_r1_ecrecover_keccak256_cost_base: 52 +ecdsa_r1_ecrecover_keccak256_msg_cost_per_byte: 2 +ecdsa_r1_ecrecover_keccak256_msg_cost_per_block: 2 +ecdsa_r1_ecrecover_sha256_cost_base: 52 +ecdsa_r1_ecrecover_sha256_msg_cost_per_byte: 2 +ecdsa_r1_ecrecover_sha256_msg_cost_per_block: 2 +ecdsa_r1_secp256r1_verify_keccak256_cost_base: 52 +ecdsa_r1_secp256r1_verify_keccak256_msg_cost_per_byte: 2 +ecdsa_r1_secp256r1_verify_keccak256_msg_cost_per_block: 2 +ecdsa_r1_secp256r1_verify_sha256_cost_base: 52 +ecdsa_r1_secp256r1_verify_sha256_msg_cost_per_byte: 2 +ecdsa_r1_secp256r1_verify_sha256_msg_cost_per_block: 2 +ecvrf_ecvrf_verify_cost_base: 52 +ecvrf_ecvrf_verify_alpha_string_cost_per_byte: 2 +ecvrf_ecvrf_verify_alpha_string_cost_per_block: 2 +ed25519_ed25519_verify_cost_base: 52 +ed25519_ed25519_verify_msg_cost_per_byte: 2 +ed25519_ed25519_verify_msg_cost_per_block: 2 +groth16_prepare_verifying_key_bls12381_cost_base: 52 +groth16_prepare_verifying_key_bn254_cost_base: 52 +groth16_verify_groth16_proof_internal_bls12381_cost_base: 52 +groth16_verify_groth16_proof_internal_bls12381_cost_per_public_input: 2 +groth16_verify_groth16_proof_internal_bn254_cost_base: 52 +groth16_verify_groth16_proof_internal_bn254_cost_per_public_input: 2 +groth16_verify_groth16_proof_internal_public_input_cost_per_byte: 2 +hash_blake2b256_cost_base: 52 +hash_blake2b256_data_cost_per_byte: 2 +hash_blake2b256_data_cost_per_block: 2 +hash_keccak256_cost_base: 52 +hash_keccak256_data_cost_per_byte: 2 +hash_keccak256_data_cost_per_block: 2 +group_ops_bls12381_decode_scalar_cost: 52 +group_ops_bls12381_decode_g1_cost: 52 +group_ops_bls12381_decode_g2_cost: 52 +group_ops_bls12381_decode_gt_cost: 52 +group_ops_bls12381_scalar_add_cost: 52 +group_ops_bls12381_g1_add_cost: 52 +group_ops_bls12381_g2_add_cost: 52 +group_ops_bls12381_gt_add_cost: 52 +group_ops_bls12381_scalar_sub_cost: 52 +group_ops_bls12381_g1_sub_cost: 52 +group_ops_bls12381_g2_sub_cost: 52 +group_ops_bls12381_gt_sub_cost: 52 +group_ops_bls12381_scalar_mul_cost: 52 +group_ops_bls12381_g1_mul_cost: 52 +group_ops_bls12381_g2_mul_cost: 52 +group_ops_bls12381_gt_mul_cost: 52 +group_ops_bls12381_scalar_div_cost: 52 +group_ops_bls12381_g1_div_cost: 52 +group_ops_bls12381_g2_div_cost: 52 +group_ops_bls12381_gt_div_cost: 52 +group_ops_bls12381_g1_hash_to_base_cost: 52 +group_ops_bls12381_g2_hash_to_base_cost: 52 +group_ops_bls12381_g1_hash_to_cost_per_byte: 2 +group_ops_bls12381_g2_hash_to_cost_per_byte: 2 +group_ops_bls12381_g1_msm_base_cost: 52 +group_ops_bls12381_g2_msm_base_cost: 52 +group_ops_bls12381_g1_msm_base_cost_per_input: 52 +group_ops_bls12381_g2_msm_base_cost_per_input: 52 +group_ops_bls12381_msm_max_len: 32 +group_ops_bls12381_pairing_cost: 52 +hmac_hmac_sha3_256_cost_base: 52 +hmac_hmac_sha3_256_input_cost_per_byte: 2 +hmac_hmac_sha3_256_input_cost_per_block: 2 +check_zklogin_id_cost_base: 200 +check_zklogin_issuer_cost_base: 200 +scoring_decision_mad_divisor: 2.3 +scoring_decision_cutoff_value: 2.5 +execution_version: 3 +consensus_bad_nodes_stake_threshold: 20 +max_jwk_votes_per_validator_per_epoch: 240 +max_age_of_jwk_in_epochs: 1 +random_beacon_reduction_allowed_delta: 800 +random_beacon_reduction_lower_bound: 1600 +random_beacon_dkg_timeout_round: 3000 +random_beacon_min_round_interval_ms: 200 +consensus_max_transaction_size_bytes: 262144 +consensus_max_transactions_in_block_bytes: 6291456 + diff --git a/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__version_47.snap b/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__version_47.snap index bcb34fc9a745d..162557285df9a 100644 --- a/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__version_47.snap +++ b/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__version_47.snap @@ -52,8 +52,6 @@ feature_flags: zklogin_max_epoch_upper_bound_delta: 30 mysticeti_leader_scoring_and_schedule: true reshare_at_same_initial_version: true - resolve_abort_locations_to_package_id: true - mysticeti_use_committed_subdag_digest: true max_tx_size_bytes: 131072 max_input_objects: 2048 max_size_written_objects: 5000000 @@ -276,7 +274,7 @@ max_age_of_jwk_in_epochs: 1 random_beacon_reduction_allowed_delta: 800 random_beacon_reduction_lower_bound: 1600 random_beacon_dkg_timeout_round: 3000 -random_beacon_min_round_interval_ms: 200 +random_beacon_min_round_interval_ms: 150 consensus_max_transaction_size_bytes: 262144 consensus_max_transactions_in_block_bytes: 6291456 diff --git a/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__version_48.snap b/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__version_48.snap index 02f8367ed5531..8be5aa235b8f4 100644 --- a/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__version_48.snap +++ b/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__version_48.snap @@ -54,7 +54,6 @@ feature_flags: reshare_at_same_initial_version: true resolve_abort_locations_to_package_id: true mysticeti_use_committed_subdag_digest: true - enable_vdf: true max_tx_size_bytes: 131072 max_input_objects: 2048 max_size_written_objects: 5000000 @@ -69,7 +68,7 @@ max_type_arguments: 16 max_type_argument_depth: 16 max_pure_argument_size: 16384 max_programmable_tx_commands: 1024 -move_binary_format_version: 7 +move_binary_format_version: 6 min_move_binary_format_version: 6 binary_module_handles: 100 binary_struct_handles: 300 @@ -268,8 +267,6 @@ hmac_hmac_sha3_256_input_cost_per_byte: 2 hmac_hmac_sha3_256_input_cost_per_block: 2 check_zklogin_id_cost_base: 200 check_zklogin_issuer_cost_base: 200 -vdf_verify_vdf_cost: 1500 -vdf_hash_to_input_cost: 100 scoring_decision_mad_divisor: 2.3 scoring_decision_cutoff_value: 2.5 execution_version: 3 diff --git a/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__version_49.snap b/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__version_49.snap new file mode 100644 index 0000000000000..57734f2c20ba4 --- /dev/null +++ b/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__version_49.snap @@ -0,0 +1,285 @@ +--- +source: crates/sui-protocol-config/src/lib.rs +expression: "ProtocolConfig::get_for_version(cur, *chain_id)" +--- +version: 49 +feature_flags: + package_upgrades: true + commit_root_state_digest: true + advance_epoch_start_time_in_safe_mode: true + loaded_child_objects_fixed: true + missing_type_is_compatibility_error: true + scoring_decision_with_validity_cutoff: true + consensus_order_end_of_epoch_last: true + disallow_adding_abilities_on_upgrade: true + disable_invariant_violation_check_in_swap_loc: true + advance_to_highest_supported_protocol_version: true + ban_entry_init: true + package_digest_hash_module: true + disallow_change_struct_type_params_on_upgrade: true + no_extraneous_module_bytes: true + narwhal_versioned_metadata: true + zklogin_auth: true + consensus_transaction_ordering: ByGasPrice + simplified_unwrap_then_delete: true + upgraded_multisig_supported: true + txn_base_cost_as_multiplier: true + shared_object_deletion: true + narwhal_new_leader_election_schedule: true + loaded_child_object_format: true + enable_jwk_consensus_updates: true + end_of_epoch_transaction_supported: true + simple_conservation_checks: true + loaded_child_object_format_type: true + receive_objects: true + random_beacon: true + bridge: true + enable_effects_v2: true + narwhal_certificate_v2: true + verify_legacy_zklogin_address: true + recompute_has_public_transfer_in_execution: true + accept_zklogin_in_multisig: true + include_consensus_digest_in_prologue: true + hardened_otw_check: true + allow_receiving_object_id: true + enable_poseidon: true + enable_coin_deny_list: true + enable_group_ops_native_functions: true + enable_group_ops_native_function_msm: true + reject_mutable_random_on_entry_functions: true + consensus_choice: SwapEachEpoch + consensus_network: Tonic + zklogin_max_epoch_upper_bound_delta: 30 + mysticeti_leader_scoring_and_schedule: true + reshare_at_same_initial_version: true + resolve_abort_locations_to_package_id: true + mysticeti_use_committed_subdag_digest: true + enable_vdf: true +max_tx_size_bytes: 131072 +max_input_objects: 2048 +max_size_written_objects: 5000000 +max_size_written_objects_system_tx: 50000000 +max_serialized_tx_effects_size_bytes: 524288 +max_serialized_tx_effects_size_bytes_system_tx: 8388608 +max_gas_payment_objects: 256 +max_modules_in_publish: 64 +max_package_dependencies: 32 +max_arguments: 512 +max_type_arguments: 16 +max_type_argument_depth: 16 +max_pure_argument_size: 16384 +max_programmable_tx_commands: 1024 +move_binary_format_version: 7 +min_move_binary_format_version: 6 +binary_module_handles: 100 +binary_struct_handles: 300 +binary_function_handles: 1500 +binary_function_instantiations: 750 +binary_signatures: 1000 +binary_constant_pool: 4000 +binary_identifiers: 10000 +binary_address_identifiers: 100 +binary_struct_defs: 200 +binary_struct_def_instantiations: 100 +binary_function_defs: 1000 +binary_field_handles: 500 +binary_field_instantiations: 250 +binary_friend_decls: 100 +max_move_object_size: 256000 +max_move_package_size: 102400 +max_publish_or_upgrade_per_ptb: 5 +max_tx_gas: 50000000000 +max_gas_price: 100000 +max_gas_computation_bucket: 5000000 +gas_rounding_step: 1000 +max_loop_depth: 5 +max_generic_instantiation_length: 32 +max_function_parameters: 128 +max_basic_blocks: 1024 +max_value_stack_size: 1024 +max_type_nodes: 256 +max_push_size: 10000 +max_struct_definitions: 200 +max_function_definitions: 1000 +max_fields_in_struct: 32 +max_dependency_depth: 100 +max_num_event_emit: 1024 +max_num_new_move_object_ids: 2048 +max_num_new_move_object_ids_system_tx: 32768 +max_num_deleted_move_object_ids: 2048 +max_num_deleted_move_object_ids_system_tx: 32768 +max_num_transferred_move_object_ids: 2048 +max_num_transferred_move_object_ids_system_tx: 32768 +max_event_emit_size: 256000 +max_event_emit_size_total: 65536000 +max_move_vector_len: 262144 +max_move_identifier_len: 128 +max_move_value_depth: 128 +max_back_edges_per_function: 10000 +max_back_edges_per_module: 10000 +max_verifier_meter_ticks_per_function: 16000000 +max_meter_ticks_per_module: 16000000 +max_meter_ticks_per_package: 16000000 +object_runtime_max_num_cached_objects: 1000 +object_runtime_max_num_cached_objects_system_tx: 16000 +object_runtime_max_num_store_entries: 1000 +object_runtime_max_num_store_entries_system_tx: 16000 +base_tx_cost_fixed: 1000 +package_publish_cost_fixed: 1000 +base_tx_cost_per_byte: 0 +package_publish_cost_per_byte: 80 +obj_access_cost_read_per_byte: 15 +obj_access_cost_mutate_per_byte: 40 +obj_access_cost_delete_per_byte: 40 +obj_access_cost_verify_per_byte: 200 +gas_model_version: 8 +obj_data_cost_refundable: 100 +obj_metadata_cost_non_refundable: 50 +storage_rebate_rate: 9900 +storage_fund_reinvest_rate: 500 +reward_slashing_rate: 10000 +storage_gas_price: 76 +max_transactions_per_checkpoint: 10000 +max_checkpoint_size_bytes: 31457280 +buffer_stake_for_protocol_upgrade_bps: 5000 +address_from_bytes_cost_base: 52 +address_to_u256_cost_base: 52 +address_from_u256_cost_base: 52 +dynamic_field_hash_type_and_key_cost_base: 100 +dynamic_field_hash_type_and_key_type_cost_per_byte: 2 +dynamic_field_hash_type_and_key_value_cost_per_byte: 2 +dynamic_field_hash_type_and_key_type_tag_cost_per_byte: 2 +dynamic_field_add_child_object_cost_base: 100 +dynamic_field_add_child_object_type_cost_per_byte: 10 +dynamic_field_add_child_object_value_cost_per_byte: 10 +dynamic_field_add_child_object_struct_tag_cost_per_byte: 10 +dynamic_field_borrow_child_object_cost_base: 100 +dynamic_field_borrow_child_object_child_ref_cost_per_byte: 10 +dynamic_field_borrow_child_object_type_cost_per_byte: 10 +dynamic_field_remove_child_object_cost_base: 100 +dynamic_field_remove_child_object_child_cost_per_byte: 2 +dynamic_field_remove_child_object_type_cost_per_byte: 2 +dynamic_field_has_child_object_cost_base: 100 +dynamic_field_has_child_object_with_ty_cost_base: 100 +dynamic_field_has_child_object_with_ty_type_cost_per_byte: 2 +dynamic_field_has_child_object_with_ty_type_tag_cost_per_byte: 2 +event_emit_cost_base: 52 +event_emit_value_size_derivation_cost_per_byte: 2 +event_emit_tag_size_derivation_cost_per_byte: 5 +event_emit_output_cost_per_byte: 10 +object_borrow_uid_cost_base: 52 +object_delete_impl_cost_base: 52 +object_record_new_uid_cost_base: 52 +transfer_transfer_internal_cost_base: 52 +transfer_freeze_object_cost_base: 52 +transfer_share_object_cost_base: 52 +transfer_receive_object_cost_base: 52 +tx_context_derive_id_cost_base: 52 +types_is_one_time_witness_cost_base: 52 +types_is_one_time_witness_type_tag_cost_per_byte: 2 +types_is_one_time_witness_type_cost_per_byte: 2 +validator_validate_metadata_cost_base: 52 +validator_validate_metadata_data_cost_per_byte: 2 +crypto_invalid_arguments_cost: 100 +bls12381_bls12381_min_sig_verify_cost_base: 52 +bls12381_bls12381_min_sig_verify_msg_cost_per_byte: 2 +bls12381_bls12381_min_sig_verify_msg_cost_per_block: 2 +bls12381_bls12381_min_pk_verify_cost_base: 52 +bls12381_bls12381_min_pk_verify_msg_cost_per_byte: 2 +bls12381_bls12381_min_pk_verify_msg_cost_per_block: 2 +ecdsa_k1_ecrecover_keccak256_cost_base: 52 +ecdsa_k1_ecrecover_keccak256_msg_cost_per_byte: 2 +ecdsa_k1_ecrecover_keccak256_msg_cost_per_block: 2 +ecdsa_k1_ecrecover_sha256_cost_base: 52 +ecdsa_k1_ecrecover_sha256_msg_cost_per_byte: 2 +ecdsa_k1_ecrecover_sha256_msg_cost_per_block: 2 +ecdsa_k1_decompress_pubkey_cost_base: 52 +ecdsa_k1_secp256k1_verify_keccak256_cost_base: 52 +ecdsa_k1_secp256k1_verify_keccak256_msg_cost_per_byte: 2 +ecdsa_k1_secp256k1_verify_keccak256_msg_cost_per_block: 2 +ecdsa_k1_secp256k1_verify_sha256_cost_base: 52 +ecdsa_k1_secp256k1_verify_sha256_msg_cost_per_byte: 2 +ecdsa_k1_secp256k1_verify_sha256_msg_cost_per_block: 2 +ecdsa_r1_ecrecover_keccak256_cost_base: 52 +ecdsa_r1_ecrecover_keccak256_msg_cost_per_byte: 2 +ecdsa_r1_ecrecover_keccak256_msg_cost_per_block: 2 +ecdsa_r1_ecrecover_sha256_cost_base: 52 +ecdsa_r1_ecrecover_sha256_msg_cost_per_byte: 2 +ecdsa_r1_ecrecover_sha256_msg_cost_per_block: 2 +ecdsa_r1_secp256r1_verify_keccak256_cost_base: 52 +ecdsa_r1_secp256r1_verify_keccak256_msg_cost_per_byte: 2 +ecdsa_r1_secp256r1_verify_keccak256_msg_cost_per_block: 2 +ecdsa_r1_secp256r1_verify_sha256_cost_base: 52 +ecdsa_r1_secp256r1_verify_sha256_msg_cost_per_byte: 2 +ecdsa_r1_secp256r1_verify_sha256_msg_cost_per_block: 2 +ecvrf_ecvrf_verify_cost_base: 52 +ecvrf_ecvrf_verify_alpha_string_cost_per_byte: 2 +ecvrf_ecvrf_verify_alpha_string_cost_per_block: 2 +ed25519_ed25519_verify_cost_base: 52 +ed25519_ed25519_verify_msg_cost_per_byte: 2 +ed25519_ed25519_verify_msg_cost_per_block: 2 +groth16_prepare_verifying_key_bls12381_cost_base: 52 +groth16_prepare_verifying_key_bn254_cost_base: 52 +groth16_verify_groth16_proof_internal_bls12381_cost_base: 52 +groth16_verify_groth16_proof_internal_bls12381_cost_per_public_input: 2 +groth16_verify_groth16_proof_internal_bn254_cost_base: 52 +groth16_verify_groth16_proof_internal_bn254_cost_per_public_input: 2 +groth16_verify_groth16_proof_internal_public_input_cost_per_byte: 2 +hash_blake2b256_cost_base: 52 +hash_blake2b256_data_cost_per_byte: 2 +hash_blake2b256_data_cost_per_block: 2 +hash_keccak256_cost_base: 52 +hash_keccak256_data_cost_per_byte: 2 +hash_keccak256_data_cost_per_block: 2 +poseidon_bn254_cost_base: 260 +poseidon_bn254_cost_per_block: 10 +group_ops_bls12381_decode_scalar_cost: 52 +group_ops_bls12381_decode_g1_cost: 52 +group_ops_bls12381_decode_g2_cost: 52 +group_ops_bls12381_decode_gt_cost: 52 +group_ops_bls12381_scalar_add_cost: 52 +group_ops_bls12381_g1_add_cost: 52 +group_ops_bls12381_g2_add_cost: 52 +group_ops_bls12381_gt_add_cost: 52 +group_ops_bls12381_scalar_sub_cost: 52 +group_ops_bls12381_g1_sub_cost: 52 +group_ops_bls12381_g2_sub_cost: 52 +group_ops_bls12381_gt_sub_cost: 52 +group_ops_bls12381_scalar_mul_cost: 52 +group_ops_bls12381_g1_mul_cost: 52 +group_ops_bls12381_g2_mul_cost: 52 +group_ops_bls12381_gt_mul_cost: 52 +group_ops_bls12381_scalar_div_cost: 52 +group_ops_bls12381_g1_div_cost: 52 +group_ops_bls12381_g2_div_cost: 52 +group_ops_bls12381_gt_div_cost: 52 +group_ops_bls12381_g1_hash_to_base_cost: 52 +group_ops_bls12381_g2_hash_to_base_cost: 52 +group_ops_bls12381_g1_hash_to_cost_per_byte: 2 +group_ops_bls12381_g2_hash_to_cost_per_byte: 2 +group_ops_bls12381_g1_msm_base_cost: 52 +group_ops_bls12381_g2_msm_base_cost: 52 +group_ops_bls12381_g1_msm_base_cost_per_input: 52 +group_ops_bls12381_g2_msm_base_cost_per_input: 52 +group_ops_bls12381_msm_max_len: 32 +group_ops_bls12381_pairing_cost: 52 +hmac_hmac_sha3_256_cost_base: 52 +hmac_hmac_sha3_256_input_cost_per_byte: 2 +hmac_hmac_sha3_256_input_cost_per_block: 2 +check_zklogin_id_cost_base: 200 +check_zklogin_issuer_cost_base: 200 +vdf_verify_vdf_cost: 1500 +vdf_hash_to_input_cost: 100 +scoring_decision_mad_divisor: 2.3 +scoring_decision_cutoff_value: 2.5 +execution_version: 3 +consensus_bad_nodes_stake_threshold: 20 +max_jwk_votes_per_validator_per_epoch: 240 +max_age_of_jwk_in_epochs: 1 +random_beacon_reduction_allowed_delta: 800 +random_beacon_reduction_lower_bound: 1600 +random_beacon_dkg_timeout_round: 3000 +random_beacon_min_round_interval_ms: 200 +consensus_max_transaction_size_bytes: 262144 +consensus_max_transactions_in_block_bytes: 6291456 + diff --git a/crates/sui-swarm-config/tests/snapshots/snapshot_tests__genesis_config_snapshot_matches.snap b/crates/sui-swarm-config/tests/snapshots/snapshot_tests__genesis_config_snapshot_matches.snap index ac60a57c9d6fe..1502af853460c 100644 --- a/crates/sui-swarm-config/tests/snapshots/snapshot_tests__genesis_config_snapshot_matches.snap +++ b/crates/sui-swarm-config/tests/snapshots/snapshot_tests__genesis_config_snapshot_matches.snap @@ -6,7 +6,7 @@ ssfn_config_info: ~ validator_config_info: ~ parameters: chain_start_timestamp_ms: 0 - protocol_version: 48 + protocol_version: 49 allow_insertion_of_extra_objects: true epoch_duration_ms: 86400000 stake_subsidy_start_epoch: 0 diff --git a/crates/sui-swarm-config/tests/snapshots/snapshot_tests__populated_genesis_snapshot_matches-2.snap b/crates/sui-swarm-config/tests/snapshots/snapshot_tests__populated_genesis_snapshot_matches-2.snap index 1dde74f38315d..12badb1bec364 100644 --- a/crates/sui-swarm-config/tests/snapshots/snapshot_tests__populated_genesis_snapshot_matches-2.snap +++ b/crates/sui-swarm-config/tests/snapshots/snapshot_tests__populated_genesis_snapshot_matches-2.snap @@ -3,7 +3,7 @@ source: crates/sui-swarm-config/tests/snapshot_tests.rs expression: genesis.sui_system_object().into_genesis_version_for_tooling() --- epoch: 0 -protocol_version: 48 +protocol_version: 49 system_state_version: 1 validators: total_stake: 20000000000000000 @@ -240,13 +240,13 @@ validators: next_epoch_worker_address: ~ extra_fields: id: - id: "0xa1ff06590dbd12f617e8f2c9d8e2e0aa66b936ddef0753ec821e3a84814cc8f0" + id: "0xe8fae25792d4718efd9f2ca4f27a27b93f147340b34297db0a26f7b38d9d51fd" size: 0 voting_power: 10000 - operation_cap_id: "0xe1c23dae44530859cd66d5b3c4dd40f2887fb28b9791679426675fda6b0219c7" + operation_cap_id: "0xff47b0d4c3bb44b3e9938cd07996979d3b5d3069f1a4eac1a05fc19a4c338543" gas_price: 1000 staking_pool: - id: "0x35465e5265fe7f26eba1ef5cd90fd376a3db04e6c6017f06621475adacee2b26" + id: "0x4b29c4a122e1891400d6b29c934d1f0bab7313575fd8f9f340972a5eeda8c1b3" activation_epoch: 0 deactivation_epoch: ~ sui_balance: 20000000000000000 @@ -254,14 +254,14 @@ validators: value: 0 pool_token_balance: 20000000000000000 exchange_rates: - id: "0xf290a4149d6a2d52c2a3ce4cc6f9ec84de672725c2fe5519de4269b53a2d9bb3" + id: "0xa8dc4f3d694f0478ca3ffcb022c0eae2451df679f6fd9ac0b2c071f6685a0bb6" size: 1 pending_stake: 0 pending_total_sui_withdraw: 0 pending_pool_token_withdraw: 0 extra_fields: id: - id: "0x2e90cb4042988b751f8d1a6592aedc3afcd8156acd8d014de080c074a1b2222e" + id: "0x7d10f6a60dc538c66ac421b683976b3001c4f6bb8c92ae4db38d258bff3927a8" size: 0 commission_rate: 200 next_epoch_stake: 20000000000000000 @@ -269,27 +269,27 @@ validators: next_epoch_commission_rate: 200 extra_fields: id: - id: "0x257c49f82dfc6f179ede2fda03e25fe73a58c97ef1d9d2d2ca77db710aed40f2" + id: "0xb6b89c52f81e1eb6b3b590664c86618458dfc9ff41967046947e06da3a6dcbc2" size: 0 pending_active_validators: contents: - id: "0xe5f6f96f60533c64ec4f45c76604572f68920bf59ed2be37b34948003ef816c4" + id: "0x65c06d37117ca9763f243033920620f0f76b74bc6605b57bf4c2f9fb1a3998cf" size: 0 pending_removals: [] staking_pool_mappings: - id: "0x6c81f9fa2cf110470cd10e3ab483ae7c619c4d8315004015686080d24c728071" + id: "0xd257af422c5f8a7f52e2f82582c66da7d3c8f88b8e95c8d2507220ee42bc687f" size: 1 inactive_validators: - id: "0xddebffbd50a286218b14af21c40725c01506a943ed6b947c50095244a4725b92" + id: "0xcd4ef7ea4703322e34997c76be982a20df250b9a8b5b380a32fe99f876c80496" size: 0 validator_candidates: - id: "0x73c69366fd5d9c54e27ffef93f4ad77808edfd0a943733e386a7c30c941dbb69" + id: "0x98d7fd6ad6e28bf394139e2b3fd57887134cedc9df76a5a659e364d83a140781" size: 0 at_risk_validators: contents: [] extra_fields: id: - id: "0xa830113361022b2604e40277bc1f213a7da7d94c84e7a81bf281027ebbc4d0cf" + id: "0xe8f2e50fac412b2274f6e25542d52b4a07f5611a23f84272228c60e81fc03dcd" size: 0 storage_fund: total_object_storage_rebates: @@ -306,7 +306,7 @@ parameters: validator_low_stake_grace_period: 7 extra_fields: id: - id: "0xc3e4654ee934b89a348699087e7f541d9209dd530b707b278e7a419b01958b0e" + id: "0xce148e02dfa82bd4630e8acfb73a76049c89b44cffc9d7117398b1984534d56a" size: 0 reference_gas_price: 1000 validator_report_records: @@ -320,7 +320,7 @@ stake_subsidy: stake_subsidy_decrease_rate: 1000 extra_fields: id: - id: "0x01152bba9266a8d45c9745e85808d002f675ea02ea2010ffc645d6ec318fbeed" + id: "0xe0c67053d256dc44ff239bec47b6e77b4990d1d9ad50e979c86dabcf0a8e17aa" size: 0 safe_mode: false safe_mode_storage_rewards: @@ -332,6 +332,6 @@ safe_mode_non_refundable_storage_fee: 0 epoch_start_timestamp_ms: 10 extra_fields: id: - id: "0x44e0d138ebb8a4d52a7bf50ad94d3b6b3141eb68db7eb414dbac6abebc077ad6" + id: "0x53bdbad748c945e8ad101cccc13ef17f08a25545190890bf75e03b028f598012" size: 0 From 7de9395407d70fdf345793a0dbad8b944b80c7fd Mon Sep 17 00:00:00 2001 From: Dario Russi <113150618+dariorussi@users.noreply.github.com> Date: Tue, 28 May 2024 19:16:54 +0200 Subject: [PATCH 011/324] towards 100% test coverage (#17895) ## Description Some cleanup and 100% test coverage for `message.move` ## Test plan This is all about testing... --- ## Release notes Check each box that your changes affect. If none of the boxes relate to your changes, release notes aren't required. For each box you select, include information after the relevant heading that describes the impact of your changes that a user might notice and any actions they must take to implement updates. - [ ] Protocol: - [ ] Nodes (Validators and Full nodes): - [ ] Indexer: - [ ] JSON-RPC: - [ ] GraphQL: - [ ] CLI: - [ ] Rust SDK: --- crates/sui-framework/docs/bridge/message.md | 16 - .../packages/bridge/sources/message.move | 21 +- .../packages/bridge/tests/message_tests.move | 492 +++++++++++++++--- 3 files changed, 431 insertions(+), 98 deletions(-) diff --git a/crates/sui-framework/docs/bridge/message.md b/crates/sui-framework/docs/bridge/message.md index f401484809207..84c43b0d2ee2b 100644 --- a/crates/sui-framework/docs/bridge/message.md +++ b/crates/sui-framework/docs/bridge/message.md @@ -563,8 +563,6 @@ title: Module `0xb::message` let token_type = bcs.peel_u8(); let amount = peel_u64_be(&mut bcs); - // TODO: add test case for invalid chain id - // TODO: replace with `chain_ids::is_valid_chain_id()` chain_ids::assert_valid_chain_id(target_chain); assert!(bcs.into_remainder_bytes().is_empty(), ETrailingBytes); @@ -629,7 +627,6 @@ Emergency op payload is just a single byte let blocklist_type = bcs.peel_u8(); let mut address_count = bcs.peel_u8(); - // TODO: add test case for 0 value assert!(address_count != 0, EEmptyList); let mut validator_eth_addresses = vector[]; @@ -676,7 +673,6 @@ Emergency op payload is just a single byte let sending_chain = bcs.peel_u8(); let limit = peel_u64_be(&mut bcs); - // TODO: add test case for invalid chain id chain_ids::assert_valid_chain_id(sending_chain); assert!(bcs.into_remainder_bytes().is_empty(), ETrailingBytes); @@ -844,9 +840,6 @@ Token Transfer Message Format: token_type: u8, amount: u64 ): BridgeMessage { - // TODO: add test case for invalid chain id - // TODO: add test case for invalid chain id - // TODO: replace with `chain_ids::is_valid_chain_id()` chain_ids::assert_valid_chain_id(source_chain); chain_ids::assert_valid_chain_id(target_chain); @@ -905,8 +898,6 @@ Emergency Op Message Format: seq_num: u64, op_type: u8, ): BridgeMessage { - // TODO: add test case for invalid chain id - // TODO: replace with `chain_ids::is_valid_chain_id()` chain_ids::assert_valid_chain_id(source_chain); BridgeMessage { @@ -953,8 +944,6 @@ Blocklist Message Format: blocklist_type: u8, validator_ecdsa_addresses: vector<vector<u8>>, ): BridgeMessage { - // TODO: add test case for invalid chain id - // TODO: replace with `chain_ids::is_valid_chain_id()` chain_ids::assert_valid_chain_id(source_chain); let address_length = validator_ecdsa_addresses.length(); @@ -1011,9 +1000,6 @@ Update bridge limit Message Format: sending_chain: u8, new_limit: u64, ): BridgeMessage { - // TODO: add test case for invalid chain id - // TODO: add test case for invalid chain id - // TODO: replace with `chain_ids::is_valid_chain_id()` chain_ids::assert_valid_chain_id(receiving_chain); chain_ids::assert_valid_chain_id(sending_chain); @@ -1062,8 +1048,6 @@ Update asset price message seq_num: u64, new_price: u64, ): BridgeMessage { - // TODO: add test case for invalid chain id - // TODO: replace with `chain_ids::is_valid_chain_id()` chain_ids::assert_valid_chain_id(source_chain); let mut payload = vector[token_id]; diff --git a/crates/sui-framework/packages/bridge/sources/message.move b/crates/sui-framework/packages/bridge/sources/message.move index a764d5c3d8207..889eaf09d6e8d 100644 --- a/crates/sui-framework/packages/bridge/sources/message.move +++ b/crates/sui-framework/packages/bridge/sources/message.move @@ -105,8 +105,6 @@ module bridge::message { let token_type = bcs.peel_u8(); let amount = peel_u64_be(&mut bcs); - // TODO: add test case for invalid chain id - // TODO: replace with `chain_ids::is_valid_chain_id()` chain_ids::assert_valid_chain_id(target_chain); assert!(bcs.into_remainder_bytes().is_empty(), ETrailingBytes); @@ -131,7 +129,6 @@ module bridge::message { let blocklist_type = bcs.peel_u8(); let mut address_count = bcs.peel_u8(); - // TODO: add test case for 0 value assert!(address_count != 0, EEmptyList); let mut validator_eth_addresses = vector[]; @@ -158,7 +155,6 @@ module bridge::message { let sending_chain = bcs.peel_u8(); let limit = peel_u64_be(&mut bcs); - // TODO: add test case for invalid chain id chain_ids::assert_valid_chain_id(sending_chain); assert!(bcs.into_remainder_bytes().is_empty(), ETrailingBytes); @@ -246,9 +242,6 @@ module bridge::message { token_type: u8, amount: u64 ): BridgeMessage { - // TODO: add test case for invalid chain id - // TODO: add test case for invalid chain id - // TODO: replace with `chain_ids::is_valid_chain_id()` chain_ids::assert_valid_chain_id(source_chain); chain_ids::assert_valid_chain_id(target_chain); @@ -287,8 +280,6 @@ module bridge::message { seq_num: u64, op_type: u8, ): BridgeMessage { - // TODO: add test case for invalid chain id - // TODO: replace with `chain_ids::is_valid_chain_id()` chain_ids::assert_valid_chain_id(source_chain); BridgeMessage { @@ -315,8 +306,6 @@ module bridge::message { blocklist_type: u8, validator_ecdsa_addresses: vector>, ): BridgeMessage { - // TODO: add test case for invalid chain id - // TODO: replace with `chain_ids::is_valid_chain_id()` chain_ids::assert_valid_chain_id(source_chain); let address_length = validator_ecdsa_addresses.length(); @@ -353,9 +342,6 @@ module bridge::message { sending_chain: u8, new_limit: u64, ): BridgeMessage { - // TODO: add test case for invalid chain id - // TODO: add test case for invalid chain id - // TODO: replace with `chain_ids::is_valid_chain_id()` chain_ids::assert_valid_chain_id(receiving_chain); chain_ids::assert_valid_chain_id(sending_chain); @@ -384,8 +370,6 @@ module bridge::message { seq_num: u64, new_price: u64, ): BridgeMessage { - // TODO: add test case for invalid chain id - // TODO: replace with `chain_ids::is_valid_chain_id()` chain_ids::assert_valid_chain_id(source_chain); let mut payload = vector[token_id]; @@ -659,6 +643,11 @@ module bridge::message { reverse_bytes(bytes) } + #[test_only] + public(package) fun set_payload(message: &mut BridgeMessage, bytes: vector) { + message.payload = bytes; + } + #[test_only] public(package) fun make_add_token_on_sui( native_token: bool, diff --git a/crates/sui-framework/packages/bridge/tests/message_tests.move b/crates/sui-framework/packages/bridge/tests/message_tests.move index 27eae1f801480..4384cfa1d8e93 100644 --- a/crates/sui-framework/packages/bridge/tests/message_tests.move +++ b/crates/sui-framework/packages/bridge/tests/message_tests.move @@ -6,43 +6,44 @@ module bridge::message_tests { use bridge::{ chain_ids, message::{ - blocklist_validator_addresses, + BridgeMessage, blocklist_validator_addresses, create_add_tokens_on_sui_message, create_blocklist_message, create_emergency_op_message, create_token_bridge_message, create_update_asset_price_message, create_update_bridge_limit_message, - deserialize_message_test_only, extract_add_tokens_on_sui, - extract_blocklist_payload, extract_token_bridge_payload, + deserialize_message_test_only, emergency_op_pause, emergency_op_unpause, + extract_add_tokens_on_sui, extract_blocklist_payload, extract_token_bridge_payload, extract_update_asset_price, extract_update_bridge_limit, make_add_token_on_sui, - make_payload, peel_u64_be_for_testing, reverse_bytes_test, - serialize_message, - update_asset_price_payload_token_id, - update_bridge_limit_payload_limit, + make_generic_message, make_payload, peel_u64_be_for_testing, reverse_bytes_test, + serialize_message, set_payload, + update_asset_price_payload_token_id, update_bridge_limit_payload_limit, update_bridge_limit_payload_receiving_chain, update_bridge_limit_payload_sending_chain, }, treasury::{Self, BTC, ETH, USDC}, }; use std::ascii; - use sui::{address, balance, coin, hex, test_scenario, test_utils::{assert_eq, destroy}}; + use sui::{ + address, balance, + coin::{Self, Coin}, + hex, test_scenario, + test_utils::{assert_eq, destroy}, + }; use sui::bcs; + const INVALID_CHAIN: u8 = 42; + #[test] fun test_message_serialization_sui_to_eth() { let sender_address = address::from_u256(100); let mut scenario = test_scenario::begin(sender_address); let ctx = test_scenario::ctx(&mut scenario); - let coin = coin::mint_for_testing(12345, ctx); - let token_bridge_message = create_token_bridge_message( - chain_ids::sui_testnet(), // source chain - 10, // seq_num - address::to_bytes(sender_address), // sender address - chain_ids::eth_sepolia(), // target_chain - // Eth address is 20 bytes long - hex::decode(b"00000000000000000000000000000000000000c8"), // target_address - 3u8, // token_type - balance::value(coin::balance(&coin)) // amount: u64 + let token_bridge_message = default_token_bridge_message( + sender_address, + &coin, + chain_ids::sui_testnet(), + chain_ids::eth_sepolia(), ); // Test payload extraction @@ -51,9 +52,14 @@ module bridge::message_tests { chain_ids::eth_sepolia(), hex::decode(b"00000000000000000000000000000000000000c8"), 3u8, - balance::value(coin::balance(&coin)) + balance::value(coin::balance(&coin)), ); - assert!(token_bridge_message.extract_token_bridge_payload() == token_payload); + let payload = token_bridge_message.extract_token_bridge_payload(); + assert!(payload.token_target_chain() == token_payload.token_target_chain()); + assert!(payload.token_target_address() == token_payload.token_target_address()); + assert!(payload.token_type() == token_payload.token_type()); + assert!(payload.token_amount() == token_payload.token_amount()); + assert!(payload == token_payload); // Test message serialization let message = serialize_message(token_bridge_message); @@ -84,7 +90,7 @@ module bridge::message_tests { chain_ids::sui_testnet(), // target_chain address::to_bytes(address_1), // target address 3u8, // token_type - balance::value(coin::balance(&coin)) // amount: u64 + balance::value(coin::balance(&coin)), // amount: u64 ); // Test payload extraction @@ -115,14 +121,12 @@ module bridge::message_tests { let emergency_op_message = create_emergency_op_message( chain_ids::sui_testnet(), // source chain 10, // seq_num - 0, + emergency_op_pause(), ); // Test message serialization let message = serialize_message(emergency_op_message); - let expected_msg = hex::decode( - b"0201000000000000000a0100", - ); + let expected_msg = hex::decode(b"0201000000000000000a0100"); assert!(message == expected_msg); assert!(emergency_op_message == deserialize_message_test_only(message)); @@ -134,14 +138,12 @@ module bridge::message_tests { let emergency_op_message = create_emergency_op_message( chain_ids::sui_custom(), 55, // seq_num - 0, // pause + emergency_op_pause(), ); // Test message serialization let message = serialize_message(emergency_op_message); - let expected_msg = hex::decode( - b"020100000000000000370200", - ); + let expected_msg = hex::decode(b"020100000000000000370200"); assert_eq(expected_msg, message); assert!(emergency_op_message == deserialize_message_test_only(message)); @@ -157,7 +159,7 @@ module bridge::message_tests { chain_ids::sui_testnet(), // source chain 10, // seq_num 0, - validator_eth_addresses + validator_eth_addresses, ); // Test message serialization let message = serialize_message(blocklist_message); @@ -184,7 +186,7 @@ module bridge::message_tests { chain_ids::sui_custom(), // source chain 129, // seq_num 0, // blocklist - validator_eth_addresses + validator_eth_addresses, ); // Test message serialization let message = serialize_message(blocklist_message); @@ -205,7 +207,7 @@ module bridge::message_tests { chain_ids::sui_custom(), // source chain 68, // seq_num 1, // unblocklist - validator_eth_addresses + validator_eth_addresses, ); // Test message serialization let message = serialize_message(blocklist_message); @@ -227,14 +229,12 @@ module bridge::message_tests { chain_ids::sui_testnet(), // source chain 10, // seq_num chain_ids::eth_sepolia(), - 1000000000 + 1000000000, ); // Test message serialization let message = serialize_message(update_bridge_limit); - let expected_msg = hex::decode( - b"0301000000000000000a010b000000003b9aca00", - ); + let expected_msg = hex::decode(b"0301000000000000000a010b000000003b9aca00"); assert!(message == expected_msg); assert!(update_bridge_limit == deserialize_message_test_only(message)); @@ -243,12 +243,10 @@ module bridge::message_tests { assert!( bridge_limit.update_bridge_limit_payload_receiving_chain() == chain_ids::sui_testnet(), - 0, ); assert!( bridge_limit.update_bridge_limit_payload_sending_chain() == chain_ids::eth_sepolia(), - 0, ); assert!(bridge_limit.update_bridge_limit_payload_limit() == 1000000000); } @@ -260,14 +258,12 @@ module bridge::message_tests { chain_ids::sui_custom(), // source chain 15, // seq_num chain_ids::eth_custom(), - 10_000_000_000 // 1M USD + 10_000_000_000, // 1M USD ); // Test message serialization let message = serialize_message(update_bridge_limit); - let expected_msg = hex::decode( - b"0301000000000000000f020c00000002540be400", - ); + let expected_msg = hex::decode(b"0301000000000000000f020c00000002540be400"); assert_eq(message, expected_msg); assert!(update_bridge_limit == deserialize_message_test_only(message)); @@ -276,12 +272,10 @@ module bridge::message_tests { assert!( bridge_limit.update_bridge_limit_payload_receiving_chain() == chain_ids::sui_custom(), - 0, ); assert!( bridge_limit.update_bridge_limit_payload_sending_chain() == chain_ids::eth_custom(), - 0, ); assert!(bridge_limit.update_bridge_limit_payload_limit() == 10_000_000_000); } @@ -292,14 +286,12 @@ module bridge::message_tests { 2, chain_ids::sui_testnet(), // source chain 10, // seq_num - 12345 + 12345, ); // Test message serialization let message = serialize_message(asset_price_message); - let expected_msg = hex::decode( - b"0401000000000000000a01020000000000003039", - ); + let expected_msg = hex::decode(b"0401000000000000000a01020000000000003039"); assert!(message == expected_msg); assert!(asset_price_message == deserialize_message_test_only(message)); @@ -312,7 +304,6 @@ module bridge::message_tests { assert!( asset_price.update_asset_price_payload_token_id() == treasury::token_id(&treasury), - 0, ); assert!(asset_price.update_asset_price_payload_new_price() == 12345); @@ -331,14 +322,12 @@ module bridge::message_tests { treasury.token_id(), chain_ids::sui_custom(), // source chain 266, // seq_num - 1_000_000_000 // $100k USD + 1_000_000_000, // $100k USD ); // Test message serialization let message = serialize_message(asset_price_message); - let expected_msg = hex::decode( - b"0401000000000000010a0201000000003b9aca00", - ); + let expected_msg = hex::decode(b"0401000000000000010a0201000000003b9aca00"); assert_eq(expected_msg, message); assert!(asset_price_message == deserialize_message_test_only(message)); @@ -347,7 +336,6 @@ module bridge::message_tests { assert!( asset_price.update_asset_price_payload_token_id() == treasury::token_id(&treasury), - 0, ); assert!(asset_price.update_asset_price_payload_new_price() == 1_000_000_000); @@ -366,10 +354,29 @@ module bridge::message_tests { 1, // seq_num false, // native_token vector[treasury.token_id(), treasury.token_id()], - vector[ascii::string(b"28ac483b6f2b62dd58abdf0bbc3f86900d86bbdc710c704ba0b33b7f1c4b43c8::btc::BTC"), ascii::string(b"0xbd69a54e7c754a332804f325307c6627c06631dc41037239707e3242bc542e99::eth::ETH")], - vector[100, 100] + vector[ + ascii::string( + b"28ac483b6f2b62dd58abdf0bbc3f86900d86bbdc710c704ba0b33b7f1c4b43c8::btc::BTC", + ), + ascii::string( + b"0xbd69a54e7c754a332804f325307c6627c06631dc41037239707e3242bc542e99::eth::ETH", + ), + ], + vector[100, 100], ); let payload = add_tokens_on_sui_message.extract_add_tokens_on_sui(); + assert!(payload.is_native() == false); + assert!( + payload.token_ids() == vector[treasury.token_id(), treasury.token_id()], + ); + assert!( + payload.token_type_names() == + vector[ + ascii::string(b"28ac483b6f2b62dd58abdf0bbc3f86900d86bbdc710c704ba0b33b7f1c4b43c8::btc::BTC"), + ascii::string(b"0xbd69a54e7c754a332804f325307c6627c06631dc41037239707e3242bc542e99::eth::ETH"), + ], + ); + assert!(payload.token_prices() == vector[100, 100]); assert!( payload == make_add_token_on_sui( false, @@ -377,7 +384,6 @@ module bridge::message_tests { vector[ascii::string(b"28ac483b6f2b62dd58abdf0bbc3f86900d86bbdc710c704ba0b33b7f1c4b43c8::btc::BTC"), ascii::string(b"0xbd69a54e7c754a332804f325307c6627c06631dc41037239707e3242bc542e99::eth::ETH")], vector[100, 100], ), - 0, ); // Test message serialization let message = serialize_message(add_tokens_on_sui_message); @@ -403,12 +409,20 @@ module bridge::message_tests { false, // native_token vector[1, 2, 3, 4], vector[ - ascii::string(b"9b5e13bcd0cb23ff25c07698e89d48056c745338d8c9dbd033a4172b87027073::btc::BTC"), - ascii::string(b"7970d71c03573f540a7157f0d3970e117effa6ae16cefd50b45c749670b24e6a::eth::ETH"), - ascii::string(b"500e429a24478405d5130222b20f8570a746b6bc22423f14b4d4e6a8ea580736::usdc::USDC"), - ascii::string(b"46bfe51da1bd9511919a92eb1154149b36c0f4212121808e13e3e5857d607a9c::usdt::USDT") + ascii::string( + b"9b5e13bcd0cb23ff25c07698e89d48056c745338d8c9dbd033a4172b87027073::btc::BTC", + ), + ascii::string( + b"7970d71c03573f540a7157f0d3970e117effa6ae16cefd50b45c749670b24e6a::eth::ETH", + ), + ascii::string( + b"500e429a24478405d5130222b20f8570a746b6bc22423f14b4d4e6a8ea580736::usdc::USDC", + ), + ascii::string( + b"46bfe51da1bd9511919a92eb1154149b36c0f4212121808e13e3e5857d607a9c::usdt::USDT", + ) ], - vector[500_000_000, 30_000_000, 1_000, 1_000] + vector[500_000_000, 30_000_000, 1_000, 1_000], ); let payload = add_tokens_on_sui_message.extract_add_tokens_on_sui(); assert!( @@ -423,7 +437,6 @@ module bridge::message_tests { ], vector[500_000_000, 30_000_000, 1_000, 1_000], ), - 0, ); // Test message serialization let message = serialize_message(add_tokens_on_sui_message); @@ -437,8 +450,10 @@ module bridge::message_tests { message_bytes.append(message); let pubkey = sui::ecdsa_k1::secp256k1_ecrecover( - &x"b75e64b040eef6fa510e4b9be853f0d35183de635c6456c190714f9546b163ba12583e615a2e9944ec2d21b520aebd9b14e181dcae0fcc6cdaefc0aa235b3abe00" - , &message_bytes, 0); + &x"b75e64b040eef6fa510e4b9be853f0d35183de635c6456c190714f9546b163ba12583e615a2e9944ec2d21b520aebd9b14e181dcae0fcc6cdaefc0aa235b3abe00", + &message_bytes, + 0, + ); assert_eq(pubkey, x"025a8c385af9a76aa506c395e240735839cb06531301f9b396e5f9ef8eeb0d8879"); destroy(treasury); @@ -453,10 +468,355 @@ module bridge::message_tests { } #[test] - public(package) fun test_peel_u64_be() { + fun test_peel_u64_be() { let input = hex::decode(b"0000000000003039"); let expected = 12345u64; let mut bcs = bcs::new(input); assert!(peel_u64_be_for_testing(&mut bcs) == expected) } + + #[test] + #[expected_failure(abort_code = bridge::message::ETrailingBytes)] + fun test_bad_payload() { + let sender_address = address::from_u256(100); + let mut scenario = test_scenario::begin(@0x1); + let ctx = test_scenario::ctx(&mut scenario); + let coin = coin::mint_for_testing(12345, ctx); + let mut token_bridge_message = create_token_bridge_message( + chain_ids::sui_testnet(), // source chain + 10, // seq_num + address::to_bytes(sender_address), // sender address + chain_ids::eth_sepolia(), // target_chain + // Eth address is 20 bytes long + hex::decode(b"00000000000000000000000000000000000000c8"), // target_address + 3u8, // token_type + balance::value(coin::balance(&coin)), // amount: u64 + ); + let mut payload = token_bridge_message.payload(); + payload.push_back(0u8); + token_bridge_message.set_payload(payload); + + token_bridge_message.extract_token_bridge_payload(); + + abort 0 + } + + #[test] + #[expected_failure(abort_code = bridge::message::ETrailingBytes)] + fun test_bad_emergency_op() { + let mut msg = create_emergency_op_message( + chain_ids::sui_testnet(), + 0, + emergency_op_pause(), + ); + let mut payload = msg.payload(); + payload.push_back(0u8); + msg.set_payload(payload); + msg.extract_emergency_op_payload(); + } + + #[test] + #[expected_failure(abort_code = bridge::message::EEmptyList)] + fun test_bad_blocklist() { + let blocklist_message = create_blocklist_message( + chain_ids::sui_testnet(), 10, 0, vector[], + ); + blocklist_message.extract_blocklist_payload(); + } + + #[test] + #[expected_failure(abort_code = bridge::message::ETrailingBytes)] + fun test_bad_blocklist_1() { + let mut blocklist_message = default_blocklist_message(); + let mut payload = blocklist_message.payload(); + payload.push_back(0u8); + blocklist_message.set_payload(payload); + blocklist_message.extract_blocklist_payload(); + } + + #[test] + #[expected_failure(abort_code = bridge::message::EInvalidAddressLength)] + fun test_bad_blocklist_2() { + let validator_pub_key1 = hex::decode(b"b14d3c4f5fbfbcfb98af2d330000d49c95b93aa7"); + // bad address + let validator_pub_key2 = hex::decode(b"f7e93cc543d97af6632c9b8864417379dba4bf150000"); + let validator_eth_addresses = vector[validator_pub_key1, validator_pub_key2]; + create_blocklist_message(chain_ids::sui_testnet(), 10, 0, validator_eth_addresses); + } + + #[test] + #[expected_failure(abort_code = bridge::message::ETrailingBytes)] + fun test_bad_bridge_limit() { + let mut update_bridge_limit = create_update_bridge_limit_message( + chain_ids::sui_testnet(), + 10, + chain_ids::eth_sepolia(), + 1000000000, + ); + let mut payload = update_bridge_limit.payload(); + payload.push_back(0u8); + update_bridge_limit.set_payload(payload); + update_bridge_limit.extract_update_bridge_limit(); + } + + #[test] + #[expected_failure(abort_code = bridge::message::ETrailingBytes)] + fun test_bad_update_price() { + let mut asset_price_message = create_update_asset_price_message( + 2, + chain_ids::sui_testnet(), // source chain + 10, // seq_num + 12345, + ); + let mut payload = asset_price_message.payload(); + payload.push_back(0u8); + asset_price_message.set_payload(payload); + asset_price_message.extract_update_asset_price(); + } + + #[test] + #[expected_failure(abort_code = bridge::message::ETrailingBytes)] + fun test_bad_add_token() { + let mut scenario = test_scenario::begin(@0x1); + let ctx = test_scenario::ctx(&mut scenario); + let treasury = treasury::mock_for_test(ctx); + + let mut add_token_message = create_add_tokens_on_sui_message( + chain_ids::sui_custom(), + 1, // seq_num + false, // native_token + vector[treasury.token_id(), treasury.token_id()], + vector[ + ascii::string( + b"28ac483b6f2b62dd58abdf0bbc3f86900d86bbdc710c704ba0b33b7f1c4b43c8::btc::BTC", + ), + ascii::string( + b"0xbd69a54e7c754a332804f325307c6627c06631dc41037239707e3242bc542e99::eth::ETH", + ), + ], + vector[100, 100], + ); + let mut payload = add_token_message.payload(); + payload.push_back(0u8); + add_token_message.set_payload(payload); + add_token_message.extract_add_tokens_on_sui(); + + abort 0 + } + + #[test] + #[expected_failure(abort_code = bridge::message::EInvalidPayloadLength)] + fun test_bad_payload_size() { + let sender_address = address::from_u256(100); + let mut scenario = test_scenario::begin(sender_address); + let ctx = test_scenario::ctx(&mut scenario); + let coin = coin::mint_for_testing(12345, ctx); + let mut sender = address::to_bytes(sender_address); + // double sender which wil make the payload different the 64 bytes + sender.append(address::to_bytes(sender_address)); + create_token_bridge_message( + chain_ids::sui_testnet(), // source chain + 10, // seq_num + sender, // sender address + chain_ids::eth_sepolia(), // target_chain + // Eth address is 20 bytes long + hex::decode(b"00000000000000000000000000000000000000c8"), // target_address + 3u8, // token_type + balance::value(coin::balance(&coin)), // amount: u64 + ); + + abort 0 + } + + #[test] + #[expected_failure(abort_code = bridge::message::EMustBeTokenMessage)] + fun test_bad_token_transfer_type() { + let msg = create_update_asset_price_message(2, chain_ids::sui_testnet(), 10, 12345); + msg.to_parsed_token_transfer_message(); + } + + #[test] + fun test_voting_power() { + let sender_address = address::from_u256(100); + let mut scenario = test_scenario::begin(sender_address); + + let ctx = test_scenario::ctx(&mut scenario); + let coin = coin::mint_for_testing(12345, ctx); + let message = default_token_bridge_message( + sender_address, + &coin, + chain_ids::sui_testnet(), + chain_ids::eth_sepolia(), + ); + assert!(message.required_voting_power() == 3334); + + let treasury = treasury::mock_for_test(ctx); + let message = create_add_tokens_on_sui_message( + chain_ids::sui_custom(), + 1, // seq_num + false, // native_token + vector[treasury.token_id(), treasury.token_id()], + vector[ + ascii::string( + b"28ac483b6f2b62dd58abdf0bbc3f86900d86bbdc710c704ba0b33b7f1c4b43c8::btc::BTC", + ), + ascii::string( + b"0xbd69a54e7c754a332804f325307c6627c06631dc41037239707e3242bc542e99::eth::ETH", + ), + ], + vector[100, 100], + ); + assert!(message.required_voting_power() == 5001); + + destroy(treasury); + coin::burn_for_testing(coin); + test_scenario::end(scenario); + + let message = create_emergency_op_message( + chain_ids::sui_testnet(), + 10, + emergency_op_pause(), + ); + assert!(message.required_voting_power() == 450); + let message = create_emergency_op_message( + chain_ids::sui_testnet(), + 10, + emergency_op_unpause(), + ); + assert!(message.required_voting_power() == 5001); + + let message = default_blocklist_message(); + assert!(message.required_voting_power() == 5001); + + let message = create_update_asset_price_message(2, chain_ids::sui_testnet(), 10, 12345); + assert!(message.required_voting_power() == 5001); + + let message = create_update_bridge_limit_message( + chain_ids::sui_testnet(), // source chain + 10, // seq_num + chain_ids::eth_sepolia(), + 1000000000, + ); + assert!(message.required_voting_power() == 5001); + } + + #[test] + #[expected_failure(abort_code = bridge::message::EInvalidEmergencyOpType)] + fun test_bad_voting_power_1() { + let message = create_emergency_op_message(chain_ids::sui_testnet(), 10, 3); + message.required_voting_power(); + } + + #[test] + #[expected_failure(abort_code = bridge::message::EInvalidMessageType)] + fun test_bad_voting_power_2() { + let message = make_generic_message( + 100, // bad message type + 1, 10, chain_ids::sui_testnet(), vector[], + ); + message.required_voting_power(); + } + + fun default_token_bridge_message( + sender: address, + coin: &Coin, + source_chain: u8, + target_chain: u8, + ): BridgeMessage { + create_token_bridge_message( + source_chain, + 10, // seq_num + address::to_bytes(sender), + target_chain, + // Eth address is 20 bytes long + hex::decode(b"00000000000000000000000000000000000000c8"), + 3u8, // token_type + balance::value(coin::balance(coin)), // amount: u64 + ) + } + + #[test] + #[expected_failure(abort_code = bridge::chain_ids::EInvalidBridgeRoute)] + fun test_invalid_chain_id_1() { + let sender_address = address::from_u256(100); + let mut scenario = test_scenario::begin(sender_address); + let ctx = test_scenario::ctx(&mut scenario); + let coin = coin::mint_for_testing(1, ctx); + default_token_bridge_message( + sender_address, + &coin, + INVALID_CHAIN, + chain_ids::eth_sepolia(), + ); + abort 0 + } + + #[test] + #[expected_failure(abort_code = bridge::chain_ids::EInvalidBridgeRoute)] + fun test_invalid_chain_id_2() { + let sender_address = address::from_u256(100); + let mut scenario = test_scenario::begin(sender_address); + let ctx = test_scenario::ctx(&mut scenario); + let coin = coin::mint_for_testing(1, ctx); + default_token_bridge_message( + sender_address, + &coin, + chain_ids::sui_testnet(), + INVALID_CHAIN, + ); + abort 0 + } + + #[test] + #[expected_failure(abort_code = bridge::chain_ids::EInvalidBridgeRoute)] + fun test_invalid_chain_id_3() { + create_emergency_op_message( + INVALID_CHAIN, + 10, // seq_num + emergency_op_pause(), + ); + abort 0 + } + + #[test] + #[expected_failure(abort_code = bridge::chain_ids::EInvalidBridgeRoute)] + fun test_invalid_chain_id_4() { + create_blocklist_message(INVALID_CHAIN, 10, 0, vector[]); + abort 0 + } + + #[test] + #[expected_failure(abort_code = bridge::chain_ids::EInvalidBridgeRoute)] + fun test_invalid_chain_id_5() { + create_update_bridge_limit_message(INVALID_CHAIN, 1, chain_ids::eth_sepolia(), 1); + abort 0 + } + + #[test] + #[expected_failure(abort_code = bridge::chain_ids::EInvalidBridgeRoute)] + fun test_invalid_chain_id_6() { + create_update_bridge_limit_message(chain_ids::sui_testnet(), 1, INVALID_CHAIN, 1); + abort 0 + } + + #[test] + #[expected_failure(abort_code = bridge::chain_ids::EInvalidBridgeRoute)] + fun test_invalid_chain_id_7() { + create_update_asset_price_message(2, INVALID_CHAIN, 1, 5); + abort 0 + } + + #[test] + #[expected_failure(abort_code = bridge::chain_ids::EInvalidBridgeRoute)] + fun test_invalid_chain_id_8() { + create_add_tokens_on_sui_message(INVALID_CHAIN, 1, false, vector[], vector[], vector[]); + abort 0 + } + + fun default_blocklist_message(): BridgeMessage { + let validator_pub_key1 = hex::decode(b"b14d3c4f5fbfbcfb98af2d330000d49c95b93aa7"); + let validator_pub_key2 = hex::decode(b"f7e93cc543d97af6632c9b8864417379dba4bf15"); + let validator_eth_addresses = vector[validator_pub_key1, validator_pub_key2]; + create_blocklist_message(chain_ids::sui_testnet(), 10, 0, validator_eth_addresses) + } } From 1782fb02c3fdd5bb88e20c7d860a99afc334ab4c Mon Sep 17 00:00:00 2001 From: Mark Logan <103447440+mystenmark@users.noreply.github.com> Date: Tue, 28 May 2024 10:25:33 -0700 Subject: [PATCH 012/324] Replace IndexMap, because of O(n) `shift_remove` (#17952) --- crates/sui-core/src/transaction_manager.rs | 119 +++++++++++++++++++-- 1 file changed, 109 insertions(+), 10 deletions(-) diff --git a/crates/sui-core/src/transaction_manager.rs b/crates/sui-core/src/transaction_manager.rs index d923048d9a289..bce7773be8de6 100644 --- a/crates/sui-core/src/transaction_manager.rs +++ b/crates/sui-core/src/transaction_manager.rs @@ -2,13 +2,12 @@ // SPDX-License-Identifier: Apache-2.0 use std::{ - cmp::max, - collections::{BTreeSet, HashMap, HashSet}, + cmp::{max, Reverse}, + collections::{BTreeSet, BinaryHeap, HashMap, HashSet}, sync::Arc, time::Duration, }; -use indexmap::IndexMap; use lru::LruCache; use mysten_metrics::monitored_scope; use parking_lot::RwLock; @@ -227,7 +226,7 @@ struct Inner { // Stores age info for all transactions depending on each object. // Used for throttling signing and submitting transactions depending on hot objects. // An `IndexMap` is used to ensure that the insertion order is preserved. - input_objects: HashMap>, + input_objects: HashMap, // Maps object IDs to the highest observed sequence number of the object. When the value is // None, indicates that the object is immutable, corresponding to an InputKey with no sequence @@ -286,12 +285,10 @@ impl Inner { ) }); for digest in digests.iter() { - let age_opt = input_txns.shift_remove(digest); - // The digest of the transaction must be inside the map. - assert!(age_opt.is_some()); + let age_opt = input_txns.remove(digest).expect("digest must be in map"); metrics .transaction_manager_transaction_queue_age_s - .observe(age_opt.unwrap().elapsed().as_secs_f64()); + .observe(age_opt.elapsed().as_secs_f64()); } if input_txns.is_empty() { @@ -786,12 +783,12 @@ impl TransactionManager { let inner = reconfig_lock.read(); keys.into_iter() .map(|key| { - let default_map = IndexMap::new(); + let default_map = TransactionQueue::default(); let txns = inner.input_objects.get(&key).unwrap_or(&default_map); ( key, txns.len(), - txns.first().map(|(_, time)| time.elapsed()), + txns.first().map(|(time, _)| time.elapsed()), ) }) .collect() @@ -939,6 +936,48 @@ where } } +#[derive(Default, Debug)] +struct TransactionQueue { + digests: HashMap, + ages: BinaryHeap<(Reverse, TransactionDigest)>, +} + +impl TransactionQueue { + fn len(&self) -> usize { + self.digests.len() + } + + fn is_empty(&self) -> bool { + self.digests.is_empty() + } + + fn insert(&mut self, digest: TransactionDigest, time: Instant) { + if self.digests.insert(digest, time).is_none() { + self.ages.push((Reverse(time), digest)); + } + } + + fn remove(&mut self, digest: &TransactionDigest) -> Option { + let Some(when) = self.digests.remove(digest) else { + return None; + }; + + while !self.ages.is_empty() + && !self + .digests + .contains_key(&self.ages.peek().expect("heap cannot be empty").1) + { + self.ages.pop(); + } + + Some(when) + } + + fn first(&self) -> Option<(Instant, TransactionDigest)> { + self.ages.peek().map(|(time, digest)| (time.0, *digest)) + } +} + #[cfg(test)] mod test { use super::*; @@ -1015,4 +1054,64 @@ mod test { }; assert_eq!(cache.is_object_available(&input_key), Some(true)); } + + #[test] + #[cfg_attr(msim, ignore)] + fn test_transaction_queue() { + let mut queue = TransactionQueue::default(); + + // insert and remove an item + let time = Instant::now(); + let digest = TransactionDigest::new([1; 32]); + queue.insert(digest, time); + assert_eq!(queue.first(), Some((time, digest))); + queue.remove(&digest); + assert_eq!(queue.first(), None); + + // remove a non-existent item + assert_eq!(queue.remove(&digest), None); + } + + #[test] + #[cfg_attr(msim, ignore)] + fn test_transaction_queue_remove_in_order() { + // insert two items, remove them in insertion order + let time1 = Instant::now(); + let digest1 = TransactionDigest::new([1; 32]); + let time2 = time1 + Duration::from_secs(1); + let digest2 = TransactionDigest::new([2; 32]); + + let mut queue = TransactionQueue::default(); + queue.insert(digest1, time1); + queue.insert(digest2, time2); + + assert_eq!(queue.first(), Some((time1, digest1))); + assert_eq!(queue.remove(&digest1), Some(time1)); + assert_eq!(queue.first(), Some((time2, digest2))); + assert_eq!(queue.remove(&digest2), Some(time2)); + assert_eq!(queue.first(), None); + } + + #[test] + #[cfg_attr(msim, ignore)] + fn test_transaction_queue_remove_in_reverse_order() { + // insert two items, remove them in reverse order + let time1 = Instant::now(); + let digest1 = TransactionDigest::new([1; 32]); + let time2 = time1 + Duration::from_secs(1); + let digest2 = TransactionDigest::new([2; 32]); + + let mut queue = TransactionQueue::default(); + queue.insert(digest1, time1); + queue.insert(digest2, time2); + + assert_eq!(queue.first(), Some((time1, digest1))); + assert_eq!(queue.remove(&digest2), Some(time2)); + + // after removing digest2, digest1 is still the first item + assert_eq!(queue.first(), Some((time1, digest1))); + assert_eq!(queue.remove(&digest1), Some(time1)); + + assert_eq!(queue.first(), None); + } } From 80b8d958dd57ecb3a12b48558d9c61c9be9d5a28 Mon Sep 17 00:00:00 2001 From: bityoume <123343203+bityoume@users.noreply.github.com> Date: Wed, 29 May 2024 01:32:53 +0800 Subject: [PATCH 013/324] [CLI] fix command `sui keytool import` using `--alias` is useless when inputting mnemonic phrase (#17935) ## Description [CLI] fix command `sui keytool import` using `--alias` is useless when inputting mnemonic phrase 2x ## Test plan How did you test the new or updated feature? --- ## Release notes Check each box that your changes affect. If none of the boxes relate to your changes, release notes aren't required. For each box you select, include information after the relevant heading that describes the impact of your changes that a user might notice and any actions they must take to implement updates. - [ ] Protocol: - [ ] Nodes (Validators and Full nodes): - [ ] Indexer: - [ ] JSON-RPC: - [ ] GraphQL: - [x] CLI: Fixed a bug where the provided alias in the `sui keytool import` command was not kept when importing a key via mnemonic. - [ ] Rust SDK: --------- Co-authored-by: stefan-mysten <135084671+stefan-mysten@users.noreply.github.com> Co-authored-by: howtosui --- crates/sui-keys/src/keystore.rs | 3 ++- crates/sui-keys/tests/tests.rs | 4 ++-- crates/sui-sdk/tests/tests.rs | 2 +- crates/sui/src/keytool.rs | 1 + 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/crates/sui-keys/src/keystore.rs b/crates/sui-keys/src/keystore.rs index 11d02b2b45de7..78d56119ae557 100644 --- a/crates/sui-keys/src/keystore.rs +++ b/crates/sui-keys/src/keystore.rs @@ -122,13 +122,14 @@ pub trait AccountKeystore: Send + Sync { phrase: &str, key_scheme: SignatureScheme, derivation_path: Option, + alias: Option, ) -> Result { let mnemonic = Mnemonic::from_phrase(phrase, Language::English) .map_err(|e| anyhow::anyhow!("Invalid mnemonic phrase: {:?}", e))?; let seed = Seed::new(&mnemonic, ""); match derive_key_pair_from_path(seed.as_bytes(), derivation_path, &key_scheme) { Ok((address, kp)) => { - self.add_key(None, kp)?; + self.add_key(alias, kp)?; Ok(address) } Err(e) => Err(anyhow!("error getting keypair {:?}", e)), diff --git a/crates/sui-keys/tests/tests.rs b/crates/sui-keys/tests/tests.rs index 0484eae84bb69..bf22dea55c17b 100644 --- a/crates/sui-keys/tests/tests.rs +++ b/crates/sui-keys/tests/tests.rs @@ -204,7 +204,7 @@ fn mnemonic_test() { let keystore_path_2 = temp_dir.path().join("sui2.keystore"); let mut keystore2 = Keystore::from(FileBasedKeystore::new(&keystore_path_2).unwrap()); let imported_address = keystore2 - .import_from_mnemonic(&phrase, SignatureScheme::ED25519, None) + .import_from_mnemonic(&phrase, SignatureScheme::ED25519, None, None) .unwrap(); assert_eq!(scheme.flag(), Ed25519SuiSignature::SCHEME.flag()); assert_eq!(address, imported_address); @@ -222,7 +222,7 @@ fn sui_wallet_address_mnemonic_test() -> Result<(), anyhow::Error> { let mut keystore = Keystore::from(FileBasedKeystore::new(&keystore_path).unwrap()); keystore - .import_from_mnemonic(phrase, SignatureScheme::ED25519, None) + .import_from_mnemonic(phrase, SignatureScheme::ED25519, None, None) .unwrap(); let pubkey = keystore.keys()[0].clone(); diff --git a/crates/sui-sdk/tests/tests.rs b/crates/sui-sdk/tests/tests.rs index 208bef68d422f..9d7e13fd1f492 100644 --- a/crates/sui-sdk/tests/tests.rs +++ b/crates/sui-sdk/tests/tests.rs @@ -17,7 +17,7 @@ fn mnemonic_test() { let keystore_path_2 = temp_dir.path().join("sui2.keystore"); let mut keystore2 = Keystore::from(FileBasedKeystore::new(&keystore_path_2).unwrap()); let imported_address = keystore2 - .import_from_mnemonic(&phrase, SignatureScheme::ED25519, None) + .import_from_mnemonic(&phrase, SignatureScheme::ED25519, None, None) .unwrap(); assert_eq!(scheme.flag(), Ed25519SuiSignature::SCHEME.flag()); assert_eq!(address, imported_address); diff --git a/crates/sui/src/keytool.rs b/crates/sui/src/keytool.rs index 24f86bd2cd2b5..2a1421185c182 100644 --- a/crates/sui/src/keytool.rs +++ b/crates/sui/src/keytool.rs @@ -639,6 +639,7 @@ impl KeyToolCommand { &input_string, key_scheme, derivation_path, + alias, )?; let skp = keystore.get_key(&sui_address)?; let key = Key::from(skp); From daa3383d4cafa99b8b717a1a04725fa741796025 Mon Sep 17 00:00:00 2001 From: mwtian <81660174+mwtian@users.noreply.github.com> Date: Tue, 28 May 2024 10:34:29 -0700 Subject: [PATCH 014/324] [Consensus] add tracing and basic metrics to tonic (#17921) ## Description Reuse the "callback layer" implementations for anemo and tonic. Add trace layer to tonic. Request and response size monitoring will be added as a followup. ## Test plan CI Private testnet. --- ## Release notes Check each box that your changes affect. If none of the boxes relate to your changes, release notes aren't required. For each box you select, include information after the relevant heading that describes the impact of your changes that a user might notice and any actions they must take to implement updates. - [ ] Protocol: - [ ] Nodes (Validators and Full nodes): - [ ] Indexer: - [ ] JSON-RPC: - [ ] GraphQL: - [ ] CLI: - [ ] Rust SDK: --- Cargo.lock | 1 + consensus/config/src/parameters.rs | 18 +- .../parameters_test__parameters.snap | 2 +- consensus/core/Cargo.toml | 1 + consensus/core/src/metrics.rs | 25 +-- consensus/core/src/network/anemo_network.rs | 169 +++++------------- consensus/core/src/network/metrics.rs | 25 +++ consensus/core/src/network/metrics_layer.rs | 126 +++++++++++++ consensus/core/src/network/mod.rs | 1 + consensus/core/src/network/tonic_network.rs | 109 +++++++++-- 10 files changed, 318 insertions(+), 159 deletions(-) create mode 100644 consensus/core/src/network/metrics_layer.rs diff --git a/Cargo.lock b/Cargo.lock index 901015c02ad2d..90f18802f0a8d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2604,6 +2604,7 @@ dependencies = [ "enum_dispatch", "fastcrypto", "futures", + "http", "hyper", "hyper-rustls 0.24.0", "itertools 0.10.5", diff --git a/consensus/config/src/parameters.rs b/consensus/config/src/parameters.rs index c21df9a058611..d2c8001e47a31 100644 --- a/consensus/config/src/parameters.rs +++ b/consensus/config/src/parameters.rs @@ -182,11 +182,13 @@ pub struct TonicParameters { #[serde(default = "TonicParameters::default_connection_buffer_size")] pub connection_buffer_size: usize, - /// Message size limits for both requests and responses. + /// Hard message size limit for both requests and responses. + /// This value is higher than strictly necessary, to allow overheads. + /// Message size targets and soft limits are computed based on this value. /// - /// If unspecified, this will default to 8MiB. + /// If unspecified, this will default to 32MiB. #[serde(default = "TonicParameters::default_message_size_limit")] - pub message_size_limit: usize, + message_size_limit: usize, } impl TonicParameters { @@ -199,7 +201,15 @@ impl TonicParameters { } fn default_message_size_limit() -> usize { - 8 << 20 + 32 << 20 + } + + pub fn excessive_message_size(&self) -> usize { + self.message_size_limit * 3 / 4 + } + + pub fn max_message_size(&self) -> usize { + self.message_size_limit } } diff --git a/consensus/config/tests/snapshots/parameters_test__parameters.snap b/consensus/config/tests/snapshots/parameters_test__parameters.snap index 61d9085c26426..65e1ddbec609b 100644 --- a/consensus/config/tests/snapshots/parameters_test__parameters.snap +++ b/consensus/config/tests/snapshots/parameters_test__parameters.snap @@ -24,4 +24,4 @@ tonic: secs: 5 nanos: 0 connection_buffer_size: 33554432 - message_size_limit: 8388608 + message_size_limit: 33554432 diff --git a/consensus/core/Cargo.toml b/consensus/core/Cargo.toml index 11314ba9e14a6..ae558c94e7563 100644 --- a/consensus/core/Cargo.toml +++ b/consensus/core/Cargo.toml @@ -21,6 +21,7 @@ dashmap.workspace = true enum_dispatch.workspace = true fastcrypto.workspace = true futures.workspace = true +http.workspace = true hyper.workspace = true hyper-rustls.workspace = true itertools.workspace = true diff --git a/consensus/core/src/metrics.rs b/consensus/core/src/metrics.rs index 99ed8641d80e9..422bf91985f35 100644 --- a/consensus/core/src/metrics.rs +++ b/consensus/core/src/metrics.rs @@ -10,7 +10,7 @@ use prometheus::{ HistogramVec, IntCounter, IntCounterVec, IntGauge, IntGaugeVec, Registry, }; -use crate::network::metrics::{NetworkRouteMetrics, QuinnConnectionMetrics}; +use crate::network::metrics::{NetworkMetrics, QuinnConnectionMetrics}; // starts from 1μs, 50μs, 100μs... const FINE_GRAINED_LATENCY_SEC_BUCKETS: &[f64] = &[ @@ -486,26 +486,3 @@ impl ChannelMetrics { } } } - -// Fields for network-agnostic metrics can be added here -pub(crate) struct NetworkMetrics { - pub(crate) network_type: IntGaugeVec, - pub(crate) inbound: NetworkRouteMetrics, - pub(crate) outbound: NetworkRouteMetrics, -} - -impl NetworkMetrics { - pub(crate) fn new(registry: &Registry) -> Self { - Self { - network_type: register_int_gauge_vec_with_registry!( - "network_type", - "Type of the network used: anemo or tonic", - &["type"], - registry - ) - .unwrap(), - inbound: NetworkRouteMetrics::new("inbound", registry), - outbound: NetworkRouteMetrics::new("outbound", registry), - } - } -} diff --git a/consensus/core/src/network/anemo_network.rs b/consensus/core/src/network/anemo_network.rs index d46cc00b80ee6..3ce71492d317b 100644 --- a/consensus/core/src/network/anemo_network.rs +++ b/consensus/core/src/network/anemo_network.rs @@ -22,7 +22,6 @@ use async_trait::async_trait; use bytes::Bytes; use cfg_if::cfg_if; use consensus_config::{AuthorityIndex, NetworkKeyPair}; -use prometheus::HistogramTimer; use serde::{Deserialize, Serialize}; use tokio::sync::broadcast::error::RecvError; use tracing::{debug, error, warn}; @@ -34,7 +33,7 @@ use super::{ }, connection_monitor::{AnemoConnectionMonitor, ConnectionMonitorHandle}, epoch_filter::{AllowedEpoch, EPOCH_HEADER_KEY}, - metrics::NetworkRouteMetrics, + metrics_layer::{MetricsCallbackMaker, MetricsResponseCallback, SizedRequest, SizedResponse}, BlockStream, NetworkClient, NetworkManager, NetworkService, }; use crate::{ @@ -403,10 +402,8 @@ impl NetworkManager for AnemoManager { } ); let epoch_string: String = self.context.committee.epoch().to_string(); - let inbound_network_metrics = - Arc::new(self.context.metrics.network_metrics.inbound.clone()); - let outbound_network_metrics = - Arc::new(self.context.metrics.network_metrics.outbound.clone()); + let inbound_network_metrics = self.context.metrics.network_metrics.inbound.clone(); + let outbound_network_metrics = self.context.metrics.network_metrics.outbound.clone(); let quinn_connection_metrics = self.context.metrics.quinn_connection_metrics.clone(); let all_peer_ids = self .context @@ -430,7 +427,7 @@ impl NetworkManager for AnemoManager { .make_span_with(DefaultMakeSpan::new().level(tracing::Level::INFO)) .on_failure(DefaultOnFailure::new().level(tracing::Level::WARN)), ) - .layer(CallbackLayer::new(MetricsMakeCallbackHandler::new( + .layer(CallbackLayer::new(MetricsCallbackMaker::new( inbound_network_metrics, self.context.parameters.anemo.excessive_message_size, ))) @@ -446,7 +443,7 @@ impl NetworkManager for AnemoManager { .make_span_with(DefaultMakeSpan::new().level(tracing::Level::INFO)) .on_failure(DefaultOnFailure::new().level(tracing::Level::WARN)), ) - .layer(CallbackLayer::new(MetricsMakeCallbackHandler::new( + .layer(CallbackLayer::new(MetricsCallbackMaker::new( outbound_network_metrics, self.context.parameters.anemo.excessive_message_size, ))) @@ -576,6 +573,50 @@ impl NetworkManager for AnemoManager { } } +// Adapt MetricsCallbackMaker and MetricsResponseCallback to anemo. + +impl SizedRequest for anemo::Request { + fn size(&self) -> usize { + self.body().len() + } + + fn route(&self) -> String { + self.route().to_string() + } +} + +impl SizedResponse for anemo::Response { + fn size(&self) -> usize { + self.body().len() + } + + fn error_type(&self) -> Option { + if self.status().is_success() { + None + } else { + Some(self.status().to_string()) + } + } +} + +impl MakeCallbackHandler for MetricsCallbackMaker { + type Handler = MetricsResponseCallback; + + fn make_handler(&self, request: &anemo::Request) -> Self::Handler { + self.handle_request(request) + } +} + +impl ResponseHandler for MetricsResponseCallback { + fn on_response(self, response: &anemo::Response) { + self.on_response(response) + } + + fn on_error(self, err: &E) { + self.on_error(err) + } +} + /// Network message types. #[derive(Clone, Serialize, Deserialize)] pub(crate) struct SendBlockRequest { @@ -611,115 +652,3 @@ pub(crate) struct FetchCommitsResponse { // Serialized SignedBlock that certify the last commit from above. certifier_blocks: Vec, } - -#[derive(Clone)] -pub(crate) struct MetricsMakeCallbackHandler { - metrics: Arc, - /// Size in bytes above which a request or response message is considered excessively large - excessive_message_size: usize, -} - -impl MetricsMakeCallbackHandler { - pub fn new(metrics: Arc, excessive_message_size: usize) -> Self { - Self { - metrics, - excessive_message_size, - } - } -} - -impl MakeCallbackHandler for MetricsMakeCallbackHandler { - type Handler = MetricsResponseHandler; - - fn make_handler(&self, request: &anemo::Request) -> Self::Handler { - let route = request.route().to_owned(); - - self.metrics.requests.with_label_values(&[&route]).inc(); - self.metrics - .inflight_requests - .with_label_values(&[&route]) - .inc(); - let body_len = request.body().len(); - self.metrics - .request_size - .with_label_values(&[&route]) - .observe(body_len as f64); - if body_len > self.excessive_message_size { - warn!( - "Saw excessively large request with size {body_len} for {route} with peer {:?}", - request.peer_id() - ); - self.metrics - .excessive_size_requests - .with_label_values(&[&route]) - .inc(); - } - - let timer = self - .metrics - .request_latency - .with_label_values(&[&route]) - .start_timer(); - - MetricsResponseHandler { - metrics: self.metrics.clone(), - timer, - route, - excessive_message_size: self.excessive_message_size, - } - } -} - -pub(crate) struct MetricsResponseHandler { - metrics: Arc, - // The timer is held on to and "observed" once dropped - #[allow(unused)] - timer: HistogramTimer, - route: String, - excessive_message_size: usize, -} - -impl ResponseHandler for MetricsResponseHandler { - fn on_response(self, response: &anemo::Response) { - let body_len = response.body().len(); - self.metrics - .response_size - .with_label_values(&[&self.route]) - .observe(body_len as f64); - if body_len > self.excessive_message_size { - warn!( - "Saw excessively large response with size {body_len} for {} with peer {:?}", - self.route, - response.peer_id() - ); - self.metrics - .excessive_size_responses - .with_label_values(&[&self.route]) - .inc(); - } - - if !response.status().is_success() { - let status = response.status().to_u16().to_string(); - self.metrics - .errors - .with_label_values(&[&self.route, &status]) - .inc(); - } - } - - fn on_error(self, _error: &E) { - self.metrics - .errors - .with_label_values(&[&self.route, "unknown"]) - .inc(); - } -} - -impl Drop for MetricsResponseHandler { - fn drop(&mut self) { - self.metrics - .inflight_requests - .with_label_values(&[&self.route]) - .dec(); - } -} diff --git a/consensus/core/src/network/metrics.rs b/consensus/core/src/network/metrics.rs index f9c9278feccff..ebc972079b1ec 100644 --- a/consensus/core/src/network/metrics.rs +++ b/consensus/core/src/network/metrics.rs @@ -1,12 +1,37 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 +use std::sync::Arc; + use prometheus::{ register_histogram_vec_with_registry, register_int_counter_vec_with_registry, register_int_gauge_vec_with_registry, register_int_gauge_with_registry, HistogramVec, IntCounterVec, IntGauge, IntGaugeVec, Registry, }; +// Fields for network-agnostic metrics can be added here +pub(crate) struct NetworkMetrics { + pub(crate) network_type: IntGaugeVec, + pub(crate) inbound: Arc, + pub(crate) outbound: Arc, +} + +impl NetworkMetrics { + pub(crate) fn new(registry: &Registry) -> Self { + Self { + network_type: register_int_gauge_vec_with_registry!( + "network_type", + "Type of the network used: anemo or tonic", + &["type"], + registry + ) + .unwrap(), + inbound: Arc::new(NetworkRouteMetrics::new("inbound", registry)), + outbound: Arc::new(NetworkRouteMetrics::new("outbound", registry)), + } + } +} + #[derive(Clone)] pub(crate) struct QuinnConnectionMetrics { /// The connection status of known peers. 0 if not connected, 1 if connected. diff --git a/consensus/core/src/network/metrics_layer.rs b/consensus/core/src/network/metrics_layer.rs new file mode 100644 index 0000000000000..5b54eabcd7191 --- /dev/null +++ b/consensus/core/src/network/metrics_layer.rs @@ -0,0 +1,126 @@ +// Copyright (c) Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +use std::sync::Arc; + +use prometheus::HistogramTimer; + +use super::metrics::NetworkRouteMetrics; + +/// Tower layer adapters that allow specifying callbacks for request and response handling +/// exist for both anemo and http. So the metrics layer implementation can be reused across +/// networking stacks. + +pub(crate) trait SizedRequest { + fn size(&self) -> usize; + fn route(&self) -> String; +} + +pub(crate) trait SizedResponse { + fn size(&self) -> usize; + fn error_type(&self) -> Option; +} + +#[derive(Clone)] +pub(crate) struct MetricsCallbackMaker { + metrics: Arc, + /// Size in bytes above which a request or response message is considered excessively large + excessive_message_size: usize, +} + +impl MetricsCallbackMaker { + pub(crate) fn new(metrics: Arc, excessive_message_size: usize) -> Self { + Self { + metrics, + excessive_message_size, + } + } + + // Update request metrics. And create a callback that should be called on response. + pub(crate) fn handle_request(&self, request: &dyn SizedRequest) -> MetricsResponseCallback { + let route = request.route(); + + self.metrics.requests.with_label_values(&[&route]).inc(); + self.metrics + .inflight_requests + .with_label_values(&[&route]) + .inc(); + let request_size = request.size(); + if request_size > 0 { + self.metrics + .request_size + .with_label_values(&[&route]) + .observe(request_size as f64); + } + if request_size > self.excessive_message_size { + self.metrics + .excessive_size_requests + .with_label_values(&[&route]) + .inc(); + } + + let timer = self + .metrics + .request_latency + .with_label_values(&[&route]) + .start_timer(); + + MetricsResponseCallback { + metrics: self.metrics.clone(), + timer, + route, + excessive_message_size: self.excessive_message_size, + } + } +} + +pub(crate) struct MetricsResponseCallback { + metrics: Arc, + // The timer is held on to and "observed" once dropped + #[allow(unused)] + timer: HistogramTimer, + route: String, + excessive_message_size: usize, +} + +impl MetricsResponseCallback { + // Update response metrics. + pub(crate) fn on_response(self, response: &dyn SizedResponse) { + let response_size = response.size(); + if response_size > 0 { + self.metrics + .response_size + .with_label_values(&[&self.route]) + .observe(response_size as f64); + } + if response_size > self.excessive_message_size { + self.metrics + .excessive_size_responses + .with_label_values(&[&self.route]) + .inc(); + } + + if let Some(err) = response.error_type() { + self.metrics + .errors + .with_label_values(&[&self.route, &err]) + .inc(); + } + } + + pub(crate) fn on_error(self, _error: &E) { + self.metrics + .errors + .with_label_values(&[&self.route, "unknown"]) + .inc(); + } +} + +impl Drop for MetricsResponseCallback { + fn drop(&mut self) { + self.metrics + .inflight_requests + .with_label_values(&[&self.route]) + .dec(); + } +} diff --git a/consensus/core/src/network/mod.rs b/consensus/core/src/network/mod.rs index 24539d1ef9813..7ad87a8abf121 100644 --- a/consensus/core/src/network/mod.rs +++ b/consensus/core/src/network/mod.rs @@ -45,6 +45,7 @@ pub(crate) mod anemo_network; pub(crate) mod connection_monitor; pub(crate) mod epoch_filter; pub(crate) mod metrics; +mod metrics_layer; #[cfg(test)] mod network_tests; #[cfg(test)] diff --git a/consensus/core/src/network/tonic_network.rs b/consensus/core/src/network/tonic_network.rs index 61e11e82115b4..cff9cb87e0d07 100644 --- a/consensus/core/src/network/tonic_network.rs +++ b/consensus/core/src/network/tonic_network.rs @@ -16,7 +16,11 @@ use consensus_config::{AuthorityIndex, NetworkKeyPair, NetworkPublicKey}; use futures::{stream, Stream, StreamExt as _}; use hyper::server::conn::Http; use mysten_common::sync::notify_once::NotifyOnce; -use mysten_network::{multiaddr::Protocol, Multiaddr}; +use mysten_network::{ + callback::{CallbackLayer, MakeCallbackHandler, ResponseHandler}, + multiaddr::Protocol, + Multiaddr, +}; use parking_lot::RwLock; use tokio::{ pin, @@ -25,14 +29,15 @@ use tokio::{ }; use tokio_rustls::TlsAcceptor; use tokio_stream::{iter, Iter}; -use tonic::{ - transport::{Channel, Server}, - Request, Response, Streaming, +use tonic::{transport::Server, Request, Response, Streaming}; +use tower_http::{ + trace::{DefaultMakeSpan, DefaultOnFailure, TraceLayer}, + ServiceBuilderExt, }; -use tower_http::ServiceBuilderExt; use tracing::{debug, error, info, trace, warn}; use super::{ + metrics_layer::{MetricsCallbackMaker, MetricsResponseCallback, SizedRequest, SizedResponse}, tonic_gen::{ consensus_service_client::ConsensusServiceClient, consensus_service_server::ConsensusService, @@ -89,8 +94,8 @@ impl TonicClient { .get_channel(self.network_keypair.clone(), peer, timeout) .await?; Ok(ConsensusServiceClient::new(channel) - .max_encoding_message_size(config.message_size_limit) - .max_decoding_message_size(config.message_size_limit)) + .max_encoding_message_size(config.max_message_size()) + .max_decoding_message_size(config.max_message_size())) } } @@ -240,6 +245,15 @@ impl NetworkClient for TonicClient { } } +// Tonic channel wrapped with layers. +type Channel = mysten_network::callback::Callback< + tower_http::trace::Trace< + tonic::transport::Channel, + tower_http::classify::SharedClassifier, + >, + MetricsCallbackMaker, +>; + /// Manages a pool of connections to peers to avoid constantly reconnecting, /// which can be expensive. struct ChannelPool { @@ -276,7 +290,7 @@ impl ChannelPool { let address = format!("https://{address}"); let config = &self.context.parameters.tonic; let buffer_size = config.connection_buffer_size; - let endpoint = Channel::from_shared(address.clone()) + let endpoint = tonic::transport::Channel::from_shared(address.clone()) .unwrap() .connect_timeout(timeout) .initial_connection_window_size(Some(buffer_size as u32)) @@ -316,6 +330,18 @@ impl ChannelPool { }; trace!("Connected to {address}"); + let channel = tower::ServiceBuilder::new() + .layer(CallbackLayer::new(MetricsCallbackMaker::new( + self.context.metrics.network_metrics.outbound.clone(), + self.context.parameters.tonic.excessive_message_size(), + ))) + .layer( + TraceLayer::new_for_grpc() + .make_span_with(DefaultMakeSpan::new().level(tracing::Level::TRACE)) + .on_failure(DefaultOnFailure::new().level(tracing::Level::DEBUG)), + ) + .service(channel); + let mut channels = self.channels.write(); // There should not be many concurrent attempts at connecting to the same peer. let channel = channels.entry(peer).or_insert(channel); @@ -531,6 +557,11 @@ impl NetworkManager for TonicManager { let config = &self.context.parameters.tonic; let consensus_service = Server::builder() + .layer( + TraceLayer::new_for_grpc() + .make_span_with(DefaultMakeSpan::new().level(tracing::Level::TRACE)) + .on_failure(DefaultOnFailure::new().level(tracing::Level::DEBUG)), + ) .initial_connection_window_size(64 << 20) .initial_stream_window_size(32 << 20) .http2_keepalive_interval(Some(config.keepalive_interval)) @@ -538,11 +569,14 @@ impl NetworkManager for TonicManager { // tcp keepalive is unsupported by msim .add_service( ConsensusServiceServer::new(service) - .max_encoding_message_size(config.message_size_limit) - .max_decoding_message_size(config.message_size_limit), + .max_encoding_message_size(config.max_message_size()) + .max_decoding_message_size(config.max_message_size()), ) .into_service(); + let inbound_metrics = self.context.metrics.network_metrics.inbound.clone(); + let excessive_message_size = self.context.parameters.tonic.excessive_message_size(); + let mut http = Http::new(); http.http2_only(true); let http = Arc::new(http); @@ -649,6 +683,7 @@ impl NetworkManager for TonicManager { let tls_acceptor = tls_acceptor.clone(); let consensus_service = consensus_service.clone(); + let inbound_metrics = inbound_metrics.clone(); let http = http.clone(); let connections_info = connections_info.clone(); let shutdown_notif = shutdown_notif.clone(); @@ -698,6 +733,10 @@ impl NetworkManager for TonicManager { // NOTE: the PeerInfo extension is copied to every request served. // If PeerInfo starts to contain complex values, it should be wrapped in an Arc<>. .add_extension(PeerInfo { authority_index }) + .layer(CallbackLayer::new(MetricsCallbackMaker::new( + inbound_metrics, + excessive_message_size, + ))) .service(consensus_service.clone()); pin! { @@ -827,6 +866,56 @@ struct PeerInfo { authority_index: AuthorityIndex, } +// Adapt MetricsCallbackMaker and MetricsResponseCallback to http. + +impl SizedRequest for http::request::Parts { + fn size(&self) -> usize { + // TODO: implement this. + 0 + } + + fn route(&self) -> String { + let path = self.uri.path(); + path.rsplit_once('/') + .map(|(_, route)| route) + .unwrap_or("unknown") + .to_string() + } +} + +impl SizedResponse for http::response::Parts { + fn size(&self) -> usize { + // TODO: implement this. + 0 + } + + fn error_type(&self) -> Option { + if self.status.is_success() { + None + } else { + Some(self.status.to_string()) + } + } +} + +impl MakeCallbackHandler for MetricsCallbackMaker { + type Handler = MetricsResponseCallback; + + fn make_handler(&self, request: &http::request::Parts) -> Self::Handler { + self.handle_request(request) + } +} + +impl ResponseHandler for MetricsResponseCallback { + fn on_response(self, response: &http::response::Parts) { + self.on_response(response) + } + + fn on_error(self, err: &E) { + self.on_error(err) + } +} + /// Network message types. #[derive(Clone, prost::Message)] pub(crate) struct SendBlockRequest { From 61293246a6db1de10094b63fdb9a57ba8a62b0cb Mon Sep 17 00:00:00 2001 From: Adam Welc Date: Tue, 28 May 2024 14:28:54 -0700 Subject: [PATCH 015/324] [move-ide] Move analyzer versioning (#17929) ## Description We would like to use the same versioning scheme we use for Sui binaries (particularly for `sui` binary) for the `move-analyzer` as well. Both `sui` and `move-analyzer` binaries "bundle" the move compiler and being able to tell which version you are using is very useful (and really necessary to avoid discrepancies in the compilation process between the IDE and CLI). It's apparently not possible to have to `move-analyzer` binaries in the repo (one in `crates` and one in `external-crates`) so I renamed the one in `external-crates` as it's the one in `crates` that is intended to be externally used from now on. ## Test plan All existing tests must pass --- .github/workflows/release.yml | 2 - Cargo.lock | 131 +++++-- Cargo.toml | 3 + binary-build-list.json | 3 +- crates/sui-move-lsp/Cargo.toml | 15 + crates/sui-move-lsp/src/bin/move-analyzer.rs | 22 ++ .../move-analyzer/editors/code/README.md | 2 +- .../move/crates/move-analyzer/src/analyzer.rs | 348 ++++++++++++++++++ .../move-analyzer/src/bin/move-analyzer.rs | 346 +---------------- .../move/crates/move-analyzer/src/lib.rs | 1 + 10 files changed, 493 insertions(+), 380 deletions(-) create mode 100644 crates/sui-move-lsp/Cargo.toml create mode 100644 crates/sui-move-lsp/src/bin/move-analyzer.rs create mode 100644 external-crates/move/crates/move-analyzer/src/analyzer.rs diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c0730a695f600..dee1ae1b55155 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -141,7 +141,6 @@ jobs: shell: bash run: | [ -f ~/.cargo/env ] && source ~/.cargo/env ; cargo build --release && cargo build --profile=dev --bin sui - cd external-crates/move && cargo build -p move-analyzer --release - name: Rename binaries for ${{ matrix.os }} if: ${{ env.s3_archive_exist == '' }} @@ -156,7 +155,6 @@ jobs: done mv ./target/debug/sui${{ env.extention }} ${{ env.TMP_BUILD_DIR }}/sui-debug${{ env.extention }} - mv ./external-crates/move/target/release/move-analyzer${{ env.extention }} ${{ env.TMP_BUILD_DIR }}/move-analyzer${{ env.extention }} tar -cvzf ./tmp/sui-${{ env.sui_tag }}-${{ env.os_type }}.tgz -C ${{ env.TMP_BUILD_DIR }} . [[ ${{ env.sui_tag }} == *"testnet"* ]] && aws s3 cp ./tmp/sui-${{ env.sui_tag }}-${{ env.os_type }}.tgz s3://sui-releases/releases/sui-${{ env.sui_tag }}-${{ env.os_type }}.tgz || true diff --git a/Cargo.lock b/Cargo.lock index 90f18802f0a8d..93d219c5c66dd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2888,49 +2888,62 @@ dependencies = [ "once_cell", ] +[[package]] +name = "crossbeam" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", +] + [[package]] name = "crossbeam-channel" -version = "0.5.8" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.2" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.13" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", - "memoffset 0.7.1", - "scopeguard", ] [[package]] -name = "crossbeam-utils" -version = "0.8.14" +name = "crossbeam-queue" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" dependencies = [ - "cfg-if", + "crossbeam-utils", ] +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + [[package]] name = "crossterm" version = "0.25.0" @@ -6266,6 +6279,31 @@ dependencies = [ "hashbrown 0.13.2", ] +[[package]] +name = "lsp-server" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "248f65b78f6db5d8e1b1604b4098a28b43d21a8eb1deeca22b1c421b276c7095" +dependencies = [ + "crossbeam-channel", + "log", + "serde", + "serde_json", +] + +[[package]] +name = "lsp-types" +version = "0.95.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e34d33a8e9b006cd3fc4fe69a921affa097bae4bb65f76271f4644f9a334365" +dependencies = [ + "bitflags 1.3.2", + "serde", + "serde_json", + "serde_repr", + "url", +] + [[package]] name = "lz4-sys" version = "1.9.4" @@ -6383,15 +6421,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "memoffset" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" -dependencies = [ - "autocfg", -] - [[package]] name = "miette" version = "7.0.0" @@ -6558,6 +6587,32 @@ dependencies = [ name = "move-abstract-stack" version = "0.0.1" +[[package]] +name = "move-analyzer" +version = "1.0.0" +dependencies = [ + "anyhow", + "clap", + "codespan-reporting", + "crossbeam", + "derivative", + "dunce", + "im", + "itertools 0.10.5", + "lsp-server", + "lsp-types", + "move-command-line-common", + "move-compiler", + "move-ir-types", + "move-package", + "move-symbol-pool", + "serde_json", + "sha2 0.9.9", + "tempfile", + "url", + "vfs", +] + [[package]] name = "move-binary-format" version = "0.0.3" @@ -7941,7 +7996,7 @@ dependencies = [ "cc", "cfg-if", "libc", - "memoffset 0.6.5", + "memoffset", ] [[package]] @@ -10864,9 +10919,9 @@ checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4" [[package]] name = "serde" -version = "1.0.190" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7" +checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" dependencies = [ "serde_derive", ] @@ -10903,9 +10958,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.190" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3" +checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" dependencies = [ "proc-macro2 1.0.78", "quote 1.0.35", @@ -10925,11 +10980,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.95" +version = "1.0.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d721eca97ac802aa7777b701877c8004d950fc142651367300d21c1cc0194744" +checksum = "4d1bd37ce2324cf3bf85e5a25f96eb4baf0d5aa6eba43e7ae8958870c4ec48ed" dependencies = [ - "indexmap 1.9.3", + "indexmap 2.1.0", "itoa", "ryu", "serde", @@ -13074,6 +13129,16 @@ dependencies = [ "tempfile", ] +[[package]] +name = "sui-move-lsp" +version = "1.27.0" +dependencies = [ + "bin-version", + "clap", + "move-analyzer", + "tokio", +] + [[package]] name = "sui-move-natives-latest" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 31a1615150ec2..2385c7cca3472 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -124,6 +124,7 @@ members = [ "crates/sui-metric-checker", "crates/sui-move", "crates/sui-move-build", + "crates/sui-move-lsp", "crates/sui-network", "crates/sui-node", "crates/sui-open-rpc", @@ -563,6 +564,7 @@ move-stackless-bytecode = { path = "external-crates/move/crates/move-stackless-b move-symbol-pool = { path = "external-crates/move/crates/move-symbol-pool" } move-abstract-interpreter = { path = "external-crates/move/crates/move-abstract-interpreter" } move-abstract-stack = { path = "external-crates/move/crates/move-abstract-stack" } +move-analyzer = { path = "external-crates/move/crates/move-analyzer" } fastcrypto = { git = "https://github.com/MystenLabs/fastcrypto", rev = "c101a5176799db3eb9c801b844e7add92153d291" } fastcrypto-tbls = { git = "https://github.com/MystenLabs/fastcrypto", rev = "c101a5176799db3eb9c801b844e7add92153d291" } @@ -622,6 +624,7 @@ sui-macros = { path = "crates/sui-macros" } sui-metric-checker = { path = "crates/sui-metric-checker" } sui-move = { path = "crates/sui-move" } sui-move-build = { path = "crates/sui-move-build" } +sui-move-lsp = { path = "crates/sui-move-lsp" } sui-network = { path = "crates/sui-network" } sui-node = { path = "crates/sui-node" } sui-open-rpc = { path = "crates/sui-open-rpc" } diff --git a/binary-build-list.json b/binary-build-list.json index 48d5966706d0f..4bb16bb391a6f 100644 --- a/binary-build-list.json +++ b/binary-build-list.json @@ -8,7 +8,8 @@ "sui-data-ingestion", "sui-bridge", "sui-bridge-cli", - "sui-graphql-rpc" + "sui-graphql-rpc", + "move-analyzer" ], "internal_binaries": [ "stress", diff --git a/crates/sui-move-lsp/Cargo.toml b/crates/sui-move-lsp/Cargo.toml new file mode 100644 index 0000000000000..6018fe6c9b528 --- /dev/null +++ b/crates/sui-move-lsp/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "sui-move-lsp" +version.workspace = true +authors = ["Mysten Labs "] +license = "Apache-2.0" +publish = false +edition = "2021" + +[dependencies] +clap = { version = "4.1.4", features = ["derive"] } +tokio = { workspace = true, features = ["full"] } + +bin-version.workspace = true +move-analyzer.workspace = true + diff --git a/crates/sui-move-lsp/src/bin/move-analyzer.rs b/crates/sui-move-lsp/src/bin/move-analyzer.rs new file mode 100644 index 0000000000000..10187b21ca468 --- /dev/null +++ b/crates/sui-move-lsp/src/bin/move-analyzer.rs @@ -0,0 +1,22 @@ +// Copyright (c) Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +use clap::*; +use move_analyzer::analyzer; + +// Define the `GIT_REVISION` and `VERSION` consts +bin_version::bin_version!(); + +#[derive(Parser)] +#[clap( + name = env!("CARGO_BIN_NAME"), + rename_all = "kebab-case", + author, + version = VERSION, +)] +struct App {} + +fn main() { + App::parse(); + analyzer::run(); +} diff --git a/external-crates/move/crates/move-analyzer/editors/code/README.md b/external-crates/move/crates/move-analyzer/editors/code/README.md index 0992d87e32bb9..985a44420010c 100644 --- a/external-crates/move/crates/move-analyzer/editors/code/README.md +++ b/external-crates/move/crates/move-analyzer/editors/code/README.md @@ -42,7 +42,7 @@ This can be done in two steps: as prerequisites for Sui installation - for Linux, macOS and Windows these prerequisites and their installation instructions can be found [here](https://docs.sui.io/guides/developer/getting-started/sui-install#additional-prerequisites-by-operating-system) -2. Invoke `cargo install --git https://github.com/MystenLabs/sui move-analyzer` to install the +2. Invoke `cargo install --git https://github.com/MystenLabs/sui sui-move-lsp` to install the `move-analyzer` language server in your Cargo binary directory, which is typically located in the `~/.cargo/bin` (macOS/Linux) or `C:\Users\USER\.cargo\bin` (Windows) directory. 3. Copy the move-analyzer binary to `~/.sui/bin` (macOS/Linux) or `C:\Users\USER\.sui\bin` diff --git a/external-crates/move/crates/move-analyzer/src/analyzer.rs b/external-crates/move/crates/move-analyzer/src/analyzer.rs new file mode 100644 index 0000000000000..f34fd8c380a34 --- /dev/null +++ b/external-crates/move/crates/move-analyzer/src/analyzer.rs @@ -0,0 +1,348 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use anyhow::Result; +use crossbeam::channel::{bounded, select}; +use lsp_server::{Connection, Message, Notification, Request, Response}; +use lsp_types::{ + notification::Notification as _, request::Request as _, CompletionOptions, Diagnostic, + HoverProviderCapability, InlayHintOptions, InlayHintServerCapabilities, OneOf, SaveOptions, + TextDocumentSyncCapability, TextDocumentSyncKind, TextDocumentSyncOptions, + TypeDefinitionProviderCapability, WorkDoneProgressOptions, +}; +use move_compiler::linters::LintLevel; +use std::{ + collections::BTreeMap, + path::PathBuf, + sync::{Arc, Mutex}, +}; + +use crate::{ + completion::on_completion_request, context::Context, inlay_hints, symbols, + vfs::on_text_document_sync_notification, +}; +use url::Url; +use vfs::{impls::memory::MemoryFS, VfsPath}; + +const LINT_NONE: &str = "none"; +const LINT_DEFAULT: &str = "default"; +const LINT_ALL: &str = "all"; + +#[allow(deprecated)] +pub fn run() { + // stdio is used to communicate Language Server Protocol requests and responses. + // stderr is used for logging (and, when Visual Studio Code is used to communicate with this + // server, it captures this output in a dedicated "output channel"). + let exe = std::env::current_exe() + .unwrap() + .to_string_lossy() + .to_string(); + eprintln!( + "Starting language server '{}' communicating via stdio...", + exe + ); + + let (connection, io_threads) = Connection::stdio(); + let symbols = Arc::new(Mutex::new(symbols::empty_symbols())); + let pkg_deps = Arc::new(Mutex::new( + BTreeMap::::new(), + )); + let ide_files_root: VfsPath = MemoryFS::new().into(); + + let (id, client_response) = connection + .initialize_start() + .expect("could not start connection initialization"); + + let capabilities = serde_json::to_value(lsp_types::ServerCapabilities { + // The server receives notifications from the client as users open, close, + // and modify documents. + text_document_sync: Some(TextDocumentSyncCapability::Options( + TextDocumentSyncOptions { + open_close: Some(true), + // TODO: We request that the language server client send us the entire text of any + // files that are modified. We ought to use the "incremental" sync kind, which would + // have clients only send us what has changed and where, thereby requiring far less + // data be sent "over the wire." However, to do so, our language server would need + // to be capable of applying deltas to its view of the client's open files. See the + // 'move_analyzer::vfs' module for details. + change: Some(TextDocumentSyncKind::FULL), + will_save: None, + will_save_wait_until: None, + save: Some( + SaveOptions { + include_text: Some(true), + } + .into(), + ), + }, + )), + selection_range_provider: None, + hover_provider: Some(HoverProviderCapability::Simple(true)), + // The server provides completions as a user is typing. + completion_provider: Some(CompletionOptions { + resolve_provider: None, + // In Move, `foo::` and `foo.` should trigger completion suggestions for after + // the `:` or `.` + // (Trigger characters are just that: characters, such as `:`, and not sequences of + // characters, such as `::`. So when the language server encounters a completion + // request, it checks whether completions are being requested for `foo:`, and returns no + // completions in that case.) + trigger_characters: Some(vec![":".to_string(), ".".to_string(), "{".to_string()]), + all_commit_characters: None, + work_done_progress_options: WorkDoneProgressOptions { + work_done_progress: None, + }, + completion_item: None, + }), + definition_provider: Some(OneOf::Left(true)), + type_definition_provider: Some(TypeDefinitionProviderCapability::Simple(true)), + references_provider: Some(OneOf::Left(true)), + document_symbol_provider: Some(OneOf::Left(true)), + inlay_hint_provider: Some(OneOf::Right(InlayHintServerCapabilities::Options( + InlayHintOptions { + work_done_progress_options: WorkDoneProgressOptions { + work_done_progress: None, + }, + resolve_provider: None, + }, + ))), + ..Default::default() + }) + .expect("could not serialize server capabilities"); + + let (diag_sender, diag_receiver) = bounded::>>>(0); + let initialize_params: lsp_types::InitializeParams = + serde_json::from_value(client_response).expect("could not deserialize client capabilities"); + + // determine if linting is on or off based on what the editor requested + let lint = { + let lint_level = initialize_params + .initialization_options + .as_ref() + .and_then(|init_options| init_options.get("lintLevel")) + .and_then(serde_json::Value::as_str) + .unwrap_or(LINT_DEFAULT); + if lint_level == LINT_ALL { + LintLevel::All + } else if lint_level == LINT_NONE { + LintLevel::None + } else { + LintLevel::Default + } + }; + eprintln!("linting level {:?}", lint); + + let symbolicator_runner = symbols::SymbolicatorRunner::new( + ide_files_root.clone(), + symbols.clone(), + pkg_deps.clone(), + diag_sender, + lint, + ); + + // If initialization information from the client contains a path to the directory being + // opened, try to initialize symbols before sending response to the client. Do not bother + // with diagnostics as they will be recomputed whenever the first source file is opened. The + // main reason for this is to enable unit tests that rely on the symbolication information + // to be available right after the client is initialized. + if let Some(uri) = initialize_params.root_uri { + if let Some(p) = symbols::SymbolicatorRunner::root_dir(&uri.to_file_path().unwrap()) { + if let Ok((Some(new_symbols), _)) = symbols::get_symbols( + Arc::new(Mutex::new(BTreeMap::new())), + ide_files_root.clone(), + p.as_path(), + lint, + ) { + let mut old_symbols = symbols.lock().unwrap(); + (*old_symbols).merge(new_symbols); + } + } + } + + let context = Context { + connection, + symbols: symbols.clone(), + inlay_type_hints: initialize_params + .initialization_options + .as_ref() + .and_then(|init_options| init_options.get("inlayHintsType")) + .and_then(serde_json::Value::as_bool) + .unwrap_or_default(), + }; + + eprintln!("inlay type hints enabled: {}", context.inlay_type_hints); + + context + .connection + .initialize_finish( + id, + serde_json::json!({ + "capabilities": capabilities, + }), + ) + .expect("could not finish connection initialization"); + + let mut shutdown_req_received = false; + loop { + select! { + recv(diag_receiver) -> message => { + match message { + Ok(result) => { + match result { + Ok(diags) => { + for (k, v) in diags { + let url = Url::from_file_path(k).unwrap(); + let params = lsp_types::PublishDiagnosticsParams::new(url, v, None); + let notification = Notification::new(lsp_types::notification::PublishDiagnostics::METHOD.to_string(), params); + if let Err(err) = context + .connection + .sender + .send(lsp_server::Message::Notification(notification)) { + eprintln!("could not send diagnostics response: {:?}", err); + }; + } + }, + Err(err) => { + let typ = lsp_types::MessageType::ERROR; + let message = format!("{err}"); + // report missing manifest only once to avoid re-generating + // user-visible error in cases when the developer decides to + // keep editing a file that does not belong to a packages + let params = lsp_types::ShowMessageParams { typ, message }; + let notification = Notification::new(lsp_types::notification::ShowMessage::METHOD.to_string(), params); + if let Err(err) = context + .connection + .sender + .send(lsp_server::Message::Notification(notification)) { + eprintln!("could not send compiler error response: {:?}", err); + }; + }, + } + }, + Err(error) => { + eprintln!("symbolicator message error: {:?}", error); + // if the analyzer crashes in a separate thread, this error will keep + // getting generated for a while unless we explicitly end the process + // obscuring the real logged reason for the crash + std::process::exit(-1); + } + } + }, + recv(context.connection.receiver) -> message => { + match message { + Ok(Message::Request(request)) => { + // the server should not quit after receiving the shutdown request to give itself + // a chance of completing pending requests (but should not accept new requests + // either which is handled inside on_requst) - instead it quits after receiving + // the exit notification from the client, which is handled below + shutdown_req_received = on_request(&context, &request, ide_files_root.clone(), pkg_deps.clone(), shutdown_req_received); + } + Ok(Message::Response(response)) => on_response(&context, &response), + Ok(Message::Notification(notification)) => { + match notification.method.as_str() { + lsp_types::notification::Exit::METHOD => break, + lsp_types::notification::Cancel::METHOD => { + // TODO: Currently the server does not implement request cancellation. + // It ought to, especially once it begins processing requests that may + // take a long time to respond to. + } + _ => on_notification(ide_files_root.clone(), &symbolicator_runner, ¬ification), + } + } + Err(error) => eprintln!("IDE message error: {:?}", error), + } + } + }; + } + + io_threads.join().expect("I/O threads could not finish"); + symbolicator_runner.quit(); + eprintln!("Shut down language server '{}'.", exe); +} + +/// This function returns `true` if shutdown request has been received, and `false` otherwise. +/// The reason why this information is also passed as an argument is that according to the LSP +/// spec, if any additional requests are received after shutdownd then the LSP implementation +/// should respond with a particular type of error. +fn on_request( + context: &Context, + request: &Request, + ide_files_root: VfsPath, + pkg_dependencies: Arc>>, + shutdown_request_received: bool, +) -> bool { + if shutdown_request_received { + let response = lsp_server::Response::new_err( + request.id.clone(), + lsp_server::ErrorCode::InvalidRequest as i32, + "a shutdown request already received by the server".to_string(), + ); + if let Err(err) = context + .connection + .sender + .send(lsp_server::Message::Response(response)) + { + eprintln!("could not send shutdown response: {:?}", err); + } + return true; + } + match request.method.as_str() { + lsp_types::request::Completion::METHOD => { + on_completion_request(context, request, ide_files_root.clone(), pkg_dependencies) + } + lsp_types::request::GotoDefinition::METHOD => { + symbols::on_go_to_def_request(context, request, &context.symbols.lock().unwrap()); + } + lsp_types::request::GotoTypeDefinition::METHOD => { + symbols::on_go_to_type_def_request(context, request, &context.symbols.lock().unwrap()); + } + lsp_types::request::References::METHOD => { + symbols::on_references_request(context, request, &context.symbols.lock().unwrap()); + } + lsp_types::request::HoverRequest::METHOD => { + symbols::on_hover_request(context, request, &context.symbols.lock().unwrap()); + } + lsp_types::request::DocumentSymbolRequest::METHOD => { + symbols::on_document_symbol_request(context, request, &context.symbols.lock().unwrap()); + } + lsp_types::request::InlayHintRequest::METHOD => { + inlay_hints::on_inlay_hint_request(context, request, &context.symbols.lock().unwrap()); + } + lsp_types::request::Shutdown::METHOD => { + eprintln!("Shutdown request received"); + let response = + lsp_server::Response::new_ok(request.id.clone(), serde_json::Value::Null); + if let Err(err) = context + .connection + .sender + .send(lsp_server::Message::Response(response)) + { + eprintln!("could not send shutdown response: {:?}", err); + } + return true; + } + _ => eprintln!("handle request '{}' from client", request.method), + } + false +} + +fn on_response(_context: &Context, _response: &Response) { + eprintln!("handle response from client"); +} + +fn on_notification( + ide_files_root: VfsPath, + symbolicator_runner: &symbols::SymbolicatorRunner, + notification: &Notification, +) { + match notification.method.as_str() { + lsp_types::notification::DidOpenTextDocument::METHOD + | lsp_types::notification::DidChangeTextDocument::METHOD + | lsp_types::notification::DidSaveTextDocument::METHOD + | lsp_types::notification::DidCloseTextDocument::METHOD => { + on_text_document_sync_notification(ide_files_root, symbolicator_runner, notification) + } + _ => eprintln!("handle notification '{}' from client", notification.method), + } +} diff --git a/external-crates/move/crates/move-analyzer/src/bin/move-analyzer.rs b/external-crates/move/crates/move-analyzer/src/bin/move-analyzer.rs index a43a488fd76e2..a65f50131bc0e 100644 --- a/external-crates/move/crates/move-analyzer/src/bin/move-analyzer.rs +++ b/external-crates/move/crates/move-analyzer/src/bin/move-analyzer.rs @@ -1,34 +1,8 @@ -// Copyright (c) The Diem Core Contributors -// Copyright (c) The Move Contributors +// Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -use anyhow::Result; use clap::Parser; -use crossbeam::channel::{bounded, select}; -use lsp_server::{Connection, Message, Notification, Request, Response}; -use lsp_types::{ - notification::Notification as _, request::Request as _, CompletionOptions, Diagnostic, - HoverProviderCapability, InlayHintOptions, InlayHintServerCapabilities, OneOf, SaveOptions, - TextDocumentSyncCapability, TextDocumentSyncKind, TextDocumentSyncOptions, - TypeDefinitionProviderCapability, WorkDoneProgressOptions, -}; -use move_compiler::linters::LintLevel; -use std::{ - collections::BTreeMap, - path::PathBuf, - sync::{Arc, Mutex}, -}; - -use move_analyzer::{ - completion::on_completion_request, context::Context, inlay_hints, symbols, - vfs::on_text_document_sync_notification, -}; -use url::Url; -use vfs::{impls::memory::MemoryFS, VfsPath}; - -const LINT_NONE: &str = "none"; -const LINT_DEFAULT: &str = "default"; -const LINT_ALL: &str = "all"; +use move_analyzer::analyzer; #[derive(Parser)] #[clap(author, version, about)] @@ -39,319 +13,5 @@ fn main() { // For now, move-analyzer only responds to options built-in to clap, // such as `--help` or `--version`. Options::parse(); - - // stdio is used to communicate Language Server Protocol requests and responses. - // stderr is used for logging (and, when Visual Studio Code is used to communicate with this - // server, it captures this output in a dedicated "output channel"). - let exe = std::env::current_exe() - .unwrap() - .to_string_lossy() - .to_string(); - eprintln!( - "Starting language server '{}' communicating via stdio...", - exe - ); - - let (connection, io_threads) = Connection::stdio(); - let symbols = Arc::new(Mutex::new(symbols::empty_symbols())); - let pkg_deps = Arc::new(Mutex::new( - BTreeMap::::new(), - )); - let ide_files_root: VfsPath = MemoryFS::new().into(); - - let (id, client_response) = connection - .initialize_start() - .expect("could not start connection initialization"); - - let capabilities = serde_json::to_value(lsp_types::ServerCapabilities { - // The server receives notifications from the client as users open, close, - // and modify documents. - text_document_sync: Some(TextDocumentSyncCapability::Options( - TextDocumentSyncOptions { - open_close: Some(true), - // TODO: We request that the language server client send us the entire text of any - // files that are modified. We ought to use the "incremental" sync kind, which would - // have clients only send us what has changed and where, thereby requiring far less - // data be sent "over the wire." However, to do so, our language server would need - // to be capable of applying deltas to its view of the client's open files. See the - // 'move_analyzer::vfs' module for details. - change: Some(TextDocumentSyncKind::FULL), - will_save: None, - will_save_wait_until: None, - save: Some( - SaveOptions { - include_text: Some(true), - } - .into(), - ), - }, - )), - selection_range_provider: None, - hover_provider: Some(HoverProviderCapability::Simple(true)), - // The server provides completions as a user is typing. - completion_provider: Some(CompletionOptions { - resolve_provider: None, - // In Move, `foo::` and `foo.` should trigger completion suggestions for after - // the `:` or `.` - // (Trigger characters are just that: characters, such as `:`, and not sequences of - // characters, such as `::`. So when the language server encounters a completion - // request, it checks whether completions are being requested for `foo:`, and returns no - // completions in that case.) - trigger_characters: Some(vec![":".to_string(), ".".to_string(), "{".to_string()]), - all_commit_characters: None, - work_done_progress_options: WorkDoneProgressOptions { - work_done_progress: None, - }, - completion_item: None, - }), - definition_provider: Some(OneOf::Left(true)), - type_definition_provider: Some(TypeDefinitionProviderCapability::Simple(true)), - references_provider: Some(OneOf::Left(true)), - document_symbol_provider: Some(OneOf::Left(true)), - inlay_hint_provider: Some(OneOf::Right(InlayHintServerCapabilities::Options( - InlayHintOptions { - work_done_progress_options: WorkDoneProgressOptions { - work_done_progress: None, - }, - resolve_provider: None, - }, - ))), - ..Default::default() - }) - .expect("could not serialize server capabilities"); - - let (diag_sender, diag_receiver) = bounded::>>>(0); - let initialize_params: lsp_types::InitializeParams = - serde_json::from_value(client_response).expect("could not deserialize client capabilities"); - - // determine if linting is on or off based on what the editor requested - let lint = { - let lint_level = initialize_params - .initialization_options - .as_ref() - .and_then(|init_options| init_options.get("lintLevel")) - .and_then(serde_json::Value::as_str) - .unwrap_or(LINT_DEFAULT); - if lint_level == LINT_ALL { - LintLevel::All - } else if lint_level == LINT_NONE { - LintLevel::None - } else { - LintLevel::Default - } - }; - eprintln!("linting level {:?}", lint); - - let symbolicator_runner = symbols::SymbolicatorRunner::new( - ide_files_root.clone(), - symbols.clone(), - pkg_deps.clone(), - diag_sender, - lint, - ); - - // If initialization information from the client contains a path to the directory being - // opened, try to initialize symbols before sending response to the client. Do not bother - // with diagnostics as they will be recomputed whenever the first source file is opened. The - // main reason for this is to enable unit tests that rely on the symbolication information - // to be available right after the client is initialized. - if let Some(uri) = initialize_params.root_uri { - if let Some(p) = symbols::SymbolicatorRunner::root_dir(&uri.to_file_path().unwrap()) { - if let Ok((Some(new_symbols), _)) = symbols::get_symbols( - Arc::new(Mutex::new(BTreeMap::new())), - ide_files_root.clone(), - p.as_path(), - lint, - ) { - let mut old_symbols = symbols.lock().unwrap(); - (*old_symbols).merge(new_symbols); - } - } - } - - let context = Context { - connection, - symbols: symbols.clone(), - inlay_type_hints: initialize_params - .initialization_options - .as_ref() - .and_then(|init_options| init_options.get("inlayHintsType")) - .and_then(serde_json::Value::as_bool) - .unwrap_or_default(), - }; - - eprintln!("inlay type hints enabled: {}", context.inlay_type_hints); - - context - .connection - .initialize_finish( - id, - serde_json::json!({ - "capabilities": capabilities, - }), - ) - .expect("could not finish connection initialization"); - - let mut shutdown_req_received = false; - loop { - select! { - recv(diag_receiver) -> message => { - match message { - Ok(result) => { - match result { - Ok(diags) => { - for (k, v) in diags { - let url = Url::from_file_path(k).unwrap(); - let params = lsp_types::PublishDiagnosticsParams::new(url, v, None); - let notification = Notification::new(lsp_types::notification::PublishDiagnostics::METHOD.to_string(), params); - if let Err(err) = context - .connection - .sender - .send(lsp_server::Message::Notification(notification)) { - eprintln!("could not send diagnostics response: {:?}", err); - }; - } - }, - Err(err) => { - let typ = lsp_types::MessageType::ERROR; - let message = format!("{err}"); - // report missing manifest only once to avoid re-generating - // user-visible error in cases when the developer decides to - // keep editing a file that does not belong to a packages - let params = lsp_types::ShowMessageParams { typ, message }; - let notification = Notification::new(lsp_types::notification::ShowMessage::METHOD.to_string(), params); - if let Err(err) = context - .connection - .sender - .send(lsp_server::Message::Notification(notification)) { - eprintln!("could not send compiler error response: {:?}", err); - }; - }, - } - }, - Err(error) => { - eprintln!("symbolicator message error: {:?}", error); - // if the analyzer crashes in a separate thread, this error will keep - // getting generated for a while unless we explicitly end the process - // obscuring the real logged reason for the crash - std::process::exit(-1); - } - } - }, - recv(context.connection.receiver) -> message => { - match message { - Ok(Message::Request(request)) => { - // the server should not quit after receiving the shutdown request to give itself - // a chance of completing pending requests (but should not accept new requests - // either which is handled inside on_requst) - instead it quits after receiving - // the exit notification from the client, which is handled below - shutdown_req_received = on_request(&context, &request, ide_files_root.clone(), pkg_deps.clone(), shutdown_req_received); - } - Ok(Message::Response(response)) => on_response(&context, &response), - Ok(Message::Notification(notification)) => { - match notification.method.as_str() { - lsp_types::notification::Exit::METHOD => break, - lsp_types::notification::Cancel::METHOD => { - // TODO: Currently the server does not implement request cancellation. - // It ought to, especially once it begins processing requests that may - // take a long time to respond to. - } - _ => on_notification(ide_files_root.clone(), &symbolicator_runner, ¬ification), - } - } - Err(error) => eprintln!("IDE message error: {:?}", error), - } - } - }; - } - - io_threads.join().expect("I/O threads could not finish"); - symbolicator_runner.quit(); - eprintln!("Shut down language server '{}'.", exe); -} - -/// This function returns `true` if shutdown request has been received, and `false` otherwise. -/// The reason why this information is also passed as an argument is that according to the LSP -/// spec, if any additional requests are received after shutdownd then the LSP implementation -/// should respond with a particular type of error. -fn on_request( - context: &Context, - request: &Request, - ide_files_root: VfsPath, - pkg_dependencies: Arc>>, - shutdown_request_received: bool, -) -> bool { - if shutdown_request_received { - let response = lsp_server::Response::new_err( - request.id.clone(), - lsp_server::ErrorCode::InvalidRequest as i32, - "a shutdown request already received by the server".to_string(), - ); - if let Err(err) = context - .connection - .sender - .send(lsp_server::Message::Response(response)) - { - eprintln!("could not send shutdown response: {:?}", err); - } - return true; - } - match request.method.as_str() { - lsp_types::request::Completion::METHOD => { - on_completion_request(context, request, ide_files_root.clone(), pkg_dependencies) - } - lsp_types::request::GotoDefinition::METHOD => { - symbols::on_go_to_def_request(context, request, &context.symbols.lock().unwrap()); - } - lsp_types::request::GotoTypeDefinition::METHOD => { - symbols::on_go_to_type_def_request(context, request, &context.symbols.lock().unwrap()); - } - lsp_types::request::References::METHOD => { - symbols::on_references_request(context, request, &context.symbols.lock().unwrap()); - } - lsp_types::request::HoverRequest::METHOD => { - symbols::on_hover_request(context, request, &context.symbols.lock().unwrap()); - } - lsp_types::request::DocumentSymbolRequest::METHOD => { - symbols::on_document_symbol_request(context, request, &context.symbols.lock().unwrap()); - } - lsp_types::request::InlayHintRequest::METHOD => { - inlay_hints::on_inlay_hint_request(context, request, &context.symbols.lock().unwrap()); - } - lsp_types::request::Shutdown::METHOD => { - eprintln!("Shutdown request received"); - let response = - lsp_server::Response::new_ok(request.id.clone(), serde_json::Value::Null); - if let Err(err) = context - .connection - .sender - .send(lsp_server::Message::Response(response)) - { - eprintln!("could not send shutdown response: {:?}", err); - } - return true; - } - _ => eprintln!("handle request '{}' from client", request.method), - } - false -} - -fn on_response(_context: &Context, _response: &Response) { - eprintln!("handle response from client"); -} - -fn on_notification( - ide_files_root: VfsPath, - symbolicator_runner: &symbols::SymbolicatorRunner, - notification: &Notification, -) { - match notification.method.as_str() { - lsp_types::notification::DidOpenTextDocument::METHOD - | lsp_types::notification::DidChangeTextDocument::METHOD - | lsp_types::notification::DidSaveTextDocument::METHOD - | lsp_types::notification::DidCloseTextDocument::METHOD => { - on_text_document_sync_notification(ide_files_root, symbolicator_runner, notification) - } - _ => eprintln!("handle notification '{}' from client", notification.method), - } + analyzer::run(); } diff --git a/external-crates/move/crates/move-analyzer/src/lib.rs b/external-crates/move/crates/move-analyzer/src/lib.rs index 55a3d5db016d0..15082886df6a0 100644 --- a/external-crates/move/crates/move-analyzer/src/lib.rs +++ b/external-crates/move/crates/move-analyzer/src/lib.rs @@ -5,6 +5,7 @@ #[macro_use(sp)] extern crate move_ir_types; +pub mod analyzer; pub mod completion; pub mod context; pub mod diagnostics; From 214719e41fc355580886d3f9563d7874ad2709c5 Mon Sep 17 00:00:00 2001 From: Todd Nowacki Date: Tue, 28 May 2024 17:18:27 -0700 Subject: [PATCH 016/324] [move] Add CFGIR Ast Visitor. Clean up rough edges of T::Program. (#17787) ## Description - Some lints probably want to use the CFGIR, since they are easier to do post optimizations - Cleaned up the linter APIs ## Test plan - internal change --- ## Release notes Check each box that your changes affect. If none of the boxes relate to your changes, release notes aren't required. For each box you select, include information after the relevant heading that describes the impact of your changes that a user might notice and any actions they must take to implement updates. - [ ] Protocol: - [ ] Nodes (Validators and Full nodes): - [ ] Indexer: - [ ] JSON-RPC: - [ ] GraphQL: - [ ] CLI: - [ ] Rust SDK: --- .../move/crates/move-analyzer/src/symbols.rs | 6 +- .../crates/move-compiler/src/cfgir/ast.rs | 10 +- .../move-compiler/src/cfgir/locals/mod.rs | 71 ++-- .../crates/move-compiler/src/cfgir/mod.rs | 8 +- .../move-compiler/src/cfgir/translate.rs | 203 ++++++------ .../crates/move-compiler/src/cfgir/visitor.rs | 306 +++++++++++++++++- .../src/command_line/compiler.rs | 6 +- .../move/crates/move-compiler/src/hlir/ast.rs | 13 +- .../src/hlir/detect_dead_code.rs | 2 +- .../move-compiler/src/hlir/translate.rs | 13 +- .../src/linters/constant_naming.rs | 8 +- .../crates/move-compiler/src/shared/mod.rs | 15 +- .../move-compiler/src/shared/program_info.rs | 6 +- .../move-compiler/src/shared/string_utils.rs | 2 +- .../move-compiler/src/sui_mode/id_leak.rs | 28 +- .../src/sui_mode/linters/coin_field.rs | 9 +- .../sui_mode/linters/collection_equality.rs | 8 +- .../sui_mode/linters/custom_state_change.rs | 2 - .../src/sui_mode/linters/freeze_wrapped.rs | 15 +- .../src/sui_mode/linters/public_random.rs | 8 +- .../src/sui_mode/linters/self_transfer.rs | 9 +- .../src/sui_mode/linters/share_owned.rs | 9 +- .../move-compiler/src/sui_mode/typing.rs | 18 +- .../src/to_bytecode/translate.rs | 5 +- .../crates/move-compiler/src/typing/ast.rs | 13 +- .../move-compiler/src/typing/translate.rs | 14 +- .../move-compiler/src/typing/visitor.rs | 90 ++++-- .../move/crates/move-model/src/lib.rs | 14 +- 28 files changed, 612 insertions(+), 299 deletions(-) diff --git a/external-crates/move/crates/move-analyzer/src/symbols.rs b/external-crates/move/crates/move-analyzer/src/symbols.rs index 014b07bac5231..c76b2d5416129 100644 --- a/external-crates/move/crates/move-analyzer/src/symbols.rs +++ b/external-crates/move/crates/move-analyzer/src/symbols.rs @@ -1335,7 +1335,7 @@ pub fn get_symbols( // uwrap's are safe - this function returns earlier (during diagnostics processing) // when failing to produce the ASTs let parsed_program = parsed_ast.unwrap(); - let typed_modules = typed_ast.unwrap().inner.modules; + let typed_modules = typed_ast.unwrap().modules; let mut mod_outer_defs = BTreeMap::new(); let mut mod_use_defs = BTreeMap::new(); @@ -1358,7 +1358,7 @@ pub fn get_symbols( if let Some(libs) = compiled_libs.clone() { pre_process_typed_modules( &parsed_program, - &libs.typing.inner.modules, + &libs.typing.modules, &files, &file_id_mapping, &file_id_to_lines, @@ -1422,7 +1422,7 @@ pub fn get_symbols( ); if let Some(libs) = compiled_libs { process_typed_modules( - &libs.typing.inner.modules, + &libs.typing.modules, &source_files, &mod_to_alias_lengths, &mut typing_symbolicator, diff --git a/external-crates/move/crates/move-compiler/src/cfgir/ast.rs b/external-crates/move/crates/move-compiler/src/cfgir/ast.rs index 2aabb9d75a506..3957768d98b13 100644 --- a/external-crates/move/crates/move-compiler/src/cfgir/ast.rs +++ b/external-crates/move/crates/move-compiler/src/cfgir/ast.rs @@ -10,12 +10,15 @@ use crate::{ StructDefinition, Var, Visibility, }, parser::ast::{ConstantName, DatatypeName, FunctionName, ENTRY_MODIFIER}, - shared::{ast_debug::*, unique_map::UniqueMap}, + shared::{ast_debug::*, program_info::TypingProgramInfo, unique_map::UniqueMap}, }; use move_core_types::runtime_value::MoveValue; use move_ir_types::location::*; use move_symbol_pool::Symbol; -use std::collections::{BTreeMap, VecDeque}; +use std::{ + collections::{BTreeMap, VecDeque}, + sync::Arc, +}; // HLIR + Unstructured Control Flow + CFG @@ -25,6 +28,7 @@ use std::collections::{BTreeMap, VecDeque}; #[derive(Debug, Clone)] pub struct Program { + pub info: Arc, pub modules: UniqueMap, } @@ -187,7 +191,7 @@ fn remap_labels_cmd(remapping: &BTreeMap, sp!(_, cmd_): &mut Comma impl AstDebug for Program { fn ast_debug(&self, w: &mut AstWriter) { - let Program { modules } = self; + let Program { modules, info: _ } = self; for (m, mdef) in modules.key_cloned_iter() { w.write(&format!("module {}", m)); diff --git a/external-crates/move/crates/move-compiler/src/cfgir/locals/mod.rs b/external-crates/move/crates/move-compiler/src/cfgir/locals/mod.rs index 0461581ebb81a..78e71fbb21d1a 100644 --- a/external-crates/move/crates/move-compiler/src/cfgir/locals/mod.rs +++ b/external-crates/move/crates/move-compiler/src/cfgir/locals/mod.rs @@ -16,7 +16,11 @@ use crate::{ }, naming::ast::{self as N, TParam}, parser::ast::{Ability_, DatatypeName}, - shared::{unique_map::UniqueMap, *}, + shared::{ + program_info::{DatatypeKind, TypingProgramInfo}, + unique_map::UniqueMap, + *, + }, }; use move_ir_types::location::*; use move_proc_macros::growing_stack; @@ -30,8 +34,8 @@ use std::collections::BTreeMap; struct LocalsSafety<'a> { env: &'a CompilationEnv, + info: &'a TypingProgramInfo, package: Option, - datatype_declared_abilities: &'a UniqueMap>, local_types: &'a UniqueMap, signature: &'a FunctionSignature, unused_mut: BTreeMap, @@ -40,11 +44,8 @@ struct LocalsSafety<'a> { impl<'a> LocalsSafety<'a> { fn new( env: &'a CompilationEnv, + info: &'a TypingProgramInfo, package: Option, - datatype_declared_abilities: &'a UniqueMap< - ModuleIdent, - UniqueMap, - >, local_types: &'a UniqueMap, signature: &'a FunctionSignature, ) -> Self { @@ -60,8 +61,8 @@ impl<'a> LocalsSafety<'a> { .collect(); Self { env, + info, package, - datatype_declared_abilities, local_types, signature, unused_mut, @@ -71,8 +72,8 @@ impl<'a> LocalsSafety<'a> { struct Context<'a, 'b> { env: &'a CompilationEnv, + info: &'a TypingProgramInfo, package: Option, - datatype_declared_abilities: &'a UniqueMap>, local_types: &'a UniqueMap, unused_mut: &'a mut BTreeMap, local_states: &'b mut LocalStates, @@ -83,14 +84,14 @@ struct Context<'a, 'b> { impl<'a, 'b> Context<'a, 'b> { fn new(locals_safety: &'a mut LocalsSafety, local_states: &'b mut LocalStates) -> Self { let env = locals_safety.env; - let datatype_declared_abilities = &locals_safety.datatype_declared_abilities; + let info = locals_safety.info; let local_types = locals_safety.local_types; let signature = locals_safety.signature; let unused_mut = &mut locals_safety.unused_mut; Self { env, + info, package: locals_safety.package, - datatype_declared_abilities, local_types, unused_mut, local_states, @@ -138,6 +139,35 @@ impl<'a, 'b> Context<'a, 'b> { fn mark_mutable_usage(&mut self, _eloc: Loc, v: &Var) { self.unused_mut.remove(v); } + + // let decl_loc = *context + // .datatype_declared_abilities + // .get(m) + // .unwrap() + // .get_loc(s) + // .unwrap(); + // let declared_abilities = context + // .datatype_declared_abilities + // .get(m) + // .unwrap() + // .get(s) + // .unwrap(); + + fn datatype_decl_loc(&self, m: &ModuleIdent, n: &DatatypeName) -> Loc { + let kind = self.info.datatype_kind(m, n); + match kind { + DatatypeKind::Struct => self.info.struct_declared_loc(m, n), + DatatypeKind::Enum => self.info.enum_declared_loc(m, n), + } + } + + fn datatype_declared_abilities(&self, m: &ModuleIdent, n: &DatatypeName) -> &'a AbilitySet { + let kind = self.info.datatype_kind(m, n); + match kind { + DatatypeKind::Struct => self.info.struct_declared_abilities(m, n), + DatatypeKind::Enum => self.info.enum_declared_abilities(m, n), + } + } } impl<'a> TransferFunctions for LocalsSafety<'a> { @@ -164,16 +194,13 @@ pub fn verify( cfg: &super::cfg::MutForwardCFG, ) -> BTreeMap { let super::CFGContext { - datatype_declared_abilities, - signature, - locals, - .. + signature, locals, .. } = context; let initial_state = LocalStates::initial(&signature.parameters, locals); let mut locals_safety = LocalsSafety::new( compilation_env, + context.info, context.package, - datatype_declared_abilities, locals, signature, ); @@ -539,18 +566,8 @@ fn add_drop_ability_tip(context: &Context, diag: &mut Diagnostic, st: SingleType (None, &owned_abilities, ty_args.clone()) } T::Apply(_, sp!(_, TN::ModuleType(m, s)), ty_args) => { - let decl_loc = *context - .datatype_declared_abilities - .get(m) - .unwrap() - .get_loc(s) - .unwrap(); - let declared_abilities = context - .datatype_declared_abilities - .get(m) - .unwrap() - .get(s) - .unwrap(); + let decl_loc = context.datatype_decl_loc(m, s); + let declared_abilities = context.datatype_declared_abilities(m, s); (Some(decl_loc), declared_abilities, ty_args.clone()) } t => panic!( diff --git a/external-crates/move/crates/move-compiler/src/cfgir/mod.rs b/external-crates/move/crates/move-compiler/src/cfgir/mod.rs index caeac4ea4ea81..958e2a3abb3fc 100644 --- a/external-crates/move/crates/move-compiler/src/cfgir/mod.rs +++ b/external-crates/move/crates/move-compiler/src/cfgir/mod.rs @@ -15,10 +15,9 @@ pub mod visitor; mod optimize; use crate::{ - expansion::ast::{AbilitySet, Attributes, ModuleIdent, Mutability}, + expansion::ast::{Attributes, ModuleIdent, Mutability}, hlir::ast::{FunctionSignature, Label, SingleType, Var, Visibility}, - parser::ast::DatatypeName, - shared::{unique_map::UniqueMap, CompilationEnv, Name}, + shared::{program_info::TypingProgramInfo, unique_map::UniqueMap, CompilationEnv, Name}, }; use cfg::*; use move_ir_types::location::Loc; @@ -27,11 +26,10 @@ use optimize::optimize; use std::collections::BTreeSet; pub struct CFGContext<'a> { + pub info: &'a TypingProgramInfo, pub package: Option, pub module: ModuleIdent, pub member: MemberName, - pub datatype_declared_abilities: - &'a UniqueMap>, pub attributes: &'a Attributes, pub entry: Option, pub visibility: Visibility, diff --git a/external-crates/move/crates/move-compiler/src/cfgir/translate.rs b/external-crates/move/crates/move-compiler/src/cfgir/translate.rs index 8192fd4efcfa2..bed2c9b1fb10a 100644 --- a/external-crates/move/crates/move-compiler/src/cfgir/translate.rs +++ b/external-crates/move/crates/move-compiler/src/cfgir/translate.rs @@ -7,13 +7,14 @@ use crate::{ self, ast::{self as G, BasicBlock, BasicBlocks, BlockInfo}, cfg::{ImmForwardCFG, MutForwardCFG}, + visitor::{CFGIRVisitorConstructor, CFGIRVisitorContext}, }, diag, diagnostics::Diagnostics, - expansion::ast::{AbilitySet, Attributes, ModuleIdent, Mutability}, + expansion::ast::{Attributes, ModuleIdent, Mutability}, hlir::ast::{self as H, BlockLabel, Label, Value, Value_, Var}, - parser::ast::{ConstantName, DatatypeName, FunctionName}, - shared::{unique_map::UniqueMap, CompilationEnv}, + parser::ast::{ConstantName, FunctionName}, + shared::{program_info::TypingProgramInfo, unique_map::UniqueMap, CompilationEnv}, FullyCompiledProgram, }; use cfgir::ast::LoopInfo; @@ -42,8 +43,8 @@ enum NamedBlockType { struct Context<'env> { env: &'env mut CompilationEnv, + info: &'env TypingProgramInfo, current_package: Option, - datatype_declared_abilities: UniqueMap>, label_count: usize, named_blocks: UniqueMap, // Used for populating block_info @@ -51,37 +52,11 @@ struct Context<'env> { } impl<'env> Context<'env> { - pub fn new( - env: &'env mut CompilationEnv, - pre_compiled_lib: Option>, - modules: &UniqueMap, - ) -> Self { - let all_modules = modules - .key_cloned_iter() - .chain(pre_compiled_lib.iter().flat_map(|pre_compiled| { - pre_compiled - .hlir - .modules - .key_cloned_iter() - .filter(|(mident, _m)| !modules.contains_key(mident)) - })); - let datatype_declared_abilities = all_modules.map(|(m, mdef)| { - let smap = mdef.structs.ref_map(|_s, sdef| sdef.abilities.clone()); - let emap = mdef.enums.ref_map(|_e, edef| edef.abilities.clone()); - ( - m, - smap.union_with(&emap, |_x, _y, _z| { - panic!("ICE should have failed in naming") - }), - ) - }); - - let datatype_declared_abilities = - UniqueMap::maybe_from_iter(datatype_declared_abilities).unwrap(); + pub fn new(env: &'env mut CompilationEnv, info: &'env TypingProgramInfo) -> Self { Context { env, + info, current_package: None, - datatype_declared_abilities, label_count: 0, named_blocks: UniqueMap::new(), loop_bounds: BTreeMap::new(), @@ -147,17 +122,23 @@ impl<'env> Context<'env> { pub fn program( compilation_env: &mut CompilationEnv, - pre_compiled_lib: Option>, + _pre_compiled_lib: Option>, prog: H::Program, ) -> G::Program { - let H::Program { modules: hmodules } = prog; + let H::Program { + modules: hmodules, + info, + } = prog; - let mut context = Context::new(compilation_env, pre_compiled_lib, &hmodules); + let mut context = Context::new(compilation_env, &info); let modules = modules(&mut context, hmodules); - let program = G::Program { modules }; - visit_program(&mut context, &program); + let mut program = G::Program { + modules, + info: info.clone(), + }; + visit_program(&mut context, &mut program); program } @@ -490,10 +471,10 @@ fn constant_( }; let fake_infinite_loop_starts = BTreeSet::new(); let function_context = super::CFGContext { + info: context.info, package: context.current_package, module, member: cfgir::MemberName::Constant(name.0), - datatype_declared_abilities: &context.datatype_declared_abilities, attributes, entry: None, visibility: H::Visibility::Internal, @@ -649,10 +630,10 @@ fn function_body( context.env.add_diags(diags); let function_context = super::CFGContext { + info: context.info, package: context.current_package, module, member: cfgir::MemberName::Function(name.0), - datatype_declared_abilities: &context.datatype_declared_abilities, attributes, entry, visibility, @@ -983,76 +964,96 @@ fn destructure_tuple((fst, snd): &(T, U)) -> (&T, &U) { // Visitors //************************************************************************************************** -fn visit_program(context: &mut Context, prog: &G::Program) { - if context.env.visitors().abs_int.is_empty() { +fn visit_program(context: &mut Context, prog: &mut G::Program) { + if context.env.visitors().abs_int.is_empty() && context.env.visitors().cfgir.is_empty() { return; } - for (mident, mdef) in prog.modules.key_cloned_iter() { - visit_module(context, prog, mident, mdef) + AbsintVisitor.visit(context.env, prog); + + for visitor in &context.env.visitors().cfgir { + let mut v = visitor.borrow_mut(); + v.visit(context.env, prog) } } -fn visit_module( - context: &mut Context, - prog: &G::Program, - mident: ModuleIdent, - mdef: &G::ModuleDefinition, -) { - context - .env - .add_warning_filter_scope(mdef.warning_filter.clone()); - for (name, fdef) in mdef.functions.key_cloned_iter() { - visit_function(context, prog, mident, name, fdef) +struct AbsintVisitor; +struct AbsintVisitorContext<'a> { + env: &'a mut CompilationEnv, + info: Arc, + current_package: Option, +} + +impl CFGIRVisitorConstructor for AbsintVisitor { + type Context<'a> = AbsintVisitorContext<'a>; + + fn context<'a>(env: &'a mut CompilationEnv, program: &G::Program) -> Self::Context<'a> { + AbsintVisitorContext { + env, + info: program.info.clone(), + current_package: None, + } } - context.env.pop_warning_filter_scope(); } -fn visit_function( - context: &mut Context, - prog: &G::Program, - mident: ModuleIdent, - name: FunctionName, - fdef: &G::Function, -) { - let G::Function { - warning_filter, - index: _, - attributes, - compiled_visibility: _, - visibility, - entry, - signature, - body, - } = fdef; - let G::FunctionBody_::Defined { - locals, - start, - blocks, - block_info, - } = &body.value - else { - return; - }; - context.env.add_warning_filter_scope(warning_filter.clone()); - let (cfg, infinite_loop_starts) = ImmForwardCFG::new(*start, blocks, block_info.iter()); - let function_context = super::CFGContext { - package: context.current_package, - module: mident, - member: cfgir::MemberName::Function(name.0), - datatype_declared_abilities: &context.datatype_declared_abilities, - attributes, - entry: *entry, - visibility: *visibility, - signature, - locals, - infinite_loop_starts: &infinite_loop_starts, - }; - let mut ds = Diagnostics::new(); - for visitor in &context.env.visitors().abs_int { - let mut v = visitor.borrow_mut(); - ds.extend(v.verify(context.env, prog, &function_context, &cfg)); +impl<'a> CFGIRVisitorContext for AbsintVisitorContext<'a> { + fn add_warning_filter_scope(&mut self, filter: crate::diagnostics::WarningFilters) { + self.env.add_warning_filter_scope(filter) + } + + fn pop_warning_filter_scope(&mut self) { + self.env.pop_warning_filter_scope() + } + + fn visit_module_custom(&mut self, _ident: ModuleIdent, mdef: &mut G::ModuleDefinition) -> bool { + self.current_package = mdef.package_name; + false + } + + fn visit_function_custom( + &mut self, + mident: ModuleIdent, + name: FunctionName, + fdef: &mut G::Function, + ) -> bool { + let G::Function { + warning_filter: _, + index: _, + attributes, + compiled_visibility: _, + visibility, + entry, + signature, + body, + } = fdef; + let G::FunctionBody_::Defined { + locals, + start, + blocks, + block_info, + } = &body.value + else { + return true; + }; + let (cfg, infinite_loop_starts) = ImmForwardCFG::new(*start, blocks, block_info.iter()); + let function_context = super::CFGContext { + info: &self.info, + package: self.current_package, + module: mident, + member: cfgir::MemberName::Function(name.0), + attributes, + entry: *entry, + visibility: *visibility, + signature, + locals, + infinite_loop_starts: &infinite_loop_starts, + }; + let mut ds = Diagnostics::new(); + for visitor in &self.env.visitors().abs_int { + let mut v = visitor.borrow_mut(); + ds.extend(v.verify(self.env, &function_context, &cfg)); + } + self.env.add_diags(ds); + true } - context.env.add_diags(ds); - context.env.pop_warning_filter_scope(); } diff --git a/external-crates/move/crates/move-compiler/src/cfgir/visitor.rs b/external-crates/move/crates/move-compiler/src/cfgir/visitor.rs index 1b8a8d3cd9b66..4fbe1f3d9a6d9 100644 --- a/external-crates/move/crates/move-compiler/src/cfgir/visitor.rs +++ b/external-crates/move/crates/move-compiler/src/cfgir/visitor.rs @@ -5,29 +5,39 @@ use std::{collections::BTreeMap, fmt::Debug}; use crate::{ cfgir::{ - self, absint::{AbstractDomain, AbstractInterpreter, JoinResult, TransferFunctions}, + ast as G, cfg::ImmForwardCFG, CFGContext, }, command_line::compiler::Visitor, - diagnostics::{Diagnostic, Diagnostics}, - hlir::ast::{ - Command, Command_, Exp, LValue, LValue_, Label, ModuleCall, Type, Type_, UnannotatedExp_, - Var, - }, + diagnostics::{Diagnostic, Diagnostics, WarningFilters}, + expansion::ast::ModuleIdent, + hlir::ast::{self as H, Command, Exp, LValue, LValue_, Label, ModuleCall, Type, Type_, Var}, + parser::ast::{ConstantName, DatatypeName, FunctionName}, shared::CompilationEnv, }; use move_ir_types::location::*; use move_proc_macros::growing_stack; pub type AbsIntVisitorObj = Box; +pub type CFGIRVisitorObj = Box; + +pub trait CFGIRVisitor { + fn visit(&mut self, env: &mut CompilationEnv, program: &mut G::Program); + + fn visitor(self) -> Visitor + where + Self: 'static + Sized, + { + Visitor::CFGIRVisitor(Box::new(self)) + } +} pub trait AbstractInterpreterVisitor { fn verify( &mut self, env: &CompilationEnv, - program: &cfgir::ast::Program, context: &CFGContext, cfg: &ImmForwardCFG, ) -> Diagnostics; @@ -41,7 +51,276 @@ pub trait AbstractInterpreterVisitor { } //************************************************************************************************** -// simple visitor +// simple ast visitor +//************************************************************************************************** + +pub trait CFGIRVisitorConstructor { + type Context<'a>: Sized + CFGIRVisitorContext; + + fn context<'a>(env: &'a mut CompilationEnv, program: &G::Program) -> Self::Context<'a>; + + fn visit(&mut self, env: &mut CompilationEnv, program: &mut G::Program) { + let mut context = Self::context(env, program); + context.visit(program); + } +} + +pub trait CFGIRVisitorContext { + fn add_warning_filter_scope(&mut self, filter: WarningFilters); + fn pop_warning_filter_scope(&mut self); + + fn visit_module_custom( + &mut self, + _ident: ModuleIdent, + _mdef: &mut G::ModuleDefinition, + ) -> bool { + false + } + + /// By default, the visitor will visit all all expressions in all functions in all modules. A + /// custom version should of this function should be created if different type of analysis is + /// required. + fn visit(&mut self, program: &mut G::Program) { + for (mident, mdef) in program.modules.key_cloned_iter_mut() { + self.add_warning_filter_scope(mdef.warning_filter.clone()); + if self.visit_module_custom(mident, mdef) { + self.pop_warning_filter_scope(); + continue; + } + + for (struct_name, sdef) in mdef.structs.key_cloned_iter_mut() { + self.visit_struct(mident, struct_name, sdef) + } + for (enum_name, edef) in mdef.enums.key_cloned_iter_mut() { + self.visit_enum(mident, enum_name, edef) + } + for (constant_name, cdef) in mdef.constants.key_cloned_iter_mut() { + self.visit_constant(mident, constant_name, cdef) + } + for (function_name, fdef) in mdef.functions.key_cloned_iter_mut() { + self.visit_function(mident, function_name, fdef) + } + + self.pop_warning_filter_scope(); + } + } + + // TODO type visiting + + fn visit_struct_custom( + &mut self, + _module: ModuleIdent, + _struct_name: DatatypeName, + _sdef: &mut H::StructDefinition, + ) -> bool { + false + } + fn visit_struct( + &mut self, + module: ModuleIdent, + struct_name: DatatypeName, + sdef: &mut H::StructDefinition, + ) { + self.add_warning_filter_scope(sdef.warning_filter.clone()); + if self.visit_struct_custom(module, struct_name, sdef) { + self.pop_warning_filter_scope(); + return; + } + self.pop_warning_filter_scope(); + } + + fn visit_enum_custom( + &mut self, + _module: ModuleIdent, + _enum_name: DatatypeName, + _edef: &mut H::EnumDefinition, + ) -> bool { + false + } + fn visit_enum( + &mut self, + module: ModuleIdent, + enum_name: DatatypeName, + edef: &mut H::EnumDefinition, + ) { + self.add_warning_filter_scope(edef.warning_filter.clone()); + if self.visit_enum_custom(module, enum_name, edef) { + self.pop_warning_filter_scope(); + return; + } + self.pop_warning_filter_scope(); + } + + fn visit_constant_custom( + &mut self, + _module: ModuleIdent, + _constant_name: ConstantName, + _cdef: &mut G::Constant, + ) -> bool { + false + } + fn visit_constant( + &mut self, + module: ModuleIdent, + constant_name: ConstantName, + cdef: &mut G::Constant, + ) { + self.add_warning_filter_scope(cdef.warning_filter.clone()); + if self.visit_constant_custom(module, constant_name, cdef) { + self.pop_warning_filter_scope(); + return; + } + self.pop_warning_filter_scope(); + } + + fn visit_function_custom( + &mut self, + _module: ModuleIdent, + _function_name: FunctionName, + _fdef: &mut G::Function, + ) -> bool { + false + } + fn visit_function( + &mut self, + module: ModuleIdent, + function_name: FunctionName, + fdef: &mut G::Function, + ) { + self.add_warning_filter_scope(fdef.warning_filter.clone()); + if self.visit_function_custom(module, function_name, fdef) { + self.pop_warning_filter_scope(); + return; + } + if let G::FunctionBody_::Defined { + locals: _, + start: _, + block_info: _, + blocks, + } = &mut fdef.body.value + { + for (lbl, block) in blocks { + self.visit_block(*lbl, block); + } + } + self.pop_warning_filter_scope(); + } + + fn visit_block_custom(&mut self, _lbl: Label, _block: &mut G::BasicBlock) -> bool { + false + } + fn visit_block(&mut self, _lbl: Label, block: &mut G::BasicBlock) { + for cmd in block { + self.visit_command(cmd) + } + } + + fn visit_command_custom(&mut self, _cmd: &mut H::Command) -> bool { + false + } + fn visit_command(&mut self, cmd: &mut H::Command) { + use H::Command_ as C; + if self.visit_command_custom(cmd) { + return; + } + match &mut cmd.value { + C::Assign(_, _, e) + | C::Abort(e) + | C::Return { exp: e, .. } + | C::IgnoreAndPop { exp: e, .. } + | C::JumpIf { cond: e, .. } + | C::VariantSwitch { subject: e, .. } => { + self.visit_exp(e); + } + C::Mutate(el, er) => { + self.visit_exp(el); + self.visit_exp(er); + } + C::Jump { .. } => (), + C::Break(_) | C::Continue(_) => panic!("ICE break/continue not translated to jumps"), + } + } + + fn visit_exp_custom(&mut self, _e: &mut H::Exp) -> bool { + false + } + #[growing_stack] + fn visit_exp(&mut self, e: &mut H::Exp) { + use H::UnannotatedExp_ as E; + if self.visit_exp_custom(e) { + return; + } + match &mut e.exp.value { + E::Unit { .. } + | E::Move { .. } + | E::Copy { .. } + | E::Constant(_) + | E::ErrorConstant { .. } + | E::BorrowLocal(_, _) + | E::Unreachable + | E::UnresolvedError => (), + + E::Value(v) => self.visit_value(v), + + E::Freeze(e) + | E::Dereference(e) + | E::UnaryExp(_, e) + | E::Borrow(_, e, _, _) + | E::Cast(e, _) => self.visit_exp(e), + + E::BinopExp(el, _, er) => { + self.visit_exp(el); + self.visit_exp(er); + } + + E::ModuleCall(m) => { + for arg in &mut m.arguments { + self.visit_exp(arg) + } + } + E::Vector(_, _, _, es) | E::Multiple(es) => { + for e in es { + self.visit_exp(e) + } + } + + E::Pack(_, _, es) | E::PackVariant(_, _, _, es) => { + for (_, _, e) in es { + self.visit_exp(e) + } + } + } + } + + fn visit_value_custom(&mut self, _v: &mut H::Value) -> bool { + false + } + #[growing_stack] + fn visit_value(&mut self, v: &mut H::Value) { + use H::Value_ as V; + if self.visit_value_custom(v) { + return; + } + match &mut v.value { + V::Address(_) + | V::U8(_) + | V::U16(_) + | V::U32(_) + | V::U64(_) + | V::U128(_) + | V::U256(_) + | V::Bool(_) => (), + V::Vector(_, vs) => { + for v in vs { + self.visit_value(v) + } + } + } + } +} + +//************************************************************************************************** +// simple absint visitor //************************************************************************************************** /// The reason why a local variable is unavailable (mostly useful for error messages) @@ -162,7 +441,6 @@ pub trait SimpleAbsIntConstructor: Sized { /// Return None if it should not be run given this context fn new<'a>( env: &CompilationEnv, - program: &'a cfgir::ast::Program, context: &'a CFGContext<'a>, init_state: &mut as SimpleAbsInt>::State, ) -> Option>; @@ -170,7 +448,6 @@ pub trait SimpleAbsIntConstructor: Sized { fn verify( &mut self, env: &CompilationEnv, - program: &cfgir::ast::Program, context: &CFGContext, cfg: &ImmForwardCFG, ) -> Diagnostics { @@ -192,7 +469,7 @@ pub trait SimpleAbsIntConstructor: Sized { ); } let mut init_state = as SimpleAbsInt>::State::new(context, locals); - let Some(mut ai) = Self::new(env, program, context, &mut init_state) else { + let Some(mut ai) = Self::new(env, context, &mut init_state) else { return Diagnostics::new(); }; let (final_state, ds) = ai.analyze_function(cfg, init_state); @@ -239,7 +516,7 @@ pub trait SimpleAbsInt: Sized { state: &mut Self::State, cmd: &Command, ) { - use Command_ as C; + use H::Command_ as C; if self.command_custom(context, state, cmd) { return; } @@ -351,7 +628,7 @@ pub trait SimpleAbsInt: Sized { state: &mut Self::State, parent_e: &Exp, ) -> Vec<::Value> { - use UnannotatedExp_ as E; + use H::UnannotatedExp_ as E; if let Some(vs) = self.exp_custom(context, state, parent_e) { return vs; } @@ -476,10 +753,9 @@ impl AbstractInterpreterVisitor for V { fn verify( &mut self, env: &CompilationEnv, - program: &cfgir::ast::Program, context: &CFGContext, cfg: &ImmForwardCFG, ) -> Diagnostics { - SimpleAbsIntConstructor::verify(self, env, program, context, cfg) + SimpleAbsIntConstructor::verify(self, env, context, cfg) } } diff --git a/external-crates/move/crates/move-compiler/src/command_line/compiler.rs b/external-crates/move/crates/move-compiler/src/command_line/compiler.rs index 73fd1f33c2fc9..65b2b581cb53d 100644 --- a/external-crates/move/crates/move-compiler/src/command_line/compiler.rs +++ b/external-crates/move/crates/move-compiler/src/command_line/compiler.rs @@ -3,7 +3,10 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{ - cfgir::{self, visitor::AbsIntVisitorObj}, + cfgir::{ + self, + visitor::{AbsIntVisitorObj, CFGIRVisitorObj}, + }, command_line::{DEFAULT_OUTPUT_DIR, MOVE_COMPILED_INTERFACES_DIR}, compiled_unit::{self, AnnotatedCompiledUnit}, diagnostics::{ @@ -107,6 +110,7 @@ pub struct FullyCompiledProgram { pub enum Visitor { TypingVisitor(TypingVisitorObj), + CFGIRVisitor(CFGIRVisitorObj), AbsIntVisitor(AbsIntVisitorObj), } diff --git a/external-crates/move/crates/move-compiler/src/hlir/ast.rs b/external-crates/move/crates/move-compiler/src/hlir/ast.rs index 13af4e702e176..ee4c37cc71ca8 100644 --- a/external-crates/move/crates/move-compiler/src/hlir/ast.rs +++ b/external-crates/move/crates/move-compiler/src/hlir/ast.rs @@ -13,11 +13,17 @@ use crate::{ self as P, BinOp, ConstantName, DatatypeName, Field, FunctionName, UnaryOp, VariantName, ENTRY_MODIFIER, }, - shared::{ast_debug::*, unique_map::UniqueMap, Name, NumericalAddress, TName}, + shared::{ + ast_debug::*, program_info::TypingProgramInfo, unique_map::UniqueMap, Name, + NumericalAddress, TName, + }, }; use move_ir_types::location::*; use move_symbol_pool::Symbol; -use std::collections::{BTreeMap, BTreeSet, VecDeque}; +use std::{ + collections::{BTreeMap, BTreeSet, VecDeque}, + sync::Arc, +}; // High Level IR @@ -27,6 +33,7 @@ use std::collections::{BTreeMap, BTreeSet, VecDeque}; #[derive(Debug, Clone)] pub struct Program { + pub info: Arc, pub modules: UniqueMap, } @@ -888,7 +895,7 @@ impl std::fmt::Display for Label { impl AstDebug for Program { fn ast_debug(&self, w: &mut AstWriter) { - let Program { modules } = self; + let Program { modules, info: _ } = self; for (m, mdef) in modules.key_cloned_iter() { w.write(&format!("module {}", m)); diff --git a/external-crates/move/crates/move-compiler/src/hlir/detect_dead_code.rs b/external-crates/move/crates/move-compiler/src/hlir/detect_dead_code.rs index d16cd678f927d..45a2529ed7e0a 100644 --- a/external-crates/move/crates/move-compiler/src/hlir/detect_dead_code.rs +++ b/external-crates/move/crates/move-compiler/src/hlir/detect_dead_code.rs @@ -211,7 +211,7 @@ fn unreachable_code(loc: Loc) -> Option { pub fn program(compilation_env: &mut CompilationEnv, prog: &T::Program) { let mut context = Context::new(compilation_env); - modules(&mut context, &prog.inner.modules); + modules(&mut context, &prog.modules); } fn modules(context: &mut Context, modules: &UniqueMap) { diff --git a/external-crates/move/crates/move-compiler/src/hlir/translate.rs b/external-crates/move/crates/move-compiler/src/hlir/translate.rs index 1f1405cebfab5..0960f13cf32bf 100644 --- a/external-crates/move/crates/move-compiler/src/hlir/translate.rs +++ b/external-crates/move/crates/move-compiler/src/hlir/translate.rs @@ -148,7 +148,7 @@ impl<'env> Context<'env> { pub fn new( env: &'env mut CompilationEnv, pre_compiled_lib_opt: Option>, - prog: &T::Program_, + prog: &T::Program, ) -> Self { fn add_struct_fields( env: &mut CompilationEnv, @@ -243,7 +243,7 @@ impl<'env> Context<'env> { let mut structs = UniqueMap::new(); let mut variant_fields = UniqueMap::new(); if let Some(pre_compiled_lib) = pre_compiled_lib_opt { - for (mident, mdef) in pre_compiled_lib.typing.inner.modules.key_cloned_iter() { + for (mident, mdef) in pre_compiled_lib.typing.modules.key_cloned_iter() { add_struct_fields(env, &mut structs, mident, &mdef.structs); add_enums(env, &mut variant_fields, mident, &mdef.enums); } @@ -389,11 +389,14 @@ pub fn program( ) -> H::Program { detect_dead_code_analysis(compilation_env, &prog); - let mut context = Context::new(compilation_env, pre_compiled_lib, &prog.inner); - let T::Program_ { modules: tmodules } = prog.inner; + let mut context = Context::new(compilation_env, pre_compiled_lib, &prog); + let T::Program { + modules: tmodules, + info, + } = prog; let modules = modules(&mut context, tmodules); - H::Program { modules } + H::Program { modules, info } } fn modules( diff --git a/external-crates/move/crates/move-compiler/src/linters/constant_naming.rs b/external-crates/move/crates/move-compiler/src/linters/constant_naming.rs index f420f4e34c067..99525fd275760 100644 --- a/external-crates/move/crates/move-compiler/src/linters/constant_naming.rs +++ b/external-crates/move/crates/move-compiler/src/linters/constant_naming.rs @@ -12,7 +12,7 @@ use crate::{ }, expansion::ast::ModuleIdent, parser::ast::ConstantName, - shared::{program_info::TypingProgramInfo, CompilationEnv}, + shared::CompilationEnv, typing::{ ast as T, visitor::{TypingVisitorConstructor, TypingVisitorContext}, @@ -37,11 +37,7 @@ pub struct Context<'a> { impl TypingVisitorConstructor for ConstantNamingVisitor { type Context<'a> = Context<'a>; - fn context<'a>( - env: &'a mut CompilationEnv, - _program_info: &'a TypingProgramInfo, - _program: &T::Program_, - ) -> Self::Context<'a> { + fn context<'a>(env: &'a mut CompilationEnv, _program: &T::Program) -> Self::Context<'a> { Context { env } } } diff --git a/external-crates/move/crates/move-compiler/src/shared/mod.rs b/external-crates/move/crates/move-compiler/src/shared/mod.rs index 9c25418aa8a7f..02c183e75fa84 100644 --- a/external-crates/move/crates/move-compiler/src/shared/mod.rs +++ b/external-crates/move/crates/move-compiler/src/shared/mod.rs @@ -3,8 +3,10 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{ - cfgir::ast as G, - cfgir::visitor::{AbsIntVisitorObj, AbstractInterpreterVisitor}, + cfgir::{ + ast as G, + visitor::{AbsIntVisitorObj, AbstractInterpreterVisitor, CFGIRVisitorObj}, + }, command_line as cli, diagnostics::{ codes::{Category, Declarations, DiagnosticsID, Severity, WarningFilter}, @@ -19,8 +21,10 @@ use crate::{ naming::ast as N, parser::ast as P, sui_mode, - typing::ast as T, - typing::visitor::{TypingVisitor, TypingVisitorObj}, + typing::{ + ast as T, + visitor::{TypingVisitor, TypingVisitorObj}, + }, }; use clap::*; use move_command_line_common::files::FileHash; @@ -882,6 +886,7 @@ impl Default for PackageConfig { pub struct Visitors { pub typing: Vec>, pub abs_int: Vec>, + pub cfgir: Vec>, } impl Visitors { @@ -890,11 +895,13 @@ impl Visitors { let mut vs = Visitors { typing: vec![], abs_int: vec![], + cfgir: vec![], }; for pass in passes { match pass { Visitor::AbsIntVisitor(f) => vs.abs_int.push(RefCell::new(f)), Visitor::TypingVisitor(f) => vs.typing.push(RefCell::new(f)), + Visitor::CFGIRVisitor(f) => vs.cfgir.push(RefCell::new(f)), } } vs diff --git a/external-crates/move/crates/move-compiler/src/shared/program_info.rs b/external-crates/move/crates/move-compiler/src/shared/program_info.rs index 594da8d4c27cc..45ba1c9715509 100644 --- a/external-crates/move/crates/move-compiler/src/shared/program_info.rs +++ b/external-crates/move/crates/move-compiler/src/shared/program_info.rs @@ -115,10 +115,14 @@ macro_rules! program_info { impl TypingProgramInfo { pub fn new( pre_compiled_lib: Option>, - prog: &T::Program_, + modules: &UniqueMap, mut module_use_funs: BTreeMap, ) -> Self { + struct Prog<'a> { + modules: &'a UniqueMap, + } let mut module_use_funs = Some(&mut module_use_funs); + let prog = Prog { modules }; program_info!(pre_compiled_lib, prog, typing, module_use_funs) } } diff --git a/external-crates/move/crates/move-compiler/src/shared/string_utils.rs b/external-crates/move/crates/move-compiler/src/shared/string_utils.rs index c965236db4327..f0933ca7484a9 100644 --- a/external-crates/move/crates/move-compiler/src/shared/string_utils.rs +++ b/external-crates/move/crates/move-compiler/src/shared/string_utils.rs @@ -36,7 +36,7 @@ pub fn make_ascii_titlecase(in_s: &str) -> String { /// /// This will use `or` as the separator for the last two elements, interspersing commas as /// appropriate: -/// ``` +/// ```text /// format_oxford_list("or", "{}", [1]); /// ==> "1" /// diff --git a/external-crates/move/crates/move-compiler/src/sui_mode/id_leak.rs b/external-crates/move/crates/move-compiler/src/sui_mode/id_leak.rs index 5c8f76f6e0ea5..78230ddf3cda1 100644 --- a/external-crates/move/crates/move-compiler/src/sui_mode/id_leak.rs +++ b/external-crates/move/crates/move-compiler/src/sui_mode/id_leak.rs @@ -6,7 +6,6 @@ use move_symbol_pool::Symbol; use crate::{ cfgir::{ - self, absint::JoinResult, visitor::{ LocalState, SimpleAbsInt, SimpleAbsIntConstructor, SimpleDomain, SimpleExecutionContext, @@ -16,10 +15,10 @@ use crate::{ diag, diagnostics::{Diagnostic, Diagnostics}, editions::Flavor, - expansion::ast::{AbilitySet, TargetKind}, + expansion::ast::{ModuleIdent, TargetKind}, hlir::ast::{Exp, Label, ModuleCall, SingleType, Type, Type_, Var}, - parser::ast::{Ability_, DatatypeName}, - shared::{unique_map::UniqueMap, CompilationEnv, Identifier}, + parser::ast::Ability_, + shared::{program_info::TypingProgramInfo, CompilationEnv, Identifier}, sui_mode::{OBJECT_NEW, TEST_SCENARIO_MODULE_NAME, TS_NEW_OBJECT}, }; use std::collections::BTreeMap; @@ -64,7 +63,8 @@ pub const FUNCTIONS_TO_SKIP: &[(Symbol, Symbol, Symbol)] = &[ pub struct IDLeakVerifier; pub struct IDLeakVerifierAI<'a> { - declared_abilities: &'a UniqueMap, + module: &'a ModuleIdent, + info: &'a TypingProgramInfo, } #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Default)] @@ -93,20 +93,19 @@ impl SimpleAbsIntConstructor for IDLeakVerifier { fn new<'a>( env: &CompilationEnv, - program: &'a cfgir::ast::Program, context: &'a CFGContext<'a>, _init_state: &mut as SimpleAbsInt>::State, ) -> Option> { let module = &context.module; - let mdef = program.modules.get(module).unwrap(); - let package_name = mdef.package_name; + let minfo = context.info.module(module); + let package_name = minfo.package; let config = env.package_config(package_name); if config.flavor != Flavor::Sui { // Skip if not sui return None; } if !matches!( - mdef.target_kind, + minfo.target_kind, TargetKind::Source { is_root_package: true } @@ -124,8 +123,10 @@ impl SimpleAbsIntConstructor for IDLeakVerifier { } } - let declared_abilities = context.datatype_declared_abilities.get(module).unwrap(); - Some(IDLeakVerifierAI { declared_abilities }) + Some(IDLeakVerifierAI { + module, + info: context.info, + }) } } @@ -160,7 +161,10 @@ impl<'a> SimpleAbsInt for IDLeakVerifierAI<'a> { let E::Pack(s, _tys, fields) = e__ else { return None; }; - let abilities = self.declared_abilities.get(s)?; + let abilities = { + let minfo = self.info.module(self.module); + &minfo.structs.get(s)?.abilities + }; if !abilities.has_ability_(Ability_::Key) { return None; } diff --git a/external-crates/move/crates/move-compiler/src/sui_mode/linters/coin_field.rs b/external-crates/move/crates/move-compiler/src/sui_mode/linters/coin_field.rs index fa76a265f077b..2390523cfab1c 100644 --- a/external-crates/move/crates/move-compiler/src/sui_mode/linters/coin_field.rs +++ b/external-crates/move/crates/move-compiler/src/sui_mode/linters/coin_field.rs @@ -8,7 +8,7 @@ use crate::{ diag, diagnostics::codes::{custom, DiagnosticInfo, Severity}, naming::ast as N, - shared::{program_info::TypingProgramInfo, CompilationEnv}, + shared::CompilationEnv, typing::{ast as T, visitor::TypingVisitor}, }; use move_ir_types::location::Loc; @@ -30,12 +30,7 @@ const COIN_FIELD_DIAG: DiagnosticInfo = custom( pub struct CoinFieldVisitor; impl TypingVisitor for CoinFieldVisitor { - fn visit( - &mut self, - env: &mut CompilationEnv, - _program_info: &TypingProgramInfo, - program: &mut T::Program_, - ) { + fn visit(&mut self, env: &mut CompilationEnv, program: &mut T::Program) { for (_, _, mdef) in program.modules.iter() { if mdef.attributes.is_test_or_test_only() { continue; diff --git a/external-crates/move/crates/move-compiler/src/sui_mode/linters/collection_equality.rs b/external-crates/move/crates/move-compiler/src/sui_mode/linters/collection_equality.rs index 8719d055c0da4..b4b4b80ec72c1 100644 --- a/external-crates/move/crates/move-compiler/src/sui_mode/linters/collection_equality.rs +++ b/external-crates/move/crates/move-compiler/src/sui_mode/linters/collection_equality.rs @@ -13,7 +13,7 @@ use crate::{ }, naming::ast as N, parser::ast as P, - shared::{program_info::TypingProgramInfo, CompilationEnv, Identifier}, + shared::{CompilationEnv, Identifier}, typing::{ ast as T, visitor::{TypingVisitorConstructor, TypingVisitorContext}, @@ -63,11 +63,7 @@ pub struct Context<'a> { impl TypingVisitorConstructor for CollectionEqualityVisitor { type Context<'a> = Context<'a>; - fn context<'a>( - env: &'a mut CompilationEnv, - _program_info: &'a TypingProgramInfo, - _program: &T::Program_, - ) -> Self::Context<'a> { + fn context<'a>(env: &'a mut CompilationEnv, _program: &T::Program) -> Self::Context<'a> { Context { env } } } diff --git a/external-crates/move/crates/move-compiler/src/sui_mode/linters/custom_state_change.rs b/external-crates/move/crates/move-compiler/src/sui_mode/linters/custom_state_change.rs index 770a0df8ea62c..436c64891e120 100644 --- a/external-crates/move/crates/move-compiler/src/sui_mode/linters/custom_state_change.rs +++ b/external-crates/move/crates/move-compiler/src/sui_mode/linters/custom_state_change.rs @@ -13,7 +13,6 @@ use move_ir_types::location::*; use crate::{ cfgir::{ absint::JoinResult, - ast::Program, visitor::{ LocalState, SimpleAbsInt, SimpleAbsIntConstructor, SimpleDomain, SimpleExecutionContext, }, @@ -87,7 +86,6 @@ impl SimpleAbsIntConstructor for CustomStateChangeVerifier { fn new<'a>( _env: &CompilationEnv, - _program: &'a Program, context: &'a CFGContext<'a>, _init_state: &mut State, ) -> Option> { diff --git a/external-crates/move/crates/move-compiler/src/sui_mode/linters/freeze_wrapped.rs b/external-crates/move/crates/move-compiler/src/sui_mode/linters/freeze_wrapped.rs index 146e88d77ad7a..b4cd109c0fa0a 100644 --- a/external-crates/move/crates/move-compiler/src/sui_mode/linters/freeze_wrapped.rs +++ b/external-crates/move/crates/move-compiler/src/sui_mode/linters/freeze_wrapped.rs @@ -5,7 +5,7 @@ //! with the key ability. In other words flags freezing of structs whose fields (directly or not) //! wrap objects. -use std::collections::BTreeMap; +use std::{collections::BTreeMap, sync::Arc}; use crate::{ diag, @@ -75,7 +75,7 @@ pub struct FreezeWrappedVisitor; pub struct Context<'a> { env: &'a mut CompilationEnv, - program_info: &'a TypingProgramInfo, + program_info: Arc, /// Memoizes information about struct fields wrapping other objects as they are discovered wrapping_fields: WrappingFields, } @@ -83,14 +83,10 @@ pub struct Context<'a> { impl TypingVisitorConstructor for FreezeWrappedVisitor { type Context<'a> = Context<'a>; - fn context<'a>( - env: &'a mut CompilationEnv, - program_info: &'a TypingProgramInfo, - _program: &T::Program_, - ) -> Self::Context<'a> { + fn context<'a>(env: &'a mut CompilationEnv, program: &T::Program) -> Self::Context<'a> { Context { env, - program_info, + program_info: program.info.clone(), wrapping_fields: WrappingFields::new(), } } @@ -226,7 +222,8 @@ impl<'a> Context<'a> { mident: E::ModuleIdent, sname: P::DatatypeName, ) -> Option { - let sdef = self.program_info.struct_definition(&mident, &sname); + let info = self.program_info.clone(); + let sdef = info.struct_definition(&mident, &sname); let N::StructFields::Defined(_, sfields) = &sdef.fields else { return None; }; diff --git a/external-crates/move/crates/move-compiler/src/sui_mode/linters/public_random.rs b/external-crates/move/crates/move-compiler/src/sui_mode/linters/public_random.rs index 8feb09726c5d4..7c2b924b9cf63 100644 --- a/external-crates/move/crates/move-compiler/src/sui_mode/linters/public_random.rs +++ b/external-crates/move/crates/move-compiler/src/sui_mode/linters/public_random.rs @@ -13,7 +13,7 @@ use crate::{ diagnostics::codes::{custom, DiagnosticInfo, Severity}, expansion::ast::Visibility, naming::ast as N, - shared::{program_info::TypingProgramInfo, CompilationEnv}, + shared::CompilationEnv, typing::ast as T, }; @@ -38,11 +38,7 @@ pub struct Context<'a> { impl TypingVisitorConstructor for PublicRandomVisitor { type Context<'a> = Context<'a>; - fn context<'a>( - env: &'a mut CompilationEnv, - _program_info: &'a TypingProgramInfo, - _program: &T::Program_, - ) -> Self::Context<'a> { + fn context<'a>(env: &'a mut CompilationEnv, _program: &T::Program) -> Self::Context<'a> { Context { env } } } diff --git a/external-crates/move/crates/move-compiler/src/sui_mode/linters/self_transfer.rs b/external-crates/move/crates/move-compiler/src/sui_mode/linters/self_transfer.rs index f4b67af3a477b..7e996ac3b64aa 100644 --- a/external-crates/move/crates/move-compiler/src/sui_mode/linters/self_transfer.rs +++ b/external-crates/move/crates/move-compiler/src/sui_mode/linters/self_transfer.rs @@ -9,7 +9,6 @@ use move_ir_types::location::*; use crate::{ cfgir::{ absint::JoinResult, - ast::Program, visitor::{ LocalState, SimpleAbsInt, SimpleAbsIntConstructor, SimpleDomain, SimpleExecutionContext, }, @@ -80,7 +79,6 @@ impl SimpleAbsIntConstructor for SelfTransferVerifier { fn new<'a>( _env: &CompilationEnv, - program: &'a Program, context: &'a CFGContext<'a>, _init_state: &mut as SimpleAbsInt>::State, ) -> Option> { @@ -90,10 +88,9 @@ impl SimpleAbsIntConstructor for SelfTransferVerifier { if context.entry.is_some() || context.attributes.is_test_or_test_only() - || program - .modules - .get(&context.module) - .unwrap() + || context + .info + .module(&context.module) .attributes .is_test_or_test_only() { diff --git a/external-crates/move/crates/move-compiler/src/sui_mode/linters/share_owned.rs b/external-crates/move/crates/move-compiler/src/sui_mode/linters/share_owned.rs index 7ecf822ec8b6e..df14dcd2e8d68 100644 --- a/external-crates/move/crates/move-compiler/src/sui_mode/linters/share_owned.rs +++ b/external-crates/move/crates/move-compiler/src/sui_mode/linters/share_owned.rs @@ -10,7 +10,6 @@ use move_ir_types::location::*; use crate::{ cfgir::{ absint::JoinResult, - ast::Program, visitor::{ LocalState, SimpleAbsInt, SimpleAbsIntConstructor, SimpleDomain, SimpleExecutionContext, }, @@ -82,15 +81,13 @@ impl SimpleAbsIntConstructor for ShareOwnedVerifier { fn new<'a>( _env: &CompilationEnv, - program: &'a Program, context: &'a CFGContext<'a>, _init_state: &mut as SimpleAbsInt>::State, ) -> Option> { if context.attributes.is_test_or_test_only() - || program - .modules - .get(&context.module) - .unwrap() + || context + .info + .module(&context.module) .attributes .is_test_or_test_only() { diff --git a/external-crates/move/crates/move-compiler/src/sui_mode/typing.rs b/external-crates/move/crates/move-compiler/src/sui_mode/typing.rs index 1c9b0a707bcaf..55f5ea4c6d0af 100644 --- a/external-crates/move/crates/move-compiler/src/sui_mode/typing.rs +++ b/external-crates/move/crates/move-compiler/src/sui_mode/typing.rs @@ -1,6 +1,8 @@ // Copyright (c) The Move Contributors // SPDX-License-Identifier: Apache-2.0 +use std::sync::Arc; + use move_ir_types::location::Loc; use move_symbol_pool::Symbol; @@ -30,12 +32,8 @@ pub struct SuiTypeChecks; impl TypingVisitorConstructor for SuiTypeChecks { type Context<'a> = Context<'a>; - fn context<'a>( - env: &'a mut CompilationEnv, - program_info: &'a TypingProgramInfo, - _program: &T::Program_, - ) -> Self::Context<'a> { - Context::new(env, program_info) + fn context<'a>(env: &'a mut CompilationEnv, program: &T::Program) -> Self::Context<'a> { + Context::new(env, program.info.clone()) } } @@ -46,7 +44,7 @@ impl TypingVisitorConstructor for SuiTypeChecks { #[allow(unused)] pub struct Context<'a> { env: &'a mut CompilationEnv, - info: &'a TypingProgramInfo, + info: Arc, sui_transfer_ident: Option, current_module: Option, otw_name: Option, @@ -55,7 +53,7 @@ pub struct Context<'a> { } impl<'a> Context<'a> { - fn new(env: &'a mut CompilationEnv, info: &'a TypingProgramInfo) -> Self { + fn new(env: &'a mut CompilationEnv, info: Arc) -> Self { let sui_module_ident = info .modules .key_cloned_iter() @@ -374,6 +372,7 @@ fn init_signature(context: &mut Context, name: FunctionName, signature: &Functio )) } + let info = context.info.clone(); let otw_name: Symbol = context.otw_name(); if parameters.len() == 1 && context.one_time_witness.is_some() @@ -420,8 +419,7 @@ fn init_signature(context: &mut Context, name: FunctionName, signature: &Functio ); diag.add_note(OTW_NOTE); context.env.add_diag(diag) - } else if let Some(sdef) = context - .info + } else if let Some(sdef) = info .module(context.current_module()) .structs .get_(&otw_name) diff --git a/external-crates/move/crates/move-compiler/src/to_bytecode/translate.rs b/external-crates/move/crates/move-compiler/src/to_bytecode/translate.rs index cdf26230c48b3..2be401fc98175 100644 --- a/external-crates/move/crates/move-compiler/src/to_bytecode/translate.rs +++ b/external-crates/move/crates/move-compiler/src/to_bytecode/translate.rs @@ -134,7 +134,10 @@ pub fn program( let mut units = vec![]; let (orderings, ddecls, fdecls) = extract_decls(compilation_env, pre_compiled_lib, &prog); - let G::Program { modules: gmodules } = prog; + let G::Program { + modules: gmodules, + info: _, + } = prog; let mut source_modules = gmodules .into_iter() diff --git a/external-crates/move/crates/move-compiler/src/typing/ast.rs b/external-crates/move/crates/move-compiler/src/typing/ast.rs index 52868de0e5b69..a2a6010c91570 100644 --- a/external-crates/move/crates/move-compiler/src/typing/ast.rs +++ b/external-crates/move/crates/move-compiler/src/typing/ast.rs @@ -36,11 +36,6 @@ use std::{ #[derive(Debug, Clone)] pub struct Program { pub info: Arc, - pub inner: Program_, -} - -#[derive(Debug, Clone)] -pub struct Program_ { pub modules: UniqueMap, } @@ -428,13 +423,7 @@ impl fmt::Display for BuiltinFunction_ { impl AstDebug for Program { fn ast_debug(&self, w: &mut AstWriter) { - self.inner.ast_debug(w) - } -} - -impl AstDebug for Program_ { - fn ast_debug(&self, w: &mut AstWriter) { - let Program_ { modules } = self; + let Program { modules, info: _ } = self; for (m, mdef) in modules.key_cloned_iter() { w.write(&format!("module {}", m)); diff --git a/external-crates/move/crates/move-compiler/src/typing/translate.rs b/external-crates/move/crates/move-compiler/src/typing/translate.rs index 41edb39254737..72acf573b154f 100644 --- a/external-crates/move/crates/move-compiler/src/typing/translate.rs +++ b/external-crates/move/crates/move-compiler/src/typing/translate.rs @@ -72,7 +72,6 @@ pub fn program( dependency_ordering::program(context.env, &mut modules); recursive_datatypes::modules(context.env, &modules); infinite_instantiations::modules(context.env, &modules); - let mut prog = T::Program_ { modules }; // we extract module use funs into the module info context let module_use_funs = context .modules @@ -80,15 +79,16 @@ pub fn program( .into_iter() .map(|(mident, minfo)| (mident, minfo.use_funs)) .collect(); - let module_info = TypingProgramInfo::new(pre_compiled_lib, &prog, module_use_funs); + let module_info = TypingProgramInfo::new(pre_compiled_lib, &modules, module_use_funs); + let mut prog = T::Program { + modules, + info: Arc::new(module_info), + }; for v in &compilation_env.visitors().typing { let mut v = v.borrow_mut(); - v.visit(compilation_env, &module_info, &mut prog); - } - T::Program { - info: Arc::new(module_info), - inner: prog, + v.visit(compilation_env, &mut prog); } + prog } fn extract_macros(context: &mut Context, modules: &UniqueMap) { diff --git a/external-crates/move/crates/move-compiler/src/typing/visitor.rs b/external-crates/move/crates/move-compiler/src/typing/visitor.rs index 9564db3902ad7..e7ed4f28b2274 100644 --- a/external-crates/move/crates/move-compiler/src/typing/visitor.rs +++ b/external-crates/move/crates/move-compiler/src/typing/visitor.rs @@ -4,8 +4,9 @@ use crate::command_line::compiler::Visitor; use crate::diagnostics::WarningFilters; use crate::expansion::ast::ModuleIdent; -use crate::parser::ast::{ConstantName, FunctionName}; -use crate::shared::{program_info::TypingProgramInfo, CompilationEnv}; +use crate::naming::ast as N; +use crate::parser::ast::{ConstantName, DatatypeName, FunctionName}; +use crate::shared::CompilationEnv; use crate::typing::ast as T; use move_proc_macros::growing_stack; @@ -13,12 +14,7 @@ use move_proc_macros::growing_stack; pub type TypingVisitorObj = Box; pub trait TypingVisitor { - fn visit( - &mut self, - env: &mut CompilationEnv, - program_info: &TypingProgramInfo, - program: &mut T::Program_, - ); + fn visit(&mut self, env: &mut CompilationEnv, program: &mut T::Program); fn visitor(self) -> Visitor where @@ -31,19 +27,10 @@ pub trait TypingVisitor { pub trait TypingVisitorConstructor { type Context<'a>: Sized + TypingVisitorContext; - fn context<'a>( - env: &'a mut CompilationEnv, - program_info: &'a TypingProgramInfo, - program: &T::Program_, - ) -> Self::Context<'a>; + fn context<'a>(env: &'a mut CompilationEnv, program: &T::Program) -> Self::Context<'a>; - fn visit( - &mut self, - env: &mut CompilationEnv, - program_info: &TypingProgramInfo, - program: &mut T::Program_, - ) { - let mut context = Self::context(env, program_info, program); + fn visit(&mut self, env: &mut CompilationEnv, program: &mut T::Program) { + let mut context = Self::context(env, program); context.visit(program); } } @@ -63,7 +50,7 @@ pub trait TypingVisitorContext { /// By default, the visitor will visit all all expressions in all functions in all modules. A /// custom version should of this function should be created if different type of analysis is /// required. - fn visit(&mut self, program: &mut T::Program_) { + fn visit(&mut self, program: &mut T::Program) { for (mident, mdef) in program.modules.key_cloned_iter_mut() { self.add_warning_filter_scope(mdef.warning_filter.clone()); if self.visit_module_custom(mident, mdef) { @@ -71,6 +58,12 @@ pub trait TypingVisitorContext { continue; } + for (struct_name, sdef) in mdef.structs.key_cloned_iter_mut() { + self.visit_struct(mident, struct_name, sdef) + } + for (enum_name, edef) in mdef.enums.key_cloned_iter_mut() { + self.visit_enum(mident, enum_name, edef) + } for (constant_name, cdef) in mdef.constants.key_cloned_iter_mut() { self.visit_constant(mident, constant_name, cdef) } @@ -82,7 +75,51 @@ pub trait TypingVisitorContext { } } - // TODO struct and type visiting + // TODO type visiting + + fn visit_struct_custom( + &mut self, + _module: ModuleIdent, + _struct_name: DatatypeName, + _sdef: &mut N::StructDefinition, + ) -> bool { + false + } + fn visit_struct( + &mut self, + module: ModuleIdent, + struct_name: DatatypeName, + sdef: &mut N::StructDefinition, + ) { + self.add_warning_filter_scope(sdef.warning_filter.clone()); + if self.visit_struct_custom(module, struct_name, sdef) { + self.pop_warning_filter_scope(); + return; + } + self.pop_warning_filter_scope(); + } + + fn visit_enum_custom( + &mut self, + _module: ModuleIdent, + _enum_name: DatatypeName, + _edef: &mut N::EnumDefinition, + ) -> bool { + false + } + fn visit_enum( + &mut self, + module: ModuleIdent, + enum_name: DatatypeName, + edef: &mut N::EnumDefinition, + ) { + self.add_warning_filter_scope(edef.warning_filter.clone()); + if self.visit_enum_custom(module, enum_name, edef) { + self.pop_warning_filter_scope(); + return; + } + self.pop_warning_filter_scope(); + } fn visit_constant_custom( &mut self, @@ -249,12 +286,7 @@ impl From for TypingVisitorObj { } impl TypingVisitor for V { - fn visit( - &mut self, - env: &mut CompilationEnv, - program_info: &TypingProgramInfo, - program: &mut T::Program_, - ) { - self.visit(env, program_info, program) + fn visit(&mut self, env: &mut CompilationEnv, program: &mut T::Program) { + self.visit(env, program) } } diff --git a/external-crates/move/crates/move-model/src/lib.rs b/external-crates/move/crates/move-model/src/lib.rs index f1d6e7d135dba..947dba095d917 100644 --- a/external-crates/move/crates/move-model/src/lib.rs +++ b/external-crates/move/crates/move-model/src/lib.rs @@ -219,14 +219,10 @@ pub fn run_model_builder_with_options_and_compilation_flags< // Extract the module/script closure let mut visited_modules = BTreeSet::new(); - for (_, mident, mdef) in &typing_ast.inner.modules { + for (_, mident, mdef) in &typing_ast.modules { let src_file_hash = mdef.loc.file_hash(); if !dep_files.contains(&src_file_hash) { - collect_related_modules_recursive( - mident, - &typing_ast.inner.modules, - &mut visited_modules, - ); + collect_related_modules_recursive(mident, &typing_ast.modules, &mut visited_modules); } } @@ -244,8 +240,7 @@ pub fn run_model_builder_with_options_and_compilation_flags< E::Program { modules } }; let typing_ast = { - let T::Program { info, inner } = typing_ast; - let T::Program_ { modules } = inner; + let T::Program { info, modules } = typing_ast; let modules = modules.filter_map(|mident, mut mdef| { visited_modules.contains(&mident.value).then(|| { mdef.target_kind = TargetKind::Source { @@ -254,8 +249,7 @@ pub fn run_model_builder_with_options_and_compilation_flags< mdef }) }); - let inner = T::Program_ { modules }; - T::Program { info, inner } + T::Program { info, modules } }; // Run the compiler fully to the compiled units From a1ce332f6f1f4a0fdadbd208d7cfcf4bc1b3371b Mon Sep 17 00:00:00 2001 From: Cam Swords Date: Tue, 28 May 2024 17:40:50 -0700 Subject: [PATCH 017/324] [move][move-ide] Revise how IDE information is recorded in the compiler (#17864) ## Description This PR moves how we record IDE information to communicate it to the Move Analyzer. It is now accrued on the `CompilationEnv` (modulo some care in typing to handle type elaboration) and can be added through methods there. The goal is to set up an extensible way to track IDE information in the future, tying it to location information. This change has also caused us to change how we compute spans for dotted expression terms: previously, we would make the expression with the call's span in order to report failures to autoborrow to point at the call site (instead of just the subject term). This caused recurring through location information in the analyzer to enter an infinite loop in the macro case, as the subject term shared the location of the overall macro call and recursion into the subject term on the macro information looped forever. This diff introduces a solution to this issue by more-carefully computing spans for subject terms so that they remain pointing at the actual subject term, and plumbs the call location through dotted expression handling to retain good error reporting for the method case. It also introduces a very small change to handle location reporting for `*`/`&`/`&mut ` usage for type errors. ## Test plan All tests still pass. --- ## Release notes Check each box that your changes affect. If none of the boxes relate to your changes, release notes aren't required. For each box you select, include information after the relevant heading that describes the impact of your changes that a user might notice and any actions they must take to implement updates. - [ ] Protocol: - [ ] Nodes (Validators and Full nodes): - [ ] Indexer: - [ ] JSON-RPC: - [ ] GraphQL: - [ ] CLI: - [ ] Rust SDK: --- .../crates/move-analyzer/src/compiler_info.rs | 62 ++++ .../move/crates/move-analyzer/src/lib.rs | 1 + .../move/crates/move-analyzer/src/symbols.rs | 91 ++--- .../src/hlir/detect_dead_code.rs | 7 +- .../move-compiler/src/hlir/translate.rs | 33 +- .../crates/move-compiler/src/naming/ast.rs | 12 - .../src/naming/resolve_use_funs.rs | 1 - .../move-compiler/src/naming/translate.rs | 1 - .../crates/move-compiler/src/shared/ide.rs | 93 +++++ .../crates/move-compiler/src/shared/mod.rs | 22 +- .../crates/move-compiler/src/typing/ast.rs | 60 ---- .../crates/move-compiler/src/typing/core.rs | 28 +- .../src/typing/dependency_ordering.rs | 6 - .../crates/move-compiler/src/typing/expand.rs | 43 ++- .../src/typing/infinite_instantiations.rs | 8 +- .../move-compiler/src/typing/macro_expand.rs | 17 +- .../move-compiler/src/typing/translate.rs | 328 ++++++++---------- .../move-compiler/src/typing/visitor.rs | 6 - .../move_2024/ide_mode/dot_incomplete.exp | 18 - .../move_2024/ide_mode/index_autocomplete.exp | 18 - .../ide_mode/named_struct_autocomplete.exp | 12 - .../positional_struct_autocomplete.exp | 12 - .../ide_mode/struct_method_autocomplete.exp | 12 - .../ide_mode/struct_scoped_autocomplete.exp | 12 - .../typing/let_mut_borrow_mut_dot_call.exp | 6 +- .../move_check/ide_mode/dot_incomplete.exp | 32 -- .../ide_mode/struct_method_autocomplete.exp | 12 - .../typing/constant_unsupported_exps.exp | 6 + .../move/crates/move-ir-types/src/location.rs | 10 + 29 files changed, 450 insertions(+), 519 deletions(-) create mode 100644 external-crates/move/crates/move-analyzer/src/compiler_info.rs create mode 100644 external-crates/move/crates/move-compiler/src/shared/ide.rs diff --git a/external-crates/move/crates/move-analyzer/src/compiler_info.rs b/external-crates/move/crates/move-analyzer/src/compiler_info.rs new file mode 100644 index 0000000000000..5972c8ddd9f01 --- /dev/null +++ b/external-crates/move/crates/move-analyzer/src/compiler_info.rs @@ -0,0 +1,62 @@ +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use std::collections::{BTreeMap, BTreeSet}; + +use move_compiler::shared::ide as CI; +use move_ir_types::location::Loc; + +#[derive(Default, Debug, Clone)] +pub struct CompilerInfo { + pub macro_info: BTreeMap, + pub expanded_lambdas: BTreeSet, + pub autocomplete_info: BTreeMap, +} + +impl CompilerInfo { + pub fn new() -> CompilerInfo { + CompilerInfo::default() + } + + pub fn from(info: impl IntoIterator) -> Self { + let mut result = Self::new(); + result.add_info(info); + result + } + + pub fn add_info(&mut self, info: impl IntoIterator) { + for (loc, entry) in info { + match entry { + CI::IDEAnnotation::MacroCallInfo(info) => { + // TODO: should we check this is not also an expanded lambda? + // TODO: what if we find two macro calls? + if let Some(_old) = self.macro_info.insert(loc, *info) { + eprintln!("Repeated macro info"); + } + } + CI::IDEAnnotation::ExpandedLambda => { + self.expanded_lambdas.insert(loc); + } + CI::IDEAnnotation::AutocompleteInfo(info) => { + // TODO: what if we find two autocomplete info sets? Intersection may be better + // than union, as it's likely in a lambda body. + if let Some(_old) = self.autocomplete_info.insert(loc, *info) { + eprintln!("Repeated autocomplete info"); + } + } + } + } + } + + pub fn get_macro_info(&mut self, loc: &Loc) -> Option<&CI::MacroCallInfo> { + self.macro_info.get(loc) + } + + pub fn is_expanded_lambda(&mut self, loc: &Loc) -> bool { + self.expanded_lambdas.contains(loc) + } + + pub fn get_autocomplete_info(&mut self, loc: &Loc) -> Option<&CI::AutocompleteInfo> { + self.autocomplete_info.get(loc) + } +} diff --git a/external-crates/move/crates/move-analyzer/src/lib.rs b/external-crates/move/crates/move-analyzer/src/lib.rs index 15082886df6a0..10dfe88703dd1 100644 --- a/external-crates/move/crates/move-analyzer/src/lib.rs +++ b/external-crates/move/crates/move-analyzer/src/lib.rs @@ -6,6 +6,7 @@ extern crate move_ir_types; pub mod analyzer; +pub mod compiler_info; pub mod completion; pub mod context; pub mod diagnostics; diff --git a/external-crates/move/crates/move-analyzer/src/symbols.rs b/external-crates/move/crates/move-analyzer/src/symbols.rs index c76b2d5416129..e22a83895f2f2 100644 --- a/external-crates/move/crates/move-analyzer/src/symbols.rs +++ b/external-crates/move/crates/move-analyzer/src/symbols.rs @@ -55,6 +55,7 @@ #![allow(clippy::non_canonical_partial_ord_impl)] use crate::{ + compiler_info::CompilerInfo, context::Context, diagnostics::{lsp_diagnostics, lsp_empty_diagnostics}, utils::get_loc, @@ -98,10 +99,13 @@ use move_compiler::{ linters::LintLevel, naming::ast::{StructDefinition, StructFields, TParam, Type, TypeName_, Type_, UseFuns}, parser::ast::{self as P, DatatypeName, FunctionName}, - shared::{unique_map::UniqueMap, Identifier, Name, NamedAddressMap, NamedAddressMaps}, + shared::{ + ide::MacroCallInfo, unique_map::UniqueMap, Identifier, Name, NamedAddressMap, + NamedAddressMaps, + }, typing::ast::{ - BuiltinFunction_, Exp, ExpListItem, Function, FunctionBody_, IDEInfo, LValue, LValueList, - LValue_, MacroCallInfo, ModuleDefinition, SequenceItem, SequenceItem_, UnannotatedExp_, + BuiltinFunction_, Exp, ExpListItem, Function, FunctionBody_, LValue, LValueList, LValue_, + ModuleDefinition, SequenceItem, SequenceItem_, UnannotatedExp_, }, unit_test::filter_test_members::UNIT_TEST_POISON_FUN_NAME, PASS_CFGIR, PASS_PARSER, PASS_TYPING, @@ -390,6 +394,8 @@ pub struct TypingSymbolicator<'a> { /// In some cases (e.g., when processing bodies of macros) we want to keep traversing /// the AST but without recording the actual metadata (uses, definitions, types, etc.) traverse_only: bool, + /// IDE Annotation Information from the Compiler + compiler_info: CompilerInfo, } /// Maps a line number to a list of use-def-s on a given line (use-def set is sorted by col_start) @@ -717,7 +723,6 @@ fn ast_exp_to_ide_string(exp: &Exp) -> Option { .join(", "), ) } - UE::IDEAnnotation(_, exp) => ast_exp_to_ide_string(exp), UE::ExpList(list) => { let items = list .iter() @@ -1194,6 +1199,7 @@ pub fn get_symbols( BuildPlan::create(resolution_graph)?.set_compiler_vfs_root(overlay_fs_root.clone()); let mut parsed_ast = None; let mut typed_ast = None; + let mut compiler_info = None; let mut diagnostics = None; let mut dependencies = build_plan.compute_dependencies(); @@ -1285,13 +1291,16 @@ pub fn get_symbols( let failure = true; diagnostics = Some((diags, failure)); eprintln!("typed AST compilation failed"); + eprintln!("diagnostics: {:#?}", diagnostics); return Ok((files, vec![])); } }; eprintln!("compiled to typed AST"); let (mut compiler, typed_program) = compiler.into_ast(); typed_ast = Some(typed_program.clone()); - + compiler_info = Some(CompilerInfo::from( + compiler.compilation_env().ide_information.clone(), + )); edition = Some(compiler.compilation_env().edition(Some(root_pkg_name))); // compile to CFGIR for accurate diags @@ -1399,7 +1408,6 @@ pub fn get_symbols( &mut mod_to_alias_lengths, ); } - let mut typing_symbolicator = TypingSymbolicator { mod_outer_defs: &mod_outer_defs, files: &files, @@ -1410,6 +1418,7 @@ pub fn get_symbols( use_defs: UseDefMap::new(), alias_lengths: &BTreeMap::new(), traverse_only: false, + compiler_info: compiler_info.unwrap(), }; process_typed_modules( @@ -2764,6 +2773,38 @@ impl<'a> TypingSymbolicator<'a> { /// Get symbols for an expression fn exp_symbols(&mut self, exp: &Exp, scope: &mut OrdMap) { + let expanded_lambda = self.compiler_info.is_expanded_lambda(&exp.exp.loc); + if let Some(macro_call_info) = self.compiler_info.get_macro_info(&exp.exp.loc) { + debug_assert!(!expanded_lambda, "Compiler info issue"); + let MacroCallInfo { + module, + name, + method_name, + type_arguments, + by_value_args, + } = macro_call_info.clone(); + self.mod_call_symbols(&module, name, method_name, &type_arguments, None, scope); + by_value_args + .iter() + .for_each(|a| self.seq_item_symbols(scope, a)); + let old_traverse_mode = self.traverse_only; + // stop adding new use-defs etc. + self.traverse_only = true; + self.exp_symbols_inner(exp, scope); + self.traverse_only = old_traverse_mode; + } else if expanded_lambda { + let old_traverse_mode = self.traverse_only; + // start adding new use-defs etc. when processing a lambda argument + self.traverse_only = false; + self.exp_symbols_inner(exp, scope); + self.traverse_only = old_traverse_mode; + } else { + self.exp_symbols_inner(exp, scope); + } + } + + /// Get symbols for an expression + fn exp_symbols_inner(&mut self, exp: &Exp, scope: &mut OrdMap) { use UnannotatedExp_ as E; match &exp.exp.value { E::Move { from_user: _, var } => { @@ -2840,41 +2881,6 @@ impl<'a> TypingSymbolicator<'a> { self.traverse_only = old_traverse_mode; } } - E::IDEAnnotation(info, exp) => { - match info { - IDEInfo::MacroCallInfo(MacroCallInfo { - module, - name, - method_name, - type_arguments, - by_value_args, - }) => { - self.mod_call_symbols( - module, - *name, - *method_name, - type_arguments, - None, - scope, - ); - by_value_args - .iter() - .for_each(|a| self.seq_item_symbols(scope, a)); - let old_traverse_mode = self.traverse_only; - // stop adding new use-defs etc. - self.traverse_only = true; - self.exp_symbols(exp, scope); - self.traverse_only = old_traverse_mode; - } - IDEInfo::ExpandedLambda => { - let old_traverse_mode = self.traverse_only; - // start adding new use-defs etc. when processing a lambda argument - self.traverse_only = false; - self.exp_symbols(exp, scope); - self.traverse_only = old_traverse_mode; - } - } - } E::Assign(lvalues, opt_types, e) => { self.lvalue_list_symbols(false, lvalues, scope); for opt_t in opt_types { @@ -2932,9 +2938,6 @@ impl<'a> TypingSymbolicator<'a> { self.exp_symbols(exp, scope); self.add_type_id_use_def(t); } - E::AutocompleteDotAccess { base_exp, .. } => { - self.exp_symbols(base_exp, scope); - } E::Unit { .. } | E::Value(_) | E::Continue(_) diff --git a/external-crates/move/crates/move-compiler/src/hlir/detect_dead_code.rs b/external-crates/move/crates/move-compiler/src/hlir/detect_dead_code.rs index 45a2529ed7e0a..b2a74124ccc41 100644 --- a/external-crates/move/crates/move-compiler/src/hlir/detect_dead_code.rs +++ b/external-crates/move/crates/move-compiler/src/hlir/detect_dead_code.rs @@ -360,7 +360,6 @@ fn tail(context: &mut Context, e: &T::Exp) -> Option { } } E::Block((_, seq)) => tail_block(context, seq), - E::IDEAnnotation(_, e) => tail(context, e), // ----------------------------------------------------------------------------------------- // statements @@ -480,7 +479,6 @@ fn value(context: &mut Context, e: &T::Exp) -> Option { } } E::Block((_, seq)) => value_block(context, seq), - E::IDEAnnotation(_, e) => value(context, e), // ----------------------------------------------------------------------------------------- // calls and nested expressions @@ -528,8 +526,7 @@ fn value(context: &mut Context, e: &T::Exp) -> Option { | E::UnaryExp(_, base_exp) | E::Borrow(_, base_exp, _) | E::Cast(base_exp, _) - | E::TempBorrow(_, base_exp) - | E::AutocompleteDotAccess { base_exp, .. } => value_report!(base_exp), + | E::TempBorrow(_, base_exp) => value_report!(base_exp), E::BorrowLocal(_, _) => None, @@ -683,7 +680,6 @@ fn statement(context: &mut Context, e: &T::Exp) -> Option { E::Block((_, seq)) => statement_block( context, seq, /* stmt_pos */ true, /* skip_last */ false, ), - E::IDEAnnotation(_, e) => statement(context, e), E::Return(rhs) => { if let Some(rhs_control_flow) = value(context, rhs) { context.report_value_error(rhs_control_flow); @@ -742,7 +738,6 @@ fn statement(context: &mut Context, e: &T::Exp) -> Option { | E::ErrorConstant { .. } | E::Move { .. } | E::Copy { .. } - | E::AutocompleteDotAccess { .. } | E::UnresolvedError => value(context, e), E::Value(_) | E::Unit { .. } => None, diff --git a/external-crates/move/crates/move-compiler/src/hlir/translate.rs b/external-crates/move/crates/move-compiler/src/hlir/translate.rs index 0960f13cf32bf..25e5a3a864927 100644 --- a/external-crates/move/crates/move-compiler/src/hlir/translate.rs +++ b/external-crates/move/crates/move-compiler/src/hlir/translate.rs @@ -15,12 +15,7 @@ use crate::{ parser::ast::{ Ability_, BinOp, BinOp_, ConstantName, DatatypeName, Field, FunctionName, VariantName, }, - shared::{ - process_binops, - string_utils::{debug_print, format_oxford_list}, - unique_map::UniqueMap, - *, - }, + shared::{process_binops, string_utils::debug_print, unique_map::UniqueMap, *}, sui_mode::ID_FIELD_NAME, typing::ast as T, FullyCompiledProgram, @@ -1044,7 +1039,6 @@ fn tail( }) } E::Block((_, seq)) => tail_block(context, block, expected_type, seq), - E::IDEAnnotation(_, e) => tail(context, block, expected_type, *e), // ----------------------------------------------------------------------------------------- // statements that need to be hoisted out @@ -1353,7 +1347,6 @@ fn value( bound_exp } E::Block((_, seq)) => value_block(context, block, Some(&out_type), eloc, seq), - E::IDEAnnotation(_, e) => value(context, block, expected_type, *e), // ----------------------------------------------------------------------------------------- // calls @@ -1692,28 +1685,6 @@ fn value( assert!(context.env.has_errors()); make_exp(HE::UnresolvedError) } - E::AutocompleteDotAccess { - base_exp: _, - methods, - fields, - } => { - if !(context.env.ide_mode()) { - context - .env - .add_diag(ice!((eloc, "Found autocomplete outside of IDE mode"))); - }; - let names = methods - .into_iter() - .map(|(m, f)| format!("{m}::{f}")) - .chain(fields.into_iter().map(|n| format!("{n}"))) - .collect::>(); - let msg = format!( - "Autocompletes to: {}", - format_oxford_list!("or", "'{}'", names) - ); - context.env.add_diag(diag!(IDE::Autocomplete, (eloc, msg))); - make_exp(HE::UnresolvedError) - } }; maybe_freeze(context, block, expected_type.cloned(), preresult) } @@ -1977,7 +1948,6 @@ fn statement(context: &mut Context, block: &mut Block, e: T::Exp) { } } E::Block((_, seq)) => statement_block(context, block, seq), - E::IDEAnnotation(_, e) => statement(context, block, *e), E::Return(rhs) => { let expected_type = context.signature.as_ref().map(|s| s.return_type.clone()); let exp = value(context, block, expected_type.as_ref(), *rhs); @@ -2055,7 +2025,6 @@ fn statement(context: &mut Context, block: &mut Block, e: T::Exp) { | E::Move { .. } | E::Copy { .. } | E::UnresolvedError - | E::AutocompleteDotAccess { .. } | E::NamedBlock(_, _)) => value_statement(context, block, make_exp(e_)), E::Value(_) | E::Unit { .. } => (), diff --git a/external-crates/move/crates/move-compiler/src/naming/ast.rs b/external-crates/move/crates/move-compiler/src/naming/ast.rs index 62a93bba0684e..0c7aae235a23a 100644 --- a/external-crates/move/crates/move-compiler/src/naming/ast.rs +++ b/external-crates/move/crates/move-compiler/src/naming/ast.rs @@ -397,11 +397,6 @@ pub enum MacroArgument { Substituted(Loc), } -#[derive(Debug, PartialEq, Clone)] -pub enum IDEInfo { - ExpandedLambda, -} - #[derive(Debug, PartialEq, Clone)] #[allow(clippy::large_enum_variant)] pub enum Exp_ { @@ -432,7 +427,6 @@ pub enum Exp_ { While(BlockLabel, Box, Box), Loop(BlockLabel, Box), Block(Block), - IDEAnnotation(IDEInfo, Box), Lambda(Lambda), Assign(LValueList, Box), @@ -1737,12 +1731,6 @@ impl AstDebug for Exp_ { e.ast_debug(w); } E::Block(seq) => seq.ast_debug(w), - E::IDEAnnotation(info, e) => match info { - IDEInfo::ExpandedLambda => { - w.write("ExpandedLambda:"); - e.ast_debug(w); - } - }, E::Lambda(l) => l.ast_debug(w), E::ExpList(es) => { w.write("("); diff --git a/external-crates/move/crates/move-compiler/src/naming/resolve_use_funs.rs b/external-crates/move/crates/move-compiler/src/naming/resolve_use_funs.rs index 12c86be4abb0d..2248154e6fcdf 100644 --- a/external-crates/move/crates/move-compiler/src/naming/resolve_use_funs.rs +++ b/external-crates/move/crates/move-compiler/src/naming/resolve_use_funs.rs @@ -358,7 +358,6 @@ fn exp(context: &mut Context, sp!(_, e_): &mut N::Exp) { from_macro_argument: _, seq, }) => sequence(context, seq), - N::Exp_::IDEAnnotation(_, e) => exp(context, e), N::Exp_::FieldMutate(ed, e) => { exp_dotted(context, ed); exp(context, e) diff --git a/external-crates/move/crates/move-compiler/src/naming/translate.rs b/external-crates/move/crates/move-compiler/src/naming/translate.rs index d9dda7a6af655..1ce2fc283609c 100644 --- a/external-crates/move/crates/move-compiler/src/naming/translate.rs +++ b/external-crates/move/crates/move-compiler/src/naming/translate.rs @@ -3785,7 +3785,6 @@ fn remove_unused_bindings_exp( from_macro_argument: _, seq, }) => remove_unused_bindings_seq(context, used, seq), - N::Exp_::IDEAnnotation(_, e) => remove_unused_bindings_exp(context, used, e), N::Exp_::Lambda(N::Lambda { parameters: sp!(_, parameters), return_label: _, diff --git a/external-crates/move/crates/move-compiler/src/shared/ide.rs b/external-crates/move/crates/move-compiler/src/shared/ide.rs new file mode 100644 index 0000000000000..123801bbbc7a6 --- /dev/null +++ b/external-crates/move/crates/move-compiler/src/shared/ide.rs @@ -0,0 +1,93 @@ +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use std::collections::BTreeSet; + +use crate::{ + expansion::ast as E, naming::ast as N, parser::ast as P, shared::Name, typing::ast as T, +}; + +use move_ir_types::location::Loc; +use move_symbol_pool::Symbol; + +//************************************************************************************************* +// Types +//************************************************************************************************* + +#[derive(Debug, Clone, Default)] +pub struct IDEInfo { + annotations: Vec<(Loc, IDEAnnotation)>, +} + +#[derive(Debug, Clone)] +/// An individual IDE annotation. +pub enum IDEAnnotation { + /// A macro call site. + MacroCallInfo(Box), + /// An expanded lambda site. + ExpandedLambda, + /// Autocomplete information. + AutocompleteInfo(Box), +} + +#[derive(Debug, Clone)] +pub struct MacroCallInfo { + /// Module where the macro is defined + pub module: E::ModuleIdent, + /// Name of the macro function + pub name: P::FunctionName, + /// Optional method name if macro invoked as dot-call + pub method_name: Option, + /// Type params at macro's call site + pub type_arguments: Vec, + /// By-value args (at this point there should only be one, representing receiver arg) + pub by_value_args: Vec, +} + +#[derive(Debug, Clone)] +pub struct AutocompleteInfo { + /// Methods that are valid autocompletes + pub methods: BTreeSet<(E::ModuleIdent, P::FunctionName)>, + /// Fields that are valid autocompletes (e.g., for a struct) + /// TODO: possibly extend this with type information? + pub fields: BTreeSet, +} + +//************************************************************************************************* +// Impls +//************************************************************************************************* + +impl IDEInfo { + pub fn new() -> Self { + Self::default() + } + + pub fn add_ide_annotation(&mut self, loc: Loc, info: IDEAnnotation) { + self.annotations.push((loc, info)); + } + + pub fn extend(&mut self, mut other: Self) { + self.annotations.append(&mut other.annotations); + } + + pub fn is_empty(&self) -> bool { + self.annotations.is_empty() + } + + pub fn iter(&self) -> std::slice::Iter<'_, (Loc, IDEAnnotation)> { + self.annotations.iter() + } + + pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, (Loc, IDEAnnotation)> { + self.annotations.iter_mut() + } +} + +impl IntoIterator for IDEInfo { + type Item = (Loc, IDEAnnotation); + type IntoIter = std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.annotations.into_iter() + } +} diff --git a/external-crates/move/crates/move-compiler/src/shared/mod.rs b/external-crates/move/crates/move-compiler/src/shared/mod.rs index 02c183e75fa84..994d7da4ae705 100644 --- a/external-crates/move/crates/move-compiler/src/shared/mod.rs +++ b/external-crates/move/crates/move-compiler/src/shared/mod.rs @@ -20,6 +20,7 @@ use crate::{ hlir::ast as H, naming::ast as N, parser::ast as P, + shared::ide::{IDEAnnotation, IDEInfo}, sui_mode, typing::{ ast as T, @@ -45,6 +46,7 @@ use std::{ use vfs::{VfsError, VfsPath}; pub mod ast_debug; +pub mod ide; pub mod known_attributes; pub mod program_info; pub mod remembering_unique_map; @@ -245,6 +247,7 @@ pub struct CompilationEnv { // pub counter: u64, mapped_files: MappedFiles, save_hooks: Vec, + pub ide_information: IDEInfo, } macro_rules! known_code_filter { @@ -367,6 +370,7 @@ impl CompilationEnv { prim_definers: BTreeMap::new(), mapped_files: MappedFiles::empty(), save_hooks, + ide_information: IDEInfo::new(), } } @@ -608,10 +612,6 @@ impl CompilationEnv { self.prim_definers.get(&t) } - pub fn ide_mode(&self) -> bool { - self.flags.ide_mode() - } - pub fn save_parser_ast(&self, ast: &P::Program) { for hook in &self.save_hooks { hook.save_parser_ast(ast) @@ -653,6 +653,20 @@ impl CompilationEnv { hook.save_cfgir_ast(ast) } } + + // -- IDE Information -- + + pub fn ide_mode(&self) -> bool { + self.flags.ide_mode() + } + + pub fn extend_ide_info(&mut self, info: IDEInfo) { + self.ide_information.extend(info); + } + + pub fn add_ide_annotation(&mut self, loc: Loc, info: IDEAnnotation) { + self.ide_information.add_ide_annotation(loc, info); + } } pub fn format_allow_attr(attr_name: FilterPrefix, filter: FilterName) -> String { diff --git a/external-crates/move/crates/move-compiler/src/typing/ast.rs b/external-crates/move/crates/move-compiler/src/typing/ast.rs index a2a6010c91570..6849e52110792 100644 --- a/external-crates/move/crates/move-compiler/src/typing/ast.rs +++ b/external-crates/move/crates/move-compiler/src/typing/ast.rs @@ -169,26 +169,6 @@ pub enum BuiltinFunction_ { } pub type BuiltinFunction = Spanned; -#[derive(Debug, PartialEq, Clone)] -pub enum IDEInfo { - MacroCallInfo(MacroCallInfo), - ExpandedLambda, -} - -#[derive(Debug, PartialEq, Clone)] -pub struct MacroCallInfo { - /// Module where the macro is defined - pub module: ModuleIdent, - /// Name of the macro function - pub name: FunctionName, - /// Optional method name if macro invoked as dot-call - pub method_name: Option, - /// Type params at macro's call site - pub type_arguments: Vec, - /// By-value args (at this point there should only be one, representing receiver arg) - pub by_value_args: Vec, -} - #[derive(Debug, PartialEq, Clone)] pub enum UnannotatedExp_ { Unit { @@ -225,7 +205,6 @@ pub enum UnannotatedExp_ { }, NamedBlock(BlockLabel, Sequence), Block(Sequence), - IDEAnnotation(IDEInfo, Box), Assign(LValueList, Vec>, Box), Mutate(Box, Box), Return(Box), @@ -253,14 +232,6 @@ pub enum UnannotatedExp_ { Cast(Box, Box), Annotate(Box, Box), - - // unfinished dot access (e.g. `some_field.`) with autocomplete information on it. - AutocompleteDotAccess { - base_exp: Box, - methods: BTreeSet<(ModuleIdent, FunctionName)>, - fields: BTreeSet, - }, - ErrorConstant { line_number_loc: Loc, error_constant: Option, @@ -756,22 +727,6 @@ impl AstDebug for UnannotatedExp_ { seq.ast_debug(w) } E::Block(seq) => seq.ast_debug(w), - E::IDEAnnotation(info, e) => match info { - IDEInfo::MacroCallInfo(i) => { - w.write(format!("{}::{}", i.module, i.name)); - if !i.type_arguments.is_empty() { - w.write("<"); - w.comma(&i.type_arguments, |w, t| t.ast_debug(w)); - w.write(">"); - } - w.write("()"); - e.ast_debug(w); - } - IDEInfo::ExpandedLambda => { - w.write("ExpandedLambda:"); - e.ast_debug(w); - } - }, E::ExpList(es) => { w.write("("); w.comma(es, |w, e| e.ast_debug(w)); @@ -865,21 +820,6 @@ impl AstDebug for UnannotatedExp_ { ty.ast_debug(w); w.write(")"); } - E::AutocompleteDotAccess { - base_exp, - methods, - fields, - } => { - base_exp.ast_debug(w); - w.write(".{"); - let names = methods - .iter() - .map(|(m, f)| format!("{m}::{f}")) - .chain(fields.iter().map(|n| format!("{n}"))) - .collect::>(); - w.comma(names, |w, n| w.write(n)); - w.write("}"); - } E::UnresolvedError => w.write("_|_"), E::ErrorConstant { line_number_loc: _, diff --git a/external-crates/move/crates/move-compiler/src/typing/core.rs b/external-crates/move/crates/move-compiler/src/typing/core.rs index 3ee5756f441b1..504bd6b46b097 100644 --- a/external-crates/move/crates/move-compiler/src/typing/core.rs +++ b/external-crates/move/crates/move-compiler/src/typing/core.rs @@ -21,8 +21,12 @@ use crate::{ Ability_, ConstantName, DatatypeName, Field, FunctionName, VariantName, ENTRY_MODIFIER, }, shared::{ - known_attributes::TestingAttribute, program_info::*, string_utils::debug_print, - unique_map::UniqueMap, *, + ide::{IDEAnnotation, IDEInfo}, + known_attributes::TestingAttribute, + program_info::*, + string_utils::debug_print, + unique_map::UniqueMap, + *, }, typing::match_compilation, FullyCompiledProgram, @@ -84,6 +88,7 @@ pub(super) struct TypingDebugFlags { pub(super) match_constant_conversion: bool, pub(super) autocomplete_resolution: bool, pub(super) function_translation: bool, + pub(super) type_elaboration: bool, } pub struct Context<'env> { @@ -123,6 +128,9 @@ pub struct Context<'env> { /// This is to prevent accidentally thinking we are in a recursive call if a macro is used /// inside a lambda body pub lambda_expansion: Vec>, + /// IDE Info for the current module member. We hold onto this during typing so we can elaborate + /// it at the end. + pub ide_info: IDEInfo, } pub struct ResolvedFunctionType { @@ -185,6 +193,7 @@ impl<'env> Context<'env> { match_constant_conversion: false, autocomplete_resolution: false, function_translation: false, + type_elaboration: false, }; Context { use_funs: vec![global_use_funs], @@ -207,6 +216,7 @@ impl<'env> Context<'env> { used_module_members: BTreeMap::new(), macro_expansion: vec![], lambda_expansion: vec![], + ide_info: IDEInfo::new(), } } @@ -474,7 +484,7 @@ impl<'env> Context<'env> { self.use_funs.last().unwrap().color.unwrap() } - pub fn reset_for_module_item(&mut self) { + pub fn reset_for_module_item(&mut self, loc: Loc) { self.named_block_map = BTreeMap::new(); self.return_type = None; self.locals = UniqueMap::new(); @@ -485,6 +495,12 @@ impl<'env> Context<'env> { self.max_variable_color = RefCell::new(0); self.macro_expansion = vec![]; self.lambda_expansion = vec![]; + + if !self.ide_info.is_empty() { + self.env + .add_diag(ice!((loc, "IDE info should be cleared after each item"))); + self.ide_info = IDEInfo::new(); + } } pub fn error_type(&mut self, loc: Loc) -> Type { @@ -864,7 +880,7 @@ impl<'env> Context<'env> { } //******************************************** - // IDE Helpers + // IDE Information //******************************************** /// Find all valid methods in scope for a given `TypeName`. This is used for autocomplete. @@ -923,6 +939,10 @@ impl<'env> Context<'env> { debug_print!(self.debug.autocomplete_resolution, (lines "fields" => &fields; dbg)); fields } + + pub fn add_ide_info(&mut self, loc: Loc, info: IDEAnnotation) { + self.ide_info.add_ide_annotation(loc, info); + } } //************************************************************************************************** diff --git a/external-crates/move/crates/move-compiler/src/typing/dependency_ordering.rs b/external-crates/move/crates/move-compiler/src/typing/dependency_ordering.rs index af5fc7f769e43..fcb9d302ba8dc 100644 --- a/external-crates/move/crates/move-compiler/src/typing/dependency_ordering.rs +++ b/external-crates/move/crates/move-compiler/src/typing/dependency_ordering.rs @@ -419,7 +419,6 @@ fn exp(context: &mut Context, e: &T::Exp) { E::Loop { body, .. } => exp(context, body), E::NamedBlock(_, seq) => sequence(context, seq), E::Block(seq) => sequence(context, seq), - E::IDEAnnotation(_, e) => exp(context, e), E::Assign(sp!(_, lvs_), ty_opts, e) => { lvalues(context, lvs_); for ty_opt in ty_opts { @@ -472,11 +471,6 @@ fn exp(context: &mut Context, e: &T::Exp) { exp(context, e); type_(context, ty) } - E::AutocompleteDotAccess { - base_exp, - methods: _, - fields: _, - } => exp(context, base_exp), E::Unit { .. } | E::Value(_) | E::Move { .. } diff --git a/external-crates/move/crates/move-compiler/src/typing/expand.rs b/external-crates/move/crates/move-compiler/src/typing/expand.rs index 7507e55b7629c..1e1c63d198529 100644 --- a/external-crates/move/crates/move-compiler/src/typing/expand.rs +++ b/external-crates/move/crates/move-compiler/src/typing/expand.rs @@ -9,8 +9,9 @@ use crate::{ ice, naming::ast::{BuiltinTypeName_, FunctionSignature, Type, TypeName_, Type_}, parser::ast::Ability_, + shared::{ide::IDEAnnotation, string_utils::debug_print, AstDebug}, typing::{ - ast::{self as T, IDEInfo}, + ast::{self as T}, core::{self, Context}, }, }; @@ -58,8 +59,10 @@ pub fn type_(context: &mut Context, ty: &mut Type) { Anything | UnresolvedError | Param(_) | Unit => (), Ref(_, b) => type_(context, b), Var(tvar) => { + debug_print!(context.debug.type_elaboration, ("before" => Var(*tvar))); let ty_tvar = sp(ty.loc, Var(*tvar)); let replacement = core::unfold_type(&context.subst, ty_tvar); + debug_print!(context.debug.type_elaboration, ("resolved" => replacement)); let replacement = match replacement { sp!(loc, Var(_)) => { let diag = ice!(( @@ -85,6 +88,7 @@ pub fn type_(context: &mut Context, ty: &mut Type) { }; *ty = replacement; type_(context, ty); + debug_print!(context.debug.type_elaboration, ("after" => ty)); } Apply(Some(_), sp!(_, TypeName_::Builtin(_)), tys) => types(context, tys), aty @ Apply(Some(_), _, _) => { @@ -258,17 +262,6 @@ pub fn exp(context: &mut Context, e: &mut T::Exp) { E::Loop { body: eloop, .. } => exp(context, eloop), E::NamedBlock(_, seq) => sequence(context, seq), E::Block(seq) => sequence(context, seq), - E::IDEAnnotation(info, er) => { - exp(context, er); - match info { - IDEInfo::MacroCallInfo(i) => { - for t in i.type_arguments.iter_mut() { - type_(context, t); - } - } - IDEInfo::ExpandedLambda => (), - } - } E::Assign(assigns, tys, er) => { lvalues(context, assigns); expected_types(context, tys); @@ -281,12 +274,7 @@ pub fn exp(context: &mut Context, e: &mut T::Exp) { | E::Dereference(base_exp) | E::UnaryExp(_, base_exp) | E::Borrow(_, base_exp, _) - | E::TempBorrow(_, base_exp) - | E::AutocompleteDotAccess { - base_exp, - methods: _, - fields: _, - } => exp(context, base_exp), + | E::TempBorrow(_, base_exp) => exp(context, base_exp), E::Mutate(el, er) => { exp(context, el); exp(context, er) @@ -520,3 +508,22 @@ fn exp_list_item(context: &mut Context, item: &mut T::ExpListItem) { } } } + +//************************************************************************************************** +// IDE Information +//************************************************************************************************** + +pub fn ide_annotation(context: &mut Context, annotation: &mut IDEAnnotation) { + match annotation { + IDEAnnotation::MacroCallInfo(info) => { + for t in info.type_arguments.iter_mut() { + type_(context, t); + } + for t in info.by_value_args.iter_mut() { + sequence_item(context, t); + } + } + IDEAnnotation::ExpandedLambda => (), + IDEAnnotation::AutocompleteInfo(_) => (), + } +} diff --git a/external-crates/move/crates/move-compiler/src/typing/infinite_instantiations.rs b/external-crates/move/crates/move-compiler/src/typing/infinite_instantiations.rs index c01b9201fb799..03e98d4e657cb 100644 --- a/external-crates/move/crates/move-compiler/src/typing/infinite_instantiations.rs +++ b/external-crates/move/crates/move-compiler/src/typing/infinite_instantiations.rs @@ -266,7 +266,6 @@ fn exp(context: &mut Context, e: &T::Exp) { E::Loop { body: eloop, .. } => exp(context, eloop), E::NamedBlock(_, seq) => sequence(context, seq), E::Block(seq) => sequence(context, seq), - E::IDEAnnotation(_, er) => exp(context, er), E::Assign(_, _, er) => exp(context, er), E::Builtin(_, base_exp) @@ -277,12 +276,7 @@ fn exp(context: &mut Context, e: &T::Exp) { | E::Dereference(base_exp) | E::UnaryExp(_, base_exp) | E::Borrow(_, base_exp, _) - | E::TempBorrow(_, base_exp) - | E::AutocompleteDotAccess { - base_exp, - methods: _, - fields: _, - } => exp(context, base_exp), + | E::TempBorrow(_, base_exp) => exp(context, base_exp), E::Mutate(el, er) | E::BinopExp(el, _, _, er) => { exp(context, el); exp(context, er) diff --git a/external-crates/move/crates/move-compiler/src/typing/macro_expand.rs b/external-crates/move/crates/move-compiler/src/typing/macro_expand.rs index fab304da9ce11..4423b7de8399e 100644 --- a/external-crates/move/crates/move-compiler/src/typing/macro_expand.rs +++ b/external-crates/move/crates/move-compiler/src/typing/macro_expand.rs @@ -10,7 +10,7 @@ use crate::{ self as N, BlockLabel, Color, MatchArm_, TParamID, Type, Type_, UseFuns, Var, Var_, }, parser::ast::FunctionName, - shared::{program_info::FunctionInfo, unique_map::UniqueMap}, + shared::{ide::IDEAnnotation, program_info::FunctionInfo, unique_map::UniqueMap}, typing::{ ast as T, core::{self, TParamSubst}, @@ -44,6 +44,7 @@ pub struct ExpandedMacro { pub body: Box, } +#[derive(Debug)] pub enum EvalStrategy { ByValue(ByValue), ByName(ByName), @@ -613,7 +614,6 @@ fn recolor_exp(ctx: &mut Recolor, sp!(_, e_): &mut N::Exp) { } recolor_seq(ctx, s); } - N::Exp_::IDEAnnotation(_, e) => recolor_exp(ctx, e), N::Exp_::FieldMutate(ed, e) => { recolor_exp_dotted(ctx, ed); recolor_exp(ctx, e) @@ -898,7 +898,6 @@ fn exp(context: &mut Context, sp!(eloc, e_): &mut N::Exp) { from_macro_argument: _, seq: s, }) => seq(context, s), - N::Exp_::IDEAnnotation(_, e) => exp(context, e), N::Exp_::FieldMutate(ed, e) => { exp_dotted(context, ed); exp(context, e) @@ -1056,11 +1055,13 @@ fn exp(context: &mut Context, sp!(eloc, e_): &mut N::Exp) { from_macro_argument: None, seq: (N::UseFuns::new(context.macro_color), result), }); - *e_ = if context.core.env.ide_mode() { - N::Exp_::IDEAnnotation(N::IDEInfo::ExpandedLambda, Box::new(sp(*eloc, block))) - } else { - block - }; + if context.core.env.ide_mode() { + context + .core + .env + .add_ide_annotation(*eloc, IDEAnnotation::ExpandedLambda); + } + *e_ = block; } /////// diff --git a/external-crates/move/crates/move-compiler/src/typing/translate.rs b/external-crates/move/crates/move-compiler/src/typing/translate.rs index 72acf573b154f..b680d8c9a98ba 100644 --- a/external-crates/move/crates/move-compiler/src/typing/translate.rs +++ b/external-crates/move/crates/move-compiler/src/typing/translate.rs @@ -20,6 +20,7 @@ use crate::{ VariantName, }, shared::{ + ide::{AutocompleteInfo, IDEAnnotation, MacroCallInfo}, known_attributes::{SyntaxAttribute, TestingAttribute}, process_binops, program_info::{ConstantInfo, DatatypeKind, TypingProgramInfo}, @@ -29,7 +30,7 @@ use crate::{ }, sui_mode, typing::{ - ast::{self as T, IDEInfo, MacroCallInfo}, + ast::{self as T}, core::{ self, public_testing_visibility, Context, PublicForTesting, ResolvedFunctionType, Subst, }, @@ -207,7 +208,7 @@ fn module( context.add_use_funs_scope(use_funs); structs .iter_mut() - .for_each(|(_, _, s)| struct_def(context, s)); + .for_each(|(loc, _name, s)| struct_def(context, loc, s)); enums.iter_mut().for_each(|(_, _, e)| enum_def(context, e)); process_attributes(context, &attributes); let constants = nconstants.map(|name, c| constant(context, name, c)); @@ -238,6 +239,18 @@ fn module( (typed_module, new_friends) } +fn finalize_ide_info(context: &mut Context) { + if !context.env.ide_mode() { + assert!(context.ide_info.is_empty()); + return; + } + let mut info = std::mem::take(&mut context.ide_info); + for (_loc, ann) in info.iter_mut() { + expand::ide_annotation(context, ann); + } + context.env.extend_ide_info(info); +} + //************************************************************************************************** // Functions //************************************************************************************************** @@ -255,7 +268,7 @@ fn function(context: &mut Context, name: FunctionName, f: N::Function) -> T::Fun } = f; context.env.add_warning_filter_scope(warning_filter.clone()); assert!(context.constraints.is_empty()); - context.reset_for_module_item(); + context.reset_for_module_item(name.loc()); context.current_function = Some(name); context.in_macro_function = macro_.is_some(); process_attributes(context, &attributes); @@ -271,6 +284,7 @@ fn function(context: &mut Context, name: FunctionName, f: N::Function) -> T::Fun } else { function_body(context, n_body) }; + finalize_ide_info(context); context.current_function = None; context.in_macro_function = false; context.env.pop_warning_filter_scope(); @@ -344,9 +358,9 @@ fn function_body(context: &mut Context, sp!(loc, nb_): N::FunctionBody) -> T::Fu // Constants //************************************************************************************************** -fn constant(context: &mut Context, _name: ConstantName, nconstant: N::Constant) -> T::Constant { +fn constant(context: &mut Context, name: ConstantName, nconstant: N::Constant) -> T::Constant { assert!(context.constraints.is_empty()); - context.reset_for_module_item(); + context.reset_for_module_item(name.loc()); let N::Constant { warning_filter, @@ -385,6 +399,9 @@ fn constant(context: &mut Context, _name: ConstantName, nconstant: N::Constant) expand::exp(context, &mut value); check_valid_constant::exp(context, &value); + if context.env.ide_mode() { + finalize_ide_info(context); + } context.env.pop_warning_filter_scope(); T::Constant { @@ -490,10 +507,6 @@ mod check_valid_constant { sequence(context, seq); return; } - E::IDEAnnotation(_, er) => { - exp(context, er); - return; - } E::UnaryExp(_, er) => { exp(context, er); return; @@ -530,14 +543,6 @@ mod check_valid_constant { exp(context, &call.arguments); "Module calls are" } - E::AutocompleteDotAccess { - base_exp, - methods: _, - fields: _, - } => { - exp(context, base_exp); - "Partial dot access paths are" - } E::Builtin(b, args) => { exp(context, args); s = format!("'{}' is", b); @@ -670,9 +675,9 @@ mod check_valid_constant { // Data Types //************************************************************************************************** -fn struct_def(context: &mut Context, s: &mut N::StructDefinition) { +fn struct_def(context: &mut Context, sloc: Loc, s: &mut N::StructDefinition) { assert!(context.constraints.is_empty()); - context.reset_for_module_item(); + context.reset_for_module_item(sloc); context .env .add_warning_filter_scope(s.warning_filter.clone()); @@ -732,8 +737,9 @@ fn enum_def(context: &mut Context, enum_: &mut N::EnumDefinition) { let enum_type_params = &enum_.type_parameters; let mut field_types = vec![]; - for (_, _, variant) in enum_.variants.iter_mut() { - let mut varient_fields = variant_def(context, enum_abilities, enum_type_params, variant); + for (vloc, _, variant) in enum_.variants.iter_mut() { + let mut varient_fields = + variant_def(context, vloc, enum_abilities, enum_type_params, variant); field_types.append(&mut varient_fields); } @@ -743,11 +749,12 @@ fn enum_def(context: &mut Context, enum_: &mut N::EnumDefinition) { fn variant_def( context: &mut Context, + vloc: Loc, enum_abilities: &AbilitySet, enum_tparams: &[DatatypeTypeParameter], v: &mut N::VariantDefinition, ) -> Vec<(usize, Type)> { - context.reset_for_module_item(); + context.reset_for_module_item(vloc); let field_map = match &mut v.fields { N::VariantFields::Empty => return vec![], @@ -1633,13 +1640,6 @@ fn exp(context: &mut Context, ne: Box) -> Box { context.maybe_exit_macro_argument(eloc, from_macro_argument); res } - NE::IDEAnnotation(info, e) => { - let new_info = match info { - N::IDEInfo::ExpandedLambda => IDEInfo::ExpandedLambda, - }; - let new_exp = exp(context, e); - (new_exp.ty.clone(), TE::IDEAnnotation(new_info, new_exp)) - } NE::Lambda(_) => { if context .env @@ -1839,7 +1839,14 @@ fn exp(context: &mut Context, ne: Box) -> Box { } NE::ExpDotted(usage, edotted) => { - let out_exp = *exp_dotted_usage(context, usage, eloc, edotted); + let mut out_exp = *exp_dotted_usage(context, usage, eloc, edotted); + // If the type location would point to this expression (i.e., not to a struct field or + // similar), we watnt to respan it to blame the overall term for a type mismatch + // (because it likely has a `&`, `*`, or `&mut `). If the type is from elsewhere, + // however, we prefer that location. + if eloc.contains(&out_exp.ty.loc) { + out_exp.ty.loc = eloc; + } (out_exp.ty, out_exp.exp.value) } @@ -3070,8 +3077,9 @@ struct ExpDotted { // if a constant appears plainly in a `use`/`copy` position, and suppresses constant usage // warning if so. warn_on_constant: bool, - // This should only be used in IDE mode, and should only occur on the outer-most parse form. - for_autocomplete: bool, + // This should only be used in IDE mode, used to drive autocompletion reporting in a situation + // like `x.foo.{CURSOR}`. + autocomplete_last: Option, } impl ExpDotted { @@ -3129,7 +3137,7 @@ fn process_exp_dotted( base_type, accessors, warn_on_constant: true, - for_autocomplete: false, + autocomplete_last: None, } } @@ -3165,58 +3173,6 @@ fn process_exp_dotted( } } - /// Process a dotted expression with autocomplete enabled. Note that this bails after the - /// innermost autocomplete, and that is the one that will receive any suggestions. - #[growing_stack] - fn process_exp_dotted_autocomplete( - context: &mut Context, - constraint_verb: Option<&str>, - sp!(dloc, ndot_): N::ExpDotted, - ) -> ExpDotted { - match ndot_ { - N::ExpDotted_::Exp(e) => process_base_exp(context, constraint_verb, dloc, e), - N::ExpDotted_::Dot(ndot, field) => { - let mut inner = process_exp_dotted_autocomplete(context, Some("dot access"), *ndot); - if inner.for_autocomplete { - return inner; - } - let inner_ty = inner.last_type(); - let field_type = resolve_field(context, dloc, inner_ty, &field); - inner.loc = dloc; - debug_print!(context.debug.autocomplete_resolution, ("field type" => field_type)); - if matches!(&field_type.value, Type_::UnresolvedError) { - // If we failed to resolve a field, mark this as for_autocomplete to provide - // suggestions at the error location. - inner.for_autocomplete = true; - } else { - inner - .accessors - .push(ExpDottedAccess::Field(field, field_type)); - } - inner - } - N::ExpDotted_::Index(ndot, sp!(argloc, nargs_)) => { - let mut inner = process_exp_dotted_autocomplete(context, Some("dot access"), *ndot); - if inner.for_autocomplete { - return inner; - } - let inner_ty = inner.last_type(); - let index_access = process_index_access(context, dloc, inner_ty, argloc, nargs_); - inner.loc = dloc; - inner.accessors.push(index_access); - inner - } - N::ExpDotted_::DotAutocomplete(_loc, ndot) => { - let mut inner = process_exp_dotted_autocomplete(context, Some("dot access"), *ndot); - if inner.for_autocomplete { - return inner; - } - inner.for_autocomplete = true; - inner - } - } - } - #[growing_stack] fn process_exp_dotted_inner( context: &mut Context, @@ -3227,6 +3183,7 @@ fn process_exp_dotted( N::ExpDotted_::Exp(e) => process_base_exp(context, constraint_verb, dloc, e), N::ExpDotted_::Dot(ndot, field) => { let mut inner = process_exp_dotted_inner(context, Some("dot access"), *ndot); + assert!(inner.autocomplete_last.is_none()); let inner_ty = inner.last_type(); let field_type = resolve_field(context, dloc, inner_ty, &field); inner.loc = dloc; @@ -3237,12 +3194,19 @@ fn process_exp_dotted( } N::ExpDotted_::Index(ndot, sp!(argloc, nargs_)) => { let mut inner = process_exp_dotted_inner(context, Some("dot access"), *ndot); + assert!(inner.autocomplete_last.is_none()); let inner_ty = inner.last_type(); let index_access = process_index_access(context, dloc, inner_ty, argloc, nargs_); inner.loc = dloc; inner.accessors.push(index_access); inner } + N::ExpDotted_::DotAutocomplete(loc, ndot) if context.env.ide_mode() => { + let mut inner = process_exp_dotted_inner(context, Some("dot access"), *ndot); + assert!(inner.autocomplete_last.is_none()); + inner.autocomplete_last = Some(loc); + inner + } N::ExpDotted_::DotAutocomplete(_loc, ndot) => { context .env @@ -3253,17 +3217,13 @@ fn process_exp_dotted( } } - if context.env.ide_mode() { - process_exp_dotted_autocomplete(context, constraint_verb, ndotted) - } else { - process_exp_dotted_inner(context, constraint_verb, ndotted) - } + process_exp_dotted_inner(context, constraint_verb, ndotted) } fn exp_dotted_usage( context: &mut Context, usage: DottedUsage, - eloc: Loc, + exp_loc: Loc, ndotted: N::ExpDotted, ) -> Box { let constraint_verb = match &ndotted.value { @@ -3274,23 +3234,23 @@ fn exp_dotted_usage( }; let edotted = process_exp_dotted(context, constraint_verb, ndotted); if matches!(usage, DottedUsage::Borrow(_)) && edotted.accessors.is_empty() { - context.add_base_type_constraint(eloc, "Invalid borrow", edotted.base.ty.clone()); + context.add_base_type_constraint(exp_loc, "Invalid borrow", edotted.base.ty.clone()); } - resolve_exp_dotted(context, usage, eloc, edotted) + resolve_exp_dotted(context, usage, exp_loc, edotted) } fn exp_dotted_expression( context: &mut Context, usage: DottedUsage, constraint_verb: Option<&str>, - eloc: Loc, + error_loc: Loc, ndotted: N::ExpDotted, ) -> Box { let edotted = process_exp_dotted(context, constraint_verb, ndotted); if matches!(usage, DottedUsage::Borrow(_)) && edotted.accessors.is_empty() { - context.add_base_type_constraint(eloc, "Invalid borrow", edotted.base.ty.clone()); + context.add_base_type_constraint(error_loc, "Invalid borrow", edotted.base.ty.clone()); } - resolve_exp_dotted(context, usage, eloc, edotted) + resolve_exp_dotted(context, usage, error_loc, edotted) } // This comment servees to document the function below. Depending on the shape of the dotted @@ -3325,17 +3285,17 @@ fn exp_dotted_expression( fn resolve_exp_dotted( context: &mut Context, usage: DottedUsage, - eloc: Loc, - mut edotted: ExpDotted, + error_loc: Loc, + edotted: ExpDotted, ) -> Box { use T::UnannotatedExp_ as TE; + let eloc = edotted.loc; let make_exp = |ty, exp_| Box::new(T::exp(ty, sp(eloc, exp_))); - let make_error = |context: &mut Context| make_error_exp(context, eloc); + let make_error = |context: &mut Context| make_error_exp(context, error_loc); let edotted_ty = core::unfold_type(&context.subst, edotted.last_type()); - let for_autocomplete = edotted.for_autocomplete; - debug_print!(context.debug.autocomplete_resolution, ("autocompleting" => edotted; dbg)); + let autocomplete_last = edotted.autocomplete_last; let result = match usage { DottedUsage::Move(loc) => { @@ -3369,7 +3329,7 @@ fn resolve_exp_dotted( loc, ) { // call for effect - borrow_exp_dotted(context, false, edotted); + borrow_exp_dotted(context, error_loc, false, edotted); let msg = "Invalid 'move'. 'move' works only with \ variables, e.g. 'move x'. 'move' on a path access is not supported"; context @@ -3410,11 +3370,11 @@ fn resolve_exp_dotted( } } } else { - exp_dotted_to_owned(context, usage, edotted) + exp_dotted_to_owned(context, error_loc, usage, edotted) }; if !matches!(copy_exp.exp.value, TE::UnresolvedError) { context.add_ability_constraint( - eloc, + error_loc, Some(format!( "Invalid 'copy' of owned value without the '{}' ability", Ability_::Copy @@ -3429,32 +3389,17 @@ fn resolve_exp_dotted( if edotted.accessors.is_empty() { Box::new(edotted.base) } else { - exp_dotted_to_owned(context, DottedUsage::Use, edotted) + exp_dotted_to_owned(context, error_loc, DottedUsage::Use, edotted) } } - DottedUsage::Borrow(mut_) => { - // To maintain previous error reporting - edotted.loc = eloc; - borrow_exp_dotted(context, mut_, edotted) - } + DottedUsage::Borrow(mut_) => borrow_exp_dotted(context, error_loc, mut_, edotted), }; - // Even if for_autocomplete is set, we process the inner dot path to report any additional - // errors that may detect or report. - if for_autocomplete { - let Some(tn) = type_to_type_name(context, &edotted_ty, eloc, "autocompletion".to_string()) - else { - return make_error_exp(context, eloc); - }; - let methods = context.find_all_methods(&tn); - let fields = context.find_all_fields(&tn); - let e_ = TE::AutocompleteDotAccess { - base_exp: result, - methods, - fields, - }; - let ty = sp(eloc, Type_::UnresolvedError); - Box::new(T::exp(ty, sp(eloc, e_))) + if let Some(loc) = autocomplete_last { + assert!(context.env.ide_mode()); + debug_print!(context.debug.autocomplete_resolution, ("computing autocomplete" => result; dbg)); + ide_report_autocomplete(context, &loc, &edotted_ty); + result } else { result } @@ -3487,9 +3432,13 @@ fn resolve_exp_dotted( // mut |- E . (index, methods, args, t) ~> f(e, args ...) : Ref(mut, t) // -fn borrow_exp_dotted(context: &mut Context, mut_: bool, ed: ExpDotted) -> Box { +fn borrow_exp_dotted( + context: &mut Context, + error_loc: Loc, + mut_: bool, + ed: ExpDotted, +) -> Box { use T::UnannotatedExp_ as TE; - fn check_mut(context: &mut Context, loc: Loc, cur_type: Type, expected_mut: bool) { let sp!(tyloc, cur_exp_type) = core::unfold_type(&context.subst, cur_type); let cur_mut = match cur_exp_type { @@ -3516,7 +3465,7 @@ fn borrow_exp_dotted(context: &mut Context, mut_: bool, ed: ExpDotted) -> Box Box { + // report autocomplete information for the IDE + ide_report_autocomplete(context, &name.loc(), &ty); let e_ = TE::Borrow(mut_, exp, name); let ty = sp(loc, Type_::Ref(mut_, Box::new(ty))); exp = Box::new(T::exp(ty, sp(loc, e_))); @@ -3578,7 +3529,7 @@ fn borrow_exp_dotted(context: &mut Context, mut_: bool, ed: ExpDotted) -> Box Box Dereference(e) // -fn exp_dotted_to_owned(context: &mut Context, usage: DottedUsage, ed: ExpDotted) -> Box { +fn exp_dotted_to_owned( + context: &mut Context, + error_loc: Loc, + usage: DottedUsage, + ed: ExpDotted, +) -> Box { use T::UnannotatedExp_ as TE; let (access_msg, access_type) = if let Some(accessor) = ed.accessors.last() { match accessor { @@ -3655,12 +3611,12 @@ fn exp_dotted_to_owned(context: &mut Context, usage: DottedUsage, ed: ExpDotted) if edotted.accessors.is_empty() { edotted.warn_on_constant = false; } - let borrow_exp = borrow_exp_dotted(context, false, edotted); + let borrow_exp = borrow_exp_dotted(context, error_loc, false, edotted); // If we're in an autoborrow, bail. // if matches!(&borrow_exp.exp.value, TE::AutocompleteAccess(..)) { return borrow_exp; } let eloc = borrow_exp.exp.loc; context.add_ability_constraint( - eloc, + error_loc, Some(format!( "Invalid {} of {} without the '{}' ability", case, @@ -3735,6 +3691,20 @@ fn warn_on_constant_borrow(context: &mut Context, loc: Loc, e: &T::Exp) { } } +fn ide_report_autocomplete(context: &mut Context, at_loc: &Loc, in_ty: &Type) { + if !context.env.ide_mode() { + return; + } + let ty = core::unfold_type(&context.subst, in_ty.clone()); + let Some(tn) = type_to_type_name(context, &ty, *at_loc, "autocompletion".to_string()) else { + return; + }; + let methods = context.find_all_methods(&tn); + let fields = context.find_all_fields(&tn); + let info = AutocompleteInfo { methods, fields }; + context.add_ide_info(*at_loc, IDEAnnotation::AutocompleteInfo(Box::new(info))); +} + //************************************************************************************************** // Calls //************************************************************************************************** @@ -3752,7 +3722,7 @@ enum ResolvedMethodCall { fn method_call( context: &mut Context, - loc: Loc, + call_loc: Loc, edotted: ExpDotted, method: Name, ty_args_opt: Option>, @@ -3762,40 +3732,43 @@ fn method_call( use T::UnannotatedExp_ as TE; let mut edotted = edotted; let (m, f, fty, usage) = - match method_call_resolve(context, loc, &mut edotted, method, ty_args_opt) { + match method_call_resolve(context, call_loc, &edotted, method, ty_args_opt) { ResolvedMethodCall::Resolved(m, f, fty, usage) => (*m, f, fty, usage), ResolvedMethodCall::UnknownName if context.env.ide_mode() => { - // If the method name fails to resolve, we do autocomplete for the dotted expression. - edotted.for_autocomplete = true; - let err_ty = context.error_type(loc); + // Even if the method name fails to resolve, we want autocomplete information. + edotted.autocomplete_last = Some(method.loc); + let err_ty = context.error_type(call_loc); let dot_output = - resolve_exp_dotted(context, DottedUsage::Borrow(false), loc, edotted); + resolve_exp_dotted(context, DottedUsage::Borrow(false), call_loc, edotted); return Some((err_ty, dot_output.exp.value)); } ResolvedMethodCall::InvalidBaseType | ResolvedMethodCall::UnknownName => return None, }; - let first_arg = *resolve_exp_dotted(context, usage, loc, edotted); + // report autocomplete information for the IDE + if context.env.ide_mode() { + edotted.autocomplete_last = Some(method.loc); + } + let first_arg = *resolve_exp_dotted(context, usage, call_loc, edotted); args.insert(0, first_arg); - let (mut call, ret_ty) = module_call_impl(context, loc, m, f, fty, argloc, args); + let (mut call, ret_ty) = module_call_impl(context, call_loc, m, f, fty, argloc, args); call.method_name = Some(method); Some((ret_ty, TE::ModuleCall(Box::new(call)))) } fn method_call_resolve( context: &mut Context, - loc: Loc, - edotted: &mut ExpDotted, + call_loc: Loc, + edotted: &ExpDotted, method: Name, ty_args_opt: Option>, ) -> ResolvedMethodCall { - edotted.loc = loc; let edotted_ty = core::unfold_type(&context.subst, edotted.last_type()); - - let Some(tn) = type_to_type_name(context, &edotted_ty, loc, "method call".to_string()) else { + let Some(tn) = type_to_type_name(context, &edotted_ty, call_loc, "method call".to_string()) + else { return ResolvedMethodCall::InvalidBaseType; }; let Some((m, f, fty)) = - core::make_method_call_type(context, loc, &edotted_ty, &tn, method, ty_args_opt) + core::make_method_call_type(context, call_loc, &edotted_ty, &tn, method, ty_args_opt) else { return ResolvedMethodCall::UnknownName; }; @@ -4239,19 +4212,22 @@ fn macro_method_call( nargs: Vec, ) -> Option<(Type, T::UnannotatedExp_)> { let mut edotted = edotted; - let (m, f, fty, usage) = - match method_call_resolve(context, loc, &mut edotted, method, ty_args_opt) { - ResolvedMethodCall::Resolved(m, f, fty, usage) => (*m, f, fty, usage), - ResolvedMethodCall::UnknownName if context.env.ide_mode() => { - // If the method name fails to resolve, we do autocomplete for the dotted expression. - edotted.for_autocomplete = true; - let err_ty = context.error_type(loc); - let dot_output = - resolve_exp_dotted(context, DottedUsage::Borrow(false), loc, edotted); - return Some((err_ty, dot_output.exp.value)); - } - ResolvedMethodCall::InvalidBaseType | ResolvedMethodCall::UnknownName => return None, - }; + let (m, f, fty, usage) = match method_call_resolve(context, loc, &edotted, method, ty_args_opt) + { + ResolvedMethodCall::Resolved(m, f, fty, usage) => (*m, f, fty, usage), + ResolvedMethodCall::UnknownName if context.env.ide_mode() => { + // Even if the method name fails to resolve, we want autocomplete information. + edotted.autocomplete_last = Some(method.loc); + let err_ty = context.error_type(loc); + let dot_output = resolve_exp_dotted(context, DottedUsage::Borrow(false), loc, edotted); + return Some((err_ty, dot_output.exp.value)); + } + ResolvedMethodCall::InvalidBaseType | ResolvedMethodCall::UnknownName => return None, + }; + // report autocomplete information for the IDE + if context.env.ide_mode() { + edotted.autocomplete_last = Some(method.loc); + } let first_arg = *resolve_exp_dotted(context, usage, loc, edotted); let mut args = vec![macro_expand::EvalStrategy::ByValue(first_arg)]; args.extend( @@ -4470,24 +4446,18 @@ fn expand_macro( seq.push_back(sp(body.exp.loc, TS::Seq(body))); let use_funs = N::UseFuns::new(context.current_call_color()); let block = TE::Block((use_funs, seq)); - let e_ = if context.env.ide_mode() { - TE::IDEAnnotation( - T::IDEInfo::MacroCallInfo(MacroCallInfo { - module: m, - name: f, - method_name, - type_arguments: type_args.clone(), - by_value_args, - }), - Box::new(T::Exp { - ty: ty.clone(), - exp: sp(call_loc, block), - }), - ) - } else { - block - }; - (ty, e_) + if context.env.ide_mode() { + let macro_call_info = MacroCallInfo { + module: m, + name: f, + method_name, + type_arguments: type_args.clone(), + by_value_args, + }; + let info = IDEAnnotation::MacroCallInfo(Box::new(macro_call_info)); + context.add_ide_info(call_loc, info); + } + (ty, block) } }; if context.pop_macro_expansion(call_loc, &m, &f) { diff --git a/external-crates/move/crates/move-compiler/src/typing/visitor.rs b/external-crates/move/crates/move-compiler/src/typing/visitor.rs index e7ed4f28b2274..a10643a417bbc 100644 --- a/external-crates/move/crates/move-compiler/src/typing/visitor.rs +++ b/external-crates/move/crates/move-compiler/src/typing/visitor.rs @@ -227,7 +227,6 @@ pub trait TypingVisitorContext { E::Loop { body, .. } => self.visit_exp(body), E::NamedBlock(_, seq) => self.visit_seq(seq), E::Block(seq) => self.visit_seq(seq), - E::IDEAnnotation(_, e) => self.visit_exp(e), E::Assign(_, _, e) => self.visit_exp(e), E::Mutate(e1, e2) => { self.visit_exp(e1); @@ -260,11 +259,6 @@ pub trait TypingVisitorContext { E::TempBorrow(_, e) => self.visit_exp(e), E::Cast(e, _) => self.visit_exp(e), E::Annotate(e, _) => self.visit_exp(e), - E::AutocompleteDotAccess { - base_exp, - methods: _, - fields: _, - } => self.visit_exp(base_exp), E::Unit { .. } | E::Value(_) | E::Move { .. } diff --git a/external-crates/move/crates/move-compiler/tests/move_2024/ide_mode/dot_incomplete.exp b/external-crates/move/crates/move-compiler/tests/move_2024/ide_mode/dot_incomplete.exp index c4a482eefd239..b109e75964879 100644 --- a/external-crates/move/crates/move-compiler/tests/move_2024/ide_mode/dot_incomplete.exp +++ b/external-crates/move/crates/move-compiler/tests/move_2024/ide_mode/dot_incomplete.exp @@ -1,9 +1,3 @@ -error[E15001]: IDE autocomplete - ┌─ tests/move_2024/ide_mode/dot_incomplete.move:13:21 - │ -13 │ let _tmp1 = _s.; // incomplete with `;` (next line should parse) - │ ^^^ Autocompletes to: 'a' - error[E01002]: unexpected token ┌─ tests/move_2024/ide_mode/dot_incomplete.move:13:24 │ @@ -13,12 +7,6 @@ error[E01002]: unexpected token │ Unexpected ';' │ Expected an identifier or a decimal number -error[E15001]: IDE autocomplete - ┌─ tests/move_2024/ide_mode/dot_incomplete.move:14:21 - │ -14 │ let _tmp2 = _s.a.; // incomplete with `;` (next line should parse) - │ ^^^^^ Autocompletes to: 'x' - error[E01002]: unexpected token ┌─ tests/move_2024/ide_mode/dot_incomplete.move:14:26 │ @@ -28,12 +16,6 @@ error[E01002]: unexpected token │ Unexpected ';' │ Expected an identifier or a decimal number -error[E15001]: IDE autocomplete - ┌─ tests/move_2024/ide_mode/dot_incomplete.move:15:21 - │ -15 │ let _tmp3 = _s.a. // incomplete without `;` (unexpected `let`) - │ ^^^^^ Autocompletes to: 'x' - error[E01002]: unexpected token ┌─ tests/move_2024/ide_mode/dot_incomplete.move:16:9 │ diff --git a/external-crates/move/crates/move-compiler/tests/move_2024/ide_mode/index_autocomplete.exp b/external-crates/move/crates/move-compiler/tests/move_2024/ide_mode/index_autocomplete.exp index 285ae8c6e170a..65c84e0fdb4b1 100644 --- a/external-crates/move/crates/move-compiler/tests/move_2024/ide_mode/index_autocomplete.exp +++ b/external-crates/move/crates/move-compiler/tests/move_2024/ide_mode/index_autocomplete.exp @@ -1,9 +1,3 @@ -error[E15001]: IDE autocomplete - ┌─ tests/move_2024/ide_mode/index_autocomplete.move:17:17 - │ -17 │ let _ = &in.0.0[1]. ; - │ ^^^^^^^^^^^ Autocompletes to: '0' - error[E01002]: unexpected token ┌─ tests/move_2024/ide_mode/index_autocomplete.move:17:29 │ @@ -13,12 +7,6 @@ error[E01002]: unexpected token │ Unexpected ';' │ Expected an identifier or a decimal number -error[E15001]: IDE autocomplete - ┌─ tests/move_2024/ide_mode/index_autocomplete.move:21:17 - │ -21 │ let _ = &in.0.0[1].0[0]. ; - │ ^^^^^^^^^^^^^^^^ Autocompletes to: - error[E01002]: unexpected token ┌─ tests/move_2024/ide_mode/index_autocomplete.move:21:34 │ @@ -28,12 +16,6 @@ error[E01002]: unexpected token │ Unexpected ';' │ Expected an identifier or a decimal number -error[E15001]: IDE autocomplete - ┌─ tests/move_2024/ide_mode/index_autocomplete.move:25:17 - │ -25 │ let _ = &in.0.0[1].0[0]. ; - │ ^^^^^^^^^^^^^^^^ Autocompletes to: 'c' or 'd' - error[E01002]: unexpected token ┌─ tests/move_2024/ide_mode/index_autocomplete.move:25:34 │ diff --git a/external-crates/move/crates/move-compiler/tests/move_2024/ide_mode/named_struct_autocomplete.exp b/external-crates/move/crates/move-compiler/tests/move_2024/ide_mode/named_struct_autocomplete.exp index 4da0d47191c91..9c31cb3b2c1db 100644 --- a/external-crates/move/crates/move-compiler/tests/move_2024/ide_mode/named_struct_autocomplete.exp +++ b/external-crates/move/crates/move-compiler/tests/move_2024/ide_mode/named_struct_autocomplete.exp @@ -1,9 +1,3 @@ -error[E15001]: IDE autocomplete - ┌─ tests/move_2024/ide_mode/named_struct_autocomplete.move:13:21 - │ -13 │ let _tmp1 = _s.; - │ ^^^ Autocompletes to: 'a' - error[E01002]: unexpected token ┌─ tests/move_2024/ide_mode/named_struct_autocomplete.move:13:24 │ @@ -13,12 +7,6 @@ error[E01002]: unexpected token │ Unexpected ';' │ Expected an identifier or a decimal number -error[E15001]: IDE autocomplete - ┌─ tests/move_2024/ide_mode/named_struct_autocomplete.move:14:21 - │ -14 │ let _tmp2 = _s.a.; - │ ^^^^^ Autocompletes to: 'x' - error[E01002]: unexpected token ┌─ tests/move_2024/ide_mode/named_struct_autocomplete.move:14:26 │ diff --git a/external-crates/move/crates/move-compiler/tests/move_2024/ide_mode/positional_struct_autocomplete.exp b/external-crates/move/crates/move-compiler/tests/move_2024/ide_mode/positional_struct_autocomplete.exp index abe451a9defe2..e206d634ed1fa 100644 --- a/external-crates/move/crates/move-compiler/tests/move_2024/ide_mode/positional_struct_autocomplete.exp +++ b/external-crates/move/crates/move-compiler/tests/move_2024/ide_mode/positional_struct_autocomplete.exp @@ -1,9 +1,3 @@ -error[E15001]: IDE autocomplete - ┌─ tests/move_2024/ide_mode/positional_struct_autocomplete.move:9:21 - │ -9 │ let _tmp1 = _s.; - │ ^^^ Autocompletes to: '0' - error[E01002]: unexpected token ┌─ tests/move_2024/ide_mode/positional_struct_autocomplete.move:9:24 │ @@ -13,12 +7,6 @@ error[E01002]: unexpected token │ Unexpected ';' │ Expected an identifier or a decimal number -error[E15001]: IDE autocomplete - ┌─ tests/move_2024/ide_mode/positional_struct_autocomplete.move:10:21 - │ -10 │ let _tmp2 = _s.0.; - │ ^^^^^ Autocompletes to: '0' - error[E01002]: unexpected token ┌─ tests/move_2024/ide_mode/positional_struct_autocomplete.move:10:26 │ diff --git a/external-crates/move/crates/move-compiler/tests/move_2024/ide_mode/struct_method_autocomplete.exp b/external-crates/move/crates/move-compiler/tests/move_2024/ide_mode/struct_method_autocomplete.exp index b7f1142c0dfcc..ff2accbd13835 100644 --- a/external-crates/move/crates/move-compiler/tests/move_2024/ide_mode/struct_method_autocomplete.exp +++ b/external-crates/move/crates/move-compiler/tests/move_2024/ide_mode/struct_method_autocomplete.exp @@ -1,9 +1,3 @@ -error[E15001]: IDE autocomplete - ┌─ tests/move_2024/ide_mode/struct_method_autocomplete.move:18:21 - │ -18 │ let _tmp1 = _a.; - │ ^^^ Autocompletes to: 'a::m::t0', 'a::m::t1', or 'a::m::t2' - error[E01002]: unexpected token ┌─ tests/move_2024/ide_mode/struct_method_autocomplete.move:18:24 │ @@ -13,12 +7,6 @@ error[E01002]: unexpected token │ Unexpected ';' │ Expected an identifier or a decimal number -error[E15001]: IDE autocomplete - ┌─ tests/move_2024/ide_mode/struct_method_autocomplete.move:19:21 - │ -19 │ let _tmp2 = _b.; - │ ^^^ Autocompletes to: 'a::m::t3', 'a::m::t4', or 'a::m::t5' - error[E01002]: unexpected token ┌─ tests/move_2024/ide_mode/struct_method_autocomplete.move:19:24 │ diff --git a/external-crates/move/crates/move-compiler/tests/move_2024/ide_mode/struct_scoped_autocomplete.exp b/external-crates/move/crates/move-compiler/tests/move_2024/ide_mode/struct_scoped_autocomplete.exp index 7dea9086a8c69..8ec4654f627f8 100644 --- a/external-crates/move/crates/move-compiler/tests/move_2024/ide_mode/struct_scoped_autocomplete.exp +++ b/external-crates/move/crates/move-compiler/tests/move_2024/ide_mode/struct_scoped_autocomplete.exp @@ -1,9 +1,3 @@ -error[E15001]: IDE autocomplete - ┌─ tests/move_2024/ide_mode/struct_scoped_autocomplete.move:17:21 - │ -17 │ let _tmp1 = _a.; - │ ^^^ Autocompletes to: 'a::m::t0' - error[E01002]: unexpected token ┌─ tests/move_2024/ide_mode/struct_scoped_autocomplete.move:17:24 │ @@ -13,12 +7,6 @@ error[E01002]: unexpected token │ Unexpected ';' │ Expected an identifier or a decimal number -error[E15001]: IDE autocomplete - ┌─ tests/move_2024/ide_mode/struct_scoped_autocomplete.move:18:21 - │ -18 │ let _tmp2 = _b.; - │ ^^^ Autocompletes to: 'a::m::t1' - error[E01002]: unexpected token ┌─ tests/move_2024/ide_mode/struct_scoped_autocomplete.move:18:24 │ diff --git a/external-crates/move/crates/move-compiler/tests/move_2024/typing/let_mut_borrow_mut_dot_call.exp b/external-crates/move/crates/move-compiler/tests/move_2024/typing/let_mut_borrow_mut_dot_call.exp index 3749156b36853..2495486805772 100644 --- a/external-crates/move/crates/move-compiler/tests/move_2024/typing/let_mut_borrow_mut_dot_call.exp +++ b/external-crates/move/crates/move-compiler/tests/move_2024/typing/let_mut_borrow_mut_dot_call.exp @@ -5,7 +5,7 @@ error[E04024]: invalid usage of immutable variable │ - To use the variable mutably, it must be declared 'mut', e.g. 'mut x' · 8 │ x.foo(); - │ ^^^^^^^ Invalid mutable borrow of immutable variable 'x' + │ ^ Invalid mutable borrow of immutable variable 'x' error[E04024]: invalid usage of immutable variable ┌─ tests/move_2024/typing/let_mut_borrow_mut_dot_call.move:9:9 @@ -14,7 +14,7 @@ error[E04024]: invalid usage of immutable variable │ - To use the variable mutably, it must be declared 'mut', e.g. 'mut y' · 9 │ y.foo(); - │ ^^^^^^^ Invalid mutable borrow of immutable variable 'y' + │ ^ Invalid mutable borrow of immutable variable 'y' error[E04024]: invalid usage of immutable variable ┌─ tests/move_2024/typing/let_mut_borrow_mut_dot_call.move:10:9 @@ -23,5 +23,5 @@ error[E04024]: invalid usage of immutable variable │ - To use the variable mutably, it must be declared 'mut', e.g. 'mut s' · 10 │ s.foo(); - │ ^^^^^^^ Invalid mutable borrow of immutable variable 's' + │ ^ Invalid mutable borrow of immutable variable 's' diff --git a/external-crates/move/crates/move-compiler/tests/move_check/ide_mode/dot_incomplete.exp b/external-crates/move/crates/move-compiler/tests/move_check/ide_mode/dot_incomplete.exp index 770682ba5502a..46f9d796222c8 100644 --- a/external-crates/move/crates/move-compiler/tests/move_check/ide_mode/dot_incomplete.exp +++ b/external-crates/move/crates/move-compiler/tests/move_check/ide_mode/dot_incomplete.exp @@ -1,17 +1,3 @@ -warning[W09003]: unused assignment - ┌─ tests/move_check/ide_mode/dot_incomplete.move:12:13 - │ -12 │ let s = AnotherStruct { another_field: SomeStruct { some_field: 0 } }; - │ ^ Unused assignment for variable 's'. Consider removing, replacing with '_', or prefixing with '_' (e.g., '_s') - │ - = This warning can be suppressed with '#[allow(unused_assignment)]' applied to the 'module' or module member ('const', 'fun', or 'struct') - -error[E15001]: IDE autocomplete - ┌─ tests/move_check/ide_mode/dot_incomplete.move:13:21 - │ -13 │ let _tmp1 = s.; // incomplete with `;` (next line should parse) - │ ^^ Autocompletes to: 'another_field' - error[E01002]: unexpected token ┌─ tests/move_check/ide_mode/dot_incomplete.move:13:23 │ @@ -21,12 +7,6 @@ error[E01002]: unexpected token │ Unexpected ';' │ Expected an identifier or a decimal number -error[E15001]: IDE autocomplete - ┌─ tests/move_check/ide_mode/dot_incomplete.move:14:21 - │ -14 │ let _tmp2 = s.another_field.; // incomplete with `;` (next line should parse) - │ ^^^^^^^^^^^^^^^^ Autocompletes to: 'some_field' - error[E01002]: unexpected token ┌─ tests/move_check/ide_mode/dot_incomplete.move:14:37 │ @@ -36,12 +16,6 @@ error[E01002]: unexpected token │ Unexpected ';' │ Expected an identifier or a decimal number -error[E15001]: IDE autocomplete - ┌─ tests/move_check/ide_mode/dot_incomplete.move:15:21 - │ -15 │ let _tmp3 = s.another_field. // incomplete without `;` (unexpected `let`) - │ ^^^^^^^^^^^^^^^^ Autocompletes to: 'some_field' - error[E01002]: unexpected token ┌─ tests/move_check/ide_mode/dot_incomplete.move:16:9 │ @@ -51,12 +25,6 @@ error[E01002]: unexpected token │ Unexpected 'let' │ Expected an identifier or a decimal number -error[E15001]: IDE autocomplete - ┌─ tests/move_check/ide_mode/dot_incomplete.move:17:20 - │ -17 │ let _tmp = s. // incomplete without `;` (unexpected `}`) - │ ^^ Autocompletes to: 'another_field' - error[E01002]: unexpected token ┌─ tests/move_check/ide_mode/dot_incomplete.move:18:5 │ diff --git a/external-crates/move/crates/move-compiler/tests/move_check/ide_mode/struct_method_autocomplete.exp b/external-crates/move/crates/move-compiler/tests/move_check/ide_mode/struct_method_autocomplete.exp index e7fbf475622ed..1cef3d8aae539 100644 --- a/external-crates/move/crates/move-compiler/tests/move_check/ide_mode/struct_method_autocomplete.exp +++ b/external-crates/move/crates/move-compiler/tests/move_check/ide_mode/struct_method_autocomplete.exp @@ -22,12 +22,6 @@ error[E13001]: feature is not supported in specified edition │ = You can update the edition in the 'Move.toml', or via command line flag if invoking the compiler directly. -error[E15001]: IDE autocomplete - ┌─ tests/move_check/ide_mode/struct_method_autocomplete.move:18:21 - │ -18 │ let _tmp1 = _a.; - │ ^^^ Autocompletes to: - error[E01002]: unexpected token ┌─ tests/move_check/ide_mode/struct_method_autocomplete.move:18:24 │ @@ -37,12 +31,6 @@ error[E01002]: unexpected token │ Unexpected ';' │ Expected an identifier or a decimal number -error[E15001]: IDE autocomplete - ┌─ tests/move_check/ide_mode/struct_method_autocomplete.move:19:21 - │ -19 │ let _tmp2 = _b.; - │ ^^^ Autocompletes to: - error[E01002]: unexpected token ┌─ tests/move_check/ide_mode/struct_method_autocomplete.move:19:24 │ diff --git a/external-crates/move/crates/move-compiler/tests/move_check/typing/constant_unsupported_exps.exp b/external-crates/move/crates/move-compiler/tests/move_check/typing/constant_unsupported_exps.exp index 61c990c49a519..df33c4621c100 100644 --- a/external-crates/move/crates/move-compiler/tests/move_check/typing/constant_unsupported_exps.exp +++ b/external-crates/move/crates/move-compiler/tests/move_check/typing/constant_unsupported_exps.exp @@ -208,3 +208,9 @@ error[E04013]: invalid statement or expression in constant 39 │ *&b.f; │ ^^^^ References (and reference operations) are not supported in constants +error[E04013]: invalid statement or expression in constant + ┌─ tests/move_check/typing/constant_unsupported_exps.move:39:11 + │ +39 │ *&b.f; + │ ^^^ References (and reference operations) are not supported in constants + diff --git a/external-crates/move/crates/move-ir-types/src/location.rs b/external-crates/move/crates/move-ir-types/src/location.rs index a119b553817dc..fb6ee5ba54fb9 100644 --- a/external-crates/move/crates/move-ir-types/src/location.rs +++ b/external-crates/move/crates/move-ir-types/src/location.rs @@ -69,6 +69,16 @@ impl Loc { end: self.end as usize, } } + + /// Indicates this this location contains the provided location + pub fn contains(&self, other: &Loc) -> bool { + self.file_hash == other.file_hash && self.start <= other.start && other.end <= self.end + } + + /// Indicates this this location overlaps the provided location + pub fn overlaps(&self, other: &Loc) -> bool { + self.file_hash == other.file_hash && !(self.end < other.start || other.end < self.start) + } } impl PartialOrd for Loc { From a92b03de425f04d1fb7797a347a1e0f1c512f3e0 Mon Sep 17 00:00:00 2001 From: hayes-mysten <135670682+hayes-mysten@users.noreply.github.com> Date: Tue, 28 May 2024 20:59:52 -0700 Subject: [PATCH 018/324] TS SDK 1.0 (#16735) ## Description Describe the changes or additions included in this PR. ## Test Plan How did you test the new or updated feature? --- If your changes are not user-facing and do not break anything, you can skip the following section. Otherwise, please briefly describe what has changed under the Release Notes section. ### Type of Change (Check all that apply) - [ ] protocol change - [ ] 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 --- .changeset/bright-wombats-try.md | 2 +- .changeset/witty-llamas-smile.md | 18 + .github/actions/ts-e2e/action.yml | 2 +- .github/workflows/e2e.yml | 4 +- apps/core/package.json | 4 +- apps/core/src/api/SentryHttpTransport.ts | 2 +- apps/core/src/hooks/useFormatCoin.ts | 4 +- apps/core/src/hooks/useGetCoins.ts | 2 +- apps/core/src/hooks/useGetDelegatedStake.tsx | 2 +- apps/core/src/hooks/useGetDynamicFields.ts | 4 +- apps/core/src/hooks/useGetKioskContents.ts | 2 +- apps/core/src/hooks/useGetObject.ts | 2 +- apps/core/src/hooks/useGetOwnedObjects.ts | 2 +- apps/core/src/hooks/useGetTransferAmount.ts | 4 +- apps/core/src/hooks/useGetValidatorsEvents.ts | 2 +- apps/core/src/hooks/useMultiGetObjects.ts | 2 +- apps/core/src/hooks/useTransactionSummary.ts | 2 +- apps/core/src/utils/getRefGasPrice.ts | 2 +- apps/core/src/utils/hasDisplayData.ts | 2 +- apps/core/src/utils/kiosk.ts | 2 +- .../transaction/getBalanceChangeSummary.ts | 4 +- .../src/utils/transaction/getGasSummary.ts | 2 +- apps/core/src/utils/transaction/getLabel.ts | 2 +- .../transaction/getObjectChangeSummary.ts | 2 +- .../transaction/getObjectDisplayLookup.ts | 2 +- .../src/utils/transaction/getOwnerType.ts | 2 +- apps/wallet/configs/ts/tsconfig.common.json | 4 +- .../configs/webpack/webpack.config.common.ts | 2 +- apps/wallet/package.json | 6 +- apps/wallet/src/background/Transactions.ts | 2 +- .../account-sources/MnemonicAccountSource.ts | 4 +- .../wallet/src/background/accounts/Account.ts | 12 +- .../background/accounts/MnemonicAccount.ts | 2 +- apps/wallet/src/background/accounts/index.ts | 2 +- .../accounts/zklogin/ZkLoginAccount.ts | 8 +- .../src/background/accounts/zklogin/utils.ts | 4 +- .../connections/ContentScriptConnection.ts | 2 +- .../background/legacy-accounts/LegacyVault.ts | 2 +- .../dapp-interface/WalletStandardInterface.ts | 78 +- .../messages/payloads/MethodPayload.ts | 3 +- .../payloads/transactions/ApprovalRequest.ts | 2 +- .../ExecuteTransactionResponse.ts | 2 +- .../ui/TransactionRequestResponse.ts | 2 +- apps/wallet/src/shared/sui-client.ts | 2 +- .../src/shared/utils/from-exported-keypair.ts | 12 +- apps/wallet/src/shared/utils/index.ts | 2 +- apps/wallet/src/ui/app/ApiProvider.ts | 2 +- apps/wallet/src/ui/app/LedgerSigner.ts | 12 +- apps/wallet/src/ui/app/QredoSigner.ts | 23 +- apps/wallet/src/ui/app/WalletSigner.ts | 29 +- .../BackgroundServiceSigner.ts | 5 +- .../src/ui/app/background-client/index.ts | 7 +- .../src/ui/app/components/AccountListItem.tsx | 2 +- .../app/components/WalletListSelectItem.tsx | 2 +- .../app/components/accounts/AccountItem.tsx | 2 +- .../accounts/AccountItemApproveConnection.tsx | 2 +- .../components/active-coins-card/index.tsx | 2 +- .../ui/app/components/address-input/index.tsx | 2 +- .../components/address-input/validation.ts | 4 +- .../src/ui/app/components/coin-icon/index.tsx | 2 +- .../ui/app/components/explorer-link/index.tsx | 2 +- .../components/ledger/LedgerAccountRow.tsx | 2 +- .../ledger/useDeriveLedgerAccounts.ts | 2 +- .../content/VerifyLedgerConnectionStatus.tsx | 2 +- .../ui/app/components/nft-display/Kiosk.tsx | 2 +- .../ui/app/components/nft-display/index.tsx | 2 +- .../components/receipt-card/StakeTxnCard.tsx | 4 +- .../receipt-card/TxnAddressLink.tsx | 2 +- .../components/receipt-card/TxnGasSummary.tsx | 2 +- .../receipt-card/UnstakeTxnCard.tsx | 4 +- .../ui/app/components/receipt-card/index.tsx | 2 +- .../app/components/sui-apps/DisconnectApp.tsx | 2 +- .../transactions-card/TxnActionLabel.tsx | 2 +- .../components/transactions-card/index.tsx | 2 +- .../src/ui/app/helpers/checkStakingTxn.ts | 2 +- .../app/helpers/filterAndSortTokenBalances.ts | 2 +- apps/wallet/src/ui/app/helpers/getAmount.ts | 2 +- .../src/ui/app/helpers/getEventsSummary.ts | 2 +- .../validation/privateKeyValidation.ts | 2 +- .../ui/app/hooks/deepbook/useGetEstimate.ts | 6 +- .../app/hooks/deepbook/useRecognizedCoins.ts | 2 +- .../ui/app/hooks/useAppResolveSuinsName.ts | 2 +- .../wallet/src/ui/app/hooks/useGetAllCoins.ts | 2 +- apps/wallet/src/ui/app/hooks/useGetNFTs.ts | 2 +- .../src/ui/app/hooks/useGetTransferAmount.ts | 4 +- .../ui/app/hooks/useGetTxnRecipientAddress.ts | 2 +- apps/wallet/src/ui/app/hooks/useMediaUrl.ts | 2 +- .../src/ui/app/hooks/useNFTBasicData.ts | 2 +- .../hooks/useQueryTransactionsByAddress.ts | 2 +- .../src/ui/app/hooks/useRecognizedPackages.ts | 2 +- .../src/ui/app/hooks/useResolveVideo.ts | 2 +- .../app/hooks/useSortedCoinsByCategories.ts | 4 +- .../src/ui/app/hooks/useTransactionData.ts | 17 +- .../src/ui/app/hooks/useTransactionDryRun.ts | 7 +- apps/wallet/src/ui/app/index.tsx | 2 +- .../transaction-request/GasFees.tsx | 10 +- .../TransactionDetails/Command.tsx | 108 +- .../TransactionDetails/Input.tsx | 20 +- .../TransactionDetails/index.tsx | 12 +- .../transaction-request/index.tsx | 6 +- .../transaction-request/utils/normalize.ts | 2 +- .../ui/app/pages/home/kiosk-details/index.tsx | 2 +- .../ui/app/pages/home/nft-details/index.tsx | 2 +- .../home/nft-transfer/TransferNFTForm.tsx | 4 +- .../home/nft-transfer/useTransferKioskItem.ts | 12 +- .../app/pages/home/nft-transfer/validation.ts | 2 +- .../app/pages/home/nfts/NonVisualAssets.tsx | 4 +- .../ui/app/pages/home/nfts/VisualAssets.tsx | 2 +- .../src/ui/app/pages/home/receipt/index.tsx | 2 +- .../app/pages/home/tokens/TokenIconLink.tsx | 2 +- .../ui/app/pages/home/tokens/TokenLink.tsx | 4 +- .../app/pages/home/tokens/TokensDetails.tsx | 4 +- .../pages/home/tokens/coin-balance/index.tsx | 2 +- .../home/transactions/QredoTransaction.tsx | 11 +- .../pages/home/transfer-coin/CoinSelector.tsx | 2 +- .../home/transfer-coin/SendTokenForm.tsx | 4 +- .../home/transfer-coin/utils/transaction.ts | 8 +- .../pages/home/transfer-coin/validation.ts | 2 +- .../components/QredoAccountItem.tsx | 2 +- .../src/ui/app/pages/swap/GasFeeSection.tsx | 2 +- .../src/ui/app/pages/swap/ToAssetSection.tsx | 4 +- apps/wallet/src/ui/app/pages/swap/index.tsx | 4 +- apps/wallet/src/ui/app/pages/swap/utils.ts | 2 +- .../ui/app/redux/slices/sui-objects/Coin.ts | 2 +- .../slices/transaction-requests/index.ts | 8 +- .../src/ui/app/shared/coin-balance/index.tsx | 2 +- .../app/shared/faucet/FaucetRequestButton.tsx | 2 +- .../ui/app/shared/faucet/useFaucetMutation.ts | 2 +- .../transaction-summary/OwnerFooter.tsx | 2 +- .../transaction-summary/cards/GasSummary.tsx | 2 +- .../cards/ObjectChanges.tsx | 2 +- .../objectSummary/ObjectChangeDisplay.tsx | 2 +- .../DelegationDetailCard.tsx | 4 +- .../src/ui/app/staking/getAllStakeSui.ts | 2 +- .../ui/app/staking/getDelegationByStakeId.ts | 2 +- .../src/ui/app/staking/getStakeSuiBySuiId.ts | 2 +- .../staking/getTokenStakeSuiForValidator.ts | 2 +- .../src/ui/app/staking/home/StakeAmount.tsx | 2 +- .../src/ui/app/staking/home/StakedCard.tsx | 4 +- .../src/ui/app/staking/stake/StakingCard.tsx | 4 +- .../src/ui/app/staking/stake/UnstakeForm.tsx | 2 +- .../ui/app/staking/stake/utils/transaction.ts | 8 +- .../app/staking/validators/ValidatorLogo.tsx | 2 +- .../app/staking/validators/ValidatorsCard.tsx | 2 +- apps/wallet/tests/demo-app/src/index.tsx | 12 +- apps/wallet/tests/utils/localnet.ts | 4 +- .../data/entry_point_types/Move.lock | 7 +- .../data/entry_point_vector/Move.lock | 7 +- dapps/kiosk-cli/index.js | 70 +- dapps/kiosk-cli/package.json | 2 +- dapps/kiosk/package.json | 2 +- dapps/kiosk/src/Root.tsx | 2 +- .../kiosk/src/components/Kiosk/FindKiosk.tsx | 2 +- .../kiosk/src/components/Kiosk/KioskData.tsx | 2 +- .../kiosk/src/components/Kiosk/KioskItems.tsx | 2 +- .../src/components/Kiosk/KioskSelector.tsx | 2 +- .../kiosk/src/components/Modals/ListPrice.tsx | 2 +- dapps/kiosk/src/hooks/kiosk.ts | 2 +- dapps/kiosk/src/hooks/useOwnedObjects.ts | 2 +- .../src/hooks/useTransactionExecution.ts | 17 +- dapps/kiosk/src/mutations/kiosk.ts | 44 +- dapps/kiosk/src/utils/utils.ts | 4 +- dapps/multisig-toolkit/package.json | 2 +- .../src/components/connect.tsx | 2 +- .../preview-effects/EffectsPreview.tsx | 2 +- .../components/preview-effects/ObjectLink.tsx | 2 +- .../preview-effects/PreviewCard.tsx | 2 +- .../partials/BalanceChanges.tsx | 2 +- .../preview-effects/partials/Events.tsx | 2 +- .../partials/ObjectChanges.tsx | 2 +- .../preview-effects/partials/Overview.tsx | 2 +- .../preview-effects/partials/Transactions.tsx | 7 +- dapps/multisig-toolkit/src/main.tsx | 2 +- .../src/routes/combine-sigs.tsx | 7 +- .../src/routes/execute-transaction.tsx | 4 +- .../src/routes/multisig-address.tsx | 5 +- .../src/routes/offline-signer.tsx | 10 +- .../src/routes/signature-analyzer.tsx | 8 +- dapps/sponsored-transactions/package.json | 2 +- dapps/sponsored-transactions/src/App.tsx | 24 +- dapps/sponsored-transactions/src/main.tsx | 2 +- dapps/sponsored-transactions/src/utils/rpc.ts | 2 +- .../src/utils/sponsorTransaction.ts | 12 +- .../transaction-auth/intent-signing.mdx | 35 +- .../packages/custom-policies.mdx | 276 +- .../concepts/transfers/transfer-to-object.mdx | 33 +- .../developer/advanced/asset-tokenization.mdx | 933 ++-- .../developer/advanced/randomness-onchain.mdx | 22 +- .../developer/app-examples/blackjack.mdx | 23 +- .../developer/app-examples/coin-flip.mdx | 36 +- .../developer/app-examples/e2e-counter.mdx | 127 +- .../developer/app-examples/recaptcha.mdx | 429 +- .../developer/app-examples/reviews-rating.mdx | 238 +- .../app-examples/trustless-swap/frontend.mdx | 42 +- .../trustless-swap/indexer-api.mdx | 14 +- .../developer/app-examples/weather-oracle.mdx | 390 +- .../cryptography/zklogin-integration.mdx | 150 +- .../developer/first-app/client-tssdk.mdx | 12 +- .../developer/getting-started/get-coins.mdx | 8 +- .../getting-started/local-network.mdx | 11 +- .../guides/developer/sui-101/building-ptb.mdx | 73 +- .../developer/sui-101/sign-and-send-txn.mdx | 138 +- .../developer/sui-101/simulating-refs.mdx | 21 +- .../guides/developer/sui-101/using-events.mdx | 120 +- .../closed-loop-token/action-request.mdx | 58 +- docs/content/standards/coin.mdx | 129 +- docs/content/standards/kiosk.mdx | 191 +- docs/content/standards/wallet-standard.mdx | 87 +- examples/mev_bot/package.json | 3 +- examples/mev_bot/src/index.ts | 416 +- examples/trading/api/helpers/cancel-escrow.ts | 2 +- .../trading/api/helpers/create-demo-data.ts | 2 +- .../api/helpers/create-demo-escrows.ts | 2 +- .../trading/api/indexer/escrow-handler.ts | 2 +- examples/trading/api/indexer/event-indexer.ts | 2 +- .../trading/api/indexer/locked-handler.ts | 2 +- examples/trading/api/package.json | 2 +- examples/trading/api/pnpm-lock.yaml | 1058 ---- examples/trading/api/sui-utils.ts | 10 +- examples/trading/frontend/package.json | 6 +- examples/trading/frontend/pnpm-lock.yaml | 4824 ----------------- .../frontend/src/components/ExplorerLink.tsx | 2 +- .../src/components/SuiObjectDisplay.tsx | 2 +- .../src/components/escrows/CreateEscrow.tsx | 2 +- .../src/components/locked/LockedObject.tsx | 2 +- examples/trading/frontend/src/constants.ts | 2 + .../src/hooks/useTransactionExecution.ts | 6 +- examples/trading/frontend/src/main.tsx | 2 +- .../trading/frontend/src/mutations/demo.ts | 2 +- .../trading/frontend/src/mutations/escrow.ts | 4 +- .../trading/frontend/src/mutations/locked.ts | 4 +- package.json | 2 +- pnpm-lock.yaml | 1539 ++++-- pnpm-workspace.yaml | 1 + sdk/bcs/README.md | 2 +- sdk/bcs/package.json | 2 +- sdk/bcs/src/bcs-type.ts | 29 +- sdk/bcs/src/bcs.ts | 82 +- sdk/bcs/src/index.ts | 13 +- sdk/bcs/src/legacy-registry.ts | 1144 ---- sdk/bcs/src/types.ts | 79 +- sdk/bcs/src/writer.ts | 14 +- sdk/bcs/tests/alias.test.ts | 42 - sdk/bcs/tests/array.type.test.ts | 112 - sdk/bcs/tests/bcs.test.ts | 156 +- sdk/bcs/tests/builder.test.ts | 12 +- sdk/bcs/tests/config.test.ts | 58 - sdk/bcs/tests/encodings.test.ts | 53 +- sdk/bcs/tests/generics.test.ts | 49 - sdk/bcs/tests/inline-definition.test.ts | 50 - sdk/bcs/tests/nested.object.test.ts | 77 - sdk/bcs/tests/parse-type-name.test.ts | 19 - sdk/bcs/tests/readme.test.ts | 276 - sdk/bcs/tests/serde.test.ts | 186 - sdk/bcs/tests/vector.generics.test.ts | 21 - sdk/build-scripts/package.json | 2 +- sdk/create-dapp/package.json | 2 +- sdk/create-dapp/src/index.ts | 2 +- .../templates/react-client-dapp/package.json | 2 +- .../templates/react-client-dapp/src/main.tsx | 2 +- .../templates/react-e2e-counter/package.json | 2 +- .../templates/react-e2e-counter/src/App.tsx | 2 +- .../react-e2e-counter/src/Counter.tsx | 26 +- .../react-e2e-counter/src/CreateCounter.tsx | 30 +- .../react-e2e-counter/src/networkConfig.ts | 2 +- sdk/dapp-kit/README.md | 4 +- sdk/dapp-kit/package.json | 6 +- .../src/components/AccountDropdownMenu.tsx | 2 +- .../src/components/SuiClientProvider.tsx | 4 +- .../src/components/WalletProvider.tsx | 18 +- sdk/dapp-kit/src/constants/walletDefaults.ts | 10 +- .../src/constants/walletMutationKeys.ts | 5 +- sdk/dapp-kit/src/hooks/networkConfig.ts | 2 +- .../src/hooks/useResolveSuiNSNames.ts | 2 +- sdk/dapp-kit/src/hooks/useSuiClient.ts | 2 +- .../src/hooks/useSuiClientInfiniteQuery.ts | 2 +- sdk/dapp-kit/src/hooks/useSuiClientQuery.ts | 2 +- .../src/hooks/wallet/useConnectWallet.ts | 7 +- .../src/hooks/wallet/useCurrentWallet.ts | 4 + .../wallet/useReportTransactionEffects.ts | 82 + .../wallet/useSignAndExecuteTransaction.ts | 167 + .../useSignAndExecuteTransactionBlock.ts | 116 - .../src/hooks/wallet/useSignTransaction.ts | 119 + .../hooks/wallet/useSignTransactionBlock.ts | 84 - .../src/hooks/wallet/useUnsafeBurnerWallet.ts | 75 +- .../src/hooks/wallet/useWalletsChanged.ts | 10 +- sdk/dapp-kit/src/index.ts | 5 +- sdk/dapp-kit/src/types.ts | 2 +- sdk/dapp-kit/src/utils/walletUtils.ts | 5 +- sdk/dapp-kit/src/walletStore.ts | 8 +- .../components/SuiClientProvider.test.tsx | 2 +- .../test/components/WalletProvider.test.tsx | 2 +- .../useSignAndExecuteTransaction.test.tsx | 239 + ...useSignAndExecuteTransactionBlock.test.tsx | 107 - ...k.test.tsx => useSignTransaction.test.tsx} | 47 +- sdk/dapp-kit/test/hooks/useSuiClient.test.tsx | 2 +- .../hooks/useSuiClientInfiniteQuery.test.tsx | 2 +- .../test/hooks/useSuiClientMutation.test.tsx | 2 +- .../test/hooks/useSuiClientQueries.test.tsx | 2 +- .../test/hooks/useSuiClientQuery.test.tsx | 2 +- sdk/dapp-kit/test/mocks/mockAccount.ts | 9 +- sdk/dapp-kit/test/mocks/mockFeatures.ts | 12 + sdk/dapp-kit/test/test-utils.tsx | 2 +- sdk/dapp-kit/vitest.config.ts | 14 +- sdk/deepbook/package.json | 6 +- sdk/deepbook/src/client.ts | 357 +- sdk/deepbook/src/types/bcs.ts | 24 +- sdk/deepbook/src/types/index.ts | 2 +- sdk/deepbook/src/utils/constants.ts | 2 +- sdk/deepbook/test/e2e/client.test.ts | 46 +- sdk/deepbook/test/e2e/setup.ts | 56 +- sdk/docs/examples/wallet-components.tsx | 2 +- sdk/docs/examples/wallet-hooks.tsx | 30 +- sdk/docs/package.json | 3 +- sdk/docs/pages/bcs/index.mdx | 2 +- sdk/docs/pages/dapp-kit/index.mdx | 4 +- sdk/docs/pages/dapp-kit/rpc-hooks.mdx | 2 +- .../pages/dapp-kit/sui-client-provider.mdx | 8 +- .../pages/dapp-kit/wallet-hooks/_meta.json | 5 +- .../useReportTransactionEffects.mdx | 56 + .../useSignAndExecuteTransaction.mdx | 61 + .../useSignAndExecuteTransactionBlock.mdx | 65 - .../wallet-hooks/useSignTransaction.mdx | 77 + .../wallet-hooks/useSignTransactionBlock.mdx | 62 - sdk/docs/pages/dapp-kit/wallet-provider.mdx | 4 +- sdk/docs/pages/kiosk/advanced-examples.mdx | 20 +- sdk/docs/pages/kiosk/from-v1.mdx | 34 +- .../pages/kiosk/kiosk-client/introduction.mdx | 2 +- .../kiosk-transaction/examples.mdx | 36 +- .../kiosk-transaction/kiosk-transaction.mdx | 26 +- .../kiosk-transaction/managing.mdx | 78 +- .../kiosk-transaction/purchasing.mdx | 24 +- .../introduction.mdx | 22 +- sdk/docs/pages/typescript/_meta.json | 7 +- sdk/docs/pages/typescript/bcs.mdx | 8 +- .../typescript/cryptography/keypairs.mdx | 56 +- .../typescript/cryptography/multisig.mdx | 12 +- sdk/docs/pages/typescript/executors.mdx | 131 + sdk/docs/pages/typescript/faucet.mdx | 4 +- sdk/docs/pages/typescript/graphql.mdx | 93 + sdk/docs/pages/typescript/hello-sui.mdx | 14 +- sdk/docs/pages/typescript/index.mdx | 43 +- sdk/docs/pages/typescript/install.mdx | 4 +- .../pages/typescript/migrations/_meta.json | 3 + .../pages/typescript/migrations/sui-1.0.mdx | 450 ++ .../custom-split-strategy.mdx | 15 +- .../typescript/owned-object-pool/examples.mdx | 79 +- .../typescript/owned-object-pool/index.mdx | 17 +- .../owned-object-pool/local-development.mdx | 13 +- .../typescript/owned-object-pool/overview.mdx | 49 +- sdk/docs/pages/typescript/plugins.mdx | 264 + sdk/docs/pages/typescript/sui-client.mdx | 62 +- .../transaction-building/_meta.json | 7 +- .../transaction-building/basics.mdx | 155 +- .../typescript/transaction-building/gas.mdx | 26 +- .../transaction-building/intents.mdx | 58 + .../transaction-building/offline.mdx | 17 +- .../sponsored-transactions.mdx | 18 +- sdk/docs/pages/typescript/utils.mdx | 2 +- sdk/docs/pages/typescript/zklogin.mdx | 6 +- sdk/docs/pages/zksend/dapp.mdx | 10 +- sdk/docs/pages/zksend/link-builder.mdx | 56 +- sdk/docs/theme.config.jsx | 9 + sdk/docs/typedoc.json | 3 +- sdk/enoki/demo/App.tsx | 14 +- sdk/enoki/package.json | 2 +- sdk/enoki/src/EnokiClient/index.ts | 18 +- sdk/enoki/src/EnokiClient/type.ts | 14 +- sdk/enoki/src/EnokiFlow.ts | 51 +- sdk/enoki/src/EnokiKeypair.ts | 16 +- sdk/enoki/src/encryption.ts | 2 +- sdk/graphql-transport/README.md | 2 +- sdk/graphql-transport/package.json | 6 +- .../src/generated/queries.ts | 830 +-- sdk/graphql-transport/src/mappers/bcs.ts | 2 +- .../src/mappers/checkpint.ts | 2 +- sdk/graphql-transport/src/mappers/display.ts | 2 +- sdk/graphql-transport/src/mappers/move.ts | 4 +- sdk/graphql-transport/src/mappers/object.ts | 2 +- sdk/graphql-transport/src/mappers/owner.ts | 2 +- sdk/graphql-transport/src/mappers/stakes.ts | 2 +- .../src/mappers/transaction-block.ts | 599 +- .../src/mappers/validator.ts | 2 +- sdk/graphql-transport/src/methods.ts | 35 +- .../devInspectTransactionBlock.graphql | 1 + .../queries/dryRunTransactionBlock.graphql | 1 + .../queries/executeTransactionBlock.graphql | 1 + .../src/queries/getCurrentEpoch.graphql | 2 +- .../queries/getLatestSuiSystemState.graphql | 9 +- .../src/queries/stakes.graphql | 1 + .../src/queries/transactions.graphql | 108 +- sdk/graphql-transport/src/transport.ts | 4 +- .../test/compatability.test.ts | 114 +- sdk/graphql-transport/tsconfig.json | 4 +- sdk/graphql-transport/vitest.config.ts | 10 +- sdk/kiosk/package.json | 6 +- sdk/kiosk/src/bcs.ts | 38 +- sdk/kiosk/src/client/kiosk-client.ts | 2 +- sdk/kiosk/src/client/kiosk-transaction.ts | 110 +- sdk/kiosk/src/client/tp-transaction.ts | 51 +- sdk/kiosk/src/query/kiosk.ts | 4 +- sdk/kiosk/src/query/transfer-policy.ts | 10 +- sdk/kiosk/src/tx/kiosk.ts | 32 +- sdk/kiosk/src/tx/personal-kiosk.ts | 6 +- sdk/kiosk/src/tx/rules/attach.ts | 10 +- sdk/kiosk/src/tx/rules/resolve.ts | 32 +- sdk/kiosk/src/tx/transfer-policy.ts | 18 +- sdk/kiosk/src/types/index.ts | 4 +- sdk/kiosk/src/types/kiosk.ts | 4 +- sdk/kiosk/src/types/transfer-policy.ts | 8 +- sdk/kiosk/src/utils.ts | 17 +- sdk/kiosk/test/e2e/e2e.test.ts | 26 +- sdk/kiosk/test/e2e/helper.ts | 52 +- sdk/kiosk/test/e2e/setup.ts | 76 +- sdk/ledgerjs-hw-app-sui/package.json | 2 +- sdk/move-bytecode-template/package.json | 2 +- sdk/move-bytecode-template/src/lib.rs | 2 +- sdk/suins-toolkit/README.md | 2 +- sdk/suins-toolkit/package.json | 8 +- sdk/suins-toolkit/src/client.ts | 2 +- sdk/suins-toolkit/src/utils/parser.ts | 4 +- sdk/suins-toolkit/src/utils/queries.ts | 2 +- sdk/suins-toolkit/tests/app.test.ts | 2 +- sdk/suins-toolkit/vitest.config.ts | 4 +- sdk/typescript/README.md | 82 +- sdk/typescript/package.json | 14 +- sdk/typescript/src/bcs/bcs.ts | 300 + sdk/typescript/src/bcs/effects.ts | 200 + sdk/typescript/src/bcs/index.ts | 513 +- sdk/typescript/src/bcs/type-tag-serializer.ts | 3 +- sdk/typescript/src/bcs/types.ts | 113 + sdk/typescript/src/client/client.ts | 28 +- sdk/typescript/src/client/http-transport.ts | 10 +- sdk/typescript/src/client/index.ts | 21 +- sdk/typescript/src/client/types/common.ts | 2 - sdk/typescript/src/client/types/generated.ts | 61 +- sdk/typescript/src/client/types/params.ts | 6 +- sdk/typescript/src/cryptography/index.ts | 36 +- sdk/typescript/src/cryptography/intent.ts | 39 +- sdk/typescript/src/cryptography/keypair.ts | 46 +- sdk/typescript/src/cryptography/publickey.ts | 24 +- sdk/typescript/src/cryptography/signature.ts | 10 +- sdk/typescript/src/faucet/faucet.ts | 130 + sdk/typescript/src/faucet/index.ts | 134 +- sdk/typescript/src/graphql/index.ts | 10 +- sdk/typescript/src/keypairs/ed25519/index.ts | 8 +- .../src/keypairs/ed25519/keypair.ts | 6 +- .../src/keypairs/ed25519/publickey.ts | 3 +- .../src/keypairs/secp256k1/index.ts | 8 +- .../src/keypairs/secp256k1/keypair.ts | 6 +- .../src/keypairs/secp256k1/publickey.ts | 3 +- .../src/keypairs/secp256r1/index.ts | 8 +- .../src/keypairs/secp256r1/keypair.ts | 6 +- .../src/keypairs/secp256r1/publickey.ts | 3 +- sdk/typescript/src/multisig/index.ts | 19 +- sdk/typescript/src/multisig/publickey.ts | 17 +- sdk/typescript/src/multisig/signer.ts | 8 +- sdk/typescript/src/signers/raw-signer.ts | 40 - .../src/signers/signer-with-provider.ts | 183 - sdk/typescript/src/signers/signer.ts | 22 - sdk/typescript/src/signers/types.ts | 14 - sdk/typescript/src/transactions/Commands.ts | 178 + sdk/typescript/src/transactions/Inputs.ts | 107 +- .../src/transactions/ObjectCache.ts | 296 + .../src/transactions/Transaction.ts | 553 ++ .../src/transactions/TransactionBlock.ts | 865 --- .../src/transactions/TransactionBlockData.ts | 242 - .../src/transactions/TransactionData.ts | 296 + .../src/transactions/Transactions.ts | 256 - .../__tests__/Transaction.test.ts | 69 +- .../src/transactions/__tests__/bcs.test.ts | 224 +- sdk/typescript/src/transactions/bcs.ts | 33 - .../src/transactions/data/internal.ts | 321 ++ sdk/typescript/src/transactions/data/v1.ts | 501 ++ sdk/typescript/src/transactions/data/v2.ts | 146 + .../src/transactions/executor/caching.ts | 94 + .../src/transactions/executor/parallel.ts | 335 ++ .../src/transactions/executor/queue.ts | 65 + .../src/transactions/executor/serial.ts | 131 + sdk/typescript/src/transactions/export.ts | 22 - sdk/typescript/src/transactions/index.ts | 43 +- .../transactions/intents/CoinWithBalance.ts | 204 + .../src/transactions/json-rpc-resolver.ts | 482 ++ sdk/typescript/src/transactions/pure.ts | 30 +- sdk/typescript/src/transactions/serializer.ts | 249 +- sdk/typescript/src/transactions/utils.ts | 33 +- sdk/typescript/src/utils/constants.ts | 15 + sdk/typescript/src/utils/index.ts | 40 +- sdk/typescript/src/verify/index.ts | 110 +- sdk/typescript/src/verify/verify.ts | 111 + sdk/typescript/src/version.ts | 2 +- sdk/typescript/src/zklogin/publickey.ts | 17 +- .../test/e2e/coin-with-balance.test.ts | 574 ++ .../test/e2e/data/coin_metadata/Move.lock | 7 +- .../test/e2e/data/dynamic_fields/Move.lock | 2 +- .../test/e2e/data/id_entry_args/Move.lock | 7 +- .../test/e2e/data/serializer/Move.lock | 6 +- .../data/serializer/sources/serializer.move | 18 +- .../sources/serializer.move | 18 +- sdk/typescript/test/e2e/dev-inspect.test.ts | 30 +- .../test/e2e/entry-point-string.test.ts | 14 +- sdk/typescript/test/e2e/id-entry-args.test.ts | 18 +- sdk/typescript/test/e2e/invalid-ids.test.ts | 8 + sdk/typescript/test/e2e/keypairs.test.ts | 19 +- sdk/typescript/test/e2e/multisig.test.ts | 18 +- sdk/typescript/test/e2e/object-cache.test.ts | 212 + sdk/typescript/test/e2e/object-vector.test.ts | 26 +- sdk/typescript/test/e2e/objects.test.ts | 10 +- .../test/e2e/parallel-executor.test.ts | 181 + sdk/typescript/test/e2e/read-events.test.ts | 7 +- .../test/e2e/read-transactions.test.ts | 24 +- .../test/e2e/receive-object.test.ts | 24 +- .../test/e2e/serial-executor.test.ts | 105 + sdk/typescript/test/e2e/subscribe.test.ts | 12 +- sdk/typescript/test/e2e/txn-builder.test.ts | 35 +- .../test/e2e/txn-serializer.test.ts | 443 +- sdk/typescript/test/e2e/utils/setup.ts | 41 +- .../test/e2e/zklogin-signature.test.ts | 2 +- .../unit/cryptography/ed25519-keypair.test.ts | 47 +- .../test/unit/cryptography/intent.test.ts | 15 +- .../test/unit/cryptography/keypair.test.ts | 31 +- .../cryptography/multisig.publickey.test.ts | 16 +- .../test/unit/cryptography/multisig.test.ts | 76 +- .../test/unit/cryptography/publickey.test.ts | 25 +- .../cryptography/secp256k1-keypair.test.ts | 43 +- .../cryptography/secp256r1-keypair.test.ts | 41 +- sdk/typescript/transactions/package.json | 4 +- sdk/typescript/vitest.config.ts | 2 +- sdk/wallet-standard/package.json | 2 +- sdk/wallet-standard/src/detect.ts | 11 +- sdk/wallet-standard/src/features/index.ts | 31 +- .../features/suiReportTransactionEffects.ts | 30 + .../features/suiSignAndExecuteTransaction.ts | 35 + .../suiSignAndExecuteTransactionBlock.ts | 6 +- .../src/features/suiSignMessage.ts | 2 + .../src/features/suiSignPersonalMessage.ts | 2 + .../src/features/suiSignTransaction.ts | 41 + .../src/features/suiSignTransactionBlock.ts | 10 +- sdk/wallet-standard/src/index.ts | 3 +- sdk/wallet-standard/src/types.ts | 170 + sdk/wallet-standard/src/wallet.ts | 83 + sdk/wallet-standard/typedoc.json | 6 + sdk/zklogin/package.json | 6 +- sdk/zklogin/src/address.ts | 2 +- sdk/zklogin/src/index.ts | 2 +- sdk/zklogin/src/nonce.ts | 4 +- sdk/zklogin/src/utils.ts | 2 +- sdk/zklogin/vitest.config.ts | 4 +- sdk/zksend/package.json | 4 +- sdk/zksend/src/index.test.ts | 108 +- sdk/zksend/src/index.ts | 2 +- sdk/zksend/src/links/builder.ts | 119 +- sdk/zksend/src/links/claim.ts | 134 +- ...ion-blocks.ts => get-sent-transactions.ts} | 26 +- sdk/zksend/src/links/list-created-links.ts | 30 +- sdk/zksend/src/links/utils.ts | 40 +- sdk/zksend/src/links/zk-bag.ts | 84 +- sdk/zksend/src/wallet/channel/index.ts | 122 +- sdk/zksend/src/wallet/index.ts | 56 +- 559 files changed, 15531 insertions(+), 17470 deletions(-) create mode 100644 .changeset/witty-llamas-smile.md delete mode 100644 examples/trading/api/pnpm-lock.yaml delete mode 100644 examples/trading/frontend/pnpm-lock.yaml delete mode 100644 sdk/bcs/src/legacy-registry.ts delete mode 100644 sdk/bcs/tests/alias.test.ts delete mode 100644 sdk/bcs/tests/array.type.test.ts delete mode 100644 sdk/bcs/tests/config.test.ts delete mode 100644 sdk/bcs/tests/generics.test.ts delete mode 100644 sdk/bcs/tests/inline-definition.test.ts delete mode 100644 sdk/bcs/tests/nested.object.test.ts delete mode 100644 sdk/bcs/tests/parse-type-name.test.ts delete mode 100644 sdk/bcs/tests/readme.test.ts delete mode 100644 sdk/bcs/tests/serde.test.ts delete mode 100644 sdk/bcs/tests/vector.generics.test.ts create mode 100644 sdk/dapp-kit/src/hooks/wallet/useReportTransactionEffects.ts create mode 100644 sdk/dapp-kit/src/hooks/wallet/useSignAndExecuteTransaction.ts delete mode 100644 sdk/dapp-kit/src/hooks/wallet/useSignAndExecuteTransactionBlock.ts create mode 100644 sdk/dapp-kit/src/hooks/wallet/useSignTransaction.ts delete mode 100644 sdk/dapp-kit/src/hooks/wallet/useSignTransactionBlock.ts create mode 100644 sdk/dapp-kit/test/hooks/useSignAndExecuteTransaction.test.tsx delete mode 100644 sdk/dapp-kit/test/hooks/useSignAndExecuteTransactionBlock.test.tsx rename sdk/dapp-kit/test/hooks/{useSignTransactionBlock.test.tsx => useSignTransaction.test.tsx} (51%) create mode 100644 sdk/docs/pages/dapp-kit/wallet-hooks/useReportTransactionEffects.mdx create mode 100644 sdk/docs/pages/dapp-kit/wallet-hooks/useSignAndExecuteTransaction.mdx delete mode 100644 sdk/docs/pages/dapp-kit/wallet-hooks/useSignAndExecuteTransactionBlock.mdx create mode 100644 sdk/docs/pages/dapp-kit/wallet-hooks/useSignTransaction.mdx delete mode 100644 sdk/docs/pages/dapp-kit/wallet-hooks/useSignTransactionBlock.mdx create mode 100644 sdk/docs/pages/typescript/executors.mdx create mode 100644 sdk/docs/pages/typescript/graphql.mdx create mode 100644 sdk/docs/pages/typescript/migrations/_meta.json create mode 100644 sdk/docs/pages/typescript/migrations/sui-1.0.mdx create mode 100644 sdk/docs/pages/typescript/plugins.mdx create mode 100644 sdk/docs/pages/typescript/transaction-building/intents.mdx create mode 100644 sdk/typescript/src/bcs/bcs.ts create mode 100644 sdk/typescript/src/bcs/effects.ts create mode 100644 sdk/typescript/src/bcs/types.ts create mode 100644 sdk/typescript/src/faucet/faucet.ts delete mode 100644 sdk/typescript/src/signers/raw-signer.ts delete mode 100644 sdk/typescript/src/signers/signer-with-provider.ts delete mode 100644 sdk/typescript/src/signers/signer.ts delete mode 100644 sdk/typescript/src/signers/types.ts create mode 100644 sdk/typescript/src/transactions/Commands.ts create mode 100644 sdk/typescript/src/transactions/ObjectCache.ts create mode 100644 sdk/typescript/src/transactions/Transaction.ts delete mode 100644 sdk/typescript/src/transactions/TransactionBlock.ts delete mode 100644 sdk/typescript/src/transactions/TransactionBlockData.ts create mode 100644 sdk/typescript/src/transactions/TransactionData.ts delete mode 100644 sdk/typescript/src/transactions/Transactions.ts delete mode 100644 sdk/typescript/src/transactions/bcs.ts create mode 100644 sdk/typescript/src/transactions/data/internal.ts create mode 100644 sdk/typescript/src/transactions/data/v1.ts create mode 100644 sdk/typescript/src/transactions/data/v2.ts create mode 100644 sdk/typescript/src/transactions/executor/caching.ts create mode 100644 sdk/typescript/src/transactions/executor/parallel.ts create mode 100644 sdk/typescript/src/transactions/executor/queue.ts create mode 100644 sdk/typescript/src/transactions/executor/serial.ts delete mode 100644 sdk/typescript/src/transactions/export.ts create mode 100644 sdk/typescript/src/transactions/intents/CoinWithBalance.ts create mode 100644 sdk/typescript/src/transactions/json-rpc-resolver.ts create mode 100644 sdk/typescript/src/utils/constants.ts create mode 100644 sdk/typescript/src/verify/verify.ts create mode 100644 sdk/typescript/test/e2e/coin-with-balance.test.ts create mode 100644 sdk/typescript/test/e2e/object-cache.test.ts create mode 100644 sdk/typescript/test/e2e/parallel-executor.test.ts create mode 100644 sdk/typescript/test/e2e/serial-executor.test.ts create mode 100644 sdk/wallet-standard/src/features/suiReportTransactionEffects.ts create mode 100644 sdk/wallet-standard/src/features/suiSignAndExecuteTransaction.ts create mode 100644 sdk/wallet-standard/src/features/suiSignTransaction.ts create mode 100644 sdk/wallet-standard/src/types.ts create mode 100644 sdk/wallet-standard/typedoc.json rename sdk/zksend/src/links/{get-sent-transaction-blocks.ts => get-sent-transactions.ts} (82%) diff --git a/.changeset/bright-wombats-try.md b/.changeset/bright-wombats-try.md index f0a8016810e5d..4a6e6e01d6838 100644 --- a/.changeset/bright-wombats-try.md +++ b/.changeset/bright-wombats-try.md @@ -1,5 +1,5 @@ --- -'@mysten/sui.js': patch +'@mysten/sui': patch --- Add support for more JSON RPC error codes diff --git a/.changeset/witty-llamas-smile.md b/.changeset/witty-llamas-smile.md new file mode 100644 index 0000000000000..cd5179574f1c8 --- /dev/null +++ b/.changeset/witty-llamas-smile.md @@ -0,0 +1,18 @@ +--- +'@mysten/sui': major +'@mysten/bcs': major +'@mysten/ledgerjs-hw-app-sui': minor +'@mysten/graphql-transport': minor +'@mysten/wallet-standard': minor +'@mysten/suins-toolkit': minor +'@mysten/create-dapp': minor +'@mysten/dapp-kit': minor +'@mysten/deepbook': minor +'@mysten/zklogin': minor +'@mysten/zksend': minor +'@mysten/enoki': minor +'@mysten/kiosk': minor +--- + +The Typescript SDK has been renamed to `@mysten/sui` and includes many new features and breaking changes. +See the [full migration guide](https://sdk.mystenlabs.com/typescript/migrations/sui-1.0) for details on how to upgrade. diff --git a/.github/actions/ts-e2e/action.yml b/.github/actions/ts-e2e/action.yml index 4d4856c76d18a..c2f4cf6258ccf 100644 --- a/.github/actions/ts-e2e/action.yml +++ b/.github/actions/ts-e2e/action.yml @@ -64,5 +64,5 @@ runs: shell: bash - name: Run TS SDK e2e tests - run: pnpm dlx concurrently --kill-others --success command-1 "$E2E_RUN_LOCAL_NET_CMD" 'pnpm --filter @mysten/sui.js --filter @mysten/graphql-transport test:e2e' + run: pnpm dlx concurrently --kill-others --success command-1 "$E2E_RUN_LOCAL_NET_CMD" 'pnpm --filter @mysten/sui --filter @mysten/graphql-transport test:e2e' shell: bash diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index a371c0aa2f984..9bcc57e9c5e80 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest outputs: isWallet: ${{ (steps.turbo.outputs.packages && contains(fromJson(steps.turbo.outputs.packages), 'sui-wallet')) }} - isTypescriptSDK: ${{ (steps.turbo.outputs.packages && contains(fromJson(steps.turbo.outputs.packages), '@mysten/sui.js')) }} + isTypescriptSDK: ${{ (steps.turbo.outputs.packages && contains(fromJson(steps.turbo.outputs.packages), '@mysten/sui')) }} isGraphQlTransport: ${{ (steps.turbo.outputs.packages && contains(fromJson(steps.turbo.outputs.packages), '@mysten/graphql-transport')) }} isRust: ${{ steps.diff.outputs.isRust }} steps: @@ -66,7 +66,7 @@ jobs: - name: Run TS SDK e2e tests if: ${{ needs.diff.outputs.isTypescriptSDK == 'true' || needs.diff.outputs.isRust == 'true'}} - run: pnpm dlx concurrently --kill-others --success command-1 "$E2E_RUN_LOCAL_NET_CMD" 'pnpm --filter @mysten/sui.js test:e2e' + run: pnpm dlx concurrently --kill-others --success command-1 "$E2E_RUN_LOCAL_NET_CMD" 'pnpm --filter @mysten/sui test:e2e' - name: Run RPC/GrpahQL comaptability e2e tests if: ${{ needs.diff.outputs.isGraphQlTransport == 'true' || needs.diff.outputs.isRust == 'true'}} diff --git a/apps/core/package.json b/apps/core/package.json index ddf387f8b9fc1..65ba4e3296424 100644 --- a/apps/core/package.json +++ b/apps/core/package.json @@ -28,7 +28,7 @@ "@hookform/resolvers": "^3.1.1", "@mysten/dapp-kit": "workspace:*", "@mysten/kiosk": "workspace:*", - "@mysten/sui.js": "workspace:*", + "@mysten/sui": "workspace:*", "@sentry/react": "^7.59.2", "@tanstack/react-query": "^5.0.0", "bignumber.js": "^9.1.1", @@ -48,6 +48,6 @@ "tailwindcss": "^3.3.3", "typescript": "^5.3.3", "vite": "^4.4.4", - "vitest": "^0.33.0" + "vitest": "^1.6.0" } } diff --git a/apps/core/src/api/SentryHttpTransport.ts b/apps/core/src/api/SentryHttpTransport.ts index 262eddd68a790..0663523c77bf3 100644 --- a/apps/core/src/api/SentryHttpTransport.ts +++ b/apps/core/src/api/SentryHttpTransport.ts @@ -1,7 +1,7 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -import { SuiHTTPTransport } from '@mysten/sui.js/client'; +import { SuiHTTPTransport } from '@mysten/sui/client'; import * as Sentry from '@sentry/react'; const IGNORED_METHODS = ['suix_resolveNameServiceNames', 'suix_resolveNameServiceAddresses']; diff --git a/apps/core/src/hooks/useFormatCoin.ts b/apps/core/src/hooks/useFormatCoin.ts index fac9c65b332b3..bd7b1317c765f 100644 --- a/apps/core/src/hooks/useFormatCoin.ts +++ b/apps/core/src/hooks/useFormatCoin.ts @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 import { useSuiClient } from '@mysten/dapp-kit'; -import { CoinMetadata } from '@mysten/sui.js/client'; -import { SUI_TYPE_ARG } from '@mysten/sui.js/utils'; +import { CoinMetadata } from '@mysten/sui/client'; +import { SUI_TYPE_ARG } from '@mysten/sui/utils'; import { useQuery, type UseQueryResult } from '@tanstack/react-query'; import BigNumber from 'bignumber.js'; import { useMemo } from 'react'; diff --git a/apps/core/src/hooks/useGetCoins.ts b/apps/core/src/hooks/useGetCoins.ts index f0e09553fb177..42ae6125c7dfb 100644 --- a/apps/core/src/hooks/useGetCoins.ts +++ b/apps/core/src/hooks/useGetCoins.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { useSuiClient } from '@mysten/dapp-kit'; -import { PaginatedCoins } from '@mysten/sui.js/client'; +import { PaginatedCoins } from '@mysten/sui/client'; import { useInfiniteQuery } from '@tanstack/react-query'; const MAX_COINS_PER_REQUEST = 10; diff --git a/apps/core/src/hooks/useGetDelegatedStake.tsx b/apps/core/src/hooks/useGetDelegatedStake.tsx index 72cb32d48f066..eca438fd4d808 100644 --- a/apps/core/src/hooks/useGetDelegatedStake.tsx +++ b/apps/core/src/hooks/useGetDelegatedStake.tsx @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { useSuiClient } from '@mysten/dapp-kit'; -import type { DelegatedStake } from '@mysten/sui.js/client'; +import type { DelegatedStake } from '@mysten/sui/client'; import { useQuery, type UseQueryOptions } from '@tanstack/react-query'; type UseGetDelegatedStakesOptions = { diff --git a/apps/core/src/hooks/useGetDynamicFields.ts b/apps/core/src/hooks/useGetDynamicFields.ts index 4c53bdc4f3aec..144d831995fe4 100644 --- a/apps/core/src/hooks/useGetDynamicFields.ts +++ b/apps/core/src/hooks/useGetDynamicFields.ts @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 import { useSuiClient } from '@mysten/dapp-kit'; -import { DynamicFieldPage } from '@mysten/sui.js/client'; -import { normalizeSuiAddress } from '@mysten/sui.js/utils'; +import { DynamicFieldPage } from '@mysten/sui/client'; +import { normalizeSuiAddress } from '@mysten/sui/utils'; import { useInfiniteQuery } from '@tanstack/react-query'; const MAX_PAGE_SIZE = 10; diff --git a/apps/core/src/hooks/useGetKioskContents.ts b/apps/core/src/hooks/useGetKioskContents.ts index db52f247d308c..c5d6e42c741e3 100644 --- a/apps/core/src/hooks/useGetKioskContents.ts +++ b/apps/core/src/hooks/useGetKioskContents.ts @@ -3,7 +3,7 @@ import { useSuiClientContext } from '@mysten/dapp-kit'; import { KIOSK_ITEM, KioskClient, KioskItem, KioskOwnerCap } from '@mysten/kiosk'; -import { SuiClient } from '@mysten/sui.js/client'; +import { SuiClient } from '@mysten/sui/client'; import { useQuery } from '@tanstack/react-query'; import { getKioskIdFromOwnerCap, ORIGINBYTE_KIOSK_OWNER_TOKEN } from '../utils/kiosk'; diff --git a/apps/core/src/hooks/useGetObject.ts b/apps/core/src/hooks/useGetObject.ts index d474496c7735e..dcafed16752f5 100644 --- a/apps/core/src/hooks/useGetObject.ts +++ b/apps/core/src/hooks/useGetObject.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { useSuiClient } from '@mysten/dapp-kit'; -import { normalizeSuiAddress } from '@mysten/sui.js/utils'; +import { normalizeSuiAddress } from '@mysten/sui/utils'; import { useQuery } from '@tanstack/react-query'; const defaultOptions = { diff --git a/apps/core/src/hooks/useGetOwnedObjects.ts b/apps/core/src/hooks/useGetOwnedObjects.ts index e0a87d1203008..d43629f19d328 100644 --- a/apps/core/src/hooks/useGetOwnedObjects.ts +++ b/apps/core/src/hooks/useGetOwnedObjects.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { useSuiClient } from '@mysten/dapp-kit'; -import { PaginatedObjectsResponse, type SuiObjectDataFilter } from '@mysten/sui.js/client'; +import { PaginatedObjectsResponse, type SuiObjectDataFilter } from '@mysten/sui/client'; import { useInfiniteQuery } from '@tanstack/react-query'; const MAX_OBJECTS_PER_REQ = 6; diff --git a/apps/core/src/hooks/useGetTransferAmount.ts b/apps/core/src/hooks/useGetTransferAmount.ts index 1bfab3b336cfa..ca9776808a32d 100644 --- a/apps/core/src/hooks/useGetTransferAmount.ts +++ b/apps/core/src/hooks/useGetTransferAmount.ts @@ -1,7 +1,7 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -import { SuiTransactionBlockResponse } from '@mysten/sui.js/client'; -import { SUI_TYPE_ARG } from '@mysten/sui.js/utils'; +import { SuiTransactionBlockResponse } from '@mysten/sui/client'; +import { SUI_TYPE_ARG } from '@mysten/sui/utils'; import { useMemo } from 'react'; import { getTotalGasUsed } from '../utils/transaction'; diff --git a/apps/core/src/hooks/useGetValidatorsEvents.ts b/apps/core/src/hooks/useGetValidatorsEvents.ts index ca7ad07064037..3948757fe649e 100644 --- a/apps/core/src/hooks/useGetValidatorsEvents.ts +++ b/apps/core/src/hooks/useGetValidatorsEvents.ts @@ -1,7 +1,7 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 import { useSuiClient } from '@mysten/dapp-kit'; -import { SuiEvent, type EventId } from '@mysten/sui.js/client'; +import { SuiEvent, type EventId } from '@mysten/sui/client'; import { useQuery } from '@tanstack/react-query'; type GetValidatorsEvent = { diff --git a/apps/core/src/hooks/useMultiGetObjects.ts b/apps/core/src/hooks/useMultiGetObjects.ts index 6d04fea411562..f01804576b26c 100644 --- a/apps/core/src/hooks/useMultiGetObjects.ts +++ b/apps/core/src/hooks/useMultiGetObjects.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { useSuiClient } from '@mysten/dapp-kit'; -import { SuiObjectDataOptions, SuiObjectResponse } from '@mysten/sui.js/client'; +import { SuiObjectDataOptions, SuiObjectResponse } from '@mysten/sui/client'; import { useQuery, UseQueryOptions } from '@tanstack/react-query'; import { chunkArray } from '../utils/chunkArray'; diff --git a/apps/core/src/hooks/useTransactionSummary.ts b/apps/core/src/hooks/useTransactionSummary.ts index a09b0f134e289..4bceaa214f89a 100644 --- a/apps/core/src/hooks/useTransactionSummary.ts +++ b/apps/core/src/hooks/useTransactionSummary.ts @@ -3,7 +3,7 @@ import { DryRunTransactionBlockResponse, type SuiTransactionBlockResponse, -} from '@mysten/sui.js/client'; +} from '@mysten/sui/client'; import { useMemo } from 'react'; import { getBalanceChangeSummary } from '../utils/transaction/getBalanceChangeSummary'; diff --git a/apps/core/src/utils/getRefGasPrice.ts b/apps/core/src/utils/getRefGasPrice.ts index 9b6f964395947..f20f82b87ad43 100644 --- a/apps/core/src/utils/getRefGasPrice.ts +++ b/apps/core/src/utils/getRefGasPrice.ts @@ -1,7 +1,7 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -import { SuiValidatorSummary } from '@mysten/sui.js/client'; +import { SuiValidatorSummary } from '@mysten/sui/client'; import { calculateStakeShare } from './calculateStakeShare'; diff --git a/apps/core/src/utils/hasDisplayData.ts b/apps/core/src/utils/hasDisplayData.ts index 034382eccf41d..02e944e25c353 100644 --- a/apps/core/src/utils/hasDisplayData.ts +++ b/apps/core/src/utils/hasDisplayData.ts @@ -1,6 +1,6 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -import { SuiObjectResponse } from '@mysten/sui.js/client'; +import { SuiObjectResponse } from '@mysten/sui/client'; export const hasDisplayData = (obj: SuiObjectResponse) => !!obj.data?.display?.data; diff --git a/apps/core/src/utils/kiosk.ts b/apps/core/src/utils/kiosk.ts index 73ce1a6047672..2c56824e8ad15 100644 --- a/apps/core/src/utils/kiosk.ts +++ b/apps/core/src/utils/kiosk.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { KIOSK_OWNER_CAP, Network, PERSONAL_KIOSK_RULE_ADDRESS } from '@mysten/kiosk'; -import { SuiObjectData, SuiObjectResponse } from '@mysten/sui.js/client'; +import { SuiObjectData, SuiObjectResponse } from '@mysten/sui/client'; export const ORIGINBYTE_KIOSK_MODULE = '0x95a441d389b07437d00dd07e0b6f05f513d7659b13fd7c5d3923c7d9d847199b::ob_kiosk'; diff --git a/apps/core/src/utils/transaction/getBalanceChangeSummary.ts b/apps/core/src/utils/transaction/getBalanceChangeSummary.ts index 4707d99f0a483..9f89165a2c367 100644 --- a/apps/core/src/utils/transaction/getBalanceChangeSummary.ts +++ b/apps/core/src/utils/transaction/getBalanceChangeSummary.ts @@ -4,8 +4,8 @@ import { type DryRunTransactionBlockResponse, type ObjectOwner, type SuiTransactionBlockResponse, -} from '@mysten/sui.js/client'; -import { normalizeSuiObjectId, parseStructTag } from '@mysten/sui.js/utils'; +} from '@mysten/sui/client'; +import { normalizeSuiObjectId, parseStructTag } from '@mysten/sui/utils'; export type BalanceChange = { coinType: string; diff --git a/apps/core/src/utils/transaction/getGasSummary.ts b/apps/core/src/utils/transaction/getGasSummary.ts index a2086f874f207..36e428ac00e2a 100644 --- a/apps/core/src/utils/transaction/getGasSummary.ts +++ b/apps/core/src/utils/transaction/getGasSummary.ts @@ -6,7 +6,7 @@ import { SuiGasData, SuiTransactionBlockResponse, TransactionEffects, -} from '@mysten/sui.js/client'; +} from '@mysten/sui/client'; type Optional = { [K in keyof T]?: T[K]; diff --git a/apps/core/src/utils/transaction/getLabel.ts b/apps/core/src/utils/transaction/getLabel.ts index 9b1b1d65679c5..81fd79a6334c9 100644 --- a/apps/core/src/utils/transaction/getLabel.ts +++ b/apps/core/src/utils/transaction/getLabel.ts @@ -1,6 +1,6 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -import { SuiTransactionBlockResponse } from '@mysten/sui.js/client'; +import { SuiTransactionBlockResponse } from '@mysten/sui/client'; // todo: add more logic for deriving transaction label export const getLabel = (transaction: SuiTransactionBlockResponse, currentAddress?: string) => { diff --git a/apps/core/src/utils/transaction/getObjectChangeSummary.ts b/apps/core/src/utils/transaction/getObjectChangeSummary.ts index 57e865750f15a..91247eb5c1232 100644 --- a/apps/core/src/utils/transaction/getObjectChangeSummary.ts +++ b/apps/core/src/utils/transaction/getObjectChangeSummary.ts @@ -9,7 +9,7 @@ import { SuiObjectChangePublished, SuiObjectChangeTransferred, SuiObjectChangeWrapped, -} from '@mysten/sui.js/client'; +} from '@mysten/sui/client'; import { groupByOwner } from './groupByOwner'; import { SuiObjectChangeTypes } from './types'; diff --git a/apps/core/src/utils/transaction/getObjectDisplayLookup.ts b/apps/core/src/utils/transaction/getObjectDisplayLookup.ts index ed683189122a3..c7b8166f6b384 100644 --- a/apps/core/src/utils/transaction/getObjectDisplayLookup.ts +++ b/apps/core/src/utils/transaction/getObjectDisplayLookup.ts @@ -1,6 +1,6 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -import { DisplayFieldsResponse, SuiObjectResponse } from '@mysten/sui.js/client'; +import { DisplayFieldsResponse, SuiObjectResponse } from '@mysten/sui/client'; import { hasDisplayData } from '../hasDisplayData'; diff --git a/apps/core/src/utils/transaction/getOwnerType.ts b/apps/core/src/utils/transaction/getOwnerType.ts index a400905201bbf..4dc63d2dc3880 100644 --- a/apps/core/src/utils/transaction/getOwnerType.ts +++ b/apps/core/src/utils/transaction/getOwnerType.ts @@ -1,7 +1,7 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -import type { SuiObjectChange } from '@mysten/sui.js/client'; +import type { SuiObjectChange } from '@mysten/sui/client'; export const getOwnerType = (change: SuiObjectChange) => { if (!('owner' in change)) return ''; diff --git a/apps/wallet/configs/ts/tsconfig.common.json b/apps/wallet/configs/ts/tsconfig.common.json index 2daa3e85bccea..030d33a1f8708 100644 --- a/apps/wallet/configs/ts/tsconfig.common.json +++ b/apps/wallet/configs/ts/tsconfig.common.json @@ -43,8 +43,8 @@ "_values/*": ["./src/ui/styles/values/*"], "_utils": ["./src/ui/styles/utils"], "_utils/*": ["./src/ui/styles/utils/*"], - "@mysten/sui.js/*": ["../../sdk/typescript/src/*"], - "@mysten/sui.js": ["../../sdk/typescript/src/"], + "@mysten/sui/*": ["../../sdk/typescript/src/*"], + "@mysten/sui": ["../../sdk/typescript/src/"], "@mysten/kiosk": ["../../sdk/kiosk/src/index.ts"], "@mysten/bcs": ["../../sdk/bcs/src/"], "@mysten/dapp-kit": ["../../sdk/dapp-kit/src/"], diff --git a/apps/wallet/configs/webpack/webpack.config.common.ts b/apps/wallet/configs/webpack/webpack.config.common.ts index 2af5fdf3f051c..4ca0a7776b2b6 100644 --- a/apps/wallet/configs/webpack/webpack.config.common.ts +++ b/apps/wallet/configs/webpack/webpack.config.common.ts @@ -110,7 +110,7 @@ const commonConfig: () => Promise = async () => { }, resolve: { extensions: ['.ts', '.tsx', '.js'], - // Fix .js imports from @mysten/sui.js since we are importing it from source + // Fix .js imports from @mysten/sui since we are importing it from source extensionAlias: { '.js': ['.js', '.ts', '.tsx', '.jsx'], '.mjs': ['.mjs', '.mts'], diff --git a/apps/wallet/package.json b/apps/wallet/package.json index cd99cc81a6411..c09bd878db308 100644 --- a/apps/wallet/package.json +++ b/apps/wallet/package.json @@ -77,7 +77,7 @@ "dotenv-webpack": "^8.0.0", "eslint-webpack-plugin": "^4.0.1", "git-rev-sync": "^3.0.2", - "happy-dom": "^10.5.1", + "happy-dom": "^14.11.0", "html-webpack-plugin": "^5.5.3", "mini-css-extract-plugin": "^2.7.6", "onchange": "^7.1.0", @@ -95,7 +95,7 @@ "typescript": "^5.3.3", "vite": "^4.4.4", "vite-tsconfig-paths": "^4.2.0", - "vitest": "^0.33.0", + "vitest": "^1.6.0", "web-ext": "^7.6.2", "webpack": "^5.79.0", "webpack-cli": "^5.0.1", @@ -120,7 +120,7 @@ "@mysten/icons": "workspace:*", "@mysten/kiosk": "workspace:*", "@mysten/ledgerjs-hw-app-sui": "workspace:*", - "@mysten/sui.js": "workspace:*", + "@mysten/sui": "workspace:*", "@mysten/wallet-standard": "workspace:*", "@mysten/zklogin": "workspace:*", "@noble/hashes": "^1.3.1", diff --git a/apps/wallet/src/background/Transactions.ts b/apps/wallet/src/background/Transactions.ts index 894309572d95b..51f9c24aad4fd 100644 --- a/apps/wallet/src/background/Transactions.ts +++ b/apps/wallet/src/background/Transactions.ts @@ -10,7 +10,7 @@ import { type SignMessageRequest } from '_payloads/transactions/SignMessage'; import type { TransactionRequestResponse } from '_payloads/transactions/ui/TransactionRequestResponse'; import type { ContentScriptConnection } from '_src/background/connections/ContentScriptConnection'; import { type SignedTransaction } from '_src/ui/app/WalletSigner'; -import { type SuiTransactionBlockResponse } from '@mysten/sui.js/client'; +import { type SuiTransactionBlockResponse } from '@mysten/sui/client'; import { type SuiSignMessageOutput } from '@mysten/wallet-standard'; import { filter, lastValueFrom, map, race, Subject, take } from 'rxjs'; import { v4 as uuidV4 } from 'uuid'; diff --git a/apps/wallet/src/background/account-sources/MnemonicAccountSource.ts b/apps/wallet/src/background/account-sources/MnemonicAccountSource.ts index fb8c3f50baf6b..4a6f712b14450 100644 --- a/apps/wallet/src/background/account-sources/MnemonicAccountSource.ts +++ b/apps/wallet/src/background/account-sources/MnemonicAccountSource.ts @@ -9,8 +9,8 @@ import { validateEntropy, } from '_shared/utils/bip39'; import { decrypt, encrypt } from '_src/shared/cryptography/keystore'; -import { mnemonicToSeedHex } from '@mysten/sui.js/cryptography'; -import { Ed25519Keypair } from '@mysten/sui.js/keypairs/ed25519'; +import { mnemonicToSeedHex } from '@mysten/sui/cryptography'; +import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519'; import { sha256 } from '@noble/hashes/sha256'; import { bytesToHex } from '@noble/hashes/utils'; import Dexie from 'dexie'; diff --git a/apps/wallet/src/background/accounts/Account.ts b/apps/wallet/src/background/accounts/Account.ts index 39e6b0615c81d..d41aff29e1d2f 100644 --- a/apps/wallet/src/background/accounts/Account.ts +++ b/apps/wallet/src/background/accounts/Account.ts @@ -2,11 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { type Serializable } from '_src/shared/cryptography/keystore'; -import { - toSerializedSignature, - type Keypair, - type SerializedSignature, -} from '@mysten/sui.js/cryptography'; +import { toSerializedSignature, type Keypair } from '@mysten/sui/cryptography'; import { blake2b } from '@noble/hashes/blake2b'; import { setupAutoLockAlarm } from '../auto-lock-accounts'; @@ -71,10 +67,10 @@ export abstract class Account< return data as T; } - protected generateSignature(data: Uint8Array, keyPair: Keypair) { + protected async generateSignature(data: Uint8Array, keyPair: Keypair) { const digest = blake2b(data, { dkLen: 32 }); const pubkey = keyPair.getPublicKey(); - const signature = keyPair.signData(digest); + const signature = await keyPair.sign(digest); const signatureScheme = keyPair.getKeyScheme(); return toSerializedSignature({ signature, @@ -176,7 +172,7 @@ export function isPasswordUnLockable(account: unknown): account is PasswordUnloc export interface SigningAccount { readonly canSign: true; - signData(data: Uint8Array): Promise; + signData(data: Uint8Array): Promise; } export function isSigningAccount(account: any): account is SigningAccount { diff --git a/apps/wallet/src/background/accounts/MnemonicAccount.ts b/apps/wallet/src/background/accounts/MnemonicAccount.ts index a641a8980f803..e949877f07d71 100644 --- a/apps/wallet/src/background/accounts/MnemonicAccount.ts +++ b/apps/wallet/src/background/accounts/MnemonicAccount.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { fromExportedKeypair } from '_src/shared/utils/from-exported-keypair'; -import { type Keypair } from '@mysten/sui.js/cryptography'; +import { type Keypair } from '@mysten/sui/cryptography'; import { MnemonicAccountSource } from '../account-sources/MnemonicAccountSource'; import { diff --git a/apps/wallet/src/background/accounts/index.ts b/apps/wallet/src/background/accounts/index.ts index b9ee836173b3b..a8feb5089c961 100644 --- a/apps/wallet/src/background/accounts/index.ts +++ b/apps/wallet/src/background/accounts/index.ts @@ -7,7 +7,7 @@ import { type MethodPayload, } from '_src/shared/messaging/messages/payloads/MethodPayload'; import { type WalletStatusChange } from '_src/shared/messaging/messages/payloads/wallet-status-change'; -import { fromB64 } from '@mysten/sui.js/utils'; +import { fromB64 } from '@mysten/sui/utils'; import Dexie from 'dexie'; import { getAccountSourceByID } from '../account-sources'; diff --git a/apps/wallet/src/background/accounts/zklogin/ZkLoginAccount.ts b/apps/wallet/src/background/accounts/zklogin/ZkLoginAccount.ts index 3d05685a8cd70..9cedb3a0f5c85 100644 --- a/apps/wallet/src/background/accounts/zklogin/ZkLoginAccount.ts +++ b/apps/wallet/src/background/accounts/zklogin/ZkLoginAccount.ts @@ -5,11 +5,7 @@ import networkEnv from '_src/background/NetworkEnv'; import { type NetworkEnvType } from '_src/shared/api-env'; import { deobfuscate, obfuscate } from '_src/shared/cryptography/keystore'; import { fromExportedKeypair } from '_src/shared/utils/from-exported-keypair'; -import { - toSerializedSignature, - type PublicKey, - type SerializedSignature, -} from '@mysten/sui.js/cryptography'; +import { toSerializedSignature, type PublicKey } from '@mysten/sui/cryptography'; import { computeZkLoginAddress, genAddressSeed, getZkLoginSignature } from '@mysten/zklogin'; import { blake2b } from '@noble/hashes/blake2b'; import { decodeJwt } from 'jose'; @@ -196,7 +192,7 @@ export class ZkLoginAccount }; } - async signData(data: Uint8Array): Promise { + async signData(data: Uint8Array): Promise { const digest = blake2b(data, { dkLen: 32 }); if (await this.isLocked()) { throw new Error('Account is locked'); diff --git a/apps/wallet/src/background/accounts/zklogin/utils.ts b/apps/wallet/src/background/accounts/zklogin/utils.ts index 8ced1343b48d8..1b937090ed32d 100644 --- a/apps/wallet/src/background/accounts/zklogin/utils.ts +++ b/apps/wallet/src/background/accounts/zklogin/utils.ts @@ -3,8 +3,8 @@ import { API_ENV, type NetworkEnvType } from '_src/shared/api-env'; import { fetchWithSentry } from '_src/shared/utils'; -import { type PublicKey } from '@mysten/sui.js/cryptography'; -import { Ed25519Keypair } from '@mysten/sui.js/keypairs/ed25519'; +import { type PublicKey } from '@mysten/sui/cryptography'; +import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519'; import { generateNonce, generateRandomness, diff --git a/apps/wallet/src/background/connections/ContentScriptConnection.ts b/apps/wallet/src/background/connections/ContentScriptConnection.ts index 36aa34c6d6c31..4eb296c0a428d 100644 --- a/apps/wallet/src/background/connections/ContentScriptConnection.ts +++ b/apps/wallet/src/background/connections/ContentScriptConnection.ts @@ -31,7 +31,7 @@ import { type SignMessageRequest, } from '_src/shared/messaging/messages/payloads/transactions/SignMessage'; import { type SignedTransaction } from '_src/ui/app/WalletSigner'; -import { type SuiTransactionBlockResponse } from '@mysten/sui.js/client'; +import { type SuiTransactionBlockResponse } from '@mysten/sui/client'; import type { Runtime } from 'webextension-polyfill'; import { getAccountsStatusData } from '../accounts'; diff --git a/apps/wallet/src/background/legacy-accounts/LegacyVault.ts b/apps/wallet/src/background/legacy-accounts/LegacyVault.ts index ef187d72c1dfd..34253c129ec54 100644 --- a/apps/wallet/src/background/legacy-accounts/LegacyVault.ts +++ b/apps/wallet/src/background/legacy-accounts/LegacyVault.ts @@ -12,7 +12,7 @@ import { fromExportedKeypair, type LegacyExportedKeyPair, } from '_shared/utils/from-exported-keypair'; -import { mnemonicToSeedHex, type Keypair } from '@mysten/sui.js/cryptography'; +import { mnemonicToSeedHex, type Keypair } from '@mysten/sui/cryptography'; import { getFromLocalStorage } from '../storage-utils'; diff --git a/apps/wallet/src/dapp-interface/WalletStandardInterface.ts b/apps/wallet/src/dapp-interface/WalletStandardInterface.ts index 74c3ef6b52533..3c74b905dd490 100644 --- a/apps/wallet/src/dapp-interface/WalletStandardInterface.ts +++ b/apps/wallet/src/dapp-interface/WalletStandardInterface.ts @@ -28,8 +28,9 @@ import { } from '_src/shared/messaging/messages/payloads/QredoConnect'; import { type SignMessageRequest } from '_src/shared/messaging/messages/payloads/transactions/SignMessage'; import { isWalletStatusChangePayload } from '_src/shared/messaging/messages/payloads/wallet-status-change'; -import { isTransactionBlock } from '@mysten/sui.js/transactions'; -import { fromB64, toB64 } from '@mysten/sui.js/utils'; +import { bcs } from '@mysten/sui/bcs'; +import { isTransaction } from '@mysten/sui/transactions'; +import { fromB64, toB64 } from '@mysten/sui/utils'; import { ReadonlyWalletAccount, SUI_CHAINS, @@ -44,9 +45,11 @@ import { type StandardEventsOnMethod, type SuiFeatures, type SuiSignAndExecuteTransactionBlockMethod, + type SuiSignAndExecuteTransactionMethod, type SuiSignMessageMethod, type SuiSignPersonalMessageMethod, type SuiSignTransactionBlockMethod, + type SuiSignTransactionMethod, type Wallet, } from '@mysten/wallet-standard'; import mitt, { type Emitter } from 'mitt'; @@ -131,10 +134,18 @@ export class SuiWallet implements Wallet { version: '1.0.0', signTransactionBlock: this.#signTransactionBlock, }, + 'sui:signTransaction': { + version: '2.0.0', + signTransaction: this.#signTransaction, + }, 'sui:signAndExecuteTransactionBlock': { version: '1.0.0', signAndExecuteTransactionBlock: this.#signAndExecuteTransactionBlock, }, + 'sui:signAndExecuteTransaction': { + version: '2.0.0', + signAndExecuteTransaction: this.#signAndExecuteTransaction, + }, 'sui:signMessage': { version: '1.0.0', signMessage: this.#signMessage, @@ -238,9 +249,9 @@ export class SuiWallet implements Wallet { account, ...input }) => { - if (!isTransactionBlock(transactionBlock)) { + if (!isTransaction(transactionBlock)) { throw new Error( - 'Unexpect transaction format found. Ensure that you are using the `Transaction` class.', + 'Unexpected transaction format found. Ensure that you are using the `Transaction` class.', ); } @@ -259,10 +270,29 @@ export class SuiWallet implements Wallet { ); }; + #signTransaction: SuiSignTransactionMethod = async ({ transaction, account, ...input }) => { + return mapToPromise( + this.#send({ + type: 'sign-transaction-request', + transaction: { + ...input, + // account might be undefined if previous version of adapters is used + // in that case use the first account address + account: account?.address || this.#accounts[0]?.address || '', + transaction: await transaction.toJSON(), + }, + }), + ({ result: { signature, transactionBlockBytes: bytes } }) => ({ + signature, + bytes, + }), + ); + }; + #signAndExecuteTransactionBlock: SuiSignAndExecuteTransactionBlockMethod = async (input) => { - if (!isTransactionBlock(input.transactionBlock)) { + if (!isTransaction(input.transactionBlock)) { throw new Error( - 'Unexpect transaction format found. Ensure that you are using the `Transaction` class.', + 'Unexpected transaction format found. Ensure that you are using the `Transaction` class.', ); } @@ -282,6 +312,42 @@ export class SuiWallet implements Wallet { ); }; + #signAndExecuteTransaction: SuiSignAndExecuteTransactionMethod = async (input) => { + return mapToPromise( + this.#send({ + type: 'execute-transaction-request', + transaction: { + type: 'transaction', + data: await input.transaction.toJSON(), + options: { + showRawEffects: true, + showRawInput: true, + }, + // account might be undefined if previous version of adapters is used + // in that case use the first account address + account: input.account?.address || this.#accounts[0]?.address || '', + }, + }), + ({ result: { rawEffects, rawTransaction, digest } }) => { + const [ + { + txSignatures: [signature], + intentMessage: { value: bcsTransaction }, + }, + ] = bcs.SenderSignedData.parse(fromB64(rawTransaction!)); + + const bytes = bcs.TransactionData.serialize(bcsTransaction).toBase64(); + + return { + digest, + signature, + bytes, + effects: toB64(new Uint8Array(rawEffects!)), + }; + }, + ); + }; + #signMessage: SuiSignMessageMethod = async ({ message, account }) => { return mapToPromise( this.#send({ diff --git a/apps/wallet/src/shared/messaging/messages/payloads/MethodPayload.ts b/apps/wallet/src/shared/messaging/messages/payloads/MethodPayload.ts index 63204b3fb5361..6704cc582cd79 100644 --- a/apps/wallet/src/shared/messaging/messages/payloads/MethodPayload.ts +++ b/apps/wallet/src/shared/messaging/messages/payloads/MethodPayload.ts @@ -5,7 +5,6 @@ import { type AccountSourceSerializedUI } from '_src/background/account-sources/ import { type SerializedUIAccount } from '_src/background/accounts/Account'; import { type ZkLoginProvider } from '_src/background/accounts/zklogin/providers'; import { type Status } from '_src/background/legacy-accounts/storage-migration'; -import { type SerializedSignature } from '@mysten/sui.js/cryptography'; import { isBasePayload } from './BasePayload'; import type { Payload } from './Payload'; @@ -44,7 +43,7 @@ type MethodPayloads = { }; accountsCreatedResponse: { accounts: SerializedUIAccount[] }; signData: { data: string; id: string }; - signDataResponse: { signature: SerializedSignature }; + signDataResponse: { signature: string }; entitiesUpdated: { type: UIAccessibleEntityType }; getStorageMigrationStatus: null; storageMigrationStatus: { status: Status }; diff --git a/apps/wallet/src/shared/messaging/messages/payloads/transactions/ApprovalRequest.ts b/apps/wallet/src/shared/messaging/messages/payloads/transactions/ApprovalRequest.ts index 9d73093667c4d..588b0a69b61ad 100644 --- a/apps/wallet/src/shared/messaging/messages/payloads/transactions/ApprovalRequest.ts +++ b/apps/wallet/src/shared/messaging/messages/payloads/transactions/ApprovalRequest.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { type SignedTransaction } from '_src/ui/app/WalletSigner'; -import type { SuiTransactionBlockResponse } from '@mysten/sui.js/client'; +import type { SuiTransactionBlockResponse } from '@mysten/sui/client'; import { type SuiSignAndExecuteTransactionBlockInput, type SuiSignMessageOutput, diff --git a/apps/wallet/src/shared/messaging/messages/payloads/transactions/ExecuteTransactionResponse.ts b/apps/wallet/src/shared/messaging/messages/payloads/transactions/ExecuteTransactionResponse.ts index bf268075a8584..7681c5bbe5462 100644 --- a/apps/wallet/src/shared/messaging/messages/payloads/transactions/ExecuteTransactionResponse.ts +++ b/apps/wallet/src/shared/messaging/messages/payloads/transactions/ExecuteTransactionResponse.ts @@ -3,7 +3,7 @@ import { isBasePayload } from '_payloads'; import type { BasePayload, Payload } from '_payloads'; -import type { SuiTransactionBlockResponse } from '@mysten/sui.js/client'; +import type { SuiTransactionBlockResponse } from '@mysten/sui/client'; import { type SuiSignTransactionBlockOutput } from '@mysten/wallet-standard'; export interface ExecuteTransactionResponse extends BasePayload { diff --git a/apps/wallet/src/shared/messaging/messages/payloads/transactions/ui/TransactionRequestResponse.ts b/apps/wallet/src/shared/messaging/messages/payloads/transactions/ui/TransactionRequestResponse.ts index 7c24a9e7c70e1..94aa701f19b6c 100644 --- a/apps/wallet/src/shared/messaging/messages/payloads/transactions/ui/TransactionRequestResponse.ts +++ b/apps/wallet/src/shared/messaging/messages/payloads/transactions/ui/TransactionRequestResponse.ts @@ -4,7 +4,7 @@ import { isBasePayload } from '_payloads'; import type { BasePayload, Payload } from '_payloads'; import { type SignedTransaction } from '_src/ui/app/WalletSigner'; -import type { SuiTransactionBlockResponse } from '@mysten/sui.js/client'; +import type { SuiTransactionBlockResponse } from '@mysten/sui/client'; import { type SuiSignMessageOutput } from '@mysten/wallet-standard'; export interface TransactionRequestResponse extends BasePayload { diff --git a/apps/wallet/src/shared/sui-client.ts b/apps/wallet/src/shared/sui-client.ts index 284225e8959ff..50fe95b12f2b0 100644 --- a/apps/wallet/src/shared/sui-client.ts +++ b/apps/wallet/src/shared/sui-client.ts @@ -4,7 +4,7 @@ import networkEnv from '_src/background/NetworkEnv'; import { API_ENV, ENV_TO_API, type NetworkEnvType } from '_src/shared/api-env'; import { SentryHttpTransport } from '@mysten/core'; -import { SuiClient, SuiHTTPTransport } from '@mysten/sui.js/client'; +import { SuiClient, SuiHTTPTransport } from '@mysten/sui/client'; const suiClientPerNetwork = new Map(); const SENTRY_MONITORED_ENVS = [API_ENV.mainnet]; diff --git a/apps/wallet/src/shared/utils/from-exported-keypair.ts b/apps/wallet/src/shared/utils/from-exported-keypair.ts index a3e7cd667de19..868a4cd62dfa5 100644 --- a/apps/wallet/src/shared/utils/from-exported-keypair.ts +++ b/apps/wallet/src/shared/utils/from-exported-keypair.ts @@ -1,16 +1,16 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -import { type Keypair, type SignatureScheme } from '@mysten/sui.js/cryptography'; +import { type Keypair, type SignatureScheme } from '@mysten/sui/cryptography'; import { decodeSuiPrivateKey, LEGACY_PRIVATE_KEY_SIZE, PRIVATE_KEY_SIZE, -} from '@mysten/sui.js/cryptography/keypair'; -import { Ed25519Keypair } from '@mysten/sui.js/keypairs/ed25519'; -import { Secp256k1Keypair } from '@mysten/sui.js/keypairs/secp256k1'; -import { Secp256r1Keypair } from '@mysten/sui.js/keypairs/secp256r1'; -import { fromB64 } from '@mysten/sui.js/utils'; +} from '@mysten/sui/cryptography/keypair'; +import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519'; +import { Secp256k1Keypair } from '@mysten/sui/keypairs/secp256k1'; +import { Secp256r1Keypair } from '@mysten/sui/keypairs/secp256r1'; +import { fromB64 } from '@mysten/sui/utils'; /** * Wallet stored data might contain imported accounts with their keys stored in the previous format. diff --git a/apps/wallet/src/shared/utils/index.ts b/apps/wallet/src/shared/utils/index.ts index d47ca5869c790..04bdea8fbc6d7 100644 --- a/apps/wallet/src/shared/utils/index.ts +++ b/apps/wallet/src/shared/utils/index.ts @@ -4,7 +4,7 @@ import { useAppSelector } from '_hooks'; import { setAttributes } from '_src/shared/experimentation/features'; import { useGrowthBook } from '@growthbook/growthbook-react'; -import { fromB64, toB64 } from '@mysten/sui.js/utils'; +import { fromB64, toB64 } from '@mysten/sui/utils'; import * as Sentry from '@sentry/browser'; import { useEffect } from 'react'; import Browser from 'webextension-polyfill'; diff --git a/apps/wallet/src/ui/app/ApiProvider.ts b/apps/wallet/src/ui/app/ApiProvider.ts index 4f79d29c43b46..0b1fc004b3217 100644 --- a/apps/wallet/src/ui/app/ApiProvider.ts +++ b/apps/wallet/src/ui/app/ApiProvider.ts @@ -4,7 +4,7 @@ import { type AccountType, type SerializedUIAccount } from '_src/background/accounts/Account'; import { API_ENV } from '_src/shared/api-env'; import { getSuiClient } from '_src/shared/sui-client'; -import { type SuiClient } from '@mysten/sui.js/client'; +import { type SuiClient } from '@mysten/sui/client'; import type { BackgroundClient } from './background-client'; import { BackgroundServiceSigner } from './background-client/BackgroundServiceSigner'; diff --git a/apps/wallet/src/ui/app/LedgerSigner.ts b/apps/wallet/src/ui/app/LedgerSigner.ts index 84dc8a7ff9493..02fd9886f7749 100644 --- a/apps/wallet/src/ui/app/LedgerSigner.ts +++ b/apps/wallet/src/ui/app/LedgerSigner.ts @@ -2,13 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 import type SuiLedgerClient from '@mysten/ledgerjs-hw-app-sui'; -import { type SuiClient } from '@mysten/sui.js/client'; -import { - toSerializedSignature, - type SerializedSignature, - type SignatureScheme, -} from '@mysten/sui.js/cryptography'; -import { Ed25519PublicKey } from '@mysten/sui.js/keypairs/ed25519'; +import { type SuiClient } from '@mysten/sui/client'; +import { toSerializedSignature, type SignatureScheme } from '@mysten/sui/cryptography'; +import { Ed25519PublicKey } from '@mysten/sui/keypairs/ed25519'; import { WalletSigner } from './WalletSigner'; @@ -51,7 +47,7 @@ export class LedgerSigner extends WalletSigner { return new Ed25519PublicKey(publicKey); } - async signData(data: Uint8Array): Promise { + async signData(data: Uint8Array): Promise { const ledgerClient = await this.#initializeSuiLedgerClient(); const { signature } = await ledgerClient.signTransaction(this.#derivationPath, data); const publicKey = await this.getPublicKey(); diff --git a/apps/wallet/src/ui/app/QredoSigner.ts b/apps/wallet/src/ui/app/QredoSigner.ts index 3841cda34c4c6..3858baefed41f 100644 --- a/apps/wallet/src/ui/app/QredoSigner.ts +++ b/apps/wallet/src/ui/app/QredoSigner.ts @@ -8,13 +8,9 @@ import { type QredoAPI, type TransactionInfoResponse, } from '_src/shared/qredo-api'; -import { type SuiClient } from '@mysten/sui.js/client'; -import { - IntentScope, - messageWithIntent, - type SerializedSignature, -} from '@mysten/sui.js/cryptography'; -import { toB64 } from '@mysten/sui.js/utils'; +import { type SuiClient } from '@mysten/sui/client'; +import { messageWithIntent } from '@mysten/sui/cryptography'; +import { toB64 } from '@mysten/sui/utils'; import mitt from 'mitt'; import { WalletSigner } from './WalletSigner'; @@ -55,7 +51,7 @@ export class QredoSigner extends WalletSigner { return this.#qredoAccount.address; } - async signData(data: Uint8Array, clientIdentifier?: string): Promise { + async signData(data: Uint8Array, clientIdentifier?: string): Promise { let txInfo = await this.#createQredoTransaction(data, false, clientIdentifier); try { txInfo = await this.#pollForQredoTransaction( @@ -86,7 +82,7 @@ export class QredoSigner extends WalletSigner { signMessage: WalletSigner['signMessage'] = async (input, clientIdentifier) => { const signature = await this.signData( - messageWithIntent(IntentScope.PersonalMessage, input.message), + messageWithIntent('PersonalMessage', input.message), clientIdentifier, ); return { @@ -98,7 +94,7 @@ export class QredoSigner extends WalletSigner { signTransactionBlock: WalletSigner['signTransactionBlock'] = async (input, clientIdentifier) => { const transactionBlockBytes = await this.prepareTransactionBlock(input.transactionBlock); const signature = await this.signData( - messageWithIntent(IntentScope.TransactionData, transactionBlockBytes), + messageWithIntent('TransactionData', transactionBlockBytes), clientIdentifier, ); return { @@ -112,10 +108,7 @@ export class QredoSigner extends WalletSigner { clientIdentifier, ) => { let txInfo = await this.#createQredoTransaction( - messageWithIntent( - IntentScope.TransactionData, - await this.prepareTransactionBlock(transactionBlock), - ), + messageWithIntent('TransactionData', await this.prepareTransactionBlock(transactionBlock)), true, clientIdentifier, ); @@ -149,7 +142,7 @@ export class QredoSigner extends WalletSigner { if (!txInfo.txHash) { throw new Error(`Digest is not set in Qredo transaction ${txInfo.txID}`); } - return this.client.waitForTransactionBlock({ + return this.client.waitForTransaction({ digest: txInfo.txHash, options: options, }); diff --git a/apps/wallet/src/ui/app/WalletSigner.ts b/apps/wallet/src/ui/app/WalletSigner.ts index 2889a7eef0070..d5df590a6b0ab 100644 --- a/apps/wallet/src/ui/app/WalletSigner.ts +++ b/apps/wallet/src/ui/app/WalletSigner.ts @@ -1,17 +1,17 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -import { bcs } from '@mysten/sui.js/bcs'; +import { bcs } from '@mysten/sui/bcs'; import { type DryRunTransactionBlockResponse, type ExecuteTransactionRequestType, type SuiClient, type SuiTransactionBlockResponse, type SuiTransactionBlockResponseOptions, -} from '@mysten/sui.js/client'; -import { IntentScope, messageWithIntent } from '@mysten/sui.js/cryptography'; -import { isTransactionBlock, type TransactionBlock } from '@mysten/sui.js/transactions'; -import { fromB64, toB64 } from '@mysten/sui.js/utils'; +} from '@mysten/sui/client'; +import { messageWithIntent } from '@mysten/sui/cryptography'; +import { isTransaction, type Transaction } from '@mysten/sui/transactions'; +import { fromB64, toB64 } from '@mysten/sui/utils'; export type SignedTransaction = { transactionBlockBytes: string; @@ -39,10 +39,7 @@ export abstract class WalletSigner { clientIdentifier?: string, ): Promise { const signature = await this.signData( - messageWithIntent( - IntentScope.PersonalMessage, - bcs.ser(['vector', 'u8'], input.message).toBytes(), - ), + messageWithIntent('PersonalMessage', bcs.vector(bcs.u8()).serialize(input.message).toBytes()), ); return { @@ -51,10 +48,8 @@ export abstract class WalletSigner { }; } - protected async prepareTransactionBlock( - transactionBlock: Uint8Array | TransactionBlock | string, - ) { - if (isTransactionBlock(transactionBlock)) { + protected async prepareTransactionBlock(transactionBlock: Uint8Array | Transaction | string) { + if (isTransaction(transactionBlock)) { // If the sender has not yet been set on the transaction, then set it. // NOTE: This allows for signing transactions with mis-matched senders, which is important for sponsored transactions. transactionBlock.setSenderIfNotSet(await this.getAddress()); @@ -75,12 +70,12 @@ export abstract class WalletSigner { async signTransactionBlock( input: { - transactionBlock: Uint8Array | TransactionBlock; + transactionBlock: Uint8Array | Transaction; }, clientIdentifier?: string, ): Promise { const bytes = await this.prepareTransactionBlock(input.transactionBlock); - const signature = await this.signData(messageWithIntent(IntentScope.TransactionData, bytes)); + const signature = await this.signData(messageWithIntent('TransactionData', bytes)); return { transactionBlockBytes: toB64(bytes), @@ -90,7 +85,7 @@ export abstract class WalletSigner { async signAndExecuteTransactionBlock( input: { - transactionBlock: Uint8Array | TransactionBlock; + transactionBlock: Uint8Array | Transaction; options?: SuiTransactionBlockResponseOptions; requestType?: ExecuteTransactionRequestType; }, @@ -110,7 +105,7 @@ export abstract class WalletSigner { } async dryRunTransactionBlock(input: { - transactionBlock: TransactionBlock | string | Uint8Array; + transactionBlock: Transaction | string | Uint8Array; }): Promise { return this.client.dryRunTransactionBlock({ transactionBlock: await this.prepareTransactionBlock(input.transactionBlock), diff --git a/apps/wallet/src/ui/app/background-client/BackgroundServiceSigner.ts b/apps/wallet/src/ui/app/background-client/BackgroundServiceSigner.ts index 2e999d24959bc..7fec7c0fe1cda 100644 --- a/apps/wallet/src/ui/app/background-client/BackgroundServiceSigner.ts +++ b/apps/wallet/src/ui/app/background-client/BackgroundServiceSigner.ts @@ -2,8 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { type SerializedUIAccount } from '_src/background/accounts/Account'; -import { type SuiClient } from '@mysten/sui.js/client'; -import type { SerializedSignature } from '@mysten/sui.js/cryptography'; +import { type SuiClient } from '@mysten/sui/client'; import type { BackgroundClient } from '.'; import { WalletSigner } from '../WalletSigner'; @@ -22,7 +21,7 @@ export class BackgroundServiceSigner extends WalletSigner { return this.#account.address; } - signData(data: Uint8Array): Promise { + signData(data: Uint8Array): Promise { return this.#backgroundClient.signData(this.#account.id, data); } diff --git a/apps/wallet/src/ui/app/background-client/index.ts b/apps/wallet/src/ui/app/background-client/index.ts index 445458929488b..669dbcbcc1ae6 100644 --- a/apps/wallet/src/ui/app/background-client/index.ts +++ b/apps/wallet/src/ui/app/background-client/index.ts @@ -30,9 +30,8 @@ import { } from '_src/shared/messaging/messages/payloads/QredoConnect'; import { type SignedMessage, type SignedTransaction } from '_src/ui/app/WalletSigner'; import type { AppDispatch } from '_store'; -import { type SuiTransactionBlockResponse } from '@mysten/sui.js/client'; -import { type SerializedSignature } from '@mysten/sui.js/cryptography'; -import { toB64 } from '@mysten/sui.js/utils'; +import { type SuiTransactionBlockResponse } from '@mysten/sui/client'; +import { toB64 } from '@mysten/sui/utils'; import { type QueryKey } from '@tanstack/react-query'; import { lastValueFrom, map, take } from 'rxjs'; @@ -151,7 +150,7 @@ export class BackgroundClient { ); } - public signData(addressOrID: string, data: Uint8Array): Promise { + public signData(addressOrID: string, data: Uint8Array): Promise { return lastValueFrom( this.sendMessage( createMessage>({ diff --git a/apps/wallet/src/ui/app/components/AccountListItem.tsx b/apps/wallet/src/ui/app/components/AccountListItem.tsx index 37dd27cdcf9f4..9052cffdb3546 100644 --- a/apps/wallet/src/ui/app/components/AccountListItem.tsx +++ b/apps/wallet/src/ui/app/components/AccountListItem.tsx @@ -4,7 +4,7 @@ import { useResolveSuiNSName } from '_app/hooks/useAppResolveSuinsName'; import { type SerializedUIAccount } from '_src/background/accounts/Account'; import { Check12, Copy12 } from '@mysten/icons'; -import { formatAddress } from '@mysten/sui.js/utils'; +import { formatAddress } from '@mysten/sui/utils'; import { useCopyToClipboard } from '../hooks/useCopyToClipboard'; import { Text } from '../shared/text'; diff --git a/apps/wallet/src/ui/app/components/WalletListSelectItem.tsx b/apps/wallet/src/ui/app/components/WalletListSelectItem.tsx index 2799d695ba624..fe583136f5000 100644 --- a/apps/wallet/src/ui/app/components/WalletListSelectItem.tsx +++ b/apps/wallet/src/ui/app/components/WalletListSelectItem.tsx @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { CheckFill16, XFill16 } from '@mysten/icons'; -import { formatAddress } from '@mysten/sui.js/utils'; +import { formatAddress } from '@mysten/sui/utils'; import { cva, cx, type VariantProps } from 'class-variance-authority'; import { useEffect, useRef } from 'react'; diff --git a/apps/wallet/src/ui/app/components/accounts/AccountItem.tsx b/apps/wallet/src/ui/app/components/accounts/AccountItem.tsx index b4f77f33de03a..629920e34da76 100644 --- a/apps/wallet/src/ui/app/components/accounts/AccountItem.tsx +++ b/apps/wallet/src/ui/app/components/accounts/AccountItem.tsx @@ -4,7 +4,7 @@ import { useResolveSuiNSName } from '_app/hooks/useAppResolveSuinsName'; import { Text } from '_src/ui/app/shared/text'; import { ArrowUpRight12, Copy12 } from '@mysten/icons'; -import { formatAddress } from '@mysten/sui.js/utils'; +import { formatAddress } from '@mysten/sui/utils'; import cn from 'clsx'; import { forwardRef, type ReactNode } from 'react'; diff --git a/apps/wallet/src/ui/app/components/accounts/AccountItemApproveConnection.tsx b/apps/wallet/src/ui/app/components/accounts/AccountItemApproveConnection.tsx index e42c0b20b1810..1972a4ce62e7b 100644 --- a/apps/wallet/src/ui/app/components/accounts/AccountItemApproveConnection.tsx +++ b/apps/wallet/src/ui/app/components/accounts/AccountItemApproveConnection.tsx @@ -7,7 +7,7 @@ import { LockUnlockButton } from '_components/accounts/LockUnlockButton'; import { useUnlockAccount } from '_components/accounts/UnlockAccountContext'; import { type SerializedUIAccount } from '_src/background/accounts/Account'; import { CheckFill16 } from '@mysten/icons'; -import { formatAddress } from '@mysten/sui.js/utils'; +import { formatAddress } from '@mysten/sui/utils'; import clsx from 'clsx'; interface Props { diff --git a/apps/wallet/src/ui/app/components/active-coins-card/index.tsx b/apps/wallet/src/ui/app/components/active-coins-card/index.tsx index 6844385876a7d..3608c1f72cf9b 100644 --- a/apps/wallet/src/ui/app/components/active-coins-card/index.tsx +++ b/apps/wallet/src/ui/app/components/active-coins-card/index.tsx @@ -6,7 +6,7 @@ import Loading from '_components/loading'; import { filterAndSortTokenBalances } from '_helpers'; import { useCoinsReFetchingConfig } from '_hooks'; import { useSuiClientQuery } from '@mysten/dapp-kit'; -import { SUI_TYPE_ARG } from '@mysten/sui.js/utils'; +import { SUI_TYPE_ARG } from '@mysten/sui/utils'; import { Link } from 'react-router-dom'; import { CoinItem } from './CoinItem'; diff --git a/apps/wallet/src/ui/app/components/address-input/index.tsx b/apps/wallet/src/ui/app/components/address-input/index.tsx index c448f44ae6f4d..b4aa1cc01ed0d 100644 --- a/apps/wallet/src/ui/app/components/address-input/index.tsx +++ b/apps/wallet/src/ui/app/components/address-input/index.tsx @@ -5,7 +5,7 @@ import { Text } from '_app/shared/text'; import Alert from '_src/ui/app/components/alert'; import { useSuiClient } from '@mysten/dapp-kit'; import { QrCode, X12 } from '@mysten/icons'; -import { isValidSuiAddress } from '@mysten/sui.js/utils'; +import { isValidSuiAddress } from '@mysten/sui/utils'; import { useQuery } from '@tanstack/react-query'; import { cx } from 'class-variance-authority'; import { useField, useFormikContext } from 'formik'; diff --git a/apps/wallet/src/ui/app/components/address-input/validation.ts b/apps/wallet/src/ui/app/components/address-input/validation.ts index fde86dcd6e749..6cd654249013d 100644 --- a/apps/wallet/src/ui/app/components/address-input/validation.ts +++ b/apps/wallet/src/ui/app/components/address-input/validation.ts @@ -3,8 +3,8 @@ import { isSuiNSName, useSuiNSEnabled } from '@mysten/core'; import { useSuiClient } from '@mysten/dapp-kit'; -import { type SuiClient } from '@mysten/sui.js/client'; -import { isValidSuiAddress } from '@mysten/sui.js/utils'; +import { type SuiClient } from '@mysten/sui/client'; +import { isValidSuiAddress } from '@mysten/sui/utils'; import { useMemo } from 'react'; import * as Yup from 'yup'; diff --git a/apps/wallet/src/ui/app/components/coin-icon/index.tsx b/apps/wallet/src/ui/app/components/coin-icon/index.tsx index 280a8077b1d7f..4f11b17f47b26 100644 --- a/apps/wallet/src/ui/app/components/coin-icon/index.tsx +++ b/apps/wallet/src/ui/app/components/coin-icon/index.tsx @@ -4,7 +4,7 @@ import { ImageIcon } from '_app/shared/image-icon'; import { useCoinMetadata } from '@mysten/core'; import { Sui, Unstaked } from '@mysten/icons'; -import { SUI_TYPE_ARG } from '@mysten/sui.js/utils'; +import { SUI_TYPE_ARG } from '@mysten/sui/utils'; import { cva, type VariantProps } from 'class-variance-authority'; const imageStyle = cva(['rounded-full flex'], { diff --git a/apps/wallet/src/ui/app/components/explorer-link/index.tsx b/apps/wallet/src/ui/app/components/explorer-link/index.tsx index fcfa9f16ee614..a1f9244e5c4dd 100644 --- a/apps/wallet/src/ui/app/components/explorer-link/index.tsx +++ b/apps/wallet/src/ui/app/components/explorer-link/index.tsx @@ -3,7 +3,7 @@ import ExternalLink from '_components/external-link'; import { ArrowUpRight16 } from '@mysten/icons'; -import { formatAddress } from '@mysten/sui.js/utils'; +import { formatAddress } from '@mysten/sui/utils'; import type { ReactNode } from 'react'; import { useExplorerLink, type ExplorerLinkConfig } from '../../hooks/useExplorerLink'; diff --git a/apps/wallet/src/ui/app/components/ledger/LedgerAccountRow.tsx b/apps/wallet/src/ui/app/components/ledger/LedgerAccountRow.tsx index 9aec96bc82fb7..b494572f48a89 100644 --- a/apps/wallet/src/ui/app/components/ledger/LedgerAccountRow.tsx +++ b/apps/wallet/src/ui/app/components/ledger/LedgerAccountRow.tsx @@ -6,7 +6,7 @@ import { Text } from '_src/ui/app/shared/text'; import { useFormatCoin } from '@mysten/core'; import { useSuiClientQuery } from '@mysten/dapp-kit'; import { CheckFill16 } from '@mysten/icons'; -import { formatAddress, SUI_TYPE_ARG } from '@mysten/sui.js/utils'; +import { formatAddress, SUI_TYPE_ARG } from '@mysten/sui/utils'; import cl from 'clsx'; import { useCoinsReFetchingConfig } from '../../hooks'; diff --git a/apps/wallet/src/ui/app/components/ledger/useDeriveLedgerAccounts.ts b/apps/wallet/src/ui/app/components/ledger/useDeriveLedgerAccounts.ts index 0e733390312fe..c67a9e3216955 100644 --- a/apps/wallet/src/ui/app/components/ledger/useDeriveLedgerAccounts.ts +++ b/apps/wallet/src/ui/app/components/ledger/useDeriveLedgerAccounts.ts @@ -3,7 +3,7 @@ import { type LedgerAccountSerializedUI } from '_src/background/accounts/LedgerAccount'; import type SuiLedgerClient from '@mysten/ledgerjs-hw-app-sui'; -import { Ed25519PublicKey } from '@mysten/sui.js/keypairs/ed25519'; +import { Ed25519PublicKey } from '@mysten/sui/keypairs/ed25519'; import { useQuery, type UseQueryOptions } from '@tanstack/react-query'; import { useSuiLedgerClient } from './SuiLedgerClientProvider'; diff --git a/apps/wallet/src/ui/app/components/menu/content/VerifyLedgerConnectionStatus.tsx b/apps/wallet/src/ui/app/components/menu/content/VerifyLedgerConnectionStatus.tsx index 6e014d3d76b86..c78faa1af2f16 100644 --- a/apps/wallet/src/ui/app/components/menu/content/VerifyLedgerConnectionStatus.tsx +++ b/apps/wallet/src/ui/app/components/menu/content/VerifyLedgerConnectionStatus.tsx @@ -8,7 +8,7 @@ import { import { Link } from '_src/ui/app/shared/Link'; import { Text } from '_src/ui/app/shared/text'; import { Check12, X12 } from '@mysten/icons'; -import { Ed25519PublicKey } from '@mysten/sui.js/keypairs/ed25519'; +import { Ed25519PublicKey } from '@mysten/sui/keypairs/ed25519'; import { useState } from 'react'; import toast from 'react-hot-toast'; diff --git a/apps/wallet/src/ui/app/components/nft-display/Kiosk.tsx b/apps/wallet/src/ui/app/components/nft-display/Kiosk.tsx index a435ee88f755b..39ee906e1a2c6 100644 --- a/apps/wallet/src/ui/app/components/nft-display/Kiosk.tsx +++ b/apps/wallet/src/ui/app/components/nft-display/Kiosk.tsx @@ -1,7 +1,7 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 import { getKioskIdFromOwnerCap, hasDisplayData, useGetKioskContents } from '@mysten/core'; -import { type SuiObjectResponse } from '@mysten/sui.js/client'; +import { type SuiObjectResponse } from '@mysten/sui/client'; import cl from 'clsx'; import { useActiveAddress } from '../../hooks'; diff --git a/apps/wallet/src/ui/app/components/nft-display/index.tsx b/apps/wallet/src/ui/app/components/nft-display/index.tsx index 4e776f441c95e..bfbaee0e4e1c0 100644 --- a/apps/wallet/src/ui/app/components/nft-display/index.tsx +++ b/apps/wallet/src/ui/app/components/nft-display/index.tsx @@ -7,7 +7,7 @@ import { NftImage, type NftImageProps } from '_components/nft-display/NftImage'; import { useFileExtensionType, useGetNFTMeta } from '_hooks'; import { isKioskOwnerToken, useGetObject } from '@mysten/core'; import { useKioskClient } from '@mysten/core/src/hooks/useKioskClient'; -import { formatAddress } from '@mysten/sui.js/utils'; +import { formatAddress } from '@mysten/sui/utils'; import { cva } from 'class-variance-authority'; import type { VariantProps } from 'class-variance-authority'; diff --git a/apps/wallet/src/ui/app/components/receipt-card/StakeTxnCard.tsx b/apps/wallet/src/ui/app/components/receipt-card/StakeTxnCard.tsx index a39d455be9618..e660bb49d4b15 100644 --- a/apps/wallet/src/ui/app/components/receipt-card/StakeTxnCard.tsx +++ b/apps/wallet/src/ui/app/components/receipt-card/StakeTxnCard.tsx @@ -15,8 +15,8 @@ import { useGetTimeBeforeEpochNumber, useGetValidatorsApy, } from '@mysten/core'; -import type { SuiEvent } from '@mysten/sui.js/client'; -import { SUI_TYPE_ARG } from '@mysten/sui.js/utils'; +import type { SuiEvent } from '@mysten/sui/client'; +import { SUI_TYPE_ARG } from '@mysten/sui/utils'; import { Card } from '../../shared/transaction-summary/Card'; diff --git a/apps/wallet/src/ui/app/components/receipt-card/TxnAddressLink.tsx b/apps/wallet/src/ui/app/components/receipt-card/TxnAddressLink.tsx index ceae6c4a6019f..92880053f96c9 100644 --- a/apps/wallet/src/ui/app/components/receipt-card/TxnAddressLink.tsx +++ b/apps/wallet/src/ui/app/components/receipt-card/TxnAddressLink.tsx @@ -4,7 +4,7 @@ import ExplorerLink from '_components/explorer-link'; import { ExplorerLinkType } from '_components/explorer-link/ExplorerLinkType'; import { isSuiNSName } from '@mysten/core'; -import { formatAddress } from '@mysten/sui.js/utils'; +import { formatAddress } from '@mysten/sui/utils'; type TxnAddressLinkProps = { address: string; diff --git a/apps/wallet/src/ui/app/components/receipt-card/TxnGasSummary.tsx b/apps/wallet/src/ui/app/components/receipt-card/TxnGasSummary.tsx index 3a6dea22374fa..e8fc1b6b482c8 100644 --- a/apps/wallet/src/ui/app/components/receipt-card/TxnGasSummary.tsx +++ b/apps/wallet/src/ui/app/components/receipt-card/TxnGasSummary.tsx @@ -4,7 +4,7 @@ import { GAS_TYPE_ARG } from '_redux/slices/sui-objects/Coin'; import { Text } from '_src/ui/app/shared/text'; import { useFormatCoin } from '@mysten/core'; -import type { GasCostSummary } from '@mysten/sui.js/client'; +import type { GasCostSummary } from '@mysten/sui/client'; type TxnGasSummaryProps = { gasSummary?: GasCostSummary; diff --git a/apps/wallet/src/ui/app/components/receipt-card/UnstakeTxnCard.tsx b/apps/wallet/src/ui/app/components/receipt-card/UnstakeTxnCard.tsx index d6326937373c5..14fee4c651a4f 100644 --- a/apps/wallet/src/ui/app/components/receipt-card/UnstakeTxnCard.tsx +++ b/apps/wallet/src/ui/app/components/receipt-card/UnstakeTxnCard.tsx @@ -5,8 +5,8 @@ import { ValidatorLogo } from '_app/staking/validators/ValidatorLogo'; import { TxnAmount } from '_components/receipt-card/TxnAmount'; import { Text } from '_src/ui/app/shared/text'; import { useFormatCoin } from '@mysten/core'; -import type { SuiEvent } from '@mysten/sui.js/client'; -import { SUI_TYPE_ARG } from '@mysten/sui.js/utils'; +import type { SuiEvent } from '@mysten/sui/client'; +import { SUI_TYPE_ARG } from '@mysten/sui/utils'; import { Card } from '../../shared/transaction-summary/Card'; diff --git a/apps/wallet/src/ui/app/components/receipt-card/index.tsx b/apps/wallet/src/ui/app/components/receipt-card/index.tsx index ac59bcbf6efc4..e0c78ff5c921d 100644 --- a/apps/wallet/src/ui/app/components/receipt-card/index.tsx +++ b/apps/wallet/src/ui/app/components/receipt-card/index.tsx @@ -3,7 +3,7 @@ import { useRecognizedPackages } from '_src/ui/app/hooks/useRecognizedPackages'; import { useTransactionSummary } from '@mysten/core'; -import { type SuiTransactionBlockResponse } from '@mysten/sui.js/client'; +import { type SuiTransactionBlockResponse } from '@mysten/sui/client'; import { DateCard } from '../../shared/date-card'; import { TransactionSummary } from '../../shared/transaction-summary'; diff --git a/apps/wallet/src/ui/app/components/sui-apps/DisconnectApp.tsx b/apps/wallet/src/ui/app/components/sui-apps/DisconnectApp.tsx index 89cea26104dd8..98db8d2093eab 100644 --- a/apps/wallet/src/ui/app/components/sui-apps/DisconnectApp.tsx +++ b/apps/wallet/src/ui/app/components/sui-apps/DisconnectApp.tsx @@ -5,7 +5,7 @@ import Overlay from '_components/overlay'; import { useAppSelector } from '_hooks'; import { permissionsSelectors } from '_redux/slices/permissions'; import { ampli } from '_src/shared/analytics/ampli'; -import { formatAddress } from '@mysten/sui.js/utils'; +import { formatAddress } from '@mysten/sui/utils'; import { useMutation } from '@tanstack/react-query'; import { useEffect, useMemo, useState } from 'react'; import { toast } from 'react-hot-toast'; diff --git a/apps/wallet/src/ui/app/components/transactions-card/TxnActionLabel.tsx b/apps/wallet/src/ui/app/components/transactions-card/TxnActionLabel.tsx index f88be8c5b35da..566a119ca3980 100644 --- a/apps/wallet/src/ui/app/components/transactions-card/TxnActionLabel.tsx +++ b/apps/wallet/src/ui/app/components/transactions-card/TxnActionLabel.tsx @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { Text } from '_app/shared/text'; -import { formatAddress } from '@mysten/sui.js/utils'; +import { formatAddress } from '@mysten/sui/utils'; type TxnTypeProps = { address: string; diff --git a/apps/wallet/src/ui/app/components/transactions-card/index.tsx b/apps/wallet/src/ui/app/components/transactions-card/index.tsx index 3a4d4f7bd75ab..fcf767842d5a7 100644 --- a/apps/wallet/src/ui/app/components/transactions-card/index.tsx +++ b/apps/wallet/src/ui/app/components/transactions-card/index.tsx @@ -6,7 +6,7 @@ import { Text } from '_app/shared/text'; import { useGetTxnRecipientAddress } from '_hooks'; import { useRecognizedPackages } from '_src/ui/app/hooks/useRecognizedPackages'; import { getLabel, useTransactionSummary } from '@mysten/core'; -import type { SuiTransactionBlockResponse } from '@mysten/sui.js/client'; +import type { SuiTransactionBlockResponse } from '@mysten/sui/client'; import { Link } from 'react-router-dom'; import { TxnTypeLabel } from './TxnActionLabel'; diff --git a/apps/wallet/src/ui/app/helpers/checkStakingTxn.ts b/apps/wallet/src/ui/app/helpers/checkStakingTxn.ts index 7ed326dab8750..940ed4faed293 100644 --- a/apps/wallet/src/ui/app/helpers/checkStakingTxn.ts +++ b/apps/wallet/src/ui/app/helpers/checkStakingTxn.ts @@ -1,7 +1,7 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -import type { SuiTransactionBlockResponse } from '@mysten/sui.js/client'; +import type { SuiTransactionBlockResponse } from '@mysten/sui/client'; // TODO: Support programmable transactions: export function checkStakingTxn(_txn: SuiTransactionBlockResponse) { diff --git a/apps/wallet/src/ui/app/helpers/filterAndSortTokenBalances.ts b/apps/wallet/src/ui/app/helpers/filterAndSortTokenBalances.ts index 576a1d12acbf5..47ae3b0f3ad9b 100644 --- a/apps/wallet/src/ui/app/helpers/filterAndSortTokenBalances.ts +++ b/apps/wallet/src/ui/app/helpers/filterAndSortTokenBalances.ts @@ -1,7 +1,7 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -import { type CoinBalance } from '@mysten/sui.js/client'; +import { type CoinBalance } from '@mysten/sui/client'; // Sort tokens by symbol and total balance // Move this to the API backend diff --git a/apps/wallet/src/ui/app/helpers/getAmount.ts b/apps/wallet/src/ui/app/helpers/getAmount.ts index b6bc94e1e5b06..d88c1026f1e35 100644 --- a/apps/wallet/src/ui/app/helpers/getAmount.ts +++ b/apps/wallet/src/ui/app/helpers/getAmount.ts @@ -1,7 +1,7 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -import type { SuiEvent, SuiTransactionBlockKind, TransactionEffects } from '@mysten/sui.js/client'; +import type { SuiEvent, SuiTransactionBlockKind, TransactionEffects } from '@mysten/sui/client'; type FormattedBalance = { amount?: number | null; diff --git a/apps/wallet/src/ui/app/helpers/getEventsSummary.ts b/apps/wallet/src/ui/app/helpers/getEventsSummary.ts index 16744e090bd6d..db984b2469dee 100644 --- a/apps/wallet/src/ui/app/helpers/getEventsSummary.ts +++ b/apps/wallet/src/ui/app/helpers/getEventsSummary.ts @@ -8,7 +8,7 @@ export {}; // getTransferObjectEvent, // isEventType, // type TransactionEvents, -// } from '@mysten/sui.js'; +// } from '@mysten/sui'; // export type CoinsMetaProps = { // amount: number; diff --git a/apps/wallet/src/ui/app/helpers/validation/privateKeyValidation.ts b/apps/wallet/src/ui/app/helpers/validation/privateKeyValidation.ts index 69f4c53dbe764..694ca95df664c 100644 --- a/apps/wallet/src/ui/app/helpers/validation/privateKeyValidation.ts +++ b/apps/wallet/src/ui/app/helpers/validation/privateKeyValidation.ts @@ -1,7 +1,7 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -import { decodeSuiPrivateKey } from '@mysten/sui.js/cryptography/keypair'; +import { decodeSuiPrivateKey } from '@mysten/sui/cryptography/keypair'; import { z } from 'zod'; export const privateKeyValidation = z diff --git a/apps/wallet/src/ui/app/hooks/deepbook/useGetEstimate.ts b/apps/wallet/src/ui/app/hooks/deepbook/useGetEstimate.ts index c4822df88d03c..2810a6396cfb2 100644 --- a/apps/wallet/src/ui/app/hooks/deepbook/useGetEstimate.ts +++ b/apps/wallet/src/ui/app/hooks/deepbook/useGetEstimate.ts @@ -7,8 +7,8 @@ import { DEEPBOOK_KEY, WALLET_FEES_PERCENTAGE } from '_pages/swap/constants'; import { useDeepBookContext } from '_shared/deepBook/context'; import { useSuiClient } from '@mysten/dapp-kit'; import { type DeepBookClient } from '@mysten/deepbook'; -import { type CoinStruct, type SuiClient } from '@mysten/sui.js/client'; -import { TransactionBlock } from '@mysten/sui.js/transactions'; +import { type CoinStruct, type SuiClient } from '@mysten/sui/client'; +import { Transaction } from '@mysten/sui/transactions'; import * as Sentry from '@sentry/react'; import { useQuery, useQueryClient } from '@tanstack/react-query'; import BigNumber from 'bignumber.js'; @@ -144,7 +144,7 @@ async function getPlaceMarketOrderTxn({ quoteConversionRate: number; lotSize: string; }) { - const txb = new TransactionBlock(); + const txb = new Transaction(); const accountCap = accountCapId || deepBookClient.createAccountCap(txb); let walletFeeCoin; diff --git a/apps/wallet/src/ui/app/hooks/deepbook/useRecognizedCoins.ts b/apps/wallet/src/ui/app/hooks/deepbook/useRecognizedCoins.ts index b0f6dafbb7fd8..7280d199ce6dc 100644 --- a/apps/wallet/src/ui/app/hooks/deepbook/useRecognizedCoins.ts +++ b/apps/wallet/src/ui/app/hooks/deepbook/useRecognizedCoins.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { useDeepBookConfigs } from '_app/hooks/deepbook/useDeepBookConfigs'; import { useDeepBookContext } from '_shared/deepBook/context'; -import { SUI_TYPE_ARG } from '@mysten/sui.js/utils'; +import { SUI_TYPE_ARG } from '@mysten/sui/utils'; export function useRecognizedCoins() { const coinsMap = useDeepBookContext().configs.coinsMap; diff --git a/apps/wallet/src/ui/app/hooks/useAppResolveSuinsName.ts b/apps/wallet/src/ui/app/hooks/useAppResolveSuinsName.ts index 052709eb549b6..44f8e1813179e 100644 --- a/apps/wallet/src/ui/app/hooks/useAppResolveSuinsName.ts +++ b/apps/wallet/src/ui/app/hooks/useAppResolveSuinsName.ts @@ -1,7 +1,7 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 import { useFeatureIsOn } from '@growthbook/growthbook-react'; -import { normalizeSuiNSName } from '@mysten/sui.js/utils'; +import { normalizeSuiNSName } from '@mysten/sui/utils'; import { useResolveSuiNSName as useResolveSuiNSNameCore } from '../../../../../core'; diff --git a/apps/wallet/src/ui/app/hooks/useGetAllCoins.ts b/apps/wallet/src/ui/app/hooks/useGetAllCoins.ts index 795513a78f525..6e9608111669b 100644 --- a/apps/wallet/src/ui/app/hooks/useGetAllCoins.ts +++ b/apps/wallet/src/ui/app/hooks/useGetAllCoins.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { useSuiClient } from '@mysten/dapp-kit'; -import type { CoinStruct, PaginatedCoins } from '@mysten/sui.js/client'; +import type { CoinStruct, PaginatedCoins } from '@mysten/sui/client'; import { useQuery } from '@tanstack/react-query'; const MAX_COINS_PER_REQUEST = 100; diff --git a/apps/wallet/src/ui/app/hooks/useGetNFTs.ts b/apps/wallet/src/ui/app/hooks/useGetNFTs.ts index 19fbfd2da647e..d958890366d12 100644 --- a/apps/wallet/src/ui/app/hooks/useGetNFTs.ts +++ b/apps/wallet/src/ui/app/hooks/useGetNFTs.ts @@ -3,7 +3,7 @@ import { hasDisplayData, isKioskOwnerToken, useGetOwnedObjects } from '@mysten/core'; import { useKioskClient } from '@mysten/core/src/hooks/useKioskClient'; -import { type SuiObjectData } from '@mysten/sui.js/client'; +import { type SuiObjectData } from '@mysten/sui/client'; import { useMemo } from 'react'; import { useBuyNLargeAsset } from '../components/buynlarge/useBuyNLargeAsset'; diff --git a/apps/wallet/src/ui/app/hooks/useGetTransferAmount.ts b/apps/wallet/src/ui/app/hooks/useGetTransferAmount.ts index 01046876538be..aa42cc850e1d4 100644 --- a/apps/wallet/src/ui/app/hooks/useGetTransferAmount.ts +++ b/apps/wallet/src/ui/app/hooks/useGetTransferAmount.ts @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 import { getAmount } from '_helpers'; -import type { SuiTransactionBlockResponse } from '@mysten/sui.js/client'; -import { SUI_TYPE_ARG } from '@mysten/sui.js/utils'; +import type { SuiTransactionBlockResponse } from '@mysten/sui/client'; +import { SUI_TYPE_ARG } from '@mysten/sui/utils'; import { useMemo } from 'react'; export function useGetTransferAmount({ diff --git a/apps/wallet/src/ui/app/hooks/useGetTxnRecipientAddress.ts b/apps/wallet/src/ui/app/hooks/useGetTxnRecipientAddress.ts index 0809910bf2319..45f5607cc7800 100644 --- a/apps/wallet/src/ui/app/hooks/useGetTxnRecipientAddress.ts +++ b/apps/wallet/src/ui/app/hooks/useGetTxnRecipientAddress.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { getAmount } from '_helpers'; -import { type SuiTransactionBlockResponse } from '@mysten/sui.js/client'; +import { type SuiTransactionBlockResponse } from '@mysten/sui/client'; import { useMemo } from 'react'; type Props = { diff --git a/apps/wallet/src/ui/app/hooks/useMediaUrl.ts b/apps/wallet/src/ui/app/hooks/useMediaUrl.ts index dd151fc7264f2..407ea1164d609 100644 --- a/apps/wallet/src/ui/app/hooks/useMediaUrl.ts +++ b/apps/wallet/src/ui/app/hooks/useMediaUrl.ts @@ -1,7 +1,7 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -import type { SuiParsedData } from '@mysten/sui.js/client'; +import type { SuiParsedData } from '@mysten/sui/client'; import { useMemo } from 'react'; export const parseIpfsUrl = (ipfsUrl: string) => diff --git a/apps/wallet/src/ui/app/hooks/useNFTBasicData.ts b/apps/wallet/src/ui/app/hooks/useNFTBasicData.ts index 8cd78e4faa65f..67973a7548913 100644 --- a/apps/wallet/src/ui/app/hooks/useNFTBasicData.ts +++ b/apps/wallet/src/ui/app/hooks/useNFTBasicData.ts @@ -1,7 +1,7 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -import type { SuiObjectData } from '@mysten/sui.js/client'; +import type { SuiObjectData } from '@mysten/sui/client'; import useFileExtensionType from './useFileExtensionType'; import useMediaUrl from './useMediaUrl'; diff --git a/apps/wallet/src/ui/app/hooks/useQueryTransactionsByAddress.ts b/apps/wallet/src/ui/app/hooks/useQueryTransactionsByAddress.ts index 571046865a9e9..f493a18fcb61e 100644 --- a/apps/wallet/src/ui/app/hooks/useQueryTransactionsByAddress.ts +++ b/apps/wallet/src/ui/app/hooks/useQueryTransactionsByAddress.ts @@ -4,7 +4,7 @@ import { FEATURES } from '_src/shared/experimentation/features'; import { useFeatureValue } from '@growthbook/growthbook-react'; import { useSuiClient } from '@mysten/dapp-kit'; -import { type SuiTransactionBlockResponse } from '@mysten/sui.js/client'; +import { type SuiTransactionBlockResponse } from '@mysten/sui/client'; import { useQuery } from '@tanstack/react-query'; export function useQueryTransactionsByAddress(address: string | null) { diff --git a/apps/wallet/src/ui/app/hooks/useRecognizedPackages.ts b/apps/wallet/src/ui/app/hooks/useRecognizedPackages.ts index c8215015794ad..f66a38d5dcad6 100644 --- a/apps/wallet/src/ui/app/hooks/useRecognizedPackages.ts +++ b/apps/wallet/src/ui/app/hooks/useRecognizedPackages.ts @@ -3,7 +3,7 @@ import { API_ENV } from '_src/shared/api-env'; import { useFeatureValue } from '@growthbook/growthbook-react'; -import { SUI_FRAMEWORK_ADDRESS, SUI_SYSTEM_ADDRESS } from '@mysten/sui.js/utils'; +import { SUI_FRAMEWORK_ADDRESS, SUI_SYSTEM_ADDRESS } from '@mysten/sui/utils'; import useAppSelector from './useAppSelector'; diff --git a/apps/wallet/src/ui/app/hooks/useResolveVideo.ts b/apps/wallet/src/ui/app/hooks/useResolveVideo.ts index cd66425535fbf..99f01ce8be090 100644 --- a/apps/wallet/src/ui/app/hooks/useResolveVideo.ts +++ b/apps/wallet/src/ui/app/hooks/useResolveVideo.ts @@ -1,7 +1,7 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -import { type SuiObjectResponse } from '@mysten/sui.js/client'; +import { type SuiObjectResponse } from '@mysten/sui/client'; import { useRecognizedPackages } from './useRecognizedPackages'; diff --git a/apps/wallet/src/ui/app/hooks/useSortedCoinsByCategories.ts b/apps/wallet/src/ui/app/hooks/useSortedCoinsByCategories.ts index ddc860dc31178..3f5c543dfb696 100644 --- a/apps/wallet/src/ui/app/hooks/useSortedCoinsByCategories.ts +++ b/apps/wallet/src/ui/app/hooks/useSortedCoinsByCategories.ts @@ -3,8 +3,8 @@ import { usePinnedCoinTypes } from '_app/hooks/usePinnedCoinTypes'; import { useRecognizedPackages } from '_app/hooks/useRecognizedPackages'; -import { type CoinBalance as CoinBalanceType } from '@mysten/sui.js/client'; -import { SUI_TYPE_ARG } from '@mysten/sui.js/utils'; +import { type CoinBalance as CoinBalanceType } from '@mysten/sui/client'; +import { SUI_TYPE_ARG } from '@mysten/sui/utils'; import { useMemo } from 'react'; function sortCoins(balances: CoinBalanceType[]) { diff --git a/apps/wallet/src/ui/app/hooks/useTransactionData.ts b/apps/wallet/src/ui/app/hooks/useTransactionData.ts index 56d17b389d0c8..ccb3d61074311 100644 --- a/apps/wallet/src/ui/app/hooks/useTransactionData.ts +++ b/apps/wallet/src/ui/app/hooks/useTransactionData.ts @@ -3,35 +3,32 @@ import { useFormatCoin } from '@mysten/core'; import { useSuiClient } from '@mysten/dapp-kit'; -import { TransactionBlock } from '@mysten/sui.js/transactions'; -import { SUI_TYPE_ARG } from '@mysten/sui.js/utils'; +import { Transaction } from '@mysten/sui/transactions'; +import { SUI_TYPE_ARG } from '@mysten/sui/utils'; import { useQuery } from '@tanstack/react-query'; -export function useTransactionData(sender?: string | null, transaction?: TransactionBlock | null) { +export function useTransactionData(sender?: string | null, transaction?: Transaction | null) { const client = useSuiClient(); return useQuery({ // eslint-disable-next-line @tanstack/query/exhaustive-deps queryKey: ['transaction-data', transaction?.serialize()], queryFn: async () => { - const clonedTransaction = new TransactionBlock(transaction!); + const clonedTransaction = Transaction.from(transaction!); if (sender) { clonedTransaction.setSenderIfNotSet(sender); } // Build the transaction to bytes, which will ensure that the transaction data is fully populated: await clonedTransaction!.build({ client }); - return clonedTransaction!.blockData; + return clonedTransaction!.getData(); }, enabled: !!transaction, }); } -export function useTransactionGasBudget( - sender?: string | null, - transaction?: TransactionBlock | null, -) { +export function useTransactionGasBudget(sender?: string | null, transaction?: Transaction | null) { const { data, ...rest } = useTransactionData(sender, transaction); - const [formattedGas] = useFormatCoin(data?.gasConfig.budget, SUI_TYPE_ARG); + const [formattedGas] = useFormatCoin(data?.gasData.budget, SUI_TYPE_ARG); return { data: formattedGas, diff --git a/apps/wallet/src/ui/app/hooks/useTransactionDryRun.ts b/apps/wallet/src/ui/app/hooks/useTransactionDryRun.ts index 9bcf576d1a9ac..0f75567bded2b 100644 --- a/apps/wallet/src/ui/app/hooks/useTransactionDryRun.ts +++ b/apps/wallet/src/ui/app/hooks/useTransactionDryRun.ts @@ -1,16 +1,13 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -import { type TransactionBlock } from '@mysten/sui.js/transactions'; +import { type Transaction } from '@mysten/sui/transactions'; import { useQuery } from '@tanstack/react-query'; import { useAccountByAddress } from './useAccountByAddress'; import { useSigner } from './useSigner'; -export function useTransactionDryRun( - sender: string | undefined, - transactionBlock: TransactionBlock, -) { +export function useTransactionDryRun(sender: string | undefined, transactionBlock: Transaction) { const { data: account } = useAccountByAddress(sender); const signer = useSigner(account || null); const response = useQuery({ diff --git a/apps/wallet/src/ui/app/index.tsx b/apps/wallet/src/ui/app/index.tsx index ef573e75488d2..2c289f192bcef 100644 --- a/apps/wallet/src/ui/app/index.tsx +++ b/apps/wallet/src/ui/app/index.tsx @@ -8,7 +8,7 @@ import { setNavVisibility } from '_redux/slices/app'; import { isLedgerAccountSerializedUI } from '_src/background/accounts/LedgerAccount'; import { persistableStorage } from '_src/shared/analytics/amplitude'; import { type LedgerAccountsPublicKeys } from '_src/shared/messaging/messages/payloads/MethodPayload'; -import { toB64 } from '@mysten/sui.js/utils'; +import { toB64 } from '@mysten/sui/utils'; import { useEffect, useMemo } from 'react'; import { Navigate, Outlet, Route, Routes, useLocation } from 'react-router-dom'; import { throttle } from 'throttle-debounce'; diff --git a/apps/wallet/src/ui/app/pages/approval-request/transaction-request/GasFees.tsx b/apps/wallet/src/ui/app/pages/approval-request/transaction-request/GasFees.tsx index 87c48268a3a79..1cc0cdfdb56b6 100644 --- a/apps/wallet/src/ui/app/pages/approval-request/transaction-request/GasFees.tsx +++ b/apps/wallet/src/ui/app/pages/approval-request/transaction-request/GasFees.tsx @@ -3,22 +3,22 @@ import { useTransactionData, useTransactionGasBudget } from '_src/ui/app/hooks'; import { GAS_SYMBOL } from '_src/ui/app/redux/slices/sui-objects/Coin'; -import { type TransactionBlock } from '@mysten/sui.js/transactions'; -import { formatAddress } from '@mysten/sui.js/utils'; +import { type Transaction } from '@mysten/sui/transactions'; +import { formatAddress } from '@mysten/sui/utils'; import { DescriptionItem, DescriptionList } from './DescriptionList'; import { SummaryCard } from './SummaryCard'; interface Props { sender?: string; - transaction: TransactionBlock; + transaction: Transaction; } export function GasFees({ sender, transaction }: Props) { const { data: transactionData } = useTransactionData(sender, transaction); const { data: gasBudget, isPending, isError } = useTransactionGasBudget(sender, transaction); const isSponsored = - transactionData?.gasConfig.owner && transactionData.sender !== transactionData.gasConfig.owner; + transactionData?.gasData.owner && transactionData.sender !== transactionData.gasData.owner; return ( - {formatAddress(transactionData!.gasConfig.owner!)} + {formatAddress(transactionData!.gasData.owner!)} )} diff --git a/apps/wallet/src/ui/app/pages/approval-request/transaction-request/TransactionDetails/Command.tsx b/apps/wallet/src/ui/app/pages/approval-request/transaction-request/TransactionDetails/Command.tsx index 251be0f0add1f..4ea1f50afa5b8 100644 --- a/apps/wallet/src/ui/app/pages/approval-request/transaction-request/TransactionDetails/Command.tsx +++ b/apps/wallet/src/ui/app/pages/approval-request/transaction-request/TransactionDetails/Command.tsx @@ -3,25 +3,25 @@ import { Text } from '_src/ui/app/shared/text'; import { ChevronDown12, ChevronRight12 } from '@mysten/icons'; -import { TypeTagSerializer, type TypeTag } from '@mysten/sui.js/bcs'; -import { type TransactionArgument, type Transactions } from '@mysten/sui.js/transactions'; -import { formatAddress, normalizeSuiAddress, toB64 } from '@mysten/sui.js/utils'; +import { type Argument, type Commands, type TransactionData } from '@mysten/sui/transactions'; +import { toB64 } from '@mysten/sui/utils'; import { useState } from 'react'; -type TransactionType = ReturnType<(typeof Transactions)[keyof typeof Transactions]>; -type MakeMoveVecTransaction = ReturnType<(typeof Transactions)['MakeMoveVec']>; -type PublishTransaction = ReturnType<(typeof Transactions)['Publish']>; +type TransactionType = TransactionData['commands'][0]; +type MakeMoveVecTransaction = ReturnType<(typeof Commands)['MakeMoveVec']>; +type PublishTransaction = ReturnType<(typeof Commands)['Publish']>; function convertCommandArgumentToString( arg: + | null | string | number | string[] | number[] - | TransactionArgument - | TransactionArgument[] - | MakeMoveVecTransaction['type'] - | PublishTransaction['modules'], + | Argument + | Argument[] + | MakeMoveVecTransaction['MakeMoveVec']['type'] + | PublishTransaction['Publish']['modules'], ): string | null { if (!arg) return null; @@ -31,14 +31,6 @@ function convertCommandArgumentToString( return null; } - if (typeof arg === 'object' && 'Some' in arg) { - if (typeof arg.Some === 'object') { - // MakeMoveVecTransaction['type'] is TypeTag type - return TypeTagSerializer.tagToString(arg.Some as TypeTag); - } - return arg.Some; - } - if (Array.isArray(arg)) { // Publish transaction special casing: if (typeof arg[0] === 'number') { @@ -48,15 +40,15 @@ function convertCommandArgumentToString( return `[${arg.map((argVal) => convertCommandArgumentToString(argVal)).join(', ')}]`; } - switch (arg.kind) { + switch (arg.$kind) { case 'GasCoin': return 'GasCoin'; case 'Input': - return `Input(${arg.index})`; + return `Input(${arg.Input})`; case 'Result': - return `Result(${arg.index})`; + return `Result(${arg.Result})`; case 'NestedResult': - return `NestedResult(${arg.index}, ${arg.resultIndex})`; + return `NestedResult(${arg.NestedResult[0]}, ${arg.NestedResult[1]})`; default: // eslint-disable-next-line no-console console.warn('Unexpected command argument type.', arg); @@ -64,20 +56,68 @@ function convertCommandArgumentToString( } } -function convertCommandToString({ kind, ...command }: TransactionType) { - const commandArguments = Object.entries(command); +function convertCommandToString(command: TransactionType) { + let normalizedCommand; + switch (command.$kind) { + case 'MoveCall': + normalizedCommand = { + kind: 'MoveCall', + ...command.MoveCall, + typeArguments: command.MoveCall.typeArguments, + }; + break; + case 'MakeMoveVec': + normalizedCommand = { + kind: 'MakeMoveVec', + type: command.MakeMoveVec.type, + elements: command.MakeMoveVec.elements, + }; + break; + case 'MergeCoins': + normalizedCommand = { + kind: 'MergeCoins', + destination: command.MergeCoins.destination, + sources: command.MergeCoins.sources, + }; + break; + case 'TransferObjects': + normalizedCommand = { + kind: 'TransferObjects', + objects: command.TransferObjects.objects, + address: command.TransferObjects.address, + }; + break; + case 'SplitCoins': + normalizedCommand = { + kind: 'SplitCoins', + coin: command.SplitCoins.coin, + amounts: command.SplitCoins.amounts, + }; + break; + case 'Publish': + normalizedCommand = { + kind: 'Publish', + modules: command.Publish.modules, + dependencies: command.Publish.dependencies, + }; + break; + case 'Upgrade': + normalizedCommand = { + kind: 'Upgrade', + modules: command.Upgrade.modules, + dependencies: command.Upgrade.dependencies, + packageId: command.Upgrade.package, + ticket: command.Upgrade.ticket, + }; + break; + case '$Intent': { + throw new Error('TransactionIntent is not supported'); + } + } + const commandArguments = Object.entries(normalizedCommand); return commandArguments .map(([key, value]) => { - if (key === 'target') { - const [packageId, moduleName, functionName] = value.split('::'); - return [ - `package: ${formatAddress(normalizeSuiAddress(packageId))}`, - `module: ${moduleName}`, - `function: ${functionName}`, - ].join(', '); - } - const stringValue = convertCommandArgumentToString(value); if (!stringValue) return null; @@ -102,7 +142,7 @@ export function Command({ command }: CommandProps) { className="flex items-center gap-2 w-full bg-transparent border-none p-0" > - {command.kind} + {command.$kind}

{expanded ? : }
diff --git a/apps/wallet/src/ui/app/pages/approval-request/transaction-request/TransactionDetails/Input.tsx b/apps/wallet/src/ui/app/pages/approval-request/transaction-request/TransactionDetails/Input.tsx index 43df87859299f..1e35d77928f0e 100644 --- a/apps/wallet/src/ui/app/pages/approval-request/transaction-request/TransactionDetails/Input.tsx +++ b/apps/wallet/src/ui/app/pages/approval-request/transaction-request/TransactionDetails/Input.tsx @@ -4,23 +4,27 @@ import ExplorerLink from '_src/ui/app/components/explorer-link'; import { ExplorerLinkType } from '_src/ui/app/components/explorer-link/ExplorerLinkType'; import { Text } from '_src/ui/app/shared/text'; -import { type TransactionBlockInput } from '@mysten/sui.js/transactions'; -import { formatAddress, toB64 } from '@mysten/sui.js/utils'; +import { type TransactionInput } from '@mysten/sui/transactions'; +import { formatAddress } from '@mysten/sui/utils'; interface InputProps { - input: TransactionBlockInput; + input: TransactionInput; } export function Input({ input }: InputProps) { - const { objectId } = input.value?.Object?.ImmOrOwned || input.value?.Object?.Shared || {}; + const { objectId } = + input?.Object?.ImmOrOwnedObject ?? + input?.Object?.SharedObject ?? + input.Object?.Receiving! ?? + {}; return (
- {'Pure' in input.value ? ( - `${toB64(new Uint8Array(input.value.Pure))}` - ) : 'Object' in input.value ? ( - + {input.Pure ? ( + `${input.Pure.bytes}` + ) : input.Object ? ( + {formatAddress(objectId)} ) : ( diff --git a/apps/wallet/src/ui/app/pages/approval-request/transaction-request/TransactionDetails/index.tsx b/apps/wallet/src/ui/app/pages/approval-request/transaction-request/TransactionDetails/index.tsx index d833ededa11b9..4511c059d1463 100644 --- a/apps/wallet/src/ui/app/pages/approval-request/transaction-request/TransactionDetails/index.tsx +++ b/apps/wallet/src/ui/app/pages/approval-request/transaction-request/TransactionDetails/index.tsx @@ -3,7 +3,7 @@ import { useTransactionData } from '_src/ui/app/hooks'; import { Tab as HeadlessTab, type TabProps } from '@headlessui/react'; -import { type TransactionBlock } from '@mysten/sui.js/transactions'; +import { type Transaction } from '@mysten/sui/transactions'; import { SummaryCard } from '../SummaryCard'; import { Command } from './Command'; @@ -11,7 +11,7 @@ import { Input } from './Input'; interface Props { sender?: string; - transaction: TransactionBlock; + transaction: Transaction; } const Tab = (props: TabProps<'div'>) => ( @@ -23,7 +23,7 @@ const Tab = (props: TabProps<'div'>) => ( export function TransactionDetails({ sender, transaction }: Props) { const { data: transactionData, isPending, isError } = useTransactionData(sender, transaction); - if (transactionData?.transactions.length === 0 && transactionData.inputs.length === 0) { + if (transactionData?.commands.length === 0 && transactionData.inputs.length === 0) { return null; } return ( @@ -36,14 +36,14 @@ export function TransactionDetails({ sender, transaction }: Props) {
- {!!transactionData.transactions.length && Transactions} + {!!transactionData.commands.length && Commands} {!!transactionData.inputs.length && Inputs} - {!!transactionData.transactions.length && ( + {!!transactionData.commands.length && ( {/* TODO: Rename components: */} - {transactionData.transactions.map((command, index) => ( + {transactionData.commands.map((command, index) => ( ))} diff --git a/apps/wallet/src/ui/app/pages/approval-request/transaction-request/index.tsx b/apps/wallet/src/ui/app/pages/approval-request/transaction-request/index.tsx index 03c01a14da4d2..dfef80b7ae59c 100644 --- a/apps/wallet/src/ui/app/pages/approval-request/transaction-request/index.tsx +++ b/apps/wallet/src/ui/app/pages/approval-request/transaction-request/index.tsx @@ -1,7 +1,7 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -// import { Transaction } from '@mysten/sui.js'; +// import { Transaction } from '@mysten/sui'; import { UserApproveContainer } from '_components/user-approve-container'; import { useAppDispatch, useTransactionData, useTransactionDryRun } from '_hooks'; import { type TransactionApprovalRequest } from '_payloads/transactions/ApprovalRequest'; @@ -14,7 +14,7 @@ import { useSigner } from '_src/ui/app/hooks/useSigner'; import { PageMainLayoutTitle } from '_src/ui/app/shared/page-main-layout/PageMainLayoutTitle'; import { TransactionSummary } from '_src/ui/app/shared/transaction-summary'; import { useTransactionSummary } from '@mysten/core'; -import { TransactionBlock } from '@mysten/sui.js/transactions'; +import { Transaction } from '@mysten/sui/transactions'; import { useMemo, useState } from 'react'; import { ConfirmationModal } from '../../../shared/ConfirmationModal'; @@ -37,7 +37,7 @@ export function TransactionRequest({ txRequest }: TransactionRequestProps) { const signer = useSigner(accountForTransaction); const dispatch = useAppDispatch(); const transaction = useMemo(() => { - const tx = TransactionBlock.from(txRequest.tx.data); + const tx = Transaction.from(txRequest.tx.data); if (addressForTransaction) { tx.setSenderIfNotSet(addressForTransaction); } diff --git a/apps/wallet/src/ui/app/pages/approval-request/transaction-request/utils/normalize.ts b/apps/wallet/src/ui/app/pages/approval-request/transaction-request/utils/normalize.ts index 0430e896e80d3..589b35ce40cdd 100644 --- a/apps/wallet/src/ui/app/pages/approval-request/transaction-request/utils/normalize.ts +++ b/apps/wallet/src/ui/app/pages/approval-request/transaction-request/utils/normalize.ts @@ -1,7 +1,7 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -import { type SuiMoveNormalizedType } from '@mysten/sui.js/client'; +import { type SuiMoveNormalizedType } from '@mysten/sui/client'; export interface TypeReference { address: string; diff --git a/apps/wallet/src/ui/app/pages/home/kiosk-details/index.tsx b/apps/wallet/src/ui/app/pages/home/kiosk-details/index.tsx index 517acce8d01ea..58bfa561c1a85 100644 --- a/apps/wallet/src/ui/app/pages/home/kiosk-details/index.tsx +++ b/apps/wallet/src/ui/app/pages/home/kiosk-details/index.tsx @@ -13,7 +13,7 @@ import { useUnlockedGuard } from '_src/ui/app/hooks/useUnlockedGuard'; import { Collapsible } from '_src/ui/app/shared/collapse'; import PageTitle from '_src/ui/app/shared/PageTitle'; import { useGetKioskContents } from '@mysten/core'; -import { formatAddress } from '@mysten/sui.js/utils'; +import { formatAddress } from '@mysten/sui/utils'; import { Link, useSearchParams } from 'react-router-dom'; function KioskDetailsPage() { diff --git a/apps/wallet/src/ui/app/pages/home/nft-details/index.tsx b/apps/wallet/src/ui/app/pages/home/nft-details/index.tsx index 4a713869d53f8..04fe0b8dd3551 100644 --- a/apps/wallet/src/ui/app/pages/home/nft-details/index.tsx +++ b/apps/wallet/src/ui/app/pages/home/nft-details/index.tsx @@ -19,7 +19,7 @@ import PageTitle from '_src/ui/app/shared/PageTitle'; import { Text } from '_src/ui/app/shared/text'; import { useGetKioskContents } from '@mysten/core'; import { ArrowRight16, ArrowUpRight12 } from '@mysten/icons'; -import { formatAddress } from '@mysten/sui.js/utils'; +import { formatAddress } from '@mysten/sui/utils'; import cl from 'clsx'; import { Navigate, useNavigate, useSearchParams } from 'react-router-dom'; diff --git a/apps/wallet/src/ui/app/pages/home/nft-transfer/TransferNFTForm.tsx b/apps/wallet/src/ui/app/pages/home/nft-transfer/TransferNFTForm.tsx index ac4f800fef8af..769a72c211c67 100644 --- a/apps/wallet/src/ui/app/pages/home/nft-transfer/TransferNFTForm.tsx +++ b/apps/wallet/src/ui/app/pages/home/nft-transfer/TransferNFTForm.tsx @@ -15,7 +15,7 @@ import { QredoActionIgnoredByUser } from '_src/ui/app/QredoSigner'; import { isSuiNSName, useGetKioskContents, useSuiNSEnabled } from '@mysten/core'; import { useSuiClient } from '@mysten/dapp-kit'; import { ArrowRight16 } from '@mysten/icons'; -import { TransactionBlock } from '@mysten/sui.js/transactions'; +import { Transaction } from '@mysten/sui/transactions'; import { useMutation, useQueryClient } from '@tanstack/react-query'; import { Field, Form, Formik } from 'formik'; import { toast } from 'react-hot-toast'; @@ -64,7 +64,7 @@ export function TransferNFTForm({ return transferKioskItem.mutateAsync({ to, clientIdentifier }); } - const tx = new TransactionBlock(); + const tx = new Transaction(); tx.transferObjects([tx.object(objectId)], to); return signer.signAndExecuteTransactionBlock( diff --git a/apps/wallet/src/ui/app/pages/home/nft-transfer/useTransferKioskItem.ts b/apps/wallet/src/ui/app/pages/home/nft-transfer/useTransferKioskItem.ts index 7073487ccc437..ea2c046c0d677 100644 --- a/apps/wallet/src/ui/app/pages/home/nft-transfer/useTransferKioskItem.ts +++ b/apps/wallet/src/ui/app/pages/home/nft-transfer/useTransferKioskItem.ts @@ -14,7 +14,7 @@ import { import { useKioskClient } from '@mysten/core/src/hooks/useKioskClient'; import { useSuiClient } from '@mysten/dapp-kit'; import { KioskTransaction } from '@mysten/kiosk'; -import { TransactionBlock } from '@mysten/sui.js/transactions'; +import { Transaction } from '@mysten/sui/transactions'; import { useMutation } from '@tanstack/react-query'; const ORIGINBYTE_PACKAGE_ID = '0x083b02db943238dcea0ff0938a54a17d7575f5b48034506446e501e963391480'; @@ -49,9 +49,9 @@ export function useTransferKioskItem({ } if (kiosk.type === KioskTypes.SUI && objectData?.data?.data?.type && kiosk?.ownerCap) { - const txb = new TransactionBlock(); + const txb = new Transaction(); - new KioskTransaction({ transactionBlock: txb, kioskClient, cap: kiosk.ownerCap }) + new KioskTransaction({ transaction: txb, kioskClient, cap: kiosk.ownerCap }) .transfer({ itemType: objectData.data.data.type as string, itemId: objectId, @@ -73,7 +73,7 @@ export function useTransferKioskItem({ } if (kiosk.type === KioskTypes.ORIGINBYTE && objectData?.data?.data?.type) { - const tx = new TransactionBlock(); + const tx = new Transaction(); const recipientKiosks = await client.getOwnedObjects({ owner: to, options: { showContent: true }, @@ -86,13 +86,13 @@ export function useTransferKioskItem({ tx.moveCall({ target: `${obPackageId}::ob_kiosk::p2p_transfer`, typeArguments: [objectType], - arguments: [tx.object(kioskId), tx.object(recipientKioskId), tx.pure(objectId)], + arguments: [tx.object(kioskId), tx.object(recipientKioskId), tx.pure.id(objectId)], }); } else { tx.moveCall({ target: `${obPackageId}::ob_kiosk::p2p_transfer_and_create_target_kiosk`, typeArguments: [objectType], - arguments: [tx.object(kioskId), tx.pure(to), tx.pure(objectId)], + arguments: [tx.object(kioskId), tx.pure.address(to), tx.pure.id(objectId)], }); } return signer.signAndExecuteTransactionBlock( diff --git a/apps/wallet/src/ui/app/pages/home/nft-transfer/validation.ts b/apps/wallet/src/ui/app/pages/home/nft-transfer/validation.ts index 91d3b47eff25e..24fcf27f75afb 100644 --- a/apps/wallet/src/ui/app/pages/home/nft-transfer/validation.ts +++ b/apps/wallet/src/ui/app/pages/home/nft-transfer/validation.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { createSuiAddressValidation } from '_components/address-input/validation'; -import { type SuiClient } from '@mysten/sui.js/client'; +import { type SuiClient } from '@mysten/sui/client'; import * as Yup from 'yup'; export function createValidationSchema( diff --git a/apps/wallet/src/ui/app/pages/home/nfts/NonVisualAssets.tsx b/apps/wallet/src/ui/app/pages/home/nfts/NonVisualAssets.tsx index 801ad9a1089c4..f61d15c475ece 100644 --- a/apps/wallet/src/ui/app/pages/home/nfts/NonVisualAssets.tsx +++ b/apps/wallet/src/ui/app/pages/home/nfts/NonVisualAssets.tsx @@ -4,8 +4,8 @@ import ExplorerLink from '_src/ui/app/components/explorer-link'; import { ExplorerLinkType } from '_src/ui/app/components/explorer-link/ExplorerLinkType'; import { Text } from '_src/ui/app/shared/text'; -import { type SuiObjectData } from '@mysten/sui.js/client'; -import { formatAddress, parseStructTag } from '@mysten/sui.js/utils'; +import { type SuiObjectData } from '@mysten/sui/client'; +import { formatAddress, parseStructTag } from '@mysten/sui/utils'; export default function NonVisualAssets({ items }: { items: SuiObjectData[] }) { return ( diff --git a/apps/wallet/src/ui/app/pages/home/nfts/VisualAssets.tsx b/apps/wallet/src/ui/app/pages/home/nfts/VisualAssets.tsx index 1e092b5877d91..004cc88e6422c 100644 --- a/apps/wallet/src/ui/app/pages/home/nfts/VisualAssets.tsx +++ b/apps/wallet/src/ui/app/pages/home/nfts/VisualAssets.tsx @@ -9,7 +9,7 @@ import { Button } from '_src/ui/app/shared/ButtonUI'; import { getKioskIdFromOwnerCap, isKioskOwnerToken } from '@mysten/core'; import { useKioskClient } from '@mysten/core/src/hooks/useKioskClient'; import { EyeClose16 } from '@mysten/icons'; -import { type SuiObjectData } from '@mysten/sui.js/client'; +import { type SuiObjectData } from '@mysten/sui/client'; import { Link } from 'react-router-dom'; import { useHiddenAssets } from '../hidden-assets/HiddenAssetsProvider'; diff --git a/apps/wallet/src/ui/app/pages/home/receipt/index.tsx b/apps/wallet/src/ui/app/pages/home/receipt/index.tsx index 054cac0051eaf..1355252e3f404 100644 --- a/apps/wallet/src/ui/app/pages/home/receipt/index.tsx +++ b/apps/wallet/src/ui/app/pages/home/receipt/index.tsx @@ -9,7 +9,7 @@ import { useActiveAddress } from '_src/ui/app/hooks/useActiveAddress'; import { useUnlockedGuard } from '_src/ui/app/hooks/useUnlockedGuard'; import { useSuiClient } from '@mysten/dapp-kit'; import { Check32 } from '@mysten/icons'; -import { type SuiTransactionBlockResponse } from '@mysten/sui.js/client'; +import { type SuiTransactionBlockResponse } from '@mysten/sui/client'; import { useQuery } from '@tanstack/react-query'; import { useCallback, useMemo, useState } from 'react'; import { Navigate, useLocation, useNavigate, useSearchParams } from 'react-router-dom'; diff --git a/apps/wallet/src/ui/app/pages/home/tokens/TokenIconLink.tsx b/apps/wallet/src/ui/app/pages/home/tokens/TokenIconLink.tsx index ddceeccb8e761..5195507018769 100644 --- a/apps/wallet/src/ui/app/pages/home/tokens/TokenIconLink.tsx +++ b/apps/wallet/src/ui/app/pages/home/tokens/TokenIconLink.tsx @@ -10,7 +10,7 @@ import { import { Text } from '_src/ui/app/shared/text'; import { useFormatCoin, useGetDelegatedStake } from '@mysten/core'; import { WalletActionStake24 } from '@mysten/icons'; -import { SUI_TYPE_ARG } from '@mysten/sui.js/utils'; +import { SUI_TYPE_ARG } from '@mysten/sui/utils'; import { useMemo } from 'react'; export function TokenIconLink({ diff --git a/apps/wallet/src/ui/app/pages/home/tokens/TokenLink.tsx b/apps/wallet/src/ui/app/pages/home/tokens/TokenLink.tsx index ee4c50374497a..9e6bf99805d57 100644 --- a/apps/wallet/src/ui/app/pages/home/tokens/TokenLink.tsx +++ b/apps/wallet/src/ui/app/pages/home/tokens/TokenLink.tsx @@ -3,8 +3,8 @@ import { CoinItem } from '_components/active-coins-card/CoinItem'; import { ampli } from '_src/shared/analytics/ampli'; -import { type CoinBalance } from '@mysten/sui.js/client'; -import { MIST_PER_SUI } from '@mysten/sui.js/utils'; +import { type CoinBalance } from '@mysten/sui/client'; +import { MIST_PER_SUI } from '@mysten/sui/utils'; import { type ReactNode } from 'react'; import { Link } from 'react-router-dom'; diff --git a/apps/wallet/src/ui/app/pages/home/tokens/TokensDetails.tsx b/apps/wallet/src/ui/app/pages/home/tokens/TokensDetails.tsx index c57c4f41bdc0b..03f749e12463d 100644 --- a/apps/wallet/src/ui/app/pages/home/tokens/TokensDetails.tsx +++ b/apps/wallet/src/ui/app/pages/home/tokens/TokensDetails.tsx @@ -40,8 +40,8 @@ import { } from '@mysten/core'; import { useSuiClientQuery } from '@mysten/dapp-kit'; import { Info12, Pin16, Unpin16 } from '@mysten/icons'; -import { type CoinBalance as CoinBalanceType } from '@mysten/sui.js/client'; -import { formatAddress, parseStructTag, SUI_TYPE_ARG } from '@mysten/sui.js/utils'; +import { type CoinBalance as CoinBalanceType } from '@mysten/sui/client'; +import { formatAddress, parseStructTag, SUI_TYPE_ARG } from '@mysten/sui/utils'; import { useQuery } from '@tanstack/react-query'; import clsx from 'clsx'; import { useEffect, useState, type ReactNode } from 'react'; diff --git a/apps/wallet/src/ui/app/pages/home/tokens/coin-balance/index.tsx b/apps/wallet/src/ui/app/pages/home/tokens/coin-balance/index.tsx index f3703d3f76eed..84086917249f5 100644 --- a/apps/wallet/src/ui/app/pages/home/tokens/coin-balance/index.tsx +++ b/apps/wallet/src/ui/app/pages/home/tokens/coin-balance/index.tsx @@ -6,7 +6,7 @@ import { API_ENV } from '_shared/api-env'; import { Heading } from '_src/ui/app/shared/heading'; import { Text } from '_src/ui/app/shared/text'; import { useBalanceInUSD, useFormatCoin } from '@mysten/core'; -import { SUI_TYPE_ARG } from '@mysten/sui.js/utils'; +import { SUI_TYPE_ARG } from '@mysten/sui/utils'; import { useMemo } from 'react'; export type CoinProps = { diff --git a/apps/wallet/src/ui/app/pages/home/transactions/QredoTransaction.tsx b/apps/wallet/src/ui/app/pages/home/transactions/QredoTransaction.tsx index 9c289827c557a..148498a8dbcb6 100644 --- a/apps/wallet/src/ui/app/pages/home/transactions/QredoTransaction.tsx +++ b/apps/wallet/src/ui/app/pages/home/transactions/QredoTransaction.tsx @@ -7,8 +7,8 @@ import { TxnIcon } from '_src/ui/app/components/transactions-card/TxnIcon'; import { useGetQredoTransaction } from '_src/ui/app/hooks/useGetQredoTransaction'; import { Text } from '_src/ui/app/shared/text'; import { formatDate, useOnScreen } from '@mysten/core'; -import { IntentScope } from '@mysten/sui.js/cryptography'; -import { fromB64 } from '@mysten/sui.js/utils'; +import { bcs } from '@mysten/sui/bcs'; +import { fromB64 } from '@mysten/sui/utils'; import { useMemo, useRef } from 'react'; export type QredoTransactionProps = { @@ -30,8 +30,11 @@ export function QredoTransaction({ qredoID, qredoTransactionID }: QredoTransacti } return null; }, [data?.MessageWithIntent]); - const scope = messageWithIntent?.[0]; - const isSignMessage = scope === IntentScope.PersonalMessage; + + const isSignMessage = messageWithIntent + ? bcs.IntentScope.parse(messageWithIntent).PersonalMessage + : false; + const transactionBytes = useMemo(() => messageWithIntent?.slice(3) || null, [messageWithIntent]); const messageToSign = useMemo( diff --git a/apps/wallet/src/ui/app/pages/home/transfer-coin/CoinSelector.tsx b/apps/wallet/src/ui/app/pages/home/transfer-coin/CoinSelector.tsx index ec2cabe2dc3c3..a3ab73764b3a8 100644 --- a/apps/wallet/src/ui/app/pages/home/transfer-coin/CoinSelector.tsx +++ b/apps/wallet/src/ui/app/pages/home/transfer-coin/CoinSelector.tsx @@ -4,7 +4,7 @@ import { ActiveCoinsCard } from '_components/active-coins-card'; import Overlay from '_components/overlay'; import { useUnlockedGuard } from '_src/ui/app/hooks/useUnlockedGuard'; -import { SUI_TYPE_ARG } from '@mysten/sui.js/utils'; +import { SUI_TYPE_ARG } from '@mysten/sui/utils'; import { useNavigate, useSearchParams } from 'react-router-dom'; function CoinsSelectorPage() { diff --git a/apps/wallet/src/ui/app/pages/home/transfer-coin/SendTokenForm.tsx b/apps/wallet/src/ui/app/pages/home/transfer-coin/SendTokenForm.tsx index f9dac7b138de4..1bda434c96b3a 100644 --- a/apps/wallet/src/ui/app/pages/home/transfer-coin/SendTokenForm.tsx +++ b/apps/wallet/src/ui/app/pages/home/transfer-coin/SendTokenForm.tsx @@ -21,8 +21,8 @@ import { } from '@mysten/core'; import { useSuiClient } from '@mysten/dapp-kit'; import { ArrowRight16 } from '@mysten/icons'; -import { type CoinStruct } from '@mysten/sui.js/client'; -import { SUI_TYPE_ARG } from '@mysten/sui.js/utils'; +import { type CoinStruct } from '@mysten/sui/client'; +import { SUI_TYPE_ARG } from '@mysten/sui/utils'; import { useQuery } from '@tanstack/react-query'; import { Field, Form, Formik, useFormikContext } from 'formik'; import { useEffect, useMemo } from 'react'; diff --git a/apps/wallet/src/ui/app/pages/home/transfer-coin/utils/transaction.ts b/apps/wallet/src/ui/app/pages/home/transfer-coin/utils/transaction.ts index 6d4dcaa8ab7a8..2a593b63ed836 100644 --- a/apps/wallet/src/ui/app/pages/home/transfer-coin/utils/transaction.ts +++ b/apps/wallet/src/ui/app/pages/home/transfer-coin/utils/transaction.ts @@ -2,9 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 import { parseAmount } from '_src/ui/app/helpers'; -import { type CoinStruct } from '@mysten/sui.js/client'; -import { TransactionBlock } from '@mysten/sui.js/transactions'; -import { SUI_TYPE_ARG } from '@mysten/sui.js/utils'; +import { type CoinStruct } from '@mysten/sui/client'; +import { Transaction } from '@mysten/sui/transactions'; +import { SUI_TYPE_ARG } from '@mysten/sui/utils'; interface Options { coinType: string; @@ -23,7 +23,7 @@ export function createTokenTransferTransaction({ coinDecimals, isPayAllSui, }: Options) { - const tx = new TransactionBlock(); + const tx = new Transaction(); if (isPayAllSui && coinType === SUI_TYPE_ARG) { tx.transferObjects([tx.gas], to); diff --git a/apps/wallet/src/ui/app/pages/home/transfer-coin/validation.ts b/apps/wallet/src/ui/app/pages/home/transfer-coin/validation.ts index da4dc437abfa4..3686d5f76d6f5 100644 --- a/apps/wallet/src/ui/app/pages/home/transfer-coin/validation.ts +++ b/apps/wallet/src/ui/app/pages/home/transfer-coin/validation.ts @@ -3,7 +3,7 @@ import { createSuiAddressValidation } from '_components/address-input/validation'; import { createTokenValidation } from '_src/shared/validation'; -import { type SuiClient } from '@mysten/sui.js/client'; +import { type SuiClient } from '@mysten/sui/client'; import * as Yup from 'yup'; export function createValidationSchemaStepOne( diff --git a/apps/wallet/src/ui/app/pages/qredo-connect/components/QredoAccountItem.tsx b/apps/wallet/src/ui/app/pages/qredo-connect/components/QredoAccountItem.tsx index ed81d17ffe129..adcb7b814f001 100644 --- a/apps/wallet/src/ui/app/pages/qredo-connect/components/QredoAccountItem.tsx +++ b/apps/wallet/src/ui/app/pages/qredo-connect/components/QredoAccountItem.tsx @@ -5,7 +5,7 @@ import { type Wallet } from '_src/shared/qredo-api'; import { BadgeLabel } from '_src/ui/app/components/BadgeLabel'; import { Text } from '_src/ui/app/shared/text'; import { CheckFill16 } from '@mysten/icons'; -import { formatAddress } from '@mysten/sui.js/utils'; +import { formatAddress } from '@mysten/sui/utils'; import cn from 'clsx'; export type QredoAccountItemProps = Wallet & { diff --git a/apps/wallet/src/ui/app/pages/swap/GasFeeSection.tsx b/apps/wallet/src/ui/app/pages/swap/GasFeeSection.tsx index 26d499fc842c1..c6052c6925b77 100644 --- a/apps/wallet/src/ui/app/pages/swap/GasFeeSection.tsx +++ b/apps/wallet/src/ui/app/pages/swap/GasFeeSection.tsx @@ -8,7 +8,7 @@ import { GAS_TYPE_ARG } from '_redux/slices/sui-objects/Coin'; import { FEATURES } from '_shared/experimentation/features'; import { useFeatureValue } from '@growthbook/growthbook-react'; import { useBalanceInUSD, useFormatCoin } from '@mysten/core'; -import { type BalanceChange } from '@mysten/sui.js/client'; +import { type BalanceChange } from '@mysten/sui/client'; export function GasFeeSection({ activeCoinType, diff --git a/apps/wallet/src/ui/app/pages/swap/ToAssetSection.tsx b/apps/wallet/src/ui/app/pages/swap/ToAssetSection.tsx index a4e063bfff016..c35b3d67bbf50 100644 --- a/apps/wallet/src/ui/app/pages/swap/ToAssetSection.tsx +++ b/apps/wallet/src/ui/app/pages/swap/ToAssetSection.tsx @@ -16,8 +16,8 @@ import { MaxSlippage, MaxSlippageModal } from '_pages/swap/MaxSlippage'; import { ToAssets } from '_pages/swap/ToAssets'; import { getUSDCurrency, useSwapData } from '_pages/swap/utils'; import { useDeepBookContext } from '_shared/deepBook/context'; -import { type BalanceChange } from '@mysten/sui.js/client'; -import { SUI_TYPE_ARG } from '@mysten/sui.js/utils'; +import { type BalanceChange } from '@mysten/sui/client'; +import { SUI_TYPE_ARG } from '@mysten/sui/utils'; import BigNumber from 'bignumber.js'; import clsx from 'clsx'; import { useEffect, useState } from 'react'; diff --git a/apps/wallet/src/ui/app/pages/swap/index.tsx b/apps/wallet/src/ui/app/pages/swap/index.tsx index f6eb0e4ff28db..f33c3d26a8e80 100644 --- a/apps/wallet/src/ui/app/pages/swap/index.tsx +++ b/apps/wallet/src/ui/app/pages/swap/index.tsx @@ -40,8 +40,8 @@ import { DeepBookContextProvider, useDeepBookContext } from '_shared/deepBook/co import { useTransactionSummary, useZodForm } from '@mysten/core'; import { useSuiClientQuery } from '@mysten/dapp-kit'; import { ArrowDown12, ArrowRight16 } from '@mysten/icons'; -import { type DryRunTransactionBlockResponse } from '@mysten/sui.js/client'; -import { SUI_TYPE_ARG } from '@mysten/sui.js/utils'; +import { type DryRunTransactionBlockResponse } from '@mysten/sui/client'; +import { SUI_TYPE_ARG } from '@mysten/sui/utils'; import { useMutation, useQueryClient } from '@tanstack/react-query'; import BigNumber from 'bignumber.js'; import clsx from 'clsx'; diff --git a/apps/wallet/src/ui/app/pages/swap/utils.ts b/apps/wallet/src/ui/app/pages/swap/utils.ts index 33d28bd227d0d..571817989fcfe 100644 --- a/apps/wallet/src/ui/app/pages/swap/utils.ts +++ b/apps/wallet/src/ui/app/pages/swap/utils.ts @@ -5,7 +5,7 @@ import { useCoinsReFetchingConfig } from '_hooks'; import { roundFloat, useFormatCoin } from '@mysten/core'; import { useSuiClientQuery } from '@mysten/dapp-kit'; import { type DeepBookClient } from '@mysten/deepbook'; -import { type BalanceChange } from '@mysten/sui.js/client'; +import { type BalanceChange } from '@mysten/sui/client'; import BigNumber from 'bignumber.js'; export function useSwapData({ diff --git a/apps/wallet/src/ui/app/redux/slices/sui-objects/Coin.ts b/apps/wallet/src/ui/app/redux/slices/sui-objects/Coin.ts index bd8437761387e..a84da3a45428b 100644 --- a/apps/wallet/src/ui/app/redux/slices/sui-objects/Coin.ts +++ b/apps/wallet/src/ui/app/redux/slices/sui-objects/Coin.ts @@ -1,7 +1,7 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -import type { SuiMoveObject, SuiObjectData } from '@mysten/sui.js/client'; +import type { SuiMoveObject, SuiObjectData } from '@mysten/sui/client'; const COIN_TYPE = '0x2::coin::Coin'; const COIN_TYPE_ARG_REGEX = /^0x2::coin::Coin<(.+)>$/; diff --git a/apps/wallet/src/ui/app/redux/slices/transaction-requests/index.ts b/apps/wallet/src/ui/app/redux/slices/transaction-requests/index.ts index 88d60baf97634..082ba7a8e6ab7 100644 --- a/apps/wallet/src/ui/app/redux/slices/transaction-requests/index.ts +++ b/apps/wallet/src/ui/app/redux/slices/transaction-requests/index.ts @@ -10,9 +10,9 @@ import { type WalletSigner, } from '_src/ui/app/WalletSigner'; import type { AppThunkConfig } from '_store/thunk-extras'; -import { type SuiTransactionBlockResponse } from '@mysten/sui.js/client'; -import { TransactionBlock } from '@mysten/sui.js/transactions'; -import { fromB64 } from '@mysten/sui.js/utils'; +import { type SuiTransactionBlockResponse } from '@mysten/sui/client'; +import { Transaction } from '@mysten/sui/transactions'; +import { fromB64 } from '@mysten/sui/utils'; import { createAsyncThunk, createEntityAdapter, createSlice } from '@reduxjs/toolkit'; import type { PayloadAction } from '@reduxjs/toolkit'; @@ -61,7 +61,7 @@ export const respondToTransactionRequest = createAsyncThunk< clientIdentifier, ); } else if (txRequest.tx.type === 'transaction') { - const tx = TransactionBlock.from(txRequest.tx.data); + const tx = Transaction.from(txRequest.tx.data); if (txRequest.tx.justSign) { // Just a signing request, do not submit txSigned = await signer.signTransactionBlock( diff --git a/apps/wallet/src/ui/app/shared/coin-balance/index.tsx b/apps/wallet/src/ui/app/shared/coin-balance/index.tsx index 3bb66b4de7866..97f74b2fa2af0 100644 --- a/apps/wallet/src/ui/app/shared/coin-balance/index.tsx +++ b/apps/wallet/src/ui/app/shared/coin-balance/index.tsx @@ -3,7 +3,7 @@ import { Text } from '_app/shared/text'; import { useFormatCoin } from '@mysten/core'; -import { SUI_TYPE_ARG } from '@mysten/sui.js/utils'; +import { SUI_TYPE_ARG } from '@mysten/sui/utils'; //TODO create variant for different use cases like heading4, subtitle, bodySmall and different symbols color interface CoinBalanceProps { diff --git a/apps/wallet/src/ui/app/shared/faucet/FaucetRequestButton.tsx b/apps/wallet/src/ui/app/shared/faucet/FaucetRequestButton.tsx index b741fffbb08ca..b4fc0bd3c041a 100644 --- a/apps/wallet/src/ui/app/shared/faucet/FaucetRequestButton.tsx +++ b/apps/wallet/src/ui/app/shared/faucet/FaucetRequestButton.tsx @@ -5,7 +5,7 @@ import { API_ENV_TO_INFO } from '_app/ApiProvider'; import { Button, type ButtonProps } from '_app/shared/ButtonUI'; import { useAppSelector } from '_hooks'; import { API_ENV } from '_src/shared/api-env'; -import { FaucetRateLimitError, getFaucetHost } from '@mysten/sui.js/faucet'; +import { FaucetRateLimitError, getFaucetHost } from '@mysten/sui/faucet'; import { toast } from 'react-hot-toast'; import FaucetMessageInfo from './FaucetMessageInfo'; diff --git a/apps/wallet/src/ui/app/shared/faucet/useFaucetMutation.ts b/apps/wallet/src/ui/app/shared/faucet/useFaucetMutation.ts index d2bd5b7575319..dda33111ede27 100644 --- a/apps/wallet/src/ui/app/shared/faucet/useFaucetMutation.ts +++ b/apps/wallet/src/ui/app/shared/faucet/useFaucetMutation.ts @@ -1,7 +1,7 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -import { getFaucetRequestStatus, requestSuiFromFaucetV1 } from '@mysten/sui.js/faucet'; +import { getFaucetRequestStatus, requestSuiFromFaucetV1 } from '@mysten/sui/faucet'; import { useIsMutating, useMutation, type UseMutationOptions } from '@tanstack/react-query'; import { useActiveAccount } from '../../hooks/useActiveAccount'; diff --git a/apps/wallet/src/ui/app/shared/transaction-summary/OwnerFooter.tsx b/apps/wallet/src/ui/app/shared/transaction-summary/OwnerFooter.tsx index 0c0b3814ca66a..f8248f1f9e878 100644 --- a/apps/wallet/src/ui/app/shared/transaction-summary/OwnerFooter.tsx +++ b/apps/wallet/src/ui/app/shared/transaction-summary/OwnerFooter.tsx @@ -4,7 +4,7 @@ import ExplorerLink from '_src/ui/app/components/explorer-link'; import { ExplorerLinkType } from '_src/ui/app/components/explorer-link/ExplorerLinkType'; import { useActiveAddress } from '_src/ui/app/hooks'; -import { formatAddress, isValidSuiAddress } from '@mysten/sui.js/utils'; +import { formatAddress, isValidSuiAddress } from '@mysten/sui/utils'; import { Text } from '../text'; import { SummaryCardFooter } from './Card'; diff --git a/apps/wallet/src/ui/app/shared/transaction-summary/cards/GasSummary.tsx b/apps/wallet/src/ui/app/shared/transaction-summary/cards/GasSummary.tsx index 85e7657cfbab8..976d9410976aa 100644 --- a/apps/wallet/src/ui/app/shared/transaction-summary/cards/GasSummary.tsx +++ b/apps/wallet/src/ui/app/shared/transaction-summary/cards/GasSummary.tsx @@ -5,7 +5,7 @@ import { ExplorerLinkType } from '_src/ui/app/components/explorer-link/ExplorerL import { useActiveAddress } from '_src/ui/app/hooks'; import { GAS_TYPE_ARG } from '_src/ui/app/redux/slices/sui-objects/Coin'; import { useFormatCoin, type GasSummaryType } from '@mysten/core'; -import { formatAddress } from '@mysten/sui.js/utils'; +import { formatAddress } from '@mysten/sui/utils'; import { Text } from '../../text'; diff --git a/apps/wallet/src/ui/app/shared/transaction-summary/cards/ObjectChanges.tsx b/apps/wallet/src/ui/app/shared/transaction-summary/cards/ObjectChanges.tsx index e71be6b7bc37f..4c64b5c94087e 100644 --- a/apps/wallet/src/ui/app/shared/transaction-summary/cards/ObjectChanges.tsx +++ b/apps/wallet/src/ui/app/shared/transaction-summary/cards/ObjectChanges.tsx @@ -12,7 +12,7 @@ import { type SuiObjectChangeWithDisplay, } from '@mysten/core'; import { ChevronDown12, ChevronRight12 } from '@mysten/icons'; -import { formatAddress } from '@mysten/sui.js/utils'; +import { formatAddress } from '@mysten/sui/utils'; import cx from 'clsx'; import { ExpandableList } from '../../ExpandableList'; diff --git a/apps/wallet/src/ui/app/shared/transaction-summary/cards/objectSummary/ObjectChangeDisplay.tsx b/apps/wallet/src/ui/app/shared/transaction-summary/cards/objectSummary/ObjectChangeDisplay.tsx index b28657b6db6a2..d15b95d8fd4b5 100644 --- a/apps/wallet/src/ui/app/shared/transaction-summary/cards/objectSummary/ObjectChangeDisplay.tsx +++ b/apps/wallet/src/ui/app/shared/transaction-summary/cards/objectSummary/ObjectChangeDisplay.tsx @@ -5,7 +5,7 @@ import ExplorerLink from '_src/ui/app/components/explorer-link'; import { ExplorerLinkType } from '_src/ui/app/components/explorer-link/ExplorerLinkType'; import { NftImage } from '_src/ui/app/components/nft-display/NftImage'; import { type SuiObjectChangeWithDisplay } from '@mysten/core'; -import { formatAddress } from '@mysten/sui.js/utils'; +import { formatAddress } from '@mysten/sui/utils'; import { Text } from '../../../text'; diff --git a/apps/wallet/src/ui/app/staking/delegation-detail/DelegationDetailCard.tsx b/apps/wallet/src/ui/app/staking/delegation-detail/DelegationDetailCard.tsx index 00622b79630af..82f0b1f695698 100644 --- a/apps/wallet/src/ui/app/staking/delegation-detail/DelegationDetailCard.tsx +++ b/apps/wallet/src/ui/app/staking/delegation-detail/DelegationDetailCard.tsx @@ -21,8 +21,8 @@ import FaucetRequestButton from '_src/ui/app/shared/faucet/FaucetRequestButton'; import { useCoinMetadata, useGetDelegatedStake, useGetValidatorsApy } from '@mysten/core'; import { useSuiClientQuery } from '@mysten/dapp-kit'; import { ArrowLeft16, StakeAdd16, StakeRemove16 } from '@mysten/icons'; -import type { StakeObject } from '@mysten/sui.js/client'; -import { MIST_PER_SUI, SUI_TYPE_ARG } from '@mysten/sui.js/utils'; +import type { StakeObject } from '@mysten/sui/client'; +import { MIST_PER_SUI, SUI_TYPE_ARG } from '@mysten/sui/utils'; import BigNumber from 'bignumber.js'; import { useMemo } from 'react'; diff --git a/apps/wallet/src/ui/app/staking/getAllStakeSui.ts b/apps/wallet/src/ui/app/staking/getAllStakeSui.ts index 1c7db94dbb87c..ddbffaf7b9180 100644 --- a/apps/wallet/src/ui/app/staking/getAllStakeSui.ts +++ b/apps/wallet/src/ui/app/staking/getAllStakeSui.ts @@ -1,7 +1,7 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -import { type DelegatedStake } from '@mysten/sui.js/client'; +import { type DelegatedStake } from '@mysten/sui/client'; // Get staked Sui export const getAllStakeSui = (allDelegation: DelegatedStake[]) => { diff --git a/apps/wallet/src/ui/app/staking/getDelegationByStakeId.ts b/apps/wallet/src/ui/app/staking/getDelegationByStakeId.ts index 0083fa6771e11..4407255f59afd 100644 --- a/apps/wallet/src/ui/app/staking/getDelegationByStakeId.ts +++ b/apps/wallet/src/ui/app/staking/getDelegationByStakeId.ts @@ -1,7 +1,7 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -import type { DelegatedStake } from '@mysten/sui.js/client'; +import type { DelegatedStake } from '@mysten/sui/client'; // Helper function to get the delegation by stakedSuiId export const getDelegationDataByStakeId = ( diff --git a/apps/wallet/src/ui/app/staking/getStakeSuiBySuiId.ts b/apps/wallet/src/ui/app/staking/getStakeSuiBySuiId.ts index dd655c6ca3f84..859c1a70012f4 100644 --- a/apps/wallet/src/ui/app/staking/getStakeSuiBySuiId.ts +++ b/apps/wallet/src/ui/app/staking/getStakeSuiBySuiId.ts @@ -1,7 +1,7 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -import { type DelegatedStake } from '@mysten/sui.js/client'; +import { type DelegatedStake } from '@mysten/sui/client'; // Get Stake SUI by stakeSuiId export const getStakeSuiBySuiId = (allDelegation: DelegatedStake[], stakeSuiId?: string | null) => { diff --git a/apps/wallet/src/ui/app/staking/getTokenStakeSuiForValidator.ts b/apps/wallet/src/ui/app/staking/getTokenStakeSuiForValidator.ts index 9f18fb409ab49..1c5873cf7bdc1 100644 --- a/apps/wallet/src/ui/app/staking/getTokenStakeSuiForValidator.ts +++ b/apps/wallet/src/ui/app/staking/getTokenStakeSuiForValidator.ts @@ -1,7 +1,7 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -import { type DelegatedStake } from '@mysten/sui.js/client'; +import { type DelegatedStake } from '@mysten/sui/client'; // Get total Stake SUI for a specific validator address export const getTokenStakeSuiForValidator = ( diff --git a/apps/wallet/src/ui/app/staking/home/StakeAmount.tsx b/apps/wallet/src/ui/app/staking/home/StakeAmount.tsx index 8f727392b670c..0b23942376cac 100644 --- a/apps/wallet/src/ui/app/staking/home/StakeAmount.tsx +++ b/apps/wallet/src/ui/app/staking/home/StakeAmount.tsx @@ -4,7 +4,7 @@ import { Heading } from '_app/shared/heading'; import { Text } from '_app/shared/text'; import { useFormatCoin } from '@mysten/core'; -import { SUI_TYPE_ARG } from '@mysten/sui.js/utils'; +import { SUI_TYPE_ARG } from '@mysten/sui/utils'; //TODO unify StakeAmount and CoinBalance interface StakeAmountProps { diff --git a/apps/wallet/src/ui/app/staking/home/StakedCard.tsx b/apps/wallet/src/ui/app/staking/home/StakedCard.tsx index ae74dfae9dfac..61410aa189843 100644 --- a/apps/wallet/src/ui/app/staking/home/StakedCard.tsx +++ b/apps/wallet/src/ui/app/staking/home/StakedCard.tsx @@ -6,8 +6,8 @@ import { CountDownTimer } from '_src/ui/app/shared/countdown-timer'; import { Text } from '_src/ui/app/shared/text'; import { IconTooltip } from '_src/ui/app/shared/tooltip'; import { useFormatCoin, useGetTimeBeforeEpochNumber } from '@mysten/core'; -import { type StakeObject } from '@mysten/sui.js/client'; -import { SUI_TYPE_ARG } from '@mysten/sui.js/utils'; +import { type StakeObject } from '@mysten/sui/client'; +import { SUI_TYPE_ARG } from '@mysten/sui/utils'; import { cva, cx, type VariantProps } from 'class-variance-authority'; import type { ReactNode } from 'react'; import { Link } from 'react-router-dom'; diff --git a/apps/wallet/src/ui/app/staking/stake/StakingCard.tsx b/apps/wallet/src/ui/app/staking/stake/StakingCard.tsx index b64d1f2aa29cd..16cc11a26b4c0 100644 --- a/apps/wallet/src/ui/app/staking/stake/StakingCard.tsx +++ b/apps/wallet/src/ui/app/staking/stake/StakingCard.tsx @@ -20,8 +20,8 @@ import { useFeatureIsOn } from '@growthbook/growthbook-react'; import { useCoinMetadata, useGetDelegatedStake } from '@mysten/core'; import { useSuiClientQuery } from '@mysten/dapp-kit'; import { ArrowLeft16 } from '@mysten/icons'; -import type { StakeObject } from '@mysten/sui.js/client'; -import { MIST_PER_SUI, SUI_TYPE_ARG } from '@mysten/sui.js/utils'; +import type { StakeObject } from '@mysten/sui/client'; +import { MIST_PER_SUI, SUI_TYPE_ARG } from '@mysten/sui/utils'; import * as Sentry from '@sentry/react'; import { useMutation, useQueryClient } from '@tanstack/react-query'; import { Formik } from 'formik'; diff --git a/apps/wallet/src/ui/app/staking/stake/UnstakeForm.tsx b/apps/wallet/src/ui/app/staking/stake/UnstakeForm.tsx index 6c6f77009308a..22ef123157801 100644 --- a/apps/wallet/src/ui/app/staking/stake/UnstakeForm.tsx +++ b/apps/wallet/src/ui/app/staking/stake/UnstakeForm.tsx @@ -5,7 +5,7 @@ import { Card } from '_app/shared/card'; import { Text } from '_app/shared/text'; import { CountDownTimer } from '_src/ui/app/shared/countdown-timer'; import { useFormatCoin, useGetTimeBeforeEpochNumber } from '@mysten/core'; -import { SUI_TYPE_ARG } from '@mysten/sui.js/utils'; +import { SUI_TYPE_ARG } from '@mysten/sui/utils'; import { Form } from 'formik'; import { useMemo } from 'react'; diff --git a/apps/wallet/src/ui/app/staking/stake/utils/transaction.ts b/apps/wallet/src/ui/app/staking/stake/utils/transaction.ts index 70f24b14169b9..c1d4e643fd8c7 100644 --- a/apps/wallet/src/ui/app/staking/stake/utils/transaction.ts +++ b/apps/wallet/src/ui/app/staking/stake/utils/transaction.ts @@ -1,11 +1,11 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -import { TransactionBlock } from '@mysten/sui.js/transactions'; -import { SUI_SYSTEM_STATE_OBJECT_ID } from '@mysten/sui.js/utils'; +import { Transaction } from '@mysten/sui/transactions'; +import { SUI_SYSTEM_STATE_OBJECT_ID } from '@mysten/sui/utils'; export function createStakeTransaction(amount: bigint, validator: string) { - const tx = new TransactionBlock(); + const tx = new Transaction(); const stakeCoin = tx.splitCoins(tx.gas, [amount]); tx.moveCall({ target: '0x3::sui_system::request_add_stake', @@ -23,7 +23,7 @@ export function createStakeTransaction(amount: bigint, validator: string) { } export function createUnstakeTransaction(stakedSuiId: string) { - const tx = new TransactionBlock(); + const tx = new Transaction(); tx.moveCall({ target: '0x3::sui_system::request_withdraw_stake', arguments: [tx.object(SUI_SYSTEM_STATE_OBJECT_ID), tx.object(stakedSuiId)], diff --git a/apps/wallet/src/ui/app/staking/validators/ValidatorLogo.tsx b/apps/wallet/src/ui/app/staking/validators/ValidatorLogo.tsx index d73408263818c..9fbe8b8d8564b 100644 --- a/apps/wallet/src/ui/app/staking/validators/ValidatorLogo.tsx +++ b/apps/wallet/src/ui/app/staking/validators/ValidatorLogo.tsx @@ -5,7 +5,7 @@ import { ImageIcon } from '_app/shared/image-icon'; import { Text } from '_app/shared/text'; import { Badge } from '_src/ui/app/shared/Badge'; import { useSuiClientQuery } from '@mysten/dapp-kit'; -import { formatAddress } from '@mysten/sui.js/utils'; +import { formatAddress } from '@mysten/sui/utils'; import cl from 'clsx'; import { useMemo } from 'react'; diff --git a/apps/wallet/src/ui/app/staking/validators/ValidatorsCard.tsx b/apps/wallet/src/ui/app/staking/validators/ValidatorsCard.tsx index e0e940a39d5b4..2fd519b42a7ab 100644 --- a/apps/wallet/src/ui/app/staking/validators/ValidatorsCard.tsx +++ b/apps/wallet/src/ui/app/staking/validators/ValidatorsCard.tsx @@ -15,7 +15,7 @@ import { import { useGetDelegatedStake } from '@mysten/core'; import { useSuiClientQuery } from '@mysten/dapp-kit'; import { Plus12 } from '@mysten/icons'; -import type { StakeObject } from '@mysten/sui.js/client'; +import type { StakeObject } from '@mysten/sui/client'; import { useMemo } from 'react'; import { useActiveAddress } from '../../hooks/useActiveAddress'; diff --git a/apps/wallet/tests/demo-app/src/index.tsx b/apps/wallet/tests/demo-app/src/index.tsx index f2529770a9f92..15fb58f123b16 100644 --- a/apps/wallet/tests/demo-app/src/index.tsx +++ b/apps/wallet/tests/demo-app/src/index.tsx @@ -2,13 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 import { type SuiWallet } from '_src/dapp-interface/WalletStandardInterface'; -import { TransactionBlock } from '@mysten/sui.js/transactions'; +import { Transaction } from '@mysten/sui/transactions'; import { getWallets, ReadonlyWalletAccount, type Wallet } from '@mysten/wallet-standard'; import { useEffect, useState } from 'react'; import ReactDOM from 'react-dom/client'; function getDemoTransaction(address: string) { - const txb = new TransactionBlock(); + const txb = new Transaction(); const [coin] = txb.splitCoins(txb.gas, [1]); txb.transferObjects([coin], address); return txb; @@ -93,11 +93,11 @@ function App() {