From 9c1f69c6790bcfa2d77505060062f426dff732c9 Mon Sep 17 00:00:00 2001 From: Bo Wu Date: Sun, 24 Nov 2024 20:10:23 -0800 Subject: [PATCH 01/78] get progress from right db --- storage/aptosdb/src/backup/restore_handler.rs | 2 +- storage/aptosdb/src/state_kv_db.rs | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/storage/aptosdb/src/backup/restore_handler.rs b/storage/aptosdb/src/backup/restore_handler.rs index e9be0ae54bf36..42339c122da73 100644 --- a/storage/aptosdb/src/backup/restore_handler.rs +++ b/storage/aptosdb/src/backup/restore_handler.rs @@ -132,7 +132,7 @@ impl RestoreHandler { } pub fn get_in_progress_state_kv_snapshot_version(&self) -> Result> { - let db = self.aptosdb.ledger_db.metadata_db_arc(); + let db = self.aptosdb.state_kv_db.metadata_db_arc(); let mut iter = db.iter::()?; iter.seek_to_first(); while let Some((k, _v)) = iter.next().transpose()? { diff --git a/storage/aptosdb/src/state_kv_db.rs b/storage/aptosdb/src/state_kv_db.rs index 27d28bf7f2696..35c1d01e3bbda 100644 --- a/storage/aptosdb/src/state_kv_db.rs +++ b/storage/aptosdb/src/state_kv_db.rs @@ -201,6 +201,10 @@ impl StateKvDb { &self.state_kv_metadata_db } + pub(crate) fn metadata_db_arc(&self) -> Arc { + Arc::clone(&self.state_kv_metadata_db) + } + pub(crate) fn db_shard(&self, shard_id: u8) -> &DB { &self.state_kv_db_shards[shard_id as usize] } From 0f219d856aa887de2e6d29dbec098780583297cc Mon Sep 17 00:00:00 2001 From: Aaron Date: Tue, 3 Dec 2024 13:27:05 -0600 Subject: [PATCH 02/78] add 3 devnet txn with module events migrated (#15448) --- ...78753811_coin_transfer_with_v2_events.json | 224 ++++++++++++ ...token_v1_mint_transfer_with_v2_events.json | 296 +++++++++++++++ ...token_v2_mint_transfer_with_v2_events.json | 338 ++++++++++++++++++ 3 files changed, 858 insertions(+) create mode 100644 ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/imported_devnet_txns/78753811_coin_transfer_with_v2_events.json create mode 100644 ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/imported_devnet_txns/78753831_token_v1_mint_transfer_with_v2_events.json create mode 100644 ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/imported_devnet_txns/78753832_token_v2_mint_transfer_with_v2_events.json diff --git a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/imported_devnet_txns/78753811_coin_transfer_with_v2_events.json b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/imported_devnet_txns/78753811_coin_transfer_with_v2_events.json new file mode 100644 index 0000000000000..da8144a60cee1 --- /dev/null +++ b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/imported_devnet_txns/78753811_coin_transfer_with_v2_events.json @@ -0,0 +1,224 @@ +{ + "timestamp": { + "seconds": "1733169023", + "nanos": 607104000 + }, + "version": "78753811", + "info": { + "hash": "78AycFoduM5wZDbsCsMjZ5x7xaGmYUYsGwGWcTJ7QLs=", + "stateChangeHash": "Oy7P0tj9JFVYUm0rfxkF4dIkCLPbG98l8Wjd0k+jLyY=", + "eventRootHash": "z0ZIe1JzEBtGyo6IUKVuxoGa98vP7xPhLSsnVInQ4PQ=", + "gasUsed": "7", + "success": true, + "vmStatus": "Executed successfully", + "accumulatorRootHash": "aw9XZJK27gS1QOlm1zD+Qt+A7vyNPuhlmFf/lz7VuHk=", + "changes": [ + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x74512d8383e6857a9a587012c44ad98420cbc713301714402611d7f87a7f4fe0", + "stateKeyHash": "H+BsjnXgnvstj69e0KbR9VL8YyGz6eyuZ5aBlMtTaYw=", + "type": { + "address": "0x1", + "module": "coin", + "name": "CoinStore", + "genericTypeParams": [ + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "aptos_coin", + "name": "AptosCoin" + } + } + ] + }, + "typeStr": "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>", + "data": "{\"coin\":{\"value\":\"2\"},\"deposit_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x74512d8383e6857a9a587012c44ad98420cbc713301714402611d7f87a7f4fe0\",\"creation_num\":\"2\"}}},\"frozen\":false,\"withdraw_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x74512d8383e6857a9a587012c44ad98420cbc713301714402611d7f87a7f4fe0\",\"creation_num\":\"3\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0xe93dcd3dd5febf8d72bf8d33e1d85a6115300fedfe055c062834d264f103ce4c", + "stateKeyHash": "GyEDoNkbSkI/rXXhfOPJk7mOq/wyMbpwiE2mga8YbF4=", + "type": { + "address": "0x1", + "module": "coin", + "name": "CoinStore", + "genericTypeParams": [ + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "aptos_coin", + "name": "AptosCoin" + } + } + ] + }, + "typeStr": "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>", + "data": "{\"coin\":{\"value\":\"34464975541459\"},\"deposit_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0xe93dcd3dd5febf8d72bf8d33e1d85a6115300fedfe055c062834d264f103ce4c\",\"creation_num\":\"2\"}}},\"frozen\":false,\"withdraw_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0xe93dcd3dd5febf8d72bf8d33e1d85a6115300fedfe055c062834d264f103ce4c\",\"creation_num\":\"3\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0xe93dcd3dd5febf8d72bf8d33e1d85a6115300fedfe055c062834d264f103ce4c", + "stateKeyHash": "f20QhQxKQpYq+vQlsCOfyelvFcaXWS1sF9rP0ilbwAk=", + "type": { + "address": "0x1", + "module": "account", + "name": "Account" + }, + "typeStr": "0x1::account::Account", + "data": "{\"authentication_key\":\"0xe93dcd3dd5febf8d72bf8d33e1d85a6115300fedfe055c062834d264f103ce4c\",\"coin_register_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0xe93dcd3dd5febf8d72bf8d33e1d85a6115300fedfe055c062834d264f103ce4c\",\"creation_num\":\"0\"}}},\"guid_creation_num\":\"8\",\"key_rotation_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0xe93dcd3dd5febf8d72bf8d33e1d85a6115300fedfe055c062834d264f103ce4c\",\"creation_num\":\"1\"}}},\"rotation_capability_offer\":{\"for\":{\"vec\":[]}},\"sequence_number\":\"2195678\",\"signer_capability_offer\":{\"for\":{\"vec\":[]}}}" + } + }, + { + "type": "TYPE_WRITE_TABLE_ITEM", + "writeTableItem": { + "stateKeyHash": "bkso1A+YoQamUWNTCSTA3LQME0nTqpFdEItNbPwd2xk=", + "handle": "0x1b854694ae746cdbd8d44186ca4929b2b337df21d1c74633be19b2710552fdca", + "key": "0x0619dc29a0aac8fa146714058e8dd6d2d0f3bdf5f6331907bf91f3acd81e6935", + "data": { + "key": "\"0x619dc29a0aac8fa146714058e8dd6d2d0f3bdf5f6331907bf91f3acd81e6935\"", + "keyType": "address", + "value": "\"18447249875628517278\"", + "valueType": "u128" + } + } + } + ] + }, + "epoch": "63", + "blockHeight": "10811317", + "type": "TRANSACTION_TYPE_USER", + "sizeInfo": { + "transactionBytes": 311, + "eventSizeInfo": [ + { + "typeTagBytes": 52, + "totalBytes": 119 + }, + { + "typeTagBytes": 51, + "totalBytes": 118 + }, + { + "typeTagBytes": 63, + "totalBytes": 103 + } + ], + "writeOpSizeInfo": [ + { + "keyBytes": 138, + "valueBytes": 105 + }, + { + "keyBytes": 138, + "valueBytes": 105 + }, + { + "keyBytes": 84, + "valueBytes": 147 + }, + { + "keyBytes": 66, + "valueBytes": 16 + } + ] + }, + "user": { + "request": { + "sender": "0xe93dcd3dd5febf8d72bf8d33e1d85a6115300fedfe055c062834d264f103ce4c", + "sequenceNumber": "2195677", + "maxGasAmount": "2000000", + "gasUnitPrice": "100", + "expirationTimestampSecs": { + "seconds": "1733169083" + }, + "payload": { + "type": "TYPE_ENTRY_FUNCTION_PAYLOAD", + "entryFunctionPayload": { + "function": { + "module": { + "address": "0x1", + "name": "coin" + }, + "name": "transfer" + }, + "typeArguments": [ + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "aptos_coin", + "name": "AptosCoin" + } + } + ], + "arguments": [ + "\"0x74512d8383e6857a9a587012c44ad98420cbc713301714402611d7f87a7f4fe0\"", + "\"1\"" + ], + "entryFunctionIdStr": "0x1::coin::transfer" + } + }, + "signature": { + "type": "TYPE_ED25519", + "ed25519": { + "publicKey": "vRgtbj9K0drw2U5T2q7OY+vVcdio4AmKAqTAtOzHyZ4=", + "signature": "q+BUcKerXUuzrATrJomw74pTkK8WzRrGUa8kzxlvo/Fa8xjpEZprvsfFODGcK3+/Rd/bYX/44JzGLTvBnICzCQ==" + } + } + }, + "events": [ + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "coin", + "name": "CoinWithdraw" + } + }, + "typeStr": "0x1::coin::CoinWithdraw", + "data": "{\"account\":\"0xe93dcd3dd5febf8d72bf8d33e1d85a6115300fedfe055c062834d264f103ce4c\",\"amount\":\"1\",\"coin_type\":\"0x1::aptos_coin::AptosCoin\"}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "coin", + "name": "CoinDeposit" + } + }, + "typeStr": "0x1::coin::CoinDeposit", + "data": "{\"account\":\"0x74512d8383e6857a9a587012c44ad98420cbc713301714402611d7f87a7f4fe0\",\"amount\":\"1\",\"coin_type\":\"0x1::aptos_coin::AptosCoin\"}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "transaction_fee", + "name": "FeeStatement" + } + }, + "typeStr": "0x1::transaction_fee::FeeStatement", + "data": "{\"execution_gas_units\":\"4\",\"io_gas_units\":\"4\",\"storage_fee_octas\":\"0\",\"storage_fee_refund_octas\":\"0\",\"total_charge_gas_units\":\"7\"}" + } + ] + } +} \ No newline at end of file diff --git a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/imported_devnet_txns/78753831_token_v1_mint_transfer_with_v2_events.json b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/imported_devnet_txns/78753831_token_v1_mint_transfer_with_v2_events.json new file mode 100644 index 0000000000000..725a1a81f293c --- /dev/null +++ b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/imported_devnet_txns/78753831_token_v1_mint_transfer_with_v2_events.json @@ -0,0 +1,296 @@ +{ + "timestamp": { + "seconds": "1733169023", + "nanos": 770129000 + }, + "version": "78753831", + "info": { + "hash": "w43BNnsj2PpsBN9oFPQeQkI6b83Tk1eK9ZaEibr79FA=", + "stateChangeHash": "zhKFGl5yxOh4aN1WvrYBcvFJZpQdf9PBwOQ+o+45upQ=", + "eventRootHash": "mDCT5P4esI+dEzcyuCK2p8QAVD0H6MZqih0xtBMkMZg=", + "gasUsed": "991", + "success": true, + "vmStatus": "Executed successfully", + "accumulatorRootHash": "oitILmzkmDySUYinpeA7XX1D51P23qxsZ3b2dUw3qqQ=", + "changes": [ + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x348cd99611633b0eb8ee803016bcd26bae4ce9d2954da8ab060cd90ecea39118", + "stateKeyHash": "G8wwBS2eFOFY8cN2oSttNxgsNsx8qVY24+nnKxHwfA8=", + "type": { + "address": "0x1", + "module": "coin", + "name": "CoinStore", + "genericTypeParams": [ + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "aptos_coin", + "name": "AptosCoin" + } + } + ] + }, + "typeStr": "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>", + "data": "{\"coin\":{\"value\":\"34465468193254\"},\"deposit_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x348cd99611633b0eb8ee803016bcd26bae4ce9d2954da8ab060cd90ecea39118\",\"creation_num\":\"2\"}}},\"frozen\":false,\"withdraw_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x348cd99611633b0eb8ee803016bcd26bae4ce9d2954da8ab060cd90ecea39118\",\"creation_num\":\"3\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x348cd99611633b0eb8ee803016bcd26bae4ce9d2954da8ab060cd90ecea39118", + "stateKeyHash": "ONtWpx0BPmQGVKRDjVp92/c1/zBTK7hDfZfVMc5ITPQ=", + "type": { + "address": "0x1", + "module": "account", + "name": "Account" + }, + "typeStr": "0x1::account::Account", + "data": "{\"authentication_key\":\"0x348cd99611633b0eb8ee803016bcd26bae4ce9d2954da8ab060cd90ecea39118\",\"coin_register_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x348cd99611633b0eb8ee803016bcd26bae4ce9d2954da8ab060cd90ecea39118\",\"creation_num\":\"0\"}}},\"guid_creation_num\":\"8\",\"key_rotation_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x348cd99611633b0eb8ee803016bcd26bae4ce9d2954da8ab060cd90ecea39118\",\"creation_num\":\"1\"}}},\"rotation_capability_offer\":{\"for\":{\"vec\":[]}},\"sequence_number\":\"2187669\",\"signer_capability_offer\":{\"for\":{\"vec\":[]}}}" + } + }, + { + "type": "TYPE_WRITE_TABLE_ITEM", + "writeTableItem": { + "stateKeyHash": "bkso1A+YoQamUWNTCSTA3LQME0nTqpFdEItNbPwd2xk=", + "handle": "0x1b854694ae746cdbd8d44186ca4929b2b337df21d1c74633be19b2710552fdca", + "key": "0x0619dc29a0aac8fa146714058e8dd6d2d0f3bdf5f6331907bf91f3acd81e6935", + "data": { + "key": "\"0x619dc29a0aac8fa146714058e8dd6d2d0f3bdf5f6331907bf91f3acd81e6935\"", + "keyType": "address", + "value": "\"18447249875627498778\"", + "valueType": "u128" + } + } + }, + { + "type": "TYPE_WRITE_TABLE_ITEM", + "writeTableItem": { + "stateKeyHash": "CfmP4qLNgYoUjFJnVN2TJbQXLHm9mQrdkLSngiSh0i4=", + "handle": "0x5b2921d6a8a8a6565432e265672fd6b9a06e243c31a7634f207eefc88fb2e7cf", + "key": "0xcdc14b3f3edbbb739a0a7168661ae562449dd88ede045f4a310a4cf41489001a16416e204e465420436f6c6c656374696f6e204e616d65164e465420436f6c6c65637469626c65202331333336300000000000000000", + "data": { + "key": "{\"property_version\":\"0\",\"token_data_id\":{\"collection\":\"An NFT Collection Name\",\"creator\":\"0xcdc14b3f3edbbb739a0a7168661ae562449dd88ede045f4a310a4cf41489001a\",\"name\":\"NFT Collectible #13360\"}}", + "keyType": "0x3::token::TokenId", + "value": "{\"amount\":\"1\",\"id\":{\"property_version\":\"0\",\"token_data_id\":{\"collection\":\"An NFT Collection Name\",\"creator\":\"0xcdc14b3f3edbbb739a0a7168661ae562449dd88ede045f4a310a4cf41489001a\",\"name\":\"NFT Collectible #13360\"}},\"token_properties\":{\"map\":{\"data\":[]}}}", + "valueType": "0x3::token::Token" + } + } + }, + { + "type": "TYPE_WRITE_TABLE_ITEM", + "writeTableItem": { + "stateKeyHash": "a/8/9Al4bygHSJUzkGvmZz+Afwf1UNkssWEwj7lnD8k=", + "handle": "0x7b4b066837bccc25b973a04a0618695db6172e8ad0f2abbba29882cf7b9134a8", + "key": "0xcdc14b3f3edbbb739a0a7168661ae562449dd88ede045f4a310a4cf41489001a16416e204e465420436f6c6c656374696f6e204e616d65164e465420436f6c6c65637469626c6520233133333630", + "data": { + "key": "{\"collection\":\"An NFT Collection Name\",\"creator\":\"0xcdc14b3f3edbbb739a0a7168661ae562449dd88ede045f4a310a4cf41489001a\",\"name\":\"NFT Collectible #13360\"}", + "keyType": "0x3::token::TokenDataId", + "value": "{\"default_properties\":{\"map\":{\"data\":[]}},\"description\":\"\",\"largest_property_version\":\"0\",\"maximum\":\"1\",\"mutability_config\":{\"description\":true,\"maximum\":true,\"properties\":true,\"royalty\":true,\"uri\":true},\"name\":\"NFT Collectible #13360\",\"royalty\":{\"payee_address\":\"0xcdc14b3f3edbbb739a0a7168661ae562449dd88ede045f4a310a4cf41489001a\",\"royalty_points_denominator\":\"100\",\"royalty_points_numerator\":\"0\"},\"supply\":\"1\",\"uri\":\"https://aptos.dev\"}", + "valueType": "0x3::token::TokenData" + } + } + }, + { + "type": "TYPE_WRITE_TABLE_ITEM", + "writeTableItem": { + "stateKeyHash": "p9Kn+cQa0KMTZmXw2ojtJzd94Y7gnrmTjdrSzg2DQsI=", + "handle": "0xfcaac4a1ffb8df81d954b182c31ddb77e2d506fac218104bd7ec67029b0fa46f", + "key": "0x16416e204e465420436f6c6c656374696f6e204e616d65", + "data": { + "key": "\"An NFT Collection Name\"", + "keyType": "0x1::string::String", + "value": "{\"description\":\"An NFT Collection Description\",\"maximum\":\"1000000\",\"mutability_config\":{\"description\":false,\"maximum\":false,\"uri\":false},\"name\":\"An NFT Collection Name\",\"supply\":\"13360\",\"uri\":\"\"}", + "valueType": "0x3::token::CollectionData" + } + } + } + ] + }, + "epoch": "63", + "blockHeight": "10811321", + "type": "TRANSACTION_TYPE_USER", + "sizeInfo": { + "transactionBytes": 284, + "eventSizeInfo": [ + { + "typeTagBytes": 58, + "totalBytes": 274 + }, + { + "typeTagBytes": 45, + "totalBytes": 163 + }, + { + "typeTagBytes": 53, + "totalBytes": 179 + }, + { + "typeTagBytes": 54, + "totalBytes": 180 + }, + { + "typeTagBytes": 53, + "totalBytes": 179 + }, + { + "typeTagBytes": 63, + "totalBytes": 103 + } + ], + "writeOpSizeInfo": [ + { + "keyBytes": 138, + "valueBytes": 105 + }, + { + "keyBytes": 84, + "valueBytes": 147 + }, + { + "keyBytes": 66, + "valueBytes": 16 + }, + { + "keyBytes": 120, + "valueBytes": 95 + }, + { + "keyBytes": 112, + "valueBytes": 120 + }, + { + "keyBytes": 57, + "valueBytes": 73 + } + ] + }, + "user": { + "request": { + "sender": "0x348cd99611633b0eb8ee803016bcd26bae4ce9d2954da8ab060cd90ecea39118", + "sequenceNumber": "2187668", + "maxGasAmount": "2000000", + "gasUnitPrice": "100", + "expirationTimestampSecs": { + "seconds": "1733169083" + }, + "payload": { + "type": "TYPE_ENTRY_FUNCTION_PAYLOAD", + "entryFunctionPayload": { + "function": { + "module": { + "address": "0xa1a48478a4f217b97198b9d828bd00abd8d96120bb97aca904e6203448f6babc", + "name": "token_v1" + }, + "name": "token_v1_mint_and_transfer_nft_sequential" + }, + "arguments": [ + "\"0xa1a48478a4f217b97198b9d828bd00abd8d96120bb97aca904e6203448f6babc\"" + ], + "entryFunctionIdStr": "0xa1a48478a4f217b97198b9d828bd00abd8d96120bb97aca904e6203448f6babc::token_v1::token_v1_mint_and_transfer_nft_sequential" + } + }, + "signature": { + "type": "TYPE_ED25519", + "ed25519": { + "publicKey": "zBz/l6D5927191fRkjZWR6pwgMB7ecJLy047B8yBVjQ=", + "signature": "uFT4XF+VuXYOUHSTakrwtGDzuNd3Nq+nweQZ64ZPsnxB10h4pYLBC7EIcH3o8+zXk1lIlMndiKa+LCQPYbt7DA==" + } + } + }, + "events": [ + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x3", + "module": "token", + "name": "TokenDataCreation" + } + }, + "typeStr": "0x3::token::TokenDataCreation", + "data": "{\"creator\":\"0xcdc14b3f3edbbb739a0a7168661ae562449dd88ede045f4a310a4cf41489001a\",\"description\":\"\",\"id\":{\"collection\":\"An NFT Collection Name\",\"creator\":\"0xcdc14b3f3edbbb739a0a7168661ae562449dd88ede045f4a310a4cf41489001a\",\"name\":\"NFT Collectible #13360\"},\"maximum\":\"1\",\"mutability_config\":{\"description\":true,\"maximum\":true,\"properties\":true,\"royalty\":true,\"uri\":true},\"name\":\"NFT Collectible #13360\",\"property_keys\":[],\"property_types\":[],\"property_values\":[],\"royalty_payee_address\":\"0xcdc14b3f3edbbb739a0a7168661ae562449dd88ede045f4a310a4cf41489001a\",\"royalty_points_denominator\":\"100\",\"royalty_points_numerator\":\"0\",\"uri\":\"https://aptos.dev\"}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x3", + "module": "token", + "name": "Mint" + } + }, + "typeStr": "0x3::token::Mint", + "data": "{\"amount\":\"1\",\"creator\":\"0xcdc14b3f3edbbb739a0a7168661ae562449dd88ede045f4a310a4cf41489001a\",\"id\":{\"collection\":\"An NFT Collection Name\",\"creator\":\"0xcdc14b3f3edbbb739a0a7168661ae562449dd88ede045f4a310a4cf41489001a\",\"name\":\"NFT Collectible #13360\"}}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x3", + "module": "token", + "name": "TokenDeposit" + } + }, + "typeStr": "0x3::token::TokenDeposit", + "data": "{\"account\":\"0xcdc14b3f3edbbb739a0a7168661ae562449dd88ede045f4a310a4cf41489001a\",\"amount\":\"1\",\"id\":{\"property_version\":\"0\",\"token_data_id\":{\"collection\":\"An NFT Collection Name\",\"creator\":\"0xcdc14b3f3edbbb739a0a7168661ae562449dd88ede045f4a310a4cf41489001a\",\"name\":\"NFT Collectible #13360\"}}}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x3", + "module": "token", + "name": "TokenWithdraw" + } + }, + "typeStr": "0x3::token::TokenWithdraw", + "data": "{\"account\":\"0xcdc14b3f3edbbb739a0a7168661ae562449dd88ede045f4a310a4cf41489001a\",\"amount\":\"1\",\"id\":{\"property_version\":\"0\",\"token_data_id\":{\"collection\":\"An NFT Collection Name\",\"creator\":\"0xcdc14b3f3edbbb739a0a7168661ae562449dd88ede045f4a310a4cf41489001a\",\"name\":\"NFT Collectible #13360\"}}}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x3", + "module": "token", + "name": "TokenDeposit" + } + }, + "typeStr": "0x3::token::TokenDeposit", + "data": "{\"account\":\"0x348cd99611633b0eb8ee803016bcd26bae4ce9d2954da8ab060cd90ecea39118\",\"amount\":\"1\",\"id\":{\"property_version\":\"0\",\"token_data_id\":{\"collection\":\"An NFT Collection Name\",\"creator\":\"0xcdc14b3f3edbbb739a0a7168661ae562449dd88ede045f4a310a4cf41489001a\",\"name\":\"NFT Collectible #13360\"}}}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "transaction_fee", + "name": "FeeStatement" + } + }, + "typeStr": "0x1::transaction_fee::FeeStatement", + "data": "{\"execution_gas_units\":\"8\",\"io_gas_units\":\"6\",\"storage_fee_octas\":\"97720\",\"storage_fee_refund_octas\":\"0\",\"total_charge_gas_units\":\"991\"}" + } + ] + } +} \ No newline at end of file diff --git a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/imported_devnet_txns/78753832_token_v2_mint_transfer_with_v2_events.json b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/imported_devnet_txns/78753832_token_v2_mint_transfer_with_v2_events.json new file mode 100644 index 0000000000000..c4503d3e48128 --- /dev/null +++ b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/imported_devnet_txns/78753832_token_v2_mint_transfer_with_v2_events.json @@ -0,0 +1,338 @@ +{ + "timestamp": { + "seconds": "1733169023", + "nanos": 770129000 + }, + "version": "78753832", + "info": { + "hash": "sbaO6U6E3bhIKcFeuMVR8Xg1TdsxK0cVUtGOIVkcZ24=", + "stateChangeHash": "f52yKEG7gyDZM2YaX2PFziFjiuB/v4TBZhYAXUa2EKY=", + "eventRootHash": "b4xyZ6VqYs9tBxUfxdNX9Qd3Gns99NMqQFvJHmUFros=", + "gasUsed": "801", + "success": true, + "vmStatus": "Executed successfully", + "accumulatorRootHash": "ONu16d7ZHQOqFI/1QxNSWTtRkv6XruTpMrJ3TuP4ckA=", + "changes": [ + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x28adfb8a46395e7ccd83038860764193eea3f834ae6894e75cd80a3e1ff23b0b", + "stateKeyHash": "0AEC/45myF2zNRsWE3y0u12bQQupMZHK3wzx+6fGCYk=", + "type": { + "address": "0x1", + "module": "coin", + "name": "CoinStore", + "genericTypeParams": [ + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "aptos_coin", + "name": "AptosCoin" + } + } + ] + }, + "typeStr": "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>", + "data": "{\"coin\":{\"value\":\"34465517137401\"},\"deposit_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x28adfb8a46395e7ccd83038860764193eea3f834ae6894e75cd80a3e1ff23b0b\",\"creation_num\":\"2\"}}},\"frozen\":false,\"withdraw_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x28adfb8a46395e7ccd83038860764193eea3f834ae6894e75cd80a3e1ff23b0b\",\"creation_num\":\"3\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x28adfb8a46395e7ccd83038860764193eea3f834ae6894e75cd80a3e1ff23b0b", + "stateKeyHash": "hG1GLIWoqV80Zg25NMtZIfr73saxe+eXw1Wn1z/FwVg=", + "type": { + "address": "0x1", + "module": "account", + "name": "Account" + }, + "typeStr": "0x1::account::Account", + "data": "{\"authentication_key\":\"0x28adfb8a46395e7ccd83038860764193eea3f834ae6894e75cd80a3e1ff23b0b\",\"coin_register_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x28adfb8a46395e7ccd83038860764193eea3f834ae6894e75cd80a3e1ff23b0b\",\"creation_num\":\"0\"}}},\"guid_creation_num\":\"8\",\"key_rotation_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x28adfb8a46395e7ccd83038860764193eea3f834ae6894e75cd80a3e1ff23b0b\",\"creation_num\":\"1\"}}},\"rotation_capability_offer\":{\"for\":{\"vec\":[]}},\"sequence_number\":\"2184764\",\"signer_capability_offer\":{\"for\":{\"vec\":[]}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x58677eec16fc1a3d37dcfe5fa3ab62081d0838a694612a34e757caa7f7f2adb0", + "stateKeyHash": "u9MRoQG+Gm9/JPOstdsHZxrIOVzruB84dVjePLJ1dlk=", + "type": { + "address": "0x1", + "module": "object", + "name": "ObjectCore" + }, + "typeStr": "0x1::object::ObjectCore", + "data": "{\"allow_ungated_transfer\":false,\"guid_creation_num\":\"1125899906842626\",\"owner\":\"0xc8185b4484917ffda406f31fb71ab9a2b9ac7387041235b21dd7e4e5bdccb838\",\"transfer_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x58677eec16fc1a3d37dcfe5fa3ab62081d0838a694612a34e757caa7f7f2adb0\",\"creation_num\":\"1125899906842624\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x58677eec16fc1a3d37dcfe5fa3ab62081d0838a694612a34e757caa7f7f2adb0", + "stateKeyHash": "u9MRoQG+Gm9/JPOstdsHZxrIOVzruB84dVjePLJ1dlk=", + "type": { + "address": "0x4", + "module": "collection", + "name": "Collection" + }, + "typeStr": "0x4::collection::Collection", + "data": "{\"creator\":\"0xc8185b4484917ffda406f31fb71ab9a2b9ac7387041235b21dd7e4e5bdccb838\",\"description\":\"Ambassador Collection Description\",\"mutation_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x58677eec16fc1a3d37dcfe5fa3ab62081d0838a694612a34e757caa7f7f2adb0\",\"creation_num\":\"1125899906842625\"}}},\"name\":\"Ambassador Collection Name\",\"uri\":\"Ambassador Collection URI\"}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x58677eec16fc1a3d37dcfe5fa3ab62081d0838a694612a34e757caa7f7f2adb0", + "stateKeyHash": "u9MRoQG+Gm9/JPOstdsHZxrIOVzruB84dVjePLJ1dlk=", + "type": { + "address": "0x4", + "module": "collection", + "name": "ConcurrentSupply" + }, + "typeStr": "0x4::collection::ConcurrentSupply", + "data": "{\"current_supply\":{\"max_value\":\"18446744073709551615\",\"value\":\"133740\"},\"total_minted\":{\"max_value\":\"18446744073709551615\",\"value\":\"133740\"}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0xb63f1fe89e713c0bbd093ea2f5d7af58fa69e90af27035f0b2e202e66d432d6b", + "stateKeyHash": "mpG7Q4U/DJ8w2RLTcP5NfSr94LNKgcACM9ljxIwE720=", + "type": { + "address": "0x1", + "module": "object", + "name": "ObjectCore" + }, + "typeStr": "0x1::object::ObjectCore", + "data": "{\"allow_ungated_transfer\":false,\"guid_creation_num\":\"1125899906842626\",\"owner\":\"0x28adfb8a46395e7ccd83038860764193eea3f834ae6894e75cd80a3e1ff23b0b\",\"transfer_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0xb63f1fe89e713c0bbd093ea2f5d7af58fa69e90af27035f0b2e202e66d432d6b\",\"creation_num\":\"1125899906842624\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0xb63f1fe89e713c0bbd093ea2f5d7af58fa69e90af27035f0b2e202e66d432d6b", + "stateKeyHash": "mpG7Q4U/DJ8w2RLTcP5NfSr94LNKgcACM9ljxIwE720=", + "type": { + "address": "0x4", + "module": "property_map", + "name": "PropertyMap" + }, + "typeStr": "0x4::property_map::PropertyMap", + "data": "{\"inner\":{\"data\":[{\"key\":\"Rank\",\"value\":{\"type\":9,\"value\":\"0x0642726f6e7a65\"}}]}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0xb63f1fe89e713c0bbd093ea2f5d7af58fa69e90af27035f0b2e202e66d432d6b", + "stateKeyHash": "mpG7Q4U/DJ8w2RLTcP5NfSr94LNKgcACM9ljxIwE720=", + "type": { + "address": "0x4", + "module": "token", + "name": "Token" + }, + "typeStr": "0x4::token::Token", + "data": "{\"collection\":{\"inner\":\"0x58677eec16fc1a3d37dcfe5fa3ab62081d0838a694612a34e757caa7f7f2adb0\"},\"description\":\"pd9eIPNuxydkn3JJsYvGKVGMomZXCvuc1EQ92PzpIW512zEeCJEKGXR21707nHmzRLokNVfJ5ufd5jzk3GINOLAZ2CjGlsM2SJWb\",\"index\":\"0\",\"mutation_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0xb63f1fe89e713c0bbd093ea2f5d7af58fa69e90af27035f0b2e202e66d432d6b\",\"creation_num\":\"1125899906842625\"}}},\"name\":\"\",\"uri\":\"fEL4YUz13hHhi573dzmC0yulbUh7RGcHxWjDteeRIuPE0dfBVBBronze\"}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0xb63f1fe89e713c0bbd093ea2f5d7af58fa69e90af27035f0b2e202e66d432d6b", + "stateKeyHash": "mpG7Q4U/DJ8w2RLTcP5NfSr94LNKgcACM9ljxIwE720=", + "type": { + "address": "0x4", + "module": "token", + "name": "TokenIdentifiers" + }, + "typeStr": "0x4::token::TokenIdentifiers", + "data": "{\"index\":{\"value\":\"133740\"},\"name\":{\"padding\":\"0x0000000000000000000000000000\",\"value\":\"superstar #133740\"}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0xb63f1fe89e713c0bbd093ea2f5d7af58fa69e90af27035f0b2e202e66d432d6b", + "stateKeyHash": "mpG7Q4U/DJ8w2RLTcP5NfSr94LNKgcACM9ljxIwE720=", + "type": { + "address": "0xc8185b4484917ffda406f31fb71ab9a2b9ac7387041235b21dd7e4e5bdccb838", + "module": "ambassador", + "name": "AmbassadorLevel" + }, + "typeStr": "0xc8185b4484917ffda406f31fb71ab9a2b9ac7387041235b21dd7e4e5bdccb838::ambassador::AmbassadorLevel", + "data": "{\"ambassador_level\":\"0\"}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0xb63f1fe89e713c0bbd093ea2f5d7af58fa69e90af27035f0b2e202e66d432d6b", + "stateKeyHash": "mpG7Q4U/DJ8w2RLTcP5NfSr94LNKgcACM9ljxIwE720=", + "type": { + "address": "0xc8185b4484917ffda406f31fb71ab9a2b9ac7387041235b21dd7e4e5bdccb838", + "module": "ambassador", + "name": "AmbassadorToken" + }, + "typeStr": "0xc8185b4484917ffda406f31fb71ab9a2b9ac7387041235b21dd7e4e5bdccb838::ambassador::AmbassadorToken", + "data": "{\"base_uri\":\"fEL4YUz13hHhi573dzmC0yulbUh7RGcHxWjDteeRIuPE0dfBVB\",\"burn_ref\":{\"inner\":{\"vec\":[{\"self\":\"0xb63f1fe89e713c0bbd093ea2f5d7af58fa69e90af27035f0b2e202e66d432d6b\"}]},\"self\":{\"vec\":[]}},\"mutator_ref\":{\"self\":\"0xb63f1fe89e713c0bbd093ea2f5d7af58fa69e90af27035f0b2e202e66d432d6b\"},\"property_mutator_ref\":{\"self\":\"0xb63f1fe89e713c0bbd093ea2f5d7af58fa69e90af27035f0b2e202e66d432d6b\"}}" + } + }, + { + "type": "TYPE_WRITE_TABLE_ITEM", + "writeTableItem": { + "stateKeyHash": "bkso1A+YoQamUWNTCSTA3LQME0nTqpFdEItNbPwd2xk=", + "handle": "0x1b854694ae746cdbd8d44186ca4929b2b337df21d1c74633be19b2710552fdca", + "key": "0x0619dc29a0aac8fa146714058e8dd6d2d0f3bdf5f6331907bf91f3acd81e6935", + "data": { + "key": "\"0x619dc29a0aac8fa146714058e8dd6d2d0f3bdf5f6331907bf91f3acd81e6935\"", + "keyType": "address", + "value": "\"18447249875627418678\"", + "valueType": "u128" + } + } + } + ] + }, + "epoch": "63", + "blockHeight": "10811321", + "type": "TRANSACTION_TYPE_USER", + "sizeInfo": { + "transactionBytes": 551, + "eventSizeInfo": [ + { + "typeTagBytes": 50, + "totalBytes": 122 + }, + { + "typeTagBytes": 50, + "totalBytes": 146 + }, + { + "typeTagBytes": 63, + "totalBytes": 103 + } + ], + "writeOpSizeInfo": [ + { + "keyBytes": 138, + "valueBytes": 105 + }, + { + "keyBytes": 84, + "valueBytes": 147 + }, + { + "keyBytes": 87, + "valueBytes": 460 + }, + { + "keyBytes": 87, + "valueBytes": 888 + }, + { + "keyBytes": 66, + "valueBytes": 16 + } + ] + }, + "user": { + "request": { + "sender": "0x28adfb8a46395e7ccd83038860764193eea3f834ae6894e75cd80a3e1ff23b0b", + "sequenceNumber": "2184763", + "maxGasAmount": "2000000", + "gasUnitPrice": "100", + "expirationTimestampSecs": { + "seconds": "1733169083" + }, + "payload": { + "type": "TYPE_ENTRY_FUNCTION_PAYLOAD", + "entryFunctionPayload": { + "function": { + "module": { + "address": "0xc8185b4484917ffda406f31fb71ab9a2b9ac7387041235b21dd7e4e5bdccb838", + "name": "ambassador" + }, + "name": "mint_numbered_ambassador_token_by_user" + }, + "arguments": [ + "\"pd9eIPNuxydkn3JJsYvGKVGMomZXCvuc1EQ92PzpIW512zEeCJEKGXR21707nHmzRLokNVfJ5ufd5jzk3GINOLAZ2CjGlsM2SJWb\"", + "\"superstar #\"", + "\"fEL4YUz13hHhi573dzmC0yulbUh7RGcHxWjDteeRIuPE0dfBVB\"" + ], + "entryFunctionIdStr": "0xc8185b4484917ffda406f31fb71ab9a2b9ac7387041235b21dd7e4e5bdccb838::ambassador::mint_numbered_ambassador_token_by_user" + } + }, + "signature": { + "type": "TYPE_MULTI_AGENT", + "multiAgent": { + "sender": { + "type": "TYPE_ED25519", + "ed25519": { + "publicKey": "3wy7e9bUTFltc/XIZB3O1mjKaTljWNPAKZwkCMA0Qxo=", + "signature": "K07rNzIE6DdPaUh2dzGi1CZjsDVvEk9JlZG4JA5FVYciKMCKo/gFtXoPC0uy1IzD+43oNmm6VVWoEPNIWYa+DA==" + } + }, + "secondarySignerAddresses": [ + "0xc8185b4484917ffda406f31fb71ab9a2b9ac7387041235b21dd7e4e5bdccb838" + ], + "secondarySigners": [ + { + "type": "TYPE_ED25519", + "ed25519": { + "publicKey": "/MmBThZ+Z4pcJGTjePvN+ySARSKW5tJMJoBxBLhvorc=", + "signature": "E9son29Wkr0nNzJmRPKy8RBVGgtdGNg4zxlKCMQPaSlTtFkrCJ+BjAYiVN8Jd/0qqCGmNEhxDW3AeAPJ2IAtAQ==" + } + } + ] + } + } + }, + "events": [ + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x4", + "module": "collection", + "name": "Mint" + } + }, + "typeStr": "0x4::collection::Mint", + "data": "{\"collection\":\"0x58677eec16fc1a3d37dcfe5fa3ab62081d0838a694612a34e757caa7f7f2adb0\",\"index\":{\"value\":\"133740\"},\"token\":\"0xb63f1fe89e713c0bbd093ea2f5d7af58fa69e90af27035f0b2e202e66d432d6b\"}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "object", + "name": "Transfer" + } + }, + "typeStr": "0x1::object::Transfer", + "data": "{\"from\":\"0xc8185b4484917ffda406f31fb71ab9a2b9ac7387041235b21dd7e4e5bdccb838\",\"object\":\"0xb63f1fe89e713c0bbd093ea2f5d7af58fa69e90af27035f0b2e202e66d432d6b\",\"to\":\"0x28adfb8a46395e7ccd83038860764193eea3f834ae6894e75cd80a3e1ff23b0b\"}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "transaction_fee", + "name": "FeeStatement" + } + }, + "typeStr": "0x1::transaction_fee::FeeStatement", + "data": "{\"execution_gas_units\":\"6\",\"io_gas_units\":\"6\",\"storage_fee_octas\":\"78920\",\"storage_fee_refund_octas\":\"0\",\"total_charge_gas_units\":\"801\"}" + } + ] + } +} \ No newline at end of file From 612018cce1f87c98ec44ab080af5f03d630575c5 Mon Sep 17 00:00:00 2001 From: Bo Wu Date: Tue, 3 Dec 2024 09:51:07 -0800 Subject: [PATCH 03/78] reduce cost --- testsuite/replay-verify/archive_disk_utils.py | 71 ++++++++++++------- 1 file changed, 44 insertions(+), 27 deletions(-) diff --git a/testsuite/replay-verify/archive_disk_utils.py b/testsuite/replay-verify/archive_disk_utils.py index bb1e67a1d6060..14d2194c2309f 100644 --- a/testsuite/replay-verify/archive_disk_utils.py +++ b/testsuite/replay-verify/archive_disk_utils.py @@ -22,6 +22,10 @@ MAINNET_SNAPSHOT_NAME = "mainnet-archive" +def get_region_from_zone(zone): + return zone.rsplit("-", 1)[0] + + def get_kubectl_credentials(project_id, region, cluster_name): try: # Command to get kubectl credentials for the cluster @@ -141,6 +145,8 @@ def create_snapshot_with_gcloud( source_disk_link, "--project", target_project, + "--storage-location", + get_region_from_zone(source_zone), ] try: @@ -156,6 +162,22 @@ def create_snapshot_with_gcloud( raise Exception(f"Error creating snapshot: {e}") +def delete_disk(disk_client, project, zone, disk_name): + # Check if the disk already exists + + try: + disk = disk_client.get(project=project, zone=zone, disk=disk_name) + logger.info(f"Disk {disk_name} already exists. Deleting it.") + # Delete the existing disk + operation = disk_client.delete(project=project, zone=zone, disk=disk_name) + wait_for_operation( + project, zone, operation.name, compute_v1.ZoneOperationsClient() + ) + logger.info(f"Disk {disk_name} deleted.") + except Exception as e: + logger.info(f"Disk {e} {disk_name} does not exist, no delete needed.") + + # Creating disk from import snapshots # require getting a hold of the kubectrl of the cluster # eg: gcloud container clusters get-credentials replay-on-archive --region us-central1 --project replay-verify @@ -172,19 +194,7 @@ def create_disk_pv_pvc_from_snapshot( ): disk_client = compute_v1.DisksClient() snapshot_client = compute_v1.SnapshotsClient() - - # Check if the disk already exists - try: - disk = disk_client.get(project=project, zone=zone, disk=disk_name) - logger.info(f"Disk {disk_name} already exists. Deleting it.") - # Delete the existing disk - operation = disk_client.delete(project=project, zone=zone, disk=disk_name) - wait_for_operation( - project, zone, operation.name, compute_v1.ZoneOperationsClient() - ) - logger.info(f"Disk {disk_name} deleted.") - except Exception as e: - logger.info(f"Disk {e} {disk_name} does not exist. Creating a new one.") + delete_disk(disk_client, project, zone, disk_name) # Create a new disk from the snapshot logger.info(f"Creating disk {disk_name} from snapshot {og_snapshot_name}.") @@ -199,14 +209,16 @@ def create_disk_pv_pvc_from_snapshot( wait_for_operation(project, zone, operation.name, compute_v1.ZoneOperationsClient()) logger.info(f"Disk {disk_name} created from snapshot {og_snapshot_name}.") - region_name = zone.rsplit("-", 1)[0] + region_name = get_region_from_zone(zone) get_kubectl_credentials(project, region_name, cluster_name) # create_persistent_volume(disk_name, pv_name, pvc_name, namespace, True) # this is only for xfs replaying logs to repair the disk repair_pv = f"{pv_name}-repair" repair_pvc = f"{pvc_name}-repair" repair_job_name = f"xfs-repair-{pvc_name}" - create_persistent_volume(disk_name, repair_pv, repair_pvc, namespace, False) + create_persistent_volume( + project, zone, disk_name, repair_pv, repair_pvc, namespace, False + ) # start a pod to mount the disk and run simple task with open("xfs-disk-repair.yaml", "r") as f: pod_manifest = yaml.safe_load(f) @@ -228,6 +240,9 @@ def create_disk_pv_pvc_from_snapshot( time.sleep(10) logger.info(f"creating final snapshot") create_snapshot_with_gcloud(snapshot_name, project, disk_name, zone, project) + logger.info("deleting repair disks") + # delete the disk used for repair + delete_disk(disk_client, project, zone, disk_name) def is_job_pod_cleanedup(namespace, job_name): @@ -255,7 +270,9 @@ def wait_for_operation(project, zone, operation_name, zone_operations_client): time.sleep(20) -def create_persistent_volume(disk_name, pv_name, pvc_name, namespace, read_only): +def create_persistent_volume( + project, zone, disk_name, pv_name, pvc_name, namespace, read_only +): config.load_kube_config() v1 = client.CoreV1Api() @@ -286,20 +303,22 @@ def create_persistent_volume(disk_name, pv_name, pvc_name, namespace, read_only) raise # Create PersistentVolume + volume_handle = f"projects/{project}/zones/{zone}/disks/{disk_name}" pv = client.V1PersistentVolume( api_version="v1", kind="PersistentVolume", metadata=client.V1ObjectMeta(name=pv_name), spec=client.V1PersistentVolumeSpec( capacity={"storage": "10000Gi"}, - access_modes=["ReadOnlyMany"], - gce_persistent_disk=client.V1GCEPersistentDiskVolumeSource( - pd_name=disk_name, + access_modes=["ReadWriteOnce"], + csi=client.V1CSIPersistentVolumeSource( + driver="pd.csi.storage.gke.io", + volume_handle=volume_handle, fs_type="xfs", read_only=read_only, ), - persistent_volume_reclaim_policy="Retain", - storage_class_name="standard", + persistent_volume_reclaim_policy="Retain", # this is to delete the PV and disk separately to speed up pv deletion + storage_class_name="ssd-data-xfs", ), ) @@ -309,9 +328,9 @@ def create_persistent_volume(disk_name, pv_name, pvc_name, namespace, read_only) kind="PersistentVolumeClaim", metadata=client.V1ObjectMeta(name=pvc_name, namespace=namespace), spec=client.V1PersistentVolumeClaimSpec( - access_modes=["ReadOnlyMany"], + access_modes=["ReadWriteOnce"], resources=client.V1ResourceRequirements(requests={"storage": "10000Gi"}), - storage_class_name="standard", + storage_class_name="ssd-data-xfs", volume_name=pv_name, ), ) @@ -427,7 +446,7 @@ def create_pvcs_from_snapshot(run_id, snapshot_name, namespace, pvc_num, label): return res -def create_disk_pv_pvc( +def create_repair_disk_and_its_snapshot( project, zone, cluster_name, og_snapshot_name, snapshot_name, prefix, namespace ): tasks = [] @@ -462,8 +481,6 @@ def create_disk_pv_pvc( except Exception as e: logger.error(f"Task generated an exception: {e}") - # start a self deleteing job to mount the xfs disks for repairing - def parse_args(): parser = argparse.ArgumentParser( @@ -506,7 +523,7 @@ def parse_args(): source_namespace, project_id, ) - create_disk_pv_pvc( + create_repair_disk_and_its_snapshot( project_id, zone, cluster_name, From c0b97e25c3871614ac7eb4104f7bdedde25d025c Mon Sep 17 00:00:00 2001 From: runtianz Date: Wed, 4 Dec 2024 10:29:02 +0800 Subject: [PATCH 04/78] [script-composer] Add infer functionality, fix multiple return values (#15438) --- aptos-move/script-composer/src/builder.rs | 39 ++++++---- aptos-move/script-composer/src/tests/mod.rs | 74 ++++++++++++++++++- .../src/tests/test_modules/sources/test.move | 6 +- 3 files changed, 103 insertions(+), 16 deletions(-) diff --git a/aptos-move/script-composer/src/builder.rs b/aptos-move/script-composer/src/builder.rs index 07c2442a0bc89..db30acf85d877 100644 --- a/aptos-move/script-composer/src/builder.rs +++ b/aptos-move/script-composer/src/builder.rs @@ -317,14 +317,35 @@ impl TransactionComposer { .collect::>() }; - for return_ty in expected_returns_ty { + let mut returned_arguments = vec![]; + let num_of_calls = self.calls.len() as u16; + + for (idx, return_ty) in expected_returns_ty.into_iter().enumerate() { + let ability = BinaryIndexedView::Script(self.builder.as_script()) + .abilities(&return_ty, &[]) + .map_err(|_| anyhow!("Failed to calculate ability for type"))?; + let local_idx = self.locals_ty.len() as u16; self.locals_ty.push(return_ty); self.locals_availability.push(true); returns.push(local_idx); + + // For values that has drop and copy ability, use copy by default to avoid calling copy manually + // on the client side. + returned_arguments.push(CallArgument::PreviousResult(PreviousResult { + operation_type: if ability.has_drop() && ability.has_copy() { + ArgumentOperation::Copy + } else { + ArgumentOperation::Move + }, + call_idx: num_of_calls, + return_idx: idx as u16, + })); } - let num_of_calls = self.calls.len() as u16; + if self.parameters.len() + self.locals_ty.len() > u8::MAX as usize { + bail!("Too many locals being allocated, please truncate the transaction"); + } self.calls.push(BuilderCall { type_args: type_arguments, @@ -335,15 +356,7 @@ impl TransactionComposer { type_tags: ty_args, }); - Ok((0..returns.len()) - .map(|idx| { - CallArgument::PreviousResult(PreviousResult { - operation_type: ArgumentOperation::Move, - call_idx: num_of_calls, - return_idx: idx as u16, - }) - }) - .collect()) + Ok(returned_arguments) } fn check_drop_at_end(&self) -> anyhow::Result<()> { @@ -390,11 +403,11 @@ impl TransactionComposer { } // Storing return values - for arg in call.returns { + for arg in call.returns.iter().rev() { script .code .code - .push(Bytecode::StLoc((arg + parameters_count) as u8)); + .push(Bytecode::StLoc((*arg + parameters_count) as u8)); } } script.code.code.push(Bytecode::Ret); diff --git a/aptos-move/script-composer/src/tests/mod.rs b/aptos-move/script-composer/src/tests/mod.rs index a2d84338a7898..71c88dea1142a 100644 --- a/aptos-move/script-composer/src/tests/mod.rs +++ b/aptos-move/script-composer/src/tests/mod.rs @@ -301,7 +301,9 @@ fn test_module() { run_txn(builder, &mut h); - // Create a copyable value and move it twice + // Create a droppable and copyable value and move it twice. This is ok because the builder + // will use copy instruction instead of move instruction for values that are both copyable + // and droppable. let mut builder = TransactionComposer::single_signer(); load_module(&mut builder, &h, "0x1::batched_execution"); let returns_1 = builder @@ -329,7 +331,7 @@ fn test_module() { ) .unwrap(); - assert!(builder + builder .add_batched_call( "0x1::batched_execution".to_string(), "consume_copyable_value".to_string(), @@ -339,6 +341,47 @@ fn test_module() { CallArgument::new_bytes(MoveValue::U8(10).simple_serialize().unwrap()), ], ) + .unwrap(); + + run_txn(builder, &mut h); + + // Create a droppable value and move it twice + let mut builder = TransactionComposer::single_signer(); + load_module(&mut builder, &h, "0x1::batched_execution"); + let returns_1 = builder + .add_batched_call( + "0x1::batched_execution".to_string(), + "create_droppable_value".to_string(), + vec![], + vec![CallArgument::new_bytes( + MoveValue::U8(10).simple_serialize().unwrap(), + )], + ) + .unwrap() + .pop() + .unwrap(); + + builder + .add_batched_call( + "0x1::batched_execution".to_string(), + "consume_droppable_value".to_string(), + vec![], + vec![ + returns_1.clone(), + CallArgument::new_bytes(MoveValue::U8(10).simple_serialize().unwrap()), + ], + ) + .unwrap(); + assert!(builder + .add_batched_call( + "0x1::batched_execution".to_string(), + "consume_droppable_value".to_string(), + vec![], + vec![ + returns_1, + CallArgument::new_bytes(MoveValue::U8(10).simple_serialize().unwrap()), + ], + ) .is_err()); // Copying a non-copyable value should return error on call. @@ -635,4 +678,31 @@ fn test_module() { ], ) .is_err()); + + // Test functions with multiple return values. + // Create a copyable value and copy it twice + let mut builder = TransactionComposer::single_signer(); + load_module(&mut builder, &h, "0x1::batched_execution"); + let returns = builder + .add_batched_call( + "0x1::batched_execution".to_string(), + "multiple_returns".to_string(), + vec![], + vec![], + ) + .unwrap(); + + builder + .add_batched_call( + "0x1::batched_execution".to_string(), + "consume_non_droppable_value".to_string(), + vec![], + vec![ + returns[1].clone(), + CallArgument::new_bytes(MoveValue::U8(1).simple_serialize().unwrap()), + ], + ) + .unwrap(); + + run_txn(builder, &mut h); } diff --git a/aptos-move/script-composer/src/tests/test_modules/sources/test.move b/aptos-move/script-composer/src/tests/test_modules/sources/test.move index fbbc7cab8269b..8af34963c0d23 100644 --- a/aptos-move/script-composer/src/tests/test_modules/sources/test.move +++ b/aptos-move/script-composer/src/tests/test_modules/sources/test.move @@ -10,7 +10,7 @@ module 0x1::batched_execution { val: u8, } - struct CopyableValue has copy { + struct CopyableValue has drop, copy { val: u8, } @@ -73,4 +73,8 @@ module 0x1::batched_execution { let GenericNonDroppableValue { val } = v; assert!(val == expected_val, 10); } + + public fun multiple_returns(): (DroppableValue, NonDroppableValue) { + return (DroppableValue { val: 0 }, NonDroppableValue { val: 1} ) + } } From 57602f0de73079c8120c7c7806170cbed858aad8 Mon Sep 17 00:00:00 2001 From: Bo Wu Date: Wed, 20 Nov 2024 09:19:22 -0800 Subject: [PATCH 05/78] remove error detail from default feature list --- aptos-move/aptos-vm/src/aptos_vm.rs | 1 - .../aptosdb/src/db/include/aptosdb_writer.rs | 7 +--- types/src/on_chain_config/aptos_features.rs | 1 - types/src/proptest_types.rs | 4 +-- types/src/transaction/mod.rs | 34 +------------------ 5 files changed, 4 insertions(+), 43 deletions(-) diff --git a/aptos-move/aptos-vm/src/aptos_vm.rs b/aptos-move/aptos-vm/src/aptos_vm.rs index f2afca7412a88..30251e439bc62 100644 --- a/aptos-move/aptos-vm/src/aptos_vm.rs +++ b/aptos-move/aptos-vm/src/aptos_vm.rs @@ -475,7 +475,6 @@ impl AptosVM { error_vm_status.clone(), self.features() .is_enabled(FeatureFlag::CHARGE_INVARIANT_VIOLATION), - self.features(), ); match txn_status { diff --git a/storage/aptosdb/src/db/include/aptosdb_writer.rs b/storage/aptosdb/src/db/include/aptosdb_writer.rs index 493b6e61c7cde..babbd5c5d1c78 100644 --- a/storage/aptosdb/src/db/include/aptosdb_writer.rs +++ b/storage/aptosdb/src/db/include/aptosdb_writer.rs @@ -308,12 +308,6 @@ impl AptosDB { .commit_transaction_accumulator(chunk.first_version, chunk.transaction_infos) .unwrap() }); - s.spawn(|_| { - self.commit_transaction_auxiliary_data( - chunk.first_version, - chunk.transaction_outputs.iter().map(TransactionOutput::auxiliary_data)) - .unwrap() - }); }); Ok(new_root_hash) @@ -488,6 +482,7 @@ impl AptosDB { Ok(root_hash) } + #[allow(dead_code)] fn commit_transaction_auxiliary_data<'a>( &self, first_version: Version, diff --git a/types/src/on_chain_config/aptos_features.rs b/types/src/on_chain_config/aptos_features.rs index 905c907b7df4e..4b4faa2f2dd6e 100644 --- a/types/src/on_chain_config/aptos_features.rs +++ b/types/src/on_chain_config/aptos_features.rs @@ -163,7 +163,6 @@ impl FeatureFlag { FeatureFlag::COIN_TO_FUNGIBLE_ASSET_MIGRATION, FeatureFlag::OBJECT_NATIVE_DERIVED_ADDRESS, FeatureFlag::DISPATCHABLE_FUNGIBLE_ASSET, - FeatureFlag::REMOVE_DETAILED_ERROR_FROM_HASH, FeatureFlag::CONCURRENT_FUNGIBLE_ASSETS, FeatureFlag::AGGREGATOR_V2_IS_AT_LEAST_API, FeatureFlag::CONCURRENT_FUNGIBLE_BALANCE, diff --git a/types/src/proptest_types.rs b/types/src/proptest_types.rs index 334caf53b6210..8c3c0180ff718 100644 --- a/types/src/proptest_types.rs +++ b/types/src/proptest_types.rs @@ -19,7 +19,7 @@ use crate::{ epoch_state::EpochState, event::{EventHandle, EventKey}, ledger_info::{generate_ledger_info_with_sig, LedgerInfo, LedgerInfoWithSignatures}, - on_chain_config::{Features, ValidatorSet}, + on_chain_config::ValidatorSet, proof::TransactionInfoListWithProof, state_store::state_key::StateKey, transaction::{ @@ -497,7 +497,7 @@ impl TransactionPayload { prop_compose! { fn arb_transaction_status()(vm_status in any::()) -> TransactionStatus { - let (txn_status, _) = TransactionStatus::from_vm_status(vm_status, true, &Features::default()); + let (txn_status, _) = TransactionStatus::from_vm_status(vm_status, true); txn_status } } diff --git a/types/src/transaction/mod.rs b/types/src/transaction/mod.rs index f626b2def15f7..dabdae0acba76 100644 --- a/types/src/transaction/mod.rs +++ b/types/src/transaction/mod.rs @@ -11,7 +11,6 @@ use crate::{ contract_event::{ContractEvent, FEE_STATEMENT_EVENT_TYPE}, keyless::{KeylessPublicKey, KeylessSignature}, ledger_info::LedgerInfo, - on_chain_config::{FeatureFlag, Features}, proof::{TransactionInfoListWithProof, TransactionInfoWithProof}, transaction::authenticator::{ AccountAuthenticator, AnyPublicKey, AnySignature, SingleKeyAuthenticator, @@ -914,22 +913,6 @@ impl ExecutionStatus { _ => ExecutionStatus::MiscellaneousError(None), } } - - pub fn remove_error_detail(self) -> Self { - match self { - ExecutionStatus::MoveAbort { - location, - code, - info: _, - } => ExecutionStatus::MoveAbort { - location, - code, - info: None, - }, - ExecutionStatus::MiscellaneousError(_) => ExecutionStatus::MiscellaneousError(None), - _ => self, - } - } } /// The status of executing a transaction. The VM decides whether or not we should `Keep` the @@ -982,7 +965,6 @@ impl TransactionStatus { pub fn from_vm_status( vm_status: VMStatus, charge_invariant_violation: bool, - features: &Features, ) -> (Self, TransactionAuxiliaryData) { let status_code = vm_status.status_code(); let txn_aux = TransactionAuxiliaryData::from_vm_status(&vm_status); @@ -1005,21 +987,7 @@ impl TransactionStatus { } }, }; - - if features.is_enabled(FeatureFlag::REMOVE_DETAILED_ERROR_FROM_HASH) { - (status.remove_error_detail(), txn_aux) - } else { - (status, txn_aux) - } - } - - pub fn remove_error_detail(self) -> Self { - match self { - TransactionStatus::Keep(status) => { - TransactionStatus::Keep(status.remove_error_detail()) - }, - _ => self, - } + (status, txn_aux) } pub fn from_executed_vm_status(vm_status: VMStatus) -> Self { From 7f1f7df848bce1c91251855e22c123c994e9921d Mon Sep 17 00:00:00 2001 From: Bo Wu Date: Thu, 21 Nov 2024 14:34:13 -0800 Subject: [PATCH 06/78] update tests --- .../src/components/feature_flags.rs | 8 ++- .../aptos_test_harness/borrow_in_loop.exp | 4 +- .../aptos_test_harness/borrow_in_loop.v2_exp | 4 +- .../aptos_test_harness/diamond_clicker.exp | 2 +- aptos-move/aptos-vm-types/src/output.rs | 11 +--- aptos-move/aptos-vm-types/src/tests/utils.rs | 3 +- aptos-move/aptos-vm/src/aptos_vm.rs | 19 ++----- .../user_transaction_sessions/epilogue.rs | 4 +- aptos-move/e2e-move-tests/src/harness.rs | 14 ++--- .../src/tests/code_publishing.rs | 15 ++---- aptos-move/e2e-move-tests/src/tests/vm.rs | 11 +--- ...__tests__data_store__borrow_after_move.exp | 26 +--------- ...__tests__data_store__change_after_move.exp | 39 ++------------ ...s__data_store__move_from_across_blocks.exp | 52 ++----------------- ...__scripts__script_bad_sig_function_dep.exp | 15 ++---- ...sts__scripts__script_code_unverifiable.exp | 15 ++---- ...ed_type_argument_module_does_not_exist.exp | 15 ++---- ...ipts__script_non_existing_function_dep.exp | 15 ++---- ...ripts__script_none_existing_module_dep.exp | 15 ++---- ...pt_type_argument_module_does_not_exist.exp | 15 ++---- ...y_txn__test_arbitrary_script_execution.exp | 15 ++---- ...t_script_dependency_fails_verification.exp | 15 ++---- ...ansitive_dependency_fails_verification.exp | 15 ++---- ...type_tag_dependency_fails_verification.exp | 15 ++---- ...ansitive_dependency_fails_verification.exp | 15 ++---- aptos-move/e2e-tests/src/executor.rs | 6 +-- execution/executor-benchmark/src/lib.rs | 6 +-- .../src/native/native_vm.rs | 3 +- types/src/on_chain_config/aptos_features.rs | 6 +-- types/src/proptest_types.rs | 3 +- types/src/transaction/mod.rs | 22 ++------ 31 files changed, 90 insertions(+), 333 deletions(-) diff --git a/aptos-move/aptos-release-builder/src/components/feature_flags.rs b/aptos-move/aptos-release-builder/src/components/feature_flags.rs index b980063aa1fd7..dc71091298b85 100644 --- a/aptos-move/aptos-release-builder/src/components/feature_flags.rs +++ b/aptos-move/aptos-release-builder/src/components/feature_flags.rs @@ -285,7 +285,9 @@ impl From for AptosFeatureFlag { FeatureFlag::ReconfigureWithDkg => AptosFeatureFlag::_DEPRECATED_RECONFIGURE_WITH_DKG, FeatureFlag::KeylessAccounts => AptosFeatureFlag::KEYLESS_ACCOUNTS, FeatureFlag::KeylessButZklessAccounts => AptosFeatureFlag::KEYLESS_BUT_ZKLESS_ACCOUNTS, - FeatureFlag::RemoveDetailedError => AptosFeatureFlag::REMOVE_DETAILED_ERROR_FROM_HASH, + FeatureFlag::RemoveDetailedError => { + AptosFeatureFlag::_DEPRECATED_REMOVE_DETAILED_ERROR_FROM_HASH + }, FeatureFlag::JwkConsensus => AptosFeatureFlag::JWK_CONSENSUS, FeatureFlag::ConcurrentFungibleAssets => AptosFeatureFlag::CONCURRENT_FUNGIBLE_ASSETS, FeatureFlag::RefundableBytes => AptosFeatureFlag::REFUNDABLE_BYTES, @@ -430,7 +432,9 @@ impl From for FeatureFlag { AptosFeatureFlag::_DEPRECATED_RECONFIGURE_WITH_DKG => FeatureFlag::ReconfigureWithDkg, AptosFeatureFlag::KEYLESS_ACCOUNTS => FeatureFlag::KeylessAccounts, AptosFeatureFlag::KEYLESS_BUT_ZKLESS_ACCOUNTS => FeatureFlag::KeylessButZklessAccounts, - AptosFeatureFlag::REMOVE_DETAILED_ERROR_FROM_HASH => FeatureFlag::RemoveDetailedError, + AptosFeatureFlag::_DEPRECATED_REMOVE_DETAILED_ERROR_FROM_HASH => { + FeatureFlag::RemoveDetailedError + }, AptosFeatureFlag::JWK_CONSENSUS => FeatureFlag::JwkConsensus, AptosFeatureFlag::CONCURRENT_FUNGIBLE_ASSETS => FeatureFlag::ConcurrentFungibleAssets, AptosFeatureFlag::REFUNDABLE_BYTES => FeatureFlag::RefundableBytes, diff --git a/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/borrow_in_loop.exp b/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/borrow_in_loop.exp index 69a5b16b8f367..f7386474fbc02 100644 --- a/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/borrow_in_loop.exp +++ b/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/borrow_in_loop.exp @@ -4,7 +4,7 @@ task 1 'publish'. lines 4-26: Error: VMError with status STLOC_UNSAFE_TO_DESTROY_ERROR at location Module ModuleId { address: f75daa73fc071f93593335eb9033da804777eb94491650dd3f095ce6f778acb6, name: Identifier("m") } at index 0 for function definition at code offset 11 in function definition 0 task 2 'run'. lines 28-28: -Error: Failed to execute transaction. ExecutionStatus: MiscellaneousError(None) +Error: Failed to execute transaction. ExecutionStatus: MiscellaneousError(Some(LINKER_ERROR)) task 3 'run'. lines 30-44: -Error: Failed to execute transaction. ExecutionStatus: MiscellaneousError(None) +Error: Failed to execute transaction. ExecutionStatus: MiscellaneousError(Some(STLOC_UNSAFE_TO_DESTROY_ERROR)) diff --git a/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/borrow_in_loop.v2_exp b/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/borrow_in_loop.v2_exp index 69a5b16b8f367..f7386474fbc02 100644 --- a/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/borrow_in_loop.v2_exp +++ b/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/borrow_in_loop.v2_exp @@ -4,7 +4,7 @@ task 1 'publish'. lines 4-26: Error: VMError with status STLOC_UNSAFE_TO_DESTROY_ERROR at location Module ModuleId { address: f75daa73fc071f93593335eb9033da804777eb94491650dd3f095ce6f778acb6, name: Identifier("m") } at index 0 for function definition at code offset 11 in function definition 0 task 2 'run'. lines 28-28: -Error: Failed to execute transaction. ExecutionStatus: MiscellaneousError(None) +Error: Failed to execute transaction. ExecutionStatus: MiscellaneousError(Some(LINKER_ERROR)) task 3 'run'. lines 30-44: -Error: Failed to execute transaction. ExecutionStatus: MiscellaneousError(None) +Error: Failed to execute transaction. ExecutionStatus: MiscellaneousError(Some(STLOC_UNSAFE_TO_DESTROY_ERROR)) diff --git a/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/diamond_clicker.exp b/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/diamond_clicker.exp index 85b58331f150d..2ad9de1be64e9 100644 --- a/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/diamond_clicker.exp +++ b/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/diamond_clicker.exp @@ -73,4 +73,4 @@ bug: BYTECODE VERIFICATION FAILED task 3 'run'. lines 70-70: -Error: Failed to execute transaction. ExecutionStatus: MiscellaneousError(None) +Error: Failed to execute transaction. ExecutionStatus: MiscellaneousError(Some(LINKER_ERROR)) diff --git a/aptos-move/aptos-vm-types/src/output.rs b/aptos-move/aptos-vm-types/src/output.rs index df477b1b1c33e..d8c4ace6d7aaa 100644 --- a/aptos-move/aptos-vm-types/src/output.rs +++ b/aptos-move/aptos-vm-types/src/output.rs @@ -34,7 +34,6 @@ pub struct VMOutput { module_write_set: ModuleWriteSet, fee_statement: FeeStatement, status: TransactionStatus, - auxiliary_data: TransactionAuxiliaryData, } impl VMOutput { @@ -43,14 +42,12 @@ impl VMOutput { module_write_set: ModuleWriteSet, fee_statement: FeeStatement, status: TransactionStatus, - auxiliary_data: TransactionAuxiliaryData, ) -> Self { Self { change_set, module_write_set, fee_statement, status, - auxiliary_data, } } @@ -60,7 +57,6 @@ impl VMOutput { module_write_set: ModuleWriteSet::empty(), fee_statement: FeeStatement::zero(), status, - auxiliary_data: TransactionAuxiliaryData::default(), } } @@ -102,10 +98,6 @@ impl VMOutput { &self.status } - pub fn auxiliary_data(&self) -> &TransactionAuxiliaryData { - &self.auxiliary_data - } - pub fn materialized_size(&self) -> u64 { let mut size = 0; for (state_key, write_size) in self @@ -179,7 +171,6 @@ impl VMOutput { module_write_set, fee_statement, status, - auxiliary_data, } = self; let (write_set, events) = change_set .try_combine_into_storage_change_set(module_write_set)? @@ -189,7 +180,7 @@ impl VMOutput { events, fee_statement.gas_used(), status, - auxiliary_data, + TransactionAuxiliaryData::default(), )) } diff --git a/aptos-move/aptos-vm-types/src/tests/utils.rs b/aptos-move/aptos-vm-types/src/tests/utils.rs index 2cd4fbb5b4a4e..71bee8d9ead3f 100644 --- a/aptos-move/aptos-vm-types/src/tests/utils.rs +++ b/aptos-move/aptos-vm-types/src/tests/utils.rs @@ -16,7 +16,7 @@ use aptos_types::{ fee_statement::FeeStatement, on_chain_config::CurrentTimeMicroseconds, state_store::{state_key::StateKey, state_value::StateValueMetadata}, - transaction::{ExecutionStatus, TransactionAuxiliaryData, TransactionStatus}, + transaction::{ExecutionStatus, TransactionStatus}, write_set::WriteOp, }; use move_binary_format::errors::PartialVMResult; @@ -252,7 +252,6 @@ pub(crate) fn build_vm_output( ModuleWriteSet::new(false, module_write_set.into_iter().collect()), FeeStatement::new(GAS_USED, GAS_USED, 0, 0, 0), STATUS, - TransactionAuxiliaryData::default(), ) } diff --git a/aptos-move/aptos-vm/src/aptos_vm.rs b/aptos-move/aptos-vm/src/aptos_vm.rs index 30251e439bc62..1b469bcd82c9a 100644 --- a/aptos-move/aptos-vm/src/aptos_vm.rs +++ b/aptos-move/aptos-vm/src/aptos_vm.rs @@ -70,8 +70,8 @@ use aptos_types::{ authenticator::AnySignature, signature_verified_transaction::SignatureVerifiedTransaction, BlockOutput, EntryFunction, ExecutionError, ExecutionStatus, ModuleBundle, Multisig, MultisigTransactionPayload, Script, SignedTransaction, Transaction, TransactionArgument, - TransactionAuxiliaryData, TransactionOutput, TransactionPayload, TransactionStatus, - VMValidatorResult, ViewFunctionOutput, WriteSetPayload, + TransactionOutput, TransactionPayload, TransactionStatus, VMValidatorResult, + ViewFunctionOutput, WriteSetPayload, }, vm_status::{AbortLocation, StatusCode, VMStatus}, }; @@ -186,7 +186,6 @@ pub(crate) fn get_system_transaction_output( ModuleWriteSet::empty(), FeeStatement::zero(), TransactionStatus::Keep(ExecutionStatus::Success), - TransactionAuxiliaryData::default(), )) } @@ -471,7 +470,7 @@ impl AptosVM { } } - let (txn_status, txn_aux_data) = TransactionStatus::from_vm_status( + let txn_status = TransactionStatus::from_vm_status( error_vm_status.clone(), self.features() .is_enabled(FeatureFlag::CHARGE_INVARIANT_VIOLATION), @@ -493,7 +492,6 @@ impl AptosVM { resolver, module_storage, status, - txn_aux_data, log_context, change_set_configs, traversal_context, @@ -541,7 +539,6 @@ impl AptosVM { resolver: &impl AptosMoveResolver, module_storage: &impl AptosModuleStorage, status: ExecutionStatus, - txn_aux_data: TransactionAuxiliaryData, log_context: &AdapterLogSchema, change_set_configs: &ChangeSetConfigs, traversal_context: &mut TraversalContext, @@ -672,13 +669,7 @@ impl AptosVM { ) })?; - epilogue_session.finish( - fee_statement, - status, - txn_aux_data, - change_set_configs, - module_storage, - ) + epilogue_session.finish(fee_statement, status, change_set_configs, module_storage) } fn success_transaction_cleanup( @@ -728,7 +719,6 @@ impl AptosVM { let output = epilogue_session.finish( fee_statement, ExecutionStatus::Success, - TransactionAuxiliaryData::default(), change_set_configs, module_storage, )?; @@ -2307,7 +2297,6 @@ impl AptosVM { module_write_set, FeeStatement::zero(), TransactionStatus::Keep(ExecutionStatus::Success), - TransactionAuxiliaryData::default(), ); Ok((VMStatus::Executed, output)) } diff --git a/aptos-move/aptos-vm/src/move_vm_ext/session/user_transaction_sessions/epilogue.rs b/aptos-move/aptos-vm/src/move_vm_ext/session/user_transaction_sessions/epilogue.rs index 0d1c4e19d04e5..673941f5f876e 100644 --- a/aptos-move/aptos-vm/src/move_vm_ext/session/user_transaction_sessions/epilogue.rs +++ b/aptos-move/aptos-vm/src/move_vm_ext/session/user_transaction_sessions/epilogue.rs @@ -17,7 +17,7 @@ use crate::{ use aptos_gas_algebra::Fee; use aptos_types::{ fee_statement::FeeStatement, - transaction::{ExecutionStatus, TransactionAuxiliaryData, TransactionStatus}, + transaction::{ExecutionStatus, TransactionStatus}, }; use aptos_vm_types::{ change_set::VMChangeSet, module_and_script_storage::module_storage::AptosModuleStorage, @@ -104,7 +104,6 @@ impl<'r, 'l> EpilogueSession<'r, 'l> { self, fee_statement: FeeStatement, execution_status: ExecutionStatus, - txn_aux_data: TransactionAuxiliaryData, change_set_configs: &ChangeSetConfigs, module_storage: &impl AptosModuleStorage, ) -> Result { @@ -135,7 +134,6 @@ impl<'r, 'l> EpilogueSession<'r, 'l> { module_write_set, fee_statement, TransactionStatus::Keep(execution_status), - txn_aux_data, )) } } diff --git a/aptos-move/e2e-move-tests/src/harness.rs b/aptos-move/e2e-move-tests/src/harness.rs index eff6c4bde5845..c549d5b1efa61 100644 --- a/aptos-move/e2e-move-tests/src/harness.rs +++ b/aptos-move/e2e-move-tests/src/harness.rs @@ -196,12 +196,11 @@ impl MoveHarness { /// Runs a signed transaction. On success, applies the write set. pub fn run_raw(&mut self, txn: SignedTransaction) -> TransactionOutput { - let mut output = self.executor.execute_transaction(txn); + let output = self.executor.execute_transaction(txn); if matches!(output.status(), TransactionStatus::Keep(_)) { self.executor.apply_write_set(output.write_set()); self.executor.append_events(output.events().to_vec()); } - output.fill_error_status(); output } @@ -239,12 +238,11 @@ impl MoveHarness { &mut self, txn_block: Vec, ) -> Vec { - let mut result = assert_ok!(self.executor.execute_block(txn_block)); - for output in &mut result { + let result = assert_ok!(self.executor.execute_block(txn_block)); + for output in &result { if matches!(output.status(), TransactionStatus::Keep(_)) { self.executor.apply_write_set(output.write_set()); } - output.fill_error_status(); } result } @@ -979,11 +977,7 @@ impl MoveHarness { offset, txns.len() ); - let mut outputs = harness.run_block_get_output(txns); - let _ = outputs - .iter_mut() - .map(|t| t.fill_error_status()) - .collect::>(); + let outputs = harness.run_block_get_output(txns); for (idx, (error, output)) in errors.into_iter().zip(outputs.iter()).enumerate() { if error == SUCCESS { assert_success!( diff --git a/aptos-move/e2e-move-tests/src/tests/code_publishing.rs b/aptos-move/e2e-move-tests/src/tests/code_publishing.rs index b2be91feeff8e..ff14ee00287af 100644 --- a/aptos-move/e2e-move-tests/src/tests/code_publishing.rs +++ b/aptos-move/e2e-move-tests/src/tests/code_publishing.rs @@ -242,17 +242,10 @@ fn code_publishing_upgrade_loader_cache_consistency() { |_| {}, ), ]; - let result = h.run_block_get_output(txns); - assert_success!(result[0].status().to_owned()); - assert_success!(result[1].status().to_owned()); - assert_eq!( - result[2] - .auxiliary_data() - .get_detail_error_message() - .unwrap() - .status_code(), - StatusCode::BACKWARD_INCOMPATIBLE_MODULE_UPDATE - ) + let result = h.run_block(txns); + assert_success!(result[0]); + assert_success!(result[1]); + assert_vm_status!(result[2], StatusCode::BACKWARD_INCOMPATIBLE_MODULE_UPDATE) } #[test] diff --git a/aptos-move/e2e-move-tests/src/tests/vm.rs b/aptos-move/e2e-move-tests/src/tests/vm.rs index a7fea434e5571..ea5736d11faad 100644 --- a/aptos-move/e2e-move-tests/src/tests/vm.rs +++ b/aptos-move/e2e-move-tests/src/tests/vm.rs @@ -41,15 +41,6 @@ fn failed_transaction_cleanup_charges_gas(status_code: StatusCode) { balance, ) .1; - - assert_eq!( - output - .auxiliary_data() - .get_detail_error_message() - .unwrap() - .status_code(), - status_code - ); let write_set: Vec<(&StateKey, &WriteOp)> = output .concrete_write_set_iter() .map(|(k, v)| (k, assert_some!(v))) @@ -59,6 +50,6 @@ fn failed_transaction_cleanup_charges_gas(status_code: StatusCode) { assert!(!output.status().is_discarded()); assert_ok_eq!( output.status().as_kept_status(), - ExecutionStatus::MiscellaneousError(None) + ExecutionStatus::MiscellaneousError(Some(status_code)) ); } diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__data_store__borrow_after_move.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__data_store__borrow_after_move.exp index 2a0a37866f8fc..9629e1dada5c4 100644 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__data_store__borrow_after_move.exp +++ b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__data_store__borrow_after_move.exp @@ -21,18 +21,7 @@ Ok( code_offset: 2, }, ), - auxiliary_data: V1( - TransactionAuxiliaryDataV1 { - detail_error_message: Some( - VMErrorDetail { - status_code: MISSING_DATA, - message: Some( - "Failed to move resource from f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1", - ), - }, - ), - }, - ), + auxiliary_data: None, }, ], ) @@ -126,18 +115,7 @@ Ok( code_offset: 2, }, ), - auxiliary_data: V1( - TransactionAuxiliaryDataV1 { - detail_error_message: Some( - VMErrorDetail { - status_code: MISSING_DATA, - message: Some( - "Failed to borrow global resource from f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1", - ), - }, - ), - }, - ), + auxiliary_data: None, }, ], ) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__data_store__change_after_move.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__data_store__change_after_move.exp index 181f5c40a26ea..8abe2916afb35 100644 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__data_store__change_after_move.exp +++ b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__data_store__change_after_move.exp @@ -21,18 +21,7 @@ Ok( code_offset: 2, }, ), - auxiliary_data: V1( - TransactionAuxiliaryDataV1 { - detail_error_message: Some( - VMErrorDetail { - status_code: MISSING_DATA, - message: Some( - "Failed to move resource from f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1", - ), - }, - ), - }, - ), + auxiliary_data: None, }, ], ) @@ -126,18 +115,7 @@ Ok( code_offset: 2, }, ), - auxiliary_data: V1( - TransactionAuxiliaryDataV1 { - detail_error_message: Some( - VMErrorDetail { - status_code: MISSING_DATA, - message: Some( - "Failed to borrow global resource from f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1", - ), - }, - ), - }, - ), + auxiliary_data: None, }, ], ) @@ -164,18 +142,7 @@ Ok( code_offset: 2, }, ), - auxiliary_data: V1( - TransactionAuxiliaryDataV1 { - detail_error_message: Some( - VMErrorDetail { - status_code: MISSING_DATA, - message: Some( - "Failed to borrow global resource from f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1", - ), - }, - ), - }, - ), + auxiliary_data: None, }, ], ) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__data_store__move_from_across_blocks.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__data_store__move_from_across_blocks.exp index f1dda7b2d2b86..2b72d7c65c94b 100644 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__data_store__move_from_across_blocks.exp +++ b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__data_store__move_from_across_blocks.exp @@ -21,18 +21,7 @@ Ok( code_offset: 2, }, ), - auxiliary_data: V1( - TransactionAuxiliaryDataV1 { - detail_error_message: Some( - VMErrorDetail { - status_code: MISSING_DATA, - message: Some( - "Failed to move resource from f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1", - ), - }, - ), - }, - ), + auxiliary_data: None, }, ], ) @@ -130,18 +119,7 @@ Ok( code_offset: 2, }, ), - auxiliary_data: V1( - TransactionAuxiliaryDataV1 { - detail_error_message: Some( - VMErrorDetail { - status_code: MISSING_DATA, - message: Some( - "Failed to move resource from f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1", - ), - }, - ), - }, - ), + auxiliary_data: None, }, ], ) @@ -168,18 +146,7 @@ Ok( code_offset: 2, }, ), - auxiliary_data: V1( - TransactionAuxiliaryDataV1 { - detail_error_message: Some( - VMErrorDetail { - status_code: MISSING_DATA, - message: Some( - "Failed to borrow global resource from f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1", - ), - }, - ), - }, - ), + auxiliary_data: None, }, ], ) @@ -250,18 +217,7 @@ Ok( code_offset: 2, }, ), - auxiliary_data: V1( - TransactionAuxiliaryDataV1 { - detail_error_message: Some( - VMErrorDetail { - status_code: MISSING_DATA, - message: Some( - "Failed to move resource from f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1", - ), - }, - ), - }, - ), + auxiliary_data: None, }, ], ) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_bad_sig_function_dep.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_bad_sig_function_dep.exp index 9aa3663a3fdc9..989537f9dbb13 100644 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_bad_sig_function_dep.exp +++ b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_bad_sig_function_dep.exp @@ -18,19 +18,12 @@ Ok( gas_used: 3, status: Keep( MiscellaneousError( - None, - ), - ), - auxiliary_data: V1( - TransactionAuxiliaryDataV1 { - detail_error_message: Some( - VMErrorDetail { - status_code: TYPE_MISMATCH, - message: None, - }, + Some( + TYPE_MISMATCH, ), - }, + ), ), + auxiliary_data: None, }, ], ) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_code_unverifiable.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_code_unverifiable.exp index 0716e44bde3af..817ad9fc21919 100644 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_code_unverifiable.exp +++ b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_code_unverifiable.exp @@ -18,19 +18,12 @@ Ok( gas_used: 3, status: Keep( MiscellaneousError( - None, - ), - ), - auxiliary_data: V1( - TransactionAuxiliaryDataV1 { - detail_error_message: Some( - VMErrorDetail { - status_code: NEGATIVE_STACK_SIZE_WITHIN_BLOCK, - message: None, - }, + Some( + NEGATIVE_STACK_SIZE_WITHIN_BLOCK, ), - }, + ), ), + auxiliary_data: None, }, ], ) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_nested_type_argument_module_does_not_exist.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_nested_type_argument_module_does_not_exist.exp index c383918b5692e..d0bb49a891939 100644 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_nested_type_argument_module_does_not_exist.exp +++ b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_nested_type_argument_module_does_not_exist.exp @@ -18,19 +18,12 @@ Ok( gas_used: 3, status: Keep( MiscellaneousError( - None, - ), - ), - auxiliary_data: V1( - TransactionAuxiliaryDataV1 { - detail_error_message: Some( - VMErrorDetail { - status_code: LINKER_ERROR, - message: None, - }, + Some( + LINKER_ERROR, ), - }, + ), ), + auxiliary_data: None, }, ], ) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_non_existing_function_dep.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_non_existing_function_dep.exp index 69cc92770c691..4a5c55d23776c 100644 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_non_existing_function_dep.exp +++ b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_non_existing_function_dep.exp @@ -18,19 +18,12 @@ Ok( gas_used: 3, status: Keep( MiscellaneousError( - None, - ), - ), - auxiliary_data: V1( - TransactionAuxiliaryDataV1 { - detail_error_message: Some( - VMErrorDetail { - status_code: LOOKUP_FAILED, - message: None, - }, + Some( + LOOKUP_FAILED, ), - }, + ), ), + auxiliary_data: None, }, ], ) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_none_existing_module_dep.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_none_existing_module_dep.exp index c383918b5692e..d0bb49a891939 100644 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_none_existing_module_dep.exp +++ b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_none_existing_module_dep.exp @@ -18,19 +18,12 @@ Ok( gas_used: 3, status: Keep( MiscellaneousError( - None, - ), - ), - auxiliary_data: V1( - TransactionAuxiliaryDataV1 { - detail_error_message: Some( - VMErrorDetail { - status_code: LINKER_ERROR, - message: None, - }, + Some( + LINKER_ERROR, ), - }, + ), ), + auxiliary_data: None, }, ], ) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_type_argument_module_does_not_exist.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_type_argument_module_does_not_exist.exp index c383918b5692e..d0bb49a891939 100644 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_type_argument_module_does_not_exist.exp +++ b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_type_argument_module_does_not_exist.exp @@ -18,19 +18,12 @@ Ok( gas_used: 3, status: Keep( MiscellaneousError( - None, - ), - ), - auxiliary_data: V1( - TransactionAuxiliaryDataV1 { - detail_error_message: Some( - VMErrorDetail { - status_code: LINKER_ERROR, - message: None, - }, + Some( + LINKER_ERROR, ), - }, + ), ), + auxiliary_data: None, }, ], ) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_arbitrary_script_execution.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_arbitrary_script_execution.exp index 08b93c02d50db..f2512b3dbe34c 100644 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_arbitrary_script_execution.exp +++ b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_arbitrary_script_execution.exp @@ -18,19 +18,12 @@ Ok( gas_used: 3, status: Keep( MiscellaneousError( - None, - ), - ), - auxiliary_data: V1( - TransactionAuxiliaryDataV1 { - detail_error_message: Some( - VMErrorDetail { - status_code: CODE_DESERIALIZATION_ERROR, - message: None, - }, + Some( + CODE_DESERIALIZATION_ERROR, ), - }, + ), ), + auxiliary_data: None, }, ], ) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_script_dependency_fails_verification.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_script_dependency_fails_verification.exp index 9d508c1e4da5e..ff35250c565a1 100644 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_script_dependency_fails_verification.exp +++ b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_script_dependency_fails_verification.exp @@ -18,19 +18,12 @@ Ok( gas_used: 3, status: Keep( MiscellaneousError( - None, - ), - ), - auxiliary_data: V1( - TransactionAuxiliaryDataV1 { - detail_error_message: Some( - VMErrorDetail { - status_code: UNEXPECTED_VERIFIER_ERROR, - message: None, - }, + Some( + UNEXPECTED_VERIFIER_ERROR, ), - }, + ), ), + auxiliary_data: None, }, ], ) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_script_transitive_dependency_fails_verification.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_script_transitive_dependency_fails_verification.exp index 9d508c1e4da5e..ff35250c565a1 100644 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_script_transitive_dependency_fails_verification.exp +++ b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_script_transitive_dependency_fails_verification.exp @@ -18,19 +18,12 @@ Ok( gas_used: 3, status: Keep( MiscellaneousError( - None, - ), - ), - auxiliary_data: V1( - TransactionAuxiliaryDataV1 { - detail_error_message: Some( - VMErrorDetail { - status_code: UNEXPECTED_VERIFIER_ERROR, - message: None, - }, + Some( + UNEXPECTED_VERIFIER_ERROR, ), - }, + ), ), + auxiliary_data: None, }, ], ) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_type_tag_dependency_fails_verification.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_type_tag_dependency_fails_verification.exp index 9d508c1e4da5e..ff35250c565a1 100644 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_type_tag_dependency_fails_verification.exp +++ b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_type_tag_dependency_fails_verification.exp @@ -18,19 +18,12 @@ Ok( gas_used: 3, status: Keep( MiscellaneousError( - None, - ), - ), - auxiliary_data: V1( - TransactionAuxiliaryDataV1 { - detail_error_message: Some( - VMErrorDetail { - status_code: UNEXPECTED_VERIFIER_ERROR, - message: None, - }, + Some( + UNEXPECTED_VERIFIER_ERROR, ), - }, + ), ), + auxiliary_data: None, }, ], ) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_type_tag_transitive_dependency_fails_verification.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_type_tag_transitive_dependency_fails_verification.exp index 9d508c1e4da5e..ff35250c565a1 100644 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_type_tag_transitive_dependency_fails_verification.exp +++ b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_type_tag_transitive_dependency_fails_verification.exp @@ -18,19 +18,12 @@ Ok( gas_used: 3, status: Keep( MiscellaneousError( - None, - ), - ), - auxiliary_data: V1( - TransactionAuxiliaryDataV1 { - detail_error_message: Some( - VMErrorDetail { - status_code: UNEXPECTED_VERIFIER_ERROR, - message: None, - }, + Some( + UNEXPECTED_VERIFIER_ERROR, ), - }, + ), ), + auxiliary_data: None, }, ], ) diff --git a/aptos-move/e2e-tests/src/executor.rs b/aptos-move/e2e-tests/src/executor.rs index c510477791f99..2d3b78221b400 100644 --- a/aptos-move/e2e-tests/src/executor.rs +++ b/aptos-move/e2e-tests/src/executor.rs @@ -805,11 +805,9 @@ impl FakeExecutor { let mut outputs = self .execute_block(txn_block) .expect("The VM should not fail to startup"); - let mut txn_output = outputs + outputs .pop() - .expect("A block with one transaction should have one output"); - txn_output.fill_error_status(); - txn_output + .expect("A block with one transaction should have one output") } pub fn execute_transaction_with_gas_profiler( diff --git a/execution/executor-benchmark/src/lib.rs b/execution/executor-benchmark/src/lib.rs index 88a2267acb89a..649281b784ab7 100644 --- a/execution/executor-benchmark/src/lib.rs +++ b/execution/executor-benchmark/src/lib.rs @@ -44,7 +44,7 @@ use aptos_transaction_generator_lib::{ create_txn_generator_creator, AlwaysApproveRootAccountHandle, TransactionGeneratorCreator, TransactionType::{self, CoinTransfer}, }; -use aptos_types::on_chain_config::{FeatureFlag, Features}; +use aptos_types::on_chain_config::Features; use aptos_vm::{aptos_vm::AptosVMBlockExecutor, VMBlockExecutor}; use db_reliable_submitter::DbReliableTransactionSubmitter; use metrics::TIMER; @@ -59,9 +59,7 @@ use std::{ use tokio::runtime::Runtime; pub fn default_benchmark_features() -> Features { - let mut init_features = Features::default(); - init_features.disable(FeatureFlag::REMOVE_DETAILED_ERROR_FROM_HASH); - init_features + Features::default() } pub fn init_db(config: &NodeConfig) -> DbReaderWriter { diff --git a/execution/executor-benchmark/src/native/native_vm.rs b/execution/executor-benchmark/src/native/native_vm.rs index 0621aebfc8648..39679672be476 100644 --- a/execution/executor-benchmark/src/native/native_vm.rs +++ b/execution/executor-benchmark/src/native/native_vm.rs @@ -41,7 +41,7 @@ use aptos_types::{ state_store::{state_key::StateKey, state_value::StateValueMetadata, StateView}, transaction::{ signature_verified_transaction::SignatureVerifiedTransaction, BlockOutput, Transaction, - TransactionAuxiliaryData, TransactionOutput, TransactionStatus, WriteSetPayload, + TransactionOutput, TransactionStatus, WriteSetPayload, }, write_set::WriteOp, AptosCoinType, @@ -162,7 +162,6 @@ impl ExecutorTask for NativeVMExecutorTask { ModuleWriteSet::empty(), FeeStatement::new(gas_units, gas_units, 0, 0, 0), TransactionStatus::Keep(aptos_types::transaction::ExecutionStatus::Success), - TransactionAuxiliaryData::default(), ))), Err(_) => ExecutionStatus::SpeculativeExecutionAbortError("something".to_string()), } diff --git a/types/src/on_chain_config/aptos_features.rs b/types/src/on_chain_config/aptos_features.rs index 4b4faa2f2dd6e..70bc4f18aa546 100644 --- a/types/src/on_chain_config/aptos_features.rs +++ b/types/src/on_chain_config/aptos_features.rs @@ -64,7 +64,7 @@ pub enum FeatureFlag { _DEPRECATED_RECONFIGURE_WITH_DKG = 45, KEYLESS_ACCOUNTS = 46, KEYLESS_BUT_ZKLESS_ACCOUNTS = 47, - REMOVE_DETAILED_ERROR_FROM_HASH = 48, + _DEPRECATED_REMOVE_DETAILED_ERROR_FROM_HASH = 48, // This feature is not used JWK_CONSENSUS = 49, CONCURRENT_FUNGIBLE_ASSETS = 50, REFUNDABLE_BYTES = 51, @@ -306,10 +306,6 @@ impl Features { self.is_enabled(FeatureFlag::FEDERATED_KEYLESS) } - pub fn is_remove_detailed_error_from_hash_enabled(&self) -> bool { - self.is_enabled(FeatureFlag::REMOVE_DETAILED_ERROR_FROM_HASH) - } - pub fn is_refundable_bytes_enabled(&self) -> bool { self.is_enabled(FeatureFlag::REFUNDABLE_BYTES) } diff --git a/types/src/proptest_types.rs b/types/src/proptest_types.rs index 8c3c0180ff718..7de8ebf1b4e10 100644 --- a/types/src/proptest_types.rs +++ b/types/src/proptest_types.rs @@ -497,8 +497,7 @@ impl TransactionPayload { prop_compose! { fn arb_transaction_status()(vm_status in any::()) -> TransactionStatus { - let (txn_status, _) = TransactionStatus::from_vm_status(vm_status, true); - txn_status + TransactionStatus::from_vm_status(vm_status, true) } } diff --git a/types/src/transaction/mod.rs b/types/src/transaction/mod.rs index dabdae0acba76..138dd8e81496c 100644 --- a/types/src/transaction/mod.rs +++ b/types/src/transaction/mod.rs @@ -962,14 +962,10 @@ impl TransactionStatus { } } - pub fn from_vm_status( - vm_status: VMStatus, - charge_invariant_violation: bool, - ) -> (Self, TransactionAuxiliaryData) { + pub fn from_vm_status(vm_status: VMStatus, charge_invariant_violation: bool) -> Self { let status_code = vm_status.status_code(); - let txn_aux = TransactionAuxiliaryData::from_vm_status(&vm_status); // TODO: keep_or_discard logic should be deprecated from Move repo and refactored into here. - let status = match vm_status.keep_or_discard() { + match vm_status.keep_or_discard() { Ok(recorded) => match recorded { // TODO(bowu):status code should be removed from transaction status KeptVMStatus::MiscellaneousError => { @@ -986,8 +982,7 @@ impl TransactionStatus { TransactionStatus::Discard(code) } }, - }; - (status, txn_aux) + } } pub fn from_executed_vm_status(vm_status: VMStatus) -> Self { @@ -1234,17 +1229,6 @@ impl TransactionOutput { (write_set, events, gas_used, status, auxiliary_data) } - // This function is supposed to be called in various tests only - pub fn fill_error_status(&mut self) { - if let TransactionStatus::Keep(ExecutionStatus::MiscellaneousError(None)) = self.status { - if let Some(detail) = self.auxiliary_data.get_detail_error_message() { - self.status = TransactionStatus::Keep(ExecutionStatus::MiscellaneousError(Some( - detail.status_code(), - ))); - } - } - } - pub fn ensure_match_transaction_info( &self, version: Version, From 994f3614ad5f9d9205514c9967a6bc5f7153f0bc Mon Sep 17 00:00:00 2001 From: rtso <8248583+rtso@users.noreply.github.com> Date: Wed, 27 Nov 2024 14:07:51 -0800 Subject: [PATCH 07/78] add scripted fa txn --- .../152449628_coin_info_write.json | 551 ++++++++++++++++++ .../fa_mint_transfer_burn.json | 283 +++++++++ .../simple_user_script3.json | 36 +- .../simple_user_script4.json | 36 +- .../imported_transactions.yaml | 1 + .../move_fixtures/fa_mint_transfer_burn.yaml | 5 + .../fa_mint_transfer_burn/Move.toml | 9 + .../fa_mint_transfer_burn/script.mv | Bin 0 -> 941 bytes .../fa_mint_transfer_burn/sources/main.move | 41 ++ 9 files changed, 926 insertions(+), 36 deletions(-) create mode 100644 ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/imported_mainnet_txns/152449628_coin_info_write.json create mode 100644 ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/fa_mint_transfer_burn.json create mode 100644 ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/fa_mint_transfer_burn.yaml create mode 100644 ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/fa_mint_transfer_burn/Move.toml create mode 100644 ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/fa_mint_transfer_burn/script.mv create mode 100644 ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/fa_mint_transfer_burn/sources/main.move diff --git a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/imported_mainnet_txns/152449628_coin_info_write.json b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/imported_mainnet_txns/152449628_coin_info_write.json new file mode 100644 index 0000000000000..6e681e8f55c72 --- /dev/null +++ b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/imported_mainnet_txns/152449628_coin_info_write.json @@ -0,0 +1,551 @@ +{ + "timestamp": { + "seconds": "1685750281", + "nanos": 40129000 + }, + "version": "152449628", + "info": { + "hash": "5vZ6mSZktJDtWeDAWCGoZoIffRztchTspT5dDz4t2yg=", + "stateChangeHash": "pFLEB6pffI8KHGEoDIJbJ/zw+cV1CIdQYDx5RJDnSsI=", + "eventRootHash": "tXhsCadpsgxtZN7OYpD1CYD5t81s87Fgwt+EbxgsnKk=", + "gasUsed": "559", + "success": true, + "vmStatus": "Executed successfully", + "accumulatorRootHash": "PTMjl6V9E79HMPRrDQjESAZ6XYZP+wpV/GTJ46CwYaE=", + "changes": [ + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af", + "stateKeyHash": "ddY/tO9PuZZxascgn2c/So1feSm42hRQk0z5qsv0018=", + "type": { + "address": "0x1", + "module": "coin", + "name": "CoinInfo", + "genericTypeParams": [ + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af", + "module": "stable_pool", + "name": "StablePoolToken", + "genericTypeParams": [ + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa", + "module": "asset", + "name": "USDC" + } + }, + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa", + "module": "asset", + "name": "USDT" + } + }, + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af", + "module": "base_pool", + "name": "Null" + } + }, + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af", + "module": "base_pool", + "name": "Null" + } + } + ] + } + } + ] + }, + "typeStr": "0x1::coin::CoinInfo<0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af::stable_pool::StablePoolToken<0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa::asset::USDC, 0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa::asset::USDT, 0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af::base_pool::Null, 0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af::base_pool::Null>>", + "data": "{\"decimals\":8,\"name\":\"SP:USDC-USDT\",\"supply\":{\"vec\":[{\"aggregator\":{\"vec\":[]},\"integer\":{\"vec\":[{\"limit\":\"340282366920938463463374607431768211455\",\"value\":\"10467737019262\"}]}}]},\"symbol\":\"THALA-LP\"}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af", + "stateKeyHash": "4k17R8DuXaI2QEJ0kRE03l4H5wZsm5pxTHsCu+s3LXk=", + "type": { + "address": "0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af", + "module": "stable_pool", + "name": "StablePool", + "genericTypeParams": [ + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa", + "module": "asset", + "name": "USDC" + } + }, + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa", + "module": "asset", + "name": "USDT" + } + }, + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af", + "module": "base_pool", + "name": "Null" + } + }, + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af", + "module": "base_pool", + "name": "Null" + } + } + ] + }, + "typeStr": "0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af::stable_pool::StablePool<0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa::asset::USDC, 0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa::asset::USDT, 0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af::base_pool::Null, 0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af::base_pool::Null>", + "data": "{\"amp_factor\":\"1000\",\"asset_0\":{\"value\":\"172862440249\"},\"asset_1\":{\"value\":\"457965334481\"},\"asset_2\":{\"value\":\"0\"},\"asset_3\":{\"value\":\"0\"},\"events\":{\"add_liquidity_events\":{\"counter\":\"1633\",\"guid\":{\"id\":{\"addr\":\"0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af\",\"creation_num\":\"16\"}}},\"param_change_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af\",\"creation_num\":\"19\"}}},\"pool_creation_events\":{\"counter\":\"1\",\"guid\":{\"id\":{\"addr\":\"0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af\",\"creation_num\":\"15\"}}},\"remove_liquidity_events\":{\"counter\":\"258\",\"guid\":{\"id\":{\"addr\":\"0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af\",\"creation_num\":\"17\"}}},\"swap_events\":{\"counter\":\"11391\",\"guid\":{\"id\":{\"addr\":\"0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af\",\"creation_num\":\"18\"}}}},\"inverse_negated_swap_fee_ratio\":{\"v\":\"18465209284871323648\"},\"pool_token_burn_cap\":{\"dummy_field\":false},\"pool_token_mint_cap\":{\"dummy_field\":false},\"precision_multipliers\":[\"100\",\"100\"],\"reserved_lp_coin\":{\"value\":\"100\"},\"swap_fee_ratio\":{\"v\":\"18446744073709551\"}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x4dbd8a5dc97d06d51130c3b0ed70e852ab3d733b265da7bf67edab9eaf1dfcd3", + "stateKeyHash": "UhAjCh7ajbbm40YB3uCc6qzATHNYIb3tpLUYsZeKilk=", + "type": { + "address": "0x1", + "module": "coin", + "name": "CoinStore", + "genericTypeParams": [ + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "aptos_coin", + "name": "AptosCoin" + } + } + ] + }, + "typeStr": "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>", + "data": "{\"coin\":{\"value\":\"299662084\"},\"deposit_events\":{\"counter\":\"4\",\"guid\":{\"id\":{\"addr\":\"0x4dbd8a5dc97d06d51130c3b0ed70e852ab3d733b265da7bf67edab9eaf1dfcd3\",\"creation_num\":\"2\"}}},\"frozen\":false,\"withdraw_events\":{\"counter\":\"2\",\"guid\":{\"id\":{\"addr\":\"0x4dbd8a5dc97d06d51130c3b0ed70e852ab3d733b265da7bf67edab9eaf1dfcd3\",\"creation_num\":\"3\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x4dbd8a5dc97d06d51130c3b0ed70e852ab3d733b265da7bf67edab9eaf1dfcd3", + "stateKeyHash": "MQVcCopNAX0NkLy1Igy9tX2aefXQ2T5tW1EPtk28RjM=", + "type": { + "address": "0x1", + "module": "coin", + "name": "CoinStore", + "genericTypeParams": [ + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af", + "module": "stable_pool", + "name": "StablePoolToken", + "genericTypeParams": [ + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa", + "module": "asset", + "name": "USDC" + } + }, + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa", + "module": "asset", + "name": "USDT" + } + }, + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af", + "module": "base_pool", + "name": "Null" + } + }, + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af", + "module": "base_pool", + "name": "Null" + } + } + ] + } + } + ] + }, + "typeStr": "0x1::coin::CoinStore<0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af::stable_pool::StablePoolToken<0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa::asset::USDC, 0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa::asset::USDT, 0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af::base_pool::Null, 0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af::base_pool::Null>>", + "data": "{\"coin\":{\"value\":\"33197993\"},\"deposit_events\":{\"counter\":\"1\",\"guid\":{\"id\":{\"addr\":\"0x4dbd8a5dc97d06d51130c3b0ed70e852ab3d733b265da7bf67edab9eaf1dfcd3\",\"creation_num\":\"8\"}}},\"frozen\":false,\"withdraw_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x4dbd8a5dc97d06d51130c3b0ed70e852ab3d733b265da7bf67edab9eaf1dfcd3\",\"creation_num\":\"9\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x4dbd8a5dc97d06d51130c3b0ed70e852ab3d733b265da7bf67edab9eaf1dfcd3", + "stateKeyHash": "hoBwnGYwq4RD099OT7+UOEBMB2ft+PdMTwKZoHNzTkI=", + "type": { + "address": "0x1", + "module": "coin", + "name": "CoinStore", + "genericTypeParams": [ + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa", + "module": "asset", + "name": "USDC" + } + } + ] + }, + "typeStr": "0x1::coin::CoinStore<0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa::asset::USDC>", + "data": "{\"coin\":{\"value\":\"0\"},\"deposit_events\":{\"counter\":\"1\",\"guid\":{\"id\":{\"addr\":\"0x4dbd8a5dc97d06d51130c3b0ed70e852ab3d733b265da7bf67edab9eaf1dfcd3\",\"creation_num\":\"6\"}}},\"frozen\":false,\"withdraw_events\":{\"counter\":\"1\",\"guid\":{\"id\":{\"addr\":\"0x4dbd8a5dc97d06d51130c3b0ed70e852ab3d733b265da7bf67edab9eaf1dfcd3\",\"creation_num\":\"7\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x4dbd8a5dc97d06d51130c3b0ed70e852ab3d733b265da7bf67edab9eaf1dfcd3", + "stateKeyHash": "aD7wBHVt37bqIs5o34rae2FCKxs1N2TsSab2Saws5Z4=", + "type": { + "address": "0x1", + "module": "coin", + "name": "CoinStore", + "genericTypeParams": [ + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa", + "module": "asset", + "name": "USDT" + } + } + ] + }, + "typeStr": "0x1::coin::CoinStore<0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa::asset::USDT>", + "data": "{\"coin\":{\"value\":\"0\"},\"deposit_events\":{\"counter\":\"2\",\"guid\":{\"id\":{\"addr\":\"0x4dbd8a5dc97d06d51130c3b0ed70e852ab3d733b265da7bf67edab9eaf1dfcd3\",\"creation_num\":\"4\"}}},\"frozen\":false,\"withdraw_events\":{\"counter\":\"2\",\"guid\":{\"id\":{\"addr\":\"0x4dbd8a5dc97d06d51130c3b0ed70e852ab3d733b265da7bf67edab9eaf1dfcd3\",\"creation_num\":\"5\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x4dbd8a5dc97d06d51130c3b0ed70e852ab3d733b265da7bf67edab9eaf1dfcd3", + "stateKeyHash": "21tKvZ52BVjlOjGLUys3k33v8AuSWeawHiZond7vUjE=", + "type": { + "address": "0x1", + "module": "account", + "name": "Account" + }, + "typeStr": "0x1::account::Account", + "data": "{\"authentication_key\":\"0x4dbd8a5dc97d06d51130c3b0ed70e852ab3d733b265da7bf67edab9eaf1dfcd3\",\"coin_register_events\":{\"counter\":\"4\",\"guid\":{\"id\":{\"addr\":\"0x4dbd8a5dc97d06d51130c3b0ed70e852ab3d733b265da7bf67edab9eaf1dfcd3\",\"creation_num\":\"0\"}}},\"guid_creation_num\":\"10\",\"key_rotation_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x4dbd8a5dc97d06d51130c3b0ed70e852ab3d733b265da7bf67edab9eaf1dfcd3\",\"creation_num\":\"1\"}}},\"rotation_capability_offer\":{\"for\":{\"vec\":[]}},\"sequence_number\":\"5\",\"signer_capability_offer\":{\"for\":{\"vec\":[]}}}" + } + }, + { + "type": "TYPE_WRITE_TABLE_ITEM", + "writeTableItem": { + "stateKeyHash": "bkso1A+YoQamUWNTCSTA3LQME0nTqpFdEItNbPwd2xk=", + "handle": "0x1b854694ae746cdbd8d44186ca4929b2b337df21d1c74633be19b2710552fdca", + "key": "0x0619dc29a0aac8fa146714058e8dd6d2d0f3bdf5f6331907bf91f3acd81e6935", + "data": { + "key": "\"0x619dc29a0aac8fa146714058e8dd6d2d0f3bdf5f6331907bf91f3acd81e6935\"", + "keyType": "address", + "value": "\"103759594674841609\"", + "valueType": "u128" + } + } + }, + { + "type": "TYPE_WRITE_TABLE_ITEM", + "writeTableItem": { + "stateKeyHash": "RN+OWuvdEuvxVKlBKmOChPniTg6H2VF5R6QoBckin3o=", + "handle": "0xd14a1c73455ce42de7350bc9d4f8d777035dad26f18b848465c873b5d60f6623", + "key": "0xac033078343832373164333964306230356264366566636132323738663232323737643666636333373535303466393833396664373366373461636532343038363161663a3a737461626c655f706f6f6c3a3a537461626c65506f6f6c546f6b656e3c3078663232626564653233376130376531323162353664393161343931656237626364666431663539303739323661396535383333386639363461303162313766613a3a61737365743a3a555344432c203078663232626564653233376130376531323162353664393161343931656237626364666431663539303739323661396535383333386639363461303162313766613a3a61737365743a3a555344542c203078343832373164333964306230356264366566636132323738663232323737643666636333373535303466393833396664373366373461636532343038363161663a3a626173655f706f6f6c3a3a4e756c6c2c203078343832373164333964306230356264366566636132323738663232323737643666636333373535303466393833396664373366373461636532343038363161663a3a626173655f706f6f6c3a3a4e756c6c3e", + "data": { + "key": "\"0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af::stable_pool::StablePoolToken<0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa::asset::USDC, 0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa::asset::USDT, 0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af::base_pool::Null, 0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af::base_pool::Null>\"", + "keyType": "0x1::string::String", + "value": "{\"amp_factor\":\"1000\",\"balances\":[\"172862440249\",\"457965334481\"],\"lp_coin_supply\":\"10467737019262\",\"precision_multipliers\":[\"100\",\"100\"]}", + "valueType": "0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af::stable_pool::StablePoolInfo" + } + } + } + ] + }, + "epoch": "2803", + "blockHeight": "58980031", + "type": "TRANSACTION_TYPE_USER", + "sizeInfo": { + "transactionBytes": 458, + "eventSizeInfo": [ + { + "typeTagBytes": 53, + "totalBytes": 109 + }, + { + "typeTagBytes": 53, + "totalBytes": 109 + }, + { + "typeTagBytes": 252, + "totalBytes": 340 + }, + { + "typeTagBytes": 60, + "totalBytes": 501 + }, + { + "typeTagBytes": 52, + "totalBytes": 108 + } + ], + "writeOpSizeInfo": [ + { + "keyBytes": 333, + "valueBytes": 58 + }, + { + "keyBytes": 280, + "valueBytes": 339 + }, + { + "keyBytes": 138, + "valueBytes": 105 + }, + { + "keyBytes": 334, + "valueBytes": 105 + }, + { + "keyBytes": 128, + "valueBytes": 105 + }, + { + "keyBytes": 128, + "valueBytes": 105 + }, + { + "keyBytes": 84, + "valueBytes": 147 + }, + { + "keyBytes": 66, + "valueBytes": 16 + }, + { + "keyBytes": 465, + "valueBytes": 50 + } + ] + }, + "user": { + "request": { + "sender": "0x4dbd8a5dc97d06d51130c3b0ed70e852ab3d733b265da7bf67edab9eaf1dfcd3", + "sequenceNumber": "4", + "maxGasAmount": "1116", + "gasUnitPrice": "100", + "expirationTimestampSecs": { + "seconds": "1685750341" + }, + "payload": { + "type": "TYPE_ENTRY_FUNCTION_PAYLOAD", + "entryFunctionPayload": { + "function": { + "module": { + "address": "0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af", + "name": "stable_pool_scripts" + }, + "name": "add_liquidity" + }, + "typeArguments": [ + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa", + "module": "asset", + "name": "USDC" + } + }, + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa", + "module": "asset", + "name": "USDT" + } + }, + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af", + "module": "base_pool", + "name": "Null" + } + }, + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af", + "module": "base_pool", + "name": "Null" + } + } + ], + "arguments": [ + "\"1000000\"", + "\"1000000\"", + "\"0\"", + "\"0\"" + ], + "entryFunctionIdStr": "0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af::stable_pool_scripts::add_liquidity" + } + }, + "signature": { + "type": "TYPE_ED25519", + "ed25519": { + "publicKey": "6Zs/LmsjX+cz5B747y518ypl8SZ5ZglT1udz1XAC+ME=", + "signature": "OaJ/9Rp9jcv24o1p5ZsAAv1zjOGQYNJHFsCO2TNuRozHlwwiAkA1fzqQlmCCR2aKb2axu7zBac5iAPabwiBfDg==" + } + } + }, + "events": [ + { + "key": { + "creationNumber": "7", + "accountAddress": "0x4dbd8a5dc97d06d51130c3b0ed70e852ab3d733b265da7bf67edab9eaf1dfcd3" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "coin", + "name": "WithdrawEvent" + } + }, + "typeStr": "0x1::coin::WithdrawEvent", + "data": "{\"amount\":\"1000000\"}" + }, + { + "key": { + "creationNumber": "5", + "accountAddress": "0x4dbd8a5dc97d06d51130c3b0ed70e852ab3d733b265da7bf67edab9eaf1dfcd3" + }, + "sequenceNumber": "1", + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "coin", + "name": "WithdrawEvent" + } + }, + "typeStr": "0x1::coin::WithdrawEvent", + "data": "{\"amount\":\"1000000\"}" + }, + { + "key": { + "creationNumber": "16", + "accountAddress": "0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af" + }, + "sequenceNumber": "1632", + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af", + "module": "stable_pool", + "name": "AddLiquidityEvent", + "genericTypeParams": [ + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa", + "module": "asset", + "name": "USDC" + } + }, + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa", + "module": "asset", + "name": "USDT" + } + }, + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af", + "module": "base_pool", + "name": "Null" + } + }, + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af", + "module": "base_pool", + "name": "Null" + } + } + ] + } + }, + "typeStr": "0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af::stable_pool::AddLiquidityEvent<0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa::asset::USDC, 0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa::asset::USDT, 0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af::base_pool::Null, 0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af::base_pool::Null>", + "data": "{\"amount_0\":\"1000000\",\"amount_1\":\"1000000\",\"amount_2\":\"0\",\"amount_3\":\"0\",\"minted_lp_coin_amount\":\"33197993\"}" + }, + { + "key": { + "accountAddress": "0x4dbd8a5dc97d06d51130c3b0ed70e852ab3d733b265da7bf67edab9eaf1dfcd3" + }, + "sequenceNumber": "3", + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "account", + "name": "CoinRegisterEvent" + } + }, + "typeStr": "0x1::account::CoinRegisterEvent", + "data": "{\"type_info\":{\"account_address\":\"0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af\",\"module_name\":\"0x737461626c655f706f6f6c\",\"struct_name\":\"0x537461626c65506f6f6c546f6b656e3c3078663232626564653233376130376531323162353664393161343931656237626364666431663539303739323661396535383333386639363461303162313766613a3a61737365743a3a555344432c203078663232626564653233376130376531323162353664393161343931656237626364666431663539303739323661396535383333386639363461303162313766613a3a61737365743a3a555344542c203078343832373164333964306230356264366566636132323738663232323737643666636333373535303466393833396664373366373461636532343038363161663a3a626173655f706f6f6c3a3a4e756c6c2c203078343832373164333964306230356264366566636132323738663232323737643666636333373535303466393833396664373366373461636532343038363161663a3a626173655f706f6f6c3a3a4e756c6c3e\"}}" + }, + { + "key": { + "creationNumber": "8", + "accountAddress": "0x4dbd8a5dc97d06d51130c3b0ed70e852ab3d733b265da7bf67edab9eaf1dfcd3" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "coin", + "name": "DepositEvent" + } + }, + "typeStr": "0x1::coin::DepositEvent", + "data": "{\"amount\":\"33197993\"}" + } + ] + } +} \ No newline at end of file diff --git a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/fa_mint_transfer_burn.json b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/fa_mint_transfer_burn.json new file mode 100644 index 0000000000000..2206cf631a561 --- /dev/null +++ b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/fa_mint_transfer_burn.json @@ -0,0 +1,283 @@ +{ + "timestamp": { + "seconds": "1732672967", + "nanos": 932459000 + }, + "version": "35", + "info": { + "hash": "DGiU+N/60a/a6uuy94V86I9qRmNIKIu+FVVdY6FUS9A=", + "stateChangeHash": "OSOA2nyyEJm1CbchaFh1jqXk2U4gBc+op44dk59bFb4=", + "eventRootHash": "vDzA4XF4bCCJwq8bN/jYVp8Yinxa+CoaxRg8KoArN2Q=", + "gasUsed": "1161", + "success": true, + "vmStatus": "Executed successfully", + "accumulatorRootHash": "ybrUtD0TqXY/+Bhh1p+69NpelbNnUpnpgeLLyQFxWIA=", + "changes": [ + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x313228f6c338fcca1b431fc6453c7288e5463b192a1b7b12914173aca3c337b7", + "stateKeyHash": "Y8Y0AitszA5qhqXL5YDf9E4PgIPbLctf+kdkZnucMyM=", + "type": { + "address": "0x1", + "module": "fungible_asset", + "name": "ConcurrentSupply" + }, + "typeStr": "0x1::fungible_asset::ConcurrentSupply", + "data": "{\"current\":{\"max_value\":\"340282366920938463463374607431768211455\",\"value\":\"0\"}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x313228f6c338fcca1b431fc6453c7288e5463b192a1b7b12914173aca3c337b7", + "stateKeyHash": "Y8Y0AitszA5qhqXL5YDf9E4PgIPbLctf+kdkZnucMyM=", + "type": { + "address": "0x1", + "module": "fungible_asset", + "name": "Metadata" + }, + "typeStr": "0x1::fungible_asset::Metadata", + "data": "{\"decimals\":8,\"icon_uri\":\"https://example.com/favicon.ico\",\"name\":\"FA Coin\",\"project_uri\":\"https://example.com\",\"symbol\":\"FA\"}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x313228f6c338fcca1b431fc6453c7288e5463b192a1b7b12914173aca3c337b7", + "stateKeyHash": "Y8Y0AitszA5qhqXL5YDf9E4PgIPbLctf+kdkZnucMyM=", + "type": { + "address": "0x1", + "module": "object", + "name": "ObjectCore" + }, + "typeStr": "0x1::object::ObjectCore", + "data": "{\"allow_ungated_transfer\":true,\"guid_creation_num\":\"1125899906842625\",\"owner\":\"0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff\",\"transfer_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x313228f6c338fcca1b431fc6453c7288e5463b192a1b7b12914173aca3c337b7\",\"creation_num\":\"1125899906842624\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x313228f6c338fcca1b431fc6453c7288e5463b192a1b7b12914173aca3c337b7", + "stateKeyHash": "Y8Y0AitszA5qhqXL5YDf9E4PgIPbLctf+kdkZnucMyM=", + "type": { + "address": "0x1", + "module": "primary_fungible_store", + "name": "DeriveRefPod" + }, + "typeStr": "0x1::primary_fungible_store::DeriveRefPod", + "data": "{\"metadata_derive_ref\":{\"self\":\"0x313228f6c338fcca1b431fc6453c7288e5463b192a1b7b12914173aca3c337b7\"}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff", + "stateKeyHash": "ceneJQEOEzV92WirHTGbXnLP+TvF5K6btYiyF5HdKKg=", + "type": { + "address": "0x1", + "module": "coin", + "name": "CoinStore", + "genericTypeParams": [ + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "aptos_coin", + "name": "AptosCoin" + } + } + ] + }, + "typeStr": "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>", + "data": "{\"coin\":{\"value\":\"99883900\"},\"deposit_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff\",\"creation_num\":\"2\"}}},\"frozen\":false,\"withdraw_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff\",\"creation_num\":\"3\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff", + "stateKeyHash": "fosKvq2RB9fkmTNvrdzHt/qGGmluI1R/CwhAP58GB3o=", + "type": { + "address": "0x1", + "module": "account", + "name": "Account" + }, + "typeStr": "0x1::account::Account", + "data": "{\"authentication_key\":\"0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff\",\"coin_register_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff\",\"creation_num\":\"0\"}}},\"guid_creation_num\":\"4\",\"key_rotation_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff\",\"creation_num\":\"1\"}}},\"rotation_capability_offer\":{\"for\":{\"vec\":[]}},\"sequence_number\":\"1\",\"signer_capability_offer\":{\"for\":{\"vec\":[]}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0xfb24be743a80eebd426967035c9023ea7e83edce89f4d7085d6d43e0c95c2f0b", + "stateKeyHash": "bntLw5n1ZIlpJmPzcUUvYBrYwMDYMchcbzDA+dlDt3s=", + "type": { + "address": "0x1", + "module": "fungible_asset", + "name": "FungibleStore" + }, + "typeStr": "0x1::fungible_asset::FungibleStore", + "data": "{\"balance\":\"0\",\"frozen\":false,\"metadata\":{\"inner\":\"0x313228f6c338fcca1b431fc6453c7288e5463b192a1b7b12914173aca3c337b7\"}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0xfb24be743a80eebd426967035c9023ea7e83edce89f4d7085d6d43e0c95c2f0b", + "stateKeyHash": "bntLw5n1ZIlpJmPzcUUvYBrYwMDYMchcbzDA+dlDt3s=", + "type": { + "address": "0x1", + "module": "object", + "name": "ObjectCore" + }, + "typeStr": "0x1::object::ObjectCore", + "data": "{\"allow_ungated_transfer\":false,\"guid_creation_num\":\"1125899906842625\",\"owner\":\"0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff\",\"transfer_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0xfb24be743a80eebd426967035c9023ea7e83edce89f4d7085d6d43e0c95c2f0b\",\"creation_num\":\"1125899906842624\"}}}}" + } + }, + { + "type": "TYPE_WRITE_TABLE_ITEM", + "writeTableItem": { + "stateKeyHash": "bkso1A+YoQamUWNTCSTA3LQME0nTqpFdEItNbPwd2xk=", + "handle": "0x1b854694ae746cdbd8d44186ca4929b2b337df21d1c74633be19b2710552fdca", + "key": "0x0619dc29a0aac8fa146714058e8dd6d2d0f3bdf5f6331907bf91f3acd81e6935", + "data": { + "key": "\"0x619dc29a0aac8fa146714058e8dd6d2d0f3bdf5f6331907bf91f3acd81e6935\"", + "keyType": "address", + "value": "\"18446744073709335625\"", + "valueType": "u128" + } + } + } + ] + }, + "epoch": "2", + "blockHeight": "17", + "type": "TRANSACTION_TYPE_USER", + "sizeInfo": { + "transactionBytes": 1111, + "eventSizeInfo": [ + { + "typeTagBytes": 57, + "totalBytes": 97 + }, + { + "typeTagBytes": 58, + "totalBytes": 98 + }, + { + "typeTagBytes": 63, + "totalBytes": 103 + } + ], + "writeOpSizeInfo": [ + { + "keyBytes": 87, + "valueBytes": 464 + }, + { + "keyBytes": 138, + "valueBytes": 105 + }, + { + "keyBytes": 84, + "valueBytes": 147 + }, + { + "keyBytes": 87, + "valueBytes": 246 + }, + { + "keyBytes": 66, + "valueBytes": 16 + } + ] + }, + "user": { + "request": { + "sender": "0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff", + "maxGasAmount": "1741", + "gasUnitPrice": "100", + "expirationTimestampSecs": { + "seconds": "1732672998" + }, + "payload": { + "type": "TYPE_SCRIPT_PAYLOAD", + "scriptPayload": { + "code": { + "bytecode": "oRzrCwcAAAoIAQAMAgwsAzhTBIsBCgWVAYkBB54CjgMIrAUgBswFSwAAAAEAAgADAAQABQEGAgAABwYAAAgAAAEJBwEAAQAKCAAACwsAAAwGAAANBgACDwcBAAAFEQcAAQ4DBAABAhACBgEAAQUSBwgAAQMTCQIAAQEUCwwBCAEAFQsNAAEAFgsOAAEAFwsPAAEAGBARAAEEGQASAAEDGhMUAQgBABsWAgEIAQAcFwIBCAEBBQQKCgoLFQwVAQYMCQgAAwgBBggACAILAwEIBAsDAQgFCAYIBwACBgwKAgEIAAEEAQsIAQkAAQoCAQgJBwYIAAsIAQQICQgJAggJCAkBCAUBBggAAQsDAQkAAQgGAQgBAQgHAgYIBgMBCAIBBQIFCwMBCQABCwMBCAQBCAQDBggHCwMBCQAIAgMGCAELAwEJAAMOZnVuZ2libGVfYXNzZXQGb2JqZWN0Bm9wdGlvbhZwcmltYXJ5X2Z1bmdpYmxlX3N0b3JlBnNpZ25lcgZzdHJpbmcOQ29uc3RydWN0b3JSZWYHQnVyblJlZg1GdW5naWJsZUFzc2V0Bk9iamVjdA1GdW5naWJsZVN0b3JlCE1ldGFkYXRhB01pbnRSZWYLVHJhbnNmZXJSZWYTY3JlYXRlX25hbWVkX29iamVjdAZPcHRpb24Ebm9uZQZTdHJpbmcEdXRmOCtjcmVhdGVfcHJpbWFyeV9zdG9yZV9lbmFibGVkX2Z1bmdpYmxlX2Fzc2V0G29iamVjdF9mcm9tX2NvbnN0cnVjdG9yX3JlZhFnZW5lcmF0ZV9taW50X3JlZhFnZW5lcmF0ZV9idXJuX3JlZhVnZW5lcmF0ZV90cmFuc2Zlcl9yZWYEbWludAphZGRyZXNzX29mG2Vuc3VyZV9wcmltYXJ5X3N0b3JlX2V4aXN0cxBkZXBvc2l0X3dpdGhfcmVmCWJ1cm5fZnJvbQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCgIDAkZBCgIIB0ZBIENvaW4KAiAfaHR0cHM6Ly9leGFtcGxlLmNvbS9mYXZpY29uLmljbwoCFBNodHRwczovL2V4YW1wbGUuY29tAAABMgoABwARAAwBDgEMBAoEOAAHARECBwARAjEIBwIRAgcDEQIRAwoEOAEMBwoEEQUMCAoEEQYMAwsEEQcMCQZAQg8AAAAAAAwCDggKAhEIDAULABEJCwc4AgwGDgkKBgsFOAMOAwsGCwI4BAI=", + "abi": { + "name": "main", + "visibility": "VISIBILITY_PUBLIC", + "isEntry": true, + "params": [ + { + "type": "MOVE_TYPES_REFERENCE", + "reference": { + "to": { + "type": "MOVE_TYPES_SIGNER" + } + } + } + ] + } + } + } + }, + "signature": { + "type": "TYPE_ED25519", + "ed25519": { + "publicKey": "spiXXSfb/zAg5e5/27rYqWnU8qLVKG4JfR25dg0E3TE=", + "signature": "neaivYBEoxiBZWvjKvdRg/oQgie7W0w3+FQO957zUxHUXtZkocABqzttJnV1kcoIwMUNAstLGdPSmyG+2nylBg==" + } + } + }, + "events": [ + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "fungible_asset", + "name": "Deposit" + } + }, + "typeStr": "0x1::fungible_asset::Deposit", + "data": "{\"amount\":\"1000000\",\"store\":\"0xfb24be743a80eebd426967035c9023ea7e83edce89f4d7085d6d43e0c95c2f0b\"}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "fungible_asset", + "name": "Withdraw" + } + }, + "typeStr": "0x1::fungible_asset::Withdraw", + "data": "{\"amount\":\"1000000\",\"store\":\"0xfb24be743a80eebd426967035c9023ea7e83edce89f4d7085d6d43e0c95c2f0b\"}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "transaction_fee", + "name": "FeeStatement" + } + }, + "typeStr": "0x1::transaction_fee::FeeStatement", + "data": "{\"execution_gas_units\":\"5\",\"io_gas_units\":\"5\",\"storage_fee_octas\":\"115200\",\"storage_fee_refund_octas\":\"0\",\"total_charge_gas_units\":\"1161\"}" + } + ] + } +} \ No newline at end of file diff --git a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script3.json b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script3.json index f68ff7ab8a46c..4aca3be5af462 100644 --- a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script3.json +++ b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script3.json @@ -1,23 +1,23 @@ { "timestamp": { - "seconds": "1731095937", - "nanos": 959635000 + "seconds": "1732672975", + "nanos": 261345000 }, - "version": "25", + "version": "57", "info": { - "hash": "mMo4Emu8DC2qussDz3u9tpPJIln6Jm6M9QjbL5N5pAw=", - "stateChangeHash": "8/OPX/UmPw1+A9AkHzAFGOJMuWJmZ+zI/5IJ11u3GCk=", + "hash": "1kLYjLwrzJF1XkkoSWG6m+EOvIkzkijdAmHc+frQImQ=", + "stateChangeHash": "h4Bop9rEeFcWLdIdxJr+aWdLDW2OJ/cqulIqA06dLDc=", "eventRootHash": "J/kCueHhHqJXi8MVudrh82sOQ/pqY9TJ9VjLOdgel6I=", "gasUsed": "3", "success": true, "vmStatus": "Executed successfully", - "accumulatorRootHash": "mQQ1fBJJ6MiDwJZM4xwl91A6F81Lzzj8GmkYb7N7Jn8=", + "accumulatorRootHash": "HusghxoSOCUrHGTtp4OaZ3qBwShyrk28S5ZBCe71fbI=", "changes": [ { "type": "TYPE_WRITE_RESOURCE", "writeResource": { - "address": "0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff", - "stateKeyHash": "ceneJQEOEzV92WirHTGbXnLP+TvF5K6btYiyF5HdKKg=", + "address": "0x8f0de18409d6fca18c72fac4062fc0f9baa6404296fed93a3ad0250fb671f8b3", + "stateKeyHash": "2Ne4/4Qg7OpxqV5LI4CB9VlZutr1u5HaXhbSTzYWYw8=", "type": { "address": "0x1", "module": "coin", @@ -34,21 +34,21 @@ ] }, "typeStr": "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>", - "data": "{\"coin\":{\"value\":\"99999700\"},\"deposit_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff\",\"creation_num\":\"2\"}}},\"frozen\":false,\"withdraw_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff\",\"creation_num\":\"3\"}}}}" + "data": "{\"coin\":{\"value\":\"99999700\"},\"deposit_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x8f0de18409d6fca18c72fac4062fc0f9baa6404296fed93a3ad0250fb671f8b3\",\"creation_num\":\"2\"}}},\"frozen\":false,\"withdraw_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x8f0de18409d6fca18c72fac4062fc0f9baa6404296fed93a3ad0250fb671f8b3\",\"creation_num\":\"3\"}}}}" } }, { "type": "TYPE_WRITE_RESOURCE", "writeResource": { - "address": "0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff", - "stateKeyHash": "fosKvq2RB9fkmTNvrdzHt/qGGmluI1R/CwhAP58GB3o=", + "address": "0x8f0de18409d6fca18c72fac4062fc0f9baa6404296fed93a3ad0250fb671f8b3", + "stateKeyHash": "CruPmGDHh8XlpNdvv1soHpZeHrF/hdy9+k4liPo15BE=", "type": { "address": "0x1", "module": "account", "name": "Account" }, "typeStr": "0x1::account::Account", - "data": "{\"authentication_key\":\"0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff\",\"coin_register_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff\",\"creation_num\":\"0\"}}},\"guid_creation_num\":\"4\",\"key_rotation_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff\",\"creation_num\":\"1\"}}},\"rotation_capability_offer\":{\"for\":{\"vec\":[]}},\"sequence_number\":\"1\",\"signer_capability_offer\":{\"for\":{\"vec\":[]}}}" + "data": "{\"authentication_key\":\"0x8f0de18409d6fca18c72fac4062fc0f9baa6404296fed93a3ad0250fb671f8b3\",\"coin_register_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x8f0de18409d6fca18c72fac4062fc0f9baa6404296fed93a3ad0250fb671f8b3\",\"creation_num\":\"0\"}}},\"guid_creation_num\":\"4\",\"key_rotation_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x8f0de18409d6fca18c72fac4062fc0f9baa6404296fed93a3ad0250fb671f8b3\",\"creation_num\":\"1\"}}},\"rotation_capability_offer\":{\"for\":{\"vec\":[]}},\"sequence_number\":\"1\",\"signer_capability_offer\":{\"for\":{\"vec\":[]}}}" } }, { @@ -60,7 +60,7 @@ "data": { "key": "\"0x619dc29a0aac8fa146714058e8dd6d2d0f3bdf5f6331907bf91f3acd81e6935\"", "keyType": "address", - "value": "\"18446744073709451425\"", + "value": "\"18446744073709235425\"", "valueType": "u128" } } @@ -68,7 +68,7 @@ ] }, "epoch": "2", - "blockHeight": "12", + "blockHeight": "27", "type": "TRANSACTION_TYPE_USER", "sizeInfo": { "transactionBytes": 190, @@ -95,11 +95,11 @@ }, "user": { "request": { - "sender": "0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff", + "sender": "0x8f0de18409d6fca18c72fac4062fc0f9baa6404296fed93a3ad0250fb671f8b3", "maxGasAmount": "4", "gasUnitPrice": "100", "expirationTimestampSecs": { - "seconds": "1731095967" + "seconds": "1732673005" }, "payload": { "type": "TYPE_SCRIPT_PAYLOAD", @@ -127,8 +127,8 @@ "signature": { "type": "TYPE_ED25519", "ed25519": { - "publicKey": "spiXXSfb/zAg5e5/27rYqWnU8qLVKG4JfR25dg0E3TE=", - "signature": "f+ItEGJ5gbupM+YmAqfiClBtzmlmyE2SVgEVJqJzKDZ4LJq+1TcQlUPgioSvnZUQb5D3SyMrR5ZOGyfTIpCcBw==" + "publicKey": "7wW+3hX0IuFsAALjzui01DQVGNmcRpU1KhhpsHeYZPs=", + "signature": "+me7d5O4YGWWVVHrr8ByGeWF83oZ/S6LCnlEIH4FnITO3eoDu1U4qQllX+hJURRn1R6rVjU8ZKaw9BRXGJvtBQ==" } } }, diff --git a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script4.json b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script4.json index bf0666bc715cd..2a28f57eea78f 100644 --- a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script4.json +++ b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script4.json @@ -1,23 +1,23 @@ { "timestamp": { - "seconds": "1731095943", - "nanos": 657108000 + "seconds": "1732672981", + "nanos": 856611000 }, - "version": "45", + "version": "77", "info": { - "hash": "44R9OxJz8dfPVpv04tgGDCt382CmB3jnJSWBZm+vouA=", - "stateChangeHash": "wynuFYaMRVir/7jo4xFcHm0aUsks0+6zUPTFuJXymoM=", + "hash": "kXQ14XDqfcKlqro7h6UnIYBU7ReXHC1f1dh4cqrA9Wc=", + "stateChangeHash": "Lcw2QcDIjyWNLv4WjU3hZRLkFqRYzhyRVs6flb5HF48=", "eventRootHash": "J/kCueHhHqJXi8MVudrh82sOQ/pqY9TJ9VjLOdgel6I=", "gasUsed": "3", "success": true, "vmStatus": "Executed successfully", - "accumulatorRootHash": "LdbHt5IAacqS6Vhkxq9a8aMxaItrAjUB3mpZHC9ZGo8=", + "accumulatorRootHash": "gnscCFfMFb90l70guVpWFI6dGl4pspC5ynpsbp2WBEw=", "changes": [ { "type": "TYPE_WRITE_RESOURCE", "writeResource": { - "address": "0x8f0de18409d6fca18c72fac4062fc0f9baa6404296fed93a3ad0250fb671f8b3", - "stateKeyHash": "2Ne4/4Qg7OpxqV5LI4CB9VlZutr1u5HaXhbSTzYWYw8=", + "address": "0x501b015c58f2a1a62a330a6da80dfee723f528f719d25a4232751986f9a9f43f", + "stateKeyHash": "mblV8kItKhzWpJyNZcf9X5l3EmRe3m4NrXTdtzITQ6k=", "type": { "address": "0x1", "module": "coin", @@ -34,21 +34,21 @@ ] }, "typeStr": "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>", - "data": "{\"coin\":{\"value\":\"99999700\"},\"deposit_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x8f0de18409d6fca18c72fac4062fc0f9baa6404296fed93a3ad0250fb671f8b3\",\"creation_num\":\"2\"}}},\"frozen\":false,\"withdraw_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x8f0de18409d6fca18c72fac4062fc0f9baa6404296fed93a3ad0250fb671f8b3\",\"creation_num\":\"3\"}}}}" + "data": "{\"coin\":{\"value\":\"99999700\"},\"deposit_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x501b015c58f2a1a62a330a6da80dfee723f528f719d25a4232751986f9a9f43f\",\"creation_num\":\"2\"}}},\"frozen\":false,\"withdraw_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x501b015c58f2a1a62a330a6da80dfee723f528f719d25a4232751986f9a9f43f\",\"creation_num\":\"3\"}}}}" } }, { "type": "TYPE_WRITE_RESOURCE", "writeResource": { - "address": "0x8f0de18409d6fca18c72fac4062fc0f9baa6404296fed93a3ad0250fb671f8b3", - "stateKeyHash": "CruPmGDHh8XlpNdvv1soHpZeHrF/hdy9+k4liPo15BE=", + "address": "0x501b015c58f2a1a62a330a6da80dfee723f528f719d25a4232751986f9a9f43f", + "stateKeyHash": "+VS7DLwWFCETA4QQAND9ZVqc3IugzikHe1YU0T9rVo0=", "type": { "address": "0x1", "module": "account", "name": "Account" }, "typeStr": "0x1::account::Account", - "data": "{\"authentication_key\":\"0x8f0de18409d6fca18c72fac4062fc0f9baa6404296fed93a3ad0250fb671f8b3\",\"coin_register_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x8f0de18409d6fca18c72fac4062fc0f9baa6404296fed93a3ad0250fb671f8b3\",\"creation_num\":\"0\"}}},\"guid_creation_num\":\"4\",\"key_rotation_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x8f0de18409d6fca18c72fac4062fc0f9baa6404296fed93a3ad0250fb671f8b3\",\"creation_num\":\"1\"}}},\"rotation_capability_offer\":{\"for\":{\"vec\":[]}},\"sequence_number\":\"1\",\"signer_capability_offer\":{\"for\":{\"vec\":[]}}}" + "data": "{\"authentication_key\":\"0x501b015c58f2a1a62a330a6da80dfee723f528f719d25a4232751986f9a9f43f\",\"coin_register_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x501b015c58f2a1a62a330a6da80dfee723f528f719d25a4232751986f9a9f43f\",\"creation_num\":\"0\"}}},\"guid_creation_num\":\"4\",\"key_rotation_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x501b015c58f2a1a62a330a6da80dfee723f528f719d25a4232751986f9a9f43f\",\"creation_num\":\"1\"}}},\"rotation_capability_offer\":{\"for\":{\"vec\":[]}},\"sequence_number\":\"1\",\"signer_capability_offer\":{\"for\":{\"vec\":[]}}}" } }, { @@ -60,7 +60,7 @@ "data": { "key": "\"0x619dc29a0aac8fa146714058e8dd6d2d0f3bdf5f6331907bf91f3acd81e6935\"", "keyType": "address", - "value": "\"18446744073709351225\"", + "value": "\"18446744073809235025\"", "valueType": "u128" } } @@ -68,7 +68,7 @@ ] }, "epoch": "2", - "blockHeight": "21", + "blockHeight": "36", "type": "TRANSACTION_TYPE_USER", "sizeInfo": { "transactionBytes": 190, @@ -95,11 +95,11 @@ }, "user": { "request": { - "sender": "0x8f0de18409d6fca18c72fac4062fc0f9baa6404296fed93a3ad0250fb671f8b3", + "sender": "0x501b015c58f2a1a62a330a6da80dfee723f528f719d25a4232751986f9a9f43f", "maxGasAmount": "4", "gasUnitPrice": "100", "expirationTimestampSecs": { - "seconds": "1731095974" + "seconds": "1732673012" }, "payload": { "type": "TYPE_SCRIPT_PAYLOAD", @@ -127,8 +127,8 @@ "signature": { "type": "TYPE_ED25519", "ed25519": { - "publicKey": "7wW+3hX0IuFsAALjzui01DQVGNmcRpU1KhhpsHeYZPs=", - "signature": "+c+T3mDD5L+FFVHEKmdYI2eUoLvnt2O8wvC7OpEXL93n+vxY/vmue6KFGrX0waCib8nugoQQkYpwxUvMU8W0Cw==" + "publicKey": "ySyOe0Rn5inKjNIBohVk3jnup8vkW1m/038QtW4Kcow=", + "signature": "CGV33Y0/bikBWNw3LC0+d831fiNYnZghAkXrqPoFNCH6SCUBAXYUywE4SkTRZa4hp3Da0GHymrCd32aLNdE7Cw==" } } }, diff --git a/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/imported_transactions.yaml b/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/imported_transactions.yaml index 17b28cf7b7301..65aae7f7a3819 100644 --- a/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/imported_transactions.yaml +++ b/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/imported_transactions.yaml @@ -22,6 +22,7 @@ mainnet: versions_to_import: # fungible asset processor 308783012: 308783012_fa_transfer + 152449628: 152449628_coin_info_write # token v2 processor 1058723093: 1058723093_token_v1_mint_withdraw_deposit_events diff --git a/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/fa_mint_transfer_burn.yaml b/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/fa_mint_transfer_burn.yaml new file mode 100644 index 0000000000000..dbb41021a2079 --- /dev/null +++ b/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/fa_mint_transfer_burn.yaml @@ -0,0 +1,5 @@ +transactions: + - output_name: fa_mint_transfer_burn + script_path: fa_mint_transfer_burn + sender_address: __ACCOUNT_A__ + \ No newline at end of file diff --git a/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/fa_mint_transfer_burn/Move.toml b/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/fa_mint_transfer_burn/Move.toml new file mode 100644 index 0000000000000..31b2db2585a77 --- /dev/null +++ b/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/fa_mint_transfer_burn/Move.toml @@ -0,0 +1,9 @@ +[package] +name = "fa_mint_transfer_burn" +version = "1.0.0" +authors = [] + +[addresses] + +[dependencies] +AptosFramework = { local = "../../../../../../aptos-move/framework/aptos-framework" } diff --git a/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/fa_mint_transfer_burn/script.mv b/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/fa_mint_transfer_burn/script.mv new file mode 100644 index 0000000000000000000000000000000000000000..41a18617673032b931fb6b55cd0cdce596dbb4e8 GIT binary patch literal 941 zcmaJ=O>fjN5FLNSc5F9oy4@CNC3*+7g42o`MZi+~l#MR=C!&)t1U?CCx_xk z@(KV5P+-6zA%X%(0iX~}CBYkwr7-{&(G3A~6H!QV2_$122;HIrY00)!K-eIqK*)}< z1g8$o2KMio4C9{J#Q0z<2f`o1Hc}rAb|Ptim&SCk7ZXXi*4hm1kO-S9V2TI@iW)`~ zk0DV)Nua`Nq@xruilji|DV0dYBUh*CyB~O>F$GkCK37_=37rpKpyo@^P+=X&lhEkr_K46b|)0V!gT+|s%T2}^F z_;T*1#md%2Z;SiJJ8{`h=gUxyo~*dP?e;DU=S$pcdT+kpaQ{xKsM=;;Ozy20t*i2x z!@c6vIU4#Cxx%#~GF)@Q%4|e=Y|!O&+PbbQnrh$qZrQrxFGsg^7rL#fTQprAiuZN6 zj?HPW9Sz}I{ojWVfzk1arb>=a4$qp}YkK(jI)p{{;`rFzmh;7pJDN1}VH+!#^ cW=hjs*~CDe8abj?WT_S=8L^BRVd#j{Ul^srKmY&$ literal 0 HcmV?d00001 diff --git a/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/fa_mint_transfer_burn/sources/main.move b/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/fa_mint_transfer_burn/sources/main.move new file mode 100644 index 0000000000000..68db695f78548 --- /dev/null +++ b/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/fa_mint_transfer_burn/sources/main.move @@ -0,0 +1,41 @@ +script { + use std::signer; + use std::string::{utf8}; + use std::option; + + use aptos_framework::object::{Self, object_from_constructor_ref}; + use aptos_framework::fungible_asset::{Self, Metadata}; + use aptos_framework::primary_fungible_store::{Self}; + + const ASSET_SYMBOL: vector = b"FA"; + + fun main(admin: &signer) { + let constructor_ref = &object::create_named_object(admin, ASSET_SYMBOL); + primary_fungible_store::create_primary_store_enabled_fungible_asset( + constructor_ref, + option::none(), + utf8(b"FA Coin"), /* name */ + utf8(ASSET_SYMBOL), /* symbol */ + 8, /* decimals */ + utf8(b"https://example.com/favicon.ico"), /* icon */ + utf8(b"https://example.com"), /* project */ + ); + let metadata = object_from_constructor_ref(constructor_ref); + + // Create mint/burn/transfer refs to allow creator to manage the fungible asset. + let mint_ref = fungible_asset::generate_mint_ref(constructor_ref); + let burn_ref = fungible_asset::generate_burn_ref(constructor_ref); + let transfer_ref = fungible_asset::generate_transfer_ref(constructor_ref); + + // Mint FA + let amount = 1000000; + let fa = fungible_asset::mint(&mint_ref, amount); + + // Transfer FA + let fa_store = primary_fungible_store::ensure_primary_store_exists(signer::address_of(admin), metadata); + fungible_asset::deposit_with_ref(&transfer_ref, fa_store, fa); + + // Burn FA + fungible_asset::burn_from(&burn_ref, fa_store, amount); + } +} From 4aeaab9bf1651ea9752a92b6efa880a4f96d2dcb Mon Sep 17 00:00:00 2001 From: rtso <8248583+rtso@users.noreply.github.com> Date: Wed, 27 Nov 2024 15:51:19 -0800 Subject: [PATCH 08/78] fa double transfer --- .../fa_double_transfer.json | 404 ++++++++++++++++++ .../fa_mint_transfer_burn.json | 128 +++--- .../simple_user_script1.json | 20 +- .../simple_user_script2.json | 20 +- .../simple_user_script3.json | 36 +- .../simple_user_script4.json | 36 +- .../indexer-transaction-generator/README.md | 5 + .../move_fixtures/fa_double_transfer.yaml | 5 + .../fa_double_transfer/Move.toml | 9 + .../fa_double_transfer/script.mv | Bin 0 -> 1029 bytes .../fa_double_transfer/sources/main.move | 45 ++ .../simple_user_script/sources/main.move | 2 +- .../simple_user_script2/sources/main.move | 2 +- .../testing_accounts.yaml | 6 + .../src/config.rs | 1 + 15 files changed, 597 insertions(+), 122 deletions(-) create mode 100644 ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/fa_double_transfer.json create mode 100644 ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/fa_double_transfer.yaml create mode 100644 ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/fa_double_transfer/Move.toml create mode 100644 ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/fa_double_transfer/script.mv create mode 100644 ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/fa_double_transfer/sources/main.move diff --git a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/fa_double_transfer.json b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/fa_double_transfer.json new file mode 100644 index 0000000000000..8327961029f55 --- /dev/null +++ b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/fa_double_transfer.json @@ -0,0 +1,404 @@ +{ + "timestamp": { + "seconds": "1732752407", + "nanos": 70774000 + }, + "version": "67", + "info": { + "hash": "WSRo7BjlDt3z165dsMFMrjSFDZHFvKsY1JXaayoSb/w=", + "stateChangeHash": "70YgHm7HUKw9br0pPszGsVlxucAlA3CWBmspWaBaVjc=", + "eventRootHash": "FmWvL7p7CNYdF2eb/mjbz8+qRiRO70XR0GQsuHS1nuk=", + "gasUsed": "2230", + "success": true, + "vmStatus": "Executed successfully", + "accumulatorRootHash": "s1cwGiYnKWCvxwQbF5XxBhw+7OT3ke/l+qo6wwTRXe0=", + "changes": [ + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x6653d0f1cd711df18dcaddeaa37e528fa7034e2f1b9ac3578cf4d0abaed12547", + "stateKeyHash": "Y+AkbTsqcSTQ2DpFI3/rV8VMAqYsnqQG5r1gT/Ms7Dg=", + "type": { + "address": "0x1", + "module": "fungible_asset", + "name": "FungibleStore" + }, + "typeStr": "0x1::fungible_asset::FungibleStore", + "data": "{\"balance\":\"0\",\"frozen\":false,\"metadata\":{\"inner\":\"0x77bc07c02b7c38abc5b9d7dbad97bd1e1ff4d4b24066c652d3884918f3e244a5\"}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x6653d0f1cd711df18dcaddeaa37e528fa7034e2f1b9ac3578cf4d0abaed12547", + "stateKeyHash": "Y+AkbTsqcSTQ2DpFI3/rV8VMAqYsnqQG5r1gT/Ms7Dg=", + "type": { + "address": "0x1", + "module": "object", + "name": "ObjectCore" + }, + "typeStr": "0x1::object::ObjectCore", + "data": "{\"allow_ungated_transfer\":false,\"guid_creation_num\":\"1125899906842625\",\"owner\":\"0xcafe\",\"transfer_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x6653d0f1cd711df18dcaddeaa37e528fa7034e2f1b9ac3578cf4d0abaed12547\",\"creation_num\":\"1125899906842624\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x77bc07c02b7c38abc5b9d7dbad97bd1e1ff4d4b24066c652d3884918f3e244a5", + "stateKeyHash": "8ggtTyLWUlffI0c+9PlrlRWEH+E0245paCpwpr95z58=", + "type": { + "address": "0x1", + "module": "fungible_asset", + "name": "ConcurrentSupply" + }, + "typeStr": "0x1::fungible_asset::ConcurrentSupply", + "data": "{\"current\":{\"max_value\":\"340282366920938463463374607431768211455\",\"value\":\"1000000\"}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x77bc07c02b7c38abc5b9d7dbad97bd1e1ff4d4b24066c652d3884918f3e244a5", + "stateKeyHash": "8ggtTyLWUlffI0c+9PlrlRWEH+E0245paCpwpr95z58=", + "type": { + "address": "0x1", + "module": "fungible_asset", + "name": "Metadata" + }, + "typeStr": "0x1::fungible_asset::Metadata", + "data": "{\"decimals\":8,\"icon_uri\":\"https://example.com/favicon.ico\",\"name\":\"FA Coin\",\"project_uri\":\"https://example.com\",\"symbol\":\"FA\"}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x77bc07c02b7c38abc5b9d7dbad97bd1e1ff4d4b24066c652d3884918f3e244a5", + "stateKeyHash": "8ggtTyLWUlffI0c+9PlrlRWEH+E0245paCpwpr95z58=", + "type": { + "address": "0x1", + "module": "object", + "name": "ObjectCore" + }, + "typeStr": "0x1::object::ObjectCore", + "data": "{\"allow_ungated_transfer\":true,\"guid_creation_num\":\"1125899906842625\",\"owner\":\"0x7a2e070df14c96d0808ffab6b735591221241c34f6c4b4a9fa34051f945b5197\",\"transfer_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x77bc07c02b7c38abc5b9d7dbad97bd1e1ff4d4b24066c652d3884918f3e244a5\",\"creation_num\":\"1125899906842624\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x77bc07c02b7c38abc5b9d7dbad97bd1e1ff4d4b24066c652d3884918f3e244a5", + "stateKeyHash": "8ggtTyLWUlffI0c+9PlrlRWEH+E0245paCpwpr95z58=", + "type": { + "address": "0x1", + "module": "primary_fungible_store", + "name": "DeriveRefPod" + }, + "typeStr": "0x1::primary_fungible_store::DeriveRefPod", + "data": "{\"metadata_derive_ref\":{\"self\":\"0x77bc07c02b7c38abc5b9d7dbad97bd1e1ff4d4b24066c652d3884918f3e244a5\"}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x7a2e070df14c96d0808ffab6b735591221241c34f6c4b4a9fa34051f945b5197", + "stateKeyHash": "u7kfWhwrD/Og9hIHs1cxQ/5xUBoY27xbrHZ0V3ow+7Y=", + "type": { + "address": "0x1", + "module": "coin", + "name": "CoinStore", + "genericTypeParams": [ + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "aptos_coin", + "name": "AptosCoin" + } + } + ] + }, + "typeStr": "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>", + "data": "{\"coin\":{\"value\":\"99777000\"},\"deposit_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x7a2e070df14c96d0808ffab6b735591221241c34f6c4b4a9fa34051f945b5197\",\"creation_num\":\"2\"}}},\"frozen\":false,\"withdraw_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x7a2e070df14c96d0808ffab6b735591221241c34f6c4b4a9fa34051f945b5197\",\"creation_num\":\"3\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x7a2e070df14c96d0808ffab6b735591221241c34f6c4b4a9fa34051f945b5197", + "stateKeyHash": "d++pe1OH6esn/cYIT8Mhu7RfnAhWrznIkZCISHuCJGM=", + "type": { + "address": "0x1", + "module": "account", + "name": "Account" + }, + "typeStr": "0x1::account::Account", + "data": "{\"authentication_key\":\"0x7a2e070df14c96d0808ffab6b735591221241c34f6c4b4a9fa34051f945b5197\",\"coin_register_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x7a2e070df14c96d0808ffab6b735591221241c34f6c4b4a9fa34051f945b5197\",\"creation_num\":\"0\"}}},\"guid_creation_num\":\"4\",\"key_rotation_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x7a2e070df14c96d0808ffab6b735591221241c34f6c4b4a9fa34051f945b5197\",\"creation_num\":\"1\"}}},\"rotation_capability_offer\":{\"for\":{\"vec\":[]}},\"sequence_number\":\"1\",\"signer_capability_offer\":{\"for\":{\"vec\":[]}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0xcd1b23b223136afb13c3effc10e8ab98343f6aa3e51002a0f1ef1eb7a27db680", + "stateKeyHash": "piJGygQd5MN8BIfx0nZlKZHgVAnDJKgPdNmoAJjeFuE=", + "type": { + "address": "0x1", + "module": "fungible_asset", + "name": "FungibleStore" + }, + "typeStr": "0x1::fungible_asset::FungibleStore", + "data": "{\"balance\":\"1000000\",\"frozen\":false,\"metadata\":{\"inner\":\"0x77bc07c02b7c38abc5b9d7dbad97bd1e1ff4d4b24066c652d3884918f3e244a5\"}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0xcd1b23b223136afb13c3effc10e8ab98343f6aa3e51002a0f1ef1eb7a27db680", + "stateKeyHash": "piJGygQd5MN8BIfx0nZlKZHgVAnDJKgPdNmoAJjeFuE=", + "type": { + "address": "0x1", + "module": "object", + "name": "ObjectCore" + }, + "typeStr": "0x1::object::ObjectCore", + "data": "{\"allow_ungated_transfer\":false,\"guid_creation_num\":\"1125899906842625\",\"owner\":\"0xbabe\",\"transfer_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0xcd1b23b223136afb13c3effc10e8ab98343f6aa3e51002a0f1ef1eb7a27db680\",\"creation_num\":\"1125899906842624\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0xfb5c41dcb7005d617e5f341bb23e9e00a2bf70a9b8b714d186ee9a3df776cdd2", + "stateKeyHash": "ccViHZkhH4GJ+CMXpAEqINqi/bmKuLmUPeV2n8Ui4tg=", + "type": { + "address": "0x1", + "module": "fungible_asset", + "name": "FungibleStore" + }, + "typeStr": "0x1::fungible_asset::FungibleStore", + "data": "{\"balance\":\"0\",\"frozen\":false,\"metadata\":{\"inner\":\"0x77bc07c02b7c38abc5b9d7dbad97bd1e1ff4d4b24066c652d3884918f3e244a5\"}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0xfb5c41dcb7005d617e5f341bb23e9e00a2bf70a9b8b714d186ee9a3df776cdd2", + "stateKeyHash": "ccViHZkhH4GJ+CMXpAEqINqi/bmKuLmUPeV2n8Ui4tg=", + "type": { + "address": "0x1", + "module": "object", + "name": "ObjectCore" + }, + "typeStr": "0x1::object::ObjectCore", + "data": "{\"allow_ungated_transfer\":false,\"guid_creation_num\":\"1125899906842625\",\"owner\":\"0x7a2e070df14c96d0808ffab6b735591221241c34f6c4b4a9fa34051f945b5197\",\"transfer_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0xfb5c41dcb7005d617e5f341bb23e9e00a2bf70a9b8b714d186ee9a3df776cdd2\",\"creation_num\":\"1125899906842624\"}}}}" + } + }, + { + "type": "TYPE_WRITE_TABLE_ITEM", + "writeTableItem": { + "stateKeyHash": "bkso1A+YoQamUWNTCSTA3LQME0nTqpFdEItNbPwd2xk=", + "handle": "0x1b854694ae746cdbd8d44186ca4929b2b337df21d1c74633be19b2710552fdca", + "key": "0x0619dc29a0aac8fa146714058e8dd6d2d0f3bdf5f6331907bf91f3acd81e6935", + "data": { + "key": "\"0x619dc29a0aac8fa146714058e8dd6d2d0f3bdf5f6331907bf91f3acd81e6935\"", + "keyType": "address", + "value": "\"18446744073709012725\"", + "valueType": "u128" + } + } + } + ] + }, + "epoch": "2", + "blockHeight": "32", + "type": "TRANSACTION_TYPE_USER", + "sizeInfo": { + "transactionBytes": 1199, + "eventSizeInfo": [ + { + "typeTagBytes": 57, + "totalBytes": 97 + }, + { + "typeTagBytes": 58, + "totalBytes": 98 + }, + { + "typeTagBytes": 57, + "totalBytes": 97 + }, + { + "typeTagBytes": 58, + "totalBytes": 98 + }, + { + "typeTagBytes": 57, + "totalBytes": 97 + }, + { + "typeTagBytes": 63, + "totalBytes": 103 + } + ], + "writeOpSizeInfo": [ + { + "keyBytes": 87, + "valueBytes": 246 + }, + { + "keyBytes": 87, + "valueBytes": 464 + }, + { + "keyBytes": 138, + "valueBytes": 105 + }, + { + "keyBytes": 84, + "valueBytes": 147 + }, + { + "keyBytes": 87, + "valueBytes": 246 + }, + { + "keyBytes": 87, + "valueBytes": 246 + }, + { + "keyBytes": 66, + "valueBytes": 16 + } + ] + }, + "user": { + "request": { + "sender": "0x7a2e070df14c96d0808ffab6b735591221241c34f6c4b4a9fa34051f945b5197", + "maxGasAmount": "3345", + "gasUnitPrice": "100", + "expirationTimestampSecs": { + "seconds": "1732752437" + }, + "payload": { + "type": "TYPE_SCRIPT_PAYLOAD", + "scriptPayload": { + "code": { + "bytecode": "oRzrCwcAAAoIAQAMAgwoAzRNBIEBCgWLAZIBB50C/AIImQUgBrkFjwEAAAABAAIAAwAEAAUBBgIAAAcAAAEIBwEAAQAJCAAACgsAAAsGAAAMBgACDgcBAAAFEAcAAQ0DBAABAg8CBgEAAQURBwgAAQMSCQIAAQETCwwBCAEAFAsNAAEAFQsOAAEAFg8QAAEEFwARAAEDGBITAQgBABkVAgEIAQAaFhABCAEBBQQKCQoKFAsUAQYMDAgAAwYIAAgBCwIBCAMLAgEIAwsCAQgDCAEIAQsCAQgECAUIBgACBgwKAgEIAAEEAQsHAQkAAQoCAQgIBwYIAAsHAQQICAgIAggICAgBCAQBBggAAQsCAQkAAQgFAQgGAgYIBQMBCAEBBQIFCwIBCQABCwIBCAMBCAMDBggGCwIBCQAIAQMGCAYLAgEJAAMOZnVuZ2libGVfYXNzZXQGb2JqZWN0Bm9wdGlvbhZwcmltYXJ5X2Z1bmdpYmxlX3N0b3JlBnNpZ25lcgZzdHJpbmcOQ29uc3RydWN0b3JSZWYNRnVuZ2libGVBc3NldAZPYmplY3QNRnVuZ2libGVTdG9yZQhNZXRhZGF0YQdNaW50UmVmC1RyYW5zZmVyUmVmE2NyZWF0ZV9uYW1lZF9vYmplY3QGT3B0aW9uBG5vbmUGU3RyaW5nBHV0ZjgrY3JlYXRlX3ByaW1hcnlfc3RvcmVfZW5hYmxlZF9mdW5naWJsZV9hc3NldBtvYmplY3RfZnJvbV9jb25zdHJ1Y3Rvcl9yZWYRZ2VuZXJhdGVfbWludF9yZWYVZ2VuZXJhdGVfdHJhbnNmZXJfcmVmBG1pbnQKYWRkcmVzc19vZhtlbnN1cmVfcHJpbWFyeV9zdG9yZV9leGlzdHMQZGVwb3NpdF93aXRoX3JlZhF3aXRoZHJhd193aXRoX3JlZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCgIDAkZBCgIIB0ZBIENvaW4KAiAfaHR0cHM6Ly9leGFtcGxlLmNvbS9mYXZpY29uLmljbwoCFBNodHRwczovL2V4YW1wbGUuY29tBSAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADK/gUgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAur4AAAFFCgAHABEADAEOAQwDCgM4AAcBEQIHABECMQgHAhECBwMRAhEDCgM4AQwKCgMRBQwLCwMRBgwMBkBCDwAAAAAADAIOCwoCEQcMBAsAEQgKCjgCDAUODAoFCwQ4Aw4MCwUKAjgEDAgHBAoKOAIMBg4MCgYLCDgDDgwLBgsCOAQMCQcFCwo4AgwHDgwLBwsJOAMC", + "abi": { + "name": "main", + "visibility": "VISIBILITY_PUBLIC", + "isEntry": true, + "params": [ + { + "type": "MOVE_TYPES_REFERENCE", + "reference": { + "to": { + "type": "MOVE_TYPES_SIGNER" + } + } + } + ] + } + } + } + }, + "signature": { + "type": "TYPE_ED25519", + "ed25519": { + "publicKey": "X3dtn8+5n300isDheC1WwnuA6rUEP5ShsSfvipASLUM=", + "signature": "oMoT4Ogp1SUNY6oh6Ng9kKDHkWkf+hBMt1Beyfqe4cvTA/K8KjumJyK6Yat7EgRgk4QgfUpRvKNFxJwRblNoCw==" + } + } + }, + "events": [ + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "fungible_asset", + "name": "Deposit" + } + }, + "typeStr": "0x1::fungible_asset::Deposit", + "data": "{\"amount\":\"1000000\",\"store\":\"0xfb5c41dcb7005d617e5f341bb23e9e00a2bf70a9b8b714d186ee9a3df776cdd2\"}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "fungible_asset", + "name": "Withdraw" + } + }, + "typeStr": "0x1::fungible_asset::Withdraw", + "data": "{\"amount\":\"1000000\",\"store\":\"0xfb5c41dcb7005d617e5f341bb23e9e00a2bf70a9b8b714d186ee9a3df776cdd2\"}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "fungible_asset", + "name": "Deposit" + } + }, + "typeStr": "0x1::fungible_asset::Deposit", + "data": "{\"amount\":\"1000000\",\"store\":\"0x6653d0f1cd711df18dcaddeaa37e528fa7034e2f1b9ac3578cf4d0abaed12547\"}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "fungible_asset", + "name": "Withdraw" + } + }, + "typeStr": "0x1::fungible_asset::Withdraw", + "data": "{\"amount\":\"1000000\",\"store\":\"0x6653d0f1cd711df18dcaddeaa37e528fa7034e2f1b9ac3578cf4d0abaed12547\"}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "fungible_asset", + "name": "Deposit" + } + }, + "typeStr": "0x1::fungible_asset::Deposit", + "data": "{\"amount\":\"1000000\",\"store\":\"0xcd1b23b223136afb13c3effc10e8ab98343f6aa3e51002a0f1ef1eb7a27db680\"}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "transaction_fee", + "name": "FeeStatement" + } + }, + "typeStr": "0x1::transaction_fee::FeeStatement", + "data": "{\"execution_gas_units\":\"7\",\"io_gas_units\":\"7\",\"storage_fee_octas\":\"221680\",\"storage_fee_refund_octas\":\"0\",\"total_charge_gas_units\":\"2230\"}" + } + ] + } +} \ No newline at end of file diff --git a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/fa_mint_transfer_burn.json b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/fa_mint_transfer_burn.json index 2206cf631a561..4f0f698750d87 100644 --- a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/fa_mint_transfer_burn.json +++ b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/fa_mint_transfer_burn.json @@ -1,79 +1,51 @@ { "timestamp": { - "seconds": "1732672967", - "nanos": 932459000 + "seconds": "1732752394", + "nanos": 753016000 }, "version": "35", "info": { - "hash": "DGiU+N/60a/a6uuy94V86I9qRmNIKIu+FVVdY6FUS9A=", - "stateChangeHash": "OSOA2nyyEJm1CbchaFh1jqXk2U4gBc+op44dk59bFb4=", - "eventRootHash": "vDzA4XF4bCCJwq8bN/jYVp8Yinxa+CoaxRg8KoArN2Q=", + "hash": "TeqP7BOUSL4Cw6A9dPrPZIk307ZvOQTqk7SyktjQa3k=", + "stateChangeHash": "yjF48v0yCpkI1a6QlRCqw264uSQ4Iji+GGI7vYwaCCM=", + "eventRootHash": "zguCQh0yktZ64gFcK3ArJOOrDjHPVhTjf/pYU5fhJdc=", "gasUsed": "1161", "success": true, "vmStatus": "Executed successfully", - "accumulatorRootHash": "ybrUtD0TqXY/+Bhh1p+69NpelbNnUpnpgeLLyQFxWIA=", + "accumulatorRootHash": "kp/XkH7fLQsz3XWemRlICZpDjLnO8yPGyvb3c19+jHE=", "changes": [ { "type": "TYPE_WRITE_RESOURCE", "writeResource": { - "address": "0x313228f6c338fcca1b431fc6453c7288e5463b192a1b7b12914173aca3c337b7", - "stateKeyHash": "Y8Y0AitszA5qhqXL5YDf9E4PgIPbLctf+kdkZnucMyM=", + "address": "0x195f4751a5c8213e03a5568ddc8f711179edc98c2a44a5923351c815f2ee32ee", + "stateKeyHash": "u+s4Aetf6Uz24aXzSwHfIak6V1deZuGLMCZ3nw26A9U=", "type": { "address": "0x1", "module": "fungible_asset", - "name": "ConcurrentSupply" - }, - "typeStr": "0x1::fungible_asset::ConcurrentSupply", - "data": "{\"current\":{\"max_value\":\"340282366920938463463374607431768211455\",\"value\":\"0\"}}" - } - }, - { - "type": "TYPE_WRITE_RESOURCE", - "writeResource": { - "address": "0x313228f6c338fcca1b431fc6453c7288e5463b192a1b7b12914173aca3c337b7", - "stateKeyHash": "Y8Y0AitszA5qhqXL5YDf9E4PgIPbLctf+kdkZnucMyM=", - "type": { - "address": "0x1", - "module": "fungible_asset", - "name": "Metadata" + "name": "FungibleStore" }, - "typeStr": "0x1::fungible_asset::Metadata", - "data": "{\"decimals\":8,\"icon_uri\":\"https://example.com/favicon.ico\",\"name\":\"FA Coin\",\"project_uri\":\"https://example.com\",\"symbol\":\"FA\"}" + "typeStr": "0x1::fungible_asset::FungibleStore", + "data": "{\"balance\":\"0\",\"frozen\":false,\"metadata\":{\"inner\":\"0xfab779a7fb23b90d00312c9dd54194c4d147e6c391d052d07445c896b427980f\"}}" } }, { "type": "TYPE_WRITE_RESOURCE", "writeResource": { - "address": "0x313228f6c338fcca1b431fc6453c7288e5463b192a1b7b12914173aca3c337b7", - "stateKeyHash": "Y8Y0AitszA5qhqXL5YDf9E4PgIPbLctf+kdkZnucMyM=", + "address": "0x195f4751a5c8213e03a5568ddc8f711179edc98c2a44a5923351c815f2ee32ee", + "stateKeyHash": "u+s4Aetf6Uz24aXzSwHfIak6V1deZuGLMCZ3nw26A9U=", "type": { "address": "0x1", "module": "object", "name": "ObjectCore" }, "typeStr": "0x1::object::ObjectCore", - "data": "{\"allow_ungated_transfer\":true,\"guid_creation_num\":\"1125899906842625\",\"owner\":\"0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff\",\"transfer_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x313228f6c338fcca1b431fc6453c7288e5463b192a1b7b12914173aca3c337b7\",\"creation_num\":\"1125899906842624\"}}}}" + "data": "{\"allow_ungated_transfer\":false,\"guid_creation_num\":\"1125899906842625\",\"owner\":\"0xd857c1f1dc5303ffcdc47205ebddc02d485c9dce619fd4d00055d86b58143363\",\"transfer_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x195f4751a5c8213e03a5568ddc8f711179edc98c2a44a5923351c815f2ee32ee\",\"creation_num\":\"1125899906842624\"}}}}" } }, { "type": "TYPE_WRITE_RESOURCE", "writeResource": { - "address": "0x313228f6c338fcca1b431fc6453c7288e5463b192a1b7b12914173aca3c337b7", - "stateKeyHash": "Y8Y0AitszA5qhqXL5YDf9E4PgIPbLctf+kdkZnucMyM=", - "type": { - "address": "0x1", - "module": "primary_fungible_store", - "name": "DeriveRefPod" - }, - "typeStr": "0x1::primary_fungible_store::DeriveRefPod", - "data": "{\"metadata_derive_ref\":{\"self\":\"0x313228f6c338fcca1b431fc6453c7288e5463b192a1b7b12914173aca3c337b7\"}}" - } - }, - { - "type": "TYPE_WRITE_RESOURCE", - "writeResource": { - "address": "0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff", - "stateKeyHash": "ceneJQEOEzV92WirHTGbXnLP+TvF5K6btYiyF5HdKKg=", + "address": "0xd857c1f1dc5303ffcdc47205ebddc02d485c9dce619fd4d00055d86b58143363", + "stateKeyHash": "nfJ3Uaxl7f7VWyJy5+RSJKgm1neNXVt5gsGPrj96LVc=", "type": { "address": "0x1", "module": "coin", @@ -90,49 +62,77 @@ ] }, "typeStr": "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>", - "data": "{\"coin\":{\"value\":\"99883900\"},\"deposit_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff\",\"creation_num\":\"2\"}}},\"frozen\":false,\"withdraw_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff\",\"creation_num\":\"3\"}}}}" + "data": "{\"coin\":{\"value\":\"99883900\"},\"deposit_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0xd857c1f1dc5303ffcdc47205ebddc02d485c9dce619fd4d00055d86b58143363\",\"creation_num\":\"2\"}}},\"frozen\":false,\"withdraw_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0xd857c1f1dc5303ffcdc47205ebddc02d485c9dce619fd4d00055d86b58143363\",\"creation_num\":\"3\"}}}}" } }, { "type": "TYPE_WRITE_RESOURCE", "writeResource": { - "address": "0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff", - "stateKeyHash": "fosKvq2RB9fkmTNvrdzHt/qGGmluI1R/CwhAP58GB3o=", + "address": "0xd857c1f1dc5303ffcdc47205ebddc02d485c9dce619fd4d00055d86b58143363", + "stateKeyHash": "IjpJdBOi/M0uwPpcz2Zg1fa61T7wSFpMl7CDWWUBMVs=", "type": { "address": "0x1", "module": "account", "name": "Account" }, "typeStr": "0x1::account::Account", - "data": "{\"authentication_key\":\"0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff\",\"coin_register_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff\",\"creation_num\":\"0\"}}},\"guid_creation_num\":\"4\",\"key_rotation_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff\",\"creation_num\":\"1\"}}},\"rotation_capability_offer\":{\"for\":{\"vec\":[]}},\"sequence_number\":\"1\",\"signer_capability_offer\":{\"for\":{\"vec\":[]}}}" + "data": "{\"authentication_key\":\"0xd857c1f1dc5303ffcdc47205ebddc02d485c9dce619fd4d00055d86b58143363\",\"coin_register_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0xd857c1f1dc5303ffcdc47205ebddc02d485c9dce619fd4d00055d86b58143363\",\"creation_num\":\"0\"}}},\"guid_creation_num\":\"4\",\"key_rotation_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0xd857c1f1dc5303ffcdc47205ebddc02d485c9dce619fd4d00055d86b58143363\",\"creation_num\":\"1\"}}},\"rotation_capability_offer\":{\"for\":{\"vec\":[]}},\"sequence_number\":\"1\",\"signer_capability_offer\":{\"for\":{\"vec\":[]}}}" } }, { "type": "TYPE_WRITE_RESOURCE", "writeResource": { - "address": "0xfb24be743a80eebd426967035c9023ea7e83edce89f4d7085d6d43e0c95c2f0b", - "stateKeyHash": "bntLw5n1ZIlpJmPzcUUvYBrYwMDYMchcbzDA+dlDt3s=", + "address": "0xfab779a7fb23b90d00312c9dd54194c4d147e6c391d052d07445c896b427980f", + "stateKeyHash": "idvP1CLTbDbbUgZhcHK8xwv/bY56FV4I8pfeHuUr5Ls=", "type": { "address": "0x1", "module": "fungible_asset", - "name": "FungibleStore" + "name": "ConcurrentSupply" }, - "typeStr": "0x1::fungible_asset::FungibleStore", - "data": "{\"balance\":\"0\",\"frozen\":false,\"metadata\":{\"inner\":\"0x313228f6c338fcca1b431fc6453c7288e5463b192a1b7b12914173aca3c337b7\"}}" + "typeStr": "0x1::fungible_asset::ConcurrentSupply", + "data": "{\"current\":{\"max_value\":\"340282366920938463463374607431768211455\",\"value\":\"0\"}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0xfab779a7fb23b90d00312c9dd54194c4d147e6c391d052d07445c896b427980f", + "stateKeyHash": "idvP1CLTbDbbUgZhcHK8xwv/bY56FV4I8pfeHuUr5Ls=", + "type": { + "address": "0x1", + "module": "fungible_asset", + "name": "Metadata" + }, + "typeStr": "0x1::fungible_asset::Metadata", + "data": "{\"decimals\":8,\"icon_uri\":\"https://example.com/favicon.ico\",\"name\":\"FA Coin\",\"project_uri\":\"https://example.com\",\"symbol\":\"FA\"}" } }, { "type": "TYPE_WRITE_RESOURCE", "writeResource": { - "address": "0xfb24be743a80eebd426967035c9023ea7e83edce89f4d7085d6d43e0c95c2f0b", - "stateKeyHash": "bntLw5n1ZIlpJmPzcUUvYBrYwMDYMchcbzDA+dlDt3s=", + "address": "0xfab779a7fb23b90d00312c9dd54194c4d147e6c391d052d07445c896b427980f", + "stateKeyHash": "idvP1CLTbDbbUgZhcHK8xwv/bY56FV4I8pfeHuUr5Ls=", "type": { "address": "0x1", "module": "object", "name": "ObjectCore" }, "typeStr": "0x1::object::ObjectCore", - "data": "{\"allow_ungated_transfer\":false,\"guid_creation_num\":\"1125899906842625\",\"owner\":\"0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff\",\"transfer_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0xfb24be743a80eebd426967035c9023ea7e83edce89f4d7085d6d43e0c95c2f0b\",\"creation_num\":\"1125899906842624\"}}}}" + "data": "{\"allow_ungated_transfer\":true,\"guid_creation_num\":\"1125899906842625\",\"owner\":\"0xd857c1f1dc5303ffcdc47205ebddc02d485c9dce619fd4d00055d86b58143363\",\"transfer_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0xfab779a7fb23b90d00312c9dd54194c4d147e6c391d052d07445c896b427980f\",\"creation_num\":\"1125899906842624\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0xfab779a7fb23b90d00312c9dd54194c4d147e6c391d052d07445c896b427980f", + "stateKeyHash": "idvP1CLTbDbbUgZhcHK8xwv/bY56FV4I8pfeHuUr5Ls=", + "type": { + "address": "0x1", + "module": "primary_fungible_store", + "name": "DeriveRefPod" + }, + "typeStr": "0x1::primary_fungible_store::DeriveRefPod", + "data": "{\"metadata_derive_ref\":{\"self\":\"0xfab779a7fb23b90d00312c9dd54194c4d147e6c391d052d07445c896b427980f\"}}" } }, { @@ -173,7 +173,7 @@ "writeOpSizeInfo": [ { "keyBytes": 87, - "valueBytes": 464 + "valueBytes": 246 }, { "keyBytes": 138, @@ -185,7 +185,7 @@ }, { "keyBytes": 87, - "valueBytes": 246 + "valueBytes": 464 }, { "keyBytes": 66, @@ -195,11 +195,11 @@ }, "user": { "request": { - "sender": "0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff", + "sender": "0xd857c1f1dc5303ffcdc47205ebddc02d485c9dce619fd4d00055d86b58143363", "maxGasAmount": "1741", "gasUnitPrice": "100", "expirationTimestampSecs": { - "seconds": "1732672998" + "seconds": "1732752425" }, "payload": { "type": "TYPE_SCRIPT_PAYLOAD", @@ -227,8 +227,8 @@ "signature": { "type": "TYPE_ED25519", "ed25519": { - "publicKey": "spiXXSfb/zAg5e5/27rYqWnU8qLVKG4JfR25dg0E3TE=", - "signature": "neaivYBEoxiBZWvjKvdRg/oQgie7W0w3+FQO957zUxHUXtZkocABqzttJnV1kcoIwMUNAstLGdPSmyG+2nylBg==" + "publicKey": "KU08yl94iErSCo4VhF6tGWQYqvSaK1IjTD/4i/uoPSI=", + "signature": "w3Va79RRl9B7rA3+e4c1BsL1mHALLYkJQPeTDUwBfs6tqW55B61XLj8bBYf5m6SPP44JGS54Sy+B17engewICg==" } } }, @@ -246,7 +246,7 @@ } }, "typeStr": "0x1::fungible_asset::Deposit", - "data": "{\"amount\":\"1000000\",\"store\":\"0xfb24be743a80eebd426967035c9023ea7e83edce89f4d7085d6d43e0c95c2f0b\"}" + "data": "{\"amount\":\"1000000\",\"store\":\"0x195f4751a5c8213e03a5568ddc8f711179edc98c2a44a5923351c815f2ee32ee\"}" }, { "key": { @@ -261,7 +261,7 @@ } }, "typeStr": "0x1::fungible_asset::Withdraw", - "data": "{\"amount\":\"1000000\",\"store\":\"0xfb24be743a80eebd426967035c9023ea7e83edce89f4d7085d6d43e0c95c2f0b\"}" + "data": "{\"amount\":\"1000000\",\"store\":\"0x195f4751a5c8213e03a5568ddc8f711179edc98c2a44a5923351c815f2ee32ee\"}" }, { "key": { diff --git a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script1.json b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script1.json index 64fdcd10b945c..8656175cb6d90 100644 --- a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script1.json +++ b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script1.json @@ -1,17 +1,17 @@ { "timestamp": { - "seconds": "1731095950", - "nanos": 496779000 + "seconds": "1732752427", + "nanos": 716542000 }, - "version": "67", + "version": "131", "info": { - "hash": "6kJvSg6J6/nzJtn+Qg0iqEu+D/LUChmq4pX5FbpJ2yE=", - "stateChangeHash": "Ud1ILaQ9/i/UVj2SIebzib9eEt/Eqz4JBYfhOoCgBfQ=", + "hash": "KpFwmiU5ttJrMUTypaifB3Ild8caulWChn2UDQqbP1A=", + "stateChangeHash": "QuedrdLgRVt8SZdyoPAbs4clpCwqCe+2UAo8+nrx1SA=", "eventRootHash": "J/kCueHhHqJXi8MVudrh82sOQ/pqY9TJ9VjLOdgel6I=", "gasUsed": "3", "success": true, "vmStatus": "Executed successfully", - "accumulatorRootHash": "FxelBtaxPVGCVulc0mkobWhQB4TqjvzFBaH5wvI71jc=", + "accumulatorRootHash": "r2FZPXOd5Djv8G3fsmDkmfWSO4ic4O6nLsoInIwSFFg=", "changes": [ { "type": "TYPE_WRITE_RESOURCE", @@ -60,7 +60,7 @@ "data": { "key": "\"0x619dc29a0aac8fa146714058e8dd6d2d0f3bdf5f6331907bf91f3acd81e6935\"", "keyType": "address", - "value": "\"18446744073809350825\"", + "value": "\"18446744074009011525\"", "valueType": "u128" } } @@ -68,7 +68,7 @@ ] }, "epoch": "2", - "blockHeight": "31", + "blockHeight": "61", "type": "TRANSACTION_TYPE_USER", "sizeInfo": { "transactionBytes": 190, @@ -99,7 +99,7 @@ "maxGasAmount": "4", "gasUnitPrice": "100", "expirationTimestampSecs": { - "seconds": "1731095980" + "seconds": "1732752458" }, "payload": { "type": "TYPE_SCRIPT_PAYLOAD", @@ -128,7 +128,7 @@ "type": "TYPE_ED25519", "ed25519": { "publicKey": "ObSsyF4CbcBWRkpeoAuY+FgmDqrSt03TC4auDU2U3fU=", - "signature": "0L++p+Cn6mxmKItu2eTyVMXiZkJY0v+KgxORh5u6GgHG2nprS3cAzw2Wk4PQVEy0RXrVHsbwtdzDi4PngcIJAw==" + "signature": "rGLJfiyHpSe+xtzx6B/3PkqTsybbYGFzoToVGb9HEfN0Va0/cEV2udTtGnxGy0ZW3VG7qHnaywt9mLFYFp8DBA==" } } }, diff --git a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script2.json b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script2.json index 4d343ea0a5bf0..32e080a650ee9 100644 --- a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script2.json +++ b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script2.json @@ -1,17 +1,17 @@ { "timestamp": { - "seconds": "1731095956", - "nanos": 533018000 + "seconds": "1732752433", + "nanos": 945287000 }, - "version": "87", + "version": "151", "info": { - "hash": "JzyTL33SVpom7cI1p+7nYedPyOyLsbHsBvzZKH1upAw=", - "stateChangeHash": "Ylxp7ADO/X1goShWlx5C05rioDlBXLUc5x2qqkVxiEU=", + "hash": "T0MflJ4xr13oeDZtbIJrwVBB6+xbXWtc22gEe8mr0lM=", + "stateChangeHash": "BEruB8zGnFmiqh19p3v5OMcGbmR7i7SNqPQxLTrli2E=", "eventRootHash": "J/kCueHhHqJXi8MVudrh82sOQ/pqY9TJ9VjLOdgel6I=", "gasUsed": "3", "success": true, "vmStatus": "Executed successfully", - "accumulatorRootHash": "yPDkkszubIu8pK4a0DgL70ro/fyChX2XZYS1/6w82DQ=", + "accumulatorRootHash": "C3Lb3f2L4loI/ozhPOyPO8vEQgYtVqv1pB0ktt/AdUw=", "changes": [ { "type": "TYPE_WRITE_RESOURCE", @@ -60,7 +60,7 @@ "data": { "key": "\"0x619dc29a0aac8fa146714058e8dd6d2d0f3bdf5f6331907bf91f3acd81e6935\"", "keyType": "address", - "value": "\"18446744073909449225\"", + "value": "\"18446744074109109925\"", "valueType": "u128" } } @@ -68,7 +68,7 @@ ] }, "epoch": "2", - "blockHeight": "40", + "blockHeight": "70", "type": "TRANSACTION_TYPE_USER", "sizeInfo": { "transactionBytes": 190, @@ -100,7 +100,7 @@ "maxGasAmount": "4", "gasUnitPrice": "100", "expirationTimestampSecs": { - "seconds": "1731095987" + "seconds": "1732752464" }, "payload": { "type": "TYPE_SCRIPT_PAYLOAD", @@ -129,7 +129,7 @@ "type": "TYPE_ED25519", "ed25519": { "publicKey": "ObSsyF4CbcBWRkpeoAuY+FgmDqrSt03TC4auDU2U3fU=", - "signature": "fuZvCUvBQpKFX31vInp+QsYCShaRCyMtu1dP4waPiVueuM2Jblo5InrcmWQfK+j4x9NeUpKJO5zI+YIC27SbAQ==" + "signature": "+939tVIjj3xsPAcg44upEZkSjnaheRT92WjUC6gN4R6y3w+GsT/wkH9RzVjHkQCREACErqbFPw7XgR/4D2JuDg==" } } }, diff --git a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script3.json b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script3.json index 4aca3be5af462..2b8128ffb31ba 100644 --- a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script3.json +++ b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script3.json @@ -1,23 +1,23 @@ { "timestamp": { - "seconds": "1732672975", - "nanos": 261345000 + "seconds": "1732752414", + "nanos": 344797000 }, - "version": "57", + "version": "89", "info": { - "hash": "1kLYjLwrzJF1XkkoSWG6m+EOvIkzkijdAmHc+frQImQ=", - "stateChangeHash": "h4Bop9rEeFcWLdIdxJr+aWdLDW2OJ/cqulIqA06dLDc=", + "hash": "0Grfy/3XflrDlM1pN9ROC4DcC8LUaE14lYdA5hZv94g=", + "stateChangeHash": "OSCXnaT5m3N/W6XcSsBMYgURA+ItiZfCdPK0jQ1QxsU=", "eventRootHash": "J/kCueHhHqJXi8MVudrh82sOQ/pqY9TJ9VjLOdgel6I=", "gasUsed": "3", "success": true, "vmStatus": "Executed successfully", - "accumulatorRootHash": "HusghxoSOCUrHGTtp4OaZ3qBwShyrk28S5ZBCe71fbI=", + "accumulatorRootHash": "rDQPrWw9UolILsSMP07nXU9BZJ+JWHJlReNjcVxV4Tk=", "changes": [ { "type": "TYPE_WRITE_RESOURCE", "writeResource": { - "address": "0x8f0de18409d6fca18c72fac4062fc0f9baa6404296fed93a3ad0250fb671f8b3", - "stateKeyHash": "2Ne4/4Qg7OpxqV5LI4CB9VlZutr1u5HaXhbSTzYWYw8=", + "address": "0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff", + "stateKeyHash": "ceneJQEOEzV92WirHTGbXnLP+TvF5K6btYiyF5HdKKg=", "type": { "address": "0x1", "module": "coin", @@ -34,21 +34,21 @@ ] }, "typeStr": "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>", - "data": "{\"coin\":{\"value\":\"99999700\"},\"deposit_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x8f0de18409d6fca18c72fac4062fc0f9baa6404296fed93a3ad0250fb671f8b3\",\"creation_num\":\"2\"}}},\"frozen\":false,\"withdraw_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x8f0de18409d6fca18c72fac4062fc0f9baa6404296fed93a3ad0250fb671f8b3\",\"creation_num\":\"3\"}}}}" + "data": "{\"coin\":{\"value\":\"99999700\"},\"deposit_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff\",\"creation_num\":\"2\"}}},\"frozen\":false,\"withdraw_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff\",\"creation_num\":\"3\"}}}}" } }, { "type": "TYPE_WRITE_RESOURCE", "writeResource": { - "address": "0x8f0de18409d6fca18c72fac4062fc0f9baa6404296fed93a3ad0250fb671f8b3", - "stateKeyHash": "CruPmGDHh8XlpNdvv1soHpZeHrF/hdy9+k4liPo15BE=", + "address": "0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff", + "stateKeyHash": "fosKvq2RB9fkmTNvrdzHt/qGGmluI1R/CwhAP58GB3o=", "type": { "address": "0x1", "module": "account", "name": "Account" }, "typeStr": "0x1::account::Account", - "data": "{\"authentication_key\":\"0x8f0de18409d6fca18c72fac4062fc0f9baa6404296fed93a3ad0250fb671f8b3\",\"coin_register_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x8f0de18409d6fca18c72fac4062fc0f9baa6404296fed93a3ad0250fb671f8b3\",\"creation_num\":\"0\"}}},\"guid_creation_num\":\"4\",\"key_rotation_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x8f0de18409d6fca18c72fac4062fc0f9baa6404296fed93a3ad0250fb671f8b3\",\"creation_num\":\"1\"}}},\"rotation_capability_offer\":{\"for\":{\"vec\":[]}},\"sequence_number\":\"1\",\"signer_capability_offer\":{\"for\":{\"vec\":[]}}}" + "data": "{\"authentication_key\":\"0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff\",\"coin_register_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff\",\"creation_num\":\"0\"}}},\"guid_creation_num\":\"4\",\"key_rotation_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff\",\"creation_num\":\"1\"}}},\"rotation_capability_offer\":{\"for\":{\"vec\":[]}},\"sequence_number\":\"1\",\"signer_capability_offer\":{\"for\":{\"vec\":[]}}}" } }, { @@ -60,7 +60,7 @@ "data": { "key": "\"0x619dc29a0aac8fa146714058e8dd6d2d0f3bdf5f6331907bf91f3acd81e6935\"", "keyType": "address", - "value": "\"18446744073709235425\"", + "value": "\"18446744073809012325\"", "valueType": "u128" } } @@ -68,7 +68,7 @@ ] }, "epoch": "2", - "blockHeight": "27", + "blockHeight": "42", "type": "TRANSACTION_TYPE_USER", "sizeInfo": { "transactionBytes": 190, @@ -95,11 +95,11 @@ }, "user": { "request": { - "sender": "0x8f0de18409d6fca18c72fac4062fc0f9baa6404296fed93a3ad0250fb671f8b3", + "sender": "0x765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff", "maxGasAmount": "4", "gasUnitPrice": "100", "expirationTimestampSecs": { - "seconds": "1732673005" + "seconds": "1732752444" }, "payload": { "type": "TYPE_SCRIPT_PAYLOAD", @@ -127,8 +127,8 @@ "signature": { "type": "TYPE_ED25519", "ed25519": { - "publicKey": "7wW+3hX0IuFsAALjzui01DQVGNmcRpU1KhhpsHeYZPs=", - "signature": "+me7d5O4YGWWVVHrr8ByGeWF83oZ/S6LCnlEIH4FnITO3eoDu1U4qQllX+hJURRn1R6rVjU8ZKaw9BRXGJvtBQ==" + "publicKey": "spiXXSfb/zAg5e5/27rYqWnU8qLVKG4JfR25dg0E3TE=", + "signature": "g4fW/Liaw2li3GQpwKqjSn/g/9nPsLewSV9Xfh2mqGhqqYp8CjKfZWaoY5xnDW25+I2xMY9qX20mM9SN0UcDBQ==" } } }, diff --git a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script4.json b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script4.json index 2a28f57eea78f..ceeb655d2ec61 100644 --- a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script4.json +++ b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script4.json @@ -1,23 +1,23 @@ { "timestamp": { - "seconds": "1732672981", - "nanos": 856611000 + "seconds": "1732752420", + "nanos": 683733000 }, - "version": "77", + "version": "109", "info": { - "hash": "kXQ14XDqfcKlqro7h6UnIYBU7ReXHC1f1dh4cqrA9Wc=", - "stateChangeHash": "Lcw2QcDIjyWNLv4WjU3hZRLkFqRYzhyRVs6flb5HF48=", + "hash": "wRDhIULIsprwu5kAQH0lrzCNH/hOXaGiwp+IkYZnrsA=", + "stateChangeHash": "VXDLlx4UXl+5kFAps8EMPPt/lEBF9OwbqtBXnjwzyZM=", "eventRootHash": "J/kCueHhHqJXi8MVudrh82sOQ/pqY9TJ9VjLOdgel6I=", "gasUsed": "3", "success": true, "vmStatus": "Executed successfully", - "accumulatorRootHash": "gnscCFfMFb90l70guVpWFI6dGl4pspC5ynpsbp2WBEw=", + "accumulatorRootHash": "N3sY2AwsTq74Qb3un7ZuTs9PFgUnWflI1u1LcSe+M3Y=", "changes": [ { "type": "TYPE_WRITE_RESOURCE", "writeResource": { - "address": "0x501b015c58f2a1a62a330a6da80dfee723f528f719d25a4232751986f9a9f43f", - "stateKeyHash": "mblV8kItKhzWpJyNZcf9X5l3EmRe3m4NrXTdtzITQ6k=", + "address": "0x8f0de18409d6fca18c72fac4062fc0f9baa6404296fed93a3ad0250fb671f8b3", + "stateKeyHash": "2Ne4/4Qg7OpxqV5LI4CB9VlZutr1u5HaXhbSTzYWYw8=", "type": { "address": "0x1", "module": "coin", @@ -34,21 +34,21 @@ ] }, "typeStr": "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>", - "data": "{\"coin\":{\"value\":\"99999700\"},\"deposit_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x501b015c58f2a1a62a330a6da80dfee723f528f719d25a4232751986f9a9f43f\",\"creation_num\":\"2\"}}},\"frozen\":false,\"withdraw_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x501b015c58f2a1a62a330a6da80dfee723f528f719d25a4232751986f9a9f43f\",\"creation_num\":\"3\"}}}}" + "data": "{\"coin\":{\"value\":\"99999700\"},\"deposit_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x8f0de18409d6fca18c72fac4062fc0f9baa6404296fed93a3ad0250fb671f8b3\",\"creation_num\":\"2\"}}},\"frozen\":false,\"withdraw_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x8f0de18409d6fca18c72fac4062fc0f9baa6404296fed93a3ad0250fb671f8b3\",\"creation_num\":\"3\"}}}}" } }, { "type": "TYPE_WRITE_RESOURCE", "writeResource": { - "address": "0x501b015c58f2a1a62a330a6da80dfee723f528f719d25a4232751986f9a9f43f", - "stateKeyHash": "+VS7DLwWFCETA4QQAND9ZVqc3IugzikHe1YU0T9rVo0=", + "address": "0x8f0de18409d6fca18c72fac4062fc0f9baa6404296fed93a3ad0250fb671f8b3", + "stateKeyHash": "CruPmGDHh8XlpNdvv1soHpZeHrF/hdy9+k4liPo15BE=", "type": { "address": "0x1", "module": "account", "name": "Account" }, "typeStr": "0x1::account::Account", - "data": "{\"authentication_key\":\"0x501b015c58f2a1a62a330a6da80dfee723f528f719d25a4232751986f9a9f43f\",\"coin_register_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x501b015c58f2a1a62a330a6da80dfee723f528f719d25a4232751986f9a9f43f\",\"creation_num\":\"0\"}}},\"guid_creation_num\":\"4\",\"key_rotation_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x501b015c58f2a1a62a330a6da80dfee723f528f719d25a4232751986f9a9f43f\",\"creation_num\":\"1\"}}},\"rotation_capability_offer\":{\"for\":{\"vec\":[]}},\"sequence_number\":\"1\",\"signer_capability_offer\":{\"for\":{\"vec\":[]}}}" + "data": "{\"authentication_key\":\"0x8f0de18409d6fca18c72fac4062fc0f9baa6404296fed93a3ad0250fb671f8b3\",\"coin_register_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x8f0de18409d6fca18c72fac4062fc0f9baa6404296fed93a3ad0250fb671f8b3\",\"creation_num\":\"0\"}}},\"guid_creation_num\":\"4\",\"key_rotation_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x8f0de18409d6fca18c72fac4062fc0f9baa6404296fed93a3ad0250fb671f8b3\",\"creation_num\":\"1\"}}},\"rotation_capability_offer\":{\"for\":{\"vec\":[]}},\"sequence_number\":\"1\",\"signer_capability_offer\":{\"for\":{\"vec\":[]}}}" } }, { @@ -60,7 +60,7 @@ "data": { "key": "\"0x619dc29a0aac8fa146714058e8dd6d2d0f3bdf5f6331907bf91f3acd81e6935\"", "keyType": "address", - "value": "\"18446744073809235025\"", + "value": "\"18446744073909011925\"", "valueType": "u128" } } @@ -68,7 +68,7 @@ ] }, "epoch": "2", - "blockHeight": "36", + "blockHeight": "51", "type": "TRANSACTION_TYPE_USER", "sizeInfo": { "transactionBytes": 190, @@ -95,11 +95,11 @@ }, "user": { "request": { - "sender": "0x501b015c58f2a1a62a330a6da80dfee723f528f719d25a4232751986f9a9f43f", + "sender": "0x8f0de18409d6fca18c72fac4062fc0f9baa6404296fed93a3ad0250fb671f8b3", "maxGasAmount": "4", "gasUnitPrice": "100", "expirationTimestampSecs": { - "seconds": "1732673012" + "seconds": "1732752451" }, "payload": { "type": "TYPE_SCRIPT_PAYLOAD", @@ -127,8 +127,8 @@ "signature": { "type": "TYPE_ED25519", "ed25519": { - "publicKey": "ySyOe0Rn5inKjNIBohVk3jnup8vkW1m/038QtW4Kcow=", - "signature": "CGV33Y0/bikBWNw3LC0+d831fiNYnZghAkXrqPoFNCH6SCUBAXYUywE4SkTRZa4hp3Da0GHymrCd32aLNdE7Cw==" + "publicKey": "7wW+3hX0IuFsAALjzui01DQVGNmcRpU1KhhpsHeYZPs=", + "signature": "0X9bVOKu0cJvabk5JyrFgGXHDYuEc20Nh9L7eY8fw+gy12roELRmNPZdUlEr6BDkc67OKHLgpNB/Q/iNuPirCw==" } } }, diff --git a/ecosystem/indexer-grpc/indexer-transaction-generator/README.md b/ecosystem/indexer-grpc/indexer-transaction-generator/README.md index d2988015abb0c..597850b618fff 100644 --- a/ecosystem/indexer-grpc/indexer-transaction-generator/README.md +++ b/ecosystem/indexer-grpc/indexer-transaction-generator/README.md @@ -65,5 +65,10 @@ You can check the example [here](imported_transactions). Each sender_address specified in script transaction config is a place holder string; the actual account address will be allocated by account manager. +The accounts in `testing_accounts.yaml` will be used to run scripted transaction. +They are persistedin config so each scripted transaction's generated output stays consistent between +`aptos-indexer-transaction-generator` runs. You can generate more testing accounts using +Aptos CLI by running `aptos init --profile local`. + TODO: account manager handles address as script argument. diff --git a/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/fa_double_transfer.yaml b/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/fa_double_transfer.yaml new file mode 100644 index 0000000000000..35871efc024e2 --- /dev/null +++ b/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/fa_double_transfer.yaml @@ -0,0 +1,5 @@ +transactions: + - output_name: fa_double_transfer + script_path: fa_double_transfer + sender_address: __ACCOUNT_A__ + \ No newline at end of file diff --git a/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/fa_double_transfer/Move.toml b/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/fa_double_transfer/Move.toml new file mode 100644 index 0000000000000..e699cdc33a1e6 --- /dev/null +++ b/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/fa_double_transfer/Move.toml @@ -0,0 +1,9 @@ +[package] +name = "fa_double_transfer" +version = "1.0.0" +authors = [] + +[addresses] + +[dependencies] +AptosFramework = { local = "../../../../../../aptos-move/framework/aptos-framework" } diff --git a/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/fa_double_transfer/script.mv b/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/fa_double_transfer/script.mv new file mode 100644 index 0000000000000000000000000000000000000000..28c804ec247b215f017fee5d9c0aed065e748f19 GIT binary patch literal 1029 zcmah|O>fjN5FOj`$J%ao)7_SjBC$s#q*h2AR-7mmy;YSc_bA;s+n{c;O1!ijIdeeb z#(@Jr0}lKE{tABqA;#&ll@Ka9*q%3U=Dktu&-Z>937{1LOYH;p_$YcyG=E1v5c!Gz zr0OFdi!b~=0RRFN7(~E{pa57!lq87u6gDsbMgUj=G)5HoKmyrd5fIv^0%<&v3JBZm zQ6OY!EJ4YU*}(cO6XUww9{`DNL4u^)o5PU4vqi&pcYA;v;gRlXJu)LAtX05-0!0im z*!7~27@|mVg-(Rk7+_msB`UEEFO~aiRnjinC6X@+-L0KrNIN z9iqtk$l_vI&C1hrmu7A2yr@rKxhZZ7U)I(3qABND^Cn%BT398Z(`(CVnzV3*S2Y0?6|63HZJ{3|FUd-JILLlZcCqDl>V#}35UGNF4hQM z%$q*^=ZqfiYpUeo{`jCSD^17u&%9r>PxkiQWj0@&yWMF$-z&1$C62U9ODKPY^B zlM=x9U;kr#{f4jRxyHwnfF&`pOtT3{l2AnGBPA)GSVEJ46RR~#xHX0)c;&^@XZ=p! z(%5L4NE;bQl-3h!d2BT|(S*g;a7`zXRWj-_0yDy>E`t{rGd;;osFBE(rZ-{qH??rV A?EnA( literal 0 HcmV?d00001 diff --git a/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/fa_double_transfer/sources/main.move b/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/fa_double_transfer/sources/main.move new file mode 100644 index 0000000000000..5f09fee77e2f7 --- /dev/null +++ b/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/fa_double_transfer/sources/main.move @@ -0,0 +1,45 @@ +script { + use std::signer; + use std::string::{utf8}; + use std::option; + + use aptos_framework::object::{Self, object_from_constructor_ref}; + use aptos_framework::fungible_asset::{Self, Metadata}; + use aptos_framework::primary_fungible_store::{Self}; + + const ASSET_SYMBOL: vector = b"FA"; + + fun main(admin: &signer) { + let constructor_ref = &object::create_named_object(admin, ASSET_SYMBOL); + primary_fungible_store::create_primary_store_enabled_fungible_asset( + constructor_ref, + option::none(), + utf8(b"FA Coin"), /* name */ + utf8(ASSET_SYMBOL), /* symbol */ + 8, /* decimals */ + utf8(b"https://example.com/favicon.ico"), /* icon */ + utf8(b"https://example.com"), /* project */ + ); + let metadata = object_from_constructor_ref(constructor_ref); + + // Create mint/transfer refs to allow creator to manage the fungible asset. + let mint_ref = fungible_asset::generate_mint_ref(constructor_ref); + let transfer_ref = fungible_asset::generate_transfer_ref(constructor_ref); + + // Mint to account A + let amount = 1000000; + let fa = fungible_asset::mint(&mint_ref, amount); + let fa_store_a = primary_fungible_store::ensure_primary_store_exists(signer::address_of(admin), metadata); + fungible_asset::deposit_with_ref(&transfer_ref, fa_store_a, fa); + + // Withdraw and transfer to account B + let fa_withdrawn = fungible_asset::withdraw_with_ref(&transfer_ref, fa_store_a, amount); + let fa_store_b = primary_fungible_store::ensure_primary_store_exists(@0xcafe, metadata); + fungible_asset::deposit_with_ref(&transfer_ref, fa_store_b, fa_withdrawn); + + // Withdraw and transfer to account C + let fa_withdrawn = fungible_asset::withdraw_with_ref(&transfer_ref, fa_store_b, amount); + let fa_store_c = primary_fungible_store::ensure_primary_store_exists(@0xbabe, metadata); + fungible_asset::deposit_with_ref(&transfer_ref, fa_store_c, fa_withdrawn); + } +} diff --git a/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/simple_user_script/sources/main.move b/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/simple_user_script/sources/main.move index 68fa0f4d90fd9..baa8e7a2a0c6b 100644 --- a/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/simple_user_script/sources/main.move +++ b/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/simple_user_script/sources/main.move @@ -1,4 +1,4 @@ script { - fun main(src: &signer) { + fun main(_: &signer) { } } diff --git a/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/simple_user_script2/sources/main.move b/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/simple_user_script2/sources/main.move index 68fa0f4d90fd9..baa8e7a2a0c6b 100644 --- a/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/simple_user_script2/sources/main.move +++ b/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/move_fixtures/simple_user_script2/sources/main.move @@ -1,4 +1,4 @@ script { - fun main(src: &signer) { + fun main(_: &signer) { } } diff --git a/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/testing_accounts.yaml b/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/testing_accounts.yaml index cec489415cde8..f0cbcdd8cfe70 100644 --- a/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/testing_accounts.yaml +++ b/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/testing_accounts.yaml @@ -13,4 +13,10 @@ accounts: - private_key: "0xf24423f014e6f2fdd1914d6961b49a2cfc9eac59b88a57457e4cd9424fc140c8" public_key: "0xb298975d27dbff3020e5ee7fdbbad8a969d4f2a2d5286e097d1db9760d04dd31" account: 765d8c8d4d5859f43a56e2756fbf5f3d2483dbaa14f3fb62872df820d6e64eff + - private_key: "0xd5dc637987a9ca85f52be2ff583a408ae5747a99f2fe85de416c9339e669a86b" + public_key: "0x5f776d9fcfb99f7d348ac0e1782d56c27b80eab5043f94a1b127ef8a90122d43" + account: 7a2e070df14c96d0808ffab6b735591221241c34f6c4b4a9fa34051f945b5197 + - private_key: "0x9a2a409701f7ca41251cc2a4a0442ec44a450133b0d23564fc09191e763fd551" + public_key: "0x294d3cca5f78884ad20a8e15845ead196418aaf49a2b52234c3ff88bfba83d22" + account: d857c1f1dc5303ffcdc47205ebddc02d485c9dce619fd4d00055d86b58143363 \ No newline at end of file diff --git a/ecosystem/indexer-grpc/indexer-transaction-generator/src/config.rs b/ecosystem/indexer-grpc/indexer-transaction-generator/src/config.rs index 356e3502d7fb4..8f6e483bd7268 100644 --- a/ecosystem/indexer-grpc/indexer-transaction-generator/src/config.rs +++ b/ecosystem/indexer-grpc/indexer-transaction-generator/src/config.rs @@ -74,6 +74,7 @@ impl IndexerCliArgs { continue; } let path = entry.path(); + println!("\nFound path: {:?}\n", path.display()); if path.extension().unwrap_or_default() == "yaml" { let file_name = path.file_name().unwrap().to_str().unwrap(); let script_transactions_raw: String = tokio::fs::read_to_string(&path).await?; From a75189b471d484f46513cb86ea2f6770332f832f Mon Sep 17 00:00:00 2001 From: rtso <8248583+rtso@users.noreply.github.com> Date: Wed, 27 Nov 2024 16:12:57 -0800 Subject: [PATCH 09/78] add more incident txns --- .../4462417704_secondary_store_burnt.json | 872 ++++++++++++++++++ .../646928741_no_events.json | 387 ++++++++ .../fa_double_transfer.json | 18 +- .../fa_mint_transfer_burn.json | 14 +- .../simple_user_script1.json | 18 +- .../simple_user_script2.json | 18 +- .../simple_user_script3.json | 18 +- .../simple_user_script4.json | 18 +- .../imported_transactions.yaml | 4 + .../src/config.rs | 1 - 10 files changed, 1315 insertions(+), 53 deletions(-) create mode 100644 ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/imported_testnet_txns/4462417704_secondary_store_burnt.json create mode 100644 ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/imported_testnet_txns/646928741_no_events.json diff --git a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/imported_testnet_txns/4462417704_secondary_store_burnt.json b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/imported_testnet_txns/4462417704_secondary_store_burnt.json new file mode 100644 index 0000000000000..e4e69218484cb --- /dev/null +++ b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/imported_testnet_txns/4462417704_secondary_store_burnt.json @@ -0,0 +1,872 @@ +{ + "timestamp": { + "seconds": "1720638211", + "nanos": 722842000 + }, + "version": "4462417704", + "info": { + "hash": "008kT24M0s3oZR4ZAoBetx8mNyReQvyRa7nUbRUJ/Sw=", + "stateChangeHash": "FOvB8UuTcK3D+ydERf1C1OftKTBsUqY3HPyhZ9dElRs=", + "eventRootHash": "rIrguN2CxmSHmDLSgcT3BNQWdIDNpl/YWepyHGqLXnI=", + "gasUsed": "228", + "success": true, + "vmStatus": "Executed successfully", + "accumulatorRootHash": "S1uePITGsuRaXaZCDnKKmz+3AvSmSvR0kFq4k3ZUeAU=", + "changes": [ + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0xd4c938456b88884e2b8ca56c7003ccefb4acd0c4f2bca8342c8290b97dca085", + "stateKeyHash": "i4ld4Iwu48uNgMppDSMbHUZxaAhT3W1EFkOhqUZdnOg=", + "type": { + "address": "0x1", + "module": "fungible_asset", + "name": "ConcurrentSupply" + }, + "typeStr": "0x1::fungible_asset::ConcurrentSupply", + "data": "{\"current\":{\"max_value\":\"340282366920938463463374607431768211455\",\"value\":\"11613950859225\"}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0xd4c938456b88884e2b8ca56c7003ccefb4acd0c4f2bca8342c8290b97dca085", + "stateKeyHash": "i4ld4Iwu48uNgMppDSMbHUZxaAhT3W1EFkOhqUZdnOg=", + "type": { + "address": "0x1", + "module": "fungible_asset", + "name": "Metadata" + }, + "typeStr": "0x1::fungible_asset::Metadata", + "data": "{\"decimals\":8,\"icon_uri\":\"https://static.mirage.money/assets/mUSD.svg\",\"name\":\"mirage dollar\",\"project_uri\":\"https://mirage.money\",\"symbol\":\"mUSD\"}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0xd4c938456b88884e2b8ca56c7003ccefb4acd0c4f2bca8342c8290b97dca085", + "stateKeyHash": "i4ld4Iwu48uNgMppDSMbHUZxaAhT3W1EFkOhqUZdnOg=", + "type": { + "address": "0x1", + "module": "object", + "name": "ObjectCore" + }, + "typeStr": "0x1::object::ObjectCore", + "data": "{\"allow_ungated_transfer\":true,\"guid_creation_num\":\"1125899906842625\",\"owner\":\"0x8933313486d5ee6b7102254d4e4e692e339127e8561d9c8a405b196a79193ca1\",\"transfer_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0xd4c938456b88884e2b8ca56c7003ccefb4acd0c4f2bca8342c8290b97dca085\",\"creation_num\":\"1125899906842624\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0xd4c938456b88884e2b8ca56c7003ccefb4acd0c4f2bca8342c8290b97dca085", + "stateKeyHash": "i4ld4Iwu48uNgMppDSMbHUZxaAhT3W1EFkOhqUZdnOg=", + "type": { + "address": "0x1", + "module": "primary_fungible_store", + "name": "DeriveRefPod" + }, + "typeStr": "0x1::primary_fungible_store::DeriveRefPod", + "data": "{\"metadata_derive_ref\":{\"self\":\"0xd4c938456b88884e2b8ca56c7003ccefb4acd0c4f2bca8342c8290b97dca085\"}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0xd4c938456b88884e2b8ca56c7003ccefb4acd0c4f2bca8342c8290b97dca085", + "stateKeyHash": "i4ld4Iwu48uNgMppDSMbHUZxaAhT3W1EFkOhqUZdnOg=", + "type": { + "address": "0x4", + "module": "property_map", + "name": "PropertyMap" + }, + "typeStr": "0x4::property_map::PropertyMap", + "data": "{\"inner\":{\"data\":[{\"key\":\"net_fees\",\"value\":{\"type\":5,\"value\":\"0xf7f348f84e0000000000000000000000\"}},{\"key\":\"net_burn\",\"value\":{\"type\":5,\"value\":\"0x96bf263e310000000000000000000000\"}}]}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0xd4c938456b88884e2b8ca56c7003ccefb4acd0c4f2bca8342c8290b97dca085", + "stateKeyHash": "i4ld4Iwu48uNgMppDSMbHUZxaAhT3W1EFkOhqUZdnOg=", + "type": { + "address": "0xce8b4fae12c51e5266106f8766e96ffa1c7b35d32cb4aa7678842550f99e69d8", + "module": "mirage", + "name": "MirageDebtStore" + }, + "typeStr": "0xce8b4fae12c51e5266106f8766e96ffa1c7b35d32cb4aa7678842550f99e69d8::mirage::MirageDebtStore", + "data": "{\"burn_ref\":{\"metadata\":{\"inner\":\"0xd4c938456b88884e2b8ca56c7003ccefb4acd0c4f2bca8342c8290b97dca085\"}},\"debt\":{\"base\":\"12970902871127\",\"elastic\":\"11613950859225\"},\"mint_ref\":{\"metadata\":{\"inner\":\"0xd4c938456b88884e2b8ca56c7003ccefb4acd0c4f2bca8342c8290b97dca085\"}},\"mutator_ref\":{\"self\":\"0xd4c938456b88884e2b8ca56c7003ccefb4acd0c4f2bca8342c8290b97dca085\"}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x1c91993f068030a2f34a85df0a1c8db073f429023ef5044b83376b9d0d1f2201", + "stateKeyHash": "AhWQpMJxVv9HCT7a6+qjslp3G58LY2DeTZiiFeFOCbY=", + "type": { + "address": "0x1", + "module": "object", + "name": "ObjectCore" + }, + "typeStr": "0x1::object::ObjectCore", + "data": "{\"allow_ungated_transfer\":true,\"guid_creation_num\":\"1125899906842625\",\"owner\":\"0x9af172d2c0a1cae6401a70fbaae1bd33dc2ebcb1a533ee24e5db561a348c3cb5\",\"transfer_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x1c91993f068030a2f34a85df0a1c8db073f429023ef5044b83376b9d0d1f2201\",\"creation_num\":\"1125899906842624\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x1c91993f068030a2f34a85df0a1c8db073f429023ef5044b83376b9d0d1f2201", + "stateKeyHash": "AhWQpMJxVv9HCT7a6+qjslp3G58LY2DeTZiiFeFOCbY=", + "type": { + "address": "0x9af172d2c0a1cae6401a70fbaae1bd33dc2ebcb1a533ee24e5db561a348c3cb5", + "module": "oracle", + "name": "Oracle" + }, + "typeStr": "0x9af172d2c0a1cae6401a70fbaae1bd33dc2ebcb1a533ee24e5db561a348c3cb5::oracle::Oracle", + "data": "{\"config\":{\"conf_threshold\":\"300\",\"ema_diff_threshold\":\"1000\",\"staleness_seconds_threshold\":\"20\"},\"extend_ref\":{\"self\":\"0x1c91993f068030a2f34a85df0a1c8db073f429023ef5044b83376b9d0d1f2201\"},\"is_stable\":false,\"last_parsed_rate\":\"309259326942\",\"last_rate_update\":\"1720638211\",\"name\":\"ETH\",\"price_feed_id\":\"0xca80ba6dc32e08d06f1aa886011eed1d77c77be9eb761cc10d72b7d0a2fd57a6\",\"price_multiplier\":\"1\"}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x312ec77102a96e7f93ec5761c08f00682844b299da987d333de4f0c8d6fa2c6e", + "stateKeyHash": "SkxnGD2XbSnhRFWb6NERTb1rY9wq/P3N4SCD/0UOFAg=", + "type": { + "address": "0x1", + "module": "object", + "name": "ObjectCore" + }, + "typeStr": "0x1::object::ObjectCore", + "data": "{\"allow_ungated_transfer\":false,\"guid_creation_num\":\"1125899906842626\",\"owner\":\"0xce8b4fae12c51e5266106f8766e96ffa1c7b35d32cb4aa7678842550f99e69d8\",\"transfer_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x312ec77102a96e7f93ec5761c08f00682844b299da987d333de4f0c8d6fa2c6e\",\"creation_num\":\"1125899906842624\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x312ec77102a96e7f93ec5761c08f00682844b299da987d333de4f0c8d6fa2c6e", + "stateKeyHash": "SkxnGD2XbSnhRFWb6NERTb1rY9wq/P3N4SCD/0UOFAg=", + "type": { + "address": "0x4", + "module": "collection", + "name": "Collection" + }, + "typeStr": "0x4::collection::Collection", + "data": "{\"creator\":\"0xce8b4fae12c51e5266106f8766e96ffa1c7b35d32cb4aa7678842550f99e69d8\",\"description\":\"mirage market\",\"mutation_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x312ec77102a96e7f93ec5761c08f00682844b299da987d333de4f0c8d6fa2c6e\",\"creation_num\":\"1125899906842625\"}}},\"name\":\"mirage market - ETHPERP/mUSD\",\"uri\":\"https://api.mirage.money/market_icons/@0x312ec77102a96e7f93ec5761c08f00682844b299da987d333de4f0c8d6fa2c6e\"}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x312ec77102a96e7f93ec5761c08f00682844b299da987d333de4f0c8d6fa2c6e", + "stateKeyHash": "SkxnGD2XbSnhRFWb6NERTb1rY9wq/P3N4SCD/0UOFAg=", + "type": { + "address": "0x4", + "module": "collection", + "name": "ConcurrentSupply" + }, + "typeStr": "0x4::collection::ConcurrentSupply", + "data": "{\"current_supply\":{\"max_value\":\"18446744073709551615\",\"value\":\"95\"},\"total_minted\":{\"max_value\":\"18446744073709551615\",\"value\":\"225\"}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x312ec77102a96e7f93ec5761c08f00682844b299da987d333de4f0c8d6fa2c6e", + "stateKeyHash": "SkxnGD2XbSnhRFWb6NERTb1rY9wq/P3N4SCD/0UOFAg=", + "type": { + "address": "0xce8b4fae12c51e5266106f8766e96ffa1c7b35d32cb4aa7678842550f99e69d8", + "module": "market", + "name": "Market" + }, + "typeStr": "0xce8b4fae12c51e5266106f8766e96ffa1c7b35d32cb4aa7678842550f99e69d8::market::Market", + "data": "{\"config\":{\"fees\":{\"liquidation_fee\":\"500\",\"max_maker_fee\":\"500\",\"max_taker_fee\":\"5000\",\"min_maker_fee\":\"100\",\"min_taker_fee\":\"500\",\"referrer_fee\":\"1000\"},\"funding\":{\"base_funding_rate\":\"10\",\"funding_interval\":\"3600\",\"max_funding_rate\":\"50000\",\"min_funding_rate\":\"50\"},\"maintenance_margin\":\"70\",\"max_leverage\":\"1000000\",\"max_oi\":\"1000000000000000\",\"max_oi_imbalance\":\"200000000000000\",\"max_order_size\":\"25000000000000\",\"min_order_size\":\"10000000\"},\"extend_ref\":{\"self\":\"0x312ec77102a96e7f93ec5761c08f00682844b299da987d333de4f0c8d6fa2c6e\"},\"is_long_close_only\":false,\"is_short_close_only\":false,\"last_funding_round\":\"1720638211\",\"long_funding_accumulated_per_unit\":{\"magnitude\":\"732077895376753\",\"negative\":false},\"long_oi\":\"29496175322\",\"margin_oracle\":{\"inner\":\"0x3c099311b8975753a026f54707d3e474a798ea7d9a656784585f7fc5581d203c\"},\"margin_token\":{\"inner\":\"0xd4c938456b88884e2b8ca56c7003ccefb4acd0c4f2bca8342c8290b97dca085\"},\"next_funding_rate\":{\"magnitude\":\"84\",\"negative\":false},\"perp_oracle\":{\"inner\":\"0x1c91993f068030a2f34a85df0a1c8db073f429023ef5044b83376b9d0d1f2201\"},\"perp_symbol\":\"ETHPERP\",\"short_funding_accumulated_per_unit\":{\"magnitude\":\"513385107575653\",\"negative\":true},\"short_oi\":\"2946952413\",\"total_long_funding_accumulated\":{\"magnitude\":\"74124639078\",\"negative\":false},\"total_long_margin\":\"2622882290805\",\"total_short_funding_accumulated\":{\"magnitude\":\"6376321805\",\"negative\":true},\"total_short_margin\":\"712967226877\"}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x33e123fc4b2658efa1192d9222981baa974c55c4a3d49178b279abbe3a9ab11b", + "stateKeyHash": "51gNMTZ9YlvvB6jqXoEKM/RM8MoaI0EHdCyRZ0kKTTY=", + "type": { + "address": "0x1", + "module": "object", + "name": "ObjectCore" + }, + "typeStr": "0x1::object::ObjectCore", + "data": "{\"allow_ungated_transfer\":true,\"guid_creation_num\":\"1125899906842625\",\"owner\":\"0xce8b4fae12c51e5266106f8766e96ffa1c7b35d32cb4aa7678842550f99e69d8\",\"transfer_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x33e123fc4b2658efa1192d9222981baa974c55c4a3d49178b279abbe3a9ab11b\",\"creation_num\":\"1125899906842624\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x47952259cb5b4ac64816d881a27155d1a3309f1041c8124b81b947e04e06d728", + "stateKeyHash": "xl9Sz65IvQVtocNezlaPX22/CHHY/+ZXk5jV6kzkp0Y=", + "type": { + "address": "0x1", + "module": "coin", + "name": "CoinStore", + "genericTypeParams": [ + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "aptos_coin", + "name": "AptosCoin" + } + } + ] + }, + "typeStr": "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>", + "data": "{\"coin\":{\"value\":\"214146650\"},\"deposit_events\":{\"counter\":\"215\",\"guid\":{\"id\":{\"addr\":\"0x47952259cb5b4ac64816d881a27155d1a3309f1041c8124b81b947e04e06d728\",\"creation_num\":\"2\"}}},\"frozen\":false,\"withdraw_events\":{\"counter\":\"223\",\"guid\":{\"id\":{\"addr\":\"0x47952259cb5b4ac64816d881a27155d1a3309f1041c8124b81b947e04e06d728\",\"creation_num\":\"3\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x47952259cb5b4ac64816d881a27155d1a3309f1041c8124b81b947e04e06d728", + "stateKeyHash": "brkJ2OhcHgt+22VC/Rn4WKK5xM54LiiUGIXthZST1dM=", + "type": { + "address": "0x1", + "module": "account", + "name": "Account" + }, + "typeStr": "0x1::account::Account", + "data": "{\"authentication_key\":\"0x47952259cb5b4ac64816d881a27155d1a3309f1041c8124b81b947e04e06d728\",\"coin_register_events\":{\"counter\":\"1\",\"guid\":{\"id\":{\"addr\":\"0x47952259cb5b4ac64816d881a27155d1a3309f1041c8124b81b947e04e06d728\",\"creation_num\":\"0\"}}},\"guid_creation_num\":\"4\",\"key_rotation_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x47952259cb5b4ac64816d881a27155d1a3309f1041c8124b81b947e04e06d728\",\"creation_num\":\"1\"}}},\"rotation_capability_offer\":{\"for\":{\"vec\":[]}},\"sequence_number\":\"404\",\"signer_capability_offer\":{\"for\":{\"vec\":[]}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x4a85ac0764bab4204eb64849756b8f11fee3b15caeacfddbd2210e52298bb1c4", + "stateKeyHash": "MT8M7FpakngfvoLVhQNLNJvUJknyUMDutvZf1aG6HyU=", + "type": { + "address": "0x1", + "module": "fungible_asset", + "name": "FungibleStore" + }, + "typeStr": "0x1::fungible_asset::FungibleStore", + "data": "{\"balance\":\"199827245910\",\"frozen\":false,\"metadata\":{\"inner\":\"0xd4c938456b88884e2b8ca56c7003ccefb4acd0c4f2bca8342c8290b97dca085\"}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x4a85ac0764bab4204eb64849756b8f11fee3b15caeacfddbd2210e52298bb1c4", + "stateKeyHash": "MT8M7FpakngfvoLVhQNLNJvUJknyUMDutvZf1aG6HyU=", + "type": { + "address": "0x1", + "module": "object", + "name": "ObjectCore" + }, + "typeStr": "0x1::object::ObjectCore", + "data": "{\"allow_ungated_transfer\":false,\"guid_creation_num\":\"1125899906842625\",\"owner\":\"0x47952259cb5b4ac64816d881a27155d1a3309f1041c8124b81b947e04e06d728\",\"transfer_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x4a85ac0764bab4204eb64849756b8f11fee3b15caeacfddbd2210e52298bb1c4\",\"creation_num\":\"1125899906842624\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x6df76d83819071a5e046eb5a1933dbc3802973f7499bef7d62cae48725ddf98b", + "stateKeyHash": "ju669zhj2TeSQTwoIztlQRNxCfVR8pKCSfxvcIzxJh0=", + "type": { + "address": "0x1", + "module": "fungible_asset", + "name": "FungibleStore" + }, + "typeStr": "0x1::fungible_asset::FungibleStore", + "data": "{\"balance\":\"32703929090\",\"frozen\":false,\"metadata\":{\"inner\":\"0xd4c938456b88884e2b8ca56c7003ccefb4acd0c4f2bca8342c8290b97dca085\"}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x6df76d83819071a5e046eb5a1933dbc3802973f7499bef7d62cae48725ddf98b", + "stateKeyHash": "ju669zhj2TeSQTwoIztlQRNxCfVR8pKCSfxvcIzxJh0=", + "type": { + "address": "0x1", + "module": "object", + "name": "ObjectCore" + }, + "typeStr": "0x1::object::ObjectCore", + "data": "{\"allow_ungated_transfer\":false,\"guid_creation_num\":\"1125899906842625\",\"owner\":\"0xc180ff5ec54082970cc70f6fa91033ede1489e534d723f24ffd2bb5b56432478\",\"transfer_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x6df76d83819071a5e046eb5a1933dbc3802973f7499bef7d62cae48725ddf98b\",\"creation_num\":\"1125899906842624\"}}}}" + } + }, + { + "type": "TYPE_DELETE_RESOURCE", + "deleteResource": { + "address": "0x7bb705733c1346e997771089d52a2a1797db6b8d3c47774ad4236f3dfbc8b258", + "stateKeyHash": "hGdrjp//XREzdwyXZRBeIJ4NJFvBjA4MLl2nhd9ugxs=", + "type": { + "address": "0x1", + "module": "object", + "name": "ObjectGroup" + }, + "typeStr": "0x1::object::ObjectGroup" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x7e783b349d3e89cf5931af376ebeadbfab855b3fa239b7ada8f5a92fbea6b387", + "stateKeyHash": "gfbqu5uDcMctWDdOtWpvPJJZKe5U+Vqt9b3BH6z1SA4=", + "type": { + "address": "0x1", + "module": "coin", + "name": "CoinStore", + "genericTypeParams": [ + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "aptos_coin", + "name": "AptosCoin" + } + } + ] + }, + "typeStr": "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>", + "data": "{\"coin\":{\"value\":\"2982812\"},\"deposit_events\":{\"counter\":\"663454\",\"guid\":{\"id\":{\"addr\":\"0x7e783b349d3e89cf5931af376ebeadbfab855b3fa239b7ada8f5a92fbea6b387\",\"creation_num\":\"3\"}}},\"frozen\":false,\"withdraw_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x7e783b349d3e89cf5931af376ebeadbfab855b3fa239b7ada8f5a92fbea6b387\",\"creation_num\":\"4\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x7e783b349d3e89cf5931af376ebeadbfab855b3fa239b7ada8f5a92fbea6b387", + "stateKeyHash": "G1peUN8GWAl/zIVbxLnECqAvC/E+VrWPgpb5vJ4RHas=", + "type": { + "address": "0x7e783b349d3e89cf5931af376ebeadbfab855b3fa239b7ada8f5a92fbea6b387", + "module": "event", + "name": "PriceFeedUpdateHandle" + }, + "typeStr": "0x7e783b349d3e89cf5931af376ebeadbfab855b3fa239b7ada8f5a92fbea6b387::event::PriceFeedUpdateHandle", + "data": "{\"event\":{\"counter\":\"2087596\",\"guid\":{\"id\":{\"addr\":\"0x7e783b349d3e89cf5931af376ebeadbfab855b3fa239b7ada8f5a92fbea6b387\",\"creation_num\":\"2\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x9af172d2c0a1cae6401a70fbaae1bd33dc2ebcb1a533ee24e5db561a348c3cb5", + "stateKeyHash": "E26BErT/RQQfbWRyD2vQsMCTd8ir+0PQ/m1jA2LiXtY=", + "type": { + "address": "0x9af172d2c0a1cae6401a70fbaae1bd33dc2ebcb1a533ee24e5db561a348c3cb5", + "module": "oracle", + "name": "OracleGlobalConfig" + }, + "typeStr": "0x9af172d2c0a1cae6401a70fbaae1bd33dc2ebcb1a533ee24e5db561a348c3cb5::oracle::OracleGlobalConfig", + "data": "{\"all_oracles\":{\"big_vec\":{\"vec\":[{\"bucket_size\":\"32\",\"buckets\":{\"inner\":{\"handle\":\"0x3c9eb231bdff90563b8009c93884a9f7ab30a51d9483bc7ab837f6e196d0a3b6\"},\"length\":\"1\"},\"end_index\":\"17\"}]},\"bucket_size\":{\"vec\":[]},\"inline_capacity\":{\"vec\":[]},\"inline_vec\":[{\"inner\":\"0x3c099311b8975753a026f54707d3e474a798ea7d9a656784585f7fc5581d203c\"},{\"inner\":\"0xbbd247e39bb6dcfbb089121496a11272e4ce89aaa42a55331486a9af83776445\"},{\"inner\":\"0x9f408861f96e222643a7e02556b29d08072e02595309fced9a5f675094e16763\"},{\"inner\":\"0x1bbafbf45630776bb19b00ea6c3a3fdbcf0cdd37f4dcc2b4c77ab847f45095df\"}]},\"pyth_fee_store\":{\"value\":\"59992457\"}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0xc180ff5ec54082970cc70f6fa91033ede1489e534d723f24ffd2bb5b56432478", + "stateKeyHash": "wZ8xX7/x0czeDitoY0vRpXo+SfM5jg8nj9bv6EViR7c=", + "type": { + "address": "0x1", + "module": "coin", + "name": "CoinStore", + "genericTypeParams": [ + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "aptos_coin", + "name": "AptosCoin" + } + } + ] + }, + "typeStr": "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>", + "data": "{\"coin\":{\"value\":\"2814041\"},\"deposit_events\":{\"counter\":\"14\",\"guid\":{\"id\":{\"addr\":\"0xc180ff5ec54082970cc70f6fa91033ede1489e534d723f24ffd2bb5b56432478\",\"creation_num\":\"2\"}}},\"frozen\":false,\"withdraw_events\":{\"counter\":\"3\",\"guid\":{\"id\":{\"addr\":\"0xc180ff5ec54082970cc70f6fa91033ede1489e534d723f24ffd2bb5b56432478\",\"creation_num\":\"3\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0xec0c7893e7f34e6bf979bd776c84ae16126bf0916700bee0032cc5b286ce83bf", + "stateKeyHash": "JIrLofpqW18Zwa1GlY5N8ScinYEs5+cBDc3kMT7ufPk=", + "type": { + "address": "0x1", + "module": "fungible_asset", + "name": "FungibleStore" + }, + "typeStr": "0x1::fungible_asset::FungibleStore", + "data": "{\"balance\":\"127676855393\",\"frozen\":false,\"metadata\":{\"inner\":\"0xd4c938456b88884e2b8ca56c7003ccefb4acd0c4f2bca8342c8290b97dca085\"}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0xec0c7893e7f34e6bf979bd776c84ae16126bf0916700bee0032cc5b286ce83bf", + "stateKeyHash": "JIrLofpqW18Zwa1GlY5N8ScinYEs5+cBDc3kMT7ufPk=", + "type": { + "address": "0x1", + "module": "object", + "name": "ObjectCore" + }, + "typeStr": "0x1::object::ObjectCore", + "data": "{\"allow_ungated_transfer\":false,\"guid_creation_num\":\"1125899906842625\",\"owner\":\"0x844586c7d97ecc0fe6c0e658862580f5da4c1c528591a059194d5d57b35c3e70\",\"transfer_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0xec0c7893e7f34e6bf979bd776c84ae16126bf0916700bee0032cc5b286ce83bf\",\"creation_num\":\"1125899906842624\"}}}}" + } + }, + { + "type": "TYPE_WRITE_TABLE_ITEM", + "writeTableItem": { + "stateKeyHash": "bkso1A+YoQamUWNTCSTA3LQME0nTqpFdEItNbPwd2xk=", + "handle": "0x1b854694ae746cdbd8d44186ca4929b2b337df21d1c74633be19b2710552fdca", + "key": "0x0619dc29a0aac8fa146714058e8dd6d2d0f3bdf5f6331907bf91f3acd81e6935", + "data": { + "key": "\"0x619dc29a0aac8fa146714058e8dd6d2d0f3bdf5f6331907bf91f3acd81e6935\"", + "keyType": "address", + "value": "\"29158142733491475922\"", + "valueType": "u128" + } + } + }, + { + "type": "TYPE_WRITE_TABLE_ITEM", + "writeTableItem": { + "stateKeyHash": "CYWbvQDejpBvd0AQOTYO1Izld5Wfn8tiO0gFKT18oak=", + "handle": "0xf8bdbac6b50639c2a2f709fe84e3ff81b2ec7a7224d2e446b43f48b8ae67e7b3", + "key": "0x20ca80ba6dc32e08d06f1aa886011eed1d77c77be9eb761cc10d72b7d0a2fd57a6", + "data": { + "key": "{\"bytes\":\"0xca80ba6dc32e08d06f1aa886011eed1d77c77be9eb761cc10d72b7d0a2fd57a6\"}", + "keyType": "0x7e783b349d3e89cf5931af376ebeadbfab855b3fa239b7ada8f5a92fbea6b387::price_identifier::PriceIdentifier", + "value": "{\"arrival_time\":\"1720638211\",\"attestation_time\":\"1720638211\",\"price_feed\":{\"ema_price\":{\"conf\":\"100834285\",\"expo\":{\"magnitude\":\"8\",\"negative\":true},\"price\":{\"magnitude\":\"310792050000\",\"negative\":false},\"timestamp\":\"1720638207\"},\"price\":{\"conf\":\"85673056\",\"expo\":{\"magnitude\":\"8\",\"negative\":true},\"price\":{\"magnitude\":\"309259326942\",\"negative\":false},\"timestamp\":\"1720638207\"},\"price_identifier\":{\"bytes\":\"0xca80ba6dc32e08d06f1aa886011eed1d77c77be9eb761cc10d72b7d0a2fd57a6\"}}}", + "valueType": "0x7e783b349d3e89cf5931af376ebeadbfab855b3fa239b7ada8f5a92fbea6b387::price_info::PriceInfo" + } + } + } + ] + }, + "epoch": "16203", + "blockHeight": "310645633", + "type": "TRANSACTION_TYPE_USER", + "sizeInfo": { + "transactionBytes": 788, + "eventSizeInfo": [ + { + "typeTagBytes": 56, + "totalBytes": 213 + }, + { + "typeTagBytes": 52, + "totalBytes": 108 + }, + { + "typeTagBytes": 52, + "totalBytes": 108 + }, + { + "typeTagBytes": 57, + "totalBytes": 105 + }, + { + "typeTagBytes": 58, + "totalBytes": 98 + }, + { + "typeTagBytes": 57, + "totalBytes": 105 + }, + { + "typeTagBytes": 57, + "totalBytes": 105 + }, + { + "typeTagBytes": 60, + "totalBytes": 135 + }, + { + "typeTagBytes": 57, + "totalBytes": 97 + }, + { + "typeTagBytes": 61, + "totalBytes": 109 + }, + { + "typeTagBytes": 64, + "totalBytes": 186 + }, + { + "typeTagBytes": 57, + "totalBytes": 97 + }, + { + "typeTagBytes": 52, + "totalBytes": 108 + }, + { + "typeTagBytes": 50, + "totalBytes": 154 + }, + { + "typeTagBytes": 57, + "totalBytes": 97 + }, + { + "typeTagBytes": 63, + "totalBytes": 103 + } + ], + "writeOpSizeInfo": [ + { + "keyBytes": 87, + "valueBytes": 768 + }, + { + "keyBytes": 87, + "valueBytes": 308 + }, + { + "keyBytes": 87, + "valueBytes": 954 + }, + { + "keyBytes": 87, + "valueBytes": 142 + }, + { + "keyBytes": 138, + "valueBytes": 105 + }, + { + "keyBytes": 84, + "valueBytes": 147 + }, + { + "keyBytes": 87, + "valueBytes": 246 + }, + { + "keyBytes": 87, + "valueBytes": 246 + }, + { + "keyBytes": 87 + }, + { + "keyBytes": 138, + "valueBytes": 105 + }, + { + "keyBytes": 96, + "valueBytes": 48 + }, + { + "keyBytes": 94, + "valueBytes": 196 + }, + { + "keyBytes": 138, + "valueBytes": 105 + }, + { + "keyBytes": 87, + "valueBytes": 246 + }, + { + "keyBytes": 66, + "valueBytes": 16 + }, + { + "keyBytes": 67, + "valueBytes": 117 + } + ] + }, + "user": { + "request": { + "sender": "0x47952259cb5b4ac64816d881a27155d1a3309f1041c8124b81b947e04e06d728", + "sequenceNumber": "403", + "maxGasAmount": "200000", + "gasUnitPrice": "100", + "expirationTimestampSecs": { + "seconds": "1720638231" + }, + "payload": { + "type": "TYPE_ENTRY_FUNCTION_PAYLOAD", + "entryFunctionPayload": { + "function": { + "module": { + "address": "0x89495b66933cc2826d3feb1b7d5dc330b67b031acd160d39206d0e89d35fcb77", + "name": "market_scripts" + }, + "name": "liquidate_position_entry" + }, + "typeArguments": [ + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0xce8b4fae12c51e5266106f8766e96ffa1c7b35d32cb4aa7678842550f99e69d8", + "module": "market", + "name": "Position" + } + } + ], + "arguments": [ + "{\"inner\":\"0x7bb705733c1346e997771089d52a2a1797db6b8d3c47774ad4236f3dfbc8b258\"}", + "\"0x504e41550100000000a001000000000100c8dde09f631ca11c3e2fb964528b3b11c35d2e4fd3bf7174303e26b0a11c6c66008276a3728872b1c539414cb73f10e4304549e6b001b7ae7eb9acd8cefeb06c00668edb0000000000001ae101faedac5851e32b9b23b5f9411a8c2bac4aae3ed4dd7b811dd1a72ea4aa7100000000047c507301415557560000000000090faae8000027104813be3ff9f8809c9f1119c22fb0693a0521784e01005500ca80ba6dc32e08d06f1aa886011eed1d77c77be9eb761cc10d72b7d0a2fd57a600000048014ad5de00000000051b4460fffffff800000000668edaff00000000668edaff000000485ca655500000000006029bed0a77af5f8c4be1f4fbd07e7225a4121b33469356f00b90622830c2c0617603b2b058e64eaebceeb20ece9c5dad9fa23fc1486832702bc872282b9830121e51bfda913af45c4f80c4915b1ca34f22f22d6e37c2c19b39c8b4203b86b843188bc01fd1af6075c114afac347a57f06b3ab662d1b105ed08a92bc2d13e6a37c615760d133869db933a51e51c944dfdceff75e48f9bd6f88ec3674742b7b56f7908c400933e861ac9f2105cce5e740f286da3d189a7faeb848465ee7eb62101264bf831eb1c1d01a232c460\"", + "\"0x\"" + ], + "entryFunctionIdStr": "0x89495b66933cc2826d3feb1b7d5dc330b67b031acd160d39206d0e89d35fcb77::market_scripts::liquidate_position_entry" + } + }, + "signature": { + "type": "TYPE_ED25519", + "ed25519": { + "publicKey": "5HsFtz/t9/nua9LeVy3V9fpua0GkiFkeq4p8DHZc42E=", + "signature": "PaTZrMM7UA8y7fhdhmC/cZULEuIFOliLP1lp4URM0F0S6V8gU20frBmKtG7TPkYrrtnzh8WqCyrrsBeSoRQ0DQ==" + } + } + }, + "events": [ + { + "key": { + "creationNumber": "2", + "accountAddress": "0x7e783b349d3e89cf5931af376ebeadbfab855b3fa239b7ada8f5a92fbea6b387" + }, + "sequenceNumber": "2087595", + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x7e783b349d3e89cf5931af376ebeadbfab855b3fa239b7ada8f5a92fbea6b387", + "module": "event", + "name": "PriceFeedUpdate" + } + }, + "typeStr": "0x7e783b349d3e89cf5931af376ebeadbfab855b3fa239b7ada8f5a92fbea6b387::event::PriceFeedUpdate", + "data": "{\"price_feed\":{\"ema_price\":{\"conf\":\"100834285\",\"expo\":{\"magnitude\":\"8\",\"negative\":true},\"price\":{\"magnitude\":\"310792050000\",\"negative\":false},\"timestamp\":\"1720638207\"},\"price\":{\"conf\":\"85673056\",\"expo\":{\"magnitude\":\"8\",\"negative\":true},\"price\":{\"magnitude\":\"309259326942\",\"negative\":false},\"timestamp\":\"1720638207\"},\"price_identifier\":{\"bytes\":\"0xca80ba6dc32e08d06f1aa886011eed1d77c77be9eb761cc10d72b7d0a2fd57a6\"}},\"timestamp\":\"1720638211722842\"}" + }, + { + "key": { + "creationNumber": "3", + "accountAddress": "0x7e783b349d3e89cf5931af376ebeadbfab855b3fa239b7ada8f5a92fbea6b387" + }, + "sequenceNumber": "663452", + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "coin", + "name": "DepositEvent" + } + }, + "typeStr": "0x1::coin::DepositEvent", + "data": "{\"amount\":\"1\"}" + }, + { + "key": { + "creationNumber": "3", + "accountAddress": "0x7e783b349d3e89cf5931af376ebeadbfab855b3fa239b7ada8f5a92fbea6b387" + }, + "sequenceNumber": "663453", + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "coin", + "name": "DepositEvent" + } + }, + "typeStr": "0x1::coin::DepositEvent", + "data": "{\"amount\":\"1\"}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x9af172d2c0a1cae6401a70fbaae1bd33dc2ebcb1a533ee24e5db561a348c3cb5", + "module": "oracle", + "name": "RateUpdateEvent" + } + }, + "typeStr": "0x9af172d2c0a1cae6401a70fbaae1bd33dc2ebcb1a533ee24e5db561a348c3cb5::oracle::RateUpdateEvent", + "data": "{\"oracle\":{\"inner\":\"0x1c91993f068030a2f34a85df0a1c8db073f429023ef5044b83376b9d0d1f2201\"},\"rate\":\"309259326942\",\"time\":\"1720638211\"}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "fungible_asset", + "name": "Withdraw" + } + }, + "typeStr": "0x1::fungible_asset::Withdraw", + "data": "{\"amount\":\"40000000000\",\"store\":\"0x33e123fc4b2658efa1192d9222981baa974c55c4a3d49178b279abbe3a9ab11b\"}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x9af172d2c0a1cae6401a70fbaae1bd33dc2ebcb1a533ee24e5db561a348c3cb5", + "module": "oracle", + "name": "RateUpdateEvent" + } + }, + "typeStr": "0x9af172d2c0a1cae6401a70fbaae1bd33dc2ebcb1a533ee24e5db561a348c3cb5::oracle::RateUpdateEvent", + "data": "{\"oracle\":{\"inner\":\"0x1c91993f068030a2f34a85df0a1c8db073f429023ef5044b83376b9d0d1f2201\"},\"rate\":\"309259326942\",\"time\":\"1720638211\"}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x9af172d2c0a1cae6401a70fbaae1bd33dc2ebcb1a533ee24e5db561a348c3cb5", + "module": "oracle", + "name": "RateUpdateEvent" + } + }, + "typeStr": "0x9af172d2c0a1cae6401a70fbaae1bd33dc2ebcb1a533ee24e5db561a348c3cb5::oracle::RateUpdateEvent", + "data": "{\"oracle\":{\"inner\":\"0x1c91993f068030a2f34a85df0a1c8db073f429023ef5044b83376b9d0d1f2201\"},\"rate\":\"309259326942\",\"time\":\"1720638211\"}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0xce8b4fae12c51e5266106f8766e96ffa1c7b35d32cb4aa7678842550f99e69d8", + "module": "market", + "name": "UpdateFundingEvent" + } + }, + "typeStr": "0xce8b4fae12c51e5266106f8766e96ffa1c7b35d32cb4aa7678842550f99e69d8::market::UpdateFundingEvent", + "data": "{\"long_funding\":{\"magnitude\":\"29998154713374\",\"negative\":false},\"market\":{\"inner\":\"0x312ec77102a96e7f93ec5761c08f00682844b299da987d333de4f0c8d6fa2c6e\"},\"next_funding_rate\":{\"magnitude\":\"84\",\"negative\":false},\"short_funding\":{\"magnitude\":\"23812968174534\",\"negative\":true}}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "fungible_asset", + "name": "Deposit" + } + }, + "typeStr": "0x1::fungible_asset::Deposit", + "data": "{\"amount\":\"240748453\",\"store\":\"0xec0c7893e7f34e6bf979bd776c84ae16126bf0916700bee0032cc5b286ce83bf\"}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0xce8b4fae12c51e5266106f8766e96ffa1c7b35d32cb4aa7678842550f99e69d8", + "module": "fee_manager", + "name": "MergeFeesEvent" + } + }, + "typeStr": "0xce8b4fae12c51e5266106f8766e96ffa1c7b35d32cb4aa7678842550f99e69d8::fee_manager::MergeFeesEvent", + "data": "{\"burn_amount\":\"561746391\",\"fee_asset\":{\"inner\":\"0xd4c938456b88884e2b8ca56c7003ccefb4acd0c4f2bca8342c8290b97dca085\"},\"protocol_fee_amount\":\"240748453\"}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0xce8b4fae12c51e5266106f8766e96ffa1c7b35d32cb4aa7678842550f99e69d8", + "module": "market", + "name": "LiquidatePositionEvent" + } + }, + "typeStr": "0xce8b4fae12c51e5266106f8766e96ffa1c7b35d32cb4aa7678842550f99e69d8::market::LiquidatePositionEvent", + "data": "{\"closing_fee\":\"802494844\",\"closing_price\":\"309259326942\",\"is_long\":false,\"liquidation_fee\":\"2000000000\",\"market\":{\"inner\":\"0x312ec77102a96e7f93ec5761c08f00682844b299da987d333de4f0c8d6fa2c6e\"},\"position\":{\"inner\":\"0x7bb705733c1346e997771089d52a2a1797db6b8d3c47774ad4236f3dfbc8b258\"},\"position_size\":\"1067857177\",\"protocol_fee\":\"16823268182\",\"remaining_maintenance_margin\":\"20374236974\",\"winnings\":{\"magnitude\":\"19625763026\",\"negative\":true}}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "fungible_asset", + "name": "Deposit" + } + }, + "typeStr": "0x1::fungible_asset::Deposit", + "data": "{\"amount\":\"20374236974\",\"store\":\"0x6df76d83819071a5e046eb5a1933dbc3802973f7499bef7d62cae48725ddf98b\"}" + }, + { + "key": { + "creationNumber": "2", + "accountAddress": "0xc180ff5ec54082970cc70f6fa91033ede1489e534d723f24ffd2bb5b56432478" + }, + "sequenceNumber": "13", + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "coin", + "name": "DepositEvent" + } + }, + "typeStr": "0x1::coin::DepositEvent", + "data": "{\"amount\":\"0\"}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x4", + "module": "collection", + "name": "Burn" + } + }, + "typeStr": "0x4::collection::Burn", + "data": "{\"collection\":\"0x312ec77102a96e7f93ec5761c08f00682844b299da987d333de4f0c8d6fa2c6e\",\"index\":\"225\",\"previous_owner\":\"0xc180ff5ec54082970cc70f6fa91033ede1489e534d723f24ffd2bb5b56432478\",\"token\":\"0x7bb705733c1346e997771089d52a2a1797db6b8d3c47774ad4236f3dfbc8b258\"}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "fungible_asset", + "name": "Deposit" + } + }, + "typeStr": "0x1::fungible_asset::Deposit", + "data": "{\"amount\":\"2000000000\",\"store\":\"0x4a85ac0764bab4204eb64849756b8f11fee3b15caeacfddbd2210e52298bb1c4\"}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "transaction_fee", + "name": "FeeStatement" + } + }, + "typeStr": "0x1::transaction_fee::FeeStatement", + "data": "{\"execution_gas_units\":\"190\",\"io_gas_units\":\"38\",\"storage_fee_octas\":\"0\",\"storage_fee_refund_octas\":\"97640\",\"total_charge_gas_units\":\"228\"}" + } + ] + } +} \ No newline at end of file diff --git a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/imported_testnet_txns/646928741_no_events.json b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/imported_testnet_txns/646928741_no_events.json new file mode 100644 index 0000000000000..6c411d2b460a6 --- /dev/null +++ b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/imported_testnet_txns/646928741_no_events.json @@ -0,0 +1,387 @@ +{ + "timestamp": { + "seconds": "1692824738", + "nanos": 380686000 + }, + "version": "646928741", + "info": { + "hash": "JrSKHFiycKHmMpoOvdbBcNNJtQ5M8cFVxmHjV2JQsCo=", + "stateChangeHash": "lTHruG1Pq2gaV0cY6keDZt3uQv9rqNaO6oBcVUSjRyg=", + "eventRootHash": "QUNDVU1VTEFUT1JfUExBQ0VIT0xERVJfSEFTSAAAAAA=", + "gasUsed": "2238", + "success": true, + "vmStatus": "Executed successfully", + "accumulatorRootHash": "/O1IzM/4boWIK9fsY9xdMkfSjFcU49q9QwpDXaMVe0I=", + "changes": [ + { + "type": "TYPE_WRITE_MODULE", + "writeModule": { + "address": "0x40b880d668a9d68d7d521bec03b92857363339053c28459fdfd8d3d905ff0379", + "stateKeyHash": "9kfGBX8r8HEerTgEc7Yx9zObDhjdzpMQQcTdwo+eBLk=", + "data": { + "bytecode": "oRzrCwYAAAAMAQAQAhAwA0CmAQTmARYF/AHeAgfaBLAFCIoKQAbKCnUQvwuhAQrgDAwM7AytBA2ZEQYAAAEBAQIBAwEEAQUBBgEHAAgIAAIKAAADDQcBAAECDggAAhYGAAIYBgACGgYAAhsIAAMnAgAEKQcBAAAHKwcAAAkAAQAACwIBAAAMAwEAAA8BBAAAEAUBAAARAAEAABIGAQAAEwMBAAAUBwgABhwFCgADHQwNAQgBHg4OAAMfDwoBCAUgEBEBCAIhEwEBCAUiEBEBCAIjFQEBCAIkFwEBCAMlGAoAAyYKGQEIAygbHAAEKgEeAQAHLB8gAAUtIQEAAi4iIwACLyIkAAIwIiUAAzEiJgACESgIAAIyKgEBCAIzLAgBCAoLDAsNCw4SDwsQEhESEwsVHR0SHhIDBgwFAwADBgwFCAECBgwFAQsCAQgDAQYMBAYMBQUDAwYMAwUBCAEFCwIBCAMLAgEIAwYIBgsCAQgHBgwBBQEIAwILAgEJAAUBAQEDAQYLAgEJAAIFCwIBCQABCwIBCAcBCAcDBggGCwIBCQADBQsCAQgDCwIBCAMGDAsCAQgHBggFAwYIBQsCAQkACAEFCwIBCAMLAgEIAwYMBggFCwIBCAcDBggFCwIBCQABAgYFCgIBCwIBCQAGCAgIBgYICAwIBAgFAgYMCgIBCAgBBAELCQEJAAEKAgEICgcGCAgLCQEECAoICgIICggKAQYICAEIBAEIBgEIBQEMBgsCAQgDCwIBCAMIAQYIAAYMCwIBCAcCBggEAwYLAgEIAwsCAQgDCwIBCAcGDAsCAQgHBggFBAYIBQsCAQkACwIBCQADBQsCAQgDCwIBCAMLAgEIBwYMBggFAwYIBQsCAQkAAwdmYV9jb2luBWVycm9yDmZ1bmdpYmxlX2Fzc2V0Bm9iamVjdAZvcHRpb24WcHJpbWFyeV9mdW5naWJsZV9zdG9yZQZzaWduZXIGc3RyaW5nFE1hbmFnZWRGdW5naWJsZUFzc2V0BGJ1cm4NRnVuZ2libGVBc3NldAdkZXBvc2l0DmZyZWV6ZV9hY2NvdW50Bk9iamVjdAhNZXRhZGF0YQxnZXRfbWV0YWRhdGELaW5pdF9tb2R1bGUEbWludAh0cmFuc2ZlchB1bmZyZWV6ZV9hY2NvdW50CHdpdGhkcmF3CG1pbnRfcmVmB01pbnRSZWYMdHJhbnNmZXJfcmVmC1RyYW5zZmVyUmVmCGJ1cm5fcmVmB0J1cm5SZWYNRnVuZ2libGVTdG9yZQphZGRyZXNzX29mCGlzX293bmVyEXBlcm1pc3Npb25fZGVuaWVkDm9iamVjdF9hZGRyZXNzDXByaW1hcnlfc3RvcmUJYnVybl9mcm9tG2Vuc3VyZV9wcmltYXJ5X3N0b3JlX2V4aXN0cxBkZXBvc2l0X3dpdGhfcmVmD3NldF9mcm96ZW5fZmxhZxVjcmVhdGVfb2JqZWN0X2FkZHJlc3MRYWRkcmVzc190b19vYmplY3QOQ29uc3RydWN0b3JSZWYTY3JlYXRlX25hbWVkX29iamVjdAZPcHRpb24Ebm9uZQZTdHJpbmcEdXRmOCtjcmVhdGVfcHJpbWFyeV9zdG9yZV9lbmFibGVkX2Z1bmdpYmxlX2Fzc2V0EWdlbmVyYXRlX21pbnRfcmVmEWdlbmVyYXRlX2J1cm5fcmVmFWdlbmVyYXRlX3RyYW5zZmVyX3JlZg9nZW5lcmF0ZV9zaWduZXIRdHJhbnNmZXJfd2l0aF9yZWYRd2l0aGRyYXdfd2l0aF9yZWZAuIDWaKnWjX1SG+wDuShXNjM5BTwoRZ/f2NPZBf8DeQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCgIDAkZBAwgBAAAAAAAAAAUgQLiA1mip1o19UhvsA7koVzYzOQU8KEWf39jT2QX/A3kKAggHRkEgQ29pbgoCHx5odHRwOi8vZXhhbXBsZS5jb20vZmF2aWNvbi5pY28KAhMSaHR0cDovL2V4YW1wbGUuY29tEmFwdG9zOjptZXRhZGF0YV92MYwBAQEAAAAAAAAACkVOT1RfT1dORVI0T25seSBmdW5naWJsZSBhc3NldCBtZXRhZGF0YSBvd25lciBjYW4gbWFrZSBjaGFuZ2VzLgEUTWFuYWdlZEZ1bmdpYmxlQXNzZXQBAwEYMHgxOjpvYmplY3Q6Ok9iamVjdEdyb3VwAQxnZXRfbWV0YWRhdGEBAQAAAgMVCAQXCAUZCAYAAQQBAAkdEQMMAwsACgMMBAwHCgQLBxEJOAAEDAUPBwERCycOBDgBKwAQAAwFCwELAzgCDAYLBQsGCwI4AwIBAQABABQdEQMMAwsACgMMBAwFCgQLBREJOAAEDAUPBwERCycOBDgBKwAQAQwHCwELAzgEDAYLBwsGCwI4BQICAQQBABYdEQMMAgsACgIMAwwECgMLBBEJOAAEDAUPBwERCycOAzgBKwAQAQwFCwELAjgEDAYLBQsGCDgGAgMBAAAKBwcCDAAOAAcAERI4BwIEAAAAGiULAAcAERQMAQ4BDAMKAzgIBwMRFgcAERYxCAcEERYHBREWERcKAxEYDAUKAxEZDAIKAxEaDAYLAxEbDAQOBAsFCwYLAhIALQACBQEEAQAnIhEDDAMLAAoDDAQMBwoECwcRCTgABAwFDwcBEQsnDgQ4ASsADAYLAQsDOAQMCAoGEAILAhEcDAULBhABCwgLBTgFAgYBBAEAKSIRAwwECwAKBAwFDAcKBQsHEQk4AAQMBQ8HARELJw4FOAErABABDAkLAQoEOAIMBgsCCwQ4BAwICwkLBgsICwM4CQIHAQQBABYdEQMMAgsACgIMAwwECgMLBBEJOAAEDAUPBwERCycOAzgBKwAQAQwFCwELAjgEDAYLBQsGCTgGAggBAAEAKx0RAwwDCwAKAwwEDAYKBAsGEQk4AAQMBQ8HARELJw4EOAErABABDAcLAgsDOAIMBQsHCwULATgKAgACAAEAAAA=", + "abi": { + "address": "0x40b880d668a9d68d7d521bec03b92857363339053c28459fdfd8d3d905ff0379", + "name": "fa_coin", + "exposedFunctions": [ + { + "name": "burn", + "visibility": "VISIBILITY_PUBLIC", + "isEntry": true, + "params": [ + { + "type": "MOVE_TYPES_REFERENCE", + "reference": { + "to": { + "type": "MOVE_TYPES_SIGNER" + } + } + }, + { + "type": "MOVE_TYPES_ADDRESS" + }, + { + "type": "MOVE_TYPES_U64" + } + ] + }, + { + "name": "deposit", + "visibility": "VISIBILITY_PUBLIC", + "params": [ + { + "type": "MOVE_TYPES_REFERENCE", + "reference": { + "to": { + "type": "MOVE_TYPES_SIGNER" + } + } + }, + { + "type": "MOVE_TYPES_ADDRESS" + }, + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "fungible_asset", + "name": "FungibleAsset" + } + } + ] + }, + { + "name": "freeze_account", + "visibility": "VISIBILITY_PUBLIC", + "isEntry": true, + "params": [ + { + "type": "MOVE_TYPES_REFERENCE", + "reference": { + "to": { + "type": "MOVE_TYPES_SIGNER" + } + } + }, + { + "type": "MOVE_TYPES_ADDRESS" + } + ] + }, + { + "name": "get_metadata", + "visibility": "VISIBILITY_PUBLIC", + "return": [ + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "object", + "name": "Object", + "genericTypeParams": [ + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "fungible_asset", + "name": "Metadata" + } + } + ] + } + } + ] + }, + { + "name": "mint", + "visibility": "VISIBILITY_PUBLIC", + "isEntry": true, + "params": [ + { + "type": "MOVE_TYPES_REFERENCE", + "reference": { + "to": { + "type": "MOVE_TYPES_SIGNER" + } + } + }, + { + "type": "MOVE_TYPES_ADDRESS" + }, + { + "type": "MOVE_TYPES_U64" + } + ] + }, + { + "name": "transfer", + "visibility": "VISIBILITY_PUBLIC", + "isEntry": true, + "params": [ + { + "type": "MOVE_TYPES_REFERENCE", + "reference": { + "to": { + "type": "MOVE_TYPES_SIGNER" + } + } + }, + { + "type": "MOVE_TYPES_ADDRESS" + }, + { + "type": "MOVE_TYPES_ADDRESS" + }, + { + "type": "MOVE_TYPES_U64" + } + ] + }, + { + "name": "unfreeze_account", + "visibility": "VISIBILITY_PUBLIC", + "isEntry": true, + "params": [ + { + "type": "MOVE_TYPES_REFERENCE", + "reference": { + "to": { + "type": "MOVE_TYPES_SIGNER" + } + } + }, + { + "type": "MOVE_TYPES_ADDRESS" + } + ] + }, + { + "name": "withdraw", + "visibility": "VISIBILITY_PUBLIC", + "params": [ + { + "type": "MOVE_TYPES_REFERENCE", + "reference": { + "to": { + "type": "MOVE_TYPES_SIGNER" + } + } + }, + { + "type": "MOVE_TYPES_U64" + }, + { + "type": "MOVE_TYPES_ADDRESS" + } + ], + "return": [ + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "fungible_asset", + "name": "FungibleAsset" + } + } + ] + } + ], + "structs": [ + { + "name": "ManagedFungibleAsset", + "abilities": [ + "MOVE_ABILITY_KEY" + ], + "fields": [ + { + "name": "mint_ref", + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "fungible_asset", + "name": "MintRef" + } + } + }, + { + "name": "transfer_ref", + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "fungible_asset", + "name": "TransferRef" + } + } + }, + { + "name": "burn_ref", + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "fungible_asset", + "name": "BurnRef" + } + } + } + ] + } + ] + } + } + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x40b880d668a9d68d7d521bec03b92857363339053c28459fdfd8d3d905ff0379", + "stateKeyHash": "YL4yMgw13bUCqkJgWN/z0WWPQTgyJ00oNEwJL0/7L3U=", + "type": { + "address": "0x1", + "module": "code", + "name": "PackageRegistry" + }, + "typeStr": "0x1::code::PackageRegistry", + "data": "{\"packages\":[{\"deps\":[{\"account\":\"0x1\",\"package_name\":\"AptosFramework\"},{\"account\":\"0x1\",\"package_name\":\"AptosStdlib\"},{\"account\":\"0x1\",\"package_name\":\"MoveStdlib\"}],\"extension\":{\"vec\":[]},\"manifest\":\"0x1f8b08000000000002ff4dcd510ac2300c06e0f79ca2f4dd4e0fe0c3107789314668a394756d694407e2dd5d3a18237949f8bfa4cf68277cd20011675257a5ef0bce39106b7853619fa22ccf662d0dd0a37385988907c0fc4a3c3ecaea3ea94c35b65c3474ed2df9aa46118e324547d17a41ada0ee60be2a248b41e2c6345bef379bfae3b4cf5afde00ff6bd1a1fb2000000\",\"modules\":[{\"extension\":{\"vec\":[]},\"name\":\"fa_coin\",\"source\":\"0x1f8b08000000000002ffed59eb6edb3614fe9fa7603b20930bd57686b6ebd42468da35db80a5019a0cc5500c0a2d51365789f4482a4e5ae4dd7778d385b692f48a025b7e0436c9737878beef5c484f261374807eb84fd9fd1d54f1bc2e09520bac50c6ab196544a20a333c27795ad46c4e672549b1944421cc725843594a2e70b50429ca14479c919e96d58230949365c92f491ec318d99ac08e6e44a0152d4b34232813042bcae6082346567e4fe4f74476cf15550bad032db0c8339ec30a592f97e52558c20a3a8f11c3158991bcac66bc8c8d8d39c968854b39361b9f8230ce7341a444bc30baacea0c336d079f290ca7ced139c5684e545a118573ac70341aa30309e6496a4e7b4e84a49cc5882a3834589013d8c45ab814b0a3b8445271d868bce51c7278f01cfc9524054eb5e3d0fb2d047fb50413968acbb41060fc8a8bb7b0a4e7eb24797f42ca224647e0e357043e9c0acc644184f9f2ac16cc7c3872b6c6e8d0c91f68f1ab27c31bf1d9df246b3738365faf1370676bd9600ed90a4895270911828b604cd239236b834a00e84952abe27130c5970afcfb64cb8c6ae88eb59703427874105f8172036285df029d1698cdb5ebb53070432af4e2e5f1697afcfae58b5709aa1f3d407b68c729b7f30727272f4ed3933f8f9e1dff9e00bc199c6bb77ebc0f0b67770f0feebac5dfbd0148792d3292ce05af9740906a464464bec0da410f5bd7fea2978dfe6a0ef52b2f7324482111040f18a2042f0d2b2b801a5c0321e3a036649e01d43a4a80ba7d4fb8a3823feb4ca1231b3e3d1640cc48f4965c3adae93fbd470a9b270db19a29bfab9deed2ad59a26db1d39e8066eaaa45ec374615c5257d473a40193798c318e698c36a078c9d184aee24fbb49134a37056a487521b4911cec1f4046d5b4e8d3a472a75286b3cb51fb8311f40d9f620983443529d25f2d40e5a65710fffd19346e166be379afcb4194d09c3b0244c9551a3ac615b6b5ddc9bb4a44f120679341af5e7748c449a8a48a791bba3184dee997c87ee4dd617f68e6396daa4182e7e6ce67c92dca86a7677a1d432994c5ca61f43699814f89cc251c6f0cf99a2bfde5adec92c053774e8888d5ca039363c377e36549d68c64d9a78f05183cb92af6c01e1420fd8e26188d50f92718f269efdc08f30ddce09d04ac3ebd744016a1d8268553e14ae53e5d7dca0aa1b78d7a9ebaebb41a58f3d47f8d4460d28f751d128b533d7a8abf8396ccdfb8cdedebc419fbd1b53d2fb0684b877f0b8f5e8554b0c60c32e248720375cf9bc7c4ec9aa4dacaf880215b6c0f7ebfd406fa1db95efa5e511cc9ac6452da8f4ed0c7cf27d8ce5d1b29e953433b9a9df2824ae8ceefa7abc1f2428b361eacd6a717039c579d1cd47db4f6de33098a2bcb813007c9c8ad680a8b7e5a89fa84dc6d54034ced3e500ac34eeb295157c17a4f09e1308142e539c0da0417e066c79e25180a6ace23553a6088f10cefea9298c0ff063dd6de0aebeb703ae6f6e56a12ed76ac10590264f671cda93956697f4c9dfac0a2391a72bc82d467aa80a10266bb156052ea85432527cb3de026f886be3b6edcdd68fdb20b1beeb280cf50045b98442a9fb50931a8674f6c3ad396b0ce639f5572ede0c331a6a9c36edc8f5f440003dd7cd1d3a2b047f47d8192a2829f301da7873d6a803c255873c5f8f494122debe0d817a5e0d508773dccca71e91222df3f5b81952a9394bc3a53e673a27ea11a8c7d14e37a8bbc4b06bfdc824a3abc34d4cf9a2e4e814fcdb11c30b7c295284e099fdf4d2c8ef1c003684d2a12004fa75b848e12cd34b90e4fa8e0b572bc6dba8405c376019a1e764f34d640db3c2284e9dd635f4dc7803e0371fd09f147feeb437e3a8abb6cd9f6951e27910824df4899aac43f9072b86c1fc04246bf63f965f0ecb02ae611bc07c0d49381778f559eaae4671e514aea3d726ce20a94267db07ee3f53734328bdf36e551b5daa0d11fdd9b66a9f0d50d7fa5ddf7c1738c0f09b8fcdafd1eaac75cdb7e88e3b8d8d399501915655adf41b907e9d2082b08cf86ba779ae80cf67de6f67e3b6a9d6f7cc73b8d3c23891f6e55ccbb89b3ab50c0988019755c319ab86b212dead0d11061cdede17b5544b9066dc3a63edf26a1740ec6f6f24c86de9a3b50b7527f2b7552a536388bd9ac6eeaced2d961791991fc14b91794f864825a2a2523fbba7396194e451fba83beac0eb4e3d2ff90c97bb9becda6fcc082fdb962aa3fed30280a222ffc2b487dc85dc3de39aeb0b2c486758d20c523b5fb5be764281b76f1f74dd574fa72b083737da794ed8e0c9cda2180b70652bf8747a51e08c741ee0ccb5d409c7e15631da994e4395372408cf82a14806c030044db4b695c505edede94d63f4a01bcdfd6e64c8dc0fb0824a57a887ec88d1c38ebae6f23aeca99eabb5e33ec227818eae4762f4a8fb6ebad6a17d804fee7c82537eec06a1bea30d3be4a7693f910e0599735dcb4e1775dfbd21174b885cfdb2816909e93fc210f72ad53f0bc2eae9c5c3e974ba13a39267583faac398fe8d2b0cdaf59c7243ec1a5f69939af16f25a4edd39b36edda50bddabadafa17d7bc10e5f61d0000\",\"source_map\":\"0x\"}],\"name\":\"Examples\",\"source_digest\":\"9C4B908412129EC47BD9B8850CDCB1B6E6F5BFC88477980A3BADF0B5DFAF476F\",\"upgrade_number\":\"2\",\"upgrade_policy\":{\"policy\":1}}]}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x40b880d668a9d68d7d521bec03b92857363339053c28459fdfd8d3d905ff0379", + "stateKeyHash": "RP9tws7885zCygCQ2v0D/HKftYyJHTa/KSkdMhc/r9A=", + "type": { + "address": "0x1", + "module": "coin", + "name": "CoinStore", + "genericTypeParams": [ + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "aptos_coin", + "name": "AptosCoin" + } + } + ] + }, + "typeStr": "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>", + "data": "{\"coin\":{\"value\":\"298963800\"},\"deposit_events\":{\"counter\":\"3\",\"guid\":{\"id\":{\"addr\":\"0x40b880d668a9d68d7d521bec03b92857363339053c28459fdfd8d3d905ff0379\",\"creation_num\":\"2\"}}},\"frozen\":false,\"withdraw_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x40b880d668a9d68d7d521bec03b92857363339053c28459fdfd8d3d905ff0379\",\"creation_num\":\"3\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x40b880d668a9d68d7d521bec03b92857363339053c28459fdfd8d3d905ff0379", + "stateKeyHash": "aEpLQPZCozE4KuCkKZdOhDHfGADyKDizzlAGU5sgzTs=", + "type": { + "address": "0x1", + "module": "account", + "name": "Account" + }, + "typeStr": "0x1::account::Account", + "data": "{\"authentication_key\":\"0x40b880d668a9d68d7d521bec03b92857363339053c28459fdfd8d3d905ff0379\",\"coin_register_events\":{\"counter\":\"1\",\"guid\":{\"id\":{\"addr\":\"0x40b880d668a9d68d7d521bec03b92857363339053c28459fdfd8d3d905ff0379\",\"creation_num\":\"0\"}}},\"guid_creation_num\":\"4\",\"key_rotation_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x40b880d668a9d68d7d521bec03b92857363339053c28459fdfd8d3d905ff0379\",\"creation_num\":\"1\"}}},\"rotation_capability_offer\":{\"for\":{\"vec\":[]}},\"sequence_number\":\"13\",\"signer_capability_offer\":{\"for\":{\"vec\":[]}}}" + } + }, + { + "type": "TYPE_WRITE_TABLE_ITEM", + "writeTableItem": { + "stateKeyHash": "bkso1A+YoQamUWNTCSTA3LQME0nTqpFdEItNbPwd2xk=", + "handle": "0x1b854694ae746cdbd8d44186ca4929b2b337df21d1c74633be19b2710552fdca", + "key": "0x0619dc29a0aac8fa146714058e8dd6d2d0f3bdf5f6331907bf91f3acd81e6935", + "data": { + "key": "\"0x619dc29a0aac8fa146714058e8dd6d2d0f3bdf5f6331907bf91f3acd81e6935\"", + "keyType": "address", + "value": "\"18607486383368079720\"", + "valueType": "u128" + } + } + } + ] + }, + "epoch": "8333", + "blockHeight": "123164094", + "type": "TRANSACTION_TYPE_USER", + "sizeInfo": { + "transactionBytes": 4741, + "writeOpSizeInfo": [ + { + "keyBytes": 75, + "valueBytes": 2267 + }, + { + "keyBytes": 89, + "valueBytes": 2241 + }, + { + "keyBytes": 138, + "valueBytes": 105 + }, + { + "keyBytes": 84, + "valueBytes": 147 + }, + { + "keyBytes": 66, + "valueBytes": 16 + } + ] + }, + "user": { + "request": { + "sender": "0x40b880d668a9d68d7d521bec03b92857363339053c28459fdfd8d3d905ff0379", + "sequenceNumber": "12", + "maxGasAmount": "200000", + "gasUnitPrice": "100", + "expirationTimestampSecs": { + "seconds": "1692824758" + }, + "payload": { + "type": "TYPE_ENTRY_FUNCTION_PAYLOAD", + "entryFunctionPayload": { + "function": { + "module": { + "address": "0x1", + "name": "code" + }, + "name": "publish_package_txn" + }, + "arguments": [ + "\"0x084578616d706c6573010000000000000000403943344239303834313231323945433437424439423838353043444342314236453646354246433838343737393830413342414446304235444641463437364692011f8b08000000000002ff4dcd510ac2300c06e0f79ca2f4dd4e0fe0c3107789314668a394756d694407e2dd5d3a18237949f8bfa4cf68277cd20011675257a5ef0bce39106b7853619fa22ccf662d0dd0a37385988907c0fc4a3c3ecaea3ea94c35b65c3474ed2df9aa46118e324547d17a41ada0ee60be2a248b41e2c6345bef379bfae3b4cf5afde00ff6bd1a1fb2000000010766615f636f696ec40e1f8b08000000000002ffed59eb6edb3614fe9fa7603b20930bd57686b6ebd42468da35db80a5019a0cc5500c0a2d51365789f4482a4e5ae4dd7778d385b692f48a025b7e0436c9737878beef5c484f261374807eb84fd9fd1d54f1bc2e09520bac50c6ab196544a20a333c27795ad46c4e672549b1944421cc725843594a2e70b50429ca14479c919e96d58230949365c92f491ec318d99ac08e6e44a0152d4b34232813042bcae6082346567e4fe4f74476cf15550bad032db0c8339ec30a592f97e52558c20a3a8f11c3158991bcac66bc8c8d8d39c968854b39361b9f8230ce7341a444bc30baacea0c336d079f290ca7ced139c5684e545a118573ac70341aa30309e6496a4e7b4e84a49cc5882a3834589013d8c45ab814b0a3b8445271d868bce51c7278f01cfc9524054eb5e3d0fb2d047fb50413968acbb41060fc8a8bb7b0a4e7eb24797f42ca224647e0e357043e9c0acc644184f9f2ac16cc7c3872b6c6e8d0c91f68f1ab27c31bf1d9df246b3738365faf1370676bd9600ed90a4895270911828b604cd239236b834a00e84952abe27130c5970afcfb64cb8c6ae88eb59703427874105f8172036285df029d1698cdb5ebb53070432af4e2e5f1697afcfae58b5709aa1f3d407b68c729b7f30727272f4ed3933f8f9e1dff9e00bc199c6bb77ebc0f0b67770f0feebac5dfbd0148792d3292ce05af9740906a464464bec0da410f5bd7fea2978dfe6a0ef52b2f7324482111040f18a2042f0d2b2b801a5c0321e3a036649e01d43a4a80ba7d4fb8a3823feb4ca1231b3e3d1640cc48f4965c3adae93fbd470a9b270db19a29bfab9deed2ad59a26db1d39e8066eaaa45ec374615c5257d473a40193798c318e698c36a078c9d184aee24fbb49134a37056a487521b4911cec1f4046d5b4e8d3a472a75286b3cb51fb8311f40d9f620983443529d25f2d40e5a65710fffd19346e166be379afcb4194d09c3b0244c9551a3ac615b6b5ddc9bb4a44f120679341af5e7748c449a8a48a791bba3184dee997c87ee4dd617f68e6396daa4182e7e6ce67c92dca86a7677a1d432994c5ca61f43699814f89cc251c6f0cf99a2bfde5adec92c053774e8888d5ca039363c377e36549d68c64d9a78f05183cb92af6c01e1420fd8e26188d50f92718f269efdc08f30ddce09d04ac3ebd744016a1d8268553e14ae53e5d7dca0aa1b78d7a9ebaebb41a58f3d47f8d4460d28f751d128b533d7a8abf8396ccdfb8cdedebc419fbd1b53d2fb0684b877f0b8f5e8554b0c60c32e248720375cf9bc7c4ec9aa4dacaf880215b6c0f7ebfd406fa1db95efa5e511cc9ac6452da8f4ed0c7cf27d8ce5d1b29e953433b9a9df2824ae8ceefa7abc1f2428b361eacd6a717039c579d1cd47db4f6de33098a2bcb813007c9c8ad680a8b7e5a89fa84dc6d54034ced3e500ac34eeb295157c17a4f09e1308142e539c0da0417e066c79e25180a6ace23553a6088f10cefea9298c0ff063dd6de0aebeb703ae6f6e56a12ed76ac10590264f671cda93956697f4c9dfac0a2391a72bc82d467aa80a10266bb156052ea85432527cb3de026f886be3b6edcdd68fdb20b1beeb280cf50045b98442a9fb50931a8674f6c3ad396b0ce639f5572ede0c331a6a9c36edc8f5f440003dd7cd1d3a2b047f47d8192a2829f301da7873d6a803c255873c5f8f494122debe0d817a5e0d508773dccca71e91222df3f5b81952a9394bc3a53e673a27ea11a8c7d14e37a8bbc4b06bfdc824a3abc34d4cf9a2e4e814fcdb11c30b7c295284e099fdf4d2c8ef1c003684d2a12004fa75b848e12cd34b90e4fa8e0b572bc6dba8405c376019a1e764f34d640db3c2284e9dd635f4dc7803e0371fd09f147feeb437e3a8abb6cd9f6951e27910824df4899aac43f9072b86c1fc04246bf63f965f0ecb02ae611bc07c0d49381778f559eaae4671e514aea3d726ce20a94267db07ee3f53734328bdf36e551b5daa0d11fdd9b66a9f0d50d7fa5ddf7c1738c0f09b8fcdafd1eaac75cdb7e88e3b8d8d399501915655adf41b907e9d2082b08cf86ba779ae80cf67de6f67e3b6a9d6f7cc73b8d3c23891f6e55ccbb89b3ab50c0988019755c319ab86b212dead0d11061cdede17b5544b9066dc3a63edf26a1740ec6f6f24c86de9a3b50b7527f2b7552a536388bd9ac6eeaced2d961791991fc14b91794f864825a2a2523fbba7396194e451fba83beac0eb4e3d2ff90c97bb9becda6fcc082fdb962aa3fed30280a222ffc2b487dc85dc3de39aeb0b2c486758d20c523b5fb5be764281b76f1f74dd574fa72b083737da794ed8e0c9cda2180b70652bf8747a51e08c741ee0ccb5d409c7e15631da994e4395372408cf82a14806c030044db4b695c505edede94d63f4a01bcdfd6e64c8dc0fb0824a57a887ec88d1c38ebae6f23aeca99eabb5e33ec227818eae4762f4a8fb6ebad6a17d804fee7c82537eec06a1bea30d3be4a7693f910e0599735dcb4e1775dfbd21174b885cfdb2816909e93fc210f72ad53f0bc2eae9c5c3e974ba13a39267583faac398fe8d2b0cdaf59c7243ec1a5f69939af16f25a4edd39b36edda50bddabadafa17d7bc10e5f61d000000000300000000000000000000000000000000000000000000000000000000000000010e4170746f734672616d65776f726b00000000000000000000000000000000000000000000000000000000000000010b4170746f735374646c696200000000000000000000000000000000000000000000000000000000000000010a4d6f76655374646c696200\"", + "[\"0xa11ceb0b060000000c0100100210300340a60104e6011605fc01de0207da04b005088a0a4006ca0a7510bf0ba1010ae00c0c0cec0cad040d9911060000010101020103010401050106010700080800020a0000030d07010001020e08000216060002180600021a0600021b080003270200042907010000072b07000009000100000b020100000c030100000f01040000100501000011000100001206010000130301000014070800061c050a00031d0c0d0108011e0e0e00031f0f0a01080520101101080221130101080522101101080223150101080224170101080325180a0003260a19010803281b1c00042a011e0100072c1f2000052d210100022e222300022f22240002302225000331222600021128080002322a01010802332c0801080a0b0c0b0d0b0e120f0b10121112130b151d1d121e1203060c05030003060c05080102060c05010b0201080301060c04060c05050303060c0305010801050b020108030b020108030608060b02010807060c0105010803020b02010900050101010301060b0201090002050b02010900010b02010807010807030608060b0201090003050b020108030b02010803060c0b02010807060805030608050b020109000801050b020108030b02010803060c0608050b02010807030608050b02010900010206050a02010b0201090006080808060608080c0804080502060c0a020108080104010b09010900010a0201080a070608080b090104080a080a02080a080a01060808010804010806010805010c060b020108030b020108030801060800060c0b020108070206080403060b020108030b020108030b02010807060c0b02010807060805040608050b020109000b0201090003050b020108030b020108030b02010807060c060805030608050b02010900030766615f636f696e056572726f720e66756e6769626c655f6173736574066f626a656374066f7074696f6e167072696d6172795f66756e6769626c655f73746f7265067369676e657206737472696e67144d616e6167656446756e6769626c654173736574046275726e0d46756e6769626c654173736574076465706f7369740e667265657a655f6163636f756e74064f626a656374084d657461646174610c6765745f6d657461646174610b696e69745f6d6f64756c65046d696e74087472616e7366657210756e667265657a655f6163636f756e74087769746864726177086d696e745f726566074d696e745265660c7472616e736665725f7265660b5472616e73666572526566086275726e5f726566074275726e5265660d46756e6769626c6553746f72650a616464726573735f6f660869735f6f776e6572117065726d697373696f6e5f64656e6965640e6f626a6563745f616464726573730d7072696d6172795f73746f7265096275726e5f66726f6d1b656e737572655f7072696d6172795f73746f72655f657869737473106465706f7369745f776974685f7265660f7365745f66726f7a656e5f666c6167156372656174655f6f626a6563745f6164647265737311616464726573735f746f5f6f626a6563740e436f6e7374727563746f72526566136372656174655f6e616d65645f6f626a656374064f7074696f6e046e6f6e6506537472696e6704757466382b6372656174655f7072696d6172795f73746f72655f656e61626c65645f66756e6769626c655f61737365741167656e65726174655f6d696e745f7265661167656e65726174655f6275726e5f7265661567656e65726174655f7472616e736665725f7265660f67656e65726174655f7369676e6572117472616e736665725f776974685f7265661177697468647261775f776974685f72656640b880d668a9d68d7d521bec03b92857363339053c28459fdfd8d3d905ff037900000000000000000000000000000000000000000000000000000000000000010a020302464103080100000000000000052040b880d668a9d68d7d521bec03b92857363339053c28459fdfd8d3d905ff03790a020807464120436f696e0a021f1e687474703a2f2f6578616d706c652e636f6d2f66617669636f6e2e69636f0a021312687474703a2f2f6578616d706c652e636f6d126170746f733a3a6d657461646174615f76318c010101000000000000000a454e4f545f4f574e4552344f6e6c792066756e6769626c65206173736574206d65746164617461206f776e65722063616e206d616b65206368616e6765732e01144d616e6167656446756e6769626c654173736574010301183078313a3a6f626a6563743a3a4f626a65637447726f7570010c6765745f6d657461646174610101000002031508041708051908060001040100091d11030c030b000a030c040c070a040b0711093800040c050f0701110b270e0438012b0010000c050b010b0338020c060b050b060b023803020101000100141d11030c030b000a030c040c050a040b0511093800040c050f0701110b270e0438012b0010010c070b010b0338040c060b070b060b023805020201040100161d11030c020b000a020c030c040a030b0411093800040c050f0701110b270e0338012b0010010c050b010b0238040c060b050b0608380602030100000a0707020c000e0007001112380702040000001a250b00070011140c010e010c030a03380807031116070011163108070411160705111611170a0311180c050a0311190c020a03111a0c060b03111b0c040e040b050b060b0212002d00020501040100272211030c030b000a030c040c070a040b0711093800040c050f0701110b270e0438012b000c060b010b0338040c080a0610020b02111c0c050b0610010b080b053805020601040100292211030c040b000a040c050c070a050b0711093800040c050f0701110b270e0538012b0010010c090b010a0438020c060b020b0438040c080b090b060b080b033809020701040100161d11030c020b000a020c030c040a030b0411093800040c050f0701110b270e0338012b0010010c050b010b0238040c060b050b060938060208010001002b1d11030c030b000a030c040c060a040b0611093800040c050f0701110b270e0438012b0010010c070b020b0338020c050b070b050b01380a0200020001000000\"]" + ], + "entryFunctionIdStr": "0x1::code::publish_package_txn" + } + }, + "signature": { + "type": "TYPE_ED25519", + "ed25519": { + "publicKey": "zZ5nqyfz8vCjeJv4tWH30duw4BbGUe7dmQfgVtTEYKQ=", + "signature": "iJixS4IYCXPhOkci7ZyGlLsS070mQirwaNeYISaUOIydPkfofbV/PbARdD+JHN1Ko4ftj2bmabsRJOPjt/48Bw==" + } + } + } + } +} \ No newline at end of file diff --git a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/fa_double_transfer.json b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/fa_double_transfer.json index 8327961029f55..8f6014678b39a 100644 --- a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/fa_double_transfer.json +++ b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/fa_double_transfer.json @@ -1,17 +1,17 @@ { "timestamp": { - "seconds": "1732752407", - "nanos": 70774000 + "seconds": "1732752738", + "nanos": 956423000 }, - "version": "67", + "version": "69", "info": { - "hash": "WSRo7BjlDt3z165dsMFMrjSFDZHFvKsY1JXaayoSb/w=", - "stateChangeHash": "70YgHm7HUKw9br0pPszGsVlxucAlA3CWBmspWaBaVjc=", + "hash": "xrzWtoXziY00v1y/H1/5YyQO6dItOHDHooBPEiiZHH0=", + "stateChangeHash": "5d8vUR5B0jwYgif3F8vvw7l+JWzxcV/M5RQG4w+ibxk=", "eventRootHash": "FmWvL7p7CNYdF2eb/mjbz8+qRiRO70XR0GQsuHS1nuk=", "gasUsed": "2230", "success": true, "vmStatus": "Executed successfully", - "accumulatorRootHash": "s1cwGiYnKWCvxwQbF5XxBhw+7OT3ke/l+qo6wwTRXe0=", + "accumulatorRootHash": "BRdjZ5CQzT+6QgnKkEl0OU0WtLE5aN0F7JfdVUmg2K0=", "changes": [ { "type": "TYPE_WRITE_RESOURCE", @@ -208,7 +208,7 @@ ] }, "epoch": "2", - "blockHeight": "32", + "blockHeight": "33", "type": "TRANSACTION_TYPE_USER", "sizeInfo": { "transactionBytes": 1199, @@ -275,7 +275,7 @@ "maxGasAmount": "3345", "gasUnitPrice": "100", "expirationTimestampSecs": { - "seconds": "1732752437" + "seconds": "1732752769" }, "payload": { "type": "TYPE_SCRIPT_PAYLOAD", @@ -304,7 +304,7 @@ "type": "TYPE_ED25519", "ed25519": { "publicKey": "X3dtn8+5n300isDheC1WwnuA6rUEP5ShsSfvipASLUM=", - "signature": "oMoT4Ogp1SUNY6oh6Ng9kKDHkWkf+hBMt1Beyfqe4cvTA/K8KjumJyK6Yat7EgRgk4QgfUpRvKNFxJwRblNoCw==" + "signature": "9Y7nb69XbP7YWzpfpYhGlH2UwtlCLdBVUCZ69Xz9pbmkeZTVIP+xwHrF4buJ9QRjHiD5iV6ZNz9FYSKVcEzrCw==" } } }, diff --git a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/fa_mint_transfer_burn.json b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/fa_mint_transfer_burn.json index 4f0f698750d87..77581c76c2ed0 100644 --- a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/fa_mint_transfer_burn.json +++ b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/fa_mint_transfer_burn.json @@ -1,17 +1,17 @@ { "timestamp": { - "seconds": "1732752394", - "nanos": 753016000 + "seconds": "1732752725", + "nanos": 407952000 }, "version": "35", "info": { - "hash": "TeqP7BOUSL4Cw6A9dPrPZIk307ZvOQTqk7SyktjQa3k=", - "stateChangeHash": "yjF48v0yCpkI1a6QlRCqw264uSQ4Iji+GGI7vYwaCCM=", + "hash": "ayRIeRnfkgKGyIpCineUBPs4ehrliH8unvneE+3Kdy4=", + "stateChangeHash": "+3sO3Xe8keMQBqigBaLQjzyIOn9q7rjFa6WfnIi9Ssg=", "eventRootHash": "zguCQh0yktZ64gFcK3ArJOOrDjHPVhTjf/pYU5fhJdc=", "gasUsed": "1161", "success": true, "vmStatus": "Executed successfully", - "accumulatorRootHash": "kp/XkH7fLQsz3XWemRlICZpDjLnO8yPGyvb3c19+jHE=", + "accumulatorRootHash": "ohk3aLs2jJLjb5zxSsO3DHfJAEsWGwlOhWTLWlekMT0=", "changes": [ { "type": "TYPE_WRITE_RESOURCE", @@ -199,7 +199,7 @@ "maxGasAmount": "1741", "gasUnitPrice": "100", "expirationTimestampSecs": { - "seconds": "1732752425" + "seconds": "1732752755" }, "payload": { "type": "TYPE_SCRIPT_PAYLOAD", @@ -228,7 +228,7 @@ "type": "TYPE_ED25519", "ed25519": { "publicKey": "KU08yl94iErSCo4VhF6tGWQYqvSaK1IjTD/4i/uoPSI=", - "signature": "w3Va79RRl9B7rA3+e4c1BsL1mHALLYkJQPeTDUwBfs6tqW55B61XLj8bBYf5m6SPP44JGS54Sy+B17engewICg==" + "signature": "kr6k4+df1lIe1fYDQ89POnorMV1YGSI8hL5aYeUNvtPBODiBUvpxPGq4wyG+HNbUpNHWtwS40NfZ/kYZjOwRDQ==" } } }, diff --git a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script1.json b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script1.json index 8656175cb6d90..1cff569455b9e 100644 --- a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script1.json +++ b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script1.json @@ -1,17 +1,17 @@ { "timestamp": { - "seconds": "1732752427", - "nanos": 716542000 + "seconds": "1732752760", + "nanos": 733718000 }, - "version": "131", + "version": "135", "info": { - "hash": "KpFwmiU5ttJrMUTypaifB3Ild8caulWChn2UDQqbP1A=", - "stateChangeHash": "QuedrdLgRVt8SZdyoPAbs4clpCwqCe+2UAo8+nrx1SA=", + "hash": "RQzeD2EQM+QpZiLInBzM9l4Z5t0BWPGf33k40KrvmkM=", + "stateChangeHash": "UieS5RIQtmLQQfs+NnTlQVgBiPBaq0hVAuCorH9MmQs=", "eventRootHash": "J/kCueHhHqJXi8MVudrh82sOQ/pqY9TJ9VjLOdgel6I=", "gasUsed": "3", "success": true, "vmStatus": "Executed successfully", - "accumulatorRootHash": "r2FZPXOd5Djv8G3fsmDkmfWSO4ic4O6nLsoInIwSFFg=", + "accumulatorRootHash": "TI595vYByB/07beHZjlqhEKIp0oiAeA1wYzi3rkqOkI=", "changes": [ { "type": "TYPE_WRITE_RESOURCE", @@ -68,7 +68,7 @@ ] }, "epoch": "2", - "blockHeight": "61", + "blockHeight": "63", "type": "TRANSACTION_TYPE_USER", "sizeInfo": { "transactionBytes": 190, @@ -99,7 +99,7 @@ "maxGasAmount": "4", "gasUnitPrice": "100", "expirationTimestampSecs": { - "seconds": "1732752458" + "seconds": "1732752791" }, "payload": { "type": "TYPE_SCRIPT_PAYLOAD", @@ -128,7 +128,7 @@ "type": "TYPE_ED25519", "ed25519": { "publicKey": "ObSsyF4CbcBWRkpeoAuY+FgmDqrSt03TC4auDU2U3fU=", - "signature": "rGLJfiyHpSe+xtzx6B/3PkqTsybbYGFzoToVGb9HEfN0Va0/cEV2udTtGnxGy0ZW3VG7qHnaywt9mLFYFp8DBA==" + "signature": "cQVhPPiCjuBaiGb5VmdZB7I546Ys7Ye2/zuUlNDHhFF/33O1wgy/fG/5G37EgnnP2J8ePfyIXeC9kEZUe6a8BQ==" } } }, diff --git a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script2.json b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script2.json index 32e080a650ee9..d07c603361eae 100644 --- a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script2.json +++ b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script2.json @@ -1,17 +1,17 @@ { "timestamp": { - "seconds": "1732752433", - "nanos": 945287000 + "seconds": "1732752767", + "nanos": 150408000 }, - "version": "151", + "version": "155", "info": { - "hash": "T0MflJ4xr13oeDZtbIJrwVBB6+xbXWtc22gEe8mr0lM=", - "stateChangeHash": "BEruB8zGnFmiqh19p3v5OMcGbmR7i7SNqPQxLTrli2E=", + "hash": "uPvgWhILXg+hzAcjHXBQckTyTAN4kmY06MfaH8U4Ks0=", + "stateChangeHash": "ffjkaIUuvKPlWv5iB1ZEqP+eaGgZvbfWk2W3DzDyKeM=", "eventRootHash": "J/kCueHhHqJXi8MVudrh82sOQ/pqY9TJ9VjLOdgel6I=", "gasUsed": "3", "success": true, "vmStatus": "Executed successfully", - "accumulatorRootHash": "C3Lb3f2L4loI/ozhPOyPO8vEQgYtVqv1pB0ktt/AdUw=", + "accumulatorRootHash": "ouZijqZ66R3YzKg+ZlEklCxMgXAyeeLk96OLTHyxCWw=", "changes": [ { "type": "TYPE_WRITE_RESOURCE", @@ -68,7 +68,7 @@ ] }, "epoch": "2", - "blockHeight": "70", + "blockHeight": "72", "type": "TRANSACTION_TYPE_USER", "sizeInfo": { "transactionBytes": 190, @@ -100,7 +100,7 @@ "maxGasAmount": "4", "gasUnitPrice": "100", "expirationTimestampSecs": { - "seconds": "1732752464" + "seconds": "1732752797" }, "payload": { "type": "TYPE_SCRIPT_PAYLOAD", @@ -129,7 +129,7 @@ "type": "TYPE_ED25519", "ed25519": { "publicKey": "ObSsyF4CbcBWRkpeoAuY+FgmDqrSt03TC4auDU2U3fU=", - "signature": "+939tVIjj3xsPAcg44upEZkSjnaheRT92WjUC6gN4R6y3w+GsT/wkH9RzVjHkQCREACErqbFPw7XgR/4D2JuDg==" + "signature": "gXBGQFT6fL1EP2YWq4O+GqIKWQUCQkgUGrrVszrEHX1rP1xuq04/eFq4GOVcCjQs7f2QlAC8OSGq+kxBfTmNCg==" } } }, diff --git a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script3.json b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script3.json index 2b8128ffb31ba..b04618998c095 100644 --- a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script3.json +++ b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script3.json @@ -1,17 +1,17 @@ { "timestamp": { - "seconds": "1732752414", - "nanos": 344797000 + "seconds": "1732752746", + "nanos": 930524000 }, - "version": "89", + "version": "93", "info": { - "hash": "0Grfy/3XflrDlM1pN9ROC4DcC8LUaE14lYdA5hZv94g=", - "stateChangeHash": "OSCXnaT5m3N/W6XcSsBMYgURA+ItiZfCdPK0jQ1QxsU=", + "hash": "8iRuztTGNuVflgAEWpnx1WcRfGZ0+Dau/wwjOiSH3+o=", + "stateChangeHash": "OcnKtsd6TAR4jLFPHupwOCBKrSPgj0xaZiTWnFVLBE8=", "eventRootHash": "J/kCueHhHqJXi8MVudrh82sOQ/pqY9TJ9VjLOdgel6I=", "gasUsed": "3", "success": true, "vmStatus": "Executed successfully", - "accumulatorRootHash": "rDQPrWw9UolILsSMP07nXU9BZJ+JWHJlReNjcVxV4Tk=", + "accumulatorRootHash": "/1sGciJhlYZDYDkbCBoJRcS3Pgksc1YfOJ1orZz8X4w=", "changes": [ { "type": "TYPE_WRITE_RESOURCE", @@ -68,7 +68,7 @@ ] }, "epoch": "2", - "blockHeight": "42", + "blockHeight": "44", "type": "TRANSACTION_TYPE_USER", "sizeInfo": { "transactionBytes": 190, @@ -99,7 +99,7 @@ "maxGasAmount": "4", "gasUnitPrice": "100", "expirationTimestampSecs": { - "seconds": "1732752444" + "seconds": "1732752777" }, "payload": { "type": "TYPE_SCRIPT_PAYLOAD", @@ -128,7 +128,7 @@ "type": "TYPE_ED25519", "ed25519": { "publicKey": "spiXXSfb/zAg5e5/27rYqWnU8qLVKG4JfR25dg0E3TE=", - "signature": "g4fW/Liaw2li3GQpwKqjSn/g/9nPsLewSV9Xfh2mqGhqqYp8CjKfZWaoY5xnDW25+I2xMY9qX20mM9SN0UcDBQ==" + "signature": "nx5JY37B7wYb/XGMQsRmniHKWAr2Em9Acw4rf2t7PaVUFri5H7a3YLuS+P8UgbWpJEQZ+8rOJheGZ/mDaovDBQ==" } } }, diff --git a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script4.json b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script4.json index ceeb655d2ec61..8de6a80f7d7b9 100644 --- a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script4.json +++ b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/scripted_transactions/simple_user_script4.json @@ -1,17 +1,17 @@ { "timestamp": { - "seconds": "1732752420", - "nanos": 683733000 + "seconds": "1732752753", + "nanos": 464510000 }, - "version": "109", + "version": "113", "info": { - "hash": "wRDhIULIsprwu5kAQH0lrzCNH/hOXaGiwp+IkYZnrsA=", - "stateChangeHash": "VXDLlx4UXl+5kFAps8EMPPt/lEBF9OwbqtBXnjwzyZM=", + "hash": "oYa+TMnfLyFeH3H2XEZgiBMLJ+DxSy6YcVcNy5J4JfY=", + "stateChangeHash": "OyOxxEbPllBNm8lOrnwFFsgBmXnX4HwKJQZTaJi9fkQ=", "eventRootHash": "J/kCueHhHqJXi8MVudrh82sOQ/pqY9TJ9VjLOdgel6I=", "gasUsed": "3", "success": true, "vmStatus": "Executed successfully", - "accumulatorRootHash": "N3sY2AwsTq74Qb3un7ZuTs9PFgUnWflI1u1LcSe+M3Y=", + "accumulatorRootHash": "88fXEFMqQhOcsrc6PVA33fJjASWpk2eaQIba6mXjoTw=", "changes": [ { "type": "TYPE_WRITE_RESOURCE", @@ -68,7 +68,7 @@ ] }, "epoch": "2", - "blockHeight": "51", + "blockHeight": "53", "type": "TRANSACTION_TYPE_USER", "sizeInfo": { "transactionBytes": 190, @@ -99,7 +99,7 @@ "maxGasAmount": "4", "gasUnitPrice": "100", "expirationTimestampSecs": { - "seconds": "1732752451" + "seconds": "1732752784" }, "payload": { "type": "TYPE_SCRIPT_PAYLOAD", @@ -128,7 +128,7 @@ "type": "TYPE_ED25519", "ed25519": { "publicKey": "7wW+3hX0IuFsAALjzui01DQVGNmcRpU1KhhpsHeYZPs=", - "signature": "0X9bVOKu0cJvabk5JyrFgGXHDYuEc20Nh9L7eY8fw+gy12roELRmNPZdUlEr6BDkc67OKHLgpNB/Q/iNuPirCw==" + "signature": "X0k4xVGiytAI2CVRyLPIo2BHY7BG2q8+KXgSGIHfVucE0c6EXbrTDYUoba2cq0lVZukXNAxpgCInvDD/6gCmCw==" } } }, diff --git a/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/imported_transactions.yaml b/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/imported_transactions.yaml index 65aae7f7a3819..3253aa8ed88c6 100644 --- a/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/imported_transactions.yaml +++ b/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/imported_transactions.yaml @@ -15,6 +15,10 @@ testnet: 5992795934: 5992795934_fa_activities 5523474016: 5523474016_validator_txn + # fungible asset processor + 4462417704: 4462417704_secondary_store_burnt + 646928741: 646928741_no_events + mainnet: transaction_stream_endpoint: https://grpc.mainnet.aptoslabs.com:443 diff --git a/ecosystem/indexer-grpc/indexer-transaction-generator/src/config.rs b/ecosystem/indexer-grpc/indexer-transaction-generator/src/config.rs index 8f6e483bd7268..356e3502d7fb4 100644 --- a/ecosystem/indexer-grpc/indexer-transaction-generator/src/config.rs +++ b/ecosystem/indexer-grpc/indexer-transaction-generator/src/config.rs @@ -74,7 +74,6 @@ impl IndexerCliArgs { continue; } let path = entry.path(); - println!("\nFound path: {:?}\n", path.display()); if path.extension().unwrap_or_default() == "yaml" { let file_name = path.file_name().unwrap().to_str().unwrap(); let script_transactions_raw: String = tokio::fs::read_to_string(&path).await?; From 96612fdd765e1cef2206e59928b790471e5bb071 Mon Sep 17 00:00:00 2001 From: Vineeth Kashyap Date: Wed, 4 Dec 2024 16:03:52 -0500 Subject: [PATCH 10/78] [compiler-v2] Optimize stackless-bytecode assign instructions (#15445) --- .../compiler-v2-doc/token_event_store.md | 58 ++++- .../move-stdlib/tests/compiler-v2-doc/mem.md | 115 ++++++++++ .../move/move-compiler-v2/src/experiments.rs | 6 + .../function_generator.rs | 19 +- .../bug-10253.off.exp | 208 ++++++++---------- .../bug-10253.on.exp | 190 +++++++--------- .../jump-label.off.exp | 69 +++--- .../jump-label.on.exp | 69 +++--- .../eager-pushes/framework_reduced_06.exp | 35 ++- .../eager-pushes/move_stdlib_reduced.exp | 27 +-- .../tests/eager-pushes/txn_reduced_01.exp | 176 +++++++++++++++ .../tests/eager-pushes/txn_reduced_01.move | 16 ++ .../file-format-generator/bug_14762.opt.exp | 47 ++-- .../file-format-generator/fields.opt.exp | 3 - .../file-format-generator/vector.opt.exp | 33 ++- .../tests/flush-writes/def_use_07.off.exp | 1 - .../tests/flush-writes/def_use_07.on.exp | 1 - .../tests/flush-writes/loop_01.off.exp | 13 +- .../tests/flush-writes/loop_01.on.exp | 13 +- .../args_with_side_effects.exp | 15 +- .../args_with_side_effects.opt.exp | 15 +- .../variable-coalescing/borrowed_var.exp | 1 - .../variable-coalescing/borrowed_var.opt.exp | 1 - .../tests/variable-coalescing/branch_2.exp | 1 - .../variable-coalescing/branch_2.opt.exp | 1 - .../tests/variable-coalescing/branch_3.exp | 1 - .../variable-coalescing/branch_3.opt.exp | 1 - ...branch_assigns_then_moves_then_assigns.exp | 2 - ...ch_assigns_then_moves_then_assigns.opt.exp | 2 - .../tests/variable-coalescing/consume_1.exp | 20 +- .../variable-coalescing/consume_1.opt.exp | 20 +- .../tests/variable-coalescing/consume_3.exp | 2 - .../variable-coalescing/consume_3.opt.exp | 2 - .../tests/variable-coalescing/consume_4.exp | 2 - .../variable-coalescing/consume_4.opt.exp | 2 - .../cyclic_assignments.exp | 1 - .../cyclic_assignments.opt.exp | 1 - .../variable-coalescing/cyclic_dead_store.exp | 16 +- .../cyclic_dead_store.opt.exp | 16 +- .../variable-coalescing/immut_refs_2.exp | 1 - .../variable-coalescing/immut_refs_2.opt.exp | 1 - .../variable-coalescing/intermingled_1.exp | 1 - .../intermingled_2.opt.exp | 5 +- .../tests/variable-coalescing/loop_1.exp | 10 +- .../tests/variable-coalescing/loop_1.opt.exp | 10 +- .../tests/variable-coalescing/loop_2.exp | 16 +- .../tests/variable-coalescing/loop_2.opt.exp | 16 +- .../tests/variable-coalescing/mut_refs_1.exp | 17 +- .../variable-coalescing/mut_refs_1.opt.exp | 17 +- .../tests/variable-coalescing/seq_kills_1.exp | 12 +- .../variable-coalescing/seq_kills_1.opt.exp | 12 +- .../tests/variable-coalescing/seq_kills_2.exp | 12 +- .../variable-coalescing/seq_kills_2.opt.exp | 12 +- .../straight_line_kills.exp | 17 +- .../straight_line_kills.opt.exp | 17 +- .../tests/variable-coalescing/swap.exp | 14 +- .../tests/variable-coalescing/swap.opt.exp | 14 +- .../variable-coalescing/swap_in_a_loop.exp | 26 +-- .../swap_in_a_loop.opt.exp | 26 +-- .../tests/misc/assign_optimize_test01.exp | 15 ++ .../tests/misc/assign_optimize_test01.move | 37 ++++ .../assert_one.optimize-no-simplify.exp | 2 +- .../no-v1-comparison/assert_one.optimize.exp | 2 +- 63 files changed, 901 insertions(+), 632 deletions(-) create mode 100644 aptos-move/framework/move-stdlib/tests/compiler-v2-doc/mem.md create mode 100644 third_party/move/move-compiler-v2/tests/eager-pushes/txn_reduced_01.exp create mode 100644 third_party/move/move-compiler-v2/tests/eager-pushes/txn_reduced_01.move create mode 100644 third_party/move/move-compiler-v2/transactional-tests/tests/misc/assign_optimize_test01.exp create mode 100644 third_party/move/move-compiler-v2/transactional-tests/tests/misc/assign_optimize_test01.move diff --git a/aptos-move/framework/aptos-token/tests/compiler-v2-doc/token_event_store.md b/aptos-move/framework/aptos-token/tests/compiler-v2-doc/token_event_store.md index 807296df0f173..8381f28f36fc0 100644 --- a/aptos-move/framework/aptos-token/tests/compiler-v2-doc/token_event_store.md +++ b/aptos-move/framework/aptos-token/tests/compiler-v2-doc/token_event_store.md @@ -11,7 +11,7 @@ This module provides utils to add and emit new token events that are not in toke - [Struct `CollectionUriMutateEvent`](#0x3_token_event_store_CollectionUriMutateEvent) - [Struct `CollectionUriMutate`](#0x3_token_event_store_CollectionUriMutate) - [Struct `CollectionMaxiumMutateEvent`](#0x3_token_event_store_CollectionMaxiumMutateEvent) -- [Struct `CollectionMaxiumMutate`](#0x3_token_event_store_CollectionMaxiumMutate) +- [Struct `CollectionMaximumMutate`](#0x3_token_event_store_CollectionMaximumMutate) - [Struct `OptInTransferEvent`](#0x3_token_event_store_OptInTransferEvent) - [Struct `OptInTransfer`](#0x3_token_event_store_OptInTransfer) - [Struct `UriMutationEvent`](#0x3_token_event_store_UriMutationEvent) @@ -25,6 +25,7 @@ This module provides utils to add and emit new token events that are not in toke - [Struct `MaxiumMutateEvent`](#0x3_token_event_store_MaxiumMutateEvent) - [Struct `MaximumMutate`](#0x3_token_event_store_MaximumMutate) - [Resource `TokenEventStoreV1`](#0x3_token_event_store_TokenEventStoreV1) +- [Struct `CollectionMaxiumMutate`](#0x3_token_event_store_CollectionMaxiumMutate) - [Function `initialize_token_event_store`](#0x3_token_event_store_initialize_token_event_store) - [Function `emit_collection_uri_mutate_event`](#0x3_token_event_store_emit_collection_uri_mutate_event) - [Function `emit_collection_description_mutate_event`](#0x3_token_event_store_emit_collection_description_mutate_event) @@ -292,15 +293,15 @@ Event emitted when the collection maximum is mutated - + -## Struct `CollectionMaxiumMutate` +## Struct `CollectionMaximumMutate` Event emitted when the collection maximum is mutated
#[event]
-struct CollectionMaxiumMutate has drop, store
+struct CollectionMaximumMutate has drop, store
 
@@ -1066,6 +1067,53 @@ Event emitted when the token maximum is mutated + + + + +## Struct `CollectionMaxiumMutate` + + + +
#[event]
+#[deprecated]
+struct CollectionMaxiumMutate has drop, store
+
+ + + +
+Fields + + +
+
+creator_addr: address +
+
+ +
+
+collection_name: string::String +
+
+ +
+
+old_maximum: u64 +
+
+ +
+
+new_maximum: u64 +
+
+ +
+
+ +
@@ -1226,7 +1274,7 @@ Emit the collection maximum mutation event let token_event_store = borrow_global_mut<TokenEventStoreV1>(signer::address_of(creator)); if (std::features::module_event_migration_enabled()) { event::emit( - CollectionMaxiumMutate { + CollectionMaximumMutate { creator_addr: signer::address_of(creator), collection_name: collection, old_maximum, diff --git a/aptos-move/framework/move-stdlib/tests/compiler-v2-doc/mem.md b/aptos-move/framework/move-stdlib/tests/compiler-v2-doc/mem.md new file mode 100644 index 0000000000000..b4ac9b3f608be --- /dev/null +++ b/aptos-move/framework/move-stdlib/tests/compiler-v2-doc/mem.md @@ -0,0 +1,115 @@ + + + +# Module `0x1::mem` + +Module with methods for safe memory manipulation. + + +- [Function `swap`](#0x1_mem_swap) +- [Function `replace`](#0x1_mem_replace) +- [Specification](#@Specification_0) + - [Function `swap`](#@Specification_0_swap) + - [Function `replace`](#@Specification_0_replace) + + +
+ + + + + +## Function `swap` + +Swap contents of two passed mutable references. + +Move prevents from having two mutable references to the same value, +so left and right references are always distinct. + + +
public(friend) fun swap<T>(left: &mut T, right: &mut T)
+
+ + + +
+Implementation + + +
public(friend) native fun swap<T>(left: &mut T, right: &mut T);
+
+ + + +
+ + + +## Function `replace` + +Replace the value reference points to with the given new value, +and return the value it had before. + + +
public(friend) fun replace<T>(ref: &mut T, new: T): T
+
+ + + +
+Implementation + + +
public(friend) fun replace<T>(ref: &mut T, new: T): T {
+    swap(ref, &mut new);
+    new
+}
+
+ + + +
+ + + +## Specification + + + + +### Function `swap` + + +
public(friend) fun swap<T>(left: &mut T, right: &mut T)
+
+ + + + +
pragma opaque;
+aborts_if false;
+ensures right == old(left);
+ensures left == old(right);
+
+ + + + + +### Function `replace` + + +
public(friend) fun replace<T>(ref: &mut T, new: T): T
+
+ + + + +
pragma opaque;
+aborts_if false;
+ensures result == old(ref);
+ensures ref == new;
+
+ + +[move-book]: https://aptos.dev/move/book/SUMMARY diff --git a/third_party/move/move-compiler-v2/src/experiments.rs b/third_party/move/move-compiler-v2/src/experiments.rs index a519049690013..fd6174e8231bf 100644 --- a/third_party/move/move-compiler-v2/src/experiments.rs +++ b/third_party/move/move-compiler-v2/src/experiments.rs @@ -271,6 +271,11 @@ pub static EXPERIMENTS: Lazy> = Lazy::new(|| { .to_string(), default: Given(false), }, + Experiment { + name: Experiment::AVOID_STORE_IN_ASSIGNS.to_string(), + description: "Avoid storing to a local during assigns".to_string(), + default: Inherited(Experiment::OPTIMIZE_WAITING_FOR_COMPARE_TESTS.to_string()), + }, ]; experiments .into_iter() @@ -286,6 +291,7 @@ impl Experiment { pub const AST_SIMPLIFY: &'static str = "ast-simplify"; pub const AST_SIMPLIFY_FULL: &'static str = "ast-simplify-full"; pub const ATTACH_COMPILED_MODULE: &'static str = "attach-compiled-module"; + pub const AVOID_STORE_IN_ASSIGNS: &'static str = "avoid-store-in-assigns"; pub const CFG_SIMPLIFICATION: &'static str = "cfg-simplification"; pub const CHECKS: &'static str = "checks"; pub const COPY_PROPAGATION: &'static str = "copy-propagation"; diff --git a/third_party/move/move-compiler-v2/src/file_format_generator/function_generator.rs b/third_party/move/move-compiler-v2/src/file_format_generator/function_generator.rs index 3a61f63bd19e6..85e5e9402fc54 100644 --- a/third_party/move/move-compiler-v2/src/file_format_generator/function_generator.rs +++ b/third_party/move/move-compiler-v2/src/file_format_generator/function_generator.rs @@ -285,9 +285,22 @@ impl<'a> FunctionGenerator<'a> { std::slice::from_ref(source), ); self.abstract_push_args(ctx, vec![*source], Some(mode)); - let local = self.temp_to_local(ctx.fun_ctx, Some(ctx.attr_id), *dest); - self.emit(FF::Bytecode::StLoc(local)); - self.abstract_pop(ctx) + // TODO: the below conditional check is temporary, the plan is to get rid of the `else` + // case if comparison testing is successful. + let options = ctx + .fun_ctx + .module + .env + .get_extension::() + .expect("Options is available"); + if options.experiment_on(Experiment::AVOID_STORE_IN_ASSIGNS) { + self.abstract_pop(ctx); + self.abstract_push_result(ctx, std::slice::from_ref(dest)); + } else { + let local = self.temp_to_local(ctx.fun_ctx, Some(ctx.attr_id), *dest); + self.emit(FF::Bytecode::StLoc(local)); + self.abstract_pop(ctx); + } }, Bytecode::Ret(_, result) => { self.balance_stack_end_of_block(ctx, result); diff --git a/third_party/move/move-compiler-v2/tests/control-flow-simplification/bug-10253.off.exp b/third_party/move/move-compiler-v2/tests/control-flow-simplification/bug-10253.off.exp index dfad2c56753be..fcda55f1a11a3 100644 --- a/third_party/move/move-compiler-v2/tests/control-flow-simplification/bug-10253.off.exp +++ b/third_party/move/move-compiler-v2/tests/control-flow-simplification/bug-10253.off.exp @@ -8,7 +8,6 @@ entry public guess_flips(Arg0: vector) /* def_idx: 0 */ { L1: loc0: &vector L2: loc1: u64 L3: loc2: u64 -L4: loc3: u64 B0: 0: ImmBorrowLoc[0](Arg0: vector) 1: StLoc[1](loc0: &vector) @@ -16,80 +15,71 @@ B0: 3: StLoc[2](loc1: u64) B1: 4: CopyLoc[2](loc1: u64) - 5: StLoc[3](loc2: u64) - 6: CopyLoc[1](loc0: &vector) - 7: VecLen(2) - 8: StLoc[4](loc3: u64) - 9: MoveLoc[3](loc2: u64) - 10: MoveLoc[4](loc3: u64) - 11: Lt - 12: BrFalse(28) + 5: CopyLoc[1](loc0: &vector) + 6: VecLen(2) + 7: Lt + 8: BrFalse(24) B2: - 13: CopyLoc[1](loc0: &vector) - 14: CopyLoc[2](loc1: u64) - 15: VecImmBorrow(2) - 16: ReadRef - 17: LdU8(0) - 18: Neq - 19: BrFalse(23) + 9: CopyLoc[1](loc0: &vector) + 10: CopyLoc[2](loc1: u64) + 11: VecImmBorrow(2) + 12: ReadRef + 13: LdU8(0) + 14: Neq + 15: BrFalse(19) B3: - 20: MoveLoc[1](loc0: &vector) - 21: Pop - 22: Branch(32) + 16: MoveLoc[1](loc0: &vector) + 17: Pop + 18: Branch(28) B4: - 23: MoveLoc[2](loc1: u64) - 24: LdU64(1) - 25: Add - 26: StLoc[2](loc1: u64) - 27: Branch(31) + 19: MoveLoc[2](loc1: u64) + 20: LdU64(1) + 21: Add + 22: StLoc[2](loc1: u64) + 23: Branch(27) B5: - 28: MoveLoc[1](loc0: &vector) - 29: Pop - 30: Branch(32) + 24: MoveLoc[1](loc0: &vector) + 25: Pop + 26: Branch(28) B6: - 31: Branch(4) + 27: Branch(4) B7: - 32: Ret + 28: Ret } entry public guess_flips_directly(Arg0: vector) /* def_idx: 1 */ { L1: loc0: u64 L2: loc1: u64 -L3: loc2: u64 B0: 0: LdU64(0) 1: StLoc[1](loc0: u64) B1: 2: CopyLoc[1](loc0: u64) - 3: StLoc[2](loc1: u64) - 4: ImmBorrowLoc[0](Arg0: vector) - 5: VecLen(2) - 6: StLoc[3](loc2: u64) - 7: MoveLoc[2](loc1: u64) - 8: MoveLoc[3](loc2: u64) - 9: Lt - 10: BrFalse(24) + 3: ImmBorrowLoc[0](Arg0: vector) + 4: VecLen(2) + 5: Lt + 6: BrFalse(20) B2: - 11: ImmBorrowLoc[0](Arg0: vector) - 12: CopyLoc[1](loc0: u64) - 13: VecImmBorrow(2) - 14: ReadRef - 15: LdU8(0) - 16: Neq - 17: BrFalse(19) + 7: ImmBorrowLoc[0](Arg0: vector) + 8: CopyLoc[1](loc0: u64) + 9: VecImmBorrow(2) + 10: ReadRef + 11: LdU8(0) + 12: Neq + 13: BrFalse(15) B3: - 18: Branch(26) + 14: Branch(22) B4: - 19: MoveLoc[1](loc0: u64) - 20: LdU64(1) - 21: Add - 22: StLoc[1](loc0: u64) - 23: Branch(25) + 15: MoveLoc[1](loc0: u64) + 16: LdU64(1) + 17: Add + 18: StLoc[1](loc0: u64) + 19: Branch(21) B5: - 24: Branch(26) + 20: Branch(22) B6: - 25: Branch(2) + 21: Branch(2) B7: - 26: Ret + 22: Ret } entry public guess_with_break_without_inline(Arg0: vector) /* def_idx: 2 */ { B0: @@ -101,7 +91,6 @@ entry public guess_without_break_with_inline(Arg0: vector) /* def_idx: 3 */ L1: loc0: &vector L2: loc1: u64 L3: loc2: u64 -L4: loc3: u64 B0: 0: ImmBorrowLoc[0](Arg0: vector) 1: StLoc[1](loc0: &vector) @@ -109,87 +98,78 @@ B0: 3: StLoc[2](loc1: u64) B1: 4: CopyLoc[2](loc1: u64) - 5: StLoc[3](loc2: u64) - 6: CopyLoc[1](loc0: &vector) - 7: VecLen(2) - 8: StLoc[4](loc3: u64) - 9: MoveLoc[3](loc2: u64) - 10: MoveLoc[4](loc3: u64) - 11: Lt - 12: BrFalse(30) + 5: CopyLoc[1](loc0: &vector) + 6: VecLen(2) + 7: Lt + 8: BrFalse(26) B2: - 13: CopyLoc[1](loc0: &vector) - 14: CopyLoc[2](loc1: u64) - 15: VecImmBorrow(2) - 16: ReadRef - 17: LdU8(0) - 18: Eq - 19: BrFalse(21) + 9: CopyLoc[1](loc0: &vector) + 10: CopyLoc[2](loc1: u64) + 11: VecImmBorrow(2) + 12: ReadRef + 13: LdU8(0) + 14: Eq + 15: BrFalse(17) B3: - 20: Branch(25) + 16: Branch(21) B4: - 21: MoveLoc[1](loc0: &vector) - 22: Pop - 23: LdU64(3) - 24: Abort + 17: MoveLoc[1](loc0: &vector) + 18: Pop + 19: LdU64(3) + 20: Abort B5: - 25: MoveLoc[2](loc1: u64) - 26: LdU64(1) - 27: Add - 28: StLoc[2](loc1: u64) - 29: Branch(33) + 21: MoveLoc[2](loc1: u64) + 22: LdU64(1) + 23: Add + 24: StLoc[2](loc1: u64) + 25: Branch(29) B6: - 30: MoveLoc[1](loc0: &vector) - 31: Pop - 32: Branch(34) + 26: MoveLoc[1](loc0: &vector) + 27: Pop + 28: Branch(30) B7: - 33: Branch(4) + 29: Branch(4) B8: - 34: Ret + 30: Ret } loops_with_break_no_inline(Arg0: &vector) /* def_idx: 4 */ { L1: loc0: u64 L2: loc1: u64 -L3: loc2: u64 B0: 0: LdU64(0) 1: StLoc[1](loc0: u64) B1: 2: CopyLoc[1](loc0: u64) - 3: StLoc[2](loc1: u64) - 4: CopyLoc[0](Arg0: &vector) - 5: VecLen(2) - 6: StLoc[3](loc2: u64) - 7: MoveLoc[2](loc1: u64) - 8: MoveLoc[3](loc2: u64) - 9: Lt - 10: BrFalse(26) + 3: CopyLoc[0](Arg0: &vector) + 4: VecLen(2) + 5: Lt + 6: BrFalse(22) B2: - 11: CopyLoc[0](Arg0: &vector) - 12: CopyLoc[1](loc0: u64) - 13: VecImmBorrow(2) - 14: ReadRef - 15: LdU8(0) - 16: Neq - 17: BrFalse(21) + 7: CopyLoc[0](Arg0: &vector) + 8: CopyLoc[1](loc0: u64) + 9: VecImmBorrow(2) + 10: ReadRef + 11: LdU8(0) + 12: Neq + 13: BrFalse(17) B3: - 18: MoveLoc[0](Arg0: &vector) - 19: Pop - 20: Branch(30) + 14: MoveLoc[0](Arg0: &vector) + 15: Pop + 16: Branch(26) B4: - 21: MoveLoc[1](loc0: u64) - 22: LdU64(1) - 23: Add - 24: StLoc[1](loc0: u64) - 25: Branch(29) + 17: MoveLoc[1](loc0: u64) + 18: LdU64(1) + 19: Add + 20: StLoc[1](loc0: u64) + 21: Branch(25) B5: - 26: MoveLoc[0](Arg0: &vector) - 27: Pop - 28: Branch(30) + 22: MoveLoc[0](Arg0: &vector) + 23: Pop + 24: Branch(26) B6: - 29: Branch(2) + 25: Branch(2) B7: - 30: Ret + 26: Ret } test_guess_directly() /* def_idx: 5 */ { B0: diff --git a/third_party/move/move-compiler-v2/tests/control-flow-simplification/bug-10253.on.exp b/third_party/move/move-compiler-v2/tests/control-flow-simplification/bug-10253.on.exp index f5fce68026abf..11a6f4028f8eb 100644 --- a/third_party/move/move-compiler-v2/tests/control-flow-simplification/bug-10253.on.exp +++ b/third_party/move/move-compiler-v2/tests/control-flow-simplification/bug-10253.on.exp @@ -234,7 +234,6 @@ entry public guess_flips(Arg0: vector) /* def_idx: 0 */ { L1: loc0: &vector L2: loc1: u64 L3: loc2: u64 -L4: loc3: u64 B0: 0: ImmBorrowLoc[0](Arg0: vector) 1: StLoc[1](loc0: &vector) @@ -242,75 +241,66 @@ B0: 3: StLoc[2](loc1: u64) B1: 4: CopyLoc[2](loc1: u64) - 5: StLoc[3](loc2: u64) - 6: CopyLoc[1](loc0: &vector) - 7: VecLen(2) - 8: StLoc[4](loc3: u64) - 9: MoveLoc[3](loc2: u64) - 10: MoveLoc[4](loc3: u64) - 11: Lt - 12: BrFalse(28) + 5: CopyLoc[1](loc0: &vector) + 6: VecLen(2) + 7: Lt + 8: BrFalse(24) B2: - 13: CopyLoc[1](loc0: &vector) - 14: CopyLoc[2](loc1: u64) - 15: VecImmBorrow(2) - 16: ReadRef - 17: LdU8(0) - 18: Neq - 19: BrFalse(23) + 9: CopyLoc[1](loc0: &vector) + 10: CopyLoc[2](loc1: u64) + 11: VecImmBorrow(2) + 12: ReadRef + 13: LdU8(0) + 14: Neq + 15: BrFalse(19) B3: - 20: MoveLoc[1](loc0: &vector) - 21: Pop + 16: MoveLoc[1](loc0: &vector) + 17: Pop B4: - 22: Ret + 18: Ret B5: - 23: MoveLoc[2](loc1: u64) - 24: LdU64(1) - 25: Add - 26: StLoc[2](loc1: u64) - 27: Branch(4) + 19: MoveLoc[2](loc1: u64) + 20: LdU64(1) + 21: Add + 22: StLoc[2](loc1: u64) + 23: Branch(4) B6: - 28: MoveLoc[1](loc0: &vector) - 29: Pop - 30: Branch(22) + 24: MoveLoc[1](loc0: &vector) + 25: Pop + 26: Branch(18) } entry public guess_flips_directly(Arg0: vector) /* def_idx: 1 */ { L1: loc0: u64 L2: loc1: u64 -L3: loc2: u64 B0: 0: LdU64(0) 1: StLoc[1](loc0: u64) B1: 2: CopyLoc[1](loc0: u64) - 3: StLoc[2](loc1: u64) - 4: ImmBorrowLoc[0](Arg0: vector) - 5: VecLen(2) - 6: StLoc[3](loc2: u64) - 7: MoveLoc[2](loc1: u64) - 8: MoveLoc[3](loc2: u64) - 9: Lt - 10: BrTrue(12) + 3: ImmBorrowLoc[0](Arg0: vector) + 4: VecLen(2) + 5: Lt + 6: BrTrue(8) B2: - 11: Branch(20) + 7: Branch(16) B3: - 12: ImmBorrowLoc[0](Arg0: vector) - 13: CopyLoc[1](loc0: u64) - 14: VecImmBorrow(2) - 15: ReadRef - 16: LdU8(0) - 17: Neq - 18: BrFalse(21) + 8: ImmBorrowLoc[0](Arg0: vector) + 9: CopyLoc[1](loc0: u64) + 10: VecImmBorrow(2) + 11: ReadRef + 12: LdU8(0) + 13: Neq + 14: BrFalse(17) B4: - 19: Branch(20) + 15: Branch(16) B5: - 20: Ret + 16: Ret B6: - 21: MoveLoc[1](loc0: u64) - 22: LdU64(1) - 23: Add - 24: StLoc[1](loc0: u64) - 25: Branch(2) + 17: MoveLoc[1](loc0: u64) + 18: LdU64(1) + 19: Add + 20: StLoc[1](loc0: u64) + 21: Branch(2) } entry public guess_with_break_without_inline(Arg0: vector) /* def_idx: 2 */ { B0: @@ -322,7 +312,6 @@ entry public guess_without_break_with_inline(Arg0: vector) /* def_idx: 3 */ L1: loc0: &vector L2: loc1: u64 L3: loc2: u64 -L4: loc3: u64 B0: 0: ImmBorrowLoc[0](Arg0: vector) 1: StLoc[1](loc0: &vector) @@ -330,78 +319,69 @@ B0: 3: StLoc[2](loc1: u64) B1: 4: CopyLoc[2](loc1: u64) - 5: StLoc[3](loc2: u64) - 6: CopyLoc[1](loc0: &vector) - 7: VecLen(2) - 8: StLoc[4](loc3: u64) - 9: MoveLoc[3](loc2: u64) - 10: MoveLoc[4](loc3: u64) - 11: Lt - 12: BrFalse(29) + 5: CopyLoc[1](loc0: &vector) + 6: VecLen(2) + 7: Lt + 8: BrFalse(25) B2: - 13: CopyLoc[1](loc0: &vector) - 14: CopyLoc[2](loc1: u64) - 15: VecImmBorrow(2) - 16: ReadRef - 17: LdU8(0) - 18: Eq - 19: BrFalse(25) + 9: CopyLoc[1](loc0: &vector) + 10: CopyLoc[2](loc1: u64) + 11: VecImmBorrow(2) + 12: ReadRef + 13: LdU8(0) + 14: Eq + 15: BrFalse(21) B3: - 20: MoveLoc[2](loc1: u64) - 21: LdU64(1) - 22: Add - 23: StLoc[2](loc1: u64) - 24: Branch(4) + 16: MoveLoc[2](loc1: u64) + 17: LdU64(1) + 18: Add + 19: StLoc[2](loc1: u64) + 20: Branch(4) B4: + 21: MoveLoc[1](loc0: &vector) + 22: Pop + 23: LdU64(3) + 24: Abort +B5: 25: MoveLoc[1](loc0: &vector) 26: Pop - 27: LdU64(3) - 28: Abort -B5: - 29: MoveLoc[1](loc0: &vector) - 30: Pop - 31: Ret + 27: Ret } loops_with_break_no_inline(Arg0: &vector) /* def_idx: 4 */ { L1: loc0: u64 L2: loc1: u64 -L3: loc2: u64 B0: 0: LdU64(0) 1: StLoc[1](loc0: u64) B1: 2: CopyLoc[1](loc0: u64) - 3: StLoc[2](loc1: u64) - 4: CopyLoc[0](Arg0: &vector) - 5: VecLen(2) - 6: StLoc[3](loc2: u64) - 7: MoveLoc[2](loc1: u64) - 8: MoveLoc[3](loc2: u64) - 9: Lt - 10: BrFalse(26) + 3: CopyLoc[0](Arg0: &vector) + 4: VecLen(2) + 5: Lt + 6: BrFalse(22) B2: - 11: CopyLoc[0](Arg0: &vector) - 12: CopyLoc[1](loc0: u64) - 13: VecImmBorrow(2) - 14: ReadRef - 15: LdU8(0) - 16: Neq - 17: BrFalse(21) + 7: CopyLoc[0](Arg0: &vector) + 8: CopyLoc[1](loc0: u64) + 9: VecImmBorrow(2) + 10: ReadRef + 11: LdU8(0) + 12: Neq + 13: BrFalse(17) B3: - 18: MoveLoc[0](Arg0: &vector) - 19: Pop + 14: MoveLoc[0](Arg0: &vector) + 15: Pop B4: - 20: Ret + 16: Ret B5: - 21: MoveLoc[1](loc0: u64) - 22: LdU64(1) - 23: Add - 24: StLoc[1](loc0: u64) - 25: Branch(2) + 17: MoveLoc[1](loc0: u64) + 18: LdU64(1) + 19: Add + 20: StLoc[1](loc0: u64) + 21: Branch(2) B6: - 26: MoveLoc[0](Arg0: &vector) - 27: Pop - 28: Branch(20) + 22: MoveLoc[0](Arg0: &vector) + 23: Pop + 24: Branch(16) } test_guess_directly() /* def_idx: 5 */ { B0: diff --git a/third_party/move/move-compiler-v2/tests/control-flow-simplification/jump-label.off.exp b/third_party/move/move-compiler-v2/tests/control-flow-simplification/jump-label.off.exp index 7894953e360c3..af6586a3f5112 100644 --- a/third_party/move/move-compiler-v2/tests/control-flow-simplification/jump-label.off.exp +++ b/third_party/move/move-compiler-v2/tests/control-flow-simplification/jump-label.off.exp @@ -10,55 +10,46 @@ use 0000000000000000000000000000000000000000000000000000000000000001::string; test(Arg0: vector): Ty0 /* def_idx: 0 */ { L1: loc0: String L2: loc1: String -L3: loc2: String B0: 0: Call foo(): String 1: StLoc[1](loc0: String) 2: CopyLoc[1](loc0: String) - 3: StLoc[2](loc1: String) - 4: LdConst[0](Vector(U8): [4, 98, 111, 111, 108]) - 5: Call string::utf8(vector): String - 6: StLoc[3](loc2: String) - 7: MoveLoc[2](loc1: String) - 8: MoveLoc[3](loc2: String) - 9: Eq - 10: BrFalse(15) + 3: LdConst[0](Vector(U8): [4, 98, 111, 111, 108]) + 4: Call string::utf8(vector): String + 5: Eq + 6: BrFalse(11) B1: - 11: MoveLoc[0](Arg0: vector) - 12: Call baz(vector): bool - 13: Call bar(bool): Ty0 - 14: Ret + 7: MoveLoc[0](Arg0: vector) + 8: Call baz(vector): bool + 9: Call bar(bool): Ty0 + 10: Ret B2: - 15: CopyLoc[1](loc0: String) - 16: StLoc[2](loc1: String) - 17: LdConst[1](Vector(U8): [2, 117, 56]) - 18: Call string::utf8(vector): String - 19: StLoc[3](loc2: String) - 20: MoveLoc[2](loc1: String) - 21: MoveLoc[3](loc2: String) - 22: Eq - 23: BrFalse(28) + 11: CopyLoc[1](loc0: String) + 12: LdConst[1](Vector(U8): [2, 117, 56]) + 13: Call string::utf8(vector): String + 14: Eq + 15: BrFalse(20) B3: - 24: MoveLoc[0](Arg0: vector) - 25: Call baz(vector): bool - 26: Call bar(bool): Ty0 - 27: Ret + 16: MoveLoc[0](Arg0: vector) + 17: Call baz(vector): bool + 18: Call bar(bool): Ty0 + 19: Ret B4: - 28: LdConst[2](Vector(U8): [3, 117, 54, 52]) - 29: Call string::utf8(vector): String - 30: StLoc[2](loc1: String) - 31: MoveLoc[1](loc0: String) - 32: MoveLoc[2](loc1: String) - 33: Eq - 34: BrFalse(39) + 20: LdConst[2](Vector(U8): [3, 117, 54, 52]) + 21: Call string::utf8(vector): String + 22: StLoc[2](loc1: String) + 23: MoveLoc[1](loc0: String) + 24: MoveLoc[2](loc1: String) + 25: Eq + 26: BrFalse(31) B5: - 35: MoveLoc[0](Arg0: vector) - 36: Call baz(vector): bool - 37: Call bar(bool): Ty0 - 38: Ret + 27: MoveLoc[0](Arg0: vector) + 28: Call baz(vector): bool + 29: Call bar(bool): Ty0 + 30: Ret B6: - 39: LdU64(0) - 40: Abort + 31: LdU64(0) + 32: Abort } bar(Arg0: bool): Ty0 /* def_idx: 1 */ { B0: diff --git a/third_party/move/move-compiler-v2/tests/control-flow-simplification/jump-label.on.exp b/third_party/move/move-compiler-v2/tests/control-flow-simplification/jump-label.on.exp index 5ad35eeb9ecae..23438ea680516 100644 --- a/third_party/move/move-compiler-v2/tests/control-flow-simplification/jump-label.on.exp +++ b/third_party/move/move-compiler-v2/tests/control-flow-simplification/jump-label.on.exp @@ -94,55 +94,46 @@ use 0000000000000000000000000000000000000000000000000000000000000001::string; test(Arg0: vector): Ty0 /* def_idx: 0 */ { L1: loc0: String L2: loc1: String -L3: loc2: String B0: 0: Call foo(): String 1: StLoc[1](loc0: String) 2: CopyLoc[1](loc0: String) - 3: StLoc[2](loc1: String) - 4: LdConst[0](Vector(U8): [4, 98, 111, 111, 108]) - 5: Call string::utf8(vector): String - 6: StLoc[3](loc2: String) - 7: MoveLoc[2](loc1: String) - 8: MoveLoc[3](loc2: String) - 9: Eq - 10: BrFalse(15) + 3: LdConst[0](Vector(U8): [4, 98, 111, 111, 108]) + 4: Call string::utf8(vector): String + 5: Eq + 6: BrFalse(11) B1: - 11: MoveLoc[0](Arg0: vector) - 12: Call baz(vector): bool - 13: Call bar(bool): Ty0 - 14: Ret + 7: MoveLoc[0](Arg0: vector) + 8: Call baz(vector): bool + 9: Call bar(bool): Ty0 + 10: Ret B2: - 15: CopyLoc[1](loc0: String) - 16: StLoc[2](loc1: String) - 17: LdConst[1](Vector(U8): [2, 117, 56]) - 18: Call string::utf8(vector): String - 19: StLoc[3](loc2: String) - 20: MoveLoc[2](loc1: String) - 21: MoveLoc[3](loc2: String) - 22: Eq - 23: BrFalse(28) + 11: CopyLoc[1](loc0: String) + 12: LdConst[1](Vector(U8): [2, 117, 56]) + 13: Call string::utf8(vector): String + 14: Eq + 15: BrFalse(20) B3: - 24: MoveLoc[0](Arg0: vector) - 25: Call baz(vector): bool - 26: Call bar(bool): Ty0 - 27: Ret + 16: MoveLoc[0](Arg0: vector) + 17: Call baz(vector): bool + 18: Call bar(bool): Ty0 + 19: Ret B4: - 28: LdConst[2](Vector(U8): [3, 117, 54, 52]) - 29: Call string::utf8(vector): String - 30: StLoc[2](loc1: String) - 31: MoveLoc[1](loc0: String) - 32: MoveLoc[2](loc1: String) - 33: Eq - 34: BrFalse(39) + 20: LdConst[2](Vector(U8): [3, 117, 54, 52]) + 21: Call string::utf8(vector): String + 22: StLoc[2](loc1: String) + 23: MoveLoc[1](loc0: String) + 24: MoveLoc[2](loc1: String) + 25: Eq + 26: BrFalse(31) B5: - 35: MoveLoc[0](Arg0: vector) - 36: Call baz(vector): bool - 37: Call bar(bool): Ty0 - 38: Ret + 27: MoveLoc[0](Arg0: vector) + 28: Call baz(vector): bool + 29: Call bar(bool): Ty0 + 30: Ret B6: - 39: LdU64(0) - 40: Abort + 31: LdU64(0) + 32: Abort } bar(Arg0: bool): Ty0 /* def_idx: 1 */ { B0: diff --git a/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_06.exp b/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_06.exp index f55c5a103ba6d..937040361d411 100644 --- a/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_06.exp +++ b/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_06.exp @@ -187,7 +187,6 @@ B0: public test(Arg0: &mut S, Arg1: S) /* def_idx: 3 */ { L2: loc0: u64 L3: loc1: u64 -L4: loc2: &mut S B0: 0: LdU64(0) 1: StLoc[2](loc0: u64) @@ -195,28 +194,24 @@ B1: 2: CopyLoc[2](loc0: u64) 3: LdU64(42) 4: Lt - 5: BrFalse(20) + 5: BrFalse(16) B2: 6: CopyLoc[0](Arg0: &mut S) - 7: StLoc[4](loc2: &mut S) - 8: MutBorrowLoc[1](Arg1: S) - 9: CopyLoc[2](loc0: u64) - 10: Call bar(&mut S, u64): u64 - 11: StLoc[3](loc1: u64) - 12: MoveLoc[4](loc2: &mut S) - 13: MoveLoc[3](loc1: u64) - 14: Call foo(&mut S, u64) - 15: MoveLoc[2](loc0: u64) - 16: LdU64(1) - 17: Add - 18: StLoc[2](loc0: u64) - 19: Branch(2) + 7: MutBorrowLoc[1](Arg1: S) + 8: CopyLoc[2](loc0: u64) + 9: Call bar(&mut S, u64): u64 + 10: Call foo(&mut S, u64) + 11: MoveLoc[2](loc0: u64) + 12: LdU64(1) + 13: Add + 14: StLoc[2](loc0: u64) + 15: Branch(2) B3: - 20: MoveLoc[0](Arg0: &mut S) - 21: Pop - 22: MoveLoc[1](Arg1: S) - 23: Call destroy(S) - 24: Ret + 16: MoveLoc[0](Arg0: &mut S) + 17: Pop + 18: MoveLoc[1](Arg1: S) + 19: Call destroy(S) + 20: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/eager-pushes/move_stdlib_reduced.exp b/third_party/move/move-compiler-v2/tests/eager-pushes/move_stdlib_reduced.exp index 5ff4fea83d589..2ebaeb0bea084 100644 --- a/third_party/move/move-compiler-v2/tests/eager-pushes/move_stdlib_reduced.exp +++ b/third_party/move/move-compiler-v2/tests/eager-pushes/move_stdlib_reduced.exp @@ -119,29 +119,24 @@ B0: } public foo(Arg0: &mut u64, Arg1: u64) /* def_idx: 1 */ { L2: loc0: u64 -L3: loc1: &mut u64 B0: 0: CopyLoc[1](Arg1: u64) 1: LdU64(0) 2: Gt - 3: BrFalse(16) + 3: BrFalse(12) B1: 4: CopyLoc[0](Arg0: &mut u64) - 5: StLoc[3](loc1: &mut u64) - 6: Call one(): u64 - 7: StLoc[2](loc0: u64) - 8: MoveLoc[3](loc1: &mut u64) - 9: MoveLoc[2](loc0: u64) - 10: Call bar(&mut u64, u64) - 11: MoveLoc[1](Arg1: u64) - 12: LdU64(1) - 13: Sub - 14: StLoc[1](Arg1: u64) - 15: Branch(0) + 5: Call one(): u64 + 6: Call bar(&mut u64, u64) + 7: MoveLoc[1](Arg1: u64) + 8: LdU64(1) + 9: Sub + 10: StLoc[1](Arg1: u64) + 11: Branch(0) B2: - 16: MoveLoc[0](Arg0: &mut u64) - 17: Pop - 18: Ret + 12: MoveLoc[0](Arg0: &mut u64) + 13: Pop + 14: Ret } one(): u64 /* def_idx: 2 */ { B0: diff --git a/third_party/move/move-compiler-v2/tests/eager-pushes/txn_reduced_01.exp b/third_party/move/move-compiler-v2/tests/eager-pushes/txn_reduced_01.exp new file mode 100644 index 0000000000000..a36517680038a --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/eager-pushes/txn_reduced_01.exp @@ -0,0 +1,176 @@ +============ initial bytecode ================ + +[variant baseline] +fun m::call_other($t0: &signer, $t1: address, $t2: u64) { + 0: return () +} + + +[variant baseline] +public fun m::test($t0: &signer, $t1: vector
, $t2: vector) { + var $t3: u64 + var $t4: &vector
+ var $t5: u64 + var $t6: bool + var $t7: &address + var $t8: &vector
+ var $t9: &u64 + var $t10: &vector + var $t11: address + var $t12: u64 + var $t13: u64 + var $t14: u64 + 0: $t4 := borrow_local($t1) + 1: $t3 := vector::length
($t4) + 2: $t5 := 0 + 3: label L0 + 4: $t6 := <($t5, $t3) + 5: if ($t6) goto 6 else goto 18 + 6: label L2 + 7: $t8 := borrow_local($t1) + 8: $t7 := vector::borrow
($t8, $t5) + 9: $t10 := borrow_local($t2) + 10: $t9 := vector::borrow($t10, $t5) + 11: $t11 := read_ref($t7) + 12: $t12 := read_ref($t9) + 13: m::call_other($t0, $t11, $t12) + 14: $t14 := 1 + 15: $t13 := +($t5, $t14) + 16: $t5 := infer($t13) + 17: goto 20 + 18: label L3 + 19: goto 22 + 20: label L4 + 21: goto 3 + 22: label L1 + 23: return () +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun m::call_other($t0: &signer, $t1: address, $t2: u64) { + # live vars: $t0, $t1, $t2 + 0: drop($t0) + # live vars: + 1: return () +} + + +[variant baseline] +public fun m::test($t0: &signer, $t1: vector
, $t2: vector) { + var $t3: u64 + var $t4: &vector
+ var $t5: u64 + var $t6: bool + var $t7: &address + var $t8: &vector
[unused] + var $t9: &u64 + var $t10: &vector + var $t11: address + var $t12: u64 + var $t13: u64 [unused] + var $t14: u64 [unused] + # live vars: $t0, $t1, $t2 + 0: $t4 := borrow_local($t1) + # live vars: $t0, $t1, $t2, $t4 + 1: $t3 := vector::length
($t4) + # live vars: $t0, $t1, $t2, $t3 + 2: $t5 := 0 + # live vars: $t0, $t1, $t2, $t3, $t5 + 3: label L0 + # live vars: $t0, $t1, $t2, $t3, $t5 + 4: $t6 := <($t5, $t3) + # live vars: $t0, $t1, $t2, $t3, $t5, $t6 + 5: if ($t6) goto 6 else goto 18 + # live vars: $t0, $t1, $t2, $t3, $t5 + 6: label L2 + # live vars: $t0, $t1, $t2, $t3, $t5 + 7: $t4 := borrow_local($t1) + # live vars: $t0, $t1, $t2, $t3, $t4, $t5 + 8: $t7 := vector::borrow
($t4, $t5) + # live vars: $t0, $t1, $t2, $t3, $t5, $t7 + 9: $t10 := borrow_local($t2) + # live vars: $t0, $t1, $t2, $t3, $t5, $t7, $t10 + 10: $t9 := vector::borrow($t10, $t5) + # live vars: $t0, $t1, $t2, $t3, $t5, $t7, $t9 + 11: $t11 := read_ref($t7) + # live vars: $t0, $t1, $t2, $t3, $t5, $t9, $t11 + 12: $t12 := read_ref($t9) + # live vars: $t0, $t1, $t2, $t3, $t5, $t11, $t12 + 13: m::call_other($t0, $t11, $t12) + # live vars: $t0, $t1, $t2, $t3, $t5 + 14: $t12 := 1 + # live vars: $t0, $t1, $t2, $t3, $t5, $t12 + 15: $t12 := +($t5, $t12) + # live vars: $t0, $t1, $t2, $t3, $t12 + 16: $t5 := move($t12) + # live vars: $t0, $t1, $t2, $t3, $t5 + 17: goto 3 + # live vars: $t0, $t1, $t2, $t3, $t5 + 18: label L3 + # live vars: $t0 + 19: drop($t0) + # live vars: + 20: return () +} + + +============ disassembled file-format ================== +// Move bytecode v7 +module c0ffee.m { + + +call_other(Arg0: &signer, Arg1: address, Arg2: u64) /* def_idx: 0 */ { +B0: + 0: MoveLoc[0](Arg0: &signer) + 1: Pop + 2: Ret +} +public test(Arg0: &signer, Arg1: vector
, Arg2: vector) /* def_idx: 1 */ { +L3: loc0: u64 +L4: loc1: u64 +L5: loc2: &u64 +L6: loc3: &address +L7: loc4: u64 +L8: loc5: address +B0: + 0: ImmBorrowLoc[1](Arg1: vector
) + 1: VecLen(3) + 2: StLoc[3](loc0: u64) + 3: LdU64(0) + 4: StLoc[4](loc1: u64) +B1: + 5: CopyLoc[4](loc1: u64) + 6: CopyLoc[3](loc0: u64) + 7: Lt + 8: BrFalse(30) +B2: + 9: ImmBorrowLoc[1](Arg1: vector
) + 10: CopyLoc[4](loc1: u64) + 11: VecImmBorrow(3) + 12: ImmBorrowLoc[2](Arg2: vector) + 13: CopyLoc[4](loc1: u64) + 14: VecImmBorrow(4) + 15: StLoc[5](loc2: &u64) + 16: ReadRef + 17: MoveLoc[5](loc2: &u64) + 18: ReadRef + 19: StLoc[7](loc4: u64) + 20: StLoc[8](loc5: address) + 21: CopyLoc[0](Arg0: &signer) + 22: MoveLoc[8](loc5: address) + 23: MoveLoc[7](loc4: u64) + 24: Call call_other(&signer, address, u64) + 25: MoveLoc[4](loc1: u64) + 26: LdU64(1) + 27: Add + 28: StLoc[4](loc1: u64) + 29: Branch(5) +B3: + 30: MoveLoc[0](Arg0: &signer) + 31: Pop + 32: Ret +} +} +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/eager-pushes/txn_reduced_01.move b/third_party/move/move-compiler-v2/tests/eager-pushes/txn_reduced_01.move new file mode 100644 index 0000000000000..362a29eea4abe --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/eager-pushes/txn_reduced_01.move @@ -0,0 +1,16 @@ +module 0xc0ffee::m { + use std::vector; + + public fun test(from: &signer, to_vec: vector
, amount_vec: vector) { + let len = vector::length(&to_vec); + let i = 0; + while (i < len) { + let to = vector::borrow(&to_vec, i); + let amount = vector::borrow(&amount_vec, i); + call_other(from, *to, *amount); + i = i + 1; + } + } + + fun call_other(_from: &signer, _to: address, _amount: u64) {} +} diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/bug_14762.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/bug_14762.opt.exp index cf9cf708cd9e3..d04e138c63dba 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/bug_14762.opt.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/bug_14762.opt.exp @@ -23,10 +23,9 @@ L3: loc1: bool L4: loc2: u64 L5: loc3: u64 L6: loc4: u64 -L7: loc5: bool -L8: loc6: u64 +L7: loc5: u64 +L8: loc6: bool L9: loc7: Option -L10: loc8: Option B0: 0: CopyLoc[0](Arg0: &mut S) 1: ImmBorrowField[0](S.entries: vector) @@ -55,7 +54,7 @@ B3: 21: ReadRef 22: CopyLoc[1](Arg1: vector) 23: Eq - 24: BrFalse(53) + 24: BrFalse(51) B4: 25: LdTrue 26: StLoc[3](loc1: bool) @@ -66,37 +65,35 @@ B5: 30: MoveLoc[2](loc0: &vector) 31: Pop 32: MoveLoc[3](loc1: bool) - 33: StLoc[7](loc5: bool) - 34: MoveLoc[4](loc2: u64) - 35: StLoc[8](loc6: u64) - 36: MoveLoc[7](loc5: bool) - 37: BrFalse(48) + 33: MoveLoc[4](loc2: u64) + 34: StLoc[7](loc5: u64) + 35: StLoc[8](loc6: bool) + 36: MoveLoc[8](loc6: bool) + 37: BrFalse(46) B6: 38: MoveLoc[0](Arg0: &mut S) 39: MutBorrowField[0](S.entries: vector) - 40: MoveLoc[8](loc6: u64) + 40: MoveLoc[7](loc5: u64) 41: Call vector::remove(&mut vector, u64): T 42: Call option::some(T): Option 43: StLoc[9](loc7: Option) B7: 44: MoveLoc[9](loc7: Option) - 45: StLoc[10](loc8: Option) - 46: MoveLoc[10](loc8: Option) - 47: Ret + 45: Ret B8: - 48: MoveLoc[0](Arg0: &mut S) - 49: Pop - 50: Call option::none(): Option - 51: StLoc[9](loc7: Option) - 52: Branch(44) + 46: MoveLoc[0](Arg0: &mut S) + 47: Pop + 48: Call option::none(): Option + 49: StLoc[9](loc7: Option) + 50: Branch(44) B9: - 53: LdU64(1) - 54: StLoc[8](loc6: u64) - 55: MoveLoc[5](loc3: u64) - 56: MoveLoc[8](loc6: u64) - 57: Add - 58: StLoc[5](loc3: u64) - 59: Branch(12) + 51: LdU64(1) + 52: StLoc[7](loc5: u64) + 53: MoveLoc[5](loc3: u64) + 54: MoveLoc[7](loc5: u64) + 55: Add + 56: StLoc[5](loc3: u64) + 57: Branch(12) } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/fields.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/fields.opt.exp index e5a00ea3e8bf8..bddcd323020fa 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/fields.opt.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/fields.opt.exp @@ -28,7 +28,6 @@ B0: } write_local_direct(): S /* def_idx: 2 */ { L0: loc0: S -L1: loc1: S B0: 0: LdU64(0) 1: LdU64(0) @@ -48,7 +47,6 @@ L0: loc0: S L1: loc1: u64 L2: loc2: &mut S L3: loc3: &mut u64 -L4: loc4: S B0: 0: LdU64(0) 1: LdU64(0) @@ -75,7 +73,6 @@ B0: 5: Ret } write_val(Arg0: S): S /* def_idx: 5 */ { -L1: loc0: S B0: 0: LdU64(42) 1: MutBorrowLoc[0](Arg0: S) diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/vector.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/vector.opt.exp index 86fe0b29dd1f5..59b0000ee2d3c 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/vector.opt.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/vector.opt.exp @@ -10,8 +10,7 @@ use 0000000000000000000000000000000000000000000000000000000000000001::vector as public remove(Arg0: &mut vector, Arg1: u64): Ty0 /* def_idx: 0 */ { L2: loc0: u64 L3: loc1: u64 -L4: loc2: &mut vector -L5: loc3: u64 +L4: loc2: u64 B0: 0: CopyLoc[0](Arg0: &mut vector) 1: FreezeRef @@ -35,27 +34,21 @@ B3: 16: CopyLoc[1](Arg1: u64) 17: CopyLoc[2](loc0: u64) 18: Lt - 19: BrFalse(35) + 19: BrFalse(29) B4: 20: CopyLoc[0](Arg0: &mut vector) - 21: StLoc[4](loc2: &mut vector) - 22: CopyLoc[1](Arg1: u64) - 23: StLoc[3](loc1: u64) - 24: MoveLoc[1](Arg1: u64) - 25: LdU64(1) - 26: Add - 27: StLoc[1](Arg1: u64) - 28: CopyLoc[1](Arg1: u64) - 29: StLoc[5](loc3: u64) - 30: MoveLoc[4](loc2: &mut vector) - 31: MoveLoc[3](loc1: u64) - 32: MoveLoc[5](loc3: u64) - 33: VecSwap(1) - 34: Branch(16) + 21: CopyLoc[1](Arg1: u64) + 22: MoveLoc[1](Arg1: u64) + 23: LdU64(1) + 24: Add + 25: StLoc[1](Arg1: u64) + 26: CopyLoc[1](Arg1: u64) + 27: VecSwap(1) + 28: Branch(16) B5: - 35: MoveLoc[0](Arg0: &mut vector) - 36: VecPopBack(1) - 37: Ret + 29: MoveLoc[0](Arg0: &mut vector) + 30: VecPopBack(1) + 31: Ret } create(): vector /* def_idx: 1 */ { B0: diff --git a/third_party/move/move-compiler-v2/tests/flush-writes/def_use_07.off.exp b/third_party/move/move-compiler-v2/tests/flush-writes/def_use_07.off.exp index 6e0f61006aa5a..da91b1fbdbafc 100644 --- a/third_party/move/move-compiler-v2/tests/flush-writes/def_use_07.off.exp +++ b/third_party/move/move-compiler-v2/tests/flush-writes/def_use_07.off.exp @@ -18,7 +18,6 @@ B0: 1: Ret } public test(): u64 /* def_idx: 2 */ { -L0: loc0: u64 B0: 0: Call one(): u64 1: Call foo(u64): u64 diff --git a/third_party/move/move-compiler-v2/tests/flush-writes/def_use_07.on.exp b/third_party/move/move-compiler-v2/tests/flush-writes/def_use_07.on.exp index 27772260db6d9..e30fa68798f35 100644 --- a/third_party/move/move-compiler-v2/tests/flush-writes/def_use_07.on.exp +++ b/third_party/move/move-compiler-v2/tests/flush-writes/def_use_07.on.exp @@ -58,7 +58,6 @@ B0: 1: Ret } public test(): u64 /* def_idx: 2 */ { -L0: loc0: u64 B0: 0: Call one(): u64 1: Call foo(u64): u64 diff --git a/third_party/move/move-compiler-v2/tests/flush-writes/loop_01.off.exp b/third_party/move/move-compiler-v2/tests/flush-writes/loop_01.off.exp index e42136755a54d..9c907cf1b4e38 100644 --- a/third_party/move/move-compiler-v2/tests/flush-writes/loop_01.off.exp +++ b/third_party/move/move-compiler-v2/tests/flush-writes/loop_01.off.exp @@ -6,17 +6,12 @@ module c0ffee.m { foo(Arg0: u64): u64 * u64 /* def_idx: 0 */ { L1: loc0: u64 -L2: loc1: u64 B0: 0: CopyLoc[0](Arg0: u64) - 1: StLoc[1](loc0: u64) - 2: MoveLoc[0](Arg0: u64) - 3: LdU64(1) - 4: Sub - 5: StLoc[0](Arg0: u64) - 6: MoveLoc[1](loc0: u64) - 7: MoveLoc[0](Arg0: u64) - 8: Ret + 1: MoveLoc[0](Arg0: u64) + 2: LdU64(1) + 3: Sub + 4: Ret } public test1(Arg0: u64) /* def_idx: 1 */ { L1: loc0: u64 diff --git a/third_party/move/move-compiler-v2/tests/flush-writes/loop_01.on.exp b/third_party/move/move-compiler-v2/tests/flush-writes/loop_01.on.exp index 934f8720dab1c..4640def1c25d2 100644 --- a/third_party/move/move-compiler-v2/tests/flush-writes/loop_01.on.exp +++ b/third_party/move/move-compiler-v2/tests/flush-writes/loop_01.on.exp @@ -69,17 +69,12 @@ module c0ffee.m { foo(Arg0: u64): u64 * u64 /* def_idx: 0 */ { L1: loc0: u64 -L2: loc1: u64 B0: 0: CopyLoc[0](Arg0: u64) - 1: StLoc[1](loc0: u64) - 2: MoveLoc[0](Arg0: u64) - 3: LdU64(1) - 4: Sub - 5: StLoc[0](Arg0: u64) - 6: MoveLoc[1](loc0: u64) - 7: MoveLoc[0](Arg0: u64) - 8: Ret + 1: MoveLoc[0](Arg0: u64) + 2: LdU64(1) + 3: Sub + 4: Ret } public test1(Arg0: u64) /* def_idx: 1 */ { B0: diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/args_with_side_effects.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/args_with_side_effects.exp index eb59c1bd4fbf0..a58b76fe10539 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/args_with_side_effects.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/args_with_side_effects.exp @@ -160,18 +160,13 @@ B0: } public test(Arg0: u64): u64 /* def_idx: 1 */ { L1: loc0: u64 -L2: loc1: u64 B0: 0: CopyLoc[0](Arg0: u64) - 1: StLoc[1](loc0: u64) - 2: MoveLoc[0](Arg0: u64) - 3: LdU64(1) - 4: Add - 5: StLoc[0](Arg0: u64) - 6: MoveLoc[1](loc0: u64) - 7: MoveLoc[0](Arg0: u64) - 8: Call add(u64, u64): u64 - 9: Ret + 1: MoveLoc[0](Arg0: u64) + 2: LdU64(1) + 3: Add + 4: Call add(u64, u64): u64 + 5: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/args_with_side_effects.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/args_with_side_effects.opt.exp index eb59c1bd4fbf0..a58b76fe10539 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/args_with_side_effects.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/args_with_side_effects.opt.exp @@ -160,18 +160,13 @@ B0: } public test(Arg0: u64): u64 /* def_idx: 1 */ { L1: loc0: u64 -L2: loc1: u64 B0: 0: CopyLoc[0](Arg0: u64) - 1: StLoc[1](loc0: u64) - 2: MoveLoc[0](Arg0: u64) - 3: LdU64(1) - 4: Add - 5: StLoc[0](Arg0: u64) - 6: MoveLoc[1](loc0: u64) - 7: MoveLoc[0](Arg0: u64) - 8: Call add(u64, u64): u64 - 9: Ret + 1: MoveLoc[0](Arg0: u64) + 2: LdU64(1) + 3: Add + 4: Call add(u64, u64): u64 + 5: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/borrowed_var.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/borrowed_var.exp index 95104220eaeb7..3fa0178005ebe 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/borrowed_var.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/borrowed_var.exp @@ -139,7 +139,6 @@ module c0ffee.m { test() /* def_idx: 0 */ { L0: loc0: u64 L1: loc1: &u64 -L2: loc2: &u64 B0: 0: LdU64(5) 1: StLoc[0](loc0: u64) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/borrowed_var.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/borrowed_var.opt.exp index 6b10a489c154c..8504db0796684 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/borrowed_var.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/borrowed_var.opt.exp @@ -151,7 +151,6 @@ test() /* def_idx: 0 */ { L0: loc0: u64 L1: loc1: &u64 L2: loc2: u64 -L3: loc3: &u64 B0: 0: LdU64(5) 1: StLoc[0](loc0: u64) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_2.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_2.exp index 4011aa65aadae..0ca6e1586c9fd 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_2.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_2.exp @@ -107,7 +107,6 @@ module c0ffee.m { test(Arg0: bool, Arg1: u64, Arg2: u64): u64 /* def_idx: 0 */ { L3: loc0: u64 -L4: loc1: u64 B0: 0: MoveLoc[0](Arg0: bool) 1: BrFalse(6) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_2.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_2.opt.exp index 4011aa65aadae..0ca6e1586c9fd 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_2.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_2.opt.exp @@ -107,7 +107,6 @@ module c0ffee.m { test(Arg0: bool, Arg1: u64, Arg2: u64): u64 /* def_idx: 0 */ { L3: loc0: u64 -L4: loc1: u64 B0: 0: MoveLoc[0](Arg0: bool) 1: BrFalse(6) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_3.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_3.exp index 957082ac783f0..62a6a6a09d546 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_3.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_3.exp @@ -106,7 +106,6 @@ module c0ffee.m { test(Arg0: bool, Arg1: u64): u64 /* def_idx: 0 */ { L2: loc0: u64 -L3: loc1: u64 B0: 0: MoveLoc[0](Arg0: bool) 1: BrFalse(6) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_3.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_3.opt.exp index 957082ac783f0..62a6a6a09d546 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_3.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_3.opt.exp @@ -106,7 +106,6 @@ module c0ffee.m { test(Arg0: bool, Arg1: u64): u64 /* def_idx: 0 */ { L2: loc0: u64 -L3: loc1: u64 B0: 0: MoveLoc[0](Arg0: bool) 1: BrFalse(6) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_assigns_then_moves_then_assigns.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_assigns_then_moves_then_assigns.exp index 2732ee278296f..4ecbc23e87caf 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_assigns_then_moves_then_assigns.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_assigns_then_moves_then_assigns.exp @@ -229,8 +229,6 @@ script { main() /* def_idx: 0 */ { L0: loc0: u64 -L1: loc1: u64 -L2: loc2: u64 B0: 0: LdU64(5) 1: StLoc[0](loc0: u64) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_assigns_then_moves_then_assigns.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_assigns_then_moves_then_assigns.opt.exp index 2732ee278296f..4ecbc23e87caf 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_assigns_then_moves_then_assigns.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_assigns_then_moves_then_assigns.opt.exp @@ -229,8 +229,6 @@ script { main() /* def_idx: 0 */ { L0: loc0: u64 -L1: loc1: u64 -L2: loc2: u64 B0: 0: LdU64(5) 1: StLoc[0](loc0: u64) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_1.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_1.exp index 74ef544575ec3..aaa97c341d3f8 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_1.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_1.exp @@ -312,18 +312,14 @@ B0: 0: Ret } public test1(Arg0: u64) /* def_idx: 2 */ { -L1: loc0: u64 B0: 0: CopyLoc[0](Arg0: u64) - 1: StLoc[1](loc0: u64) - 2: MoveLoc[0](Arg0: u64) + 1: MoveLoc[0](Arg0: u64) + 2: Call consume(u64) 3: Call consume(u64) - 4: MoveLoc[1](loc0: u64) - 5: Call consume(u64) - 6: Ret + 4: Ret } public test2(Arg0: u64) /* def_idx: 3 */ { -L1: loc0: u64 B0: 0: CopyLoc[0](Arg0: u64) 1: Call consume(u64) @@ -332,18 +328,14 @@ B0: 4: Ret } public test3(Arg0: W) /* def_idx: 4 */ { -L1: loc0: W B0: 0: CopyLoc[0](Arg0: W) - 1: StLoc[1](loc0: W) - 2: MoveLoc[0](Arg0: W) + 1: MoveLoc[0](Arg0: W) + 2: Call consume_(W) 3: Call consume_(W) - 4: MoveLoc[1](loc0: W) - 5: Call consume_(W) - 6: Ret + 4: Ret } public test4(Arg0: W) /* def_idx: 5 */ { -L1: loc0: W B0: 0: CopyLoc[0](Arg0: W) 1: Call consume_(W) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_1.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_1.opt.exp index 74ef544575ec3..aaa97c341d3f8 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_1.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_1.opt.exp @@ -312,18 +312,14 @@ B0: 0: Ret } public test1(Arg0: u64) /* def_idx: 2 */ { -L1: loc0: u64 B0: 0: CopyLoc[0](Arg0: u64) - 1: StLoc[1](loc0: u64) - 2: MoveLoc[0](Arg0: u64) + 1: MoveLoc[0](Arg0: u64) + 2: Call consume(u64) 3: Call consume(u64) - 4: MoveLoc[1](loc0: u64) - 5: Call consume(u64) - 6: Ret + 4: Ret } public test2(Arg0: u64) /* def_idx: 3 */ { -L1: loc0: u64 B0: 0: CopyLoc[0](Arg0: u64) 1: Call consume(u64) @@ -332,18 +328,14 @@ B0: 4: Ret } public test3(Arg0: W) /* def_idx: 4 */ { -L1: loc0: W B0: 0: CopyLoc[0](Arg0: W) - 1: StLoc[1](loc0: W) - 2: MoveLoc[0](Arg0: W) + 1: MoveLoc[0](Arg0: W) + 2: Call consume_(W) 3: Call consume_(W) - 4: MoveLoc[1](loc0: W) - 5: Call consume_(W) - 6: Ret + 4: Ret } public test4(Arg0: W) /* def_idx: 5 */ { -L1: loc0: W B0: 0: CopyLoc[0](Arg0: W) 1: Call consume_(W) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_3.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_3.exp index 7ecc0e6a884b1..c15338be6f7e7 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_3.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_3.exp @@ -198,7 +198,6 @@ B0: 0: Ret } public test(Arg0: u32) /* def_idx: 2 */ { -L1: loc0: u32 B0: 0: CopyLoc[0](Arg0: u32) 1: Call consume(u32) @@ -207,7 +206,6 @@ B0: 4: Ret } public test_(Arg0: W) /* def_idx: 3 */ { -L1: loc0: W B0: 0: CopyLoc[0](Arg0: W) 1: Call consume_(W) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_3.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_3.opt.exp index 7ecc0e6a884b1..c15338be6f7e7 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_3.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_3.opt.exp @@ -198,7 +198,6 @@ B0: 0: Ret } public test(Arg0: u32) /* def_idx: 2 */ { -L1: loc0: u32 B0: 0: CopyLoc[0](Arg0: u32) 1: Call consume(u32) @@ -207,7 +206,6 @@ B0: 4: Ret } public test_(Arg0: W) /* def_idx: 3 */ { -L1: loc0: W B0: 0: CopyLoc[0](Arg0: W) 1: Call consume_(W) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_4.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_4.exp index f2b1a0c6caaf7..e801617e44e8f 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_4.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_4.exp @@ -220,7 +220,6 @@ B0: 0: Ret } public test(Arg0: u32) /* def_idx: 2 */ { -L1: loc0: u32 B0: 0: CopyLoc[0](Arg0: u32) 1: Call consume(u32) @@ -229,7 +228,6 @@ B0: 4: Ret } public test_struct(Arg0: W) /* def_idx: 3 */ { -L1: loc0: W B0: 0: CopyLoc[0](Arg0: W) 1: Call consume_(W) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_4.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_4.opt.exp index f2b1a0c6caaf7..e801617e44e8f 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_4.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_4.opt.exp @@ -220,7 +220,6 @@ B0: 0: Ret } public test(Arg0: u32) /* def_idx: 2 */ { -L1: loc0: u32 B0: 0: CopyLoc[0](Arg0: u32) 1: Call consume(u32) @@ -229,7 +228,6 @@ B0: 4: Ret } public test_struct(Arg0: W) /* def_idx: 3 */ { -L1: loc0: W B0: 0: CopyLoc[0](Arg0: W) 1: Call consume_(W) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_assignments.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_assignments.exp index 6a5b5d0f8d8ff..8dd3b318bd40c 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_assignments.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_assignments.exp @@ -83,7 +83,6 @@ module c0ffee.m { cyclic(Arg0: u64): u64 /* def_idx: 0 */ { -L1: loc0: u64 B0: 0: MoveLoc[0](Arg0: u64) 1: Ret diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_assignments.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_assignments.opt.exp index 6a5b5d0f8d8ff..8dd3b318bd40c 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_assignments.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_assignments.opt.exp @@ -83,7 +83,6 @@ module c0ffee.m { cyclic(Arg0: u64): u64 /* def_idx: 0 */ { -L1: loc0: u64 B0: 0: MoveLoc[0](Arg0: u64) 1: Ret diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_dead_store.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_dead_store.exp index 860e46ca74071..532b75388a4fb 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_dead_store.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_dead_store.exp @@ -276,15 +276,17 @@ B1: 2: CopyLoc[3](loc0: u64) 3: CopyLoc[0](Arg0: u64) 4: Lt - 5: BrFalse(11) + 5: BrFalse(13) B2: - 6: MoveLoc[3](loc0: u64) - 7: LdU64(1) - 8: Add - 9: StLoc[3](loc0: u64) - 10: Branch(2) + 6: MoveLoc[2](Arg2: u64) + 7: MoveLoc[3](loc0: u64) + 8: LdU64(1) + 9: Add + 10: StLoc[3](loc0: u64) + 11: StLoc[2](Arg2: u64) + 12: Branch(2) B3: - 11: Ret + 13: Ret } public test2(Arg0: u64, Arg1: u64) /* def_idx: 1 */ { L2: loc0: u64 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_dead_store.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_dead_store.opt.exp index 860e46ca74071..532b75388a4fb 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_dead_store.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_dead_store.opt.exp @@ -276,15 +276,17 @@ B1: 2: CopyLoc[3](loc0: u64) 3: CopyLoc[0](Arg0: u64) 4: Lt - 5: BrFalse(11) + 5: BrFalse(13) B2: - 6: MoveLoc[3](loc0: u64) - 7: LdU64(1) - 8: Add - 9: StLoc[3](loc0: u64) - 10: Branch(2) + 6: MoveLoc[2](Arg2: u64) + 7: MoveLoc[3](loc0: u64) + 8: LdU64(1) + 9: Add + 10: StLoc[3](loc0: u64) + 11: StLoc[2](Arg2: u64) + 12: Branch(2) B3: - 11: Ret + 13: Ret } public test2(Arg0: u64, Arg1: u64) /* def_idx: 1 */ { L2: loc0: u64 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/immut_refs_2.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/immut_refs_2.exp index 154ea1d90c925..180cc62af2a3b 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/immut_refs_2.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/immut_refs_2.exp @@ -122,7 +122,6 @@ module c0ffee.m { test(Arg0: u64): u64 /* def_idx: 0 */ { L1: loc0: &u64 -L2: loc1: u64 B0: 0: ImmBorrowLoc[0](Arg0: u64) 1: Pop diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/immut_refs_2.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/immut_refs_2.opt.exp index 154ea1d90c925..180cc62af2a3b 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/immut_refs_2.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/immut_refs_2.opt.exp @@ -122,7 +122,6 @@ module c0ffee.m { test(Arg0: u64): u64 /* def_idx: 0 */ { L1: loc0: &u64 -L2: loc1: u64 B0: 0: ImmBorrowLoc[0](Arg0: u64) 1: Pop diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_1.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_1.exp index 1fc069963391a..6d8197b4a1bcd 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_1.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_1.exp @@ -112,7 +112,6 @@ module c0ffee.m { test(): u64 /* def_idx: 0 */ { L0: loc0: u64 -L1: loc1: u64 B0: 0: LdU64(1) 1: LdU64(2) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_2.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_2.opt.exp index def8e4b7b85f5..6eb72ab89b2c0 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_2.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_2.opt.exp @@ -110,13 +110,14 @@ module c0ffee.m { test(): u64 /* def_idx: 0 */ { L0: loc0: u64 +L1: loc1: u64 B0: 0: LdU64(1) 1: LdU64(1) 2: Add - 3: StLoc[0](loc0: u64) + 3: StLoc[1](loc1: u64) 4: LdU64(2) - 5: MoveLoc[0](loc0: u64) + 5: MoveLoc[1](loc1: u64) 6: Add 7: Ret } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_1.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_1.exp index 3c4fe82378d7c..b8c4d57d833a0 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_1.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_1.exp @@ -189,11 +189,11 @@ B1: 7: BrFalse(15) B2: 8: CopyLoc[0](Arg0: u64) - 9: StLoc[1](loc0: u64) - 10: MoveLoc[2](loc1: u64) - 11: LdU64(1) - 12: Add - 13: StLoc[2](loc1: u64) + 9: MoveLoc[2](loc1: u64) + 10: LdU64(1) + 11: Add + 12: StLoc[2](loc1: u64) + 13: StLoc[1](loc0: u64) 14: Branch(4) B3: 15: MoveLoc[1](loc0: u64) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_1.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_1.opt.exp index 3c4fe82378d7c..b8c4d57d833a0 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_1.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_1.opt.exp @@ -189,11 +189,11 @@ B1: 7: BrFalse(15) B2: 8: CopyLoc[0](Arg0: u64) - 9: StLoc[1](loc0: u64) - 10: MoveLoc[2](loc1: u64) - 11: LdU64(1) - 12: Add - 13: StLoc[2](loc1: u64) + 9: MoveLoc[2](loc1: u64) + 10: LdU64(1) + 11: Add + 12: StLoc[2](loc1: u64) + 13: StLoc[1](loc0: u64) 14: Branch(4) B3: 15: MoveLoc[1](loc0: u64) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_2.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_2.exp index edcfd71c7b42c..3334689dfa167 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_2.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_2.exp @@ -179,24 +179,24 @@ L2: loc1: u64 L3: loc2: u64 B0: 0: CopyLoc[0](Arg0: u64) - 1: StLoc[1](loc0: u64) - 2: LdU64(0) + 1: LdU64(0) + 2: StLoc[1](loc0: u64) 3: StLoc[2](loc1: u64) B1: - 4: CopyLoc[2](loc1: u64) + 4: CopyLoc[1](loc0: u64) 5: LdU64(10) 6: Lt 7: BrFalse(15) B2: 8: CopyLoc[0](Arg0: u64) - 9: StLoc[1](loc0: u64) - 10: MoveLoc[2](loc1: u64) - 11: LdU64(1) - 12: Add + 9: MoveLoc[1](loc0: u64) + 10: LdU64(1) + 11: Add + 12: StLoc[1](loc0: u64) 13: StLoc[2](loc1: u64) 14: Branch(4) B3: - 15: MoveLoc[1](loc0: u64) + 15: MoveLoc[2](loc1: u64) 16: Ret } } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_2.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_2.opt.exp index edcfd71c7b42c..3334689dfa167 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_2.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_2.opt.exp @@ -179,24 +179,24 @@ L2: loc1: u64 L3: loc2: u64 B0: 0: CopyLoc[0](Arg0: u64) - 1: StLoc[1](loc0: u64) - 2: LdU64(0) + 1: LdU64(0) + 2: StLoc[1](loc0: u64) 3: StLoc[2](loc1: u64) B1: - 4: CopyLoc[2](loc1: u64) + 4: CopyLoc[1](loc0: u64) 5: LdU64(10) 6: Lt 7: BrFalse(15) B2: 8: CopyLoc[0](Arg0: u64) - 9: StLoc[1](loc0: u64) - 10: MoveLoc[2](loc1: u64) - 11: LdU64(1) - 12: Add + 9: MoveLoc[1](loc0: u64) + 10: LdU64(1) + 11: Add + 12: StLoc[1](loc0: u64) 13: StLoc[2](loc1: u64) 14: Branch(4) B3: - 15: MoveLoc[1](loc0: u64) + 15: MoveLoc[2](loc1: u64) 16: Ret } } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/mut_refs_1.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/mut_refs_1.exp index 8514f77eee3b5..f821096a76a3e 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/mut_refs_1.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/mut_refs_1.exp @@ -96,18 +96,15 @@ module c0ffee.m { test(Arg0: u64): u64 /* def_idx: 0 */ { -L1: loc0: u64 -L2: loc1: &mut u64 +L1: loc0: &mut u64 B0: 0: CopyLoc[0](Arg0: u64) - 1: StLoc[1](loc0: u64) - 2: MutBorrowLoc[0](Arg0: u64) - 3: StLoc[2](loc1: &mut u64) - 4: LdU64(1) - 5: MoveLoc[2](loc1: &mut u64) - 6: WriteRef - 7: MoveLoc[1](loc0: u64) - 8: Ret + 1: MutBorrowLoc[0](Arg0: u64) + 2: StLoc[1](loc0: &mut u64) + 3: LdU64(1) + 4: MoveLoc[1](loc0: &mut u64) + 5: WriteRef + 6: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/mut_refs_1.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/mut_refs_1.opt.exp index 8514f77eee3b5..f821096a76a3e 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/mut_refs_1.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/mut_refs_1.opt.exp @@ -96,18 +96,15 @@ module c0ffee.m { test(Arg0: u64): u64 /* def_idx: 0 */ { -L1: loc0: u64 -L2: loc1: &mut u64 +L1: loc0: &mut u64 B0: 0: CopyLoc[0](Arg0: u64) - 1: StLoc[1](loc0: u64) - 2: MutBorrowLoc[0](Arg0: u64) - 3: StLoc[2](loc1: &mut u64) - 4: LdU64(1) - 5: MoveLoc[2](loc1: &mut u64) - 6: WriteRef - 7: MoveLoc[1](loc0: u64) - 8: Ret + 1: MutBorrowLoc[0](Arg0: u64) + 2: StLoc[1](loc0: &mut u64) + 3: LdU64(1) + 4: MoveLoc[1](loc0: &mut u64) + 5: WriteRef + 6: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_1.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_1.exp index a6a7f2aabdfa2..86b5890cae6d7 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_1.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_1.exp @@ -129,13 +129,13 @@ B0: 0: CopyLoc[0](Arg0: u64) 1: StLoc[1](loc0: u64) 2: CopyLoc[1](loc0: u64) - 3: StLoc[2](loc1: u64) - 4: MoveLoc[0](Arg0: u64) - 5: LdU64(1) - 6: Add - 7: Pop + 3: MoveLoc[0](Arg0: u64) + 4: LdU64(1) + 5: Add + 6: Pop + 7: StLoc[3](loc2: u64) 8: MoveLoc[1](loc0: u64) - 9: MoveLoc[2](loc1: u64) + 9: MoveLoc[3](loc2: u64) 10: Eq 11: Ret } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_1.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_1.opt.exp index a6a7f2aabdfa2..86b5890cae6d7 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_1.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_1.opt.exp @@ -129,13 +129,13 @@ B0: 0: CopyLoc[0](Arg0: u64) 1: StLoc[1](loc0: u64) 2: CopyLoc[1](loc0: u64) - 3: StLoc[2](loc1: u64) - 4: MoveLoc[0](Arg0: u64) - 5: LdU64(1) - 6: Add - 7: Pop + 3: MoveLoc[0](Arg0: u64) + 4: LdU64(1) + 5: Add + 6: Pop + 7: StLoc[3](loc2: u64) 8: MoveLoc[1](loc0: u64) - 9: MoveLoc[2](loc1: u64) + 9: MoveLoc[3](loc2: u64) 10: Eq 11: Ret } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_2.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_2.exp index 37fb2e50db125..eb034ba9ffbaf 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_2.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_2.exp @@ -129,13 +129,13 @@ B0: 0: CopyLoc[0](Arg0: u64) 1: StLoc[1](loc0: u64) 2: CopyLoc[1](loc0: u64) - 3: StLoc[2](loc1: u64) - 4: MoveLoc[0](Arg0: u64) - 5: LdU64(1) - 6: Add - 7: Pop + 3: MoveLoc[0](Arg0: u64) + 4: LdU64(1) + 5: Add + 6: Pop + 7: StLoc[3](loc2: u64) 8: MoveLoc[1](loc0: u64) - 9: MoveLoc[2](loc1: u64) + 9: MoveLoc[3](loc2: u64) 10: Eq 11: Ret } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_2.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_2.opt.exp index 37fb2e50db125..eb034ba9ffbaf 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_2.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_2.opt.exp @@ -129,13 +129,13 @@ B0: 0: CopyLoc[0](Arg0: u64) 1: StLoc[1](loc0: u64) 2: CopyLoc[1](loc0: u64) - 3: StLoc[2](loc1: u64) - 4: MoveLoc[0](Arg0: u64) - 5: LdU64(1) - 6: Add - 7: Pop + 3: MoveLoc[0](Arg0: u64) + 4: LdU64(1) + 5: Add + 6: Pop + 7: StLoc[3](loc2: u64) 8: MoveLoc[1](loc0: u64) - 9: MoveLoc[2](loc1: u64) + 9: MoveLoc[3](loc2: u64) 10: Eq 11: Ret } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/straight_line_kills.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/straight_line_kills.exp index 0d49f3e8a14f9..822f245566624 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/straight_line_kills.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/straight_line_kills.exp @@ -113,20 +113,17 @@ module c0ffee.m { copy_kill(Arg0: u64): u64 /* def_idx: 0 */ { L1: loc0: u64 L2: loc1: u64 -L3: loc2: u64 B0: 0: CopyLoc[0](Arg0: u64) 1: StLoc[1](loc0: u64) 2: CopyLoc[1](loc0: u64) - 3: StLoc[2](loc1: u64) - 4: MoveLoc[0](Arg0: u64) - 5: LdU64(1) - 6: Add - 7: Pop - 8: MoveLoc[2](loc1: u64) - 9: MoveLoc[1](loc0: u64) - 10: Add - 11: Ret + 3: MoveLoc[0](Arg0: u64) + 4: LdU64(1) + 5: Add + 6: Pop + 7: MoveLoc[1](loc0: u64) + 8: Add + 9: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/straight_line_kills.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/straight_line_kills.opt.exp index 0d49f3e8a14f9..822f245566624 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/straight_line_kills.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/straight_line_kills.opt.exp @@ -113,20 +113,17 @@ module c0ffee.m { copy_kill(Arg0: u64): u64 /* def_idx: 0 */ { L1: loc0: u64 L2: loc1: u64 -L3: loc2: u64 B0: 0: CopyLoc[0](Arg0: u64) 1: StLoc[1](loc0: u64) 2: CopyLoc[1](loc0: u64) - 3: StLoc[2](loc1: u64) - 4: MoveLoc[0](Arg0: u64) - 5: LdU64(1) - 6: Add - 7: Pop - 8: MoveLoc[2](loc1: u64) - 9: MoveLoc[1](loc0: u64) - 10: Add - 11: Ret + 3: MoveLoc[0](Arg0: u64) + 4: LdU64(1) + 5: Add + 6: Pop + 7: MoveLoc[1](loc0: u64) + 8: Add + 9: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/swap.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/swap.exp index 64990776e2cdc..08533b6b6dd91 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/swap.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/swap.exp @@ -92,14 +92,12 @@ public test(Arg0: u64, Arg1: u64): u64 * u64 /* def_idx: 0 */ { L2: loc0: u64 B0: 0: MoveLoc[0](Arg0: u64) - 1: StLoc[2](loc0: u64) - 2: MoveLoc[1](Arg1: u64) - 3: StLoc[0](Arg0: u64) - 4: MoveLoc[2](loc0: u64) - 5: StLoc[1](Arg1: u64) - 6: MoveLoc[0](Arg0: u64) - 7: MoveLoc[1](Arg1: u64) - 8: Ret + 1: MoveLoc[1](Arg1: u64) + 2: StLoc[0](Arg0: u64) + 3: StLoc[1](Arg1: u64) + 4: MoveLoc[0](Arg0: u64) + 5: MoveLoc[1](Arg1: u64) + 6: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/swap.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/swap.opt.exp index 64990776e2cdc..08533b6b6dd91 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/swap.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/swap.opt.exp @@ -92,14 +92,12 @@ public test(Arg0: u64, Arg1: u64): u64 * u64 /* def_idx: 0 */ { L2: loc0: u64 B0: 0: MoveLoc[0](Arg0: u64) - 1: StLoc[2](loc0: u64) - 2: MoveLoc[1](Arg1: u64) - 3: StLoc[0](Arg0: u64) - 4: MoveLoc[2](loc0: u64) - 5: StLoc[1](Arg1: u64) - 6: MoveLoc[0](Arg0: u64) - 7: MoveLoc[1](Arg1: u64) - 8: Ret + 1: MoveLoc[1](Arg1: u64) + 2: StLoc[0](Arg0: u64) + 3: StLoc[1](Arg1: u64) + 4: MoveLoc[0](Arg0: u64) + 5: MoveLoc[1](Arg1: u64) + 6: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/swap_in_a_loop.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/swap_in_a_loop.exp index e0b25100114af..4b4283ceb66ac 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/swap_in_a_loop.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/swap_in_a_loop.exp @@ -201,23 +201,21 @@ B1: 2: CopyLoc[2](loc0: u64) 3: LdU64(0) 4: Gt - 5: BrFalse(17) + 5: BrFalse(15) B2: 6: MoveLoc[0](Arg0: u64) - 7: StLoc[3](loc1: u64) - 8: MoveLoc[1](Arg1: u64) - 9: StLoc[0](Arg0: u64) - 10: MoveLoc[3](loc1: u64) - 11: StLoc[1](Arg1: u64) - 12: MoveLoc[2](loc0: u64) - 13: LdU64(1) - 14: Sub - 15: StLoc[2](loc0: u64) - 16: Branch(2) + 7: MoveLoc[1](Arg1: u64) + 8: StLoc[0](Arg0: u64) + 9: MoveLoc[2](loc0: u64) + 10: LdU64(1) + 11: Sub + 12: StLoc[2](loc0: u64) + 13: StLoc[1](Arg1: u64) + 14: Branch(2) B3: - 17: MoveLoc[0](Arg0: u64) - 18: MoveLoc[1](Arg1: u64) - 19: Ret + 15: MoveLoc[0](Arg0: u64) + 16: MoveLoc[1](Arg1: u64) + 17: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/swap_in_a_loop.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/swap_in_a_loop.opt.exp index e0b25100114af..4b4283ceb66ac 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/swap_in_a_loop.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/swap_in_a_loop.opt.exp @@ -201,23 +201,21 @@ B1: 2: CopyLoc[2](loc0: u64) 3: LdU64(0) 4: Gt - 5: BrFalse(17) + 5: BrFalse(15) B2: 6: MoveLoc[0](Arg0: u64) - 7: StLoc[3](loc1: u64) - 8: MoveLoc[1](Arg1: u64) - 9: StLoc[0](Arg0: u64) - 10: MoveLoc[3](loc1: u64) - 11: StLoc[1](Arg1: u64) - 12: MoveLoc[2](loc0: u64) - 13: LdU64(1) - 14: Sub - 15: StLoc[2](loc0: u64) - 16: Branch(2) + 7: MoveLoc[1](Arg1: u64) + 8: StLoc[0](Arg0: u64) + 9: MoveLoc[2](loc0: u64) + 10: LdU64(1) + 11: Sub + 12: StLoc[2](loc0: u64) + 13: StLoc[1](Arg1: u64) + 14: Branch(2) B3: - 17: MoveLoc[0](Arg0: u64) - 18: MoveLoc[1](Arg1: u64) - 19: Ret + 15: MoveLoc[0](Arg0: u64) + 16: MoveLoc[1](Arg1: u64) + 17: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/misc/assign_optimize_test01.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/misc/assign_optimize_test01.exp new file mode 100644 index 0000000000000..8b8df292e459f --- /dev/null +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/misc/assign_optimize_test01.exp @@ -0,0 +1,15 @@ +processed 5 tasks + +task 1 'run'. lines 31-31: +return values: 100 + +task 2 'run'. lines 33-33: +return values: 50 + +task 3 'run'. lines 35-35: +return values: 100 + +task 4 'run'. lines 37-37: +return values: 50 + +==> Compiler v2 delivered same results! diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/misc/assign_optimize_test01.move b/third_party/move/move-compiler-v2/transactional-tests/tests/misc/assign_optimize_test01.move new file mode 100644 index 0000000000000..26970f2f2866d --- /dev/null +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/misc/assign_optimize_test01.move @@ -0,0 +1,37 @@ +//# publish +module 0xc0ffee::m { + fun foo1(a: u64, b: u64, c: bool): u64 { + if (c) { + a = b; + }; + let t = a * 2; + bar(); + let t2 = a * 3; + t + t2 + } + + fun foo2(a: u64, b: u64, c: bool): u64 { + if (c) { + a = b; + }; + let t = a * 2; + if (c) { + bar(); + }; + bar(); + let t2 = a * 3; + t + t2 + } + + fun bar() { + assert!(true, 1); + } +} + +//# run 0xc0ffee::m::foo1 --args 10 20 true + +//# run 0xc0ffee::m::foo1 --args 10 20 false + +//# run 0xc0ffee::m::foo2 --args 10 20 true + +//# run 0xc0ffee::m::foo2 --args 10 20 false diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/assert_one.optimize-no-simplify.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/assert_one.optimize-no-simplify.exp index 9d1a8ab06c8cb..2161a50d2b658 100644 --- a/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/assert_one.optimize-no-simplify.exp +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/assert_one.optimize-no-simplify.exp @@ -6,5 +6,5 @@ Error: Script execution failed with VMError: { sub_status: Some(14566554180833181696), location: script, indices: [], - offsets: [(FunctionDefinitionIndex(0), 31)], + offsets: [(FunctionDefinitionIndex(0), 27)], } diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/assert_one.optimize.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/assert_one.optimize.exp index 9d1a8ab06c8cb..2161a50d2b658 100644 --- a/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/assert_one.optimize.exp +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/assert_one.optimize.exp @@ -6,5 +6,5 @@ Error: Script execution failed with VMError: { sub_status: Some(14566554180833181696), location: script, indices: [], - offsets: [(FunctionDefinitionIndex(0), 31)], + offsets: [(FunctionDefinitionIndex(0), 27)], } From 63f0df8e19577145300d2025166300feda8c370d Mon Sep 17 00:00:00 2001 From: Balaji Arun Date: Wed, 4 Dec 2024 13:30:16 -0800 Subject: [PATCH 11/78] [qs] batch store bootstrap perf improvements (#15491) * [qs] Use expiration buffer to cleanup during bootstrap * [qs] async gc old epoch batches from batch store * [qs] monitor! create batch store --- consensus/src/quorum_store/batch_store.rs | 84 +++++++++++++++---- .../src/quorum_store/quorum_store_builder.rs | 5 +- .../tests/batch_proof_queue_test.rs | 24 +++--- .../quorum_store/tests/batch_store_test.rs | 9 +- 4 files changed, 91 insertions(+), 31 deletions(-) diff --git a/consensus/src/quorum_store/batch_store.rs b/consensus/src/quorum_store/batch_store.rs index 74720737dd278..523744c76749f 100644 --- a/consensus/src/quorum_store/batch_store.rs +++ b/consensus/src/quorum_store/batch_store.rs @@ -123,6 +123,7 @@ pub struct BatchStore { impl BatchStore { pub(crate) fn new( epoch: u64, + is_new_epoch: bool, last_certified_time: u64, db: Arc, memory_quota: usize, @@ -146,18 +147,73 @@ impl BatchStore { persist_subscribers: DashMap::new(), expiration_buffer_usecs, }; - let db_content = db_clone - .get_all_batches() - .expect("failed to read data from db"); + + if is_new_epoch { + tokio::task::spawn_blocking(move || { + Self::gc_previous_epoch_batches_from_db(db_clone, epoch); + }); + } else { + Self::populate_cache_and_gc_expired_batches( + db_clone, + epoch, + last_certified_time, + expiration_buffer_usecs, + &batch_store, + ); + } + + batch_store + } + + fn gc_previous_epoch_batches_from_db(db: Arc, current_epoch: u64) { + let db_content = db.get_all_batches().expect("failed to read data from db"); + info!( + epoch = current_epoch, + "QS: Read batches from storage. Len: {}", + db_content.len(), + ); + let mut expired_keys = Vec::new(); - trace!( - "QS: Batchreader {} {} {}", + for (digest, value) in db_content { + let epoch = value.epoch(); + + trace!( + "QS: Batchreader recovery content epoch {:?}, digest {}", + epoch, + digest + ); + + if epoch < current_epoch { + expired_keys.push(digest); + } + } + + info!( + "QS: Batch store bootstrap expired keys len {}", + expired_keys.len() + ); + db.delete_batches(expired_keys) + .expect("Deletion of expired keys should not fail"); + } + + fn populate_cache_and_gc_expired_batches( + db: Arc, + current_epoch: u64, + last_certified_time: u64, + expiration_buffer_usecs: u64, + batch_store: &BatchStore, + ) { + let db_content = db.get_all_batches().expect("failed to read data from db"); + info!( + epoch = current_epoch, + "QS: Read batches from storage. Len: {}, Last Cerified Time: {}", db_content.len(), - epoch, last_certified_time ); + + let mut expired_keys = Vec::new(); for (digest, value) in db_content { - let expiration = value.expiration(); + let expiration = value.expiration().saturating_sub(expiration_buffer_usecs); trace!( "QS: Batchreader recovery content exp {:?}, digest {}", @@ -173,15 +229,15 @@ impl BatchStore { .expect("Storage limit exceeded upon BatchReader construction"); } } - trace!( - "QS: Batchreader recovery expired keys len {}", + + info!( + "QS: Batch store bootstrap expired keys len {}", expired_keys.len() ); - db_clone - .delete_batches(expired_keys) - .expect("Deletion of expired keys should not fail"); - - batch_store + tokio::task::spawn_blocking(move || { + db.delete_batches(expired_keys) + .expect("Deletion of expired keys should not fail"); + }); } fn epoch(&self) -> u64 { diff --git a/consensus/src/quorum_store/quorum_store_builder.rs b/consensus/src/quorum_store/quorum_store_builder.rs index f56fd94397129..069fa3d241eda 100644 --- a/consensus/src/quorum_store/quorum_store_builder.rs +++ b/consensus/src/quorum_store/quorum_store_builder.rs @@ -5,6 +5,7 @@ use super::quorum_store_db::QuorumStoreStorage; use crate::{ consensus_observer::publisher::consensus_publisher::ConsensusPublisher, error::error_kind, + monitor, network::{IncomingBatchRetrievalRequest, NetworkSender}, network_interface::ConsensusMsg, payload_manager::{DirectMempoolPayloadManager, QuorumStorePayloadManager, TPayloadManager}, @@ -235,6 +236,7 @@ impl InnerBuilder { .get_latest_ledger_info() .expect("could not get latest ledger info"); let last_committed_timestamp = latest_ledger_info_with_sigs.commit_info().timestamp_usecs(); + let is_new_epoch = latest_ledger_info_with_sigs.ledger_info().ends_epoch(); let batch_requester = BatchRequester::new( self.epoch, @@ -248,6 +250,7 @@ impl InnerBuilder { ); let batch_store = Arc::new(BatchStore::new( self.epoch, + is_new_epoch, last_committed_timestamp, self.quorum_store_storage.clone(), self.config.memory_quota, @@ -434,7 +437,7 @@ impl InnerBuilder { Arc, Option>, ) { - let batch_reader = self.create_batch_store(); + let batch_reader = monitor!("qs_create_batch_store", self.create_batch_store()); ( Arc::from(QuorumStorePayloadManager::new( diff --git a/consensus/src/quorum_store/tests/batch_proof_queue_test.rs b/consensus/src/quorum_store/tests/batch_proof_queue_test.rs index 96ab5414ab120..49746df432b75 100644 --- a/consensus/src/quorum_store/tests/batch_proof_queue_test.rs +++ b/consensus/src/quorum_store/tests/batch_proof_queue_test.rs @@ -58,8 +58,8 @@ fn proof_of_store_with_size( ) } -#[test] -fn test_proof_queue_sorting() { +#[tokio::test] +async fn test_proof_queue_sorting() { let my_peer_id = PeerId::random(); let batch_store = batch_store_for_test(5 * 1024 * 1024); let mut proof_queue = BatchProofQueue::new(my_peer_id, batch_store, 1); @@ -145,8 +145,8 @@ fn test_proof_queue_sorting() { assert_eq!(count_author_1, 2); } -#[test] -fn test_proof_calculate_remaining_txns_and_proofs() { +#[tokio::test] +async fn test_proof_calculate_remaining_txns_and_proofs() { let my_peer_id = PeerId::random(); let batch_store = batch_store_for_test(5 * 1024 * 1024); let mut proof_queue = BatchProofQueue::new(my_peer_id, batch_store, 1); @@ -405,8 +405,8 @@ fn test_proof_calculate_remaining_txns_and_proofs() { assert_eq!(proof_queue.batch_summaries_len(), 0); } -#[test] -fn test_proof_pull_proofs_with_duplicates() { +#[tokio::test] +async fn test_proof_pull_proofs_with_duplicates() { let my_peer_id = PeerId::random(); let batch_store = batch_store_for_test(5 * 1024 * 1024); let mut proof_queue = BatchProofQueue::new(my_peer_id, batch_store, 1); @@ -656,8 +656,8 @@ fn test_proof_pull_proofs_with_duplicates() { assert!(proof_queue.is_empty()); } -#[test] -fn test_proof_queue_soft_limit() { +#[tokio::test] +async fn test_proof_queue_soft_limit() { let my_peer_id = PeerId::random(); let batch_store = batch_store_for_test(5 * 1024 * 1024); let mut proof_queue = BatchProofQueue::new(my_peer_id, batch_store, 1); @@ -698,8 +698,8 @@ fn test_proof_queue_soft_limit() { assert_eq!(num_unique_txns, 20); } -#[test] -fn test_proof_queue_insert_after_commit() { +#[tokio::test] +async fn test_proof_queue_insert_after_commit() { let my_peer_id = PeerId::random(); let batch_store = batch_store_for_test(5 * 1024); let mut proof_queue = BatchProofQueue::new(my_peer_id, batch_store, 1); @@ -730,8 +730,8 @@ fn test_proof_queue_insert_after_commit() { assert!(proof_queue.is_empty()); } -#[test] -fn test_proof_queue_pull_full_utilization() { +#[tokio::test] +async fn test_proof_queue_pull_full_utilization() { let my_peer_id = PeerId::random(); let batch_store = batch_store_for_test(5 * 1024); let mut proof_queue = BatchProofQueue::new(my_peer_id, batch_store, 1); diff --git a/consensus/src/quorum_store/tests/batch_store_test.rs b/consensus/src/quorum_store/tests/batch_store_test.rs index 196255f69e50a..2992700b05dd2 100644 --- a/consensus/src/quorum_store/tests/batch_store_test.rs +++ b/consensus/src/quorum_store/tests/batch_store_test.rs @@ -30,6 +30,7 @@ pub fn batch_store_for_test(memory_quota: usize) -> Arc { Arc::new(BatchStore::new( 10, // epoch + false, 10, // last committed round db, memory_quota, // memory_quota @@ -61,8 +62,8 @@ fn request_for_test( ) } -#[test] -fn test_insert_expire() { +#[tokio::test] +async fn test_insert_expire() { let batch_store = batch_store_for_test(30); let digest = HashValue::random(); @@ -226,8 +227,8 @@ fn test_quota_manager() { assert_ok_eq!(qm.update_quota(2), StorageMode::MemoryAndPersisted); } -#[test] -fn test_get_local_batch() { +#[tokio::test] +async fn test_get_local_batch() { let store = batch_store_for_test(30); let digest_1 = HashValue::random(); From 83377943588abd58f516054e75baa95d340f3d50 Mon Sep 17 00:00:00 2001 From: Balaji Arun Date: Mon, 2 Dec 2024 19:13:54 -0800 Subject: [PATCH 12/78] [forge] update memory thresholds for Forge stable --- testsuite/forge-cli/src/suites/realistic_environment.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testsuite/forge-cli/src/suites/realistic_environment.rs b/testsuite/forge-cli/src/suites/realistic_environment.rs index 28a1e6e20e2b8..dfa3ba868b885 100644 --- a/testsuite/forge-cli/src/suites/realistic_environment.rs +++ b/testsuite/forge-cli/src/suites/realistic_environment.rs @@ -262,9 +262,9 @@ pub(crate) fn realistic_env_graceful_overload(duration: Duration) -> ForgeConfig // overload test uses more CPUs than others, so increase the limit // Check that we don't use more than 28 CPU cores for 20% of the time. MetricsThreshold::new(28.0, 20), - // Memory starts around 6GB, and grows around 8GB/hr in this test. + // Memory starts around 7GB, and grows around 8GB/hr in this test. // Check that we don't use more than final expected memory for more than 20% of the time. - MetricsThreshold::new_gb(6.5 + 8.0 * (duration.as_secs_f64() / 3600.0), 20), + MetricsThreshold::new_gb(7.5 + 8.0 * (duration.as_secs_f64() / 3600.0), 20), )) .add_latency_threshold(10.0, LatencyType::P50) .add_latency_threshold(30.0, LatencyType::P90) From fe96e6dc50ac1b2a64dad88f8c33c26c7ee7c831 Mon Sep 17 00:00:00 2001 From: Balaji Arun Date: Wed, 4 Dec 2024 13:11:27 -0800 Subject: [PATCH 13/78] revert pipeline flag --- testsuite/forge/src/config.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/testsuite/forge/src/config.rs b/testsuite/forge/src/config.rs index 7d173941b8e26..940589e7fb3b1 100644 --- a/testsuite/forge/src/config.rs +++ b/testsuite/forge/src/config.rs @@ -238,10 +238,6 @@ impl ForgeConfig { ["enable_storage_sharding"] = true.into(); helm_values["validator"]["config"]["indexer_db_config"]["enable_event"] = true.into(); helm_values["fullnode"]["config"]["indexer_db_config"]["enable_event"] = true.into(); - // enable new pipeline - helm_values["validator"]["config"]["consensus"]["enable_pipeline"] = true.into(); - helm_values["fullnode"]["config"]["consensus_observer"]["enable_pipeline"] = - true.into(); })) } From 966452ae38af4bb2ef16b78c6d88009e6eea0185 Mon Sep 17 00:00:00 2001 From: Vineeth Kashyap Date: Wed, 4 Dec 2024 17:45:16 -0500 Subject: [PATCH 14/78] [compiler-v2] Do not include vector module for compiler v1 (#15484) --- third_party/move/move-model/src/lib.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/third_party/move/move-model/src/lib.rs b/third_party/move/move-model/src/lib.rs index 7242281bb1748..737a5a847021d 100644 --- a/third_party/move/move-model/src/lib.rs +++ b/third_party/move/move-model/src/lib.rs @@ -330,12 +330,14 @@ pub fn run_model_builder_with_options_and_compilation_flags< let mut expansion_ast = { let E::Program { modules, scripts } = expansion_ast; let modules = modules.filter_map(|mident, mut mdef| { - // Always need to include the vector module because it can be implicitly used. - // TODO(#12492): we can remove this once this bug is fixed + // We need to always include the `vector` module (only for compiler v2), + // to handle cases of implicit usage. + // E.g., index operation on a vector results in a call to `vector::borrow`. + // TODO(#15483): consider refactoring code to avoid this special case. let is_vector = mident.value.address.into_addr_bytes().into_inner() == AccountAddress::ONE && mident.value.module.0.value.as_str() == "vector"; - (is_vector || visited_modules.contains(&mident.value)).then(|| { + (is_vector && compile_via_model || visited_modules.contains(&mident.value)).then(|| { mdef.is_source_module = true; mdef }) From c6f57523cf2923b1208022044282112c1904c217 Mon Sep 17 00:00:00 2001 From: "Brian R. Murphy" <132495859+brmataptos@users.noreply.github.com> Date: Wed, 4 Dec 2024 15:23:46 -0800 Subject: [PATCH 15/78] [move-compiler-v2] clean up a few remaining issues in lambda parser/front-end code (#15365) - Distinguish between "not supported" and "not implemented" for lambda features. - Add a test case to illustrate the function name aliasing issue ([Bug][move-compiler-v2] visible function names shadow local variables with same name in function calls #15360), but changed other tests here to avoid it. - Remove Constraint::NoFunction as it's too broad. - Make sure there are still errors for all planned unsupported cases - Fix LambdaLifter case for bound free variable without copy. - Refine lambda test cases to make _ok versions that compile up to "not implemented" errors. --- .../src/bytecode_generator.rs | 38 +- .../src/env_pipeline/lambda_lifter.rs | 2 +- .../file_format_generator/module_generator.rs | 2 +- .../inlining/function_name_shadowing.exp | 66 + .../inlining/function_name_shadowing.move | 30 + .../tests/checking/typing/lambda.exp | 8 - .../tests/checking/typing/lambda_typed.exp | 8 - .../inline-parity/subtype_args.lambda.exp | 4 +- .../move-compiler-v2/tests/lambda/lambda.exp | 8 - .../tests/lambda/lambda.lambda.exp | 8 - .../tests/lambda/lambda4.lambda.exp | 2 +- .../tests/lambda/storable/closure_args.exp | 781 +++ .../lambda/storable/closure_args.lambda.exp | 5456 +++++++++++++++++ .../tests/lambda/storable/closure_args.move | 287 + .../tests/lambda/storable/doable_func.exp | 24 +- .../lambda/storable/doable_func.lambda.exp | 445 +- .../tests/lambda/storable/doable_func.move | 20 +- .../storable/registry_errors.lambda.exp | 21 +- .../tests/lambda/storable/registry_ok.exp | 38 +- .../lambda/storable/registry_ok.lambda.exp | 48 +- .../tests/lambda/storable/registry_ok.move | 25 +- .../tests/lambda/storable/registry_ok2.exp | 61 + .../lambda/storable/registry_ok2.lambda.exp | 1909 ++++++ .../tests/lambda/storable/registry_ok2.move | 128 + .../lambda/storable/return_func.lambda.exp | 16 - .../tests/lambda/storable/return_func_ok.exp | 187 + .../lambda/storable/return_func_ok.lambda.exp | 1572 +++++ .../tests/lambda/storable/return_func_ok.move | 106 + .../inlining/function_name_shadowing.exp | 27 + .../inlining/function_name_shadowing.move | 30 + .../inlining/function_name_shadowing.move | 30 + .../inlining/function_name_shadowing.exp | 4 + .../inlining/function_name_shadowing.move | 30 + third_party/move/move-model/src/ty.rs | 40 +- .../boogie-backend/src/boogie_helpers.rs | 2 +- .../boogie-backend/src/spec_translator.rs | 12 +- .../tests/sources/functional/restrictions.exp | 4 +- .../sources/functional/restrictions.v2_exp | 4 +- 38 files changed, 10999 insertions(+), 484 deletions(-) create mode 100644 third_party/move/move-compiler-v2/tests/checking/inlining/function_name_shadowing.exp create mode 100644 third_party/move/move-compiler-v2/tests/checking/inlining/function_name_shadowing.move create mode 100644 third_party/move/move-compiler-v2/tests/lambda/storable/closure_args.exp create mode 100644 third_party/move/move-compiler-v2/tests/lambda/storable/closure_args.lambda.exp create mode 100644 third_party/move/move-compiler-v2/tests/lambda/storable/closure_args.move create mode 100644 third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok2.exp create mode 100644 third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok2.lambda.exp create mode 100644 third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok2.move create mode 100644 third_party/move/move-compiler-v2/tests/lambda/storable/return_func_ok.exp create mode 100644 third_party/move/move-compiler-v2/tests/lambda/storable/return_func_ok.lambda.exp create mode 100644 third_party/move/move-compiler-v2/tests/lambda/storable/return_func_ok.move create mode 100644 third_party/move/move-compiler-v2/transactional-tests/tests/inlining/function_name_shadowing.exp create mode 100644 third_party/move/move-compiler-v2/transactional-tests/tests/inlining/function_name_shadowing.move create mode 100644 third_party/move/move-compiler/tests/move_check/inlining/function_name_shadowing.move create mode 100644 third_party/move/move-compiler/transactional-tests/tests/inlining/function_name_shadowing.exp create mode 100644 third_party/move/move-compiler/transactional-tests/tests/inlining/function_name_shadowing.move diff --git a/third_party/move/move-compiler-v2/src/bytecode_generator.rs b/third_party/move/move-compiler-v2/src/bytecode_generator.rs index 19d571863998a..e6be8ca0e80c5 100644 --- a/third_party/move/move-compiler-v2/src/bytecode_generator.rs +++ b/third_party/move/move-compiler-v2/src/bytecode_generator.rs @@ -2,6 +2,7 @@ // Parts of the project are originally copyright © Meta Platforms, Inc. // SPDX-License-Identifier: Apache-2.0 +use crate::{experiments::Experiment, Options}; use codespan_reporting::diagnostic::Severity; use ethnum::U256; use itertools::Itertools; @@ -324,6 +325,14 @@ impl<'env> Generator<'env> { let loc = env.get_node_loc(id); env.diag(severity, &loc, msg.as_ref()) } + + fn check_if_lambdas_enabled(&self) -> bool { + let options = self + .env() + .get_extension::() + .expect("Options is available"); + options.experiment_on(Experiment::LAMBDA_VALUES) + } } // ====================================================================================== @@ -480,14 +489,23 @@ impl<'env> Generator<'env> { self.emit_with(*id, |attr| Bytecode::SpecBlock(attr, spec)); }, // TODO(LAMBDA) - ExpData::Lambda(id, _, _, _, _) => self.error( + ExpData::Lambda(id, _, _, _, _) => + self.error( *id, - "Function-typed values not yet supported except as parameters to calls to inline functions", + if self.check_if_lambdas_enabled() { + "Function-typed values not yet implemented except as parameters to calls to inline functions" + } else { + "Function-typed values not yet supported except as parameters to calls to inline functions" + } ), // TODO(LAMBDA) ExpData::Invoke(id, _exp, _) => self.error( *id, - "Calls to function values other than inline function parameters not yet supported", + if self.check_if_lambdas_enabled() { + "Calls to function values other than inline function parameters not yet implemented" + } else { + "Calls to function values other than inline function parameters not yet supported" + } ), ExpData::Quant(id, _, _, _, _, _) => { self.internal_error(*id, "unsupported specification construct") @@ -564,10 +582,16 @@ impl<'env> Generator<'env> { Constant::Bool(false) } }, + // TODO(LAMBDA) Value::Function(_mid, _fid) => { self.error( id, - "Function-typed values not yet supported except as parameters to calls to inline functions"); + if self.check_if_lambdas_enabled() { + "Function-typed values not yet implemented except as parameters to calls to inline functions" + } else { + "Function-typed values not yet supported except as parameters to calls to inline functions" + } + ); Constant::Bool(false) }, } @@ -794,7 +818,11 @@ impl<'env> Generator<'env> { // TODO(LAMBDA) Operation::EarlyBind => self.error( id, - "Function-typed values not yet supported except as parameters to calls to inline functions", + if self.check_if_lambdas_enabled() { + "Function-typed values not yet implemented except as parameters to calls to inline functions" + } else { + "Function-typed values not yet supported except as parameters to calls to inline functions" + }, ), Operation::TestVariants(mid, sid, variants) => { self.gen_test_variants(targets, id, mid.qualified(*sid), variants, args) diff --git a/third_party/move/move-compiler-v2/src/env_pipeline/lambda_lifter.rs b/third_party/move/move-compiler-v2/src/env_pipeline/lambda_lifter.rs index d16593bac2da0..f3f661ba11f30 100644 --- a/third_party/move/move-compiler-v2/src/env_pipeline/lambda_lifter.rs +++ b/third_party/move/move-compiler-v2/src/env_pipeline/lambda_lifter.rs @@ -739,7 +739,7 @@ impl<'a> ExpRewriterFunctions for LambdaLifter<'a> { env.error( &loc, // TODO(LAMBDA) - "Lambdas expressions with `store` ability currently may only be a simple call to an existing `public` function. This lambda expression requires defining a `public` helper function, which is not yet supported." + "The body of a lambdas expression with `store` ability currently must be a simple call to an existing `public` function, with lambda params the same as the *final* arguments to the function call." ); return None; }; diff --git a/third_party/move/move-compiler-v2/src/file_format_generator/module_generator.rs b/third_party/move/move-compiler-v2/src/file_format_generator/module_generator.rs index ce120a5ca1170..96b2904f042a9 100644 --- a/third_party/move/move-compiler-v2/src/file_format_generator/module_generator.rs +++ b/third_party/move/move-compiler-v2/src/file_format_generator/module_generator.rs @@ -372,7 +372,7 @@ impl ModuleGenerator { ctx.error( loc, format!( - "Unexpected type: {}", + "Unimplemented type: {}", ty.display(&ctx.env.get_type_display_ctx()) ), ); diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/function_name_shadowing.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/function_name_shadowing.exp new file mode 100644 index 0000000000000..ff76888fa7377 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/function_name_shadowing.exp @@ -0,0 +1,66 @@ + +Diagnostics: +warning: Unused parameter `f`. Consider removing or prefixing with an underscore: `_f` + ┌─ tests/checking/inlining/function_name_shadowing.move:20:28 + │ +20 │ public inline fun quux(f:|u64, u64|u64, g:|u64|u64, i:|u8|u8, a: u64, b: u64): u64 { + │ ^ + +warning: Unused parameter `g`. Consider removing or prefixing with an underscore: `_g` + ┌─ tests/checking/inlining/function_name_shadowing.move:20:45 + │ +20 │ public inline fun quux(f:|u64, u64|u64, g:|u64|u64, i:|u8|u8, a: u64, b: u64): u64 { + │ ^ + +warning: Unused parameter `i`. Consider removing or prefixing with an underscore: `_i` + ┌─ tests/checking/inlining/function_name_shadowing.move:20:57 + │ +20 │ public inline fun quux(f:|u64, u64|u64, g:|u64|u64, i:|u8|u8, a: u64, b: u64): u64 { + │ ^ + +// -- Model dump before bytecode pipeline +module 0x42::OtherModule { + public fun g(a: u64,b: u64): u64 { + Add(a, b) + } + public fun h(a: u64,b: u64): u64 { + Add(Mul(2, a), b) + } +} // end 0x42::OtherModule +module 0x42::Test { + use 0x42::OtherModule::{g}; // resolved as: 0x42::OtherModule + public fun f(a: u64,b: u64): u64 { + Mul(a, b) + } + public inline fun quux(f: |(u64, u64)|u64,g: |u64|u64,i: |u8|u8,a: u64,b: u64): u64 { + Mul(Mul(Test::f(a, b), OtherModule::g(a, b)), OtherModule::h(a, b)) + } + public fun test_shadowing(): u64 { + Mul(Mul(Test::f(10, 2), OtherModule::g(10, 2)), OtherModule::h(10, 2)) + } +} // end 0x42::Test + +// -- Sourcified model before bytecode pipeline +module 0x42::OtherModule { + public fun g(a: u64, b: u64): u64 { + a + b + } + public fun h(a: u64, b: u64): u64 { + 2 * a + b + } +} +module 0x42::Test { + use 0x42::OtherModule; + public fun f(a: u64, b: u64): u64 { + a * b + } + public inline fun quux(f: |(u64, u64)|u64, g: |u64|u64, i: |u8|u8, a: u64, b: u64): u64 { + f(a, b) * OtherModule::g(a, b) * OtherModule::h(a, b) + } + public fun test_shadowing(): u64 { + f(10, 2) * OtherModule::g(10, 2) * OtherModule::h(10, 2) + } +} + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/function_name_shadowing.move b/third_party/move/move-compiler-v2/tests/checking/inlining/function_name_shadowing.move new file mode 100644 index 0000000000000..e527c426c7eef --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/function_name_shadowing.move @@ -0,0 +1,30 @@ +//# publish +module 0x42::OtherModule { + public fun g(a: u64, b: u64): u64 { + a + b + } + + public fun h(a: u64, b: u64): u64 { + 2 * a + b + } +} + +//# publish +module 0x42::Test { + use 0x42::OtherModule::g; + + public fun f(a: u64, b: u64): u64 { + a * b + } + + public inline fun quux(f:|u64, u64|u64, g:|u64|u64, i:|u8|u8, a: u64, b: u64): u64 { + use 0x42::OtherModule::h; + f(a, b) * g(a, b) * h(a, b) + } + + public fun test_shadowing(): u64 { + quux(|a, b| a - b, |a| a + 2, |b| 255u8-b, 10, 2) + } +} + +//# run 0x42::Test::test_shadowing diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/lambda.exp b/third_party/move/move-compiler-v2/tests/checking/typing/lambda.exp index 51ad60912dcd3..ec2b425961e52 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/lambda.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/lambda.exp @@ -48,11 +48,3 @@ error: tuple type `()` is not allowed as a type argument (type was inferred) │ ^ │ = required by instantiating type parameter `T` of function `foreach` - -error: function type `|u64|u64` is not allowed as a field type - ┌─ tests/checking/typing/lambda.move:81:12 - │ -81 │ f: |u64|u64, // expected lambda not allowed - │ ^^^^^^^^ - │ - = required by declaration of field `f` diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/lambda_typed.exp b/third_party/move/move-compiler-v2/tests/checking/typing/lambda_typed.exp index b3c6fa59c5fb7..e12ab89c8a728 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/lambda_typed.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/lambda_typed.exp @@ -35,11 +35,3 @@ error: cannot pass `|&u64|u64 with copy+store` to a function which expects argum │ 73 │ foreach(&v, |e: &u64| { sum = sum + *e; *e }) // expected to have wrong result type of lambda │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: function type `|u64|u64` is not allowed as a field type - ┌─ tests/checking/typing/lambda_typed.move:81:12 - │ -81 │ f: |u64|u64, // expected lambda not allowed - │ ^^^^^^^^ - │ - = required by declaration of field `f` diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/subtype_args.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/subtype_args.lambda.exp index 13fdcad48d3be..9db6927c3bd50 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/subtype_args.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/subtype_args.lambda.exp @@ -532,13 +532,13 @@ module 0x8675309::M { Diagnostics: -error: Calls to function values other than inline function parameters not yet supported +error: Calls to function values other than inline function parameters not yet implemented ┌─ tests/lambda/inline-parity/subtype_args.move:24:9 │ 24 │ f(&mut 0, &mut 0); │ ^^^^^^^^^^^^^^^^^ -error: Calls to function values other than inline function parameters not yet supported +error: Calls to function values other than inline function parameters not yet implemented ┌─ tests/lambda/inline-parity/subtype_args.move:25:9 │ 25 │ f(&0, &mut 0); diff --git a/third_party/move/move-compiler-v2/tests/lambda/lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/lambda.exp index 7328ae7924537..a21a059fa0d53 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/lambda.exp @@ -48,11 +48,3 @@ error: tuple type `()` is not allowed as a type argument (type was inferred) │ ^ │ = required by instantiating type parameter `T` of function `foreach` - -error: function type `|u64|u64` is not allowed as a field type - ┌─ tests/lambda/lambda.move:81:12 - │ -81 │ f: |u64|u64, // expected lambda not allowed - │ ^^^^^^^^ - │ - = required by declaration of field `f` diff --git a/third_party/move/move-compiler-v2/tests/lambda/lambda.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/lambda.lambda.exp index 7328ae7924537..a21a059fa0d53 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/lambda.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/lambda.lambda.exp @@ -48,11 +48,3 @@ error: tuple type `()` is not allowed as a type argument (type was inferred) │ ^ │ = required by instantiating type parameter `T` of function `foreach` - -error: function type `|u64|u64` is not allowed as a field type - ┌─ tests/lambda/lambda.move:81:12 - │ -81 │ f: |u64|u64, // expected lambda not allowed - │ ^^^^^^^^ - │ - = required by declaration of field `f` diff --git a/third_party/move/move-compiler-v2/tests/lambda/lambda4.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/lambda4.lambda.exp index f374630d851fb..07f8e32499a97 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/lambda4.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/lambda4.lambda.exp @@ -177,7 +177,7 @@ public fun M::fun_result_lambda_not_allowed(): |u64| { Diagnostics: -error: Unexpected type: |u64| +error: Unimplemented type: |u64| ┌─ tests/lambda/lambda4.move:89:16 │ 89 │ public fun fun_result_lambda_not_allowed(): |u64| { // expected lambda not allowed diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/closure_args.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/closure_args.exp new file mode 100644 index 0000000000000..c3015376ea32d --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/closure_args.exp @@ -0,0 +1,781 @@ + +Diagnostics: +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:59:17 + │ +59 │ move |x| base_fun(a, x) + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:61:17 + │ +61 │ move |x| base_fun2(x, a) + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:63:17 + │ +63 │ move |x| copy_fun(a_copy, x) + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:65:17 + │ +65 │ move |x| copy_fun2(x, a_copy) + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:67:17 + │ +67 │ move |x| store_fun(a_store, x) + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:69:17 + │ +69 │ move |x| store_fun2(x, a_store) + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:71:17 + │ +71 │ move |x| both_fun(a_both, x) + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:73:17 + │ +73 │ move |x| both_fun2(x, a_both) + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:75:17 + │ +75 │ move |x| x * 2 + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:88:17 + │ +88 │ move |x| base_fun(a, x) + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:90:17 + │ +90 │ move |x| base_fun2(x, a) + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:92:17 + │ +92 │ move |x| copy_fun(a_copy, x) + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:94:17 + │ +94 │ move |x| copy_fun2(x, a_copy) + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:96:17 + │ +96 │ move |x| store_fun(a_store, x) + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:98:17 + │ +98 │ move |x| store_fun2(x, a_store) + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:100:17 + │ +100 │ move |x| both_fun(a_both, x) + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:102:17 + │ +102 │ move |x| both_fun2(x, a_both) + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:104:17 + │ +104 │ move |x| x * 2 with copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:104:32 + │ +104 │ move |x| x * 2 with copy + │ ^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:119:17 + │ +119 │ move |x| base_fun(a, x) with copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:119:41 + │ +119 │ move |x| base_fun(a, x) with copy + │ ^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:121:17 + │ +121 │ move |x| base_fun2(x, a) with copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:121:42 + │ +121 │ move |x| base_fun2(x, a) with copy + │ ^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:123:17 + │ +123 │ move |x| copy_fun(a_copy, x) with copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:123:46 + │ +123 │ move |x| copy_fun(a_copy, x) with copy + │ ^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:125:17 + │ +125 │ move |x| copy_fun2(x, a_copy) with copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:125:47 + │ +125 │ move |x| copy_fun2(x, a_copy) with copy + │ ^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:127:17 + │ +127 │ move |x| store_fun(a_store, x) with copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:127:48 + │ +127 │ move |x| store_fun(a_store, x) with copy + │ ^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:129:17 + │ +129 │ move |x| store_fun2(x, a_store) with copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:129:49 + │ +129 │ move |x| store_fun2(x, a_store) with copy + │ ^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:131:17 + │ +131 │ move |x| both_fun(a_both, x) with copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:131:46 + │ +131 │ move |x| both_fun(a_both, x) with copy + │ ^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:133:17 + │ +133 │ move |x| both_fun2(x, a_both) with copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:133:47 + │ +133 │ move |x| both_fun2(x, a_both) with copy + │ ^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:135:17 + │ +135 │ move |x| x * 2 with copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:135:32 + │ +135 │ move |x| x * 2 with copy + │ ^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:140:65 + │ +140 │ public fun return_function_copy(key: u64, x: u64): |u64|u64 with copy { + │ ^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:148:17 + │ +148 │ move |x| base_fun(a, x) with copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:148:41 + │ +148 │ move |x| base_fun(a, x) with copy + │ ^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:150:17 + │ +150 │ move |x| base_fun2(x, a) with copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:150:42 + │ +150 │ move |x| base_fun2(x, a) with copy + │ ^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:152:17 + │ +152 │ move |x| copy_fun(a_copy, x) with copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:152:46 + │ +152 │ move |x| copy_fun(a_copy, x) with copy + │ ^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:154:17 + │ +154 │ move |x| copy_fun2(x, a_copy) with copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:154:47 + │ +154 │ move |x| copy_fun2(x, a_copy) with copy + │ ^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:156:17 + │ +156 │ move |x| store_fun(a_store, x) with copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:156:48 + │ +156 │ move |x| store_fun(a_store, x) with copy + │ ^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:158:17 + │ +158 │ move |x| store_fun2(x, a_store) with copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:158:49 + │ +158 │ move |x| store_fun2(x, a_store) with copy + │ ^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:160:17 + │ +160 │ move |x| both_fun(a_both, x) with copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:160:46 + │ +160 │ move |x| both_fun(a_both, x) with copy + │ ^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:162:17 + │ +162 │ move |x| both_fun2(x, a_both) with copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:162:47 + │ +162 │ move |x| both_fun2(x, a_both) with copy + │ ^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:164:17 + │ +164 │ move |x| x * 2 with copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:164:32 + │ +164 │ move |x| x * 2 with copy + │ ^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:178:17 + │ +178 │ move |x| base_fun(a, x) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:178:41 + │ +178 │ move |x| base_fun(a, x) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:180:17 + │ +180 │ move |x| base_fun2(x, a) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:180:42 + │ +180 │ move |x| base_fun2(x, a) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:182:17 + │ +182 │ move |x| copy_fun(a_copy, x) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:182:46 + │ +182 │ move |x| copy_fun(a_copy, x) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:184:17 + │ +184 │ move |x| copy_fun2(x, a_copy) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:184:47 + │ +184 │ move |x| copy_fun2(x, a_copy) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:186:17 + │ +186 │ move |x| store_fun(a_store, x) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:186:48 + │ +186 │ move |x| store_fun(a_store, x) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:188:17 + │ +188 │ move |x| store_fun2(x, a_store) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:188:49 + │ +188 │ move |x| store_fun2(x, a_store) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:190:17 + │ +190 │ move |x| both_fun(a_both, x) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:190:46 + │ +190 │ move |x| both_fun(a_both, x) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:192:17 + │ +192 │ move |x| both_fun2(x, a_both) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:192:47 + │ +192 │ move |x| both_fun2(x, a_both) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:194:17 + │ +194 │ move |x| x * 2 with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:194:32 + │ +194 │ move |x| x * 2 with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:199:66 + │ +199 │ public fun return_function_store(key: u64, x: u64): |u64|u64 with store { + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:207:17 + │ +207 │ move |x| base_fun(a, x) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:207:41 + │ +207 │ move |x| base_fun(a, x) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:209:17 + │ +209 │ move |x| base_fun2(x, a) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:209:42 + │ +209 │ move |x| base_fun2(x, a) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:211:17 + │ +211 │ move |x| copy_fun(a_copy, x) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:211:46 + │ +211 │ move |x| copy_fun(a_copy, x) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:213:17 + │ +213 │ move |x| copy_fun2(x, a_copy) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:213:47 + │ +213 │ move |x| copy_fun2(x, a_copy) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:215:17 + │ +215 │ move |x| store_fun(a_store, x) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:215:48 + │ +215 │ move |x| store_fun(a_store, x) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:217:17 + │ +217 │ move |x| store_fun2(x, a_store) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:217:49 + │ +217 │ move |x| store_fun2(x, a_store) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:219:17 + │ +219 │ move |x| both_fun(a_both, x) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:219:46 + │ +219 │ move |x| both_fun(a_both, x) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:221:17 + │ +221 │ move |x| both_fun2(x, a_both) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:221:47 + │ +221 │ move |x| both_fun2(x, a_both) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:223:17 + │ +223 │ move |x| x * 2 with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:223:32 + │ +223 │ move |x| x * 2 with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:238:17 + │ +238 │ move |x| base_fun(a, x) with store+copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:238:41 + │ +238 │ move |x| base_fun(a, x) with store+copy + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:240:17 + │ +240 │ move |x| base_fun2(x, a) with store+copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:240:42 + │ +240 │ move |x| base_fun2(x, a) with store+copy + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:242:17 + │ +242 │ move |x| copy_fun(a_copy, x) with store+copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:242:46 + │ +242 │ move |x| copy_fun(a_copy, x) with store+copy + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:244:17 + │ +244 │ move |x| copy_fun2(x, a_copy) with store+copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:244:47 + │ +244 │ move |x| copy_fun2(x, a_copy) with store+copy + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:246:17 + │ +246 │ move |x| store_fun(a_store, x) with store+copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:246:48 + │ +246 │ move |x| store_fun(a_store, x) with store+copy + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:248:17 + │ +248 │ move |x| store_fun2(x, a_store) with store+copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:248:49 + │ +248 │ move |x| store_fun2(x, a_store) with store+copy + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:250:17 + │ +250 │ move |x| both_fun(a_both, x) with store+copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:250:46 + │ +250 │ move |x| both_fun(a_both, x) with store+copy + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:252:17 + │ +252 │ move |x| both_fun2(x, a_both) with store+copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:252:47 + │ +252 │ move |x| both_fun2(x, a_both) with store+copy + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:254:17 + │ +254 │ move |x| x * 2 with store+copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:254:32 + │ +254 │ move |x| x * 2 with store+copy + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:259:65 + │ +259 │ public fun return_function_both(key: u64, x: u64): |u64|u64 with store+copy { + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:267:17 + │ +267 │ move |x| base_fun(a, x) with store+copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:267:41 + │ +267 │ move |x| base_fun(a, x) with store+copy + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:269:17 + │ +269 │ move |x| base_fun2(x, a) with store+copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:269:42 + │ +269 │ move |x| base_fun2(x, a) with store+copy + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:271:17 + │ +271 │ move |x| copy_fun(a_copy, x) with store+copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:271:46 + │ +271 │ move |x| copy_fun(a_copy, x) with store+copy + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:273:17 + │ +273 │ move |x| copy_fun2(x, a_copy) with store+copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:273:47 + │ +273 │ move |x| copy_fun2(x, a_copy) with store+copy + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:275:17 + │ +275 │ move |x| store_fun(a_store, x) with store+copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:275:48 + │ +275 │ move |x| store_fun(a_store, x) with store+copy + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:277:17 + │ +277 │ move |x| store_fun2(x, a_store) with store+copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:277:49 + │ +277 │ move |x| store_fun2(x, a_store) with store+copy + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:279:17 + │ +279 │ move |x| both_fun(a_both, x) with store+copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:279:46 + │ +279 │ move |x| both_fun(a_both, x) with store+copy + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:281:17 + │ +281 │ move |x| both_fun2(x, a_both) with store+copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:281:47 + │ +281 │ move |x| both_fun2(x, a_both) with store+copy + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:283:17 + │ +283 │ move |x| x * 2 with store+copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/closure_args.move:283:32 + │ +283 │ move |x| x * 2 with store+copy + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/closure_args.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/closure_args.lambda.exp new file mode 100644 index 0000000000000..faf6b4e48d3d4 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/closure_args.lambda.exp @@ -0,0 +1,5456 @@ +// -- Model dump before env processor pipeline: +module 0x42::mod1 { + struct S { + x: u64, + } + struct Sboth { + x: u64, + } + struct Scopy { + x: u64, + } + struct Sstore { + x: u64, + } + public fun base_fun(a: S,b: u64): u64 { + Mul(select mod1::S.x(a), b) + } + public fun base_fun2(a: u64,b: S): u64 { + Mul(a, select mod1::S.x(b)) + } + public fun both_fun(a: Sboth,b: u64): u64 { + Mul(select mod1::Sboth.x(a), b) + } + public fun both_fun2(a: u64,b: Sboth): u64 { + Mul(a, select mod1::Sboth.x(b)) + } + public fun copy_fun(a: Scopy,b: u64): u64 { + Mul(select mod1::Scopy.x(a), b) + } + public fun copy_fun2(a: u64,b: Scopy): u64 { + Mul(a, select mod1::Scopy.x(b)) + } + public fun return_function_base(key: u64,x: u64): |u64|u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) + } else { + move|x: u64| Mul(x, 2) with copy, drop + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun return_function_both(key: u64,x: u64): |u64|u64 with copy+store { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop, store + } else { + move|x: u64| Mul(x, 2) with copy, drop, store + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun return_function_copy(key: u64,x: u64): |u64|u64 with copy { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop + } else { + move|x: u64| Mul(x, 2) with copy, drop + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun return_function_store(key: u64,x: u64): |u64|u64 with store { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with drop, store + } else { + move|x: u64| Mul(x, 2) with drop, store + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun store_fun(a: Sstore,b: u64): u64 { + Mul(select mod1::Sstore.x(a), b) + } + public fun store_fun2(a: u64,b: Sstore): u64 { + Mul(a, select mod1::Sstore.x(b)) + } + public fun use_function_base(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) + } else { + move|x: u64| Mul(x, 2) + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } + public fun use_function_both(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop, store + } else { + move|x: u64| Mul(x, 2) with copy, drop, store + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } + public fun use_function_copy(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop + } else { + move|x: u64| Mul(x, 2) with copy, drop + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } + public fun use_function_store(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with drop, store + } else { + move|x: u64| Mul(x, 2) with drop, store + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } +} // end 0x42::mod1 + + +// -- Model dump after env processor unused checks: +module 0x42::mod1 { + struct S { + x: u64, + } + struct Sboth { + x: u64, + } + struct Scopy { + x: u64, + } + struct Sstore { + x: u64, + } + public fun base_fun(a: S,b: u64): u64 { + Mul(select mod1::S.x(a), b) + } + public fun base_fun2(a: u64,b: S): u64 { + Mul(a, select mod1::S.x(b)) + } + public fun both_fun(a: Sboth,b: u64): u64 { + Mul(select mod1::Sboth.x(a), b) + } + public fun both_fun2(a: u64,b: Sboth): u64 { + Mul(a, select mod1::Sboth.x(b)) + } + public fun copy_fun(a: Scopy,b: u64): u64 { + Mul(select mod1::Scopy.x(a), b) + } + public fun copy_fun2(a: u64,b: Scopy): u64 { + Mul(a, select mod1::Scopy.x(b)) + } + public fun return_function_base(key: u64,x: u64): |u64|u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) + } else { + move|x: u64| Mul(x, 2) with copy, drop + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun return_function_both(key: u64,x: u64): |u64|u64 with copy+store { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop, store + } else { + move|x: u64| Mul(x, 2) with copy, drop, store + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun return_function_copy(key: u64,x: u64): |u64|u64 with copy { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop + } else { + move|x: u64| Mul(x, 2) with copy, drop + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun return_function_store(key: u64,x: u64): |u64|u64 with store { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with drop, store + } else { + move|x: u64| Mul(x, 2) with drop, store + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun store_fun(a: Sstore,b: u64): u64 { + Mul(select mod1::Sstore.x(a), b) + } + public fun store_fun2(a: u64,b: Sstore): u64 { + Mul(a, select mod1::Sstore.x(b)) + } + public fun use_function_base(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) + } else { + move|x: u64| Mul(x, 2) + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } + public fun use_function_both(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop, store + } else { + move|x: u64| Mul(x, 2) with copy, drop, store + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } + public fun use_function_copy(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop + } else { + move|x: u64| Mul(x, 2) with copy, drop + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } + public fun use_function_store(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with drop, store + } else { + move|x: u64| Mul(x, 2) with drop, store + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } +} // end 0x42::mod1 + + +// -- Model dump after env processor type parameter check: +module 0x42::mod1 { + struct S { + x: u64, + } + struct Sboth { + x: u64, + } + struct Scopy { + x: u64, + } + struct Sstore { + x: u64, + } + public fun base_fun(a: S,b: u64): u64 { + Mul(select mod1::S.x(a), b) + } + public fun base_fun2(a: u64,b: S): u64 { + Mul(a, select mod1::S.x(b)) + } + public fun both_fun(a: Sboth,b: u64): u64 { + Mul(select mod1::Sboth.x(a), b) + } + public fun both_fun2(a: u64,b: Sboth): u64 { + Mul(a, select mod1::Sboth.x(b)) + } + public fun copy_fun(a: Scopy,b: u64): u64 { + Mul(select mod1::Scopy.x(a), b) + } + public fun copy_fun2(a: u64,b: Scopy): u64 { + Mul(a, select mod1::Scopy.x(b)) + } + public fun return_function_base(key: u64,x: u64): |u64|u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) + } else { + move|x: u64| Mul(x, 2) with copy, drop + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun return_function_both(key: u64,x: u64): |u64|u64 with copy+store { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop, store + } else { + move|x: u64| Mul(x, 2) with copy, drop, store + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun return_function_copy(key: u64,x: u64): |u64|u64 with copy { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop + } else { + move|x: u64| Mul(x, 2) with copy, drop + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun return_function_store(key: u64,x: u64): |u64|u64 with store { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with drop, store + } else { + move|x: u64| Mul(x, 2) with drop, store + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun store_fun(a: Sstore,b: u64): u64 { + Mul(select mod1::Sstore.x(a), b) + } + public fun store_fun2(a: u64,b: Sstore): u64 { + Mul(a, select mod1::Sstore.x(b)) + } + public fun use_function_base(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) + } else { + move|x: u64| Mul(x, 2) + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } + public fun use_function_both(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop, store + } else { + move|x: u64| Mul(x, 2) with copy, drop, store + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } + public fun use_function_copy(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop + } else { + move|x: u64| Mul(x, 2) with copy, drop + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } + public fun use_function_store(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with drop, store + } else { + move|x: u64| Mul(x, 2) with drop, store + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } +} // end 0x42::mod1 + + +// -- Model dump after env processor check recursive struct definition: +module 0x42::mod1 { + struct S { + x: u64, + } + struct Sboth { + x: u64, + } + struct Scopy { + x: u64, + } + struct Sstore { + x: u64, + } + public fun base_fun(a: S,b: u64): u64 { + Mul(select mod1::S.x(a), b) + } + public fun base_fun2(a: u64,b: S): u64 { + Mul(a, select mod1::S.x(b)) + } + public fun both_fun(a: Sboth,b: u64): u64 { + Mul(select mod1::Sboth.x(a), b) + } + public fun both_fun2(a: u64,b: Sboth): u64 { + Mul(a, select mod1::Sboth.x(b)) + } + public fun copy_fun(a: Scopy,b: u64): u64 { + Mul(select mod1::Scopy.x(a), b) + } + public fun copy_fun2(a: u64,b: Scopy): u64 { + Mul(a, select mod1::Scopy.x(b)) + } + public fun return_function_base(key: u64,x: u64): |u64|u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) + } else { + move|x: u64| Mul(x, 2) with copy, drop + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun return_function_both(key: u64,x: u64): |u64|u64 with copy+store { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop, store + } else { + move|x: u64| Mul(x, 2) with copy, drop, store + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun return_function_copy(key: u64,x: u64): |u64|u64 with copy { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop + } else { + move|x: u64| Mul(x, 2) with copy, drop + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun return_function_store(key: u64,x: u64): |u64|u64 with store { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with drop, store + } else { + move|x: u64| Mul(x, 2) with drop, store + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun store_fun(a: Sstore,b: u64): u64 { + Mul(select mod1::Sstore.x(a), b) + } + public fun store_fun2(a: u64,b: Sstore): u64 { + Mul(a, select mod1::Sstore.x(b)) + } + public fun use_function_base(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) + } else { + move|x: u64| Mul(x, 2) + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } + public fun use_function_both(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop, store + } else { + move|x: u64| Mul(x, 2) with copy, drop, store + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } + public fun use_function_copy(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop + } else { + move|x: u64| Mul(x, 2) with copy, drop + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } + public fun use_function_store(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with drop, store + } else { + move|x: u64| Mul(x, 2) with drop, store + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } +} // end 0x42::mod1 + + +// -- Model dump after env processor check cyclic type instantiation: +module 0x42::mod1 { + struct S { + x: u64, + } + struct Sboth { + x: u64, + } + struct Scopy { + x: u64, + } + struct Sstore { + x: u64, + } + public fun base_fun(a: S,b: u64): u64 { + Mul(select mod1::S.x(a), b) + } + public fun base_fun2(a: u64,b: S): u64 { + Mul(a, select mod1::S.x(b)) + } + public fun both_fun(a: Sboth,b: u64): u64 { + Mul(select mod1::Sboth.x(a), b) + } + public fun both_fun2(a: u64,b: Sboth): u64 { + Mul(a, select mod1::Sboth.x(b)) + } + public fun copy_fun(a: Scopy,b: u64): u64 { + Mul(select mod1::Scopy.x(a), b) + } + public fun copy_fun2(a: u64,b: Scopy): u64 { + Mul(a, select mod1::Scopy.x(b)) + } + public fun return_function_base(key: u64,x: u64): |u64|u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) + } else { + move|x: u64| Mul(x, 2) with copy, drop + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun return_function_both(key: u64,x: u64): |u64|u64 with copy+store { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop, store + } else { + move|x: u64| Mul(x, 2) with copy, drop, store + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun return_function_copy(key: u64,x: u64): |u64|u64 with copy { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop + } else { + move|x: u64| Mul(x, 2) with copy, drop + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun return_function_store(key: u64,x: u64): |u64|u64 with store { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with drop, store + } else { + move|x: u64| Mul(x, 2) with drop, store + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun store_fun(a: Sstore,b: u64): u64 { + Mul(select mod1::Sstore.x(a), b) + } + public fun store_fun2(a: u64,b: Sstore): u64 { + Mul(a, select mod1::Sstore.x(b)) + } + public fun use_function_base(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) + } else { + move|x: u64| Mul(x, 2) + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } + public fun use_function_both(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop, store + } else { + move|x: u64| Mul(x, 2) with copy, drop, store + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } + public fun use_function_copy(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop + } else { + move|x: u64| Mul(x, 2) with copy, drop + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } + public fun use_function_store(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with drop, store + } else { + move|x: u64| Mul(x, 2) with drop, store + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } +} // end 0x42::mod1 + + +// -- Model dump after env processor unused struct params check: +module 0x42::mod1 { + struct S { + x: u64, + } + struct Sboth { + x: u64, + } + struct Scopy { + x: u64, + } + struct Sstore { + x: u64, + } + public fun base_fun(a: S,b: u64): u64 { + Mul(select mod1::S.x(a), b) + } + public fun base_fun2(a: u64,b: S): u64 { + Mul(a, select mod1::S.x(b)) + } + public fun both_fun(a: Sboth,b: u64): u64 { + Mul(select mod1::Sboth.x(a), b) + } + public fun both_fun2(a: u64,b: Sboth): u64 { + Mul(a, select mod1::Sboth.x(b)) + } + public fun copy_fun(a: Scopy,b: u64): u64 { + Mul(select mod1::Scopy.x(a), b) + } + public fun copy_fun2(a: u64,b: Scopy): u64 { + Mul(a, select mod1::Scopy.x(b)) + } + public fun return_function_base(key: u64,x: u64): |u64|u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) + } else { + move|x: u64| Mul(x, 2) with copy, drop + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun return_function_both(key: u64,x: u64): |u64|u64 with copy+store { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop, store + } else { + move|x: u64| Mul(x, 2) with copy, drop, store + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun return_function_copy(key: u64,x: u64): |u64|u64 with copy { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop + } else { + move|x: u64| Mul(x, 2) with copy, drop + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun return_function_store(key: u64,x: u64): |u64|u64 with store { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with drop, store + } else { + move|x: u64| Mul(x, 2) with drop, store + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun store_fun(a: Sstore,b: u64): u64 { + Mul(select mod1::Sstore.x(a), b) + } + public fun store_fun2(a: u64,b: Sstore): u64 { + Mul(a, select mod1::Sstore.x(b)) + } + public fun use_function_base(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) + } else { + move|x: u64| Mul(x, 2) + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } + public fun use_function_both(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop, store + } else { + move|x: u64| Mul(x, 2) with copy, drop, store + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } + public fun use_function_copy(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop + } else { + move|x: u64| Mul(x, 2) with copy, drop + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } + public fun use_function_store(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with drop, store + } else { + move|x: u64| Mul(x, 2) with drop, store + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } +} // end 0x42::mod1 + + +// -- Model dump after env processor access and use check before inlining: +module 0x42::mod1 { + struct S { + x: u64, + } + struct Sboth { + x: u64, + } + struct Scopy { + x: u64, + } + struct Sstore { + x: u64, + } + public fun base_fun(a: S,b: u64): u64 { + Mul(select mod1::S.x(a), b) + } + public fun base_fun2(a: u64,b: S): u64 { + Mul(a, select mod1::S.x(b)) + } + public fun both_fun(a: Sboth,b: u64): u64 { + Mul(select mod1::Sboth.x(a), b) + } + public fun both_fun2(a: u64,b: Sboth): u64 { + Mul(a, select mod1::Sboth.x(b)) + } + public fun copy_fun(a: Scopy,b: u64): u64 { + Mul(select mod1::Scopy.x(a), b) + } + public fun copy_fun2(a: u64,b: Scopy): u64 { + Mul(a, select mod1::Scopy.x(b)) + } + public fun return_function_base(key: u64,x: u64): |u64|u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) + } else { + move|x: u64| Mul(x, 2) with copy, drop + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun return_function_both(key: u64,x: u64): |u64|u64 with copy+store { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop, store + } else { + move|x: u64| Mul(x, 2) with copy, drop, store + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun return_function_copy(key: u64,x: u64): |u64|u64 with copy { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop + } else { + move|x: u64| Mul(x, 2) with copy, drop + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun return_function_store(key: u64,x: u64): |u64|u64 with store { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with drop, store + } else { + move|x: u64| Mul(x, 2) with drop, store + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun store_fun(a: Sstore,b: u64): u64 { + Mul(select mod1::Sstore.x(a), b) + } + public fun store_fun2(a: u64,b: Sstore): u64 { + Mul(a, select mod1::Sstore.x(b)) + } + public fun use_function_base(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) + } else { + move|x: u64| Mul(x, 2) + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } + public fun use_function_both(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop, store + } else { + move|x: u64| Mul(x, 2) with copy, drop, store + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } + public fun use_function_copy(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop + } else { + move|x: u64| Mul(x, 2) with copy, drop + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } + public fun use_function_store(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with drop, store + } else { + move|x: u64| Mul(x, 2) with drop, store + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } +} // end 0x42::mod1 + + +// -- Model dump after env processor inlining: +module 0x42::mod1 { + struct S { + x: u64, + } + struct Sboth { + x: u64, + } + struct Scopy { + x: u64, + } + struct Sstore { + x: u64, + } + public fun base_fun(a: S,b: u64): u64 { + Mul(select mod1::S.x(a), b) + } + public fun base_fun2(a: u64,b: S): u64 { + Mul(a, select mod1::S.x(b)) + } + public fun both_fun(a: Sboth,b: u64): u64 { + Mul(select mod1::Sboth.x(a), b) + } + public fun both_fun2(a: u64,b: Sboth): u64 { + Mul(a, select mod1::Sboth.x(b)) + } + public fun copy_fun(a: Scopy,b: u64): u64 { + Mul(select mod1::Scopy.x(a), b) + } + public fun copy_fun2(a: u64,b: Scopy): u64 { + Mul(a, select mod1::Scopy.x(b)) + } + public fun return_function_base(key: u64,x: u64): |u64|u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) + } else { + move|x: u64| Mul(x, 2) with copy, drop + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun return_function_both(key: u64,x: u64): |u64|u64 with copy+store { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop, store + } else { + move|x: u64| Mul(x, 2) with copy, drop, store + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun return_function_copy(key: u64,x: u64): |u64|u64 with copy { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop + } else { + move|x: u64| Mul(x, 2) with copy, drop + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun return_function_store(key: u64,x: u64): |u64|u64 with store { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with drop, store + } else { + move|x: u64| Mul(x, 2) with drop, store + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun store_fun(a: Sstore,b: u64): u64 { + Mul(select mod1::Sstore.x(a), b) + } + public fun store_fun2(a: u64,b: Sstore): u64 { + Mul(a, select mod1::Sstore.x(b)) + } + public fun use_function_base(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) + } else { + move|x: u64| Mul(x, 2) + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } + public fun use_function_both(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop, store + } else { + move|x: u64| Mul(x, 2) with copy, drop, store + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } + public fun use_function_copy(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop + } else { + move|x: u64| Mul(x, 2) with copy, drop + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } + public fun use_function_store(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with drop, store + } else { + move|x: u64| Mul(x, 2) with drop, store + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } +} // end 0x42::mod1 + + +// -- Model dump after env processor access and use check after inlining: +module 0x42::mod1 { + struct S { + x: u64, + } + struct Sboth { + x: u64, + } + struct Scopy { + x: u64, + } + struct Sstore { + x: u64, + } + public fun base_fun(a: S,b: u64): u64 { + Mul(select mod1::S.x(a), b) + } + public fun base_fun2(a: u64,b: S): u64 { + Mul(a, select mod1::S.x(b)) + } + public fun both_fun(a: Sboth,b: u64): u64 { + Mul(select mod1::Sboth.x(a), b) + } + public fun both_fun2(a: u64,b: Sboth): u64 { + Mul(a, select mod1::Sboth.x(b)) + } + public fun copy_fun(a: Scopy,b: u64): u64 { + Mul(select mod1::Scopy.x(a), b) + } + public fun copy_fun2(a: u64,b: Scopy): u64 { + Mul(a, select mod1::Scopy.x(b)) + } + public fun return_function_base(key: u64,x: u64): |u64|u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) + } else { + move|x: u64| Mul(x, 2) with copy, drop + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun return_function_both(key: u64,x: u64): |u64|u64 with copy+store { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop, store + } else { + move|x: u64| Mul(x, 2) with copy, drop, store + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun return_function_copy(key: u64,x: u64): |u64|u64 with copy { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop + } else { + move|x: u64| Mul(x, 2) with copy, drop + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun return_function_store(key: u64,x: u64): |u64|u64 with store { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with drop, store + } else { + move|x: u64| Mul(x, 2) with drop, store + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun store_fun(a: Sstore,b: u64): u64 { + Mul(select mod1::Sstore.x(a), b) + } + public fun store_fun2(a: u64,b: Sstore): u64 { + Mul(a, select mod1::Sstore.x(b)) + } + public fun use_function_base(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) + } else { + move|x: u64| Mul(x, 2) + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } + public fun use_function_both(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop, store + } else { + move|x: u64| Mul(x, 2) with copy, drop, store + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } + public fun use_function_copy(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop + } else { + move|x: u64| Mul(x, 2) with copy, drop + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } + public fun use_function_store(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with drop, store + } else { + move|x: u64| Mul(x, 2) with drop, store + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } +} // end 0x42::mod1 + + +// -- Model dump after env processor acquires check: +module 0x42::mod1 { + struct S { + x: u64, + } + struct Sboth { + x: u64, + } + struct Scopy { + x: u64, + } + struct Sstore { + x: u64, + } + public fun base_fun(a: S,b: u64): u64 { + Mul(select mod1::S.x(a), b) + } + public fun base_fun2(a: u64,b: S): u64 { + Mul(a, select mod1::S.x(b)) + } + public fun both_fun(a: Sboth,b: u64): u64 { + Mul(select mod1::Sboth.x(a), b) + } + public fun both_fun2(a: u64,b: Sboth): u64 { + Mul(a, select mod1::Sboth.x(b)) + } + public fun copy_fun(a: Scopy,b: u64): u64 { + Mul(select mod1::Scopy.x(a), b) + } + public fun copy_fun2(a: u64,b: Scopy): u64 { + Mul(a, select mod1::Scopy.x(b)) + } + public fun return_function_base(key: u64,x: u64): |u64|u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) + } else { + move|x: u64| Mul(x, 2) with copy, drop + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun return_function_both(key: u64,x: u64): |u64|u64 with copy+store { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop, store + } else { + move|x: u64| Mul(x, 2) with copy, drop, store + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun return_function_copy(key: u64,x: u64): |u64|u64 with copy { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop + } else { + move|x: u64| Mul(x, 2) with copy, drop + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun return_function_store(key: u64,x: u64): |u64|u64 with store { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with drop, store + } else { + move|x: u64| Mul(x, 2) with drop, store + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun store_fun(a: Sstore,b: u64): u64 { + Mul(select mod1::Sstore.x(a), b) + } + public fun store_fun2(a: u64,b: Sstore): u64 { + Mul(a, select mod1::Sstore.x(b)) + } + public fun use_function_base(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) + } else { + move|x: u64| Mul(x, 2) + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } + public fun use_function_both(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop, store + } else { + move|x: u64| Mul(x, 2) with copy, drop, store + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } + public fun use_function_copy(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with copy, drop + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop + } else { + move|x: u64| Mul(x, 2) with copy, drop + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } + public fun use_function_store(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + { + let x: u64 = 3; + move|x: u64| mod1::base_fun(a, x) with drop, store + } + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with drop, store + } else { + move|x: u64| Mul(x, 2) with drop, store + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } +} // end 0x42::mod1 + + +// -- Model dump after env processor simplifier: +module 0x42::mod1 { + struct S { + x: u64, + } + struct Sboth { + x: u64, + } + struct Scopy { + x: u64, + } + struct Sstore { + x: u64, + } + public fun base_fun(a: S,b: u64): u64 { + Mul(select mod1::S.x(a), b) + } + public fun base_fun2(a: u64,b: S): u64 { + Mul(a, select mod1::S.x(b)) + } + public fun both_fun(a: Sboth,b: u64): u64 { + Mul(select mod1::Sboth.x(a), b) + } + public fun both_fun2(a: u64,b: Sboth): u64 { + Mul(a, select mod1::Sboth.x(b)) + } + public fun copy_fun(a: Scopy,b: u64): u64 { + Mul(select mod1::Scopy.x(a), b) + } + public fun copy_fun2(a: u64,b: Scopy): u64 { + Mul(a, select mod1::Scopy.x(b)) + } + public fun return_function_base(key: u64,x: u64): |u64|u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + move|x: u64| mod1::base_fun(a, x) + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) + } else { + move|x: u64| Mul(x, 2) with copy, drop + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun return_function_both(key: u64,x: u64): |u64|u64 with copy+store { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + move|x: u64| mod1::base_fun(a, x) with copy, drop, store + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop, store + } else { + move|x: u64| Mul(x, 2) with copy, drop, store + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun return_function_copy(key: u64,x: u64): |u64|u64 with copy { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + move|x: u64| mod1::base_fun(a, x) with copy, drop + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop + } else { + move|x: u64| Mul(x, 2) with copy, drop + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun return_function_store(key: u64,x: u64): |u64|u64 with store { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + move|x: u64| mod1::base_fun(a, x) with drop, store + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with drop, store + } else { + move|x: u64| Mul(x, 2) with drop, store + } + } + } + } + } + } + } + }; + f + } + } + } + } + } + } + public fun store_fun(a: Sstore,b: u64): u64 { + Mul(select mod1::Sstore.x(a), b) + } + public fun store_fun2(a: u64,b: Sstore): u64 { + Mul(a, select mod1::Sstore.x(b)) + } + public fun use_function_base(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + move|x: u64| mod1::base_fun(a, x) + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) + } else { + move|x: u64| Mul(x, 2) + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } + public fun use_function_both(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + move|x: u64| mod1::base_fun(a, x) with copy, drop, store + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop, store + } else { + move|x: u64| Mul(x, 2) with copy, drop, store + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } + public fun use_function_copy(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + move|x: u64| mod1::base_fun(a, x) with copy, drop + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with copy, drop + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with copy, drop + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with copy, drop + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with copy, drop + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with copy, drop + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with copy, drop + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with copy, drop + } else { + move|x: u64| Mul(x, 2) with copy, drop + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } + public fun use_function_store(key: u64,x: u64): u64 { + { + let a: S = pack mod1::S(2); + { + let a_copy: Scopy = pack mod1::Scopy(2); + { + let a_store: Sstore = pack mod1::Sstore(2); + { + let a_both: Sboth = pack mod1::Sboth(2); + { + let f: |u64|u64 with copy+store = if Eq(key, 0) { + move|x: u64| mod1::base_fun(a, x) with drop, store + } else { + if Eq(key, 1) { + move|x: u64| mod1::base_fun2(x, a) with drop, store + } else { + if Eq(key, 2) { + move|x: u64| mod1::copy_fun(a_copy, x) with drop, store + } else { + if Eq(key, 3) { + move|x: u64| mod1::copy_fun2(x, a_copy) with drop, store + } else { + if Eq(key, 4) { + move|x: u64| mod1::store_fun(a_store, x) with drop, store + } else { + if Eq(key, 5) { + move|x: u64| mod1::store_fun2(x, a_store) with drop, store + } else { + if Eq(key, 6) { + move|x: u64| mod1::both_fun(a_both, x) with drop, store + } else { + if Eq(key, 7) { + move|x: u64| mod1::both_fun2(x, a_both) with drop, store + } else { + move|x: u64| Mul(x, 2) with drop, store + } + } + } + } + } + } + } + }; + (f)(x) + } + } + } + } + } + } +} // end 0x42::mod1 + + + +Diagnostics: +warning: Unused local variable `x`. Consider removing or prefixing with an underscore: `_x` + ┌─ tests/lambda/storable/closure_args.move:58:21 + │ +58 │ let x = 3; + │ ^ + +warning: Unused parameter `x`. Consider removing or prefixing with an underscore: `_x` + ┌─ tests/lambda/storable/closure_args.move:80:47 + │ +80 │ public fun return_function_base(key: u64, x: u64): |u64|u64 { + │ ^ + +warning: Unused local variable `x`. Consider removing or prefixing with an underscore: `_x` + ┌─ tests/lambda/storable/closure_args.move:87:21 + │ +87 │ let x = 3; + │ ^ + +warning: Unused local variable `x`. Consider removing or prefixing with an underscore: `_x` + ┌─ tests/lambda/storable/closure_args.move:118:21 + │ +118 │ let x = 3; + │ ^ + +error: Lambda captures free variables with types that do not have some declared abilities: copy + ┌─ tests/lambda/storable/closure_args.move:119:17 + │ +119 │ move |x| base_fun(a, x) with copy + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + │ │ + │ Captured free value is missing abilities: copy + +error: Lambda captures free variables with types that do not have some declared abilities: copy + ┌─ tests/lambda/storable/closure_args.move:127:17 + │ +127 │ move |x| store_fun(a_store, x) with copy + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + │ │ + │ Captured free value is missing abilities: copy + +warning: Unused parameter `x`. Consider removing or prefixing with an underscore: `_x` + ┌─ tests/lambda/storable/closure_args.move:140:47 + │ +140 │ public fun return_function_copy(key: u64, x: u64): |u64|u64 with copy { + │ ^ + +warning: Unused local variable `x`. Consider removing or prefixing with an underscore: `_x` + ┌─ tests/lambda/storable/closure_args.move:147:21 + │ +147 │ let x = 3; + │ ^ + +error: Lambda captures free variables with types that do not have some declared abilities: copy + ┌─ tests/lambda/storable/closure_args.move:148:17 + │ +148 │ move |x| base_fun(a, x) with copy + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + │ │ + │ Captured free value is missing abilities: copy + +error: Lambda captures free variables with types that do not have some declared abilities: copy + ┌─ tests/lambda/storable/closure_args.move:156:17 + │ +156 │ move |x| store_fun(a_store, x) with copy + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + │ │ + │ Captured free value is missing abilities: copy + +warning: Unused local variable `x`. Consider removing or prefixing with an underscore: `_x` + ┌─ tests/lambda/storable/closure_args.move:177:21 + │ +177 │ let x = 3; + │ ^ + +error: Lambda captures free variables with types that do not have some declared abilities: store + ┌─ tests/lambda/storable/closure_args.move:178:17 + │ +178 │ move |x| base_fun(a, x) with store + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + │ │ + │ Captured free value is missing abilities: store + +error: The body of a lambdas expression with `store` ability currently must be a simple call to an existing `public` function, with lambda params the same as the *final* arguments to the function call. + ┌─ tests/lambda/storable/closure_args.move:178:17 + │ +178 │ move |x| base_fun(a, x) with store + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: The body of a lambdas expression with `store` ability currently must be a simple call to an existing `public` function, with lambda params the same as the *final* arguments to the function call. + ┌─ tests/lambda/storable/closure_args.move:180:17 + │ +180 │ move |x| base_fun2(x, a) with store + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Lambda captures free variables with types that do not have some declared abilities: store + ┌─ tests/lambda/storable/closure_args.move:182:17 + │ +182 │ move |x| copy_fun(a_copy, x) with store + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + │ │ + │ Captured free value is missing abilities: store + +error: The body of a lambdas expression with `store` ability currently must be a simple call to an existing `public` function, with lambda params the same as the *final* arguments to the function call. + ┌─ tests/lambda/storable/closure_args.move:182:17 + │ +182 │ move |x| copy_fun(a_copy, x) with store + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: The body of a lambdas expression with `store` ability currently must be a simple call to an existing `public` function, with lambda params the same as the *final* arguments to the function call. + ┌─ tests/lambda/storable/closure_args.move:184:17 + │ +184 │ move |x| copy_fun2(x, a_copy) with store + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: The body of a lambdas expression with `store` ability currently must be a simple call to an existing `public` function, with lambda params the same as the *final* arguments to the function call. + ┌─ tests/lambda/storable/closure_args.move:188:17 + │ +188 │ move |x| store_fun2(x, a_store) with store + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: The body of a lambdas expression with `store` ability currently must be a simple call to an existing `public` function, with lambda params the same as the *final* arguments to the function call. + ┌─ tests/lambda/storable/closure_args.move:192:17 + │ +192 │ move |x| both_fun2(x, a_both) with store + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: The body of a lambdas expression with `store` ability currently must be a simple call to an existing `public` function, with lambda params the same as the *final* arguments to the function call. + ┌─ tests/lambda/storable/closure_args.move:194:17 + │ +194 │ move |x| x * 2 with store + │ ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: Unused parameter `x`. Consider removing or prefixing with an underscore: `_x` + ┌─ tests/lambda/storable/closure_args.move:199:48 + │ +199 │ public fun return_function_store(key: u64, x: u64): |u64|u64 with store { + │ ^ + +warning: Unused local variable `x`. Consider removing or prefixing with an underscore: `_x` + ┌─ tests/lambda/storable/closure_args.move:206:21 + │ +206 │ let x = 3; + │ ^ + +error: Lambda captures free variables with types that do not have some declared abilities: store + ┌─ tests/lambda/storable/closure_args.move:207:17 + │ +207 │ move |x| base_fun(a, x) with store + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + │ │ + │ Captured free value is missing abilities: store + +error: The body of a lambdas expression with `store` ability currently must be a simple call to an existing `public` function, with lambda params the same as the *final* arguments to the function call. + ┌─ tests/lambda/storable/closure_args.move:207:17 + │ +207 │ move |x| base_fun(a, x) with store + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: The body of a lambdas expression with `store` ability currently must be a simple call to an existing `public` function, with lambda params the same as the *final* arguments to the function call. + ┌─ tests/lambda/storable/closure_args.move:209:17 + │ +209 │ move |x| base_fun2(x, a) with store + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Lambda captures free variables with types that do not have some declared abilities: store + ┌─ tests/lambda/storable/closure_args.move:211:17 + │ +211 │ move |x| copy_fun(a_copy, x) with store + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + │ │ + │ Captured free value is missing abilities: store + +error: The body of a lambdas expression with `store` ability currently must be a simple call to an existing `public` function, with lambda params the same as the *final* arguments to the function call. + ┌─ tests/lambda/storable/closure_args.move:211:17 + │ +211 │ move |x| copy_fun(a_copy, x) with store + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: The body of a lambdas expression with `store` ability currently must be a simple call to an existing `public` function, with lambda params the same as the *final* arguments to the function call. + ┌─ tests/lambda/storable/closure_args.move:213:17 + │ +213 │ move |x| copy_fun2(x, a_copy) with store + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: The body of a lambdas expression with `store` ability currently must be a simple call to an existing `public` function, with lambda params the same as the *final* arguments to the function call. + ┌─ tests/lambda/storable/closure_args.move:217:17 + │ +217 │ move |x| store_fun2(x, a_store) with store + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: The body of a lambdas expression with `store` ability currently must be a simple call to an existing `public` function, with lambda params the same as the *final* arguments to the function call. + ┌─ tests/lambda/storable/closure_args.move:221:17 + │ +221 │ move |x| both_fun2(x, a_both) with store + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: The body of a lambdas expression with `store` ability currently must be a simple call to an existing `public` function, with lambda params the same as the *final* arguments to the function call. + ┌─ tests/lambda/storable/closure_args.move:223:17 + │ +223 │ move |x| x * 2 with store + │ ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: Unused local variable `x`. Consider removing or prefixing with an underscore: `_x` + ┌─ tests/lambda/storable/closure_args.move:237:21 + │ +237 │ let x = 3; + │ ^ + +error: Lambda captures free variables with types that do not have some declared abilities: copy + store + ┌─ tests/lambda/storable/closure_args.move:238:17 + │ +238 │ move |x| base_fun(a, x) with store+copy + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + │ │ + │ Captured free value is missing abilities: copy + store + +error: The body of a lambdas expression with `store` ability currently must be a simple call to an existing `public` function, with lambda params the same as the *final* arguments to the function call. + ┌─ tests/lambda/storable/closure_args.move:238:17 + │ +238 │ move |x| base_fun(a, x) with store+copy + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: The body of a lambdas expression with `store` ability currently must be a simple call to an existing `public` function, with lambda params the same as the *final* arguments to the function call. + ┌─ tests/lambda/storable/closure_args.move:240:17 + │ +240 │ move |x| base_fun2(x, a) with store+copy + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Lambda captures free variables with types that do not have some declared abilities: store + ┌─ tests/lambda/storable/closure_args.move:242:17 + │ +242 │ move |x| copy_fun(a_copy, x) with store+copy + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + │ │ + │ Captured free value is missing abilities: store + +error: The body of a lambdas expression with `store` ability currently must be a simple call to an existing `public` function, with lambda params the same as the *final* arguments to the function call. + ┌─ tests/lambda/storable/closure_args.move:242:17 + │ +242 │ move |x| copy_fun(a_copy, x) with store+copy + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: The body of a lambdas expression with `store` ability currently must be a simple call to an existing `public` function, with lambda params the same as the *final* arguments to the function call. + ┌─ tests/lambda/storable/closure_args.move:244:17 + │ +244 │ move |x| copy_fun2(x, a_copy) with store+copy + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Lambda captures free variables with types that do not have some declared abilities: copy + ┌─ tests/lambda/storable/closure_args.move:246:17 + │ +246 │ move |x| store_fun(a_store, x) with store+copy + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + │ │ + │ Captured free value is missing abilities: copy + +error: The body of a lambdas expression with `store` ability currently must be a simple call to an existing `public` function, with lambda params the same as the *final* arguments to the function call. + ┌─ tests/lambda/storable/closure_args.move:246:17 + │ +246 │ move |x| store_fun(a_store, x) with store+copy + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: The body of a lambdas expression with `store` ability currently must be a simple call to an existing `public` function, with lambda params the same as the *final* arguments to the function call. + ┌─ tests/lambda/storable/closure_args.move:248:17 + │ +248 │ move |x| store_fun2(x, a_store) with store+copy + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: The body of a lambdas expression with `store` ability currently must be a simple call to an existing `public` function, with lambda params the same as the *final* arguments to the function call. + ┌─ tests/lambda/storable/closure_args.move:252:17 + │ +252 │ move |x| both_fun2(x, a_both) with store+copy + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: The body of a lambdas expression with `store` ability currently must be a simple call to an existing `public` function, with lambda params the same as the *final* arguments to the function call. + ┌─ tests/lambda/storable/closure_args.move:254:17 + │ +254 │ move |x| x * 2 with store+copy + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: Unused parameter `x`. Consider removing or prefixing with an underscore: `_x` + ┌─ tests/lambda/storable/closure_args.move:259:47 + │ +259 │ public fun return_function_both(key: u64, x: u64): |u64|u64 with store+copy { + │ ^ + +warning: Unused local variable `x`. Consider removing or prefixing with an underscore: `_x` + ┌─ tests/lambda/storable/closure_args.move:266:21 + │ +266 │ let x = 3; + │ ^ + +error: Lambda captures free variables with types that do not have some declared abilities: copy + store + ┌─ tests/lambda/storable/closure_args.move:267:17 + │ +267 │ move |x| base_fun(a, x) with store+copy + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + │ │ + │ Captured free value is missing abilities: copy + store + +error: The body of a lambdas expression with `store` ability currently must be a simple call to an existing `public` function, with lambda params the same as the *final* arguments to the function call. + ┌─ tests/lambda/storable/closure_args.move:267:17 + │ +267 │ move |x| base_fun(a, x) with store+copy + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: The body of a lambdas expression with `store` ability currently must be a simple call to an existing `public` function, with lambda params the same as the *final* arguments to the function call. + ┌─ tests/lambda/storable/closure_args.move:269:17 + │ +269 │ move |x| base_fun2(x, a) with store+copy + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Lambda captures free variables with types that do not have some declared abilities: store + ┌─ tests/lambda/storable/closure_args.move:271:17 + │ +271 │ move |x| copy_fun(a_copy, x) with store+copy + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + │ │ + │ Captured free value is missing abilities: store + +error: The body of a lambdas expression with `store` ability currently must be a simple call to an existing `public` function, with lambda params the same as the *final* arguments to the function call. + ┌─ tests/lambda/storable/closure_args.move:271:17 + │ +271 │ move |x| copy_fun(a_copy, x) with store+copy + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: The body of a lambdas expression with `store` ability currently must be a simple call to an existing `public` function, with lambda params the same as the *final* arguments to the function call. + ┌─ tests/lambda/storable/closure_args.move:273:17 + │ +273 │ move |x| copy_fun2(x, a_copy) with store+copy + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Lambda captures free variables with types that do not have some declared abilities: copy + ┌─ tests/lambda/storable/closure_args.move:275:17 + │ +275 │ move |x| store_fun(a_store, x) with store+copy + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + │ │ + │ Captured free value is missing abilities: copy + +error: The body of a lambdas expression with `store` ability currently must be a simple call to an existing `public` function, with lambda params the same as the *final* arguments to the function call. + ┌─ tests/lambda/storable/closure_args.move:275:17 + │ +275 │ move |x| store_fun(a_store, x) with store+copy + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: The body of a lambdas expression with `store` ability currently must be a simple call to an existing `public` function, with lambda params the same as the *final* arguments to the function call. + ┌─ tests/lambda/storable/closure_args.move:277:17 + │ +277 │ move |x| store_fun2(x, a_store) with store+copy + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: The body of a lambdas expression with `store` ability currently must be a simple call to an existing `public` function, with lambda params the same as the *final* arguments to the function call. + ┌─ tests/lambda/storable/closure_args.move:281:17 + │ +281 │ move |x| both_fun2(x, a_both) with store+copy + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: The body of a lambdas expression with `store` ability currently must be a simple call to an existing `public` function, with lambda params the same as the *final* arguments to the function call. + ┌─ tests/lambda/storable/closure_args.move:283:17 + │ +283 │ move |x| x * 2 with store+copy + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/closure_args.move b/third_party/move/move-compiler-v2/tests/lambda/storable/closure_args.move new file mode 100644 index 0000000000000..375f07e6700cb --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/closure_args.move @@ -0,0 +1,287 @@ +module 0x42::mod1 { + struct S has drop { + x: u64 + } + + struct Scopy has copy, drop { + x: u64 + } + + struct Sstore has store, drop { + x: u64 + } + + struct Sboth has store, copy, drop { + x: u64 + } + + public fun base_fun(a: S, b: u64) : u64 { + a.x * b + } + + public fun base_fun2(a: u64, b: S) : u64 { + a * b.x + } + + public fun copy_fun(a: Scopy, b: u64) : u64 { + a.x * b + } + + public fun copy_fun2(a: u64, b: Scopy) : u64 { + a * b.x + } + + public fun store_fun(a: Sstore, b: u64) : u64 { + a.x * b + } + + public fun store_fun2(a: u64, b: Sstore) : u64 { + a * b.x + } + + public fun both_fun(a: Sboth, b: u64) : u64 { + a.x * b + } + + public fun both_fun2(a: u64, b: Sboth) : u64 { + a * b.x + } + + // just drop + public fun use_function_base(key: u64, x: u64): u64 { + let a = S { x: 2 }; + let a_copy = Scopy { x: 2 }; + let a_store = Sstore { x: 2 }; + let a_both = Sboth { x: 2 }; + let f = + if (key == 0) { + let x = 3; + move |x| base_fun(a, x) + } else if (key == 1) { + move |x| base_fun2(x, a) + } else if (key == 2) { + move |x| copy_fun(a_copy, x) + } else if (key == 3) { + move |x| copy_fun2(x, a_copy) + } else if (key == 4) { + move |x| store_fun(a_store, x) + } else if (key == 5) { + move |x| store_fun2(x, a_store) + } else if (key == 6) { + move |x| both_fun(a_both, x) + } else if (key == 7) { + move |x| both_fun2(x, a_both) + } else { + move |x| x * 2 + }; + f(x) + } + + public fun return_function_base(key: u64, x: u64): |u64|u64 { + let a = S { x: 2 }; + let a_copy = Scopy { x: 2 }; + let a_store = Sstore { x: 2 }; + let a_both = Sboth { x: 2 }; + let f = + if (key == 0) { + let x = 3; + move |x| base_fun(a, x) + } else if (key == 1) { + move |x| base_fun2(x, a) + } else if (key == 2) { + move |x| copy_fun(a_copy, x) + } else if (key == 3) { + move |x| copy_fun2(x, a_copy) + } else if (key == 4) { + move |x| store_fun(a_store, x) + } else if (key == 5) { + move |x| store_fun2(x, a_store) + } else if (key == 6) { + move |x| both_fun(a_both, x) + } else if (key == 7) { + move |x| both_fun2(x, a_both) + } else { + move |x| x * 2 with copy + }; + f + } + + + // copy + public fun use_function_copy(key: u64, x: u64): u64 { + let a = S { x: 2 }; + let a_copy = Scopy { x: 2 }; + let a_store = Sstore { x: 2 }; + let a_both = Sboth { x: 2 }; + let f = + if (key == 0) { + let x = 3; + move |x| base_fun(a, x) with copy + } else if (key == 1) { + move |x| base_fun2(x, a) with copy + } else if (key == 2) { + move |x| copy_fun(a_copy, x) with copy + } else if (key == 3) { + move |x| copy_fun2(x, a_copy) with copy + } else if (key == 4) { + move |x| store_fun(a_store, x) with copy + } else if (key == 5) { + move |x| store_fun2(x, a_store) with copy + } else if (key == 6) { + move |x| both_fun(a_both, x) with copy + } else if (key == 7) { + move |x| both_fun2(x, a_both) with copy + } else { + move |x| x * 2 with copy + }; + f(x) + } + + public fun return_function_copy(key: u64, x: u64): |u64|u64 with copy { + let a = S { x: 2 }; + let a_copy = Scopy { x: 2 }; + let a_store = Sstore { x: 2 }; + let a_both = Sboth { x: 2 }; + let f = + if (key == 0) { + let x = 3; + move |x| base_fun(a, x) with copy + } else if (key == 1) { + move |x| base_fun2(x, a) with copy + } else if (key == 2) { + move |x| copy_fun(a_copy, x) with copy + } else if (key == 3) { + move |x| copy_fun2(x, a_copy) with copy + } else if (key == 4) { + move |x| store_fun(a_store, x) with copy + } else if (key == 5) { + move |x| store_fun2(x, a_store) with copy + } else if (key == 6) { + move |x| both_fun(a_both, x) with copy + } else if (key == 7) { + move |x| both_fun2(x, a_both) with copy + } else { + move |x| x * 2 with copy + }; + f + } + + // store + public fun use_function_store(key: u64, x: u64): u64 { + let a = S { x: 2 }; + let a_copy = Scopy { x: 2 }; + let a_store = Sstore { x: 2 }; + let a_both = Sboth { x: 2 }; + let f = + if (key == 0) { + let x = 3; + move |x| base_fun(a, x) with store + } else if (key == 1) { + move |x| base_fun2(x, a) with store + } else if (key == 2) { + move |x| copy_fun(a_copy, x) with store + } else if (key == 3) { + move |x| copy_fun2(x, a_copy) with store + } else if (key == 4) { + move |x| store_fun(a_store, x) with store + } else if (key == 5) { + move |x| store_fun2(x, a_store) with store + } else if (key == 6) { + move |x| both_fun(a_both, x) with store + } else if (key == 7) { + move |x| both_fun2(x, a_both) with store + } else { + move |x| x * 2 with store + }; + f(x) + } + + public fun return_function_store(key: u64, x: u64): |u64|u64 with store { + let a = S { x: 2 }; + let a_copy = Scopy { x: 2 }; + let a_store = Sstore { x: 2 }; + let a_both = Sboth { x: 2 }; + let f = + if (key == 0) { + let x = 3; + move |x| base_fun(a, x) with store + } else if (key == 1) { + move |x| base_fun2(x, a) with store + } else if (key == 2) { + move |x| copy_fun(a_copy, x) with store + } else if (key == 3) { + move |x| copy_fun2(x, a_copy) with store + } else if (key == 4) { + move |x| store_fun(a_store, x) with store + } else if (key == 5) { + move |x| store_fun2(x, a_store) with store + } else if (key == 6) { + move |x| both_fun(a_both, x) with store + } else if (key == 7) { + move |x| both_fun2(x, a_both) with store + } else { + move |x| x * 2 with store + }; + f + } + + + // both = store+copy + public fun use_function_both(key: u64, x: u64): u64 { + let a = S { x: 2 }; + let a_copy = Scopy { x: 2 }; + let a_store = Sstore { x: 2 }; + let a_both = Sboth { x: 2 }; + let f = + if (key == 0) { + let x = 3; + move |x| base_fun(a, x) with store+copy + } else if (key == 1) { + move |x| base_fun2(x, a) with store+copy + } else if (key == 2) { + move |x| copy_fun(a_copy, x) with store+copy + } else if (key == 3) { + move |x| copy_fun2(x, a_copy) with store+copy + } else if (key == 4) { + move |x| store_fun(a_store, x) with store+copy + } else if (key == 5) { + move |x| store_fun2(x, a_store) with store+copy + } else if (key == 6) { + move |x| both_fun(a_both, x) with store+copy + } else if (key == 7) { + move |x| both_fun2(x, a_both) with store+copy + } else { + move |x| x * 2 with store+copy + }; + f(x) + } + + public fun return_function_both(key: u64, x: u64): |u64|u64 with store+copy { + let a = S { x: 2 }; + let a_copy = Scopy { x: 2 }; + let a_store = Sstore { x: 2 }; + let a_both = Sboth { x: 2 }; + let f = + if (key == 0) { + let x = 3; + move |x| base_fun(a, x) with store+copy + } else if (key == 1) { + move |x| base_fun2(x, a) with store+copy + } else if (key == 2) { + move |x| copy_fun(a_copy, x) with store+copy + } else if (key == 3) { + move |x| copy_fun2(x, a_copy) with store+copy + } else if (key == 4) { + move |x| store_fun(a_store, x) with store+copy + } else if (key == 5) { + move |x| store_fun2(x, a_store) with store+copy + } else if (key == 6) { + move |x| both_fun(a_both, x) with store+copy + } else if (key == 7) { + move |x| both_fun2(x, a_both) with store+copy + } else { + move |x| x * 2 with store+copy + }; + f + } +} diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/doable_func.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/doable_func.exp index bee6d7e4e76c2..059c9197682da 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/storable/doable_func.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/doable_func.exp @@ -15,25 +15,25 @@ error: unsupported language construct error: unsupported language construct ┌─ tests/lambda/storable/doable_func.move:49:17 │ -49 │ move |y| mod3::multiply(y, x) +49 │ move |y| mod3::multiply(x, y) │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression error: unsupported language construct ┌─ tests/lambda/storable/doable_func.move:51:17 │ -51 │ move |x| multiply3(x, 3, 2) +51 │ move |x| multiply3(3, 2, x) │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression error: unsupported language construct ┌─ tests/lambda/storable/doable_func.move:53:17 │ -53 │ move |x| mod3::multiply(x, 7) +53 │ move |x| mod3::multiply(7, x) │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression error: unsupported language construct ┌─ tests/lambda/storable/doable_func.move:55:17 │ -55 │ move |x| multiply3(4, x, 2) +55 │ move |x| { multiply3(4, 2, x) } │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression error: unsupported language construct @@ -45,19 +45,19 @@ error: unsupported language construct error: unsupported language construct ┌─ tests/lambda/storable/doable_func.move:61:17 │ -61 │ move |z| multiply3(x, y, z) +61 │ move |z| multiply3(x + 1, y, z) │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression error: unsupported language construct ┌─ tests/lambda/storable/doable_func.move:64:17 │ -64 │ move |x| alt_multiply(x, z) with copy +64 │ move |x| alt_multiply(z, x) with copy │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression error: unsupported language construct ┌─ tests/lambda/storable/doable_func.move:64:45 │ -64 │ move |x| alt_multiply(x, z) with copy +64 │ move |x| alt_multiply(z, x) with copy │ ^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions error: unsupported language construct @@ -75,19 +75,19 @@ error: unsupported language construct error: unsupported language construct ┌─ tests/lambda/storable/doable_func.move:67:17 │ -67 │ move |x| g(x, 11) +67 │ move |x| g(11, x) │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression error: unsupported language construct ┌─ tests/lambda/storable/doable_func.move:69:25 │ -69 │ let h = move |x| mod3::multiply(x, 12) with copy; +69 │ let h = move |x| mod3::multiply(12, x) with copy; │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression error: unsupported language construct ┌─ tests/lambda/storable/doable_func.move:69:56 │ -69 │ let h = move |x| mod3::multiply(x, 12) with copy; +69 │ let h = move |x| mod3::multiply(12, x) with copy; │ ^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions error: unsupported language construct @@ -105,7 +105,7 @@ error: unsupported language construct error: unsupported language construct ┌─ tests/lambda/storable/doable_func.move:72:25 │ -72 │ let i = move |x| multiply3(2, x, 2); +72 │ let i = move |x| multiply3(2, 2, x); │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression error: unsupported language construct @@ -123,5 +123,5 @@ error: unsupported language construct error: unsupported language construct ┌─ tests/lambda/storable/doable_func.move:76:17 │ -76 │ move |x| i(x, 15) +76 │ move |x| i(15, x) │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/doable_func.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/doable_func.lambda.exp index e39fd4deaeb18..f43754aae1268 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/storable/doable_func.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/doable_func.lambda.exp @@ -47,17 +47,17 @@ module 0x42::test { if Eq(key, 4) { { let x: u64 = 6; - move|y: u64| mod3::multiply(y, x) + move|y: u64| mod3::multiply(x, y) } } else { if Eq(key, 5) { - move|x: u64| test::multiply3(x, 3, 2) + move|x: u64| test::multiply3(3, 2, x) } else { if Eq(key, 6) { - move|x: u64| mod3::multiply(x, 7) + move|x: u64| mod3::multiply(7, x) } else { if Eq(key, 7) { - move|x: u64| test::multiply3(4, x, 2) + move|x: u64| test::multiply3(4, 2, x) } else { if Eq(key, 8) { move|x: u64| test::multiply3(3, 3, x) @@ -67,31 +67,31 @@ module 0x42::test { let x: u64 = 2; { let y: u64 = 5; - move|z: u64| test::multiply3(x, y, z) + move|z: u64| test::multiply3(Add(x, 1), y, z) } } } else { if Eq(key, 10) { { let z: u64 = 11; - move|x: u64| mod4::alt_multiply(x, z) with copy, drop + move|x: u64| mod4::alt_multiply(z, x) with copy, drop } } else { if Eq(key, 11) { { let g: |(u64, u64)|u64 with copy+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; - move|x: u64| (g)(x, 11) + move|x: u64| (g)(11, x) } } else { if Eq(key, 12) { { - let h: |u64|u64 with copy+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + let h: |u64|u64 with copy+store = move|x: u64| mod3::multiply(12, x) with copy, drop; move|x: u64| (h)(x) with copy, drop } } else { if Eq(key, 14) { { - let i: |u64|u64 with copy+store = move|x: u64| test::multiply3(2, x, 2); + let i: |u64|u64 with copy+store = move|x: u64| test::multiply3(2, 2, x); move|z: u64| (i)(z) } } else { @@ -100,7 +100,7 @@ module 0x42::test { let q: u64 = Sub(y, 1); mod3::multiply(x, Add(q, 1)) }; - move|x: u64| (i)(x, 15) + move|x: u64| (i)(15, x) } } } @@ -214,17 +214,17 @@ module 0x42::test { if Eq(key, 4) { { let x: u64 = 6; - move|y: u64| mod3::multiply(y, x) + move|y: u64| mod3::multiply(x, y) } } else { if Eq(key, 5) { - move|x: u64| test::multiply3(x, 3, 2) + move|x: u64| test::multiply3(3, 2, x) } else { if Eq(key, 6) { - move|x: u64| mod3::multiply(x, 7) + move|x: u64| mod3::multiply(7, x) } else { if Eq(key, 7) { - move|x: u64| test::multiply3(4, x, 2) + move|x: u64| test::multiply3(4, 2, x) } else { if Eq(key, 8) { move|x: u64| test::multiply3(3, 3, x) @@ -234,31 +234,31 @@ module 0x42::test { let x: u64 = 2; { let y: u64 = 5; - move|z: u64| test::multiply3(x, y, z) + move|z: u64| test::multiply3(Add(x, 1), y, z) } } } else { if Eq(key, 10) { { let z: u64 = 11; - move|x: u64| mod4::alt_multiply(x, z) with copy, drop + move|x: u64| mod4::alt_multiply(z, x) with copy, drop } } else { if Eq(key, 11) { { let g: |(u64, u64)|u64 with copy+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; - move|x: u64| (g)(x, 11) + move|x: u64| (g)(11, x) } } else { if Eq(key, 12) { { - let h: |u64|u64 with copy+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + let h: |u64|u64 with copy+store = move|x: u64| mod3::multiply(12, x) with copy, drop; move|x: u64| (h)(x) with copy, drop } } else { if Eq(key, 14) { { - let i: |u64|u64 with copy+store = move|x: u64| test::multiply3(2, x, 2); + let i: |u64|u64 with copy+store = move|x: u64| test::multiply3(2, 2, x); move|z: u64| (i)(z) } } else { @@ -267,7 +267,7 @@ module 0x42::test { let q: u64 = Sub(y, 1); mod3::multiply(x, Add(q, 1)) }; - move|x: u64| (i)(x, 15) + move|x: u64| (i)(15, x) } } } @@ -381,17 +381,17 @@ module 0x42::test { if Eq(key, 4) { { let x: u64 = 6; - move|y: u64| mod3::multiply(y, x) + move|y: u64| mod3::multiply(x, y) } } else { if Eq(key, 5) { - move|x: u64| test::multiply3(x, 3, 2) + move|x: u64| test::multiply3(3, 2, x) } else { if Eq(key, 6) { - move|x: u64| mod3::multiply(x, 7) + move|x: u64| mod3::multiply(7, x) } else { if Eq(key, 7) { - move|x: u64| test::multiply3(4, x, 2) + move|x: u64| test::multiply3(4, 2, x) } else { if Eq(key, 8) { move|x: u64| test::multiply3(3, 3, x) @@ -401,31 +401,31 @@ module 0x42::test { let x: u64 = 2; { let y: u64 = 5; - move|z: u64| test::multiply3(x, y, z) + move|z: u64| test::multiply3(Add(x, 1), y, z) } } } else { if Eq(key, 10) { { let z: u64 = 11; - move|x: u64| mod4::alt_multiply(x, z) with copy, drop + move|x: u64| mod4::alt_multiply(z, x) with copy, drop } } else { if Eq(key, 11) { { let g: |(u64, u64)|u64 with copy+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; - move|x: u64| (g)(x, 11) + move|x: u64| (g)(11, x) } } else { if Eq(key, 12) { { - let h: |u64|u64 with copy+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + let h: |u64|u64 with copy+store = move|x: u64| mod3::multiply(12, x) with copy, drop; move|x: u64| (h)(x) with copy, drop } } else { if Eq(key, 14) { { - let i: |u64|u64 with copy+store = move|x: u64| test::multiply3(2, x, 2); + let i: |u64|u64 with copy+store = move|x: u64| test::multiply3(2, 2, x); move|z: u64| (i)(z) } } else { @@ -434,7 +434,7 @@ module 0x42::test { let q: u64 = Sub(y, 1); mod3::multiply(x, Add(q, 1)) }; - move|x: u64| (i)(x, 15) + move|x: u64| (i)(15, x) } } } @@ -548,17 +548,17 @@ module 0x42::test { if Eq(key, 4) { { let x: u64 = 6; - move|y: u64| mod3::multiply(y, x) + move|y: u64| mod3::multiply(x, y) } } else { if Eq(key, 5) { - move|x: u64| test::multiply3(x, 3, 2) + move|x: u64| test::multiply3(3, 2, x) } else { if Eq(key, 6) { - move|x: u64| mod3::multiply(x, 7) + move|x: u64| mod3::multiply(7, x) } else { if Eq(key, 7) { - move|x: u64| test::multiply3(4, x, 2) + move|x: u64| test::multiply3(4, 2, x) } else { if Eq(key, 8) { move|x: u64| test::multiply3(3, 3, x) @@ -568,31 +568,31 @@ module 0x42::test { let x: u64 = 2; { let y: u64 = 5; - move|z: u64| test::multiply3(x, y, z) + move|z: u64| test::multiply3(Add(x, 1), y, z) } } } else { if Eq(key, 10) { { let z: u64 = 11; - move|x: u64| mod4::alt_multiply(x, z) with copy, drop + move|x: u64| mod4::alt_multiply(z, x) with copy, drop } } else { if Eq(key, 11) { { let g: |(u64, u64)|u64 with copy+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; - move|x: u64| (g)(x, 11) + move|x: u64| (g)(11, x) } } else { if Eq(key, 12) { { - let h: |u64|u64 with copy+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + let h: |u64|u64 with copy+store = move|x: u64| mod3::multiply(12, x) with copy, drop; move|x: u64| (h)(x) with copy, drop } } else { if Eq(key, 14) { { - let i: |u64|u64 with copy+store = move|x: u64| test::multiply3(2, x, 2); + let i: |u64|u64 with copy+store = move|x: u64| test::multiply3(2, 2, x); move|z: u64| (i)(z) } } else { @@ -601,7 +601,7 @@ module 0x42::test { let q: u64 = Sub(y, 1); mod3::multiply(x, Add(q, 1)) }; - move|x: u64| (i)(x, 15) + move|x: u64| (i)(15, x) } } } @@ -715,17 +715,17 @@ module 0x42::test { if Eq(key, 4) { { let x: u64 = 6; - move|y: u64| mod3::multiply(y, x) + move|y: u64| mod3::multiply(x, y) } } else { if Eq(key, 5) { - move|x: u64| test::multiply3(x, 3, 2) + move|x: u64| test::multiply3(3, 2, x) } else { if Eq(key, 6) { - move|x: u64| mod3::multiply(x, 7) + move|x: u64| mod3::multiply(7, x) } else { if Eq(key, 7) { - move|x: u64| test::multiply3(4, x, 2) + move|x: u64| test::multiply3(4, 2, x) } else { if Eq(key, 8) { move|x: u64| test::multiply3(3, 3, x) @@ -735,31 +735,31 @@ module 0x42::test { let x: u64 = 2; { let y: u64 = 5; - move|z: u64| test::multiply3(x, y, z) + move|z: u64| test::multiply3(Add(x, 1), y, z) } } } else { if Eq(key, 10) { { let z: u64 = 11; - move|x: u64| mod4::alt_multiply(x, z) with copy, drop + move|x: u64| mod4::alt_multiply(z, x) with copy, drop } } else { if Eq(key, 11) { { let g: |(u64, u64)|u64 with copy+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; - move|x: u64| (g)(x, 11) + move|x: u64| (g)(11, x) } } else { if Eq(key, 12) { { - let h: |u64|u64 with copy+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + let h: |u64|u64 with copy+store = move|x: u64| mod3::multiply(12, x) with copy, drop; move|x: u64| (h)(x) with copy, drop } } else { if Eq(key, 14) { { - let i: |u64|u64 with copy+store = move|x: u64| test::multiply3(2, x, 2); + let i: |u64|u64 with copy+store = move|x: u64| test::multiply3(2, 2, x); move|z: u64| (i)(z) } } else { @@ -768,7 +768,7 @@ module 0x42::test { let q: u64 = Sub(y, 1); mod3::multiply(x, Add(q, 1)) }; - move|x: u64| (i)(x, 15) + move|x: u64| (i)(15, x) } } } @@ -882,17 +882,17 @@ module 0x42::test { if Eq(key, 4) { { let x: u64 = 6; - move|y: u64| mod3::multiply(y, x) + move|y: u64| mod3::multiply(x, y) } } else { if Eq(key, 5) { - move|x: u64| test::multiply3(x, 3, 2) + move|x: u64| test::multiply3(3, 2, x) } else { if Eq(key, 6) { - move|x: u64| mod3::multiply(x, 7) + move|x: u64| mod3::multiply(7, x) } else { if Eq(key, 7) { - move|x: u64| test::multiply3(4, x, 2) + move|x: u64| test::multiply3(4, 2, x) } else { if Eq(key, 8) { move|x: u64| test::multiply3(3, 3, x) @@ -902,31 +902,31 @@ module 0x42::test { let x: u64 = 2; { let y: u64 = 5; - move|z: u64| test::multiply3(x, y, z) + move|z: u64| test::multiply3(Add(x, 1), y, z) } } } else { if Eq(key, 10) { { let z: u64 = 11; - move|x: u64| mod4::alt_multiply(x, z) with copy, drop + move|x: u64| mod4::alt_multiply(z, x) with copy, drop } } else { if Eq(key, 11) { { let g: |(u64, u64)|u64 with copy+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; - move|x: u64| (g)(x, 11) + move|x: u64| (g)(11, x) } } else { if Eq(key, 12) { { - let h: |u64|u64 with copy+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + let h: |u64|u64 with copy+store = move|x: u64| mod3::multiply(12, x) with copy, drop; move|x: u64| (h)(x) with copy, drop } } else { if Eq(key, 14) { { - let i: |u64|u64 with copy+store = move|x: u64| test::multiply3(2, x, 2); + let i: |u64|u64 with copy+store = move|x: u64| test::multiply3(2, 2, x); move|z: u64| (i)(z) } } else { @@ -935,7 +935,7 @@ module 0x42::test { let q: u64 = Sub(y, 1); mod3::multiply(x, Add(q, 1)) }; - move|x: u64| (i)(x, 15) + move|x: u64| (i)(15, x) } } } @@ -1049,17 +1049,17 @@ module 0x42::test { if Eq(key, 4) { { let x: u64 = 6; - move|y: u64| mod3::multiply(y, x) + move|y: u64| mod3::multiply(x, y) } } else { if Eq(key, 5) { - move|x: u64| test::multiply3(x, 3, 2) + move|x: u64| test::multiply3(3, 2, x) } else { if Eq(key, 6) { - move|x: u64| mod3::multiply(x, 7) + move|x: u64| mod3::multiply(7, x) } else { if Eq(key, 7) { - move|x: u64| test::multiply3(4, x, 2) + move|x: u64| test::multiply3(4, 2, x) } else { if Eq(key, 8) { move|x: u64| test::multiply3(3, 3, x) @@ -1069,31 +1069,31 @@ module 0x42::test { let x: u64 = 2; { let y: u64 = 5; - move|z: u64| test::multiply3(x, y, z) + move|z: u64| test::multiply3(Add(x, 1), y, z) } } } else { if Eq(key, 10) { { let z: u64 = 11; - move|x: u64| mod4::alt_multiply(x, z) with copy, drop + move|x: u64| mod4::alt_multiply(z, x) with copy, drop } } else { if Eq(key, 11) { { let g: |(u64, u64)|u64 with copy+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; - move|x: u64| (g)(x, 11) + move|x: u64| (g)(11, x) } } else { if Eq(key, 12) { { - let h: |u64|u64 with copy+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + let h: |u64|u64 with copy+store = move|x: u64| mod3::multiply(12, x) with copy, drop; move|x: u64| (h)(x) with copy, drop } } else { if Eq(key, 14) { { - let i: |u64|u64 with copy+store = move|x: u64| test::multiply3(2, x, 2); + let i: |u64|u64 with copy+store = move|x: u64| test::multiply3(2, 2, x); move|z: u64| (i)(z) } } else { @@ -1102,7 +1102,7 @@ module 0x42::test { let q: u64 = Sub(y, 1); mod3::multiply(x, Add(q, 1)) }; - move|x: u64| (i)(x, 15) + move|x: u64| (i)(15, x) } } } @@ -1216,17 +1216,17 @@ module 0x42::test { if Eq(key, 4) { { let x: u64 = 6; - move|y: u64| mod3::multiply(y, x) + move|y: u64| mod3::multiply(x, y) } } else { if Eq(key, 5) { - move|x: u64| test::multiply3(x, 3, 2) + move|x: u64| test::multiply3(3, 2, x) } else { if Eq(key, 6) { - move|x: u64| mod3::multiply(x, 7) + move|x: u64| mod3::multiply(7, x) } else { if Eq(key, 7) { - move|x: u64| test::multiply3(4, x, 2) + move|x: u64| test::multiply3(4, 2, x) } else { if Eq(key, 8) { move|x: u64| test::multiply3(3, 3, x) @@ -1236,31 +1236,31 @@ module 0x42::test { let x: u64 = 2; { let y: u64 = 5; - move|z: u64| test::multiply3(x, y, z) + move|z: u64| test::multiply3(Add(x, 1), y, z) } } } else { if Eq(key, 10) { { let z: u64 = 11; - move|x: u64| mod4::alt_multiply(x, z) with copy, drop + move|x: u64| mod4::alt_multiply(z, x) with copy, drop } } else { if Eq(key, 11) { { let g: |(u64, u64)|u64 with copy+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; - move|x: u64| (g)(x, 11) + move|x: u64| (g)(11, x) } } else { if Eq(key, 12) { { - let h: |u64|u64 with copy+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + let h: |u64|u64 with copy+store = move|x: u64| mod3::multiply(12, x) with copy, drop; move|x: u64| (h)(x) with copy, drop } } else { if Eq(key, 14) { { - let i: |u64|u64 with copy+store = move|x: u64| test::multiply3(2, x, 2); + let i: |u64|u64 with copy+store = move|x: u64| test::multiply3(2, 2, x); move|z: u64| (i)(z) } } else { @@ -1269,7 +1269,7 @@ module 0x42::test { let q: u64 = Sub(y, 1); mod3::multiply(x, Add(q, 1)) }; - move|x: u64| (i)(x, 15) + move|x: u64| (i)(15, x) } } } @@ -1383,17 +1383,17 @@ module 0x42::test { if Eq(key, 4) { { let x: u64 = 6; - move|y: u64| mod3::multiply(y, x) + move|y: u64| mod3::multiply(x, y) } } else { if Eq(key, 5) { - move|x: u64| test::multiply3(x, 3, 2) + move|x: u64| test::multiply3(3, 2, x) } else { if Eq(key, 6) { - move|x: u64| mod3::multiply(x, 7) + move|x: u64| mod3::multiply(7, x) } else { if Eq(key, 7) { - move|x: u64| test::multiply3(4, x, 2) + move|x: u64| test::multiply3(4, 2, x) } else { if Eq(key, 8) { move|x: u64| test::multiply3(3, 3, x) @@ -1403,31 +1403,31 @@ module 0x42::test { let x: u64 = 2; { let y: u64 = 5; - move|z: u64| test::multiply3(x, y, z) + move|z: u64| test::multiply3(Add(x, 1), y, z) } } } else { if Eq(key, 10) { { let z: u64 = 11; - move|x: u64| mod4::alt_multiply(x, z) with copy, drop + move|x: u64| mod4::alt_multiply(z, x) with copy, drop } } else { if Eq(key, 11) { { let g: |(u64, u64)|u64 with copy+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; - move|x: u64| (g)(x, 11) + move|x: u64| (g)(11, x) } } else { if Eq(key, 12) { { - let h: |u64|u64 with copy+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + let h: |u64|u64 with copy+store = move|x: u64| mod3::multiply(12, x) with copy, drop; move|x: u64| (h)(x) with copy, drop } } else { if Eq(key, 14) { { - let i: |u64|u64 with copy+store = move|x: u64| test::multiply3(2, x, 2); + let i: |u64|u64 with copy+store = move|x: u64| test::multiply3(2, 2, x); move|z: u64| (i)(z) } } else { @@ -1436,7 +1436,7 @@ module 0x42::test { let q: u64 = Sub(y, 1); mod3::multiply(x, Add(q, 1)) }; - move|x: u64| (i)(x, 15) + move|x: u64| (i)(15, x) } } } @@ -1550,17 +1550,17 @@ module 0x42::test { if Eq(key, 4) { { let x: u64 = 6; - move|y: u64| mod3::multiply(y, x) + move|y: u64| mod3::multiply(x, y) } } else { if Eq(key, 5) { - move|x: u64| test::multiply3(x, 3, 2) + move|x: u64| test::multiply3(3, 2, x) } else { if Eq(key, 6) { - move|x: u64| mod3::multiply(x, 7) + move|x: u64| mod3::multiply(7, x) } else { if Eq(key, 7) { - move|x: u64| test::multiply3(4, x, 2) + move|x: u64| test::multiply3(4, 2, x) } else { if Eq(key, 8) { move|x: u64| test::multiply3(3, 3, x) @@ -1570,31 +1570,31 @@ module 0x42::test { let x: u64 = 2; { let y: u64 = 5; - move|z: u64| test::multiply3(x, y, z) + move|z: u64| test::multiply3(Add(x, 1), y, z) } } } else { if Eq(key, 10) { { let z: u64 = 11; - move|x: u64| mod4::alt_multiply(x, z) with copy, drop + move|x: u64| mod4::alt_multiply(z, x) with copy, drop } } else { if Eq(key, 11) { { let g: |(u64, u64)|u64 with copy+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; - move|x: u64| (g)(x, 11) + move|x: u64| (g)(11, x) } } else { if Eq(key, 12) { { - let h: |u64|u64 with copy+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + let h: |u64|u64 with copy+store = move|x: u64| mod3::multiply(12, x) with copy, drop; move|x: u64| (h)(x) with copy, drop } } else { if Eq(key, 14) { { - let i: |u64|u64 with copy+store = move|x: u64| test::multiply3(2, x, 2); + let i: |u64|u64 with copy+store = move|x: u64| test::multiply3(2, 2, x); move|z: u64| (i)(z) } } else { @@ -1603,7 +1603,7 @@ module 0x42::test { let q: u64 = Sub(y, 1); mod3::multiply(x, Add(q, 1)) }; - move|x: u64| (i)(x, 15) + move|x: u64| (i)(15, x) } } } @@ -1712,41 +1712,41 @@ module 0x42::test { move|y: u64| mod4::alt_multiply(5, y) } else { if Eq(key, 4) { - move|y: u64| mod3::multiply(y, 6) + move|y: u64| mod3::multiply(6, y) } else { if Eq(key, 5) { - move|x: u64| test::multiply3(x, 3, 2) + move|x: u64| test::multiply3(3, 2, x) } else { if Eq(key, 6) { - move|x: u64| mod3::multiply(x, 7) + move|x: u64| mod3::multiply(7, x) } else { if Eq(key, 7) { - move|x: u64| test::multiply3(4, x, 2) + move|x: u64| test::multiply3(4, 2, x) } else { if Eq(key, 8) { move|x: u64| test::multiply3(3, 3, x) } else { if Eq(key, 9) { - move|z: u64| test::multiply3(2, 5, z) + move|z: u64| test::multiply3(3, 5, z) } else { if Eq(key, 10) { - move|x: u64| mod4::alt_multiply(x, 11) with copy, drop + move|x: u64| mod4::alt_multiply(11, x) with copy, drop } else { if Eq(key, 11) { { let g: |(u64, u64)|u64 with copy+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; - move|x: u64| (g)(x, 11) + move|x: u64| (g)(11, x) } } else { if Eq(key, 12) { { - let h: |u64|u64 with copy+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + let h: |u64|u64 with copy+store = move|x: u64| mod3::multiply(12, x) with copy, drop; move|x: u64| (h)(x) with copy, drop } } else { if Eq(key, 14) { { - let i: |u64|u64 with copy+store = move|x: u64| test::multiply3(2, x, 2); + let i: |u64|u64 with copy+store = move|x: u64| test::multiply3(2, 2, x); move|z: u64| (i)(z) } } else { @@ -1755,7 +1755,7 @@ module 0x42::test { let q: u64 = Sub(y, 1); mod3::multiply(x, Add(q, 1)) }; - move|x: u64| (i)(x, 15) + move|x: u64| (i)(15, x) } } } @@ -1858,47 +1858,47 @@ module 0x42::test { earlybind(mod4::alt_multiply, 5) } else { if Eq(key, 4) { - test::choose_function1$lambda$1 + earlybind(mod3::multiply, 6) } else { if Eq(key, 5) { - test::choose_function1$lambda$2 + earlybind(test::multiply3, 3, 2) } else { if Eq(key, 6) { - test::choose_function1$lambda$3 + earlybind(mod3::multiply, 7) } else { if Eq(key, 7) { - test::choose_function1$lambda$4 + earlybind(test::multiply3, 4, 2) } else { if Eq(key, 8) { earlybind(test::multiply3, 3, 3) } else { if Eq(key, 9) { - earlybind(test::multiply3, 2, 5) + earlybind(test::multiply3, 3, 5) } else { if Eq(key, 10) { - test::choose_function1$lambda$5 + earlybind(mod4::alt_multiply, 11) } else { if Eq(key, 11) { { let g: |(u64, u64)|u64 with copy+store = mod3::multiply; - earlybind(test::choose_function1$lambda$6, g) + earlybind(g, 11) } } else { if Eq(key, 12) { { - let h: |u64|u64 with copy+store = test::choose_function1$lambda$7; + let h: |u64|u64 with copy+store = earlybind(mod3::multiply, 12); h } } else { if Eq(key, 14) { { - let i: |u64|u64 with copy+store = test::choose_function1$lambda$8; + let i: |u64|u64 with copy+store = earlybind(test::multiply3, 2, 2); i } } else { { - let i: |(u64, u64)|u64 with copy+store = test::choose_function1$lambda$9; - earlybind(test::choose_function1$lambda$10, i) + let i: |(u64, u64)|u64 with copy+store = test::choose_function1$lambda$1; + earlybind(i, 15) } } } @@ -1954,39 +1954,12 @@ module 0x42::test { } } } - private fun choose_function1$lambda$1(y: u64): u64 { - mod3::multiply(y, 6) - } - private fun choose_function1$lambda$2(x: u64): u64 { - test::multiply3(x, 3, 2) - } - private fun choose_function1$lambda$3(x: u64): u64 { - mod3::multiply(x, 7) - } - private fun choose_function1$lambda$4(x: u64): u64 { - test::multiply3(4, x, 2) - } - private fun choose_function1$lambda$5(x: u64): u64 { - mod4::alt_multiply(x, 11) - } - private fun choose_function1$lambda$6(g: |(u64, u64)|u64 with copy+store,x: u64): u64 { - (g)(x, 11) - } - private fun choose_function1$lambda$7(x: u64): u64 { - mod3::multiply(x, 12) - } - private fun choose_function1$lambda$8(x: u64): u64 { - test::multiply3(2, x, 2) - } - private fun choose_function1$lambda$9(x: u64,y: u64): u64 { + private fun choose_function1$lambda$1(x: u64,y: u64): u64 { { let q: u64 = Sub(y, 1); mod3::multiply(x, Add(q, 1)) } } - private fun choose_function1$lambda$10(i: |(u64, u64)|u64 with copy+store,x: u64): u64 { - (i)(x, 15) - } } // end 0x42::test @@ -2034,47 +2007,47 @@ module 0x42::test { earlybind(mod4::alt_multiply, 5) } else { if Eq(key, 4) { - test::choose_function1$lambda$1 + earlybind(mod3::multiply, 6) } else { if Eq(key, 5) { - test::choose_function1$lambda$2 + earlybind(test::multiply3, 3, 2) } else { if Eq(key, 6) { - test::choose_function1$lambda$3 + earlybind(mod3::multiply, 7) } else { if Eq(key, 7) { - test::choose_function1$lambda$4 + earlybind(test::multiply3, 4, 2) } else { if Eq(key, 8) { earlybind(test::multiply3, 3, 3) } else { if Eq(key, 9) { - earlybind(test::multiply3, 2, 5) + earlybind(test::multiply3, 3, 5) } else { if Eq(key, 10) { - test::choose_function1$lambda$5 + earlybind(mod4::alt_multiply, 11) } else { if Eq(key, 11) { { let g: |(u64, u64)|u64 with copy+store = mod3::multiply; - earlybind(test::choose_function1$lambda$6, g) + earlybind(g, 11) } } else { if Eq(key, 12) { { - let h: |u64|u64 with copy+store = test::choose_function1$lambda$7; + let h: |u64|u64 with copy+store = earlybind(mod3::multiply, 12); h } } else { if Eq(key, 14) { { - let i: |u64|u64 with copy+store = test::choose_function1$lambda$8; + let i: |u64|u64 with copy+store = earlybind(test::multiply3, 2, 2); i } } else { { - let i: |(u64, u64)|u64 with copy+store = test::choose_function1$lambda$9; - earlybind(test::choose_function1$lambda$10, i) + let i: |(u64, u64)|u64 with copy+store = test::choose_function1$lambda$1; + earlybind(i, 15) } } } @@ -2130,39 +2103,12 @@ module 0x42::test { } } } - private fun choose_function1$lambda$1(y: u64): u64 { - mod3::multiply(y, 6) - } - private fun choose_function1$lambda$2(x: u64): u64 { - test::multiply3(x, 3, 2) - } - private fun choose_function1$lambda$3(x: u64): u64 { - mod3::multiply(x, 7) - } - private fun choose_function1$lambda$4(x: u64): u64 { - test::multiply3(4, x, 2) - } - private fun choose_function1$lambda$5(x: u64): u64 { - mod4::alt_multiply(x, 11) - } - private fun choose_function1$lambda$6(g: |(u64, u64)|u64 with copy+store,x: u64): u64 { - (g)(x, 11) - } - private fun choose_function1$lambda$7(x: u64): u64 { - mod3::multiply(x, 12) - } - private fun choose_function1$lambda$8(x: u64): u64 { - test::multiply3(2, x, 2) - } - private fun choose_function1$lambda$9(x: u64,y: u64): u64 { + private fun choose_function1$lambda$1(x: u64,y: u64): u64 { { let q: u64 = Sub(y, 1); mod3::multiply(x, Add(q, 1)) } } - private fun choose_function1$lambda$10(i: |(u64, u64)|u64 with copy+store,x: u64): u64 { - (i)(x, 15) - } } // end 0x42::test @@ -2210,47 +2156,47 @@ module 0x42::test { earlybind(mod4::alt_multiply, 5) } else { if Eq(key, 4) { - test::choose_function1$lambda$1 + earlybind(mod3::multiply, 6) } else { if Eq(key, 5) { - test::choose_function1$lambda$2 + earlybind(test::multiply3, 3, 2) } else { if Eq(key, 6) { - test::choose_function1$lambda$3 + earlybind(mod3::multiply, 7) } else { if Eq(key, 7) { - test::choose_function1$lambda$4 + earlybind(test::multiply3, 4, 2) } else { if Eq(key, 8) { earlybind(test::multiply3, 3, 3) } else { if Eq(key, 9) { - earlybind(test::multiply3, 2, 5) + earlybind(test::multiply3, 3, 5) } else { if Eq(key, 10) { - test::choose_function1$lambda$5 + earlybind(mod4::alt_multiply, 11) } else { if Eq(key, 11) { { let g: |(u64, u64)|u64 with copy+store = mod3::multiply; - earlybind(test::choose_function1$lambda$6, g) + earlybind(g, 11) } } else { if Eq(key, 12) { { - let h: |u64|u64 with copy+store = test::choose_function1$lambda$7; + let h: |u64|u64 with copy+store = earlybind(mod3::multiply, 12); h } } else { if Eq(key, 14) { { - let i: |u64|u64 with copy+store = test::choose_function1$lambda$8; + let i: |u64|u64 with copy+store = earlybind(test::multiply3, 2, 2); i } } else { { - let i: |(u64, u64)|u64 with copy+store = test::choose_function1$lambda$9; - earlybind(test::choose_function1$lambda$10, i) + let i: |(u64, u64)|u64 with copy+store = test::choose_function1$lambda$1; + earlybind(i, 15) } } } @@ -2306,159 +2252,120 @@ module 0x42::test { } } } - private fun choose_function1$lambda$1(y: u64): u64 { - mod3::multiply(y, 6) - } - private fun choose_function1$lambda$2(x: u64): u64 { - test::multiply3(x, 3, 2) - } - private fun choose_function1$lambda$3(x: u64): u64 { - mod3::multiply(x, 7) - } - private fun choose_function1$lambda$4(x: u64): u64 { - test::multiply3(4, x, 2) - } - private fun choose_function1$lambda$5(x: u64): u64 { - mod4::alt_multiply(x, 11) - } - private fun choose_function1$lambda$6(g: |(u64, u64)|u64 with copy+store,x: u64): u64 { - (g)(x, 11) - } - private fun choose_function1$lambda$7(x: u64): u64 { - mod3::multiply(x, 12) - } - private fun choose_function1$lambda$8(x: u64): u64 { - test::multiply3(2, x, 2) - } - private fun choose_function1$lambda$9(x: u64,y: u64): u64 { + private fun choose_function1$lambda$1(x: u64,y: u64): u64 { { let q: u64 = Sub(y, 1); mod3::multiply(x, Add(q, 1)) } } - private fun choose_function1$lambda$10(i: |(u64, u64)|u64 with copy+store,x: u64): u64 { - (i)(x, 15) - } } // end 0x42::test Diagnostics: -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:39:17 │ 39 │ mod2::double │ ^^^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:41:17 │ 41 │ mod1::triple │ ^^^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:43:17 │ 43 │ move |x| mod3::multiply(4, x) │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:46:17 │ 46 │ move |y| alt_multiply(x, y) │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:49:17 │ -49 │ move |y| mod3::multiply(y, x) +49 │ move |y| mod3::multiply(x, y) │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:51:17 │ -51 │ move |x| multiply3(x, 3, 2) +51 │ move |x| multiply3(3, 2, x) │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:53:17 │ -53 │ move |x| mod3::multiply(x, 7) +53 │ move |x| mod3::multiply(7, x) │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:55:17 │ -55 │ move |x| multiply3(4, x, 2) - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +55 │ move |x| { multiply3(4, 2, x) } + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:57:17 │ 57 │ move |x| multiply3(3, 3, x) │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:61:17 │ -61 │ move |z| multiply3(x, y, z) - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +61 │ move |z| multiply3(x + 1, y, z) + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:64:17 │ -64 │ move |x| alt_multiply(x, z) with copy +64 │ move |x| alt_multiply(z, x) with copy │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:66:37 │ 66 │ let g = move |x, y| mod3::multiply(x, y) with copy+drop; │ ^^^^^^^^^^^^^^^^^^^^ -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/storable/doable_func.move:67:26 - │ -67 │ move |x| g(x, 11) - │ ^^^^^^^^ - -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:67:17 │ -67 │ move |x| g(x, 11) +67 │ move |x| g(11, x) │ ^^^^^^^^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:69:25 │ -69 │ let h = move |x| mod3::multiply(x, 12) with copy; +69 │ let h = move |x| mod3::multiply(12, x) with copy; │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:72:25 │ -72 │ let i = move |x| multiply3(2, x, 2); +72 │ let i = move |x| multiply3(2, 2, x); │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:75:25 │ 75 │ let i = move |x, y| { let q = y - 1; 0x42::mod3::multiply(x, q + 1) }; │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/storable/doable_func.move:76:26 - │ -76 │ move |x| i(x, 15) - │ ^^^^^^^^ - -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:76:17 │ -76 │ move |x| i(x, 15) +76 │ move |x| i(15, x) │ ^^^^^^^^^^^^^^^^^ -error: Calls to function values other than inline function parameters not yet supported +error: Calls to function values other than inline function parameters not yet implemented ┌─ tests/lambda/storable/doable_func.move:78:9 │ 78 │ f(x) diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/doable_func.move b/third_party/move/move-compiler-v2/tests/lambda/storable/doable_func.move index e53e9c9d3dc45..11035738ea530 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/storable/doable_func.move +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/doable_func.move @@ -46,34 +46,34 @@ module 0x42::test { move |y| alt_multiply(x, y) } else if (key == 4) { let x = 6; - move |y| mod3::multiply(y, x) + move |y| mod3::multiply(x, y) } else if (key == 5) { - move |x| multiply3(x, 3, 2) + move |x| multiply3(3, 2, x) } else if (key == 6) { - move |x| mod3::multiply(x, 7) + move |x| mod3::multiply(7, x) } else if (key == 7) { - move |x| multiply3(4, x, 2) + move |x| { multiply3(4, 2, x) } } else if (key == 8) { move |x| multiply3(3, 3, x) } else if (key == 9) { let x = 2; let y = 5; - move |z| multiply3(x, y, z) + move |z| multiply3(x + 1, y, z) } else if (key == 10) { let z = 11; - move |x| alt_multiply(x, z) with copy + move |x| alt_multiply(z, x) with copy } else if (key == 11) { let g = move |x, y| mod3::multiply(x, y) with copy+drop; - move |x| g(x, 11) + move |x| g(11, x) } else if (key == 12) { - let h = move |x| mod3::multiply(x, 12) with copy; + let h = move |x| mod3::multiply(12, x) with copy; move |x| { h(x) } with copy + drop } else if (key == 14) { - let i = move |x| multiply3(2, x, 2); + let i = move |x| multiply3(2, 2, x); move |z| i(z) } else { let i = move |x, y| { let q = y - 1; 0x42::mod3::multiply(x, q + 1) }; - move |x| i(x, 15) + move |x| i(15, x) }; f(x) } diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/registry_errors.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_errors.lambda.exp index 0cc07aff247e8..a3e43481806b2 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/storable/registry_errors.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_errors.lambda.exp @@ -1,23 +1,10 @@ Diagnostics: -error: function type `|u64|u64 with store` is not allowed as a field type - ┌─ tests/lambda/storable/registry_errors.move:9:12 - │ -9 │ f: |u64| u64 with store, - │ ^^^^^^^^^^^^^^^^^^^^ - │ - = required by declaration of field `f` - -error: function type `|u64|u64 with store` is not allowed as a type argument (type was inferred) - ┌─ tests/lambda/storable/registry_errors.move:22:21 - │ -13 │ enum Option { - │ - declaration of type parameter `T` - · -22 │ x = Option::Some(f.f) - │ ^^^^^^^^^^^^ +error: cannot return `Option<|u64|u64 with store>` from a function with result type `Option` + ┌─ tests/lambda/storable/registry_errors.move:25:9 │ - = required by instantiating type parameter `T` of struct `Option` +25 │ x + │ ^ error: expected `&mut Function` but found a value of type `|u64|u64 with store` ┌─ tests/lambda/storable/registry_errors.move:32:17 diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok.exp index 9292304f56251..1d6d6c5bdef9b 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok.exp @@ -1,43 +1,37 @@ Diagnostics: error: unsupported language construct - ┌─ tests/lambda/storable/registry_ok.move:10:22 - │ -10 │ f: |u64| u64 with store+copy, - │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types + ┌─ tests/lambda/storable/registry_ok.move:6:36 + │ +6 │ struct FunctionValue(|u64| u64 with store+copy) has store, copy, drop; + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types error: unsupported language construct - ┌─ tests/lambda/storable/registry_ok.move:29:84 + ┌─ tests/lambda/storable/registry_ok.move:32:84 │ -29 │ fun replace_or_add_function(v: &mut vector, k: u64, new_f: |u64| u64 with store+copy): Option<|u64| u64 with store+copy> { +32 │ fun replace_or_add_function(v: &mut vector, k: u64, new_f: |u64| u64 with store+copy): Option<|u64| u64 with store+copy> { │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types error: unsupported language construct - ┌─ tests/lambda/storable/registry_ok.move:29:119 + ┌─ tests/lambda/storable/registry_ok.move:32:119 │ -29 │ fun replace_or_add_function(v: &mut vector, k: u64, new_f: |u64| u64 with store+copy): Option<|u64| u64 with store+copy> { +32 │ fun replace_or_add_function(v: &mut vector, k: u64, new_f: |u64| u64 with store+copy): Option<|u64| u64 with store+copy> { │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types error: unsupported language construct - ┌─ tests/lambda/storable/registry_ok.move:53:47 + ┌─ tests/lambda/storable/registry_ok.move:56:47 │ -53 │ fun register(owner: &signer, f: |u64| u64 with store+copy, k: u64) acquires Registry { +56 │ fun register(owner: &signer, f: |u64| u64 with store+copy, k: u64) acquires Registry { │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types error: unsupported language construct - ┌─ tests/lambda/storable/registry_ok.move:106:41 - │ -106 │ fun multiply_by_x(x: u64): |u64|u64 with store { - │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types - -error: unsupported language construct - ┌─ tests/lambda/storable/registry_ok.move:110:42 + ┌─ tests/lambda/storable/registry_ok.move:110:23 │ -110 │ fun multiply_by_x2(x: u64): |u64|u64 with store { - │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types +110 │ FunctionValue(move |y| multiply(x, y)) + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression error: unsupported language construct - ┌─ tests/lambda/storable/registry_ok.move:111:9 + ┌─ tests/lambda/storable/registry_ok.move:114:23 │ -111 │ move |y| multiply(x, y) - │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression +114 │ FunctionValue(move |y| multiply(x, y)) + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok.lambda.exp index cfe0567301c9b..38be6559eeacd 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok.lambda.exp @@ -1,42 +1,10 @@ Diagnostics: -error: function type `|u64|u64 with copy+store` is not allowed as a field type - ┌─ tests/lambda/storable/registry_ok.move:10:12 - │ -10 │ f: |u64| u64 with store+copy, - │ ^^^^^^^^^^^^^^^^^^^^^^^^^ - │ - = required by declaration of field `f` - -error: function type `|u64|u64 with copy+store` is not allowed as a type argument (type was inferred) - ┌─ tests/lambda/storable/registry_ok.move:23:21 - │ -14 │ enum Option { - │ - declaration of type parameter `T` - · -23 │ x = Option::Some(f.f) - │ ^^^^^^^^^^^^ - │ - = required by instantiating type parameter `T` of struct `Option` - -error: function type `|u64|u64 with copy+store` is not allowed as a type argument - ┌─ tests/lambda/storable/registry_ok.move:29:109 - │ -14 │ enum Option { - │ - declaration of type parameter `T` - · -29 │ fun replace_or_add_function(v: &mut vector, k: u64, new_f: |u64| u64 with store+copy): Option<|u64| u64 with store+copy> { - │ ^^^^^^^^^^^^^^^^^^^^^^^^^ - │ - = required by instantiating type parameter `T` of struct `Option` - -error: function type `|u64|u64 with copy+store` is not allowed as a type argument (type was inferred) - ┌─ tests/lambda/storable/registry_ok.move:33:26 - │ -14 │ enum Option { - │ - declaration of type parameter `T` - · -33 │ result = Option::Some(f.f); - │ ^^^^^^^^^^^^ - │ - = required by instantiating type parameter `T` of struct `Option` +error: duplicate declaration, item, or annotation + ┌─ tests/lambda/storable/registry_ok.move:4:14 + │ +2 │ use std::signer; + │ ------ Alias previously defined here +3 │ use std::vector; +4 │ use std::signer; + │ ^^^^^^ Duplicate module alias 'signer'. Module aliases must be unique within a given namespace diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok.move b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok.move index 047415e26d4ef..bd0ec2f12cec9 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok.move +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok.move @@ -1,24 +1,27 @@ module 0x42::test { + use std::signer; use std::vector; use std::signer; + struct FunctionValue(|u64| u64 with store+copy) has store, copy, drop; + struct Registry has key { - functions: vector + functions: vector } - struct Function has store { - f: |u64| u64 with store+copy, + struct FunctionEntry has store, copy { + f: FunctionValue, key: u64 } - enum Option { + enum Option has store, copy { None(), Some(T) } - fun get_function(v: &vector, k: u64): Option { + fun get_function(v: &vector, k: u64): Option { let x = Option::None; - vector::for_each_ref(v, |f: &Function| { + vector::for_each_ref(v, |f: &FunctionEntry| { if (f.key == k) { x = Option::Some(f.f) } @@ -70,7 +73,7 @@ module 0x42::test { match (get_function(®istry.functions, k)) { Some(func) => { let Function { f: f, key: key } = func; - Option::Some(f(x)) + Option::Some((f.0)(x)) }, _ => { Option::None @@ -103,12 +106,12 @@ module 0x42::test { x * y } - fun multiply_by_x(x: u64): |u64|u64 with store { - |y| multiply(x, y) + fun multiply_by_x(x: u64): FunctionValue { + FunctionValue(move |y| multiply(x, y)) } - fun multiply_by_x2(x: u64): |u64|u64 with store { - move |y| multiply(x, y) + fun multiply_by_x2(x: u64): FunctionValue { + FunctionValue(move |y| multiply(x, y)) } #[test(a = @0x42)] diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok2.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok2.exp new file mode 100644 index 0000000000000..6c7af59b023f9 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok2.exp @@ -0,0 +1,61 @@ + +Diagnostics: +error: unsupported language construct + ┌─ tests/lambda/storable/registry_ok2.move:5:36 + │ +5 │ struct FunctionValue(|u64| u64 with store+copy) has store, copy, drop; + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types + +error: unsupported language construct + ┌─ tests/lambda/storable/registry_ok2.move:12:22 + │ +12 │ f: |u64| u64 with store+copy, + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types + +error: unsupported language construct + ┌─ tests/lambda/storable/registry_ok2.move:21:75 + │ +21 │ fun get_function(v: &vector, k: u64): Option<|u64| u64 with store+copy> { + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types + +error: unsupported language construct + ┌─ tests/lambda/storable/registry_ok2.move:31:85 + │ +31 │ fun replace_or_add_function(v: &mut vector, k: u64, f: |u64| u64 with store+copy): Option<|u64| u64 with store+copy> { + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types + +error: unsupported language construct + ┌─ tests/lambda/storable/registry_ok2.move:31:120 + │ +31 │ fun replace_or_add_function(v: &mut vector, k: u64, f: |u64| u64 with store+copy): Option<|u64| u64 with store+copy> { + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types + +error: unsupported language construct + ┌─ tests/lambda/storable/registry_ok2.move:52:47 + │ +52 │ fun register(owner: &signer, f: |u64| u64 with store+copy, k: u64) acquires Registry { + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types + +error: unsupported language construct + ┌─ tests/lambda/storable/registry_ok2.move:91:42 + │ +91 │ fun multiply_by_x(x: u64): |u64| u64 with store+copy { + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types + +error: unsupported language construct + ┌─ tests/lambda/storable/registry_ok2.move:92:9 + │ +92 │ move |y| multiply(x, y) + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/registry_ok2.move:95:43 + │ +95 │ fun multiply_by_x2(x: u64): |u64| u64 with store+copy { + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types + +error: unsupported language construct + ┌─ tests/lambda/storable/registry_ok2.move:96:9 + │ +96 │ move |y| multiply(x, y) + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok2.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok2.lambda.exp new file mode 100644 index 0000000000000..00cdf2ef8e2d2 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok2.lambda.exp @@ -0,0 +1,1909 @@ +// -- Model dump before env processor pipeline: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: |u64|u64 with copy+store, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option<|u64|u64 with copy+store> { + { + let x: Option<|u64|u64 with copy+store> = pack test::Option::None<|u64|u64 with copy+store>(); + vector::for_each_ref(v, |f: &FunctionEntry| if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option<|u64|u64 with copy+store> = pack test::Option::Some<|u64|u64 with copy+store>(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + }); + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some<|u64|u64 with copy+store>{ 0: f } => { + pack test::Option::Some((f)(x)) + } + _: Option<|u64|u64 with copy+store> => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): |u64|u64 with copy+store { + move|y: u64| test::multiply(x, y) + } + private fun multiply_by_x2(x: u64): |u64|u64 with copy+store { + move|y: u64| test::multiply(x, y) + } + private fun register(owner: &signer,f: |u64|u64 with copy+store,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: |u64|u64 with copy+store): Option<|u64|u64 with copy+store> { + { + let result: Option<|u64|u64 with copy+store> = pack test::Option::None<|u64|u64 with copy+store>(); + vector::for_each_mut(v, |record: &mut FunctionEntry| if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: |u64|u64 with copy+store = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option<|u64|u64 with copy+store> = pack test::Option::Some<|u64|u64 with copy+store>(old_f); + Tuple() + } + } else { + Tuple() + }); + match (result) { + test::Option::None<|u64|u64 with copy+store> => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None<|u64|u64 with copy+store>() + } + } + test::Option::Some<|u64|u64 with copy+store>{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor unused checks: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: |u64|u64 with copy+store, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option<|u64|u64 with copy+store> { + { + let x: Option<|u64|u64 with copy+store> = pack test::Option::None<|u64|u64 with copy+store>(); + vector::for_each_ref(v, |f: &FunctionEntry| if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option<|u64|u64 with copy+store> = pack test::Option::Some<|u64|u64 with copy+store>(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + }); + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some<|u64|u64 with copy+store>{ 0: f } => { + pack test::Option::Some((f)(x)) + } + _: Option<|u64|u64 with copy+store> => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): |u64|u64 with copy+store { + move|y: u64| test::multiply(x, y) + } + private fun multiply_by_x2(x: u64): |u64|u64 with copy+store { + move|y: u64| test::multiply(x, y) + } + private fun register(owner: &signer,f: |u64|u64 with copy+store,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: |u64|u64 with copy+store): Option<|u64|u64 with copy+store> { + { + let result: Option<|u64|u64 with copy+store> = pack test::Option::None<|u64|u64 with copy+store>(); + vector::for_each_mut(v, |record: &mut FunctionEntry| if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: |u64|u64 with copy+store = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option<|u64|u64 with copy+store> = pack test::Option::Some<|u64|u64 with copy+store>(old_f); + Tuple() + } + } else { + Tuple() + }); + match (result) { + test::Option::None<|u64|u64 with copy+store> => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None<|u64|u64 with copy+store>() + } + } + test::Option::Some<|u64|u64 with copy+store>{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor type parameter check: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: |u64|u64 with copy+store, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option<|u64|u64 with copy+store> { + { + let x: Option<|u64|u64 with copy+store> = pack test::Option::None<|u64|u64 with copy+store>(); + vector::for_each_ref(v, |f: &FunctionEntry| if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option<|u64|u64 with copy+store> = pack test::Option::Some<|u64|u64 with copy+store>(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + }); + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some<|u64|u64 with copy+store>{ 0: f } => { + pack test::Option::Some((f)(x)) + } + _: Option<|u64|u64 with copy+store> => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): |u64|u64 with copy+store { + move|y: u64| test::multiply(x, y) + } + private fun multiply_by_x2(x: u64): |u64|u64 with copy+store { + move|y: u64| test::multiply(x, y) + } + private fun register(owner: &signer,f: |u64|u64 with copy+store,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: |u64|u64 with copy+store): Option<|u64|u64 with copy+store> { + { + let result: Option<|u64|u64 with copy+store> = pack test::Option::None<|u64|u64 with copy+store>(); + vector::for_each_mut(v, |record: &mut FunctionEntry| if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: |u64|u64 with copy+store = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option<|u64|u64 with copy+store> = pack test::Option::Some<|u64|u64 with copy+store>(old_f); + Tuple() + } + } else { + Tuple() + }); + match (result) { + test::Option::None<|u64|u64 with copy+store> => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None<|u64|u64 with copy+store>() + } + } + test::Option::Some<|u64|u64 with copy+store>{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor check recursive struct definition: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: |u64|u64 with copy+store, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option<|u64|u64 with copy+store> { + { + let x: Option<|u64|u64 with copy+store> = pack test::Option::None<|u64|u64 with copy+store>(); + vector::for_each_ref(v, |f: &FunctionEntry| if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option<|u64|u64 with copy+store> = pack test::Option::Some<|u64|u64 with copy+store>(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + }); + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some<|u64|u64 with copy+store>{ 0: f } => { + pack test::Option::Some((f)(x)) + } + _: Option<|u64|u64 with copy+store> => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): |u64|u64 with copy+store { + move|y: u64| test::multiply(x, y) + } + private fun multiply_by_x2(x: u64): |u64|u64 with copy+store { + move|y: u64| test::multiply(x, y) + } + private fun register(owner: &signer,f: |u64|u64 with copy+store,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: |u64|u64 with copy+store): Option<|u64|u64 with copy+store> { + { + let result: Option<|u64|u64 with copy+store> = pack test::Option::None<|u64|u64 with copy+store>(); + vector::for_each_mut(v, |record: &mut FunctionEntry| if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: |u64|u64 with copy+store = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option<|u64|u64 with copy+store> = pack test::Option::Some<|u64|u64 with copy+store>(old_f); + Tuple() + } + } else { + Tuple() + }); + match (result) { + test::Option::None<|u64|u64 with copy+store> => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None<|u64|u64 with copy+store>() + } + } + test::Option::Some<|u64|u64 with copy+store>{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor check cyclic type instantiation: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: |u64|u64 with copy+store, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option<|u64|u64 with copy+store> { + { + let x: Option<|u64|u64 with copy+store> = pack test::Option::None<|u64|u64 with copy+store>(); + vector::for_each_ref(v, |f: &FunctionEntry| if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option<|u64|u64 with copy+store> = pack test::Option::Some<|u64|u64 with copy+store>(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + }); + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some<|u64|u64 with copy+store>{ 0: f } => { + pack test::Option::Some((f)(x)) + } + _: Option<|u64|u64 with copy+store> => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): |u64|u64 with copy+store { + move|y: u64| test::multiply(x, y) + } + private fun multiply_by_x2(x: u64): |u64|u64 with copy+store { + move|y: u64| test::multiply(x, y) + } + private fun register(owner: &signer,f: |u64|u64 with copy+store,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: |u64|u64 with copy+store): Option<|u64|u64 with copy+store> { + { + let result: Option<|u64|u64 with copy+store> = pack test::Option::None<|u64|u64 with copy+store>(); + vector::for_each_mut(v, |record: &mut FunctionEntry| if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: |u64|u64 with copy+store = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option<|u64|u64 with copy+store> = pack test::Option::Some<|u64|u64 with copy+store>(old_f); + Tuple() + } + } else { + Tuple() + }); + match (result) { + test::Option::None<|u64|u64 with copy+store> => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None<|u64|u64 with copy+store>() + } + } + test::Option::Some<|u64|u64 with copy+store>{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor unused struct params check: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: |u64|u64 with copy+store, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option<|u64|u64 with copy+store> { + { + let x: Option<|u64|u64 with copy+store> = pack test::Option::None<|u64|u64 with copy+store>(); + vector::for_each_ref(v, |f: &FunctionEntry| if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option<|u64|u64 with copy+store> = pack test::Option::Some<|u64|u64 with copy+store>(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + }); + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some<|u64|u64 with copy+store>{ 0: f } => { + pack test::Option::Some((f)(x)) + } + _: Option<|u64|u64 with copy+store> => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): |u64|u64 with copy+store { + move|y: u64| test::multiply(x, y) + } + private fun multiply_by_x2(x: u64): |u64|u64 with copy+store { + move|y: u64| test::multiply(x, y) + } + private fun register(owner: &signer,f: |u64|u64 with copy+store,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: |u64|u64 with copy+store): Option<|u64|u64 with copy+store> { + { + let result: Option<|u64|u64 with copy+store> = pack test::Option::None<|u64|u64 with copy+store>(); + vector::for_each_mut(v, |record: &mut FunctionEntry| if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: |u64|u64 with copy+store = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option<|u64|u64 with copy+store> = pack test::Option::Some<|u64|u64 with copy+store>(old_f); + Tuple() + } + } else { + Tuple() + }); + match (result) { + test::Option::None<|u64|u64 with copy+store> => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None<|u64|u64 with copy+store>() + } + } + test::Option::Some<|u64|u64 with copy+store>{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor access and use check before inlining: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: |u64|u64 with copy+store, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option<|u64|u64 with copy+store> { + { + let x: Option<|u64|u64 with copy+store> = pack test::Option::None<|u64|u64 with copy+store>(); + vector::for_each_ref(v, |f: &FunctionEntry| if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option<|u64|u64 with copy+store> = pack test::Option::Some<|u64|u64 with copy+store>(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + }); + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some<|u64|u64 with copy+store>{ 0: f } => { + pack test::Option::Some((f)(x)) + } + _: Option<|u64|u64 with copy+store> => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): |u64|u64 with copy+store { + move|y: u64| test::multiply(x, y) + } + private fun multiply_by_x2(x: u64): |u64|u64 with copy+store { + move|y: u64| test::multiply(x, y) + } + private fun register(owner: &signer,f: |u64|u64 with copy+store,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: |u64|u64 with copy+store): Option<|u64|u64 with copy+store> { + { + let result: Option<|u64|u64 with copy+store> = pack test::Option::None<|u64|u64 with copy+store>(); + vector::for_each_mut(v, |record: &mut FunctionEntry| if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: |u64|u64 with copy+store = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option<|u64|u64 with copy+store> = pack test::Option::Some<|u64|u64 with copy+store>(old_f); + Tuple() + } + } else { + Tuple() + }); + match (result) { + test::Option::None<|u64|u64 with copy+store> => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None<|u64|u64 with copy+store>() + } + } + test::Option::Some<|u64|u64 with copy+store>{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor inlining: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: |u64|u64 with copy+store, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option<|u64|u64 with copy+store> { + { + let x: Option<|u64|u64 with copy+store> = pack test::Option::None<|u64|u64 with copy+store>(); + { + let (v: &vector): (&vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(v)) { + { + let (f: &FunctionEntry): (&FunctionEntry) = Tuple(vector::borrow(v, i)); + if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option<|u64|u64 with copy+store> = pack test::Option::Some<|u64|u64 with copy+store>(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some<|u64|u64 with copy+store>{ 0: f } => { + pack test::Option::Some((f)(x)) + } + _: Option<|u64|u64 with copy+store> => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): |u64|u64 with copy+store { + move|y: u64| test::multiply(x, y) + } + private fun multiply_by_x2(x: u64): |u64|u64 with copy+store { + move|y: u64| test::multiply(x, y) + } + private fun register(owner: &signer,f: |u64|u64 with copy+store,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: |u64|u64 with copy+store): Option<|u64|u64 with copy+store> { + { + let result: Option<|u64|u64 with copy+store> = pack test::Option::None<|u64|u64 with copy+store>(); + { + let (v: &mut vector): (&mut vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(Freeze(false)(v))) { + { + let (record: &mut FunctionEntry): (&mut FunctionEntry) = Tuple(vector::borrow_mut(v, i)); + if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: |u64|u64 with copy+store = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option<|u64|u64 with copy+store> = pack test::Option::Some<|u64|u64 with copy+store>(old_f); + Tuple() + } + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + match (result) { + test::Option::None<|u64|u64 with copy+store> => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None<|u64|u64 with copy+store>() + } + } + test::Option::Some<|u64|u64 with copy+store>{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor access and use check after inlining: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: |u64|u64 with copy+store, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option<|u64|u64 with copy+store> { + { + let x: Option<|u64|u64 with copy+store> = pack test::Option::None<|u64|u64 with copy+store>(); + { + let (v: &vector): (&vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(v)) { + { + let (f: &FunctionEntry): (&FunctionEntry) = Tuple(vector::borrow(v, i)); + if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option<|u64|u64 with copy+store> = pack test::Option::Some<|u64|u64 with copy+store>(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some<|u64|u64 with copy+store>{ 0: f } => { + pack test::Option::Some((f)(x)) + } + _: Option<|u64|u64 with copy+store> => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): |u64|u64 with copy+store { + move|y: u64| test::multiply(x, y) + } + private fun multiply_by_x2(x: u64): |u64|u64 with copy+store { + move|y: u64| test::multiply(x, y) + } + private fun register(owner: &signer,f: |u64|u64 with copy+store,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: |u64|u64 with copy+store): Option<|u64|u64 with copy+store> { + { + let result: Option<|u64|u64 with copy+store> = pack test::Option::None<|u64|u64 with copy+store>(); + { + let (v: &mut vector): (&mut vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(Freeze(false)(v))) { + { + let (record: &mut FunctionEntry): (&mut FunctionEntry) = Tuple(vector::borrow_mut(v, i)); + if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: |u64|u64 with copy+store = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option<|u64|u64 with copy+store> = pack test::Option::Some<|u64|u64 with copy+store>(old_f); + Tuple() + } + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + match (result) { + test::Option::None<|u64|u64 with copy+store> => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None<|u64|u64 with copy+store>() + } + } + test::Option::Some<|u64|u64 with copy+store>{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor acquires check: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: |u64|u64 with copy+store, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option<|u64|u64 with copy+store> { + { + let x: Option<|u64|u64 with copy+store> = pack test::Option::None<|u64|u64 with copy+store>(); + { + let (v: &vector): (&vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(v)) { + { + let (f: &FunctionEntry): (&FunctionEntry) = Tuple(vector::borrow(v, i)); + if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option<|u64|u64 with copy+store> = pack test::Option::Some<|u64|u64 with copy+store>(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some<|u64|u64 with copy+store>{ 0: f } => { + pack test::Option::Some((f)(x)) + } + _: Option<|u64|u64 with copy+store> => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): |u64|u64 with copy+store { + move|y: u64| test::multiply(x, y) + } + private fun multiply_by_x2(x: u64): |u64|u64 with copy+store { + move|y: u64| test::multiply(x, y) + } + private fun register(owner: &signer,f: |u64|u64 with copy+store,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: |u64|u64 with copy+store): Option<|u64|u64 with copy+store> { + { + let result: Option<|u64|u64 with copy+store> = pack test::Option::None<|u64|u64 with copy+store>(); + { + let (v: &mut vector): (&mut vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(Freeze(false)(v))) { + { + let (record: &mut FunctionEntry): (&mut FunctionEntry) = Tuple(vector::borrow_mut(v, i)); + if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: |u64|u64 with copy+store = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option<|u64|u64 with copy+store> = pack test::Option::Some<|u64|u64 with copy+store>(old_f); + Tuple() + } + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + match (result) { + test::Option::None<|u64|u64 with copy+store> => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None<|u64|u64 with copy+store>() + } + } + test::Option::Some<|u64|u64 with copy+store>{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor simplifier: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: |u64|u64 with copy+store, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option<|u64|u64 with copy+store> { + { + let x: Option<|u64|u64 with copy+store> = pack test::Option::None<|u64|u64 with copy+store>(); + { + let (v: &vector): (&vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(v)) { + { + let (f: &FunctionEntry): (&FunctionEntry) = Tuple(vector::borrow(v, i)); + if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option<|u64|u64 with copy+store> = pack test::Option::Some<|u64|u64 with copy+store>(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some<|u64|u64 with copy+store>{ 0: f } => { + pack test::Option::Some((f)(x)) + } + _: Option<|u64|u64 with copy+store> => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): |u64|u64 with copy+store { + move|y: u64| test::multiply(x, y) + } + private fun multiply_by_x2(x: u64): |u64|u64 with copy+store { + move|y: u64| test::multiply(x, y) + } + private fun register(owner: &signer,f: |u64|u64 with copy+store,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: |u64|u64 with copy+store): Option<|u64|u64 with copy+store> { + { + let result: Option<|u64|u64 with copy+store> = pack test::Option::None<|u64|u64 with copy+store>(); + { + let (v: &mut vector): (&mut vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(Freeze(false)(v))) { + { + let (record: &mut FunctionEntry): (&mut FunctionEntry) = Tuple(vector::borrow_mut(v, i)); + if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: |u64|u64 with copy+store = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option<|u64|u64 with copy+store> = pack test::Option::Some<|u64|u64 with copy+store>(old_f); + Tuple() + } + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + match (result) { + test::Option::None<|u64|u64 with copy+store> => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None<|u64|u64 with copy+store>() + } + } + test::Option::Some<|u64|u64 with copy+store>{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor lambda-lifting: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: |u64|u64 with copy+store, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option<|u64|u64 with copy+store> { + { + let x: Option<|u64|u64 with copy+store> = pack test::Option::None<|u64|u64 with copy+store>(); + { + let (v: &vector): (&vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(v)) { + { + let (f: &FunctionEntry): (&FunctionEntry) = Tuple(vector::borrow(v, i)); + if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option<|u64|u64 with copy+store> = pack test::Option::Some<|u64|u64 with copy+store>(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some<|u64|u64 with copy+store>{ 0: f } => { + pack test::Option::Some((f)(x)) + } + _: Option<|u64|u64 with copy+store> => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): |u64|u64 with copy+store { + earlybind(test::multiply, x) + } + private fun multiply_by_x2(x: u64): |u64|u64 with copy+store { + earlybind(test::multiply, x) + } + private fun register(owner: &signer,f: |u64|u64 with copy+store,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: |u64|u64 with copy+store): Option<|u64|u64 with copy+store> { + { + let result: Option<|u64|u64 with copy+store> = pack test::Option::None<|u64|u64 with copy+store>(); + { + let (v: &mut vector): (&mut vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(Freeze(false)(v))) { + { + let (record: &mut FunctionEntry): (&mut FunctionEntry) = Tuple(vector::borrow_mut(v, i)); + if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: |u64|u64 with copy+store = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option<|u64|u64 with copy+store> = pack test::Option::Some<|u64|u64 with copy+store>(old_f); + Tuple() + } + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + match (result) { + test::Option::None<|u64|u64 with copy+store> => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None<|u64|u64 with copy+store>() + } + } + test::Option::Some<|u64|u64 with copy+store>{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor specification checker: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: |u64|u64 with copy+store, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option<|u64|u64 with copy+store> { + { + let x: Option<|u64|u64 with copy+store> = pack test::Option::None<|u64|u64 with copy+store>(); + { + let (v: &vector): (&vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(v)) { + { + let (f: &FunctionEntry): (&FunctionEntry) = Tuple(vector::borrow(v, i)); + if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option<|u64|u64 with copy+store> = pack test::Option::Some<|u64|u64 with copy+store>(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some<|u64|u64 with copy+store>{ 0: f } => { + pack test::Option::Some((f)(x)) + } + _: Option<|u64|u64 with copy+store> => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): |u64|u64 with copy+store { + earlybind(test::multiply, x) + } + private fun multiply_by_x2(x: u64): |u64|u64 with copy+store { + earlybind(test::multiply, x) + } + private fun register(owner: &signer,f: |u64|u64 with copy+store,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: |u64|u64 with copy+store): Option<|u64|u64 with copy+store> { + { + let result: Option<|u64|u64 with copy+store> = pack test::Option::None<|u64|u64 with copy+store>(); + { + let (v: &mut vector): (&mut vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(Freeze(false)(v))) { + { + let (record: &mut FunctionEntry): (&mut FunctionEntry) = Tuple(vector::borrow_mut(v, i)); + if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: |u64|u64 with copy+store = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option<|u64|u64 with copy+store> = pack test::Option::Some<|u64|u64 with copy+store>(old_f); + Tuple() + } + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + match (result) { + test::Option::None<|u64|u64 with copy+store> => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None<|u64|u64 with copy+store>() + } + } + test::Option::Some<|u64|u64 with copy+store>{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor specification rewriter: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: |u64|u64 with copy+store, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option<|u64|u64 with copy+store> { + { + let x: Option<|u64|u64 with copy+store> = pack test::Option::None<|u64|u64 with copy+store>(); + { + let (v: &vector): (&vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(v)) { + { + let (f: &FunctionEntry): (&FunctionEntry) = Tuple(vector::borrow(v, i)); + if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option<|u64|u64 with copy+store> = pack test::Option::Some<|u64|u64 with copy+store>(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some<|u64|u64 with copy+store>{ 0: f } => { + pack test::Option::Some((f)(x)) + } + _: Option<|u64|u64 with copy+store> => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): |u64|u64 with copy+store { + earlybind(test::multiply, x) + } + private fun multiply_by_x2(x: u64): |u64|u64 with copy+store { + earlybind(test::multiply, x) + } + private fun register(owner: &signer,f: |u64|u64 with copy+store,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: |u64|u64 with copy+store): Option<|u64|u64 with copy+store> { + { + let result: Option<|u64|u64 with copy+store> = pack test::Option::None<|u64|u64 with copy+store>(); + { + let (v: &mut vector): (&mut vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(Freeze(false)(v))) { + { + let (record: &mut FunctionEntry): (&mut FunctionEntry) = Tuple(vector::borrow_mut(v, i)); + if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: |u64|u64 with copy+store = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option<|u64|u64 with copy+store> = pack test::Option::Some<|u64|u64 with copy+store>(old_f); + Tuple() + } + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + match (result) { + test::Option::None<|u64|u64 with copy+store> => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None<|u64|u64 with copy+store>() + } + } + test::Option::Some<|u64|u64 with copy+store>{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + + +Diagnostics: +error: Calls to function values other than inline function parameters not yet implemented + ┌─ tests/lambda/storable/registry_ok2.move:71:30 + │ +71 │ Option::Some(f(x)) + │ ^^^^ + +error: Function-typed values not yet implemented except as parameters to calls to inline functions + ┌─ tests/lambda/storable/registry_ok2.move:92:9 + │ +92 │ move |y| multiply(x, y) + │ ^^^^^^^^^^^^^^^^^^^^^^^ + +error: Function-typed values not yet implemented except as parameters to calls to inline functions + ┌─ tests/lambda/storable/registry_ok2.move:96:9 + │ +96 │ move |y| multiply(x, y) + │ ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok2.move b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok2.move new file mode 100644 index 0000000000000..fbfd16c17475d --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok2.move @@ -0,0 +1,128 @@ +module 0x42::test { + use std::signer; + use std::vector; + + struct FunctionValue(|u64| u64 with store+copy) has store, copy, drop; + + struct Registry has key { + functions: vector + } + + struct FunctionEntry has store, copy, drop { + f: |u64| u64 with store+copy, + key: u64 + } + + enum Option has store, copy { + None(), + Some(T) + } + + fun get_function(v: &vector, k: u64): Option<|u64| u64 with store+copy> { + let x = Option::None; + vector::for_each_ref(v, |f: &FunctionEntry| { + if (f.key == k) { + x = Option::Some(f.f) + } + }); + x + } + + fun replace_or_add_function(v: &mut vector, k: u64, f: |u64| u64 with store+copy): Option<|u64| u64 with store+copy> { + let result = Option::None; + vector::for_each_mut(v, |record: &mut FunctionEntry| { + if (record.key == k) { + let old_f = record.f; + record.f = f; + result = Option::Some(old_f); + } + }); + match (result) { + Option::None => { + let new_record = FunctionEntry { f: f, key: k }; + vector::push_back(v, new_record); + Option::None + }, + Option::Some(_) => { + result + } + } + } + + fun register(owner: &signer, f: |u64| u64 with store+copy, k: u64) acquires Registry { + let addr = signer::address_of(owner); + if (!exists(addr)) { + let new_registry = Registry { + functions: vector[] + }; + move_to(owner, new_registry); + }; + let registry = borrow_global_mut(addr); + replace_or_add_function(&mut registry.functions, k, f); + } + + fun invoke(addr: address, k: u64, x: u64): Option acquires Registry { + if (!exists(addr)) { + return Option::None + }; + let registry = borrow_global(addr); + match (get_function(®istry.functions, k)) { + Option::Some(f) => { + Option::Some(f(x)) + }, + _ => { + Option::None + } + } + } + + fun double(x: u64):u64 { + x * 2 + } + + fun triple(x: u64):u64 { + x * 3 + } + + public fun multiply(x: u64, y: u64): u64 { + x * y + } + + fun multiply_by_x(x: u64): |u64| u64 with store+copy { + move |y| multiply(x, y) + } + + fun multiply_by_x2(x: u64): |u64| u64 with store+copy { + move |y| multiply(x, y) + } + + #[test(a = @0x42)] + fun test_registry1(a: signer) { + register(a, double, 2); + register(a, negate, 3); + register(a, multiply_by_x(4), 4); + register(a, multiply_by_x(5), 5); + register(a, multiply_by_x2(6), 6); + + match (invoke(a, 2, 10)) { + Some(x) => { assert!(x == 20); } + _ => assert!(false) + }; + match (invoke(a, 3, 11)) { + Some(x) => { assert!(x == 33); } + _ => assert!(false) + }; + match (invoke(a, 4, 2)) { + Some(x) => { assert!(x == 8); } + _ => assert!(false) + }; + match (invoke(a, 5, 3)) { + Some(x) => { assert!(x == 15); } + _ => assert!(false) + }; + match (invoke(a, 6, 3)) { + Some(x) => { assert!(x == 18); } + _ => assert!(false) + }; + } +} diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/return_func.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/return_func.lambda.exp index 7dd9a43a5339c..b40e18997943d 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/storable/return_func.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/return_func.lambda.exp @@ -29,19 +29,3 @@ error: expected `|integer|_ with copy+store` but found a value of type `u64` │ 87 │ vector::push_back(&mut sum, h(6)); │ ^^^^ - -error: function type `|integer|_` is not allowed as a type argument (type was inferred) - ┌─ tests/lambda/storable/return_func.move:89:21 - │ -89 │ let funcs = vector[choose_function(0), choose_function(1), choose_function(2)]; - │ ^^^^^^ - │ - = required by instantiating vector type parameter - -error: function type `|u64|u64 with store` is not allowed as a type argument (type was inferred) - ┌─ tests/lambda/storable/return_func.move:89:21 - │ -89 │ let funcs = vector[choose_function(0), choose_function(1), choose_function(2)]; - │ ^^^^^^ - │ - = required by instantiating vector type parameter diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/return_func_ok.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/return_func_ok.exp new file mode 100644 index 0000000000000..dad5d051d6533 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/return_func_ok.exp @@ -0,0 +1,187 @@ + +Diagnostics: +error: unsupported language construct + ┌─ tests/lambda/storable/return_func_ok.move:20:41 + │ +20 │ fun multiply_by_x(x: u64): |u64|u64 with store { + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func_ok.move:21:9 + │ +21 │ move |y| multiply(x, y) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func_ok.move:21:33 + │ +21 │ move |y| multiply(x, y) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func_ok.move:24:46 + │ +24 │ fun choose_function(key: u64) : |u64|u64 with store { + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func_ok.move:34:46 + │ +34 │ fun choose_function2(key: u64): |u64|u64 with store { + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func_ok.move:36:13 + │ +36 │ move |x| double(x) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func_ok.move:36:32 + │ +36 │ move |x| double(x) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func_ok.move:38:13 + │ +38 │ move |x| triple(x) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func_ok.move:38:32 + │ +38 │ move |x| triple(x) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func_ok.move:41:13 + │ +41 │ move |x| f(x) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func_ok.move:41:27 + │ +41 │ move |x| f(x) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func_ok.move:44:13 + │ +44 │ move |x| f(x) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func_ok.move:44:27 + │ +44 │ move |x| f(x) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func_ok.move:46:21 + │ +46 │ let f = move |y| multiply(6, y) with store; + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func_ok.move:46:45 + │ +46 │ let f = move |y| multiply(6, y) with store; + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func_ok.move:49:13 + │ +49 │ move |y| multiply(y, 7) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func_ok.move:49:37 + │ +49 │ move |y| multiply(y, 7) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func_ok.move:51:21 + │ +51 │ let f = move |y| multiply(6, y) with store; + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func_ok.move:51:45 + │ +51 │ let f = move |y| multiply(6, y) with store; + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func_ok.move:52:13 + │ +52 │ move |x| f(x) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func_ok.move:52:27 + │ +52 │ move |x| f(x) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func_ok.move:55:13 + │ +55 │ move |x| f(x) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func_ok.move:55:27 + │ +55 │ move |x| f(x) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func_ok.move:57:13 + │ +57 │ move |y| multiply3(y, 3, 4) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func_ok.move:57:41 + │ +57 │ move |y| multiply3(y, 3, 4) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func_ok.move:61:47 + │ +61 │ fun choose_function3(key: u64) : |u64|u64 with store { + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func_ok.move:63:21 + │ +63 │ let f = move |x| double(x) with store; + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func_ok.move:63:40 + │ +63 │ let f = move |x| double(x) with store; + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func_ok.move:66:21 + │ +66 │ let g = move |x| triple(x) with store; + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func_ok.move:66:40 + │ +66 │ let g = move |x| triple(x) with store; + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func_ok.move:74:67 + │ +74 │ public fun test_functions(choose_function_arg: |u64|(|u64|u64 with store)) { + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/return_func_ok.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/return_func_ok.lambda.exp new file mode 100644 index 0000000000000..b37236d35a6fc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/return_func_ok.lambda.exp @@ -0,0 +1,1572 @@ +// -- Model dump before env processor pipeline: +module 0x42::test { + use std::vector; + private fun choose_function(key: u64): |u64|u64 with store { + if Eq(key, 0) { + test::double + } else { + if Eq(key, 1) { + test::triple + } else { + test::multiply_by_x(4) + } + } + } + private fun choose_function2(key: u64): |u64|u64 with store { + if Eq(key, 0) { + move|x: u64| test::double(x) with drop, store + } else { + if Eq(key, 1) { + move|x: u64| test::triple(x) with drop, store + } else { + if Eq(key, 2) { + { + let f: |u64|u64 with store = test::multiply_by_x(4); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 3) { + { + let f: |u64|u64 with store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 4) { + { + let f: |u64|u64 with copy+store = move|y: u64| test::multiply(6, y) with drop, store; + f + } + } else { + if Eq(key, 5) { + move|y: u64| test::multiply(y, 7) with drop, store + } else { + if Eq(key, 6) { + { + let f: |u64|u64 with copy+store = move|y: u64| test::multiply(6, y) with drop, store; + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 7) { + { + let f: |u64|u64 with store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + move|y: u64| test::multiply3(y, 3, 4) with drop, store + } + } + } + } + } + } + } + } + } + private fun choose_function3(key: u64): |u64|u64 with store { + if Eq(key, 0) { + { + let f: |u64|u64 with copy+store = move|x: u64| test::double(x) with drop, store; + f + } + } else { + if Eq(key, 1) { + { + let g: |u64|u64 with copy+store = move|x: u64| test::triple(x) with drop, store; + g + } + } else { + { + let h: |u64|u64 with store = test::multiply_by_x(4); + h + } + } + } + } + public fun double(x: u64): u64 { + Mul(x, 2) + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + public fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + private fun multiply_by_x(x: u64): |u64|u64 with store { + move|y: u64| test::multiply(x, y) with drop, store + } + public fun test_function_choosers() { + test::test_functions(test::choose_function); + test::test_functions(test::choose_function2); + test::test_functions(test::choose_function3); + Tuple() + } + public fun test_functions(choose_function_arg: |u64||u64|u64 with store) { + { + let sum: vector = Vector(); + { + let x: u64 = 3; + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(0))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(1))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(2))(x)); + { + let g: |u64|u64 with store = test::choose_function(1); + { + let h: |u64|u64 with store = test::choose_function(2); + { + let f: |u64|u64 with store = test::choose_function(0); + vector::push_back(Borrow(Mutable)(sum), (f)(5)); + vector::push_back(Borrow(Mutable)(sum), (g)(7)); + vector::push_back(Borrow(Mutable)(sum), (h)(6)); + { + let funcs: vector<|u64|u64 with store> = Vector<|u64|u64 with store>(test::choose_function(0), test::choose_function(1), test::choose_function(2)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 0)))(9)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 1)))(11)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 2)))(13)); + if Eq>(sum, Vector(6, 9, 12, 10, 21, 24, 18, 33, 52)) { + Tuple() + } else { + Abort(14566554180833181696) + } + } + } + } + } + } + } + } + public fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor unused checks: +module 0x42::test { + use std::vector; + private fun choose_function(key: u64): |u64|u64 with store { + if Eq(key, 0) { + test::double + } else { + if Eq(key, 1) { + test::triple + } else { + test::multiply_by_x(4) + } + } + } + private fun choose_function2(key: u64): |u64|u64 with store { + if Eq(key, 0) { + move|x: u64| test::double(x) with drop, store + } else { + if Eq(key, 1) { + move|x: u64| test::triple(x) with drop, store + } else { + if Eq(key, 2) { + { + let f: |u64|u64 with store = test::multiply_by_x(4); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 3) { + { + let f: |u64|u64 with store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 4) { + { + let f: |u64|u64 with copy+store = move|y: u64| test::multiply(6, y) with drop, store; + f + } + } else { + if Eq(key, 5) { + move|y: u64| test::multiply(y, 7) with drop, store + } else { + if Eq(key, 6) { + { + let f: |u64|u64 with copy+store = move|y: u64| test::multiply(6, y) with drop, store; + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 7) { + { + let f: |u64|u64 with store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + move|y: u64| test::multiply3(y, 3, 4) with drop, store + } + } + } + } + } + } + } + } + } + private fun choose_function3(key: u64): |u64|u64 with store { + if Eq(key, 0) { + { + let f: |u64|u64 with copy+store = move|x: u64| test::double(x) with drop, store; + f + } + } else { + if Eq(key, 1) { + { + let g: |u64|u64 with copy+store = move|x: u64| test::triple(x) with drop, store; + g + } + } else { + { + let h: |u64|u64 with store = test::multiply_by_x(4); + h + } + } + } + } + public fun double(x: u64): u64 { + Mul(x, 2) + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + public fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + private fun multiply_by_x(x: u64): |u64|u64 with store { + move|y: u64| test::multiply(x, y) with drop, store + } + public fun test_function_choosers() { + test::test_functions(test::choose_function); + test::test_functions(test::choose_function2); + test::test_functions(test::choose_function3); + Tuple() + } + public fun test_functions(choose_function_arg: |u64||u64|u64 with store) { + { + let sum: vector = Vector(); + { + let x: u64 = 3; + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(0))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(1))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(2))(x)); + { + let g: |u64|u64 with store = test::choose_function(1); + { + let h: |u64|u64 with store = test::choose_function(2); + { + let f: |u64|u64 with store = test::choose_function(0); + vector::push_back(Borrow(Mutable)(sum), (f)(5)); + vector::push_back(Borrow(Mutable)(sum), (g)(7)); + vector::push_back(Borrow(Mutable)(sum), (h)(6)); + { + let funcs: vector<|u64|u64 with store> = Vector<|u64|u64 with store>(test::choose_function(0), test::choose_function(1), test::choose_function(2)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 0)))(9)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 1)))(11)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 2)))(13)); + if Eq>(sum, Vector(6, 9, 12, 10, 21, 24, 18, 33, 52)) { + Tuple() + } else { + Abort(14566554180833181696) + } + } + } + } + } + } + } + } + public fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor type parameter check: +module 0x42::test { + use std::vector; + private fun choose_function(key: u64): |u64|u64 with store { + if Eq(key, 0) { + test::double + } else { + if Eq(key, 1) { + test::triple + } else { + test::multiply_by_x(4) + } + } + } + private fun choose_function2(key: u64): |u64|u64 with store { + if Eq(key, 0) { + move|x: u64| test::double(x) with drop, store + } else { + if Eq(key, 1) { + move|x: u64| test::triple(x) with drop, store + } else { + if Eq(key, 2) { + { + let f: |u64|u64 with store = test::multiply_by_x(4); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 3) { + { + let f: |u64|u64 with store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 4) { + { + let f: |u64|u64 with copy+store = move|y: u64| test::multiply(6, y) with drop, store; + f + } + } else { + if Eq(key, 5) { + move|y: u64| test::multiply(y, 7) with drop, store + } else { + if Eq(key, 6) { + { + let f: |u64|u64 with copy+store = move|y: u64| test::multiply(6, y) with drop, store; + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 7) { + { + let f: |u64|u64 with store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + move|y: u64| test::multiply3(y, 3, 4) with drop, store + } + } + } + } + } + } + } + } + } + private fun choose_function3(key: u64): |u64|u64 with store { + if Eq(key, 0) { + { + let f: |u64|u64 with copy+store = move|x: u64| test::double(x) with drop, store; + f + } + } else { + if Eq(key, 1) { + { + let g: |u64|u64 with copy+store = move|x: u64| test::triple(x) with drop, store; + g + } + } else { + { + let h: |u64|u64 with store = test::multiply_by_x(4); + h + } + } + } + } + public fun double(x: u64): u64 { + Mul(x, 2) + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + public fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + private fun multiply_by_x(x: u64): |u64|u64 with store { + move|y: u64| test::multiply(x, y) with drop, store + } + public fun test_function_choosers() { + test::test_functions(test::choose_function); + test::test_functions(test::choose_function2); + test::test_functions(test::choose_function3); + Tuple() + } + public fun test_functions(choose_function_arg: |u64||u64|u64 with store) { + { + let sum: vector = Vector(); + { + let x: u64 = 3; + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(0))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(1))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(2))(x)); + { + let g: |u64|u64 with store = test::choose_function(1); + { + let h: |u64|u64 with store = test::choose_function(2); + { + let f: |u64|u64 with store = test::choose_function(0); + vector::push_back(Borrow(Mutable)(sum), (f)(5)); + vector::push_back(Borrow(Mutable)(sum), (g)(7)); + vector::push_back(Borrow(Mutable)(sum), (h)(6)); + { + let funcs: vector<|u64|u64 with store> = Vector<|u64|u64 with store>(test::choose_function(0), test::choose_function(1), test::choose_function(2)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 0)))(9)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 1)))(11)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 2)))(13)); + if Eq>(sum, Vector(6, 9, 12, 10, 21, 24, 18, 33, 52)) { + Tuple() + } else { + Abort(14566554180833181696) + } + } + } + } + } + } + } + } + public fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor check recursive struct definition: +module 0x42::test { + use std::vector; + private fun choose_function(key: u64): |u64|u64 with store { + if Eq(key, 0) { + test::double + } else { + if Eq(key, 1) { + test::triple + } else { + test::multiply_by_x(4) + } + } + } + private fun choose_function2(key: u64): |u64|u64 with store { + if Eq(key, 0) { + move|x: u64| test::double(x) with drop, store + } else { + if Eq(key, 1) { + move|x: u64| test::triple(x) with drop, store + } else { + if Eq(key, 2) { + { + let f: |u64|u64 with store = test::multiply_by_x(4); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 3) { + { + let f: |u64|u64 with store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 4) { + { + let f: |u64|u64 with copy+store = move|y: u64| test::multiply(6, y) with drop, store; + f + } + } else { + if Eq(key, 5) { + move|y: u64| test::multiply(y, 7) with drop, store + } else { + if Eq(key, 6) { + { + let f: |u64|u64 with copy+store = move|y: u64| test::multiply(6, y) with drop, store; + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 7) { + { + let f: |u64|u64 with store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + move|y: u64| test::multiply3(y, 3, 4) with drop, store + } + } + } + } + } + } + } + } + } + private fun choose_function3(key: u64): |u64|u64 with store { + if Eq(key, 0) { + { + let f: |u64|u64 with copy+store = move|x: u64| test::double(x) with drop, store; + f + } + } else { + if Eq(key, 1) { + { + let g: |u64|u64 with copy+store = move|x: u64| test::triple(x) with drop, store; + g + } + } else { + { + let h: |u64|u64 with store = test::multiply_by_x(4); + h + } + } + } + } + public fun double(x: u64): u64 { + Mul(x, 2) + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + public fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + private fun multiply_by_x(x: u64): |u64|u64 with store { + move|y: u64| test::multiply(x, y) with drop, store + } + public fun test_function_choosers() { + test::test_functions(test::choose_function); + test::test_functions(test::choose_function2); + test::test_functions(test::choose_function3); + Tuple() + } + public fun test_functions(choose_function_arg: |u64||u64|u64 with store) { + { + let sum: vector = Vector(); + { + let x: u64 = 3; + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(0))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(1))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(2))(x)); + { + let g: |u64|u64 with store = test::choose_function(1); + { + let h: |u64|u64 with store = test::choose_function(2); + { + let f: |u64|u64 with store = test::choose_function(0); + vector::push_back(Borrow(Mutable)(sum), (f)(5)); + vector::push_back(Borrow(Mutable)(sum), (g)(7)); + vector::push_back(Borrow(Mutable)(sum), (h)(6)); + { + let funcs: vector<|u64|u64 with store> = Vector<|u64|u64 with store>(test::choose_function(0), test::choose_function(1), test::choose_function(2)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 0)))(9)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 1)))(11)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 2)))(13)); + if Eq>(sum, Vector(6, 9, 12, 10, 21, 24, 18, 33, 52)) { + Tuple() + } else { + Abort(14566554180833181696) + } + } + } + } + } + } + } + } + public fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor check cyclic type instantiation: +module 0x42::test { + use std::vector; + private fun choose_function(key: u64): |u64|u64 with store { + if Eq(key, 0) { + test::double + } else { + if Eq(key, 1) { + test::triple + } else { + test::multiply_by_x(4) + } + } + } + private fun choose_function2(key: u64): |u64|u64 with store { + if Eq(key, 0) { + move|x: u64| test::double(x) with drop, store + } else { + if Eq(key, 1) { + move|x: u64| test::triple(x) with drop, store + } else { + if Eq(key, 2) { + { + let f: |u64|u64 with store = test::multiply_by_x(4); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 3) { + { + let f: |u64|u64 with store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 4) { + { + let f: |u64|u64 with copy+store = move|y: u64| test::multiply(6, y) with drop, store; + f + } + } else { + if Eq(key, 5) { + move|y: u64| test::multiply(y, 7) with drop, store + } else { + if Eq(key, 6) { + { + let f: |u64|u64 with copy+store = move|y: u64| test::multiply(6, y) with drop, store; + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 7) { + { + let f: |u64|u64 with store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + move|y: u64| test::multiply3(y, 3, 4) with drop, store + } + } + } + } + } + } + } + } + } + private fun choose_function3(key: u64): |u64|u64 with store { + if Eq(key, 0) { + { + let f: |u64|u64 with copy+store = move|x: u64| test::double(x) with drop, store; + f + } + } else { + if Eq(key, 1) { + { + let g: |u64|u64 with copy+store = move|x: u64| test::triple(x) with drop, store; + g + } + } else { + { + let h: |u64|u64 with store = test::multiply_by_x(4); + h + } + } + } + } + public fun double(x: u64): u64 { + Mul(x, 2) + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + public fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + private fun multiply_by_x(x: u64): |u64|u64 with store { + move|y: u64| test::multiply(x, y) with drop, store + } + public fun test_function_choosers() { + test::test_functions(test::choose_function); + test::test_functions(test::choose_function2); + test::test_functions(test::choose_function3); + Tuple() + } + public fun test_functions(choose_function_arg: |u64||u64|u64 with store) { + { + let sum: vector = Vector(); + { + let x: u64 = 3; + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(0))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(1))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(2))(x)); + { + let g: |u64|u64 with store = test::choose_function(1); + { + let h: |u64|u64 with store = test::choose_function(2); + { + let f: |u64|u64 with store = test::choose_function(0); + vector::push_back(Borrow(Mutable)(sum), (f)(5)); + vector::push_back(Borrow(Mutable)(sum), (g)(7)); + vector::push_back(Borrow(Mutable)(sum), (h)(6)); + { + let funcs: vector<|u64|u64 with store> = Vector<|u64|u64 with store>(test::choose_function(0), test::choose_function(1), test::choose_function(2)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 0)))(9)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 1)))(11)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 2)))(13)); + if Eq>(sum, Vector(6, 9, 12, 10, 21, 24, 18, 33, 52)) { + Tuple() + } else { + Abort(14566554180833181696) + } + } + } + } + } + } + } + } + public fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor unused struct params check: +module 0x42::test { + use std::vector; + private fun choose_function(key: u64): |u64|u64 with store { + if Eq(key, 0) { + test::double + } else { + if Eq(key, 1) { + test::triple + } else { + test::multiply_by_x(4) + } + } + } + private fun choose_function2(key: u64): |u64|u64 with store { + if Eq(key, 0) { + move|x: u64| test::double(x) with drop, store + } else { + if Eq(key, 1) { + move|x: u64| test::triple(x) with drop, store + } else { + if Eq(key, 2) { + { + let f: |u64|u64 with store = test::multiply_by_x(4); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 3) { + { + let f: |u64|u64 with store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 4) { + { + let f: |u64|u64 with copy+store = move|y: u64| test::multiply(6, y) with drop, store; + f + } + } else { + if Eq(key, 5) { + move|y: u64| test::multiply(y, 7) with drop, store + } else { + if Eq(key, 6) { + { + let f: |u64|u64 with copy+store = move|y: u64| test::multiply(6, y) with drop, store; + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 7) { + { + let f: |u64|u64 with store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + move|y: u64| test::multiply3(y, 3, 4) with drop, store + } + } + } + } + } + } + } + } + } + private fun choose_function3(key: u64): |u64|u64 with store { + if Eq(key, 0) { + { + let f: |u64|u64 with copy+store = move|x: u64| test::double(x) with drop, store; + f + } + } else { + if Eq(key, 1) { + { + let g: |u64|u64 with copy+store = move|x: u64| test::triple(x) with drop, store; + g + } + } else { + { + let h: |u64|u64 with store = test::multiply_by_x(4); + h + } + } + } + } + public fun double(x: u64): u64 { + Mul(x, 2) + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + public fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + private fun multiply_by_x(x: u64): |u64|u64 with store { + move|y: u64| test::multiply(x, y) with drop, store + } + public fun test_function_choosers() { + test::test_functions(test::choose_function); + test::test_functions(test::choose_function2); + test::test_functions(test::choose_function3); + Tuple() + } + public fun test_functions(choose_function_arg: |u64||u64|u64 with store) { + { + let sum: vector = Vector(); + { + let x: u64 = 3; + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(0))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(1))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(2))(x)); + { + let g: |u64|u64 with store = test::choose_function(1); + { + let h: |u64|u64 with store = test::choose_function(2); + { + let f: |u64|u64 with store = test::choose_function(0); + vector::push_back(Borrow(Mutable)(sum), (f)(5)); + vector::push_back(Borrow(Mutable)(sum), (g)(7)); + vector::push_back(Borrow(Mutable)(sum), (h)(6)); + { + let funcs: vector<|u64|u64 with store> = Vector<|u64|u64 with store>(test::choose_function(0), test::choose_function(1), test::choose_function(2)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 0)))(9)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 1)))(11)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 2)))(13)); + if Eq>(sum, Vector(6, 9, 12, 10, 21, 24, 18, 33, 52)) { + Tuple() + } else { + Abort(14566554180833181696) + } + } + } + } + } + } + } + } + public fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor access and use check before inlining: +module 0x42::test { + use std::vector; + private fun choose_function(key: u64): |u64|u64 with store { + if Eq(key, 0) { + test::double + } else { + if Eq(key, 1) { + test::triple + } else { + test::multiply_by_x(4) + } + } + } + private fun choose_function2(key: u64): |u64|u64 with store { + if Eq(key, 0) { + move|x: u64| test::double(x) with drop, store + } else { + if Eq(key, 1) { + move|x: u64| test::triple(x) with drop, store + } else { + if Eq(key, 2) { + { + let f: |u64|u64 with store = test::multiply_by_x(4); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 3) { + { + let f: |u64|u64 with store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 4) { + { + let f: |u64|u64 with copy+store = move|y: u64| test::multiply(6, y) with drop, store; + f + } + } else { + if Eq(key, 5) { + move|y: u64| test::multiply(y, 7) with drop, store + } else { + if Eq(key, 6) { + { + let f: |u64|u64 with copy+store = move|y: u64| test::multiply(6, y) with drop, store; + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 7) { + { + let f: |u64|u64 with store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + move|y: u64| test::multiply3(y, 3, 4) with drop, store + } + } + } + } + } + } + } + } + } + private fun choose_function3(key: u64): |u64|u64 with store { + if Eq(key, 0) { + { + let f: |u64|u64 with copy+store = move|x: u64| test::double(x) with drop, store; + f + } + } else { + if Eq(key, 1) { + { + let g: |u64|u64 with copy+store = move|x: u64| test::triple(x) with drop, store; + g + } + } else { + { + let h: |u64|u64 with store = test::multiply_by_x(4); + h + } + } + } + } + public fun double(x: u64): u64 { + Mul(x, 2) + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + public fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + private fun multiply_by_x(x: u64): |u64|u64 with store { + move|y: u64| test::multiply(x, y) with drop, store + } + public fun test_function_choosers() { + test::test_functions(test::choose_function); + test::test_functions(test::choose_function2); + test::test_functions(test::choose_function3); + Tuple() + } + public fun test_functions(choose_function_arg: |u64||u64|u64 with store) { + { + let sum: vector = Vector(); + { + let x: u64 = 3; + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(0))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(1))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(2))(x)); + { + let g: |u64|u64 with store = test::choose_function(1); + { + let h: |u64|u64 with store = test::choose_function(2); + { + let f: |u64|u64 with store = test::choose_function(0); + vector::push_back(Borrow(Mutable)(sum), (f)(5)); + vector::push_back(Borrow(Mutable)(sum), (g)(7)); + vector::push_back(Borrow(Mutable)(sum), (h)(6)); + { + let funcs: vector<|u64|u64 with store> = Vector<|u64|u64 with store>(test::choose_function(0), test::choose_function(1), test::choose_function(2)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 0)))(9)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 1)))(11)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 2)))(13)); + if Eq>(sum, Vector(6, 9, 12, 10, 21, 24, 18, 33, 52)) { + Tuple() + } else { + Abort(14566554180833181696) + } + } + } + } + } + } + } + } + public fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor inlining: +module 0x42::test { + use std::vector; + private fun choose_function(key: u64): |u64|u64 with store { + if Eq(key, 0) { + test::double + } else { + if Eq(key, 1) { + test::triple + } else { + test::multiply_by_x(4) + } + } + } + private fun choose_function2(key: u64): |u64|u64 with store { + if Eq(key, 0) { + move|x: u64| test::double(x) with drop, store + } else { + if Eq(key, 1) { + move|x: u64| test::triple(x) with drop, store + } else { + if Eq(key, 2) { + { + let f: |u64|u64 with store = test::multiply_by_x(4); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 3) { + { + let f: |u64|u64 with store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 4) { + { + let f: |u64|u64 with copy+store = move|y: u64| test::multiply(6, y) with drop, store; + f + } + } else { + if Eq(key, 5) { + move|y: u64| test::multiply(y, 7) with drop, store + } else { + if Eq(key, 6) { + { + let f: |u64|u64 with copy+store = move|y: u64| test::multiply(6, y) with drop, store; + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 7) { + { + let f: |u64|u64 with store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + move|y: u64| test::multiply3(y, 3, 4) with drop, store + } + } + } + } + } + } + } + } + } + private fun choose_function3(key: u64): |u64|u64 with store { + if Eq(key, 0) { + { + let f: |u64|u64 with copy+store = move|x: u64| test::double(x) with drop, store; + f + } + } else { + if Eq(key, 1) { + { + let g: |u64|u64 with copy+store = move|x: u64| test::triple(x) with drop, store; + g + } + } else { + { + let h: |u64|u64 with store = test::multiply_by_x(4); + h + } + } + } + } + public fun double(x: u64): u64 { + Mul(x, 2) + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + public fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + private fun multiply_by_x(x: u64): |u64|u64 with store { + move|y: u64| test::multiply(x, y) with drop, store + } + public fun test_function_choosers() { + test::test_functions(test::choose_function); + test::test_functions(test::choose_function2); + test::test_functions(test::choose_function3); + Tuple() + } + public fun test_functions(choose_function_arg: |u64||u64|u64 with store) { + { + let sum: vector = Vector(); + { + let x: u64 = 3; + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(0))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(1))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(2))(x)); + { + let g: |u64|u64 with store = test::choose_function(1); + { + let h: |u64|u64 with store = test::choose_function(2); + { + let f: |u64|u64 with store = test::choose_function(0); + vector::push_back(Borrow(Mutable)(sum), (f)(5)); + vector::push_back(Borrow(Mutable)(sum), (g)(7)); + vector::push_back(Borrow(Mutable)(sum), (h)(6)); + { + let funcs: vector<|u64|u64 with store> = Vector<|u64|u64 with store>(test::choose_function(0), test::choose_function(1), test::choose_function(2)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 0)))(9)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 1)))(11)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 2)))(13)); + if Eq>(sum, Vector(6, 9, 12, 10, 21, 24, 18, 33, 52)) { + Tuple() + } else { + Abort(14566554180833181696) + } + } + } + } + } + } + } + } + public fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor access and use check after inlining: +module 0x42::test { + use std::vector; + private fun choose_function(key: u64): |u64|u64 with store { + if Eq(key, 0) { + test::double + } else { + if Eq(key, 1) { + test::triple + } else { + test::multiply_by_x(4) + } + } + } + private fun choose_function2(key: u64): |u64|u64 with store { + if Eq(key, 0) { + move|x: u64| test::double(x) with drop, store + } else { + if Eq(key, 1) { + move|x: u64| test::triple(x) with drop, store + } else { + if Eq(key, 2) { + { + let f: |u64|u64 with store = test::multiply_by_x(4); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 3) { + { + let f: |u64|u64 with store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 4) { + { + let f: |u64|u64 with copy+store = move|y: u64| test::multiply(6, y) with drop, store; + f + } + } else { + if Eq(key, 5) { + move|y: u64| test::multiply(y, 7) with drop, store + } else { + if Eq(key, 6) { + { + let f: |u64|u64 with copy+store = move|y: u64| test::multiply(6, y) with drop, store; + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 7) { + { + let f: |u64|u64 with store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + move|y: u64| test::multiply3(y, 3, 4) with drop, store + } + } + } + } + } + } + } + } + } + private fun choose_function3(key: u64): |u64|u64 with store { + if Eq(key, 0) { + { + let f: |u64|u64 with copy+store = move|x: u64| test::double(x) with drop, store; + f + } + } else { + if Eq(key, 1) { + { + let g: |u64|u64 with copy+store = move|x: u64| test::triple(x) with drop, store; + g + } + } else { + { + let h: |u64|u64 with store = test::multiply_by_x(4); + h + } + } + } + } + public fun double(x: u64): u64 { + Mul(x, 2) + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + public fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + private fun multiply_by_x(x: u64): |u64|u64 with store { + move|y: u64| test::multiply(x, y) with drop, store + } + public fun test_function_choosers() { + test::test_functions(test::choose_function); + test::test_functions(test::choose_function2); + test::test_functions(test::choose_function3); + Tuple() + } + public fun test_functions(choose_function_arg: |u64||u64|u64 with store) { + { + let sum: vector = Vector(); + { + let x: u64 = 3; + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(0))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(1))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(2))(x)); + { + let g: |u64|u64 with store = test::choose_function(1); + { + let h: |u64|u64 with store = test::choose_function(2); + { + let f: |u64|u64 with store = test::choose_function(0); + vector::push_back(Borrow(Mutable)(sum), (f)(5)); + vector::push_back(Borrow(Mutable)(sum), (g)(7)); + vector::push_back(Borrow(Mutable)(sum), (h)(6)); + { + let funcs: vector<|u64|u64 with store> = Vector<|u64|u64 with store>(test::choose_function(0), test::choose_function(1), test::choose_function(2)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 0)))(9)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 1)))(11)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 2)))(13)); + if Eq>(sum, Vector(6, 9, 12, 10, 21, 24, 18, 33, 52)) { + Tuple() + } else { + Abort(14566554180833181696) + } + } + } + } + } + } + } + } + public fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor acquires check: +module 0x42::test { + use std::vector; + private fun choose_function(key: u64): |u64|u64 with store { + if Eq(key, 0) { + test::double + } else { + if Eq(key, 1) { + test::triple + } else { + test::multiply_by_x(4) + } + } + } + private fun choose_function2(key: u64): |u64|u64 with store { + if Eq(key, 0) { + move|x: u64| test::double(x) with drop, store + } else { + if Eq(key, 1) { + move|x: u64| test::triple(x) with drop, store + } else { + if Eq(key, 2) { + { + let f: |u64|u64 with store = test::multiply_by_x(4); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 3) { + { + let f: |u64|u64 with store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 4) { + { + let f: |u64|u64 with copy+store = move|y: u64| test::multiply(6, y) with drop, store; + f + } + } else { + if Eq(key, 5) { + move|y: u64| test::multiply(y, 7) with drop, store + } else { + if Eq(key, 6) { + { + let f: |u64|u64 with copy+store = move|y: u64| test::multiply(6, y) with drop, store; + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 7) { + { + let f: |u64|u64 with store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + move|y: u64| test::multiply3(y, 3, 4) with drop, store + } + } + } + } + } + } + } + } + } + private fun choose_function3(key: u64): |u64|u64 with store { + if Eq(key, 0) { + { + let f: |u64|u64 with copy+store = move|x: u64| test::double(x) with drop, store; + f + } + } else { + if Eq(key, 1) { + { + let g: |u64|u64 with copy+store = move|x: u64| test::triple(x) with drop, store; + g + } + } else { + { + let h: |u64|u64 with store = test::multiply_by_x(4); + h + } + } + } + } + public fun double(x: u64): u64 { + Mul(x, 2) + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + public fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + private fun multiply_by_x(x: u64): |u64|u64 with store { + move|y: u64| test::multiply(x, y) with drop, store + } + public fun test_function_choosers() { + test::test_functions(test::choose_function); + test::test_functions(test::choose_function2); + test::test_functions(test::choose_function3); + Tuple() + } + public fun test_functions(choose_function_arg: |u64||u64|u64 with store) { + { + let sum: vector = Vector(); + { + let x: u64 = 3; + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(0))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(1))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(2))(x)); + { + let g: |u64|u64 with store = test::choose_function(1); + { + let h: |u64|u64 with store = test::choose_function(2); + { + let f: |u64|u64 with store = test::choose_function(0); + vector::push_back(Borrow(Mutable)(sum), (f)(5)); + vector::push_back(Borrow(Mutable)(sum), (g)(7)); + vector::push_back(Borrow(Mutable)(sum), (h)(6)); + { + let funcs: vector<|u64|u64 with store> = Vector<|u64|u64 with store>(test::choose_function(0), test::choose_function(1), test::choose_function(2)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 0)))(9)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 1)))(11)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 2)))(13)); + if Eq>(sum, Vector(6, 9, 12, 10, 21, 24, 18, 33, 52)) { + Tuple() + } else { + Abort(14566554180833181696) + } + } + } + } + } + } + } + } + public fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor simplifier: +module 0x42::test { + use std::vector; + private fun choose_function(key: u64): |u64|u64 with store { + if Eq(key, 0) { + test::double + } else { + if Eq(key, 1) { + test::triple + } else { + test::multiply_by_x(4) + } + } + } + private fun choose_function2(key: u64): |u64|u64 with store { + if Eq(key, 0) { + move|x: u64| test::double(x) with drop, store + } else { + if Eq(key, 1) { + move|x: u64| test::triple(x) with drop, store + } else { + if Eq(key, 2) { + { + let f: |u64|u64 with store = test::multiply_by_x(4); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 3) { + { + let f: |u64|u64 with store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 4) { + { + let f: |u64|u64 with copy+store = move|y: u64| test::multiply(6, y) with drop, store; + f + } + } else { + if Eq(key, 5) { + move|y: u64| test::multiply(y, 7) with drop, store + } else { + if Eq(key, 6) { + { + let f: |u64|u64 with copy+store = move|y: u64| test::multiply(6, y) with drop, store; + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 7) { + { + let f: |u64|u64 with store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + move|y: u64| test::multiply3(y, 3, 4) with drop, store + } + } + } + } + } + } + } + } + } + private fun choose_function3(key: u64): |u64|u64 with store { + if Eq(key, 0) { + { + let f: |u64|u64 with copy+store = move|x: u64| test::double(x) with drop, store; + f + } + } else { + if Eq(key, 1) { + { + let g: |u64|u64 with copy+store = move|x: u64| test::triple(x) with drop, store; + g + } + } else { + { + let h: |u64|u64 with store = test::multiply_by_x(4); + h + } + } + } + } + public fun double(x: u64): u64 { + Mul(x, 2) + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + public fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + private fun multiply_by_x(x: u64): |u64|u64 with store { + move|y: u64| test::multiply(x, y) with drop, store + } + public fun test_function_choosers() { + test::test_functions(test::choose_function); + test::test_functions(test::choose_function2); + test::test_functions(test::choose_function3); + Tuple() + } + public fun test_functions(choose_function_arg: |u64||u64|u64 with store) { + { + let sum: vector = Vector(); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(0))(3)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(1))(3)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(2))(3)); + { + let g: |u64|u64 with store = test::choose_function(1); + { + let h: |u64|u64 with store = test::choose_function(2); + { + let f: |u64|u64 with store = test::choose_function(0); + vector::push_back(Borrow(Mutable)(sum), (f)(5)); + vector::push_back(Borrow(Mutable)(sum), (g)(7)); + vector::push_back(Borrow(Mutable)(sum), (h)(6)); + { + let funcs: vector<|u64|u64 with store> = Vector<|u64|u64 with store>(test::choose_function(0), test::choose_function(1), test::choose_function(2)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 0)))(9)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 1)))(11)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 2)))(13)); + if Eq>(sum, [Number(6), Number(9), Number(12), Number(10), Number(21), Number(24), Number(18), Number(33), Number(52)]) { + Tuple() + } else { + Abort(14566554180833181696) + } + } + } + } + } + } + } + public fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + + +Diagnostics: +error: The body of a lambdas expression with `store` ability currently must be a simple call to an existing `public` function, with lambda params the same as the *final* arguments to the function call. + ┌─ tests/lambda/storable/return_func_ok.move:49:13 + │ +49 │ move |y| multiply(y, 7) with store + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: The body of a lambdas expression with `store` ability currently must be a simple call to an existing `public` function, with lambda params the same as the *final* arguments to the function call. + ┌─ tests/lambda/storable/return_func_ok.move:57:13 + │ +57 │ move |y| multiply3(y, 3, 4) with store + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/return_func_ok.move b/third_party/move/move-compiler-v2/tests/lambda/storable/return_func_ok.move new file mode 100644 index 0000000000000..7917652a778a6 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/return_func_ok.move @@ -0,0 +1,106 @@ +module 0x42::test { + use std::vector; + + public fun double(x: u64): u64 { + x * 2 + } + + public fun triple(x: u64) : u64 { + x * 3 + } + + public fun multiply(x: u64, y: u64): u64 { + x * y + } + + public fun multiply3(x: u64, y: u64, z: u64): u64 { + x * y * z + } + + fun multiply_by_x(x: u64): |u64|u64 with store { + move |y| multiply(x, y) with store + } + + fun choose_function(key: u64) : |u64|u64 with store { + if (key == 0) { + double + } else if (key == 1) { + triple + } else { + multiply_by_x(4) + } + } + + fun choose_function2(key: u64): |u64|u64 with store { + if (key == 0) { + move |x| double(x) with store + } else if (key == 1) { + move |x| triple(x) with store + } else if (key == 2) { + let f = multiply_by_x(4); + move |x| f(x) with store + } else if (key == 3) { + let f = multiply_by_x(5); + move |x| f(x) with store + } else if (key == 4) { + let f = move |y| multiply(6, y) with store; + f + } else if (key == 5) { + move |y| multiply(y, 7) with store + } else if (key == 6) { + let f = move |y| multiply(6, y) with store; + move |x| f(x) with store + } else if (key == 7) { + let f = multiply_by_x(5); + move |x| f(x) with store + } else { + move |y| multiply3(y, 3, 4) with store + } + } + + fun choose_function3(key: u64) : |u64|u64 with store { + if (key == 0) { + let f = move |x| double(x) with store; + f + } else if (key == 1) { + let g = move |x| triple(x) with store; + g + } else { + let h = multiply_by_x(4); + h + } + } + + public fun test_functions(choose_function_arg: |u64|(|u64|u64 with store)) { + let sum = vector[]; + let x = 3; + // Note that currently we can only resolve a local var as a + // function value in a call if (1) there is no existing function with that name, + // or (2) the function name is in parentheses, to distinguish from an + // old-fashioned function call. + vector::push_back(&mut sum, (choose_function_arg(0))(x)); + vector::push_back(&mut sum, choose_function_arg(1)(x)); + vector::push_back(&mut sum, (choose_function_arg(2))(x)); + + let g = choose_function(1); + let h = choose_function(2); + let f = choose_function(0); + + vector::push_back(&mut sum, f(5)); + vector::push_back(&mut sum, g(7)); + vector::push_back(&mut sum, h(6)); + + let funcs = vector[choose_function(0), choose_function(1), choose_function(2)]; + vector::push_back(&mut sum, (funcs[0])(9)); + vector::push_back(&mut sum, (funcs[1])(11)); + vector::push_back(&mut sum, (funcs[2])(13)); + + assert!(sum == vector[6, 9, 12, 10, 21, 24, 18, 33, 52]) + } + + public fun test_function_choosers() { + test_functions(choose_function); + test_functions(choose_function2); + test_functions(choose_function3); + } +} diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/function_name_shadowing.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/function_name_shadowing.exp new file mode 100644 index 0000000000000..e2453ef24dad5 --- /dev/null +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/function_name_shadowing.exp @@ -0,0 +1,27 @@ +comparison between v1 and v2 failed: += processed 3 tasks += ++ task 1 'publish'. lines 12-28: ++ warning: Unused parameter `f`. Consider removing or prefixing with an underscore: `_f` ++ ┌─ TEMPFILE1:18:28 ++ │ ++ 18 │ public inline fun quux(f:|u64, u64|u64, g:|u64|u64, i:|u8|u8, a: u64, b: u64): u64 { ++ │ ^ ++ ++ warning: Unused parameter `g`. Consider removing or prefixing with an underscore: `_g` ++ ┌─ TEMPFILE1:18:45 ++ │ ++ 18 │ public inline fun quux(f:|u64, u64|u64, g:|u64|u64, i:|u8|u8, a: u64, b: u64): u64 { ++ │ ^ ++ ++ warning: Unused parameter `i`. Consider removing or prefixing with an underscore: `_i` ++ ┌─ TEMPFILE1:18:57 ++ │ ++ 18 │ public inline fun quux(f:|u64, u64|u64, g:|u64|u64, i:|u8|u8, a: u64, b: u64): u64 { ++ │ ^ ++ ++ ++ += task 2 'run'. lines 30-30: += return values: 5280 += diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/function_name_shadowing.move b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/function_name_shadowing.move new file mode 100644 index 0000000000000..e527c426c7eef --- /dev/null +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/function_name_shadowing.move @@ -0,0 +1,30 @@ +//# publish +module 0x42::OtherModule { + public fun g(a: u64, b: u64): u64 { + a + b + } + + public fun h(a: u64, b: u64): u64 { + 2 * a + b + } +} + +//# publish +module 0x42::Test { + use 0x42::OtherModule::g; + + public fun f(a: u64, b: u64): u64 { + a * b + } + + public inline fun quux(f:|u64, u64|u64, g:|u64|u64, i:|u8|u8, a: u64, b: u64): u64 { + use 0x42::OtherModule::h; + f(a, b) * g(a, b) * h(a, b) + } + + public fun test_shadowing(): u64 { + quux(|a, b| a - b, |a| a + 2, |b| 255u8-b, 10, 2) + } +} + +//# run 0x42::Test::test_shadowing diff --git a/third_party/move/move-compiler/tests/move_check/inlining/function_name_shadowing.move b/third_party/move/move-compiler/tests/move_check/inlining/function_name_shadowing.move new file mode 100644 index 0000000000000..e527c426c7eef --- /dev/null +++ b/third_party/move/move-compiler/tests/move_check/inlining/function_name_shadowing.move @@ -0,0 +1,30 @@ +//# publish +module 0x42::OtherModule { + public fun g(a: u64, b: u64): u64 { + a + b + } + + public fun h(a: u64, b: u64): u64 { + 2 * a + b + } +} + +//# publish +module 0x42::Test { + use 0x42::OtherModule::g; + + public fun f(a: u64, b: u64): u64 { + a * b + } + + public inline fun quux(f:|u64, u64|u64, g:|u64|u64, i:|u8|u8, a: u64, b: u64): u64 { + use 0x42::OtherModule::h; + f(a, b) * g(a, b) * h(a, b) + } + + public fun test_shadowing(): u64 { + quux(|a, b| a - b, |a| a + 2, |b| 255u8-b, 10, 2) + } +} + +//# run 0x42::Test::test_shadowing diff --git a/third_party/move/move-compiler/transactional-tests/tests/inlining/function_name_shadowing.exp b/third_party/move/move-compiler/transactional-tests/tests/inlining/function_name_shadowing.exp new file mode 100644 index 0000000000000..2463a580a0079 --- /dev/null +++ b/third_party/move/move-compiler/transactional-tests/tests/inlining/function_name_shadowing.exp @@ -0,0 +1,4 @@ +processed 3 tasks + +task 2 'run'. lines 30-30: +return values: 5280 diff --git a/third_party/move/move-compiler/transactional-tests/tests/inlining/function_name_shadowing.move b/third_party/move/move-compiler/transactional-tests/tests/inlining/function_name_shadowing.move new file mode 100644 index 0000000000000..e527c426c7eef --- /dev/null +++ b/third_party/move/move-compiler/transactional-tests/tests/inlining/function_name_shadowing.move @@ -0,0 +1,30 @@ +//# publish +module 0x42::OtherModule { + public fun g(a: u64, b: u64): u64 { + a + b + } + + public fun h(a: u64, b: u64): u64 { + 2 * a + b + } +} + +//# publish +module 0x42::Test { + use 0x42::OtherModule::g; + + public fun f(a: u64, b: u64): u64 { + a * b + } + + public inline fun quux(f:|u64, u64|u64, g:|u64|u64, i:|u8|u8, a: u64, b: u64): u64 { + use 0x42::OtherModule::h; + f(a, b) * g(a, b) * h(a, b) + } + + public fun test_shadowing(): u64 { + quux(|a, b| a - b, |a| a + 2, |b| 255u8-b, 10, 2) + } +} + +//# run 0x42::Test::test_shadowing diff --git a/third_party/move/move-model/src/ty.rs b/third_party/move/move-model/src/ty.rs index 485bd3c273a96..1d2c5c74d106a 100644 --- a/third_party/move/move-model/src/ty.rs +++ b/third_party/move/move-model/src/ty.rs @@ -164,9 +164,6 @@ pub enum Constraint { /// a pseudo constraint which never fails, but used to generate a default for /// inference. WithDefault(Type), - /// The type must not be function because it is used as the type of some field or - /// as a type argument. - NoFunction, } /// Scope of ability checking. @@ -409,10 +406,7 @@ impl Constraint { /// for internal constraints which would be mostly confusing to users. pub fn hidden(&self) -> bool { use Constraint::*; - matches!( - self, - NoPhantom | NoReference | NoTuple | NoFunction | WithDefault(..) - ) + matches!(self, NoPhantom | NoReference | NoTuple | WithDefault(..)) } /// Returns true if this context is accumulating. When adding a new constraint @@ -430,7 +424,6 @@ impl Constraint { | Constraint::NoPhantom | Constraint::NoTuple | Constraint::NoReference - | Constraint::NoFunction ) } @@ -449,10 +442,7 @@ impl Constraint { /// the same type. pub fn report_only_once(&self) -> bool { use Constraint::*; - matches!( - self, - HasAbilities(..) | NoReference | NoFunction | NoPhantom | NoTuple - ) + matches!(self, HasAbilities(..) | NoReference | NoPhantom | NoTuple) } /// Joins the two constraints. If they are incompatible, produces a type unification error. @@ -539,7 +529,6 @@ impl Constraint { )) } }, - (Constraint::NoFunction, Constraint::NoFunction) => Ok(true), (Constraint::NoReference, Constraint::NoReference) => Ok(true), (Constraint::NoTuple, Constraint::NoTuple) => Ok(true), (Constraint::NoPhantom, Constraint::NoPhantom) => Ok(true), @@ -590,14 +579,10 @@ impl Constraint { } /// Returns the constraints which need to be satisfied to instantiate the given type - /// parameter. This creates NoReference, NoFunction, NoTuple, NoPhantom unless the type + /// parameter. This creates NoReference, NoTuple, NoPhantom unless the type /// parameter is phantom, and HasAbilities if any abilities need to be met. pub fn for_type_parameter(param: &TypeParameter) -> Vec { - let mut result = vec![ - Constraint::NoReference, - Constraint::NoTuple, - Constraint::NoFunction, // TODO(LAMBDA) - remove when implement LAMBDA_AS_TYPE_PARAMETERS - ]; + let mut result = vec![Constraint::NoReference, Constraint::NoTuple]; let TypeParameter( _, TypeParameterKind { @@ -624,7 +609,6 @@ impl Constraint { Constraint::NoPhantom, Constraint::NoReference, Constraint::NoTuple, - Constraint::NoFunction, // TODO(LAMBDA) - remove when we implement LAMBDA_IN_VECTORS ] } @@ -635,7 +619,6 @@ impl Constraint { Constraint::NoPhantom, Constraint::NoTuple, Constraint::NoReference, - Constraint::NoFunction, ]; let abilities = if struct_abilities.has_ability(Ability::Key) { struct_abilities.remove(Ability::Key).add(Ability::Store) @@ -705,7 +688,6 @@ impl Constraint { ) }, Constraint::NoReference => "no-ref".to_string(), - Constraint::NoFunction => "no-func".to_string(), Constraint::NoTuple => "no-tuple".to_string(), Constraint::NoPhantom => "no-phantom".to_string(), Constraint::HasAbilities(required_abilities, _) => { @@ -1925,13 +1907,6 @@ impl Substitution { Ok(()) } }, - (Constraint::NoFunction, ty) => { - if ty.is_function() { - constraint_unsatisfied_error() - } else { - Ok(()) - } - }, (Constraint::NoTuple, ty) => { if ty.is_tuple() { constraint_unsatisfied_error() @@ -3175,13 +3150,6 @@ impl TypeUnificationError { item_name() ) }, - Constraint::NoFunction => { - format!( - "function type `{}` is not allowed {}", - ty.display(display_context), - item_name() - ) - }, Constraint::NoPhantom => { format!( "phantom type `{}` can only be used as an argument for another phantom type parameter", diff --git a/third_party/move/move-prover/boogie-backend/src/boogie_helpers.rs b/third_party/move/move-prover/boogie-backend/src/boogie_helpers.rs index 0b58373ba8267..8a921e15b66be 100644 --- a/third_party/move/move-prover/boogie-backend/src/boogie_helpers.rs +++ b/third_party/move/move-prover/boogie-backend/src/boogie_helpers.rs @@ -592,7 +592,7 @@ pub fn boogie_value(env: &GlobalEnv, _options: &BoogieOptions, val: &Value) -> S .collect_vec(), ), Value::Tuple(vec) => format!("<>", vec), - Value::Function(mid, fid) => format!("", mid, fid), // TODO(LAMBDA) + Value::Function(mid, fid) => format!("", mid, fid), // TODO(LAMBDA) } } diff --git a/third_party/move/move-prover/boogie-backend/src/spec_translator.rs b/third_party/move/move-prover/boogie-backend/src/spec_translator.rs index b674d30b855b9..d3157c01a7161 100644 --- a/third_party/move/move-prover/boogie-backend/src/spec_translator.rs +++ b/third_party/move/move-prover/boogie-backend/src/spec_translator.rs @@ -270,8 +270,12 @@ impl<'env> SpecTranslator<'env> { // so we don't need to translate it. return; } - if let Type::Tuple(..) | Type::Fun(..) = fun.result_type { - self.error(&fun.loc, "function or tuple result type not yet supported"); + if let Type::Tuple(..) = fun.result_type { + self.error(&fun.loc, "tuple result type not yet supported"); + return; + } + if let Type::Fun(..) = fun.result_type { + self.error(&fun.loc, "function result type not yet supported"); // TODO(LAMBDA) return; } let qid = module_env.get_id().qualified(id); @@ -684,6 +688,7 @@ impl<'env> SpecTranslator<'env> { }, ExpData::Invoke(node_id, ..) => { self.error(&self.env.get_node_loc(*node_id), "Invoke not yet supported"); + // TODO(LAMBDA) }, ExpData::Lambda(node_id, ..) => self.error( &self.env.get_node_loc(*node_id), @@ -1020,8 +1025,7 @@ impl<'env> SpecTranslator<'env> { self.env.error( &self.env.get_node_loc(node_id), &format!( - "bug: operation {} is not supported \ - in the current context", + "bug: operation {} is not supported in the current context", oper.display(self.env, node_id) ), ); diff --git a/third_party/move/move-prover/tests/sources/functional/restrictions.exp b/third_party/move/move-prover/tests/sources/functional/restrictions.exp index 947924207b0ce..bcc3d281dd599 100644 --- a/third_party/move/move-prover/tests/sources/functional/restrictions.exp +++ b/third_party/move/move-prover/tests/sources/functional/restrictions.exp @@ -1,11 +1,11 @@ Move prover returns: exiting with condition generation errors -error: [boogie translator] function or tuple result type not yet supported +error: [boogie translator] tuple result type not yet supported ┌─ tests/sources/functional/restrictions.move:9:9 │ 9 │ fun f1(): (u64, u64) { (1u64, 2u64) } │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [boogie translator] function or tuple result type not yet supported +error: [boogie translator] function result type not yet supported ┌─ tests/sources/functional/restrictions.move:12:9 │ 12 │ fun f2(): | |num { | | 1 } diff --git a/third_party/move/move-prover/tests/sources/functional/restrictions.v2_exp b/third_party/move/move-prover/tests/sources/functional/restrictions.v2_exp index 947924207b0ce..bcc3d281dd599 100644 --- a/third_party/move/move-prover/tests/sources/functional/restrictions.v2_exp +++ b/third_party/move/move-prover/tests/sources/functional/restrictions.v2_exp @@ -1,11 +1,11 @@ Move prover returns: exiting with condition generation errors -error: [boogie translator] function or tuple result type not yet supported +error: [boogie translator] tuple result type not yet supported ┌─ tests/sources/functional/restrictions.move:9:9 │ 9 │ fun f1(): (u64, u64) { (1u64, 2u64) } │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [boogie translator] function or tuple result type not yet supported +error: [boogie translator] function result type not yet supported ┌─ tests/sources/functional/restrictions.move:12:9 │ 12 │ fun f2(): | |num { | | 1 } From f60f1f0ca1dd935330152e481e680f1beb5b44ec Mon Sep 17 00:00:00 2001 From: rtso <8248583+rtso@users.noreply.github.com> Date: Tue, 3 Dec 2024 16:00:39 -0800 Subject: [PATCH 16/78] untransferable test txn --- .../1806220919_object_untransferable.json | 728 ++++++++++++++++++ .../imported_transactions.yaml | 1 + 2 files changed, 729 insertions(+) create mode 100644 ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/imported_mainnet_txns/1806220919_object_untransferable.json diff --git a/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/imported_mainnet_txns/1806220919_object_untransferable.json b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/imported_mainnet_txns/1806220919_object_untransferable.json new file mode 100644 index 0000000000000..5a0d700f18b08 --- /dev/null +++ b/ecosystem/indexer-grpc/indexer-test-transactions/json_transactions/imported_mainnet_txns/1806220919_object_untransferable.json @@ -0,0 +1,728 @@ +{ + "timestamp": { + "seconds": "1729151735", + "nanos": 597669000 + }, + "version": "1806220919", + "info": { + "hash": "kPcYHGxmU8ioZeo6xdX06sjvHwjeeODK1qWydTGye3w=", + "stateChangeHash": "ZsKjcfAVPiC3mq1csZx27G/csYTBCndAN+QzDgqvNtM=", + "eventRootHash": "57VS4Brx3Z2jHTm72IkMmK8S/ythocloolZ5s7sHsvA=", + "gasUsed": "63", + "success": true, + "vmStatus": "Executed successfully", + "accumulatorRootHash": "WaxBMc3C0vSXvOUuDDAG7WTG48jgDkrJRdFLbFkpCbc=", + "changes": [ + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x6ca8040183582748c2dea091990c724b3903c45e747cc8d8a75701c8acd86b9", + "stateKeyHash": "lB+jpxNlJYkV0hQHc0JXdGpak0gRqPjOAXgwrOAYrOs=", + "type": { + "address": "0x1", + "module": "fungible_asset", + "name": "FungibleStore" + }, + "typeStr": "0x1::fungible_asset::FungibleStore", + "data": "{\"balance\":\"28698862237658\",\"frozen\":true,\"metadata\":{\"inner\":\"0x7f5170624083679dbb5a8119e3dec380d95fddfd0940a4fb7118c7d9db61d425\"}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x6ca8040183582748c2dea091990c724b3903c45e747cc8d8a75701c8acd86b9", + "stateKeyHash": "lB+jpxNlJYkV0hQHc0JXdGpak0gRqPjOAXgwrOAYrOs=", + "type": { + "address": "0x1", + "module": "object", + "name": "ObjectCore" + }, + "typeStr": "0x1::object::ObjectCore", + "data": "{\"allow_ungated_transfer\":false,\"guid_creation_num\":\"1125899906842625\",\"owner\":\"0x121ed48962169f2d0670380fc8768bfa0d713dea51c176496274808c4b6a75ab\",\"transfer_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x6ca8040183582748c2dea091990c724b3903c45e747cc8d8a75701c8acd86b9\",\"creation_num\":\"1125899906842624\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x6ca8040183582748c2dea091990c724b3903c45e747cc8d8a75701c8acd86b9", + "stateKeyHash": "lB+jpxNlJYkV0hQHc0JXdGpak0gRqPjOAXgwrOAYrOs=", + "type": { + "address": "0x1", + "module": "object", + "name": "Untransferable" + }, + "typeStr": "0x1::object::Untransferable", + "data": "{\"dummy_field\":false}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x7c8e9b0f2ec5621dc150afbd5cb6cb9d0f61ca91921041b5fdfe063e524b851", + "stateKeyHash": "jaX6YqcidGWaVYW0mxJikPfFX6jCr8SGUMblSrwTqAc=", + "type": { + "address": "0x1", + "module": "coin", + "name": "CoinStore", + "genericTypeParams": [ + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "aptos_coin", + "name": "AptosCoin" + } + } + ] + }, + "typeStr": "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>", + "data": "{\"coin\":{\"value\":\"186521510104405\"},\"deposit_events\":{\"counter\":\"88\",\"guid\":{\"id\":{\"addr\":\"0x7c8e9b0f2ec5621dc150afbd5cb6cb9d0f61ca91921041b5fdfe063e524b851\",\"creation_num\":\"2\"}}},\"frozen\":false,\"withdraw_events\":{\"counter\":\"44\",\"guid\":{\"id\":{\"addr\":\"0x7c8e9b0f2ec5621dc150afbd5cb6cb9d0f61ca91921041b5fdfe063e524b851\",\"creation_num\":\"3\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x121ed48962169f2d0670380fc8768bfa0d713dea51c176496274808c4b6a75ab", + "stateKeyHash": "zGmQffK8AOfOjeBAygD2sAQL/Plx9Qoy5rz5/Doy1Sw=", + "type": { + "address": "0x1", + "module": "coin", + "name": "CoinStore", + "genericTypeParams": [ + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "aptos_coin", + "name": "AptosCoin" + } + } + ] + }, + "typeStr": "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>", + "data": "{\"coin\":{\"value\":\"498999545100\"},\"deposit_events\":{\"counter\":\"2\",\"guid\":{\"id\":{\"addr\":\"0x121ed48962169f2d0670380fc8768bfa0d713dea51c176496274808c4b6a75ab\",\"creation_num\":\"2\"}}},\"frozen\":false,\"withdraw_events\":{\"counter\":\"3\",\"guid\":{\"id\":{\"addr\":\"0x121ed48962169f2d0670380fc8768bfa0d713dea51c176496274808c4b6a75ab\",\"creation_num\":\"3\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x121ed48962169f2d0670380fc8768bfa0d713dea51c176496274808c4b6a75ab", + "stateKeyHash": "z4+TOcKzkVjZ7t9soGHhIXxZiR9SWBN8YEQ7i9xPLrY=", + "type": { + "address": "0x1", + "module": "account", + "name": "Account" + }, + "typeStr": "0x1::account::Account", + "data": "{\"authentication_key\":\"0x121ed48962169f2d0670380fc8768bfa0d713dea51c176496274808c4b6a75ab\",\"coin_register_events\":{\"counter\":\"3\",\"guid\":{\"id\":{\"addr\":\"0x121ed48962169f2d0670380fc8768bfa0d713dea51c176496274808c4b6a75ab\",\"creation_num\":\"0\"}}},\"guid_creation_num\":\"8\",\"key_rotation_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x121ed48962169f2d0670380fc8768bfa0d713dea51c176496274808c4b6a75ab\",\"creation_num\":\"1\"}}},\"rotation_capability_offer\":{\"for\":{\"vec\":[]}},\"sequence_number\":\"5\",\"signer_capability_offer\":{\"for\":{\"vec\":[]}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x3d795bc052b321c5d9934ef943d414a2d82ed5680a44be43b01c05052c495274", + "stateKeyHash": "cqqKWkjjzcDmHbNU05zg/Qkva3s19Fxrc1uDwvwkjQU=", + "type": { + "address": "0x1", + "module": "fungible_asset", + "name": "FungibleStore" + }, + "typeStr": "0x1::fungible_asset::FungibleStore", + "data": "{\"balance\":\"186521510104405\",\"frozen\":false,\"metadata\":{\"inner\":\"0xf8d3506b42a6879680974fc745526c9cbd48b0b0816079aa59f65fc865bdfbf6\"}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x3d795bc052b321c5d9934ef943d414a2d82ed5680a44be43b01c05052c495274", + "stateKeyHash": "cqqKWkjjzcDmHbNU05zg/Qkva3s19Fxrc1uDwvwkjQU=", + "type": { + "address": "0x1", + "module": "object", + "name": "ObjectCore" + }, + "typeStr": "0x1::object::ObjectCore", + "data": "{\"allow_ungated_transfer\":false,\"guid_creation_num\":\"1125899906842625\",\"owner\":\"0xe6a9765b0a7ebf70080e9ad115e3e70b637394a04363f5dda865887c0c21781e\",\"transfer_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x3d795bc052b321c5d9934ef943d414a2d82ed5680a44be43b01c05052c495274\",\"creation_num\":\"1125899906842624\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x5b691834b5a284ce1bf87796eddbac39422e4c0e2db43903a0b98f9a3778824a", + "stateKeyHash": "fNB3jZFX6aRaaVWukgcHzSY/yaYeTIhMQ5l6a9OVflE=", + "type": { + "address": "0x1", + "module": "fungible_asset", + "name": "FungibleStore" + }, + "typeStr": "0x1::fungible_asset::FungibleStore", + "data": "{\"balance\":\"0\",\"frozen\":false,\"metadata\":{\"inner\":\"0xf8d3506b42a6879680974fc745526c9cbd48b0b0816079aa59f65fc865bdfbf6\"}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x5b691834b5a284ce1bf87796eddbac39422e4c0e2db43903a0b98f9a3778824a", + "stateKeyHash": "fNB3jZFX6aRaaVWukgcHzSY/yaYeTIhMQ5l6a9OVflE=", + "type": { + "address": "0x1", + "module": "object", + "name": "ObjectCore" + }, + "typeStr": "0x1::object::ObjectCore", + "data": "{\"allow_ungated_transfer\":false,\"guid_creation_num\":\"1125899906842625\",\"owner\":\"0x121ed48962169f2d0670380fc8768bfa0d713dea51c176496274808c4b6a75ab\",\"transfer_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x5b691834b5a284ce1bf87796eddbac39422e4c0e2db43903a0b98f9a3778824a\",\"creation_num\":\"1125899906842624\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x7f5170624083679dbb5a8119e3dec380d95fddfd0940a4fb7118c7d9db61d425", + "stateKeyHash": "zyp/Zocl+KA0IWYEb/JUvRvrYHeY3tjfqCUsNcoAFaY=", + "type": { + "address": "0x1", + "module": "fungible_asset", + "name": "ConcurrentSupply" + }, + "typeStr": "0x1::fungible_asset::ConcurrentSupply", + "data": "{\"current\":{\"max_value\":\"340282366920938463463374607431768211455\",\"value\":\"254362465131536\"}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x7f5170624083679dbb5a8119e3dec380d95fddfd0940a4fb7118c7d9db61d425", + "stateKeyHash": "zyp/Zocl+KA0IWYEb/JUvRvrYHeY3tjfqCUsNcoAFaY=", + "type": { + "address": "0x1", + "module": "fungible_asset", + "name": "Metadata" + }, + "typeStr": "0x1::fungible_asset::Metadata", + "data": "{\"decimals\":8,\"icon_uri\":\"\",\"name\":\"aApt\",\"project_uri\":\"\",\"symbol\":\"AAPT\"}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x7f5170624083679dbb5a8119e3dec380d95fddfd0940a4fb7118c7d9db61d425", + "stateKeyHash": "zyp/Zocl+KA0IWYEb/JUvRvrYHeY3tjfqCUsNcoAFaY=", + "type": { + "address": "0x1", + "module": "fungible_asset", + "name": "Untransferable" + }, + "typeStr": "0x1::fungible_asset::Untransferable", + "data": "{\"dummy_field\":false}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x7f5170624083679dbb5a8119e3dec380d95fddfd0940a4fb7118c7d9db61d425", + "stateKeyHash": "zyp/Zocl+KA0IWYEb/JUvRvrYHeY3tjfqCUsNcoAFaY=", + "type": { + "address": "0x1", + "module": "object", + "name": "ObjectCore" + }, + "typeStr": "0x1::object::ObjectCore", + "data": "{\"allow_ungated_transfer\":true,\"guid_creation_num\":\"1125899906842625\",\"owner\":\"0xeab7ea4d635b6b6add79d5045c4a45d8148d88287b1cfa1c3b6a4b56f46839ed\",\"transfer_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0x7f5170624083679dbb5a8119e3dec380d95fddfd0940a4fb7118c7d9db61d425\",\"creation_num\":\"1125899906842624\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x7f5170624083679dbb5a8119e3dec380d95fddfd0940a4fb7118c7d9db61d425", + "stateKeyHash": "zyp/Zocl+KA0IWYEb/JUvRvrYHeY3tjfqCUsNcoAFaY=", + "type": { + "address": "0x1", + "module": "primary_fungible_store", + "name": "DeriveRefPod" + }, + "typeStr": "0x1::primary_fungible_store::DeriveRefPod", + "data": "{\"metadata_derive_ref\":{\"self\":\"0x7f5170624083679dbb5a8119e3dec380d95fddfd0940a4fb7118c7d9db61d425\"}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0x7f5170624083679dbb5a8119e3dec380d95fddfd0940a4fb7118c7d9db61d425", + "stateKeyHash": "zyp/Zocl+KA0IWYEb/JUvRvrYHeY3tjfqCUsNcoAFaY=", + "type": { + "address": "0xeab7ea4d635b6b6add79d5045c4a45d8148d88287b1cfa1c3b6a4b56f46839ed", + "module": "token_base", + "name": "ManagedFungibleAsset" + }, + "typeStr": "0xeab7ea4d635b6b6add79d5045c4a45d8148d88287b1cfa1c3b6a4b56f46839ed::token_base::ManagedFungibleAsset", + "data": "{\"burn_ref\":{\"metadata\":{\"inner\":\"0x7f5170624083679dbb5a8119e3dec380d95fddfd0940a4fb7118c7d9db61d425\"}},\"mint_ref\":{\"metadata\":{\"inner\":\"0x7f5170624083679dbb5a8119e3dec380d95fddfd0940a4fb7118c7d9db61d425\"}},\"transfer_ref\":{\"metadata\":{\"inner\":\"0x7f5170624083679dbb5a8119e3dec380d95fddfd0940a4fb7118c7d9db61d425\"}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0xf8d3506b42a6879680974fc745526c9cbd48b0b0816079aa59f65fc865bdfbf6", + "stateKeyHash": "VZ42Cl5+fE8t7V6lztY5baV1AugAZwv+woJ/bnaPBTg=", + "type": { + "address": "0x1", + "module": "fungible_asset", + "name": "ConcurrentSupply" + }, + "typeStr": "0x1::fungible_asset::ConcurrentSupply", + "data": "{\"current\":{\"max_value\":\"1000000000000000000\",\"value\":\"186521510104405\"}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0xf8d3506b42a6879680974fc745526c9cbd48b0b0816079aa59f65fc865bdfbf6", + "stateKeyHash": "VZ42Cl5+fE8t7V6lztY5baV1AugAZwv+woJ/bnaPBTg=", + "type": { + "address": "0x1", + "module": "fungible_asset", + "name": "Metadata" + }, + "typeStr": "0x1::fungible_asset::Metadata", + "data": "{\"decimals\":8,\"icon_uri\":\"https://aptoscan.com/images/empty-coin.svg\",\"name\":\"Apt\",\"project_uri\":\"https://aptoscan.com\",\"symbol\":\"APT\"}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0xf8d3506b42a6879680974fc745526c9cbd48b0b0816079aa59f65fc865bdfbf6", + "stateKeyHash": "VZ42Cl5+fE8t7V6lztY5baV1AugAZwv+woJ/bnaPBTg=", + "type": { + "address": "0x1", + "module": "object", + "name": "ObjectCore" + }, + "typeStr": "0x1::object::ObjectCore", + "data": "{\"allow_ungated_transfer\":true,\"guid_creation_num\":\"1125899906842625\",\"owner\":\"0x53390ca959abc075b2d18d6c29e2168e62068ac24838b064fce51f16613cad09\",\"transfer_events\":{\"counter\":\"0\",\"guid\":{\"id\":{\"addr\":\"0xf8d3506b42a6879680974fc745526c9cbd48b0b0816079aa59f65fc865bdfbf6\",\"creation_num\":\"1125899906842624\"}}}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0xf8d3506b42a6879680974fc745526c9cbd48b0b0816079aa59f65fc865bdfbf6", + "stateKeyHash": "VZ42Cl5+fE8t7V6lztY5baV1AugAZwv+woJ/bnaPBTg=", + "type": { + "address": "0x1", + "module": "primary_fungible_store", + "name": "DeriveRefPod" + }, + "typeStr": "0x1::primary_fungible_store::DeriveRefPod", + "data": "{\"metadata_derive_ref\":{\"self\":\"0xf8d3506b42a6879680974fc745526c9cbd48b0b0816079aa59f65fc865bdfbf6\"}}" + } + }, + { + "type": "TYPE_WRITE_RESOURCE", + "writeResource": { + "address": "0xf8d3506b42a6879680974fc745526c9cbd48b0b0816079aa59f65fc865bdfbf6", + "stateKeyHash": "VZ42Cl5+fE8t7V6lztY5baV1AugAZwv+woJ/bnaPBTg=", + "type": { + "address": "0xeab7ea4d635b6b6add79d5045c4a45d8148d88287b1cfa1c3b6a4b56f46839ed", + "module": "underlying_token_factory", + "name": "ManagedFungibleAsset" + }, + "typeStr": "0xeab7ea4d635b6b6add79d5045c4a45d8148d88287b1cfa1c3b6a4b56f46839ed::underlying_token_factory::ManagedFungibleAsset", + "data": "{\"burn_ref\":{\"metadata\":{\"inner\":\"0xf8d3506b42a6879680974fc745526c9cbd48b0b0816079aa59f65fc865bdfbf6\"}},\"mint_ref\":{\"metadata\":{\"inner\":\"0xf8d3506b42a6879680974fc745526c9cbd48b0b0816079aa59f65fc865bdfbf6\"}},\"transfer_ref\":{\"metadata\":{\"inner\":\"0xf8d3506b42a6879680974fc745526c9cbd48b0b0816079aa59f65fc865bdfbf6\"}}}" + } + }, + { + "type": "TYPE_WRITE_TABLE_ITEM", + "writeTableItem": { + "stateKeyHash": "0G3P/bncGDYS7AfQi70eScsDJ25LLBluXoqenXtcRgo=", + "handle": "0x075214b565eca9c51738d051a5a85c840504aa1fbe2d15ae02219c8d2766b058", + "key": "0x0100000000000000", + "data": { + "key": "\"1\"", + "keyType": "u64", + "value": "[{\"hash\":\"18284012927815856109\",\"key\":\"0xf8d3506b42a6879680974fc745526c9cbd48b0b0816079aa59f65fc865bdfbf6\",\"value\":{\"a_token_address\":\"0x7f5170624083679dbb5a8119e3dec380d95fddfd0940a4fb7118c7d9db61d425\",\"accrued_to_treasury\":\"1225458039\",\"configuration\":{\"data\":\"27679702067468833659736\"},\"current_liquidity_rate\":\"2419151083639521685424860\",\"current_variable_borrow_rate\":\"10669695587784006271441329\",\"id\":0,\"isolation_mode_total_debt\":\"0\",\"last_update_timestamp\":\"1729151735\",\"liquidity_index\":\"1000039664716620419206721357\",\"unbacked\":\"0\",\"variable_borrow_index\":\"1000174769739502015654977841\",\"variable_debt_token_address\":\"0x4a1655da0e64eb8d641b820b7d9e0aa5433cd7436e81f62d21b947d12933fcd1\"}},{\"hash\":\"15468314229053427081\",\"key\":\"0x2760ca0d7ed74fec37f1c539fd752b5c684fa011c539a79def7a6c67717ebace\",\"value\":{\"a_token_address\":\"0xee2a8176e27b75bd30419b0ded6c00f15ec551135a6ea69f2575601ec87439a6\",\"accrued_to_treasury\":\"11553225\",\"configuration\":{\"data\":\"27679702630418787081048\"},\"current_liquidity_rate\":\"336278684909752263229774\",\"current_variable_borrow_rate\":\"4754678791895514837045933\",\"id\":1,\"isolation_mode_total_debt\":\"0\",\"last_update_timestamp\":\"1729151580\",\"liquidity_index\":\"1000002915105130102400753265\",\"unbacked\":\"0\",\"variable_borrow_index\":\"1000050598668096455674895092\",\"variable_debt_token_address\":\"0x8dcaf4d5453e938271e99940e56c0ff17cedac3bc62421c32e598202972563a6\"}}]", + "valueType": "vector<0x1::smart_table::Entry>" + } + } + }, + { + "type": "TYPE_WRITE_TABLE_ITEM", + "writeTableItem": { + "stateKeyHash": "bkso1A+YoQamUWNTCSTA3LQME0nTqpFdEItNbPwd2xk=", + "handle": "0x1b854694ae746cdbd8d44186ca4929b2b337df21d1c74633be19b2710552fdca", + "key": "0x0619dc29a0aac8fa146714058e8dd6d2d0f3bdf5f6331907bf91f3acd81e6935", + "data": { + "key": "\"0x619dc29a0aac8fa146714058e8dd6d2d0f3bdf5f6331907bf91f3acd81e6935\"", + "keyType": "address", + "value": "\"112125669383047952\"", + "valueType": "u128" + } + } + }, + { + "type": "TYPE_WRITE_TABLE_ITEM", + "writeTableItem": { + "stateKeyHash": "gBNyHZOJjGWmJdTRAhh5/PcQgkcIkdFMKW8tlY4FVJY=", + "handle": "0x757f59d1093c97d214ae533f313498b412dad0bccf78d149eeff317d1d95a287", + "key": "0x1100000000000000", + "data": { + "key": "\"17\"", + "keyType": "u64", + "value": "[{\"hash\":\"1317857034859683601\",\"key\":\"@0x9fdbd47d7efe89c52836d762c264e6cf02e4f840db13db56a65a8592748c4ac6_@0xe7abd29ed72c3de3efff113ee0f7e32753a55327a0de32370baa88ae29c9efbe\",\"value\":{\"additional_data\":\"1000000720252743677740805733\",\"balance\":\"0\"}},{\"hash\":\"13797321631402460081\",\"key\":\"@0xdc547dd3a5e8b225383948dc3e9832f0afc2a5e81aae1940219a53f6dabf4649_@0x7f5170624083679dbb5a8119e3dec380d95fddfd0940a4fb7118c7d9db61d425\",\"value\":{\"additional_data\":\"1000000050342570579205531100\",\"balance\":\"233854270\"}},{\"hash\":\"4083923470927304433\",\"key\":\"@0x79fcbdfaf07426b1953b7ad2f3a0f73e020ee4d4419e2765676199be78f2d904_@0xee2a8176e27b75bd30419b0ded6c00f15ec551135a6ea69f2575601ec87439a6\",\"value\":{\"additional_data\":\"1000000554450579199742637867\",\"balance\":\"249999861920\"}},{\"hash\":\"1888349924734582545\",\"key\":\"@0x121ed48962169f2d0670380fc8768bfa0d713dea51c176496274808c4b6a75ab_@0x7f5170624083679dbb5a8119e3dec380d95fddfd0940a4fb7118c7d9db61d425\",\"value\":{\"additional_data\":\"1000039664716620419206721357\",\"balance\":\"28698862237658\"}}]", + "valueType": "vector<0x1::smart_table::Entry<0x1::string::String, 0xeab7ea4d635b6b6add79d5045c4a45d8148d88287b1cfa1c3b6a4b56f46839ed::token_base::UserState>>" + } + } + }, + { + "type": "TYPE_WRITE_TABLE_ITEM", + "writeTableItem": { + "stateKeyHash": "yKYjr7JygbWYaKGiZJ57GJScJBDR6pdlAxk2s1LaYss=", + "handle": "0xaa8b6777f8e9281c3faf9557a5b43f33dd56e647dc3d8a2f19b4239df6f4b750", + "key": "0x0100000000000000", + "data": { + "key": "\"1\"", + "keyType": "u64", + "value": "[{\"hash\":\"11042075261116213331\",\"key\":\"0x7f5170624083679dbb5a8119e3dec380d95fddfd0940a4fb7118c7d9db61d425\",\"value\":{\"resource_account\":\"0xe6a9765b0a7ebf70080e9ad115e3e70b637394a04363f5dda865887c0c21781e\",\"scaled_total_supply\":\"254362465131536\",\"treasury\":\"0x53390ca959abc075b2d18d6c29e2168e62068ac24838b064fce51f16613cad09\",\"underlying_asset\":\"0xf8d3506b42a6879680974fc745526c9cbd48b0b0816079aa59f65fc865bdfbf6\"}},{\"hash\":\"13855069079191215931\",\"key\":\"0x8dcaf4d5453e938271e99940e56c0ff17cedac3bc62421c32e598202972563a6\",\"value\":{\"resource_account\":\"0x0\",\"scaled_total_supply\":\"1894442060796\",\"treasury\":\"0x0\",\"underlying_asset\":\"0x2760ca0d7ed74fec37f1c539fd752b5c684fa011c539a79def7a6c67717ebace\"}},{\"hash\":\"3797068605666336777\",\"key\":\"0x66c070de0eb43e4c593d1b1ba7a12da2ce07c9e59286d3bef6d329bea49f6034\",\"value\":{\"resource_account\":\"0x558b499a4ce14742369d8633c3c0470eb18384d2a0b4465e7b63d79c4e15153a\",\"scaled_total_supply\":\"130924440\",\"treasury\":\"0x53390ca959abc075b2d18d6c29e2168e62068ac24838b064fce51f16613cad09\",\"underlying_asset\":\"0x66cca033c185547a88494a9c71baa0dd2185212cfe5e79ec2ec0c4040b5c35c0\"}},{\"hash\":\"6772208373927250815\",\"key\":\"0xfd87ffc7afd8da69da3939c16792515368333385b37803489831a8133821ada9\",\"value\":{\"resource_account\":\"0x0\",\"scaled_total_supply\":\"14115688\",\"treasury\":\"0x0\",\"underlying_asset\":\"0x66cca033c185547a88494a9c71baa0dd2185212cfe5e79ec2ec0c4040b5c35c0\"}},{\"hash\":\"15204122241108007857\",\"key\":\"0xe7abd29ed72c3de3efff113ee0f7e32753a55327a0de32370baa88ae29c9efbe\",\"value\":{\"resource_account\":\"0x0\",\"scaled_total_supply\":\"28077231\",\"treasury\":\"0x0\",\"underlying_asset\":\"0xc2315bdb8f7789e1817ac423e80748075fa68b7e33949bde8c2769a46fdb212\"}}]", + "valueType": "vector<0x1::smart_table::Entry>" + } + } + } + ] + }, + "epoch": "8878", + "blockHeight": "240114161", + "type": "TRANSACTION_TYPE_USER", + "sizeInfo": { + "transactionBytes": 380, + "eventSizeInfo": [ + { + "typeTagBytes": 53, + "totalBytes": 109 + }, + { + "typeTagBytes": 52, + "totalBytes": 108 + }, + { + "typeTagBytes": 57, + "totalBytes": 97 + }, + { + "typeTagBytes": 58, + "totalBytes": 218 + }, + { + "typeTagBytes": 58, + "totalBytes": 98 + }, + { + "typeTagBytes": 57, + "totalBytes": 97 + }, + { + "typeTagBytes": 56, + "totalBytes": 89 + }, + { + "typeTagBytes": 57, + "totalBytes": 97 + }, + { + "typeTagBytes": 54, + "totalBytes": 150 + }, + { + "typeTagBytes": 50, + "totalBytes": 210 + }, + { + "typeTagBytes": 54, + "totalBytes": 184 + }, + { + "typeTagBytes": 63, + "totalBytes": 103 + } + ], + "writeOpSizeInfo": [ + { + "keyBytes": 87, + "valueBytes": 303 + }, + { + "keyBytes": 138, + "valueBytes": 105 + }, + { + "keyBytes": 138, + "valueBytes": 105 + }, + { + "keyBytes": 84, + "valueBytes": 147 + }, + { + "keyBytes": 87, + "valueBytes": 246 + }, + { + "keyBytes": 87, + "valueBytes": 246 + }, + { + "keyBytes": 87, + "valueBytes": 640 + }, + { + "keyBytes": 87, + "valueBytes": 649 + }, + { + "keyBytes": 42, + "valueBytes": 549 + }, + { + "keyBytes": 66, + "valueBytes": 16 + }, + { + "keyBytes": 42, + "valueBytes": 709 + }, + { + "keyBytes": 42, + "valueBytes": 841 + } + ] + }, + "user": { + "request": { + "sender": "0x121ed48962169f2d0670380fc8768bfa0d713dea51c176496274808c4b6a75ab", + "sequenceNumber": "4", + "maxGasAmount": "63", + "gasUnitPrice": "100", + "expirationTimestampSecs": { + "seconds": "1729151794" + }, + "payload": { + "type": "TYPE_ENTRY_FUNCTION_PAYLOAD", + "entryFunctionPayload": { + "function": { + "module": { + "address": "0xeab7ea4d635b6b6add79d5045c4a45d8148d88287b1cfa1c3b6a4b56f46839ed", + "name": "router" + }, + "name": "supply_simple" + }, + "typeArguments": [ + { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "aptos_coin", + "name": "AptosCoin" + } + } + ], + "arguments": [ + "\"0xf8d3506b42a6879680974fc745526c9cbd48b0b0816079aa59f65fc865bdfbf6\"", + "\"5700000000000\"", + "\"0x121ed48962169f2d0670380fc8768bfa0d713dea51c176496274808c4b6a75ab\"", + "1", + "false" + ], + "entryFunctionIdStr": "0xeab7ea4d635b6b6add79d5045c4a45d8148d88287b1cfa1c3b6a4b56f46839ed::router::supply_simple" + } + }, + "signature": { + "type": "TYPE_ED25519", + "ed25519": { + "publicKey": "MhqN2w1t3ylxqcAZ5Q82LHg5tf0bNvGle3Ez+smxl4k=", + "signature": "KNEo85UdU1M+QT4z17IRKXBSfgmSztoMGem7KZuRwzlwyQcP90cjZmBO7Tx5acZUaXs9BlSBvow63NMBxEuLDA==" + } + } + }, + "events": [ + { + "key": { + "creationNumber": "3", + "accountAddress": "0x121ed48962169f2d0670380fc8768bfa0d713dea51c176496274808c4b6a75ab" + }, + "sequenceNumber": "2", + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "coin", + "name": "WithdrawEvent" + } + }, + "typeStr": "0x1::coin::WithdrawEvent", + "data": "{\"amount\":\"5700000000000\"}" + }, + { + "key": { + "creationNumber": "2", + "accountAddress": "0x07c8e9b0f2ec5621dc150afbd5cb6cb9d0f61ca91921041b5fdfe063e524b851" + }, + "sequenceNumber": "87", + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "coin", + "name": "DepositEvent" + } + }, + "typeStr": "0x1::coin::DepositEvent", + "data": "{\"amount\":\"5700000000000\"}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "fungible_asset", + "name": "Deposit" + } + }, + "typeStr": "0x1::fungible_asset::Deposit", + "data": "{\"amount\":\"5700000000000\",\"store\":\"0x5b691834b5a284ce1bf87796eddbac39422e4c0e2db43903a0b98f9a3778824a\"}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0xeab7ea4d635b6b6add79d5045c4a45d8148d88287b1cfa1c3b6a4b56f46839ed", + "module": "pool", + "name": "ReserveDataUpdated" + } + }, + "typeStr": "0xeab7ea4d635b6b6add79d5045c4a45d8148d88287b1cfa1c3b6a4b56f46839ed::pool::ReserveDataUpdated", + "data": "{\"liquidity_index\":\"1000039664716620419206721357\",\"liquidity_rate\":\"2419151083639521685424860\",\"reserve\":\"0xf8d3506b42a6879680974fc745526c9cbd48b0b0816079aa59f65fc865bdfbf6\",\"variable_borrow_index\":\"1000174769739502015654977841\",\"variable_borrow_rate\":\"10669695587784006271441329\"}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "fungible_asset", + "name": "Withdraw" + } + }, + "typeStr": "0x1::fungible_asset::Withdraw", + "data": "{\"amount\":\"5700000000000\",\"store\":\"0x5b691834b5a284ce1bf87796eddbac39422e4c0e2db43903a0b98f9a3778824a\"}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "fungible_asset", + "name": "Deposit" + } + }, + "typeStr": "0x1::fungible_asset::Deposit", + "data": "{\"amount\":\"5700000000000\",\"store\":\"0x3d795bc052b321c5d9934ef943d414a2d82ed5680a44be43b01c05052c495274\"}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "fungible_asset", + "name": "Frozen" + } + }, + "typeStr": "0x1::fungible_asset::Frozen", + "data": "{\"frozen\":true,\"store\":\"0x6ca8040183582748c2dea091990c724b3903c45e747cc8d8a75701c8acd86b9\"}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "fungible_asset", + "name": "Deposit" + } + }, + "typeStr": "0x1::fungible_asset::Deposit", + "data": "{\"amount\":\"5699773920083\",\"store\":\"0x6ca8040183582748c2dea091990c724b3903c45e747cc8d8a75701c8acd86b9\"}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0xeab7ea4d635b6b6add79d5045c4a45d8148d88287b1cfa1c3b6a4b56f46839ed", + "module": "token_base", + "name": "Transfer" + } + }, + "typeStr": "0xeab7ea4d635b6b6add79d5045c4a45d8148d88287b1cfa1c3b6a4b56f46839ed::token_base::Transfer", + "data": "{\"from\":\"0x0\",\"to\":\"0x121ed48962169f2d0670380fc8768bfa0d713dea51c176496274808c4b6a75ab\",\"value\":\"5700000569896\"}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0xeab7ea4d635b6b6add79d5045c4a45d8148d88287b1cfa1c3b6a4b56f46839ed", + "module": "token_base", + "name": "Mint" + } + }, + "typeStr": "0xeab7ea4d635b6b6add79d5045c4a45d8148d88287b1cfa1c3b6a4b56f46839ed::token_base::Mint", + "data": "{\"balance_increase\":\"569896\",\"caller\":\"0x121ed48962169f2d0670380fc8768bfa0d713dea51c176496274808c4b6a75ab\",\"index\":\"1000039664716620419206721357\",\"on_behalf_of\":\"0x121ed48962169f2d0670380fc8768bfa0d713dea51c176496274808c4b6a75ab\",\"value\":\"5700000569896\"}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0xeab7ea4d635b6b6add79d5045c4a45d8148d88287b1cfa1c3b6a4b56f46839ed", + "module": "supply_logic", + "name": "Supply" + } + }, + "typeStr": "0xeab7ea4d635b6b6add79d5045c4a45d8148d88287b1cfa1c3b6a4b56f46839ed::supply_logic::Supply", + "data": "{\"amount\":\"5700000000000\",\"on_behalf_of\":\"0x121ed48962169f2d0670380fc8768bfa0d713dea51c176496274808c4b6a75ab\",\"referral_code\":1,\"reserve\":\"0xf8d3506b42a6879680974fc745526c9cbd48b0b0816079aa59f65fc865bdfbf6\",\"user\":\"0x121ed48962169f2d0670380fc8768bfa0d713dea51c176496274808c4b6a75ab\"}" + }, + { + "key": { + "accountAddress": "0x0" + }, + "type": { + "type": "MOVE_TYPES_STRUCT", + "struct": { + "address": "0x1", + "module": "transaction_fee", + "name": "FeeStatement" + } + }, + "typeStr": "0x1::transaction_fee::FeeStatement", + "data": "{\"execution_gas_units\":\"37\",\"io_gas_units\":\"26\",\"storage_fee_octas\":\"0\",\"storage_fee_refund_octas\":\"0\",\"total_charge_gas_units\":\"63\"}" + } + ] + } +} \ No newline at end of file diff --git a/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/imported_transactions.yaml b/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/imported_transactions.yaml index 3253aa8ed88c6..e01864698e7a7 100644 --- a/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/imported_transactions.yaml +++ b/ecosystem/indexer-grpc/indexer-transaction-generator/imported_transactions/imported_transactions.yaml @@ -60,6 +60,7 @@ mainnet: # objects processor 578318306: 578318306_objects_write_resource + 1806220919: 1806220919_object_untransferable # stake processor 121508544: 121508544_stake_distribute From 60ee0c686c15480b2cbba224c205e03f479bcdbd Mon Sep 17 00:00:00 2001 From: Aaron Date: Wed, 4 Dec 2024 18:24:29 -0600 Subject: [PATCH 17/78] add devnet test txns (#15489) --- ecosystem/indexer-grpc/indexer-test-transactions/build.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ecosystem/indexer-grpc/indexer-test-transactions/build.rs b/ecosystem/indexer-grpc/indexer-test-transactions/build.rs index b574313a291b0..ede1ca06eabbc 100644 --- a/ecosystem/indexer-grpc/indexer-test-transactions/build.rs +++ b/ecosystem/indexer-grpc/indexer-test-transactions/build.rs @@ -5,6 +5,7 @@ use std::{env, fs, path::Path}; const IMPORTED_MAINNET_TXNS: &str = "imported_mainnet_txns"; const IMPORTED_TESTNET_TXNS: &str = "imported_testnet_txns"; +const IMPORTED_DEVNET_TXNS: &str = "imported_devnet_txns"; const SCRIPTED_TRANSACTIONS_TXNS: &str = "scripted_transactions"; #[derive(Default)] pub struct TransactionCodeBuilder { @@ -113,12 +114,14 @@ fn main() { // Create necessary directories if missing create_directory_if_missing(&format!("json_transactions/{}", IMPORTED_MAINNET_TXNS)); create_directory_if_missing(&format!("json_transactions/{}", IMPORTED_TESTNET_TXNS)); + create_directory_if_missing(&format!("json_transactions/{}", IMPORTED_DEVNET_TXNS)); create_directory_if_missing(&format!("json_transactions/{}", SCRIPTED_TRANSACTIONS_TXNS)); // Using the builder pattern to construct the code let code = TransactionCodeBuilder::new() .add_directory(IMPORTED_MAINNET_TXNS, IMPORTED_MAINNET_TXNS, false) .add_directory(IMPORTED_TESTNET_TXNS, IMPORTED_TESTNET_TXNS, false) + .add_directory(IMPORTED_DEVNET_TXNS, IMPORTED_DEVNET_TXNS, false) .add_directory(SCRIPTED_TRANSACTIONS_TXNS, SCRIPTED_TRANSACTIONS_TXNS, true) .add_transaction_name_function() .build(); From c2969f0b0ecd826aa1516a386aed59496a247958 Mon Sep 17 00:00:00 2001 From: Aaron Date: Wed, 4 Dec 2024 18:43:01 -0600 Subject: [PATCH 18/78] [FA] get rid of migration flag (#15269) * [FA] get rid of migration flag * fixup! [FA] get rid of migration flag --- .../framework/aptos-framework/doc/coin.md | 152 ++++++++++-------- .../aptos-framework/sources/coin.move | 69 ++++---- .../aptos-framework/sources/coin.spec.move | 3 +- .../src/aptos_framework_sdk_builder.rs | 46 ++++++ .../framework/move-stdlib/doc/features.md | 11 ++ .../sources/configs/features.spec.move | 4 + 6 files changed, 185 insertions(+), 100 deletions(-) diff --git a/aptos-move/framework/aptos-framework/doc/coin.md b/aptos-move/framework/aptos-framework/doc/coin.md index 273f2a2f3e1f0..98f56f007e8b3 100644 --- a/aptos-move/framework/aptos-framework/doc/coin.md +++ b/aptos-move/framework/aptos-framework/doc/coin.md @@ -19,7 +19,6 @@ This module provides the foundation for typesafe Coins. - [Struct `WithdrawEvent`](#0x1_coin_WithdrawEvent) - [Struct `CoinEventHandleDeletion`](#0x1_coin_CoinEventHandleDeletion) - [Struct `PairCreation`](#0x1_coin_PairCreation) -- [Resource `MigrationFlag`](#0x1_coin_MigrationFlag) - [Struct `MintCapability`](#0x1_coin_MintCapability) - [Struct `FreezeCapability`](#0x1_coin_FreezeCapability) - [Struct `BurnCapability`](#0x1_coin_BurnCapability) @@ -29,6 +28,7 @@ This module provides the foundation for typesafe Coins. - [Struct `MintRefReceipt`](#0x1_coin_MintRefReceipt) - [Struct `TransferRefReceipt`](#0x1_coin_TransferRefReceipt) - [Struct `BurnRefReceipt`](#0x1_coin_BurnRefReceipt) +- [Resource `MigrationFlag`](#0x1_coin_MigrationFlag) - [Resource `Ghost$supply`](#0x1_coin_Ghost$supply) - [Resource `Ghost$aggregate_supply`](#0x1_coin_Ghost$aggregate_supply) - [Constants](#@Constants_0) @@ -57,6 +57,7 @@ This module provides the foundation for typesafe Coins. - [Function `calculate_amount_to_withdraw`](#0x1_coin_calculate_amount_to_withdraw) - [Function `maybe_convert_to_fungible_store`](#0x1_coin_maybe_convert_to_fungible_store) - [Function `migrate_to_fungible_store`](#0x1_coin_migrate_to_fungible_store) +- [Function `migrate_coin_store_to_fungible_store`](#0x1_coin_migrate_coin_store_to_fungible_store) - [Function `coin_address`](#0x1_coin_coin_address) - [Function `balance`](#0x1_coin_balance) - [Function `is_balance_at_least`](#0x1_coin_is_balance_at_least) @@ -72,7 +73,7 @@ This module provides the foundation for typesafe Coins. - [Function `burn`](#0x1_coin_burn) - [Function `burn_from`](#0x1_coin_burn_from) - [Function `deposit`](#0x1_coin_deposit) -- [Function `migrated_primary_fungible_store_exists`](#0x1_coin_migrated_primary_fungible_store_exists) +- [Function `can_receive_paired_fungible_asset`](#0x1_coin_can_receive_paired_fungible_asset) - [Function `force_deposit`](#0x1_coin_force_deposit) - [Function `destroy_zero`](#0x1_coin_destroy_zero) - [Function `extract`](#0x1_coin_extract) @@ -151,6 +152,7 @@ This module provides the foundation for typesafe Coins. use 0x1::system_addresses; use 0x1::table; use 0x1::type_info; +use 0x1::vector; @@ -621,35 +623,6 @@ Module event emitted when a new pair of coin and fungible asset is created. - - - - -## Resource `MigrationFlag` - -The flag the existence of which indicates the primary fungible store is created by the migration from CoinStore. - - -
#[resource_group_member(#[group = 0x1::object::ObjectGroup])]
-struct MigrationFlag has key
-
- - - -
-Fields - - -
-
-dummy_field: bool -
-
- -
-
- -
@@ -916,6 +889,36 @@ The hot potato receipt for flash borrowing BurnRef. + + + + +## Resource `MigrationFlag` + +The flag the existence of which indicates the primary fungible store is created by the migration from CoinStore. + + +
#[resource_group_member(#[group = 0x1::object::ObjectGroup])]
+#[deprecated]
+struct MigrationFlag has key
+
+ + + +
+Fields + + +
+
+dummy_field: bool +
+
+ +
+
+ +
@@ -2038,7 +2041,6 @@ or disallow upgradability of total supply. let metadata = ensure_paired_metadata<CoinType>(); let store = primary_fungible_store::ensure_primary_store_exists(account, metadata); - let store_address = object::object_address(&store); if (exists<CoinStore<CoinType>>(account)) { let CoinStore<CoinType> { coin, frozen, deposit_events, withdraw_events } = move_from<CoinStore<CoinType>>( account @@ -2068,9 +2070,6 @@ or disallow upgradability of total supply. fungible_asset::set_frozen_flag_internal(store, frozen); } }; - if (!exists<MigrationFlag>(store_address)) { - move_to(&create_signer::create_signer(store_address), MigrationFlag {}); - } } @@ -2103,6 +2102,37 @@ Voluntarily migrate to fungible store for CoinType if not yet. + + + + +## Function `migrate_coin_store_to_fungible_store` + +Migrate to fungible store for CoinType if not yet. + + +
public entry fun migrate_coin_store_to_fungible_store<CoinType>(accounts: vector<address>)
+
+ + + +
+Implementation + + +
public entry fun migrate_coin_store_to_fungible_store<CoinType>(
+    accounts: vector<address>
+) acquires CoinStore, CoinConversionMap, CoinInfo {
+    if (features::new_accounts_default_to_fa_apt_store_enabled()) {
+        std::vector::for_each(accounts, |account| {
+            maybe_convert_to_fungible_store<CoinType>(account);
+        });
+    }
+}
+
+ + +
@@ -2314,7 +2344,7 @@ Returns true if account_addr is registered to r let paired_metadata_opt = paired_metadata<CoinType>(); (option::is_some( &paired_metadata_opt - ) && migrated_primary_fungible_store_exists(account_addr, option::destroy_some(paired_metadata_opt))) + ) && can_receive_paired_fungible_asset(account_addr, option::destroy_some(paired_metadata_opt))) } } @@ -2590,7 +2620,7 @@ Deposit the coin balance into the recipient's account and emit an event. merge(&mut coin_store.coin, coin); } else { let metadata = paired_metadata<CoinType>(); - if (option::is_some(&metadata) && migrated_primary_fungible_store_exists( + if (option::is_some(&metadata) && can_receive_paired_fungible_asset( account_addr, option::destroy_some(metadata) )) { @@ -2606,13 +2636,13 @@ Deposit the coin balance into the recipient's account and emit an event. - + -## Function `migrated_primary_fungible_store_exists` +## Function `can_receive_paired_fungible_asset` -
fun migrated_primary_fungible_store_exists(account_address: address, metadata: object::Object<fungible_asset::Metadata>): bool
+
fun can_receive_paired_fungible_asset(account_address: address, metadata: object::Object<fungible_asset::Metadata>): bool
 
@@ -2621,15 +2651,17 @@ Deposit the coin balance into the recipient's account and emit an event. Implementation -
inline fun migrated_primary_fungible_store_exists(
+
inline fun can_receive_paired_fungible_asset(
     account_address: address,
     metadata: Object<Metadata>
 ): bool {
-    let primary_store_address = primary_fungible_store::primary_store_address<Metadata>(account_address, metadata);
-    fungible_asset::store_exists(primary_store_address) && (
-        // migration flag is needed, until we start defaulting new accounts to APT PFS
-        features::new_accounts_default_to_fa_apt_store_enabled() || exists<MigrationFlag>(primary_store_address)
-    )
+    (features::new_accounts_default_to_fa_apt_store_enabled() && object::object_address(&metadata) == @0xa) || {
+        let primary_store_address = primary_fungible_store::primary_store_address<Metadata>(
+            account_address,
+            metadata
+        );
+        fungible_asset::store_exists(primary_store_address)
+    }
 }
 
@@ -2663,13 +2695,13 @@ This is for internal use only and doesn't emit an DepositEvent. merge(&mut coin_store.coin, coin); } else { let metadata = paired_metadata<CoinType>(); - if (option::is_some(&metadata) && migrated_primary_fungible_store_exists( + if (option::is_some(&metadata) && can_receive_paired_fungible_asset( account_addr, option::destroy_some(metadata) )) { let fa = coin_to_fungible_asset(coin); let metadata = fungible_asset::asset_metadata(&fa); - let store = primary_fungible_store::primary_store(account_addr, metadata); + let store = primary_fungible_store::ensure_primary_store_exists(account_addr, metadata); fungible_asset::deposit_internal(object::object_address(&store), fa); } else { abort error::not_found(ECOIN_STORE_NOT_PUBLISHED) @@ -3782,7 +3814,8 @@ Get address by reflection.
fun spec_is_account_registered<CoinType>(account_addr: address): bool {
    let paired_metadata_opt = spec_paired_metadata<CoinType>();
-   exists<CoinStore<CoinType>>(account_addr) || (option::spec_is_some(
+   exists<CoinStore<CoinType>>(account_addr) || features::spec_new_accounts_default_to_fa_apt_store_enabled(
+   ) || (option::spec_is_some(
        paired_metadata_opt
    ) && primary_fungible_store::spec_primary_store_exists(account_addr, option::spec_borrow(paired_metadata_opt)))
 }
@@ -4195,27 +4228,6 @@ The creator of CoinType must be @aptos_framework.
 
-Make sure name and symbol are legal length. -Only the creator of CoinType can initialize. - - - - - -
schema InitializeInternalSchema<CoinType> {
-    account: signer;
-    name: vector<u8>;
-    symbol: vector<u8>;
-    let account_addr = signer::address_of(account);
-    let coin_address = type_info::type_of<CoinType>().account_address;
-    aborts_if coin_address != account_addr;
-    aborts_if exists<CoinInfo<CoinType>>(account_addr);
-    aborts_if len(name) > MAX_COIN_NAME_LENGTH;
-    aborts_if len(symbol) > MAX_COIN_SYMBOL_LENGTH;
-}
-
- - diff --git a/aptos-move/framework/aptos-framework/sources/coin.move b/aptos-move/framework/aptos-framework/sources/coin.move index f1d9a81962785..2ea6aca5762ec 100644 --- a/aptos-move/framework/aptos-framework/sources/coin.move +++ b/aptos-move/framework/aptos-framework/sources/coin.move @@ -221,10 +221,6 @@ module aptos_framework::coin { fungible_asset_metadata_address: address, } - #[resource_group_member(group = aptos_framework::object::ObjectGroup)] - /// The flag the existence of which indicates the primary fungible store is created by the migration from CoinStore. - struct MigrationFlag has key {} - /// Capability required to mint coins. struct MintCapability has copy, store {} @@ -572,7 +568,6 @@ module aptos_framework::coin { let metadata = ensure_paired_metadata(); let store = primary_fungible_store::ensure_primary_store_exists(account, metadata); - let store_address = object::object_address(&store); if (exists>(account)) { let CoinStore { coin, frozen, deposit_events, withdraw_events } = move_from>( account @@ -602,9 +597,6 @@ module aptos_framework::coin { fungible_asset::set_frozen_flag_internal(store, frozen); } }; - if (!exists(store_address)) { - move_to(&create_signer::create_signer(store_address), MigrationFlag {}); - } } /// Voluntarily migrate to fungible store for `CoinType` if not yet. @@ -614,6 +606,17 @@ module aptos_framework::coin { maybe_convert_to_fungible_store(signer::address_of(account)); } + /// Migrate to fungible store for `CoinType` if not yet. + public entry fun migrate_coin_store_to_fungible_store( + accounts: vector
+ ) acquires CoinStore, CoinConversionMap, CoinInfo { + if (features::new_accounts_default_to_fa_apt_store_enabled()) { + std::vector::for_each(accounts, |account| { + maybe_convert_to_fungible_store(account); + }); + } + } + // // Getter functions // @@ -692,7 +695,7 @@ module aptos_framework::coin { let paired_metadata_opt = paired_metadata(); (option::is_some( &paired_metadata_opt - ) && migrated_primary_fungible_store_exists(account_addr, option::destroy_some(paired_metadata_opt))) + ) && can_receive_paired_fungible_asset(account_addr, option::destroy_some(paired_metadata_opt))) } } @@ -811,7 +814,7 @@ module aptos_framework::coin { merge(&mut coin_store.coin, coin); } else { let metadata = paired_metadata(); - if (option::is_some(&metadata) && migrated_primary_fungible_store_exists( + if (option::is_some(&metadata) && can_receive_paired_fungible_asset( account_addr, option::destroy_some(metadata) )) { @@ -822,15 +825,17 @@ module aptos_framework::coin { } } - inline fun migrated_primary_fungible_store_exists( + inline fun can_receive_paired_fungible_asset( account_address: address, metadata: Object ): bool { - let primary_store_address = primary_fungible_store::primary_store_address(account_address, metadata); - fungible_asset::store_exists(primary_store_address) && ( - // migration flag is needed, until we start defaulting new accounts to APT PFS - features::new_accounts_default_to_fa_apt_store_enabled() || exists(primary_store_address) - ) + (features::new_accounts_default_to_fa_apt_store_enabled() && object::object_address(&metadata) == @0xa) || { + let primary_store_address = primary_fungible_store::primary_store_address( + account_address, + metadata + ); + fungible_asset::store_exists(primary_store_address) + } } /// Deposit the coin balance into the recipient's account without checking if the account is frozen. @@ -844,13 +849,13 @@ module aptos_framework::coin { merge(&mut coin_store.coin, coin); } else { let metadata = paired_metadata(); - if (option::is_some(&metadata) && migrated_primary_fungible_store_exists( + if (option::is_some(&metadata) && can_receive_paired_fungible_asset( account_addr, option::destroy_some(metadata) )) { let fa = coin_to_fungible_asset(coin); let metadata = fungible_asset::asset_metadata(&fa); - let store = primary_fungible_store::primary_store(account_addr, metadata); + let store = primary_fungible_store::ensure_primary_store_exists(account_addr, metadata); fungible_asset::deposit_internal(object::object_address(&store), fa); } else { abort error::not_found(ECOIN_STORE_NOT_PUBLISHED) @@ -1906,7 +1911,6 @@ module aptos_framework::coin { } #[test(account = @aptos_framework, aaron = @0xaa10, bob = @0xb0b)] - #[expected_failure(abort_code = 0x60005, location = Self)] fun test_force_deposit( account: &signer, aaron: &signer, @@ -1920,6 +1924,7 @@ module aptos_framework::coin { account::create_account_for_test(bob_addr); let (burn_cap, freeze_cap, mint_cap) = initialize_and_register_fake_money(account, 1, true); maybe_convert_to_fungible_store(aaron_addr); + maybe_convert_to_fungible_store(bob_addr); deposit(aaron_addr, mint(1, &mint_cap)); force_deposit(account_addr, mint(100, &mint_cap)); @@ -1949,6 +1954,8 @@ module aptos_framework::coin { account::create_account_for_test(account_addr); account::create_account_for_test(aaron_addr); account::create_account_for_test(bob_addr); + let feature = features::get_new_accounts_default_to_fa_apt_store_feature(); + features::change_feature_flags_for_testing(account, vector[], vector[feature]); let (burn_cap, freeze_cap, mint_cap) = initialize_and_register_fake_money(account, 1, true); assert!(coin_store_exists(account_addr), 0); @@ -1957,6 +1964,13 @@ module aptos_framework::coin { assert!(!coin_store_exists(aaron_addr), 0); assert!(!is_account_registered(aaron_addr), 0); + register(bob); + assert!(coin_store_exists(bob_addr), 0); + maybe_convert_to_fungible_store(bob_addr); + assert!(!coin_store_exists(bob_addr), 0); + register(bob); + assert!(!coin_store_exists(bob_addr), 0); + maybe_convert_to_fungible_store(aaron_addr); let coin = mint(100, &mint_cap); deposit(aaron_addr, coin); @@ -1968,15 +1982,8 @@ module aptos_framework::coin { assert!(!coin_store_exists(account_addr), 0); assert!(is_account_registered(account_addr), 0); - // Deposit FA to bob to created primary fungible store without `MigrationFlag`. primary_fungible_store::deposit(bob_addr, coin_to_fungible_asset(mint(100, &mint_cap))); assert!(!coin_store_exists(bob_addr), 0); - register(bob); - assert!(coin_store_exists(bob_addr), 0); - maybe_convert_to_fungible_store(bob_addr); - assert!(!coin_store_exists(bob_addr), 0); - register(bob); - assert!(!coin_store_exists(bob_addr), 0); move_to(account, FakeMoneyCapabilities { burn_cap, @@ -1985,7 +1992,7 @@ module aptos_framework::coin { }); } - #[test(account = @aptos_framework, aaron = @0xaa10)] + #[test(account = @aptos_framework)] fun test_migration_with_existing_primary_fungible_store( account: &signer, ) acquires CoinConversionMap, CoinInfo, CoinStore, PairedCoinType { @@ -1998,9 +2005,8 @@ module aptos_framework::coin { assert!(coin_balance(account_addr) == 0, 0); assert!(balance(account_addr) == 100, 0); let coin = withdraw(account, 50); - assert!(!migrated_primary_fungible_store_exists(account_addr, ensure_paired_metadata()), 0); + assert!(can_receive_paired_fungible_asset(account_addr, ensure_paired_metadata()), 0); maybe_convert_to_fungible_store(account_addr); - assert!(migrated_primary_fungible_store_exists(account_addr, ensure_paired_metadata()), 0); deposit(account_addr, coin); assert!(coin_balance(account_addr) == 0, 0); assert!(balance(account_addr) == 100, 0); @@ -2011,4 +2017,9 @@ module aptos_framework::coin { mint_cap, }); } + + #[deprecated] + #[resource_group_member(group = aptos_framework::object::ObjectGroup)] + /// The flag the existence of which indicates the primary fungible store is created by the migration from CoinStore. + struct MigrationFlag has key {} } diff --git a/aptos-move/framework/aptos-framework/sources/coin.spec.move b/aptos-move/framework/aptos-framework/sources/coin.spec.move index 7033b42589b7f..b43c5850ec882 100644 --- a/aptos-move/framework/aptos-framework/sources/coin.spec.move +++ b/aptos-move/framework/aptos-framework/sources/coin.spec.move @@ -161,7 +161,8 @@ spec aptos_framework::coin { spec fun spec_is_account_registered(account_addr: address): bool { let paired_metadata_opt = spec_paired_metadata(); - exists>(account_addr) || (option::spec_is_some( + exists>(account_addr) || features::spec_new_accounts_default_to_fa_apt_store_enabled( + ) || (option::spec_is_some( paired_metadata_opt ) && primary_fungible_store::spec_primary_store_exists(account_addr, option::spec_borrow(paired_metadata_opt))) } diff --git a/aptos-move/framework/cached-packages/src/aptos_framework_sdk_builder.rs b/aptos-move/framework/cached-packages/src/aptos_framework_sdk_builder.rs index 4819248b3e12e..c7fe5a59010e1 100644 --- a/aptos-move/framework/cached-packages/src/aptos_framework_sdk_builder.rs +++ b/aptos-move/framework/cached-packages/src/aptos_framework_sdk_builder.rs @@ -323,6 +323,12 @@ pub enum EntryFunctionCall { coin_type: TypeTag, }, + /// Migrate to fungible store for `CoinType` if not yet. + CoinMigrateCoinStoreToFungibleStore { + coin_type: TypeTag, + accounts: Vec, + }, + /// Voluntarily migrate to fungible store for `CoinType` if not yet. CoinMigrateToFungibleStore { coin_type: TypeTag, @@ -1298,6 +1304,10 @@ impl EntryFunctionCall { } => code_publish_package_txn(metadata_serialized, code), CoinCreateCoinConversionMap {} => coin_create_coin_conversion_map(), CoinCreatePairing { coin_type } => coin_create_pairing(coin_type), + CoinMigrateCoinStoreToFungibleStore { + coin_type, + accounts, + } => coin_migrate_coin_store_to_fungible_store(coin_type, accounts), CoinMigrateToFungibleStore { coin_type } => coin_migrate_to_fungible_store(coin_type), CoinTransfer { coin_type, @@ -2562,6 +2572,25 @@ pub fn coin_create_pairing(coin_type: TypeTag) -> TransactionPayload { )) } +/// Migrate to fungible store for `CoinType` if not yet. +pub fn coin_migrate_coin_store_to_fungible_store( + coin_type: TypeTag, + accounts: Vec, +) -> TransactionPayload { + TransactionPayload::EntryFunction(EntryFunction::new( + ModuleId::new( + AccountAddress::new([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, + ]), + ident_str!("coin").to_owned(), + ), + ident_str!("migrate_coin_store_to_fungible_store").to_owned(), + vec![coin_type], + vec![bcs::to_bytes(&accounts).unwrap()], + )) +} + /// Voluntarily migrate to fungible store for `CoinType` if not yet. pub fn coin_migrate_to_fungible_store(coin_type: TypeTag) -> TransactionPayload { TransactionPayload::EntryFunction(EntryFunction::new( @@ -5398,6 +5427,19 @@ mod decoder { } } + pub fn coin_migrate_coin_store_to_fungible_store( + payload: &TransactionPayload, + ) -> Option { + if let TransactionPayload::EntryFunction(script) = payload { + Some(EntryFunctionCall::CoinMigrateCoinStoreToFungibleStore { + coin_type: script.ty_args().get(0)?.clone(), + accounts: bcs::from_bytes(script.args().get(0)?).ok()?, + }) + } else { + None + } + } + pub fn coin_migrate_to_fungible_store( payload: &TransactionPayload, ) -> Option { @@ -6947,6 +6989,10 @@ static SCRIPT_FUNCTION_DECODER_MAP: once_cell::sync::Lazy + + +
fun spec_new_accounts_default_to_fa_apt_store_enabled(): bool {
+   spec_is_enabled(NEW_ACCOUNTS_DEFAULT_TO_FA_APT_STORE)
+}
+
+ + + + diff --git a/aptos-move/framework/move-stdlib/sources/configs/features.spec.move b/aptos-move/framework/move-stdlib/sources/configs/features.spec.move index 9b8e0c8d4f4ef..7fd386a0bdb2a 100644 --- a/aptos-move/framework/move-stdlib/sources/configs/features.spec.move +++ b/aptos-move/framework/move-stdlib/sources/configs/features.spec.move @@ -96,6 +96,10 @@ spec std::features { spec_is_enabled(ABORT_IF_MULTISIG_PAYLOAD_MISMATCH) } + spec fun spec_new_accounts_default_to_fa_apt_store_enabled(): bool { + spec_is_enabled(NEW_ACCOUNTS_DEFAULT_TO_FA_APT_STORE) + } + spec fun spec_simulation_enhancement_enabled(): bool { spec_is_enabled(TRANSACTION_SIMULATION_ENHANCEMENT) } From 9e5cc9d26ec544a45bd1c0fe0f81dba35b04f403 Mon Sep 17 00:00:00 2001 From: Junkil Park Date: Wed, 4 Dec 2024 18:25:52 -0800 Subject: [PATCH 19/78] Event V2 Translation (#14615) --- api/src/context.rs | 106 +- api/src/tests/event_v2_translation_test.rs | 912 +++++++++++ api/src/tests/mod.rs | 5 +- .../tests/move/pack_token_objects/Move.toml | 10 + .../sources/token_objects.move | 415 +++++ api/src/tests/move/pack_token_v1/Move.toml | 11 + .../move/pack_token_v1/sources/token_v1.move | 123 ++ api/src/transactions.rs | 7 +- api/test-context/src/test_context.rs | 111 ++ .../src/config/internal_indexer_db_config.rs | 16 + crates/aptos-rosetta/src/types/objects.rs | 4 +- .../src/internal_indexer_db_service.rs | 27 +- storage/aptosdb/src/event_store/mod.rs | 3 +- storage/indexer/src/db_indexer.rs | 150 +- storage/indexer/src/event_v2_translator.rs | 1361 +++++++++++++++++ storage/indexer/src/indexer_reader.rs | 33 +- storage/indexer/src/lib.rs | 1 + storage/indexer_schemas/src/metadata.rs | 1 + .../src/schema/event_sequence_number/mod.rs | 53 + .../src/schema/event_sequence_number/test.rs | 19 + storage/indexer_schemas/src/schema/mod.rs | 18 + .../src/schema/translated_v1_event/mod.rs | 66 + .../src/schema/translated_v1_event/test.rs | 20 + .../move-core/types/src/language_storage.rs | 2 + types/src/account_config/events/burn.rs | 73 + types/src/account_config/events/burn_event.rs | 53 + types/src/account_config/events/burn_token.rs | 63 + .../account_config/events/burn_token_event.rs | 53 + .../src/account_config/events/cancel_offer.rs | 74 + types/src/account_config/events/claim.rs | 74 + types/src/account_config/events/coin.rs | 113 -- .../src/account_config/events/coin_deposit.rs | 62 + .../account_config/events/coin_register.rs | 50 + .../events/coin_register_event.rs | 44 + .../account_config/events/coin_withdraw.rs | 62 + .../events/collection_description_mutate.rs | 74 + .../collection_description_mutate_event.rs | 74 + .../events/collection_maximum_mutate.rs | 74 + .../events/collection_maximum_mutate_event.rs | 76 + .../events/collection_mutation.rs | 72 + .../events/collection_mutation_event.rs | 47 + .../events/collection_uri_mutate.rs | 74 + .../events/collection_uri_mutate_event.rs | 74 + .../events/create_collection.rs | 81 + .../events/create_collection_event.rs | 81 + .../events/create_token_data_event.rs | 133 ++ .../events/default_property_mutate.rs | 99 ++ .../events/default_property_mutate_event.rs | 91 ++ .../account_config/events/deposit_event.rs | 49 + .../events/description_mutate.rs | 81 + .../events/description_mutate_event.rs | 81 + .../src/account_config/events/key_rotation.rs | 55 + .../events/key_rotation_event.rs | 56 + .../account_config/events/maximum_mutate.rs | 81 + .../events/maximum_mutate_event.rs | 83 + types/src/account_config/events/mint.rs | 69 + types/src/account_config/events/mint_event.rs | 53 + types/src/account_config/events/mint_token.rs | 63 + .../account_config/events/mint_token_event.rs | 53 + types/src/account_config/events/mod.rs | 114 +- .../events/mutate_property_map.rs | 88 ++ .../events/mutate_token_property_map_event.rs | 80 + types/src/account_config/events/offer.rs | 74 + .../account_config/events/opt_in_transfer.rs | 57 + .../events/opt_in_transfer_event.rs | 48 + .../account_config/events/royalty_mutate.rs | 109 ++ .../events/royalty_mutate_event.rs | 109 ++ .../events/token_cancel_offer_event.rs | 63 + .../events/token_claim_event.rs | 63 + .../events/token_data_creation.rs | 145 ++ .../account_config/events/token_deposit.rs | 76 + .../events/token_deposit_event.rs | 53 + .../account_config/events/token_mutation.rs | 73 + .../events/token_mutation_event.rs | 61 + .../events/token_offer_event.rs | 63 + .../account_config/events/token_withdraw.rs | 63 + .../events/token_withdraw_event.rs | 53 + types/src/account_config/events/transfer.rs | 58 + .../account_config/events/transfer_event.rs | 58 + .../src/account_config/events/uri_mutation.rs | 81 + .../events/uri_mutation_event.rs | 81 + .../account_config/events/withdraw_event.rs | 49 + .../account_config/resources/aggregator.rs | 2 +- types/src/account_config/resources/any.rs | 40 + .../account_config/resources/collection.rs | 65 + .../account_config/resources/collections.rs | 64 + .../account_config/resources/fixed_supply.rs | 64 + types/src/account_config/resources/mod.rs | 19 + types/src/account_config/resources/object.rs | 19 + .../resources/pending_claims.rs | 57 + types/src/account_config/resources/token.rs | 71 + .../resources/token_event_store_v1.rs | 99 ++ .../account_config/resources/token_store.rs | 77 + .../src/account_config/resources/type_info.rs | 20 +- .../resources/unlimited_supply.rs | 57 + types/src/contract_event.rs | 1 + types/src/indexer/indexer_db_reader.rs | 9 +- types/src/utility_coin.rs | 20 + 98 files changed, 8222 insertions(+), 150 deletions(-) create mode 100644 api/src/tests/event_v2_translation_test.rs create mode 100644 api/src/tests/move/pack_token_objects/Move.toml create mode 100644 api/src/tests/move/pack_token_objects/sources/token_objects.move create mode 100644 api/src/tests/move/pack_token_v1/Move.toml create mode 100644 api/src/tests/move/pack_token_v1/sources/token_v1.move create mode 100644 storage/indexer/src/event_v2_translator.rs create mode 100644 storage/indexer_schemas/src/schema/event_sequence_number/mod.rs create mode 100644 storage/indexer_schemas/src/schema/event_sequence_number/test.rs create mode 100644 storage/indexer_schemas/src/schema/translated_v1_event/mod.rs create mode 100644 storage/indexer_schemas/src/schema/translated_v1_event/test.rs create mode 100644 types/src/account_config/events/burn.rs create mode 100644 types/src/account_config/events/burn_event.rs create mode 100644 types/src/account_config/events/burn_token.rs create mode 100644 types/src/account_config/events/burn_token_event.rs create mode 100644 types/src/account_config/events/cancel_offer.rs create mode 100644 types/src/account_config/events/claim.rs delete mode 100644 types/src/account_config/events/coin.rs create mode 100644 types/src/account_config/events/coin_deposit.rs create mode 100644 types/src/account_config/events/coin_register.rs create mode 100644 types/src/account_config/events/coin_register_event.rs create mode 100644 types/src/account_config/events/coin_withdraw.rs create mode 100644 types/src/account_config/events/collection_description_mutate.rs create mode 100644 types/src/account_config/events/collection_description_mutate_event.rs create mode 100644 types/src/account_config/events/collection_maximum_mutate.rs create mode 100644 types/src/account_config/events/collection_maximum_mutate_event.rs create mode 100644 types/src/account_config/events/collection_mutation.rs create mode 100644 types/src/account_config/events/collection_mutation_event.rs create mode 100644 types/src/account_config/events/collection_uri_mutate.rs create mode 100644 types/src/account_config/events/collection_uri_mutate_event.rs create mode 100644 types/src/account_config/events/create_collection.rs create mode 100644 types/src/account_config/events/create_collection_event.rs create mode 100644 types/src/account_config/events/create_token_data_event.rs create mode 100644 types/src/account_config/events/default_property_mutate.rs create mode 100644 types/src/account_config/events/default_property_mutate_event.rs create mode 100644 types/src/account_config/events/deposit_event.rs create mode 100644 types/src/account_config/events/description_mutate.rs create mode 100644 types/src/account_config/events/description_mutate_event.rs create mode 100644 types/src/account_config/events/key_rotation.rs create mode 100644 types/src/account_config/events/key_rotation_event.rs create mode 100644 types/src/account_config/events/maximum_mutate.rs create mode 100644 types/src/account_config/events/maximum_mutate_event.rs create mode 100644 types/src/account_config/events/mint.rs create mode 100644 types/src/account_config/events/mint_event.rs create mode 100644 types/src/account_config/events/mint_token.rs create mode 100644 types/src/account_config/events/mint_token_event.rs create mode 100644 types/src/account_config/events/mutate_property_map.rs create mode 100644 types/src/account_config/events/mutate_token_property_map_event.rs create mode 100644 types/src/account_config/events/offer.rs create mode 100644 types/src/account_config/events/opt_in_transfer.rs create mode 100644 types/src/account_config/events/opt_in_transfer_event.rs create mode 100644 types/src/account_config/events/royalty_mutate.rs create mode 100644 types/src/account_config/events/royalty_mutate_event.rs create mode 100644 types/src/account_config/events/token_cancel_offer_event.rs create mode 100644 types/src/account_config/events/token_claim_event.rs create mode 100644 types/src/account_config/events/token_data_creation.rs create mode 100644 types/src/account_config/events/token_deposit.rs create mode 100644 types/src/account_config/events/token_deposit_event.rs create mode 100644 types/src/account_config/events/token_mutation.rs create mode 100644 types/src/account_config/events/token_mutation_event.rs create mode 100644 types/src/account_config/events/token_offer_event.rs create mode 100644 types/src/account_config/events/token_withdraw.rs create mode 100644 types/src/account_config/events/token_withdraw_event.rs create mode 100644 types/src/account_config/events/transfer.rs create mode 100644 types/src/account_config/events/transfer_event.rs create mode 100644 types/src/account_config/events/uri_mutation.rs create mode 100644 types/src/account_config/events/uri_mutation_event.rs create mode 100644 types/src/account_config/events/withdraw_event.rs create mode 100644 types/src/account_config/resources/any.rs create mode 100644 types/src/account_config/resources/collection.rs create mode 100644 types/src/account_config/resources/collections.rs create mode 100644 types/src/account_config/resources/fixed_supply.rs create mode 100644 types/src/account_config/resources/pending_claims.rs create mode 100644 types/src/account_config/resources/token.rs create mode 100644 types/src/account_config/resources/token_event_store_v1.rs create mode 100644 types/src/account_config/resources/token_store.rs create mode 100644 types/src/account_config/resources/unlimited_supply.rs diff --git a/api/src/context.rs b/api/src/context.rs index e1c6095d19307..bdc96fa74e0a1 100644 --- a/api/src/context.rs +++ b/api/src/context.rs @@ -32,7 +32,7 @@ use aptos_types::{ account_address::AccountAddress, account_config::{AccountResource, NewBlockEvent}, chain_id::ChainId, - contract_event::EventWithVersion, + contract_event::{ContractEvent, ContractEventV1, EventWithVersion}, event::EventKey, indexer::indexer_db_reader::IndexerReader, ledger_info::LedgerInfoWithSignatures, @@ -820,12 +820,16 @@ impl Context { .into_iter() .zip(infos) .enumerate() - .map(|(i, ((txn, txn_output), info))| { - let version = start_version + i as u64; - let (write_set, events, _, _, _) = txn_output.unpack(); - self.get_accumulator_root_hash(version) - .map(|h| (version, txn, info, events, h, write_set).into()) - }) + .map( + |(i, ((txn, txn_output), info))| -> Result { + let version = start_version + i as u64; + let (write_set, events, _, _, _) = txn_output.unpack(); + let h = self.get_accumulator_root_hash(version)?; + let txn: TransactionOnChainData = + (version, txn, info, events, h, write_set).into(); + Ok(self.maybe_translate_v2_to_v1_events(txn)) + }, + ) .collect() } @@ -880,7 +884,10 @@ impl Context { })?; txns.into_inner() .into_iter() - .map(|t| self.convert_into_transaction_on_chain_data(t)) + .map(|t| -> Result { + let txn = self.convert_into_transaction_on_chain_data(t)?; + Ok(self.maybe_translate_v2_to_v1_events(txn)) + }) .collect::>>() .context("Failed to parse account transactions") .map_err(|err| E::internal_with_code(err, AptosErrorCode::InternalError, ledger_info)) @@ -891,10 +898,15 @@ impl Context { hash: HashValue, ledger_version: u64, ) -> Result> { - self.db + if let Some(t) = self + .db .get_transaction_by_hash(hash, ledger_version, true)? - .map(|t| self.convert_into_transaction_on_chain_data(t)) - .transpose() + { + let txn: TransactionOnChainData = self.convert_into_transaction_on_chain_data(t)?; + Ok(Some(self.maybe_translate_v2_to_v1_events(txn))) + } else { + Ok(None) + } } pub async fn get_pending_transaction_by_hash( @@ -917,11 +929,73 @@ impl Context { version: u64, ledger_version: u64, ) -> Result { - self.convert_into_transaction_on_chain_data(self.db.get_transaction_by_version( - version, - ledger_version, - true, - )?) + let txn = self.convert_into_transaction_on_chain_data( + self.db + .get_transaction_by_version(version, ledger_version, true)?, + )?; + Ok(self.maybe_translate_v2_to_v1_events(txn)) + } + + fn maybe_translate_v2_to_v1_events( + &self, + mut txn: TransactionOnChainData, + ) -> TransactionOnChainData { + if self.indexer_reader.is_some() + && self + .node_config + .indexer_db_config + .enable_event_v2_translation + { + self.translate_v2_to_v1_events_for_version(txn.version, &mut txn.events) + .ok(); + } + txn + } + + fn translate_v2_to_v1_events_for_version( + &self, + version: u64, + events: &mut [ContractEvent], + ) -> Result<()> { + for (idx, event) in events.iter_mut().enumerate() { + let translated_event = self + .indexer_reader + .as_ref() + .ok_or(anyhow!("Internal indexer reader doesn't exist"))? + .get_translated_v1_event_by_version_and_index(version, idx as u64); + if let Ok(translated_event) = translated_event { + *event = ContractEvent::V1(translated_event); + } + } + Ok(()) + } + + pub fn translate_v2_to_v1_events_for_simulation( + &self, + events: &mut [ContractEvent], + ) -> Result<()> { + let mut count_map: HashMap = HashMap::new(); + for event in events.iter_mut() { + if let ContractEvent::V2(v2) = event { + let translated_event = self + .indexer_reader + .as_ref() + .ok_or(anyhow!("Internal indexer reader doesn't exist"))? + .translate_event_v2_to_v1(v2)?; + if let Some(v1) = translated_event { + let count = count_map.get(v1.key()).unwrap_or(&0); + let v1_adjusted = ContractEventV1::new( + *v1.key(), + v1.sequence_number() + count, + v1.type_tag().clone(), + v1.event_data().to_vec(), + ); + *event = ContractEvent::V1(v1_adjusted); + count_map.insert(*v1.key(), count + 1); + } + } + } + Ok(()) } pub fn get_accumulator_root_hash(&self, version: u64) -> Result { diff --git a/api/src/tests/event_v2_translation_test.rs b/api/src/tests/event_v2_translation_test.rs new file mode 100644 index 0000000000000..7c8ed0aa4a919 --- /dev/null +++ b/api/src/tests/event_v2_translation_test.rs @@ -0,0 +1,912 @@ +// Copyright © Aptos Foundation +// Parts of the project are originally copyright © Meta Platforms, Inc. +// SPDX-License-Identifier: Apache-2.0 + +use super::{new_test_context, new_test_context_with_db_sharding_and_internal_indexer}; +use aptos_api_test_context::{current_function_name, TestContext}; +use aptos_crypto::{ed25519::Ed25519PrivateKey, SigningKey, ValidCryptoMaterial}; +use aptos_sdk::types::LocalAccount; +use aptos_types::account_config::RotationProofChallenge; +use move_core_types::{account_address::AccountAddress, language_storage::CORE_CODE_ADDRESS}; +use serde_json::{json, Value}; +use std::path::PathBuf; + +static MODULE_EVENT_MIGRATION: u64 = 57; + +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn test_feature_enable_disable() { + let mut context = new_test_context(current_function_name!()); + context.enable_feature(MODULE_EVENT_MIGRATION).await; + assert!(context.is_feature_enabled(MODULE_EVENT_MIGRATION).await); + context.disable_feature(MODULE_EVENT_MIGRATION).await; + assert!(!context.is_feature_enabled(MODULE_EVENT_MIGRATION).await); + context.enable_feature(MODULE_EVENT_MIGRATION).await; + assert!(context.is_feature_enabled(MODULE_EVENT_MIGRATION).await); +} + +#[allow(clippy::cmp_owned)] +fn matches_event_details( + event: &Value, + event_type: &str, + creation_number: u64, + account_address: AccountAddress, + sequence_number: u64, +) -> bool { + event["type"] == event_type + && event["guid"]["creation_number"] == creation_number.to_string() + && event["guid"]["account_address"] == account_address.to_hex_literal() + && event["sequence_number"] == sequence_number.to_string() +} + +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn test_event_v2_translation_coin_deposit_event() { + let context = + &mut new_test_context_with_db_sharding_and_internal_indexer(current_function_name!()); + + // Start with the MODULE_EVENT_MIGRATION feature disabled + context.disable_feature(MODULE_EVENT_MIGRATION).await; + + // Create two accounts + let account1 = &mut context.api_create_account().await; + let account2 = &mut context.api_create_account().await; + + // Transfer coins from account1 to account2, emitting V1 events as the feature is disabled + context + .api_execute_aptos_account_transfer(account2, account1.address(), 101) + .await; + + // Enable the MODULE_EVENT_MIGRATION feature + context.enable_feature(MODULE_EVENT_MIGRATION).await; + + // Check the simulation API outputs the translated V1 event rather than the V2 event as it is + let payload = json!({ + "type": "entry_function_payload", + "function": "0x1::coin::transfer", + "type_arguments": ["0x1::aptos_coin::AptosCoin"], + "arguments": [ + account1.address().to_hex_literal(), "102" + ] + }); + let resp = context.simulate_transaction(account2, payload, 200).await; + + let is_expected_event = |e: &Value| { + matches_event_details(e, "0x1::coin::DepositEvent", 2, account1.address(), 2) + && e["data"]["amount"] == "102" + }; + + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(is_expected_event)); + + // Transfer coins from account2 to account1, emitting V2 events as the feature is enabled + context + .api_execute_aptos_account_transfer(account2, account1.address(), 102) + .await; + + // Check the event_by_creation_number API outputs the translated V1 event + let resp = context + .gen_events_by_creation_num(&account1.address(), 2) + .await; + assert!(is_expected_event(resp.as_array().unwrap().last().unwrap())); + + // Check the event_by_handle API outputs the translated V1 event + let resp = context + .gen_events_by_handle( + &account1.address(), + "0x1::coin::CoinStore%3C0x1::aptos_coin::AptosCoin%3E", + "deposit_events", + ) + .await; + assert!(is_expected_event(resp.as_array().unwrap().last().unwrap())); + + // Check the accounts-transactions API outputs the translated V1 event + let resp = context + .get( + format!( + "/accounts/{}/transactions?limit=1", + account2.address().to_hex_literal() + ) + .as_str(), + ) + .await; + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(is_expected_event)); + let hash = resp[0]["hash"].as_str().unwrap(); + let version = resp[0]["version"].as_str().unwrap(); + + // Check the transactions API outputs the translated V1 event + let resp = context + .get(format!("/transactions?start={}&limit=1", version).as_str()) + .await; + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(is_expected_event)); + + // Check the transactions_by_hash API outputs the translated V1 event + let resp = context + .get(format!("/transactions/by_hash/{}", hash).as_str()) + .await; + assert!(resp["events"] + .as_array() + .unwrap() + .iter() + .any(is_expected_event)); + + // Check the transactions_by_version API outputs the translated V1 event + let resp = context + .get(format!("/transactions/by_version/{}", version).as_str()) + .await; + assert!(resp["events"] + .as_array() + .unwrap() + .iter() + .any(is_expected_event)); +} + +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn test_event_v2_translation_coin_withdraw_event() { + let context = + &mut new_test_context_with_db_sharding_and_internal_indexer(current_function_name!()); + + // Start with the MODULE_EVENT_MIGRATION feature disabled + context.disable_feature(MODULE_EVENT_MIGRATION).await; + + // Create two accounts + let account1 = &mut context.api_create_account().await; + let account2 = &mut context.api_create_account().await; + + // Transfer coins from account1 to account2, emitting V1 events as the feature is disabled + context + .api_execute_aptos_account_transfer(account2, account1.address(), 101) + .await; + + // Enable the MODULE_EVENT_MIGRATION feature + context.enable_feature(MODULE_EVENT_MIGRATION).await; + + // Check the simulation API outputs the translated V1 event rather than the V2 event as it is + let payload = json!({ + "type": "entry_function_payload", + "function": "0x1::coin::transfer", + "type_arguments": ["0x1::aptos_coin::AptosCoin"], + "arguments": [ + account1.address().to_hex_literal(), "102" + ] + }); + let resp = context.simulate_transaction(account2, payload, 200).await; + let address2_address = account2.address(); + let is_expected_event = |e: &Value| { + matches_event_details(e, "0x1::coin::WithdrawEvent", 3, address2_address, 1) + && e["data"]["amount"] == "102" + }; + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(is_expected_event)); + + // Transfer coins from account2 to account1, emitting V2 events as the feature is enabled + context + .api_execute_aptos_account_transfer(account2, account1.address(), 102) + .await; + + // Check the event_by_creation_number API outputs the translated V1 event + let resp = context + .gen_events_by_creation_num(&account2.address(), 3) + .await; + assert!(is_expected_event(resp.as_array().unwrap().last().unwrap())); + + // Check the event_by_handle API outputs the translated V1 event + let resp = context + .gen_events_by_handle( + &account2.address(), + "0x1::coin::CoinStore%3C0x1::aptos_coin::AptosCoin%3E", + "withdraw_events", + ) + .await; + assert!(is_expected_event(resp.as_array().unwrap().last().unwrap())); + + // Check the accounts-transactions API outputs the translated V1 event + let resp = context + .get( + format!( + "/accounts/{}/transactions?limit=1", + account2.address().to_hex_literal() + ) + .as_str(), + ) + .await; + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(is_expected_event)); + let hash = resp[0]["hash"].as_str().unwrap(); + let version = resp[0]["version"].as_str().unwrap(); + + // Check the transactions API outputs the translated V1 event + let resp = context + .get(format!("/transactions?start={}&limit=1", version).as_str()) + .await; + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(is_expected_event)); + + // Check the transactions_by_hash API outputs the translated V1 event + let resp = context + .get(format!("/transactions/by_hash/{}", hash).as_str()) + .await; + assert!(resp["events"] + .as_array() + .unwrap() + .iter() + .any(is_expected_event)); + + // Check the transactions_by_version API outputs the translated V1 event + let resp = context + .get(format!("/transactions/by_version/{}", version).as_str()) + .await; + assert!(resp["events"] + .as_array() + .unwrap() + .iter() + .any(is_expected_event)); +} + +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn test_event_v2_translation_account_coin_register_event() { + let context = + &mut new_test_context_with_db_sharding_and_internal_indexer(current_function_name!()); + + // Make sure that the MODULE_EVENT_MIGRATION feature is enabled + context.enable_feature(MODULE_EVENT_MIGRATION).await; + + // Create two accounts + let account1 = &mut context.api_create_account().await; + let account2 = &mut context.gen_account(); + + let is_expected_event = |e: &Value| { + matches_event_details( + e, + "0x1::account::CoinRegisterEvent", + 0, + account2.address(), + 0, + ) && e["data"]["type_info"]["struct_name"] + == format!("0x{}", hex::encode("AptosCoin".to_string().as_bytes())) + }; + + // Transfer coins from account2 to account1, emitting V2 events as the feature is enabled + context + .api_execute_aptos_account_transfer(account1, account2.address(), 102) + .await; + + // Check the event_by_creation_number API outputs the translated V1 event + let resp = context + .gen_events_by_creation_num(&account2.address(), 0) + .await; + assert!(is_expected_event(resp.as_array().unwrap().last().unwrap())); + + // Check the event_by_handle API outputs the translated V1 event + let resp = context + .gen_events_by_handle( + &account2.address(), + "0x1::account::Account", + "coin_register_events", + ) + .await; + assert!(is_expected_event(resp.as_array().unwrap().last().unwrap())); + + // Check the accounts-transactions API outputs the translated V1 event + let resp = context + .get( + format!( + "/accounts/{}/transactions?limit=1", + account1.address().to_hex_literal() + ) + .as_str(), + ) + .await; + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(is_expected_event)); + let hash = resp[0]["hash"].as_str().unwrap(); + let version = resp[0]["version"].as_str().unwrap(); + + // Check the transactions API outputs the translated V1 event + let resp = context + .get(format!("/transactions?start={}&limit=1", version).as_str()) + .await; + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(is_expected_event)); + + // Check the transactions_by_hash API outputs the translated V1 event + let resp = context + .get(format!("/transactions/by_hash/{}", hash).as_str()) + .await; + assert!(resp["events"] + .as_array() + .unwrap() + .iter() + .any(is_expected_event)); + + // Check the transactions_by_version API outputs the translated V1 event + let resp = context + .get(format!("/transactions/by_version/{}", version).as_str()) + .await; + assert!(resp["events"] + .as_array() + .unwrap() + .iter() + .any(is_expected_event)); +} + +fn rotate_authentication_key_payload( + account: &LocalAccount, + new_private_key: &Ed25519PrivateKey, + new_public_key_bytes: Vec, +) -> Value { + let from_scheme = 0; + let to_scheme = 0; + + // Construct a proof challenge struct that proves that + // the user intends to rotate their auth key. + let rotation_proof = RotationProofChallenge { + account_address: CORE_CODE_ADDRESS, + module_name: String::from("account"), + struct_name: String::from("RotationProofChallenge"), + sequence_number: account.sequence_number(), + originator: account.address(), + current_auth_key: AccountAddress::from_bytes(account.authentication_key()).unwrap(), + new_public_key: new_public_key_bytes.clone(), + }; + + let rotation_msg = bcs::to_bytes(&rotation_proof).unwrap(); + + // Sign the rotation message by the current private key and the new private key. + let signature_by_curr_privkey = account.private_key().sign_arbitrary_message(&rotation_msg); + let signature_by_new_privkey = new_private_key.sign_arbitrary_message(&rotation_msg); + + json!({ + "type": "entry_function_payload", + "function": "0x1::account::rotate_authentication_key", + "type_arguments": [], + "arguments": [ + from_scheme, + hex::encode(account.public_key().to_bytes()), + to_scheme, + hex::encode(new_public_key_bytes), + hex::encode(signature_by_curr_privkey.to_bytes()), + hex::encode(signature_by_new_privkey.to_bytes()), + ] + }) +} + +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn test_event_v2_translation_account_key_rotation_event() { + let context = + &mut new_test_context_with_db_sharding_and_internal_indexer(current_function_name!()); + + // Make sure that the MODULE_EVENT_MIGRATION feature is enabled + context.enable_feature(MODULE_EVENT_MIGRATION).await; + + // Create two accounts + let account1 = &mut context.api_create_account().await; + let account2 = &mut context.gen_account(); + + // Check the simulation API outputs the translated V1 event rather than the V2 event as it is + let payload = rotate_authentication_key_payload( + account1, + account2.private_key(), + account2.public_key().to_bytes().to_vec(), + ); + let resp = context + .simulate_transaction(account1, payload.clone(), 200) + .await; + + let account1_address = account1.address(); + let account1_authentication_key = account1.authentication_key(); + let is_expected_event = |e: &Value| { + matches_event_details(e, "0x1::account::KeyRotationEvent", 1, account1_address, 0) + && e["data"]["old_authentication_key"] + == format!("0x{}", hex::encode(account1_authentication_key.to_bytes())) + && e["data"]["new_authentication_key"] + == format!( + "0x{}", + hex::encode(account2.authentication_key().to_bytes()) + ) + }; + + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(is_expected_event)); + + // Rotate authentication key, emitting V2 events as the feature is enabled + context.api_execute_txn(account1, payload).await; + context.wait_for_internal_indexer_caught_up().await; + + // Check the event_by_creation_number API outputs the translated V1 event + let resp = context + .gen_events_by_creation_num(&account1.address(), 1) + .await; + assert!(resp.as_array().unwrap().iter().any(is_expected_event)); + + // Check the event_by_handle API outputs the translated V1 event + let resp = context + .gen_events_by_handle( + &account1.address(), + "0x1::account::Account", + "key_rotation_events", + ) + .await; + assert!(resp.as_array().unwrap().iter().any(is_expected_event)); + + // Check the accounts-transactions API outputs the translated V1 event + let resp = context + .get( + format!( + "/accounts/{}/transactions?limit=1", + account1.address().to_hex_literal() + ) + .as_str(), + ) + .await; + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(is_expected_event)); + let hash = resp[0]["hash"].as_str().unwrap(); + let version = resp[0]["version"].as_str().unwrap(); + + // Check the transactions API outputs the translated V1 event + let resp = context + .get(format!("/transactions?start={}&limit=1", version).as_str()) + .await; + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(is_expected_event)); + + // Check the transactions_by_hash API outputs the translated V1 event + let resp = context + .get(format!("/transactions/by_hash/{}", hash).as_str()) + .await; + assert!(resp["events"] + .as_array() + .unwrap() + .iter() + .any(is_expected_event)); + + // Check the transactions_by_version API outputs the translated V1 event + let resp = context + .get(format!("/transactions/by_version/{}", version).as_str()) + .await; + assert!(resp["events"] + .as_array() + .unwrap() + .iter() + .any(is_expected_event)); +} + +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn test_event_v2_translation_token_objects() { + let context = + &mut new_test_context_with_db_sharding_and_internal_indexer(current_function_name!()); + + // Make sure that the MODULE_EVENT_MIGRATION feature is enabled + context.enable_feature(MODULE_EVENT_MIGRATION).await; + + // Create two accounts + let creator = &mut context.api_create_account().await; + let user = &mut context.api_create_account().await; + + let creator_addr = creator.address(); + let user_addr = user.address(); + + let named_addresses = vec![("addr".to_string(), creator_addr)]; + let txn = futures::executor::block_on(async move { + let path = PathBuf::from(std::env!("CARGO_MANIFEST_DIR")) + .join("src/tests/move/pack_token_objects"); + TestContext::build_package(path, named_addresses) + }); + context.publish_package(creator, txn).await; + context.wait_for_internal_indexer_caught_up().await; + + let payload = json!({ + "type": "entry_function_payload", + "function": format!("{}::token_objects::run", creator_addr.to_hex_literal()), + "type_arguments": [], + "arguments": [ + user_addr.to_hex_literal() + ] + }); + context.api_execute_txn(creator, payload).await; + context.wait_for_internal_indexer_caught_up().await; + let resp = context + .get( + format!( + "/accounts/{}/transactions?limit=1", + creator_addr.to_hex_literal() + ) + .as_str(), + ) + .await; + + // Test TransferTranslator + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(|e: &Value| { + e["type"] == "0x1::object::TransferEvent" + && e["sequence_number"] == "0" + && e["data"]["from"] == creator_addr.to_hex_literal() + && e["data"]["to"] == user_addr.to_hex_literal() + })); + + // Test TokenMutationTranslator + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(|e: &Value| { + e["type"] == "0x4::token::MutationEvent" + && e["sequence_number"] == "0" + && e["data"]["mutated_field_name"] == *"uri" + })); + + // Test CollectionMutationTranslator + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(|e: &Value| { + e["type"] == "0x4::collection::MutationEvent" + && e["sequence_number"] == "0" + && e["data"]["mutated_field_name"] == *"uri" + })); + + // Test MintTranslator + // The example Move package uses ConcurrentSupply which doesn't have the mint event handle. + // So, the mint event is not translated in this case. + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(|e: &Value| { + e["type"] == "0x4::collection::Mint" + && e["guid"]["account_address"] == *"0x0" + && e["sequence_number"] == "0" + })); + // The cases with FixedSupply and UnlimitedSupply have been tested in the localnet. + // In those cases, the mint event is translated correctly as follows: + // Object { + // "guid": Object { + // "creation_number": String("1125899906842626"), + // "account_address": String("0x999a601c1abf720ccb54acae160a980f9a35209611a12b1e31e091172ed061fc"), + // }, + // "sequence_number": String("0"), + // "type": String("0x4::collection::MintEvent"), + // "data": Object { + // "index": String("1"), + // "token": String("0x7dbdec16c12211da2db477a15941df2495218ceb6c221da7bd3efcb93d75cffe"), + // }, + // }, + + let payload = json!({ + "type": "entry_function_payload", + "function": format!("{}::token_objects::burn", creator_addr.to_hex_literal()), + "type_arguments": [], + "arguments": [ + "0x7dbdec16c12211da2db477a15941df2495218ceb6c221da7bd3efcb93d75cffe" + ] + }); + context.api_execute_txn(creator, payload).await; + context.wait_for_internal_indexer_caught_up().await; + let resp = context + .get( + format!( + "/accounts/{}/transactions?limit=1", + creator_addr.to_hex_literal() + ) + .as_str(), + ) + .await; + + // Test BurnTranslator + // The example Move package uses ConcurrentSupply which doesn't have the burn event handle. + // So, the burn event is not translated in this case. + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(|e: &Value| { + e["type"] == "0x4::collection::Burn" + && e["guid"]["account_address"] == *"0x0" + && e["sequence_number"] == "0" + })); + // The cases with FixedSupply and UnlimitedSupply have been tested in the localnet. + // In those cases, the burn event is translated correctly as follows: + // Object { + // "guid": Object { + // "creation_number": String("1125899906842625"), + // "account_address": String("0x999a601c1abf720ccb54acae160a980f9a35209611a12b1e31e091172ed061fc"), + // }, + // "sequence_number": String("0"), + // "type": String("0x4::collection::BurnEvent"), + // "data": Object { + // "index": String("1"), + // "token": String("0x7dbdec16c12211da2db477a15941df2495218ceb6c221da7bd3efcb93d75cffe"), + // }, + // }, +} + +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn test_event_v2_translation_token_v1() { + let context = + &mut new_test_context_with_db_sharding_and_internal_indexer(current_function_name!()); + + // Make sure that the MODULE_EVENT_MIGRATION feature is enabled + context.enable_feature(MODULE_EVENT_MIGRATION).await; + + // Create two accounts + let creator = &mut context.api_create_account().await; + // let user = &mut context.api_create_account().await; + + let creator_addr = creator.address(); + // let user_addr = user.address(); + + let named_addresses = vec![("addr".to_string(), creator_addr)]; + let txn = futures::executor::block_on(async move { + let path = + PathBuf::from(std::env!("CARGO_MANIFEST_DIR")).join("src/tests/move/pack_token_v1"); + TestContext::build_package(path, named_addresses) + }); + context.publish_package(creator, txn).await; + context.wait_for_internal_indexer_caught_up().await; + + let payload = json!({ + "type": "entry_function_payload", + "function": format!("{}::token_v1::run", creator_addr.to_hex_literal()), + "type_arguments": [], + "arguments": [ + ] + }); + context.api_execute_txn(creator, payload).await; + context.wait_for_internal_indexer_caught_up().await; + let resp = context + .get( + format!( + "/accounts/{}/transactions?limit=1", + creator_addr.to_hex_literal() + ) + .as_str(), + ) + .await; + + // Test TokenDepositTranslator + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(|e: &Value| { + e["type"] == "0x3::token::DepositEvent" + && e["sequence_number"] == "4" + && e["data"]["id"]["token_data_id"]["creator"] == creator_addr.to_hex_literal() + })); + + // Test TokenWithdrawTranslator + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(|e: &Value| { + e["type"] == "0x3::token::WithdrawEvent" + && e["sequence_number"] == "4" + && e["data"]["id"]["token_data_id"]["creator"] == creator_addr.to_hex_literal() + })); + + // Test BurnTokenTranslator + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(|e: &Value| { + e["type"] == "0x3::token::BurnTokenEvent" + && e["sequence_number"] == "0" + && e["data"]["id"]["token_data_id"]["creator"] == creator_addr.to_hex_literal() + })); + + // Test MutatePropertyMapTranslator + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(|e: &Value| { + e["type"] == "0x3::token::MutateTokenPropertyMapEvent" + && e["sequence_number"] == "0" + && e["data"]["new_id"]["property_version"] == "1" + })); + + // Test MintTokenTranslator + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(|e: &Value| { + e["type"] == "0x3::token::MintTokenEvent" + && e["sequence_number"] == "0" + && e["data"]["amount"] == "10" + })); + + // Test CreateCollectionTranslator + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(|e: &Value| { + e["type"] == "0x3::token::CreateCollectionEvent" + && e["sequence_number"] == "0" + && e["data"]["creator"] == creator_addr.to_hex_literal() + })); + + // Test TokenDataCreationTranslator + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(|e: &Value| { + e["type"] == "0x3::token::CreateTokenDataEvent" + && e["sequence_number"] == "0" + && e["data"]["name"] == "Token 1" + })); + + // Test OfferTranslator + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(|e: &Value| { + e["type"] == "0x3::token_transfers::TokenOfferEvent" + && e["sequence_number"] == "1" + && e["data"]["amount"] == "1" + })); + + // Test CancelOfferTranslator + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(|e: &Value| { + e["type"] == "0x3::token_transfers::TokenCancelOfferEvent" + && e["sequence_number"] == "0" + && e["data"]["amount"] == "1" + })); + + // Test ClaimTranslator + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(|e: &Value| { + e["type"] == "0x3::token_transfers::TokenClaimEvent" + && e["sequence_number"] == "0" + && e["data"]["amount"] == "1" + })); + + // Test CollectionDescriptionMutateTranslator + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(|e: &Value| { + e["type"] == "0x3::token_event_store::CollectionDescriptionMutateEvent" + && e["sequence_number"] == "0" + && e["data"]["creator_addr"] == creator_addr.to_hex_literal() + })); + + // Test CollectionUriMutateTranslator + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(|e: &Value| { + e["type"] == "0x3::token_event_store::CollectionUriMutateEvent" + && e["sequence_number"] == "0" + && e["data"]["creator_addr"] == creator_addr.to_hex_literal() + })); + + // Test CollectionMaximumMutateTranslator + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(|e: &Value| { + e["type"] == "0x3::token_event_store::CollectionMaxiumMutateEvent" + && e["sequence_number"] == "0" + && e["data"]["creator_addr"] == creator_addr.to_hex_literal() + })); + + // Test UriMutationTranslator + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(|e: &Value| { + e["type"] == "0x3::token_event_store::UriMutationEvent" + && e["sequence_number"] == "0" + && e["data"]["creator"] == creator_addr.to_hex_literal() + })); + + // Test DefaultPropertyMutateTranslator + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(|e: &Value| { + e["type"] == "0x3::token_event_store::DefaultPropertyMutateEvent" + && e["sequence_number"] == "0" + && e["data"]["creator"] == creator_addr.to_hex_literal() + })); + + // Test DescriptionMutateTranslator + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(|e: &Value| { + e["type"] == "0x3::token_event_store::DescriptionMutateEvent" + && e["sequence_number"] == "0" + && e["data"]["creator"] == creator_addr.to_hex_literal() + })); + + // Test RoyaltyMutateTranslator + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(|e: &Value| { + e["type"] == "0x3::token_event_store::RoyaltyMutateEvent" + && e["sequence_number"] == "0" + && e["data"]["creator"] == creator_addr.to_hex_literal() + })); + + // Test MaximumMutateTranslator + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(|e: &Value| { + e["type"] == "0x3::token_event_store::MaxiumMutateEvent" + && e["sequence_number"] == "0" + && e["data"]["creator"] == creator_addr.to_hex_literal() + })); + + // Test OptInTransferTranslator + assert!(resp[0]["events"] + .as_array() + .unwrap() + .iter() + .any(|e: &Value| { + e["type"] == "0x3::token_event_store::OptInTransferEvent" + && e["sequence_number"] == "0" + && e["data"]["opt_in"] == Value::Bool(true) + })); +} diff --git a/api/src/tests/mod.rs b/api/src/tests/mod.rs index 340721b1ce200..43468220043b8 100644 --- a/api/src/tests/mod.rs +++ b/api/src/tests/mod.rs @@ -5,6 +5,7 @@ mod accounts_test; mod blocks_test; mod converter_test; +mod event_v2_translation_test; mod events_test; mod index_test; mod invalid_post_request_test; @@ -36,7 +37,7 @@ fn new_test_context_with_config(test_name: String, node_config: NodeConfig) -> T fn new_test_context_with_db_sharding_and_internal_indexer(test_name: String) -> TestContext { let mut node_config = NodeConfig::default(); node_config.storage.rocksdb_configs.enable_storage_sharding = true; - node_config.indexer_db_config = InternalIndexerDBConfig::new(true, true, true, 10); + node_config.indexer_db_config = InternalIndexerDBConfig::new(true, true, true, 0, true, 10); let test_context = super_new_test_context(test_name, node_config, false, None); let _ = test_context .get_indexer_reader() @@ -51,6 +52,6 @@ fn new_test_context_with_sharding_and_delayed_internal_indexer( ) -> TestContext { let mut node_config = NodeConfig::default(); node_config.storage.rocksdb_configs.enable_storage_sharding = true; - node_config.indexer_db_config = InternalIndexerDBConfig::new(true, true, true, 1); + node_config.indexer_db_config = InternalIndexerDBConfig::new(true, true, true, 0, true, 1); super_new_test_context(test_name, node_config, false, end_version) } diff --git a/api/src/tests/move/pack_token_objects/Move.toml b/api/src/tests/move/pack_token_objects/Move.toml new file mode 100644 index 0000000000000..dc432ee0a11ad --- /dev/null +++ b/api/src/tests/move/pack_token_objects/Move.toml @@ -0,0 +1,10 @@ +[package] +name = "pack_token_objects" +version = "0.0.0" + +[dependencies] +AptosFramework = { local = "../../../../../aptos-move/framework/aptos-framework" } +AptosTokenObjects = { local = "../../../../../aptos-move/framework/aptos-token-objects" } + +[addresses] +addr = "_" diff --git a/api/src/tests/move/pack_token_objects/sources/token_objects.move b/api/src/tests/move/pack_token_objects/sources/token_objects.move new file mode 100644 index 0000000000000..5e20f844f3282 --- /dev/null +++ b/api/src/tests/move/pack_token_objects/sources/token_objects.move @@ -0,0 +1,415 @@ +module addr::token_objects { + use std::error; + use std::option; + use std::string::{Self, String}; + use std::signer; + + use aptos_framework::object::{Self, Object}; + use aptos_token_objects::collection; + use aptos_token_objects::token; + use aptos_token_objects::property_map; + use aptos_framework::event; + use aptos_std::string_utils::{to_string}; + + /// The token does not exist + const ETOKEN_DOES_NOT_EXIST: u64 = 1; + /// The provided signer is not the creator + const ENOT_CREATOR: u64 = 2; + /// Attempted to mutate an immutable field + const EFIELD_NOT_MUTABLE: u64 = 3; + /// Attempted to burn a non-burnable token + const ETOKEN_NOT_BURNABLE: u64 = 4; + /// Attempted to mutate a property map that is not mutable + const EPROPERTIES_NOT_MUTABLE: u64 = 5; + // The collection does not exist + const ECOLLECTION_DOES_NOT_EXIST: u64 = 6; + + /// The ambassador token collection name + const COLLECTION_NAME: vector = b"Ambassador Collection Name"; + /// The ambassador token collection description + const COLLECTION_DESCRIPTION: vector = b"Ambassador Collection Description"; + /// The ambassador token collection URI + const COLLECTION_URI: vector = b"Ambassador Collection URI"; + + /// The ambassador rank + const RANK_GOLD: vector = b"Gold"; + const RANK_SILVER: vector = b"Silver"; + const RANK_BRONZE: vector = b"Bronze"; + + #[resource_group_member(group = aptos_framework::object::ObjectGroup)] + /// The ambassador token + struct AmbassadorToken has key { + /// Used to mutate the token uri + mutator_ref: token::MutatorRef, + /// Used to burn. + burn_ref: token::BurnRef, + /// Used to mutate properties + property_mutator_ref: property_map::MutatorRef, + /// the base URI of the token + base_uri: String, + } + + #[resource_group_member(group = aptos_framework::object::ObjectGroup)] + /// The ambassador level + struct AmbassadorLevel has key { + ambassador_level: u64, + } + + #[event] + /// The ambassador level update event + struct LevelUpdate has drop, store { + token: Object, + old_level: u64, + new_level: u64, + } + + #[view] + /// Returns the ambassador level of the token + public fun ambassador_level(token: Object): u64 acquires AmbassadorLevel { + let ambassador_level = borrow_global(object::object_address(&token)); + ambassador_level.ambassador_level + } + + #[view] + /// Returns the ambassador rank of the token + public fun ambassador_rank(token: Object): String { + property_map::read_string(&token, &string::utf8(b"Rank")) + } + + #[view] + /// Returns the ambassador level of the token of the address + public fun ambassador_level_from_address(addr: address): u64 acquires AmbassadorLevel { + let token = object::address_to_object(addr); + ambassador_level(token) + } + + #[view] + /// Returns the ambassador rank of the token of the address + public fun ambassador_rank_from_address(addr: address): String { + let token = object::address_to_object(addr); + ambassador_rank(token) + } + + /// Creates the ambassador collection. This function creates a collection with unlimited supply using + /// the module constants for description, name, and URI, defined above. The collection will not have + /// any royalty configuration because the tokens in this collection will not be transferred or sold. + fun create_ambassador_collection(creator: &signer) { + // Constructs the strings from the bytes. + let description = string::utf8(COLLECTION_DESCRIPTION); + let name = string::utf8(COLLECTION_NAME); + let uri = string::utf8(COLLECTION_URI); + + // Creates the collection with unlimited supply and without establishing any royalty configuration. + + // let constructor_ref = collection::create_unlimited_collection( + let constructor_ref = collection::create_unlimited_collection( + creator, + description, + name, + option::none(), + uri, + ); + + let mutator_ref = collection::generate_mutator_ref(&constructor_ref); + collection::set_uri(&mutator_ref, string::utf8(b"Ambassador Collection URI 2")); + } + + /// Mints an ambassador token. This function mints a new ambassador token and transfers it to the + /// `soul_bound_to` address. The token is minted with level 0 and rank Bronze. + public entry fun mint_ambassador_token( + creator: &signer, + description: String, + name: String, + base_uri: String, + soul_bound_to: address, + ) { + mint_ambassador_token_impl(creator, description, name, base_uri, soul_bound_to, false); + } + + /// Mints an ambassador token. This function mints a new ambassador token and transfers it to the + /// `soul_bound_to` address. The token is minted with level 0 and rank Bronze. + public entry fun mint_numbered_ambassador_token( + creator: &signer, + description: String, + name: String, + base_uri: String, + soul_bound_to: address, + ) { + mint_ambassador_token_impl(creator, description, name, base_uri, soul_bound_to, true); + } + + /// Function used for benchmarking. + /// Uses multisig to mint to user, with creator permissions. + /// Uses users address as unique name of the soulbound token. + public entry fun mint_ambassador_token_by_user( + user: &signer, + creator: &signer, + description: String, + uri: String, + ) { + let user_addr = signer::address_of(user); + mint_ambassador_token(creator, description, to_string
(&user_addr), uri, user_addr); + } + + /// Function used for benchmarking. + /// Uses multisig to mint to user, with creator permissions. + public entry fun mint_numbered_ambassador_token_by_user( + user: &signer, + creator: &signer, + description: String, + name: String, + uri: String, + ) { + mint_numbered_ambassador_token(creator, description, name, uri, signer::address_of(user)); + } + + /// Mints an ambassador token. This function mints a new ambassador token and transfers it to the + /// `soul_bound_to` address. The token is minted with level 0 and rank Bronze. + fun mint_ambassador_token_impl( + creator: &signer, + description: String, + name: String, + base_uri: String, + soul_bound_to: address, + numbered: bool, + ) { + // The collection name is used to locate the collection object and to create a new token object. + let collection = string::utf8(COLLECTION_NAME); + // Creates the ambassador token, and get the constructor ref of the token. The constructor ref + // is used to generate the refs of the token. + let uri = base_uri; + string::append(&mut uri, string::utf8(RANK_BRONZE)); + let constructor_ref = if (numbered) { + token::create_numbered_token( + creator, + collection, + description, + name, + string::utf8(b""), + option::none(), + uri, + ) + } else { + token::create_named_token( + creator, + collection, + description, + name, + option::none(), + uri, + ) + }; + + // Generates the object signer and the refs. The object signer is used to publish a resource + // (e.g., AmbassadorLevel) under the token object address. The refs are used to manage the token. + let object_signer = object::generate_signer(&constructor_ref); + let transfer_ref = object::generate_transfer_ref(&constructor_ref); + let mutator_ref = token::generate_mutator_ref(&constructor_ref); + let burn_ref = token::generate_burn_ref(&constructor_ref); + let property_mutator_ref = property_map::generate_mutator_ref(&constructor_ref); + + // Transfers the token to the `soul_bound_to` address + let linear_transfer_ref = object::generate_linear_transfer_ref(&transfer_ref); + object::transfer_with_ref(linear_transfer_ref, soul_bound_to); + + // Disables ungated transfer, thus making the token soulbound and non-transferable + object::disable_ungated_transfer(&transfer_ref); + + // Initializes the ambassador level as 0 + move_to(&object_signer, AmbassadorLevel { ambassador_level: 0 }); + + // Initialize the property map and the ambassador rank as Bronze + let properties = property_map::prepare_input(vector[], vector[], vector[]); + property_map::init(&constructor_ref, properties); + property_map::add_typed( + &property_mutator_ref, + string::utf8(b"Rank"), + string::utf8(RANK_BRONZE) + ); + + // Publishes the AmbassadorToken resource with the refs. + let ambassador_token = AmbassadorToken { + mutator_ref, + burn_ref, + property_mutator_ref, + base_uri + }; + move_to(&object_signer, ambassador_token); + } + + /// Burns an ambassador token. This function burns the ambassador token and destroys the + /// AmbassadorToken resource, AmbassadorLevel resource, the event handle, and the property map. + public entry fun burn(creator: &signer, token: Object) acquires AmbassadorToken, AmbassadorLevel { + authorize_creator(creator, &token); + let ambassador_token = move_from(object::object_address(&token)); + let AmbassadorToken { + mutator_ref: _, + burn_ref, + property_mutator_ref, + base_uri: _ + } = ambassador_token; + + let AmbassadorLevel { + ambassador_level: _ + } = move_from(object::object_address(&token)); + + property_map::burn(property_mutator_ref); + token::burn(burn_ref); + } + + /// Function used for benchmarking. + /// Uses multisig to mint to user, with creator permissions. + /// Uses users address as unique name of the soulbound token. + /// Burns token that was minted by mint_ambassador_token_by_user + public entry fun burn_named_by_user(user: &signer, creator: &signer) acquires AmbassadorToken, AmbassadorLevel { + let collection_name = string::utf8(COLLECTION_NAME); + let token_address = token::create_token_address( + &signer::address_of(creator), + &collection_name, + &to_string
(&signer::address_of(user)), + ); + let token = object::address_to_object(token_address); + burn(creator, token); + } + + /// Sets the ambassador level of the token. Only the creator of the token can set the level. When the level + /// is updated, the `LevelUpdate` is emitted. The ambassador rank is updated based on the new level. + public entry fun set_ambassador_level( + creator: &signer, + token: Object, + new_ambassador_level: u64 + ) acquires AmbassadorLevel, AmbassadorToken { + // Asserts that `creator` is the creator of the token. + authorize_creator(creator, &token); + + let token_address = object::object_address(&token); + let ambassador_level = borrow_global_mut(token_address); + // Emits the `LevelUpdate`. + event::emit( + LevelUpdate { + token, + old_level: ambassador_level.ambassador_level, + new_level: new_ambassador_level, + } + ); + // Updates the ambassador level. + ambassador_level.ambassador_level = new_ambassador_level; + // Updates the ambassador rank based on the new level. + update_ambassador_rank(token, new_ambassador_level); + } + + /// Updates the ambassador rank of the token based on the new level + fun update_ambassador_rank( + token: Object, + new_ambassador_level: u64 + ) acquires AmbassadorToken { + // `new_rank` is determined based on the new level. + let new_rank = if (new_ambassador_level < 10) { + RANK_BRONZE + } else if (new_ambassador_level < 20) { + RANK_SILVER + } else { + RANK_GOLD + }; + + let token_address = object::object_address(&token); + let ambassador_token = borrow_global(token_address); + // Gets `property_mutator_ref` to update the rank in the property map. + let property_mutator_ref = &ambassador_token.property_mutator_ref; + // Updates the rank in the property map. + property_map::update_typed(property_mutator_ref, &string::utf8(b"Rank"), string::utf8(new_rank)); + // Updates the token URI based on the new rank. + let uri = ambassador_token.base_uri; + string::append(&mut uri, string::utf8(new_rank)); + token::set_uri(&ambassador_token.mutator_ref, uri); + } + + /// Authorizes the creator of the token. Asserts that the token exists and the creator of the token + /// is `creator`. + inline fun authorize_creator(creator: &signer, token: &Object) { + let token_address = object::object_address(token); + assert!( + exists(token_address), + error::not_found(ETOKEN_DOES_NOT_EXIST), + ); + assert!( + token::creator(*token) == signer::address_of(creator), + error::permission_denied(ENOT_CREATOR), + ); + } + + public entry fun run(creator: &signer, user_addr: address) acquires AmbassadorToken, AmbassadorLevel { + // ------------------------------------------ + // Creator creates the Ambassador Collection. + // ------------------------------------------ + create_ambassador_collection(creator); + + // ------------------------------------------- + // Creator mints a Ambassador token for User1. + // ------------------------------------------- + let token_name = string::utf8(b"Ambassador Token #1"); + let token_description = string::utf8(b"Ambassador Token #1 Description"); + let token_uri = string::utf8(b"Ambassador Token #1 URI/"); + // Creates the Ambassador token for User1. + mint_ambassador_token( + creator, + token_description, + token_name, + token_uri, + user_addr, + ); + let collection_name = string::utf8(COLLECTION_NAME); + let token_address = token::create_token_address( + &signer::address_of(creator), + &collection_name, + &token_name + ); + let token = object::address_to_object(token_address); + // Asserts that the owner of the token is User1. + assert!(object::owner(token) == user_addr, 1); + + // ----------------------- + // Creator sets the level. + // ----------------------- + // Asserts that the initial level of the token is 0. + assert!(ambassador_level(token) == 0, 2); + // Asserts that the initial rank of the token is "Bronze". + assert!(ambassador_rank(token) == string::utf8(RANK_BRONZE), 3); + assert!(token::uri(token) == string::utf8(b"Ambassador Token #1 URI/Bronze"), 4); + // `creator` sets the level to 15. + set_ambassador_level(creator, token, 15); + // Asserts that the level is updated to 15. + assert!(ambassador_level(token) == 15, 4); + // Asserts that the rank is updated to "Silver" which is the expected rank for level 15. + assert!(token::uri(token) == string::utf8(b"Ambassador Token #1 URI/Silver"), 5); + + // // ------------------------ + // // Creator burns the token. + // // ------------------------ + // let token_addr = object::object_address(&token); + // // Asserts that the token exists before burning. + // assert!(exists(token_addr), 6); + // // Burns the token. + // burn(creator, token); + // // Asserts that the token does not exist after burning. + // assert!(!exists(token_addr), 7); + } + + #[test(creator = @0x123, user1 = @0x456)] + fun test_mint_burn_by_user(creator: &signer, user1: &signer) acquires AmbassadorToken, AmbassadorLevel { + // ------------------------------------------ + // Creator creates the Ambassador Collection. + // ------------------------------------------ + create_ambassador_collection(creator); + + let token_description = string::utf8(b"Ambassador Token #1 Description"); + let token_uri = string::utf8(b"Ambassador Token #1 URI/"); + mint_ambassador_token_by_user( + user1, + creator, + token_description, + token_uri + ); + burn_named_by_user(user1, creator); + } +} diff --git a/api/src/tests/move/pack_token_v1/Move.toml b/api/src/tests/move/pack_token_v1/Move.toml new file mode 100644 index 0000000000000..c459b5fa469bc --- /dev/null +++ b/api/src/tests/move/pack_token_v1/Move.toml @@ -0,0 +1,11 @@ +[package] +name = "pack_token_v1" +version = "0.0.0" + +[dependencies] +MoveStdlib = { local = "../../../../../aptos-move/framework/move-stdlib" } +AptosFramework = { local = "../../../../../aptos-move/framework/aptos-framework" } +AptosToken = { local = "../../../../../aptos-move/framework/aptos-token" } + +[addresses] +addr = "_" diff --git a/api/src/tests/move/pack_token_v1/sources/token_v1.move b/api/src/tests/move/pack_token_v1/sources/token_v1.move new file mode 100644 index 0000000000000..b1c70cd8e782e --- /dev/null +++ b/api/src/tests/move/pack_token_v1/sources/token_v1.move @@ -0,0 +1,123 @@ +module addr::token_v1 { + use std::string::{Self, String}; + use std::signer; + use std::bcs; + use aptos_token::token; + use aptos_token::property_map; + use aptos_token::token_transfers; + + /// The ambassador token collection name + const COLLECTION_NAME: vector = b"Ambassador Collection Name"; + /// The ambassador token collection description + const COLLECTION_DESCRIPTION: vector = b"Ambassador Collection Description"; + /// The ambassador token collection URI + const COLLECTION_URI: vector = b"Ambassador Collection URI"; + + const TOKEN_NAME: vector = b"Token 1"; + + public entry fun run(creator: &signer) { + token::create_collection( + creator, + string::utf8(COLLECTION_NAME), + string::utf8(COLLECTION_DESCRIPTION), + string::utf8(COLLECTION_URI), + 100, + vector[true, true, true], + ); + let default_keys = vector[string::utf8(b"attack"), string::utf8(b"num_of_use"), string::utf8(b"TOKEN_BURNABLE_BY_OWNER")]; + let default_vals = vector>[bcs::to_bytes(&10), bcs::to_bytes(&5), bcs::to_bytes(&true)]; + let default_types = vector[string::utf8(b"u64"), string::utf8(b"u64"), string::utf8(b"bool")]; + let mutate_setting = vector[true, true, true, true, true]; + + let amount = 10; + let token_max = 100; + + token::create_token_script( + creator, + string::utf8(COLLECTION_NAME), + string::utf8(TOKEN_NAME), + string::utf8(b"Hello, Token"), + amount, + token_max, + string::utf8(b"https://aptos.dev"), + signer::address_of(creator), + 100, + 0, + mutate_setting, + default_keys, + default_vals, + default_types, + ); + let token_id = token::create_token_id_raw( + signer::address_of(creator), + string::utf8(COLLECTION_NAME), + string::utf8(TOKEN_NAME), + 0 + ); + let new_keys = vector[ + string::utf8(b"attack"), string::utf8(b"num_of_use") + ]; + let new_vals = vector>[ + bcs::to_bytes(&1), bcs::to_bytes(&1) + ]; + let new_types = vector[ + string::utf8(b"u64"), string::utf8(b"u64") + ]; + let new_token_id = token::mutate_one_token( + creator, + signer::address_of(creator), + token_id, + new_keys, + new_vals, + new_types, + ); + let updated_pm = token::get_property_map(signer::address_of(creator), new_token_id); + property_map::update_property_value( + &mut updated_pm, + &string::utf8(b"attack"), + property_map::create_property_value(&2), + ); + + let creator_addr = signer::address_of(creator); + let token_data_id = token::create_token_data_id(signer::address_of(creator), string::utf8(COLLECTION_NAME), string::utf8(TOKEN_NAME)); + token::mutate_tokendata_uri(creator, token_data_id, string::utf8(b"new_uri")); + token::mutate_tokendata_property(creator, token_data_id, new_keys, + new_vals, + new_types); + token::mutate_tokendata_description(creator, token_data_id, string::utf8(b"new_description")); + let royalty = token::create_royalty(50, 100, creator_addr); + token::mutate_tokendata_royalty(creator, token_data_id, royalty); + token::mutate_tokendata_maximum(creator, token_data_id, 1001); + + token::mutate_collection_description(creator, string::utf8(COLLECTION_NAME), string::utf8(b"new_collection_description")); + token::mutate_collection_uri(creator, string::utf8(COLLECTION_NAME), string::utf8(b"new_collection_uri")); + token::mutate_collection_maximum(creator, string::utf8(COLLECTION_NAME), 2002); + + let token_0 = token::withdraw_token(creator, token_id, 1); + token::deposit_token(creator, token_0); + + token::burn( + creator, + signer::address_of(creator), + string::utf8(COLLECTION_NAME), + string::utf8(TOKEN_NAME), + 0, + 1 + ); + + token_transfers::offer(creator, creator_addr, token_id, 1); + token_transfers::claim(creator, creator_addr, token_id); + + token_transfers::offer(creator, creator_addr, token_id, 1); + token_transfers::cancel_offer(creator, creator_addr, token_id); + + token::opt_in_direct_transfer(creator, true); + } + + #[test(creator = @0xAF, owner = @0xBB)] + fun test(creator: &signer) { + use 0x1::account; + account::create_account_for_test(signer::address_of(creator)); + run(creator); + } +} diff --git a/api/src/transactions.rs b/api/src/transactions.rs index 24e4a1c26c87a..f5cf952c967b5 100644 --- a/api/src/transactions.rs +++ b/api/src/transactions.rs @@ -1440,11 +1440,16 @@ impl TransactionsApi { output.gas_used(), exe_status, ); + let mut events = output.events().to_vec(); + let _ = self + .context + .translate_v2_to_v1_events_for_simulation(&mut events); + let simulated_txn = TransactionOnChainData { version, transaction: txn, info, - events: output.events().to_vec(), + events, accumulator_root_hash: zero_hash, changes: output.write_set().clone(), }; diff --git a/api/test-context/src/test_context.rs b/api/test-context/src/test_context.rs index 99ff148314c0c..cd0e85509619d 100644 --- a/api/test-context/src/test_context.rs +++ b/api/test-context/src/test_context.rs @@ -373,6 +373,56 @@ impl TestContext { ) } + pub async fn enable_feature(&mut self, feature: u64) { + // This function executes the following script as the root account: + // script { + // fun main(root: &signer, feature: u64) { + // let aptos_framework = aptos_framework::aptos_governance::get_signer_testnet_only(root, @0x1); + // std::features::change_feature_flags_for_next_epoch(&aptos_framework, vector[feature], vector[]); + // aptos_framework::aptos_governance::reconfigure(&aptos_framework); + // std::features::on_new_epoch(&aptos_framework); + // } + // } + let mut root = self.root_account().await; + self.api_execute_script( + &mut root, + "a11ceb0b0700000a06010004030418051c1707336f08a2012006c201260000000100020301000101030502000100040602000101050602000102060c03010c0002060c05010303060c0a030a0301060c106170746f735f676f7665726e616e6365086665617475726573176765745f7369676e65725f746573746e65745f6f6e6c79236368616e67655f666561747572655f666c6167735f666f725f6e6578745f65706f63680b7265636f6e6669677572650c6f6e5f6e65775f65706f63680000000000000000000000000000000000000000000000000000000000000001052000000000000000000000000000000000000000000000000000000000000000010a0301000000010e0b00070011000c020e020b0140040100000000000000070111010e0211020e02110302", + json!([]), + json!([feature.to_string()]), + ).await; + self.wait_for_internal_indexer_caught_up().await; + } + + pub async fn disable_feature(&mut self, feature: u64) { + // This function executes the following script as the root account: + // script { + // fun main(root: &signer, feature: u64) { + // let aptos_framework = aptos_framework::aptos_governance::get_signer_testnet_only(root, @0x1); + // std::features::change_feature_flags_for_next_epoch(&aptos_framework, vector[], vector[feature]); + // aptos_framework::aptos_governance::reconfigure(&aptos_framework); + // std::features::on_new_epoch(&aptos_framework); + // } + // } + let mut root = self.root_account().await; + self.api_execute_script( + &mut root, + "a11ceb0b0700000a06010004030418051c1707336f08a2012006c201260000000100020301000101030502000100040602000101050602000102060c03010c0002060c05010303060c0a030a0301060c106170746f735f676f7665726e616e6365086665617475726573176765745f7369676e65725f746573746e65745f6f6e6c79236368616e67655f666561747572655f666c6167735f666f725f6e6578745f65706f63680b7265636f6e6669677572650c6f6e5f6e65775f65706f63680000000000000000000000000000000000000000000000000000000000000001052000000000000000000000000000000000000000000000000000000000000000010a0301000000010e0b00070011000c020e0207010b014004010000000000000011010e0211020e02110302", + json!([]), + json!([feature.to_string()]), + ).await; + self.wait_for_internal_indexer_caught_up().await; + } + + pub async fn is_feature_enabled(&self, feature: u64) -> bool { + let request = json!({ + "function":"0x1::features::is_enabled", + "arguments": vec![feature.to_string()], + "type_arguments": Vec::::new(), + }); + let resp = self.post("/view", request).await; + resp[0].as_bool().unwrap() + } + pub fn latest_state_view(&self) -> DbStateView { self.context .state_view_at_version(self.get_latest_ledger_info().version()) @@ -401,6 +451,46 @@ impl TestContext { account } + pub async fn api_create_account(&mut self) -> LocalAccount { + let root = &mut self.root_account().await; + let account = self.gen_account(); + self.api_execute_aptos_account_transfer(root, account.address(), TRANSFER_AMOUNT) + .await; + account + } + + pub async fn api_execute_aptos_account_transfer( + &mut self, + sender: &mut LocalAccount, + receiver: AccountAddress, + amount: u64, + ) { + self.api_execute_entry_function( + sender, + "0x1::aptos_account::transfer", + json!([]), + json!([receiver.to_hex_literal(), amount.to_string()]), + ) + .await; + self.wait_for_internal_indexer_caught_up().await; + } + + pub async fn wait_for_internal_indexer_caught_up(&self) { + let (internal_indexer_ledger_info_opt, storage_ledger_info) = self + .context + .get_latest_internal_and_storage_ledger_info::() + .expect("cannot get ledger info"); + if let Some(mut internal_indexer_ledger_info) = internal_indexer_ledger_info_opt { + while internal_indexer_ledger_info.version() < storage_ledger_info.version() { + tokio::time::sleep(Duration::from_millis(10)).await; + internal_indexer_ledger_info = self + .context + .get_latest_internal_indexer_ledger_info::() + .expect("cannot get internal indexer version"); + } + } + } + pub async fn create_user_account(&self, account: &LocalAccount) -> SignedTransaction { let mut tc = self.root_account().await; self.create_user_account_by(&mut tc, account) @@ -867,6 +957,27 @@ impl TestContext { .await; } + pub async fn api_execute_script( + &mut self, + account: &mut LocalAccount, + bytecode: &str, + type_args: serde_json::Value, + args: serde_json::Value, + ) { + self.api_execute_txn( + account, + json!({ + "type": "script_payload", + "code": { + "bytecode": bytecode, + }, + "type_arguments": type_args, + "arguments": args + }), + ) + .await; + } + pub async fn api_execute_txn(&mut self, account: &mut LocalAccount, payload: Value) { self.api_execute_txn_expecting(account, payload, 202).await; } diff --git a/config/src/config/internal_indexer_db_config.rs b/config/src/config/internal_indexer_db_config.rs index 323d02c090b45..d88d3a5dd2ed1 100644 --- a/config/src/config/internal_indexer_db_config.rs +++ b/config/src/config/internal_indexer_db_config.rs @@ -12,6 +12,8 @@ use serde::{Deserialize, Serialize}; pub struct InternalIndexerDBConfig { pub enable_transaction: bool, pub enable_event: bool, + pub enable_event_v2_translation: bool, + pub event_v2_translation_ignores_below_version: u64, pub enable_statekeys: bool, pub batch_size: usize, } @@ -20,12 +22,16 @@ impl InternalIndexerDBConfig { pub fn new( enable_transaction: bool, enable_event: bool, + enable_event_v2_translation: bool, + event_v2_translation_ignores_below_version: u64, enable_statekeys: bool, batch_size: usize, ) -> Self { Self { enable_transaction, enable_event, + enable_event_v2_translation, + event_v2_translation_ignores_below_version, enable_statekeys, batch_size, } @@ -39,6 +45,14 @@ impl InternalIndexerDBConfig { self.enable_event } + pub fn enable_event_v2_translation(&self) -> bool { + self.enable_event_v2_translation + } + + pub fn event_v2_translation_ignores_below_version(&self) -> u64 { + self.event_v2_translation_ignores_below_version + } + pub fn enable_statekeys(&self) -> bool { self.enable_statekeys } @@ -57,6 +71,8 @@ impl Default for InternalIndexerDBConfig { Self { enable_transaction: false, enable_event: false, + enable_event_v2_translation: false, + event_v2_translation_ignores_below_version: 0, enable_statekeys: false, batch_size: 10_000, } diff --git a/crates/aptos-rosetta/src/types/objects.rs b/crates/aptos-rosetta/src/types/objects.rs index e1764b6b3b309..2a4cdc575cb21 100644 --- a/crates/aptos-rosetta/src/types/objects.rs +++ b/crates/aptos-rosetta/src/types/objects.rs @@ -2175,8 +2175,8 @@ fn get_amount_from_event_v2( ) -> Vec { filter_v2_events(type_tag, events, |event| { if let Ok(event) = bcs::from_bytes::(event.event_data()) { - if event.account == account_address && &event.coin_type == coin_type { - Some(event.amount) + if event.account() == &account_address && event.coin_type() == coin_type { + Some(event.amount()) } else { None } diff --git a/ecosystem/indexer-grpc/indexer-grpc-table-info/src/internal_indexer_db_service.rs b/ecosystem/indexer-grpc/indexer-grpc-table-info/src/internal_indexer_db_service.rs index c795a724e9324..5b39bbe9784aa 100644 --- a/ecosystem/indexer-grpc/indexer-grpc-table-info/src/internal_indexer_db_service.rs +++ b/ecosystem/indexer-grpc/indexer-grpc-table-info/src/internal_indexer_db_service.rs @@ -50,7 +50,9 @@ impl InternalIndexerDBService { open_internal_indexer_db(db_path_buf.as_path(), &rocksdb_config) .expect("Failed to open internal indexer db"), ); - let internal_indexer_db_config = InternalIndexerDBConfig::new(true, true, true, 10_000); + + let internal_indexer_db_config = + InternalIndexerDBConfig::new(true, true, true, 0, true, 10_000); Some(InternalIndexerDB::new(arc_db, internal_indexer_db_config)) } @@ -136,6 +138,29 @@ impl InternalIndexerDBService { } } + if node_config.indexer_db_config.enable_event_v2_translation() { + let event_v2_translation_start_version = self + .db_indexer + .indexer_db + .get_event_v2_translation_version()? + .map_or(0, |v| v + 1); + if node_config + .indexer_db_config + .event_v2_translation_ignores_below_version() + < start_version + && start_version != event_v2_translation_start_version + { + panic!( + "Cannot start event v2 translation indexer because the progress doesn't match. \ + start_version: {}, event_v2_translation_start_version: {}", + start_version, event_v2_translation_start_version + ); + } + if !node_config.indexer_db_config.enable_event() { + panic!("Cannot start event v2 translation indexer because event indexer is not enabled."); + } + } + Ok(start_version) } diff --git a/storage/aptosdb/src/event_store/mod.rs b/storage/aptosdb/src/event_store/mod.rs index 1ff4d31c330d4..e909ab782a4f7 100644 --- a/storage/aptosdb/src/event_store/mod.rs +++ b/storage/aptosdb/src/event_store/mod.rs @@ -19,13 +19,14 @@ use aptos_crypto::{ }; use aptos_db_indexer_schemas::schema::{ event_by_key::EventByKeySchema, event_by_version::EventByVersionSchema, + translated_v1_event::TranslatedV1EventSchema, }; use aptos_schemadb::{iterator::SchemaIterator, schema::ValueCodec, ReadOptions, SchemaBatch, DB}; use aptos_storage_interface::{db_ensure as ensure, db_other_bail, AptosDbError, Result}; use aptos_types::{ account_address::AccountAddress, account_config::{new_block_event_key, NewBlockEvent}, - contract_event::ContractEvent, + contract_event::{ContractEvent, ContractEventV1}, event::EventKey, proof::position::Position, transaction::Version, diff --git a/storage/indexer/src/db_indexer.rs b/storage/indexer/src/db_indexer.rs index ac3d18709a068..21a4a877afedd 100644 --- a/storage/indexer/src/db_indexer.rs +++ b/storage/indexer/src/db_indexer.rs @@ -1,27 +1,34 @@ // Copyright (c) Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -use crate::{metrics::TIMER, utils::PrefixedStateValueIterator}; +use crate::{ + event_v2_translator::EventV2TranslationEngine, metrics::TIMER, + utils::PrefixedStateValueIterator, +}; use aptos_config::config::internal_indexer_db_config::InternalIndexerDBConfig; use aptos_db_indexer_schemas::{ metadata::{MetadataKey, MetadataValue, StateSnapshotProgress}, schema::{ event_by_key::EventByKeySchema, event_by_version::EventByVersionSchema, + event_sequence_number::EventSequenceNumberSchema, indexer_metadata::InternalIndexerMetadataSchema, state_keys::StateKeysSchema, transaction_by_account::TransactionByAccountSchema, + translated_v1_event::TranslatedV1EventSchema, }, utils::{ error_if_too_many_requested, get_first_seq_num_and_limit, AccountTransactionVersionIter, MAX_REQUEST_LIMIT, }, }; +use aptos_logger::warn; use aptos_schemadb::{SchemaBatch, DB}; use aptos_storage_interface::{ db_ensure as ensure, db_other_bail as bail, AptosDbError, DbReader, Result, }; use aptos_types::{ account_address::AccountAddress, - contract_event::{ContractEvent, EventWithVersion}, + account_config::{BURN_TYPE, MINT_TYPE}, + contract_event::{ContractEvent, ContractEventV1, ContractEventV2, EventWithVersion}, event::EventKey, indexer::indexer_db_reader::Order, state_store::{ @@ -33,6 +40,7 @@ use aptos_types::{ }; use std::{ cmp::min, + collections::HashSet, sync::{ mpsc::{self, Receiver, Sender}, Arc, @@ -69,7 +77,7 @@ impl DBCommitter { #[derive(Clone, Debug)] pub struct InternalIndexerDB { - db: Arc, + pub db: Arc, config: InternalIndexerDBConfig, } @@ -114,10 +122,18 @@ impl InternalIndexerDB { self.get_version(&MetadataKey::TransactionVersion) } + pub fn get_event_v2_translation_version(&self) -> Result> { + self.get_version(&MetadataKey::EventV2TranslationVersion) + } + pub fn event_enabled(&self) -> bool { self.config.enable_event } + pub fn event_v2_translation_enabled(&self) -> bool { + self.config.enable_event_v2_translation + } + pub fn transaction_enabled(&self) -> bool { self.config.enable_transaction } @@ -273,6 +289,16 @@ impl InternalIndexerDB { .get::(key)? .map(|v| v.expect_version())) } + + pub fn get_translated_v1_event_by_version_and_index( + &self, + version: Version, + index: u64, + ) -> Result { + self.db + .get::(&(version, index))? + .ok_or_else(|| AptosDbError::NotFound(format!("Event {} of Txn {}", index, version))) + } } pub struct DBIndexer { @@ -280,6 +306,7 @@ pub struct DBIndexer { pub main_db_reader: Arc, sender: Sender>, committer_handle: Option>, + pub event_v2_translation_engine: EventV2TranslationEngine, } impl Drop for DBIndexer { @@ -300,6 +327,7 @@ impl DBIndexer { let (sender, reciver) = mpsc::channel(); let db = indexer_db.get_inner_db_ref().to_owned(); + let internal_indexer_db = db.clone(); let committer_handle = thread::spawn(move || { let committer = DBCommitter::new(db, reciver); committer.run(); @@ -307,9 +335,13 @@ impl DBIndexer { Self { indexer_db, - main_db_reader: db_reader, + main_db_reader: db_reader.clone(), sender, committer_handle: Some(committer_handle), + event_v2_translation_engine: EventV2TranslationEngine::new( + db_reader, + internal_indexer_db, + ), } } @@ -367,6 +399,7 @@ impl DBIndexer { // This promises num_transactions should be readable from main db let mut db_iter = self.get_main_db_iter(version, num_transactions)?; let batch = SchemaBatch::new(); + let mut event_keys: HashSet = HashSet::new(); db_iter.try_for_each(|res| { let (txn, events, writeset) = res?; if let Some(txn) = txn.try_as_signed_user_txn() { @@ -379,7 +412,7 @@ impl DBIndexer { } if self.indexer_db.event_enabled() { - events.iter().enumerate().for_each(|(idx, event)| { + events.iter().enumerate().try_for_each(|(idx, event)| { if let ContractEvent::V1(v1) = event { batch .put::( @@ -394,7 +427,45 @@ impl DBIndexer { ) .expect("Failed to put events by version to a batch"); } - }); + if self.indexer_db.event_v2_translation_enabled() { + if let ContractEvent::V2(v2) = event { + if let Some(translated_v1_event) = + self.translate_event_v2_to_v1(v2).map_err(|e| { + anyhow::anyhow!( + "Failed to translate event: {:?}. Error: {}", + v2, + e + ) + })? + { + let key = *translated_v1_event.key(); + let sequence_number = translated_v1_event.sequence_number(); + self.event_v2_translation_engine + .cache_sequence_number(&key, sequence_number); + event_keys.insert(key); + batch + .put::( + &(key, sequence_number), + &(version, idx as u64), + ) + .expect("Failed to put events by key to a batch"); + batch + .put::( + &(key, version, sequence_number), + &(idx as u64), + ) + .expect("Failed to put events by version to a batch"); + batch + .put::( + &(version, idx as u64), + &translated_v1_event, + ) + .expect("Failed to put translated v1 events to a batch"); + } + } + } + Ok::<(), AptosDbError>(()) + })?; } if self.indexer_db.statekeys_enabled() { @@ -413,6 +484,25 @@ impl DBIndexer { assert_eq!(num_transactions, version - start_version); + if self.indexer_db.event_v2_translation_enabled() { + batch.put::( + &MetadataKey::EventV2TranslationVersion, + &MetadataValue::Version(version - 1), + )?; + + for event_key in event_keys { + batch + .put::( + &event_key, + &self + .event_v2_translation_engine + .get_cached_sequence_number(&event_key) + .unwrap_or(0), + ) + .expect("Failed to put events by key to a batch"); + } + } + if self.indexer_db.transaction_enabled() { batch.put::( &MetadataKey::TransactionVersion, @@ -441,6 +531,42 @@ impl DBIndexer { Ok(version) } + pub fn translate_event_v2_to_v1( + &self, + v2: &ContractEventV2, + ) -> Result> { + let _timer = TIMER + .with_label_values(&["translate_event_v2_to_v1"]) + .start_timer(); + if let Some(translator) = self + .event_v2_translation_engine + .translators + .get(v2.type_tag()) + { + let result = translator.translate_event_v2_to_v1(v2, &self.event_v2_translation_engine); + match result { + Ok(v1) => Ok(Some(v1)), + Err(e) => { + // If the token object collection uses ConcurrentSupply, skip the translation and ignore the error. + // This is expected, as the event handle won't be found in either FixedSupply or UnlimitedSupply. + let is_ignored_error = (v2.type_tag() == &*MINT_TYPE + || v2.type_tag() == &*BURN_TYPE) + && e.to_string().contains("resource not found"); + if !is_ignored_error { + warn!( + "Failed to translate event: {:?}. Error: {}", + v2, + e.to_string() + ); + } + Ok(None) + }, + } + } else { + Ok(None) + } + } + pub fn get_account_transactions( &self, address: AccountAddress, @@ -550,9 +676,16 @@ impl DBIndexer { let mut events_with_version = event_indices .into_iter() .map(|(seq, ver, idx)| { - let event = self + let event = match self .main_db_reader - .get_event_by_version_and_index(ver, idx)?; + .get_event_by_version_and_index(ver, idx)? + { + event @ ContractEvent::V1(_) => event, + ContractEvent::V2(_) => ContractEvent::V1( + self.indexer_db + .get_translated_v1_event_by_version_and_index(ver, idx)?, + ), + }; let v0 = match &event { ContractEvent::V1(event) => event, ContractEvent::V2(_) => bail!("Unexpected module event"), @@ -563,6 +696,7 @@ impl DBIndexer { seq, v0.sequence_number() ); + Ok(EventWithVersion::new(ver, event)) }) .collect::>>()?; diff --git a/storage/indexer/src/event_v2_translator.rs b/storage/indexer/src/event_v2_translator.rs new file mode 100644 index 0000000000000..89cda0cac7175 --- /dev/null +++ b/storage/indexer/src/event_v2_translator.rs @@ -0,0 +1,1361 @@ +// Copyright (c) Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use aptos_db_indexer_schemas::schema::event_sequence_number::EventSequenceNumberSchema; +use aptos_schemadb::DB; +use aptos_storage_interface::{ + state_store::state_view::db_state_view::LatestDbStateCheckpointView, AptosDbError, DbReader, + Result, +}; +use aptos_types::{ + account_config::{ + AccountResource, Burn, BurnEvent, BurnToken, BurnTokenEvent, CancelOffer, Claim, + CoinDeposit, CoinRegister, CoinRegisterEvent, CoinStoreResource, CoinWithdraw, + CollectionDescriptionMutate, CollectionDescriptionMutateEvent, CollectionMaximumMutate, + CollectionMaximumMutateEvent, CollectionMutation, CollectionMutationEvent, + CollectionResource, CollectionUriMutate, CollectionUriMutateEvent, CollectionsResource, + CreateCollection, CreateCollectionEvent, CreateTokenDataEvent, DefaultPropertyMutate, + DefaultPropertyMutateEvent, DepositEvent, DescriptionMutate, DescriptionMutateEvent, + FixedSupplyResource, KeyRotation, KeyRotationEvent, MaximumMutate, MaximumMutateEvent, + Mint, MintEvent, MintToken, MintTokenEvent, MutatePropertyMap, MutateTokenPropertyMapEvent, + ObjectCoreResource, ObjectGroupResource, Offer, OptInTransfer, OptInTransferEvent, + PendingClaimsResource, RoyaltyMutate, RoyaltyMutateEvent, TokenCancelOfferEvent, + TokenClaimEvent, TokenDataCreation, TokenDeposit, TokenDepositEvent, + TokenEventStoreV1Resource, TokenMutation, TokenMutationEvent, TokenOfferEvent, + TokenResource, TokenStoreResource, TokenWithdraw, TokenWithdrawEvent, Transfer, + TransferEvent, UnlimitedSupplyResource, UriMutation, UriMutationEvent, WithdrawEvent, + BURN_EVENT_TYPE, BURN_TOKEN_EVENT_TYPE, BURN_TOKEN_TYPE, BURN_TYPE, CANCEL_OFFER_TYPE, + CLAIM_TYPE, COIN_DEPOSIT_TYPE, COIN_REGISTER_EVENT_TYPE, COIN_REGISTER_TYPE, + COIN_WITHDRAW_TYPE, COLLECTION_DESCRIPTION_MUTATE_EVENT_TYPE, + COLLECTION_DESCRIPTION_MUTATE_TYPE, COLLECTION_MAXIMUM_MUTATE_EVENT_TYPE, + COLLECTION_MAXIMUM_MUTATE_TYPE, COLLECTION_MUTATION_EVENT_TYPE, COLLECTION_MUTATION_TYPE, + COLLECTION_URI_MUTATE_EVENT_TYPE, COLLECTION_URI_MUTATE_TYPE, CREATE_COLLECTION_EVENT_TYPE, + CREATE_COLLECTION_TYPE, CREATE_TOKEN_DATA_EVENT_TYPE, DEFAULT_PROPERTY_MUTATE_EVENT_TYPE, + DEFAULT_PROPERTY_MUTATE_TYPE, DEPOSIT_EVENT_TYPE, DESCRIPTION_MUTATE_EVENT_TYPE, + DESCRIPTION_MUTATE_TYPE, KEY_ROTATION_EVENT_TYPE, KEY_ROTATION_TYPE, + MAXIMUM_MUTATE_EVENT_TYPE, MAXIMUM_MUTATE_TYPE, MINT_EVENT_TYPE, MINT_TOKEN_EVENT_TYPE, + MINT_TOKEN_TYPE, MINT_TYPE, MUTATE_PROPERTY_MAP_TYPE, MUTATE_TOKEN_PROPERTY_MAP_EVENT_TYPE, + OFFER_TYPE, OPT_IN_TRANSFER_EVENT_TYPE, OPT_IN_TRANSFER_TYPE, ROYALTY_MUTATE_EVENT_TYPE, + ROYALTY_MUTATE_TYPE, TOKEN_CANCEL_OFFER_EVENT_TYPE, TOKEN_CLAIM_EVENT_TYPE, + TOKEN_DATA_CREATION_TYPE, TOKEN_DEPOSIT_EVENT_TYPE, TOKEN_DEPOSIT_TYPE, + TOKEN_MUTATION_EVENT_TYPE, TOKEN_MUTATION_TYPE, TOKEN_OFFER_EVENT_TYPE, + TOKEN_WITHDRAW_EVENT_TYPE, TOKEN_WITHDRAW_TYPE, TRANSFER_EVENT_TYPE, TRANSFER_TYPE, + URI_MUTATION_EVENT_TYPE, URI_MUTATION_TYPE, WITHDRAW_EVENT_TYPE, + }, + contract_event::{ContractEventV1, ContractEventV2}, + event::EventKey, + state_store::{state_key::StateKey, TStateView}, + DummyCoinType, +}; +use bytes::Bytes; +use dashmap::DashMap; +use move_core_types::{ + account_address::AccountAddress, + language_storage::{StructTag, TypeTag}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use std::{collections::HashMap, str::FromStr, sync::Arc}; + +pub trait EventV2Translator: Send + Sync { + fn translate_event_v2_to_v1( + &self, + v2: &ContractEventV2, + engine: &EventV2TranslationEngine, + ) -> Result; +} + +pub struct EventV2TranslationEngine { + pub main_db_reader: Arc, + pub internal_indexer_db: Arc, + // Map from event type to translator + pub translators: HashMap>, + event_sequence_number_cache: DashMap, +} + +impl EventV2TranslationEngine { + pub fn new(main_db_reader: Arc, internal_indexer_db: Arc) -> Self { + let translators: HashMap> = [ + ( + COIN_DEPOSIT_TYPE.clone(), + Box::new(CoinDepositTranslator) as Box, + ), + (COIN_WITHDRAW_TYPE.clone(), Box::new(CoinWithdrawTranslator)), + (COIN_REGISTER_TYPE.clone(), Box::new(CoinRegisterTranslator)), + (KEY_ROTATION_TYPE.clone(), Box::new(KeyRotationTranslator)), + (TRANSFER_TYPE.clone(), Box::new(TransferTranslator)), + ( + TOKEN_MUTATION_TYPE.clone(), + Box::new(TokenMutationTranslator), + ), + ( + COLLECTION_MUTATION_TYPE.clone(), + Box::new(CollectionMutationTranslator), + ), + (MINT_TYPE.clone(), Box::new(MintTranslator)), + (BURN_TYPE.clone(), Box::new(BurnTranslator)), + (TOKEN_DEPOSIT_TYPE.clone(), Box::new(TokenDepositTranslator)), + ( + TOKEN_WITHDRAW_TYPE.clone(), + Box::new(TokenWithdrawTranslator), + ), + (BURN_TOKEN_TYPE.clone(), Box::new(BurnTokenTranslator)), + ( + MUTATE_PROPERTY_MAP_TYPE.clone(), + Box::new(MutatePropertyMapTranslator), + ), + (MINT_TOKEN_TYPE.clone(), Box::new(MintTokenTranslator)), + ( + CREATE_COLLECTION_TYPE.clone(), + Box::new(CreateCollectionTranslator), + ), + ( + TOKEN_DATA_CREATION_TYPE.clone(), + Box::new(TokenDataCreationTranslator), + ), + (OFFER_TYPE.clone(), Box::new(OfferTranslator)), + (CANCEL_OFFER_TYPE.clone(), Box::new(CancelOfferTranslator)), + (CLAIM_TYPE.clone(), Box::new(ClaimTranslator)), + ( + COLLECTION_DESCRIPTION_MUTATE_TYPE.clone(), + Box::new(CollectionDescriptionMutateTranslator), + ), + ( + COLLECTION_URI_MUTATE_TYPE.clone(), + Box::new(CollectionUriMutateTranslator), + ), + ( + COLLECTION_MAXIMUM_MUTATE_TYPE.clone(), + Box::new(CollectionMaximumMutateTranslator), + ), + (URI_MUTATION_TYPE.clone(), Box::new(UriMutationTranslator)), + ( + DEFAULT_PROPERTY_MUTATE_TYPE.clone(), + Box::new(DefaultPropertyMutateTranslator), + ), + ( + DESCRIPTION_MUTATE_TYPE.clone(), + Box::new(DescriptionMutateTranslator), + ), + ( + ROYALTY_MUTATE_TYPE.clone(), + Box::new(RoyaltyMutateTranslator), + ), + ( + MAXIMUM_MUTATE_TYPE.clone(), + Box::new(MaximumMutateTranslator), + ), + ( + OPT_IN_TRANSFER_TYPE.clone(), + Box::new(OptInTransferTranslator), + ), + ] + .into_iter() + .collect(); + Self { + main_db_reader, + internal_indexer_db, + translators, + event_sequence_number_cache: DashMap::new(), + } + } + + // When the node starts with a non-empty EventSequenceNumberSchema table, the in-memory cache + // `event_sequence_number_cache` is empty. In the future, we decide to backup and restore the + // event sequence number data to support fast sync, we may need to load the cache from the DB + // when the node starts using this function `load_cache_from_db`. + pub fn load_cache_from_db(&self) -> Result<()> { + let mut iter = self + .internal_indexer_db + .iter::()?; + iter.seek_to_first(); + while let Some((event_key, sequence_number)) = iter.next().transpose()? { + self.event_sequence_number_cache + .insert(event_key, sequence_number); + } + Ok(()) + } + + pub fn cache_sequence_number(&self, event_key: &EventKey, sequence_number: u64) { + self.event_sequence_number_cache + .insert(*event_key, sequence_number); + } + + pub fn get_cached_sequence_number(&self, event_key: &EventKey) -> Option { + self.event_sequence_number_cache + .get(event_key) + .map(|seq| *seq) + } + + pub fn get_next_sequence_number(&self, event_key: &EventKey, default: u64) -> Result { + if let Some(seq) = self.get_cached_sequence_number(event_key) { + Ok(seq + 1) + } else { + let seq = self + .internal_indexer_db + .get::(event_key)? + .map_or(default, |seq| seq + 1); + Ok(seq) + } + } + + pub fn get_state_value_bytes_for_resource( + &self, + address: &AccountAddress, + struct_tag: &StructTag, + ) -> Result> { + let state_view = self + .main_db_reader + .latest_state_checkpoint_view() + .expect("Failed to get state view"); + let state_key = StateKey::resource(address, struct_tag)?; + let maybe_state_value = state_view.get_state_value(&state_key)?; + Ok(maybe_state_value.map(|state_value| state_value.bytes().clone())) + } + + pub fn get_state_value_bytes_for_object_group_resource( + &self, + address: &AccountAddress, + struct_tag: &StructTag, + ) -> Result> { + let state_view = self + .main_db_reader + .latest_state_checkpoint_view() + .expect("Failed to get state view"); + static OBJECT_GROUP_TAG: Lazy = Lazy::new(ObjectGroupResource::struct_tag); + let state_key = StateKey::resource_group(address, &OBJECT_GROUP_TAG); + let maybe_state_value = state_view.get_state_value(&state_key)?; + let state_value = maybe_state_value + .ok_or_else(|| anyhow::format_err!("ObjectGroup resource not found"))?; + let object_group_resource: ObjectGroupResource = bcs::from_bytes(state_value.bytes())?; + Ok(object_group_resource + .group + .get(struct_tag) + .map(|bytes| Bytes::copy_from_slice(bytes))) + } +} + +struct CoinDepositTranslator; +impl EventV2Translator for CoinDepositTranslator { + fn translate_event_v2_to_v1( + &self, + v2: &ContractEventV2, + engine: &EventV2TranslationEngine, + ) -> Result { + let coin_deposit = CoinDeposit::try_from_bytes(v2.event_data())?; + let struct_tag_str = format!("0x1::coin::CoinStore<{}>", coin_deposit.coin_type()); + let struct_tag = StructTag::from_str(&struct_tag_str)?; + let (key, sequence_number) = if let Some(state_value_bytes) = + engine.get_state_value_bytes_for_resource(coin_deposit.account(), &struct_tag)? + { + // We can use `DummyCoinType` as it does not affect the correctness of deserialization. + let coin_store_resource: CoinStoreResource = + bcs::from_bytes(&state_value_bytes)?; + let key = *coin_store_resource.deposit_events().key(); + let sequence_number = engine + .get_next_sequence_number(&key, coin_store_resource.deposit_events().count())?; + (key, sequence_number) + } else { + // The creation number of DepositEvent is deterministically 2. + static DEPOSIT_EVENT_CREATION_NUMBER: u64 = 2; + ( + EventKey::new(DEPOSIT_EVENT_CREATION_NUMBER, *coin_deposit.account()), + 0, + ) + }; + let deposit_event = DepositEvent::new(coin_deposit.amount()); + Ok(ContractEventV1::new( + key, + sequence_number, + DEPOSIT_EVENT_TYPE.clone(), + bcs::to_bytes(&deposit_event)?, + )) + } +} + +struct CoinWithdrawTranslator; +impl EventV2Translator for CoinWithdrawTranslator { + fn translate_event_v2_to_v1( + &self, + v2: &ContractEventV2, + engine: &EventV2TranslationEngine, + ) -> Result { + let coin_withdraw = CoinWithdraw::try_from_bytes(v2.event_data())?; + let struct_tag_str = format!("0x1::coin::CoinStore<{}>", coin_withdraw.coin_type()); + let struct_tag = StructTag::from_str(&struct_tag_str)?; + let (key, sequence_number) = if let Some(state_value_bytes) = + engine.get_state_value_bytes_for_resource(coin_withdraw.account(), &struct_tag)? + { + // We can use `DummyCoinType` as it does not affect the correctness of deserialization. + let coin_store_resource: CoinStoreResource = + bcs::from_bytes(&state_value_bytes)?; + let key = *coin_store_resource.withdraw_events().key(); + let sequence_number = engine + .get_next_sequence_number(&key, coin_store_resource.withdraw_events().count())?; + (key, sequence_number) + } else { + // The creation number of WithdrawEvent is deterministically 3. + static WITHDRAW_EVENT_CREATION_NUMBER: u64 = 3; + ( + EventKey::new(WITHDRAW_EVENT_CREATION_NUMBER, *coin_withdraw.account()), + 0, + ) + }; + let withdraw_event = WithdrawEvent::new(coin_withdraw.amount()); + Ok(ContractEventV1::new( + key, + sequence_number, + WITHDRAW_EVENT_TYPE.clone(), + bcs::to_bytes(&withdraw_event)?, + )) + } +} + +struct CoinRegisterTranslator; +impl EventV2Translator for CoinRegisterTranslator { + fn translate_event_v2_to_v1( + &self, + v2: &ContractEventV2, + engine: &EventV2TranslationEngine, + ) -> Result { + let coin_register = CoinRegister::try_from_bytes(v2.event_data())?; + let struct_tag_str = "0x1::account::Account".to_string(); + let struct_tag = StructTag::from_str(&struct_tag_str)?; + let (key, sequence_number) = if let Some(state_value_bytes) = + engine.get_state_value_bytes_for_resource(coin_register.account(), &struct_tag)? + { + let account_resource: AccountResource = bcs::from_bytes(&state_value_bytes)?; + let key = *account_resource.coin_register_events().key(); + let sequence_number = engine + .get_next_sequence_number(&key, account_resource.coin_register_events().count())?; + (key, sequence_number) + } else { + // The creation number of CoinRegisterEvent is deterministically 0. + static COIN_REGISTER_EVENT_CREATION_NUMBER: u64 = 0; + ( + EventKey::new( + COIN_REGISTER_EVENT_CREATION_NUMBER, + *coin_register.account(), + ), + 0, + ) + }; + let coin_register_event = CoinRegisterEvent::new(coin_register.type_info().clone()); + Ok(ContractEventV1::new( + key, + sequence_number, + COIN_REGISTER_EVENT_TYPE.clone(), + bcs::to_bytes(&coin_register_event)?, + )) + } +} + +struct KeyRotationTranslator; +impl EventV2Translator for KeyRotationTranslator { + fn translate_event_v2_to_v1( + &self, + v2: &ContractEventV2, + engine: &EventV2TranslationEngine, + ) -> Result { + let key_rotation = KeyRotation::try_from_bytes(v2.event_data())?; + let struct_tag_str = "0x1::account::Account".to_string(); + let struct_tag = StructTag::from_str(&struct_tag_str)?; + let (key, sequence_number) = if let Some(state_value_bytes) = + engine.get_state_value_bytes_for_resource(key_rotation.account(), &struct_tag)? + { + let account_resource: AccountResource = bcs::from_bytes(&state_value_bytes)?; + let key = *account_resource.key_rotation_events().key(); + let sequence_number = engine + .get_next_sequence_number(&key, account_resource.key_rotation_events().count())?; + (key, sequence_number) + } else { + // The creation number of KeyRotationEvent is deterministically 1. + static KEY_ROTATION_EVENT_CREATION_NUMBER: u64 = 1; + ( + EventKey::new(KEY_ROTATION_EVENT_CREATION_NUMBER, *key_rotation.account()), + 0, + ) + }; + let key_rotation_event = KeyRotationEvent::new( + key_rotation.old_authentication_key().clone(), + key_rotation.new_authentication_key().clone(), + ); + Ok(ContractEventV1::new( + key, + sequence_number, + KEY_ROTATION_EVENT_TYPE.clone(), + bcs::to_bytes(&key_rotation_event)?, + )) + } +} + +struct TransferTranslator; +impl EventV2Translator for TransferTranslator { + fn translate_event_v2_to_v1( + &self, + v2: &ContractEventV2, + engine: &EventV2TranslationEngine, + ) -> Result { + let transfer = Transfer::try_from_bytes(v2.event_data())?; + let struct_tag_str = "0x1::object::ObjectCore".to_string(); + let struct_tag = StructTag::from_str(&struct_tag_str)?; + let (key, sequence_number) = if let Some(state_value_bytes) = engine + .get_state_value_bytes_for_object_group_resource(transfer.object(), &struct_tag)? + { + let object_core_resource: ObjectCoreResource = bcs::from_bytes(&state_value_bytes)?; + let key = *object_core_resource.transfer_events().key(); + let sequence_number = engine + .get_next_sequence_number(&key, object_core_resource.transfer_events().count())?; + (key, sequence_number) + } else { + // The creation number of TransferEvent is deterministically 0x4000000000000 + // because the INIT_GUID_CREATION_NUM in the Move module is 0x4000000000000. + static TRANSFER_EVENT_CREATION_NUMBER: u64 = 0x4000000000000; + ( + EventKey::new(TRANSFER_EVENT_CREATION_NUMBER, *transfer.object()), + 0, + ) + }; + let transfer_event = + TransferEvent::new(*transfer.object(), *transfer.from(), *transfer.to()); + Ok(ContractEventV1::new( + key, + sequence_number, + TRANSFER_EVENT_TYPE.clone(), + bcs::to_bytes(&transfer_event)?, + )) + } +} + +struct TokenMutationTranslator; +impl EventV2Translator for TokenMutationTranslator { + fn translate_event_v2_to_v1( + &self, + v2: &ContractEventV2, + engine: &EventV2TranslationEngine, + ) -> Result { + let token_mutation = TokenMutation::try_from_bytes(v2.event_data())?; + let struct_tag_str = "0x4::token::Token".to_string(); + let struct_tag = StructTag::from_str(&struct_tag_str)?; + let (key, sequence_number) = if let Some(state_value_bytes) = engine + .get_state_value_bytes_for_object_group_resource( + token_mutation.token_address(), + &struct_tag, + )? { + let token_resource: TokenResource = bcs::from_bytes(&state_value_bytes)?; + let key = *token_resource.mutation_events().key(); + let sequence_number = + engine.get_next_sequence_number(&key, token_resource.mutation_events().count())?; + (key, sequence_number) + } else { + // If the token resource is not found, we skip the event translation to avoid panic + // because the creation number cannot be decided. The token may have been burned. + return Err(AptosDbError::from(anyhow::format_err!( + "Token resource not found" + ))); + }; + let token_mutation_event = TokenMutationEvent::new( + token_mutation.mutated_field_name().clone(), + token_mutation.old_value().clone(), + token_mutation.new_value().clone(), + ); + Ok(ContractEventV1::new( + key, + sequence_number, + TOKEN_MUTATION_EVENT_TYPE.clone(), + bcs::to_bytes(&token_mutation_event)?, + )) + } +} + +struct CollectionMutationTranslator; +impl EventV2Translator for CollectionMutationTranslator { + fn translate_event_v2_to_v1( + &self, + v2: &ContractEventV2, + engine: &EventV2TranslationEngine, + ) -> Result { + let collection_mutation = CollectionMutation::try_from_bytes(v2.event_data())?; + let struct_tag_str = "0x4::collection::Collection".to_string(); + let struct_tag = StructTag::from_str(&struct_tag_str)?; + let (key, sequence_number) = if let Some(state_value_bytes) = engine + .get_state_value_bytes_for_object_group_resource( + collection_mutation.collection().inner(), + &struct_tag, + )? { + let collection_resource: CollectionResource = bcs::from_bytes(&state_value_bytes)?; + let key = *collection_resource.mutation_events().key(); + let sequence_number = engine + .get_next_sequence_number(&key, collection_resource.mutation_events().count())?; + (key, sequence_number) + } else { + // If the token resource is not found, we skip the event translation to avoid panic + // because the creation number cannot be decided. + return Err(AptosDbError::from(anyhow::format_err!( + "Collection resource not found" + ))); + }; + let collection_mutation_event = + CollectionMutationEvent::new(collection_mutation.mutated_field_name().clone()); + Ok(ContractEventV1::new( + key, + sequence_number, + COLLECTION_MUTATION_EVENT_TYPE.clone(), + bcs::to_bytes(&collection_mutation_event)?, + )) + } +} + +struct MintTranslator; +impl EventV2Translator for MintTranslator { + fn translate_event_v2_to_v1( + &self, + v2: &ContractEventV2, + engine: &EventV2TranslationEngine, + ) -> Result { + let mint = Mint::try_from_bytes(v2.event_data())?; + let fixed_supply_struct_tag = StructTag::from_str("0x4::collection::FixedSupply")?; + let unlimited_supply_struct_tag = StructTag::from_str("0x4::collection::UnlimitedSupply")?; + let (key, sequence_number) = if let Some(state_value_bytes) = engine + .get_state_value_bytes_for_object_group_resource( + mint.collection(), + &fixed_supply_struct_tag, + )? { + let fixed_supply_resource: FixedSupplyResource = bcs::from_bytes(&state_value_bytes)?; + let key = *fixed_supply_resource.mint_events().key(); + let sequence_number = engine + .get_next_sequence_number(&key, fixed_supply_resource.mint_events().count())?; + (key, sequence_number) + } else if let Some(state_value_bytes) = engine + .get_state_value_bytes_for_object_group_resource( + mint.collection(), + &unlimited_supply_struct_tag, + )? + { + let unlimited_supply_resource: UnlimitedSupplyResource = + bcs::from_bytes(&state_value_bytes)?; + let key = *unlimited_supply_resource.mint_events().key(); + let sequence_number = engine + .get_next_sequence_number(&key, unlimited_supply_resource.mint_events().count())?; + (key, sequence_number) + } else { + // If the collection resource is not found, we skip the event translation to avoid panic + // because the creation number cannot be decided. The collection may have ConcurrentSupply. + return Err(AptosDbError::from(anyhow::format_err!( + "FixedSupply or UnlimitedSupply resource not found" + ))); + }; + let mint_event = MintEvent::new(mint.index().value, *mint.token()); + Ok(ContractEventV1::new( + key, + sequence_number, + MINT_EVENT_TYPE.clone(), + bcs::to_bytes(&mint_event)?, + )) + } +} + +struct BurnTranslator; +impl EventV2Translator for BurnTranslator { + fn translate_event_v2_to_v1( + &self, + v2: &ContractEventV2, + engine: &EventV2TranslationEngine, + ) -> Result { + let burn = Burn::try_from_bytes(v2.event_data())?; + let fixed_supply_struct_tag = StructTag::from_str("0x4::collection::FixedSupply")?; + let unlimited_supply_struct_tag = StructTag::from_str("0x4::collection::UnlimitedSupply")?; + let (key, sequence_number) = if let Some(state_value_bytes) = engine + .get_state_value_bytes_for_object_group_resource( + burn.collection(), + &fixed_supply_struct_tag, + )? { + let fixed_supply_resource: FixedSupplyResource = bcs::from_bytes(&state_value_bytes)?; + let key = *fixed_supply_resource.burn_events().key(); + let sequence_number = engine + .get_next_sequence_number(&key, fixed_supply_resource.burn_events().count())?; + (key, sequence_number) + } else if let Some(state_value_bytes) = engine + .get_state_value_bytes_for_object_group_resource( + burn.collection(), + &unlimited_supply_struct_tag, + )? + { + let unlimited_supply_resource: UnlimitedSupplyResource = + bcs::from_bytes(&state_value_bytes)?; + let key = *unlimited_supply_resource.burn_events().key(); + let sequence_number = engine + .get_next_sequence_number(&key, unlimited_supply_resource.burn_events().count())?; + (key, sequence_number) + } else { + // If the collection resource is not found, we skip the event translation to avoid panic + // because the creation number cannot be decided. The collection may have ConcurrentSupply. + return Err(AptosDbError::from(anyhow::format_err!( + "FixedSupply or UnlimitedSupply resource not found" + ))); + }; + let burn_event = BurnEvent::new(*burn.index(), *burn.token()); + Ok(ContractEventV1::new( + key, + sequence_number, + BURN_EVENT_TYPE.clone(), + bcs::to_bytes(&burn_event)?, + )) + } +} + +struct TokenDepositTranslator; +impl EventV2Translator for TokenDepositTranslator { + fn translate_event_v2_to_v1( + &self, + v2: &ContractEventV2, + engine: &EventV2TranslationEngine, + ) -> Result { + let deposit = TokenDeposit::try_from_bytes(v2.event_data())?; + let struct_tag = StructTag::from_str("0x3::token::TokenStore")?; + let (key, sequence_number) = if let Some(state_value_bytes) = + engine.get_state_value_bytes_for_resource(deposit.account(), &struct_tag)? + { + let token_store_resource: TokenStoreResource = bcs::from_bytes(&state_value_bytes)?; + let key = *token_store_resource.deposit_events().key(); + let sequence_number = engine + .get_next_sequence_number(&key, token_store_resource.deposit_events().count())?; + (key, sequence_number) + } else { + // If the token store resource is not found, we skip the event translation to avoid panic + // because the creation number cannot be decided. + return Err(AptosDbError::from(anyhow::format_err!( + "Token store resource not found" + ))); + }; + let deposit_event = TokenDepositEvent::new(deposit.id().clone(), deposit.amount()); + Ok(ContractEventV1::new( + key, + sequence_number, + TOKEN_DEPOSIT_EVENT_TYPE.clone(), + bcs::to_bytes(&deposit_event)?, + )) + } +} + +struct TokenWithdrawTranslator; +impl EventV2Translator for TokenWithdrawTranslator { + fn translate_event_v2_to_v1( + &self, + v2: &ContractEventV2, + engine: &EventV2TranslationEngine, + ) -> Result { + let withdraw = TokenWithdraw::try_from_bytes(v2.event_data())?; + let struct_tag = StructTag::from_str("0x3::token::TokenStore")?; + let (key, sequence_number) = if let Some(state_value_bytes) = + engine.get_state_value_bytes_for_resource(withdraw.account(), &struct_tag)? + { + let token_store_resource: TokenStoreResource = bcs::from_bytes(&state_value_bytes)?; + let key = *token_store_resource.withdraw_events().key(); + let sequence_number = engine + .get_next_sequence_number(&key, token_store_resource.withdraw_events().count())?; + (key, sequence_number) + } else { + // If the token store resource is not found, we skip the event translation to avoid panic + // because the creation number cannot be decided. + return Err(AptosDbError::from(anyhow::format_err!( + "Token store resource not found" + ))); + }; + let withdraw_event = TokenWithdrawEvent::new(withdraw.id().clone(), withdraw.amount()); + Ok(ContractEventV1::new( + key, + sequence_number, + TOKEN_WITHDRAW_EVENT_TYPE.clone(), + bcs::to_bytes(&withdraw_event)?, + )) + } +} + +struct BurnTokenTranslator; +impl EventV2Translator for BurnTokenTranslator { + fn translate_event_v2_to_v1( + &self, + v2: &ContractEventV2, + engine: &EventV2TranslationEngine, + ) -> Result { + let burn = BurnToken::try_from_bytes(v2.event_data())?; + let struct_tag = StructTag::from_str("0x3::token::TokenStore")?; + let (key, sequence_number) = if let Some(state_value_bytes) = + engine.get_state_value_bytes_for_resource(burn.account(), &struct_tag)? + { + let token_store_resource: TokenStoreResource = bcs::from_bytes(&state_value_bytes)?; + let key = *token_store_resource.burn_events().key(); + let sequence_number = engine + .get_next_sequence_number(&key, token_store_resource.burn_events().count())?; + (key, sequence_number) + } else { + // If the token store resource is not found, we skip the event translation to avoid panic + // because the creation number cannot be decided. + return Err(AptosDbError::from(anyhow::format_err!( + "Token store resource not found" + ))); + }; + let burn_event = BurnTokenEvent::new(burn.id().clone(), burn.amount()); + Ok(ContractEventV1::new( + key, + sequence_number, + BURN_TOKEN_EVENT_TYPE.clone(), + bcs::to_bytes(&burn_event)?, + )) + } +} + +struct MutatePropertyMapTranslator; +impl EventV2Translator for MutatePropertyMapTranslator { + fn translate_event_v2_to_v1( + &self, + v2: &ContractEventV2, + engine: &EventV2TranslationEngine, + ) -> Result { + let mutate = MutatePropertyMap::try_from_bytes(v2.event_data())?; + let struct_tag = StructTag::from_str("0x3::token::TokenStore")?; + let (key, sequence_number) = if let Some(state_value_bytes) = + engine.get_state_value_bytes_for_resource(mutate.account(), &struct_tag)? + { + let token_store_resource: TokenStoreResource = bcs::from_bytes(&state_value_bytes)?; + let key = *token_store_resource.mutate_token_property_events().key(); + let sequence_number = engine.get_next_sequence_number( + &key, + token_store_resource.mutate_token_property_events().count(), + )?; + (key, sequence_number) + } else { + // If the token store resource is not found, we skip the event translation to avoid panic + // because the creation number cannot be decided. + return Err(AptosDbError::from(anyhow::format_err!( + "Token store resource not found" + ))); + }; + let mutate_event = MutateTokenPropertyMapEvent::new( + mutate.old_id().clone(), + mutate.new_id().clone(), + mutate.keys().clone(), + mutate.values().clone(), + mutate.types().clone(), + ); + + Ok(ContractEventV1::new( + key, + sequence_number, + MUTATE_TOKEN_PROPERTY_MAP_EVENT_TYPE.clone(), + bcs::to_bytes(&mutate_event)?, + )) + } +} + +struct MintTokenTranslator; +impl EventV2Translator for MintTokenTranslator { + fn translate_event_v2_to_v1( + &self, + v2: &ContractEventV2, + engine: &EventV2TranslationEngine, + ) -> Result { + let mint = MintToken::try_from_bytes(v2.event_data())?; + let struct_tag = StructTag::from_str("0x3::token::Collections")?; + let (key, sequence_number) = if let Some(state_value_bytes) = + engine.get_state_value_bytes_for_resource(mint.creator(), &struct_tag)? + { + let token_store_resource: CollectionsResource = bcs::from_bytes(&state_value_bytes)?; + let key = *token_store_resource.mint_token_events().key(); + let sequence_number = engine + .get_next_sequence_number(&key, token_store_resource.mint_token_events().count())?; + (key, sequence_number) + } else { + // If the collections store resource is not found, we skip the event translation to + // avoid panic because the creation number cannot be decided. + return Err(AptosDbError::from(anyhow::format_err!( + "Collections resource not found" + ))); + }; + let mint_event = MintTokenEvent::new(mint.id().clone(), mint.amount()); + + Ok(ContractEventV1::new( + key, + sequence_number, + MINT_TOKEN_EVENT_TYPE.clone(), + bcs::to_bytes(&mint_event)?, + )) + } +} + +struct CreateCollectionTranslator; +impl EventV2Translator for CreateCollectionTranslator { + fn translate_event_v2_to_v1( + &self, + v2: &ContractEventV2, + engine: &EventV2TranslationEngine, + ) -> Result { + let create = CreateCollection::try_from_bytes(v2.event_data())?; + let struct_tag = StructTag::from_str("0x3::token::Collections")?; + let (key, sequence_number) = if let Some(state_value_bytes) = + engine.get_state_value_bytes_for_resource(create.creator(), &struct_tag)? + { + let collections_resource: CollectionsResource = bcs::from_bytes(&state_value_bytes)?; + let key = *collections_resource.create_collection_events().key(); + let sequence_number = engine.get_next_sequence_number( + &key, + collections_resource.create_collection_events().count(), + )?; + (key, sequence_number) + } else { + // If the collections resource is not found, we skip the event translation to + // avoid panic because the creation number cannot be decided. + return Err(AptosDbError::from(anyhow::format_err!( + "Collections resource not found" + ))); + }; + let create_event = CreateCollectionEvent::new( + *create.creator(), + create.collection_name().clone(), + create.uri().clone(), + create.description().clone(), + create.maximum(), + ); + Ok(ContractEventV1::new( + key, + sequence_number, + CREATE_COLLECTION_EVENT_TYPE.clone(), + bcs::to_bytes(&create_event)?, + )) + } +} + +struct TokenDataCreationTranslator; +impl EventV2Translator for TokenDataCreationTranslator { + fn translate_event_v2_to_v1( + &self, + v2: &ContractEventV2, + engine: &EventV2TranslationEngine, + ) -> Result { + let create = TokenDataCreation::try_from_bytes(v2.event_data())?; + let struct_tag = StructTag::from_str("0x3::token::Collections")?; + let (key, sequence_number) = if let Some(state_value_bytes) = + engine.get_state_value_bytes_for_resource(create.creator(), &struct_tag)? + { + let collections_resource: CollectionsResource = bcs::from_bytes(&state_value_bytes)?; + let key = *collections_resource.create_token_data_events().key(); + let sequence_number = engine.get_next_sequence_number( + &key, + collections_resource.create_token_data_events().count(), + )?; + (key, sequence_number) + } else { + // If the collections resource is not found, we skip the event translation to + // avoid panic because the creation number cannot be decided. + return Err(AptosDbError::from(anyhow::format_err!( + "Collections resource not found" + ))); + }; + let create_event = CreateTokenDataEvent::new( + create.id().clone(), + create.description().clone(), + create.maximum(), + create.uri().clone(), + *create.royalty_payee_address(), + create.royalty_points_denominator(), + create.royalty_points_numerator(), + create.name().clone(), + create.mutability_config().clone(), + create.property_keys().clone(), + create.property_values().clone(), + create.property_types().clone(), + ); + Ok(ContractEventV1::new( + key, + sequence_number, + CREATE_TOKEN_DATA_EVENT_TYPE.clone(), + bcs::to_bytes(&create_event)?, + )) + } +} + +struct OfferTranslator; +impl EventV2Translator for OfferTranslator { + fn translate_event_v2_to_v1( + &self, + v2: &ContractEventV2, + engine: &EventV2TranslationEngine, + ) -> Result { + let offer = Offer::try_from_bytes(v2.event_data())?; + let struct_tag = StructTag::from_str("0x3::token_transfers::PendingClaims")?; + let (key, sequence_number) = if let Some(state_value_bytes) = + engine.get_state_value_bytes_for_resource(offer.account(), &struct_tag)? + { + let object_resource: PendingClaimsResource = bcs::from_bytes(&state_value_bytes)?; + let key = *object_resource.offer_events().key(); + let sequence_number = + engine.get_next_sequence_number(&key, object_resource.offer_events().count())?; + (key, sequence_number) + } else { + // If the PendingClaims resource is not found, we skip the event translation to + // avoid panic because the creation number cannot be decided. + return Err(AptosDbError::from(anyhow::format_err!( + "PendingClaims resource not found" + ))); + }; + let offer_event = TokenOfferEvent::new( + *offer.to_address(), + offer.token_id().clone(), + offer.amount(), + ); + Ok(ContractEventV1::new( + key, + sequence_number, + TOKEN_OFFER_EVENT_TYPE.clone(), + bcs::to_bytes(&offer_event)?, + )) + } +} + +struct CancelOfferTranslator; +impl EventV2Translator for CancelOfferTranslator { + fn translate_event_v2_to_v1( + &self, + v2: &ContractEventV2, + engine: &EventV2TranslationEngine, + ) -> Result { + let cancel_offer = CancelOffer::try_from_bytes(v2.event_data())?; + let struct_tag = StructTag::from_str("0x3::token_transfers::PendingClaims")?; + let (key, sequence_number) = if let Some(state_value_bytes) = + engine.get_state_value_bytes_for_resource(cancel_offer.account(), &struct_tag)? + { + let object_resource: PendingClaimsResource = bcs::from_bytes(&state_value_bytes)?; + let key = *object_resource.cancel_offer_events().key(); + let sequence_number = engine + .get_next_sequence_number(&key, object_resource.cancel_offer_events().count())?; + (key, sequence_number) + } else { + // If the PendingClaims resource is not found, we skip the event translation to + // avoid panic because the creation number cannot be decided. + return Err(AptosDbError::from(anyhow::format_err!( + "PendingClaims resource not found" + ))); + }; + let cancel_offer_event = TokenCancelOfferEvent::new( + *cancel_offer.to_address(), + cancel_offer.token_id().clone(), + cancel_offer.amount(), + ); + Ok(ContractEventV1::new( + key, + sequence_number, + TOKEN_CANCEL_OFFER_EVENT_TYPE.clone(), + bcs::to_bytes(&cancel_offer_event)?, + )) + } +} + +struct ClaimTranslator; +impl EventV2Translator for ClaimTranslator { + fn translate_event_v2_to_v1( + &self, + v2: &ContractEventV2, + engine: &EventV2TranslationEngine, + ) -> Result { + let claim = Claim::try_from_bytes(v2.event_data())?; + let struct_tag = StructTag::from_str("0x3::token_transfers::PendingClaims")?; + let (key, sequence_number) = if let Some(state_value_bytes) = + engine.get_state_value_bytes_for_resource(claim.account(), &struct_tag)? + { + let object_resource: PendingClaimsResource = bcs::from_bytes(&state_value_bytes)?; + let key = *object_resource.claim_events().key(); + let sequence_number = + engine.get_next_sequence_number(&key, object_resource.claim_events().count())?; + (key, sequence_number) + } else { + // If the PendingClaims resource is not found, we skip the event translation to + // avoid panic because the creation number cannot be decided. + return Err(AptosDbError::from(anyhow::format_err!( + "PendingClaims resource not found" + ))); + }; + let claim_event = TokenClaimEvent::new( + *claim.to_address(), + claim.token_id().clone(), + claim.amount(), + ); + Ok(ContractEventV1::new( + key, + sequence_number, + TOKEN_CLAIM_EVENT_TYPE.clone(), + bcs::to_bytes(&claim_event)?, + )) + } +} + +struct CollectionDescriptionMutateTranslator; +impl EventV2Translator for CollectionDescriptionMutateTranslator { + fn translate_event_v2_to_v1( + &self, + v2: &ContractEventV2, + engine: &EventV2TranslationEngine, + ) -> Result { + let collection_description_mutate = + CollectionDescriptionMutate::try_from_bytes(v2.event_data())?; + let struct_tag = StructTag::from_str("0x3::token_event_store::TokenEventStoreV1")?; + let (key, sequence_number) = if let Some(state_value_bytes) = engine + .get_state_value_bytes_for_resource( + collection_description_mutate.creator_addr(), + &struct_tag, + )? { + let object_resource: TokenEventStoreV1Resource = bcs::from_bytes(&state_value_bytes)?; + let key = *object_resource.collection_description_mutate_events().key(); + let sequence_number = engine.get_next_sequence_number( + &key, + object_resource + .collection_description_mutate_events() + .count(), + )?; + (key, sequence_number) + } else { + // If the TokenEventStoreV1 resource is not found, we skip the event translation to + // avoid panic because the creation number cannot be decided. + return Err(AptosDbError::from(anyhow::format_err!( + "TokenEventStoreV1 resource not found" + ))); + }; + let collection_mutation_event = CollectionDescriptionMutateEvent::new( + *collection_description_mutate.creator_addr(), + collection_description_mutate.collection_name().clone(), + collection_description_mutate.old_description().clone(), + collection_description_mutate.new_description().clone(), + ); + Ok(ContractEventV1::new( + key, + sequence_number, + COLLECTION_DESCRIPTION_MUTATE_EVENT_TYPE.clone(), + bcs::to_bytes(&collection_mutation_event)?, + )) + } +} + +struct CollectionUriMutateTranslator; +impl EventV2Translator for CollectionUriMutateTranslator { + fn translate_event_v2_to_v1( + &self, + v2: &ContractEventV2, + engine: &EventV2TranslationEngine, + ) -> Result { + let collection_uri_mutate = CollectionUriMutate::try_from_bytes(v2.event_data())?; + let struct_tag = StructTag::from_str("0x3::token_event_store::TokenEventStoreV1")?; + let (key, sequence_number) = if let Some(state_value_bytes) = engine + .get_state_value_bytes_for_resource(collection_uri_mutate.creator_addr(), &struct_tag)? + { + let object_resource: TokenEventStoreV1Resource = bcs::from_bytes(&state_value_bytes)?; + let key = *object_resource.collection_uri_mutate_events().key(); + let sequence_number = engine.get_next_sequence_number( + &key, + object_resource.collection_uri_mutate_events().count(), + )?; + (key, sequence_number) + } else { + // If the TokenEventStoreV1 resource is not found, we skip the event translation to + // avoid panic because the creation number cannot be decided. + return Err(AptosDbError::from(anyhow::format_err!( + "TokenEventStoreV1 resource not found" + ))); + }; + let collection_mutation_event = CollectionUriMutateEvent::new( + *collection_uri_mutate.creator_addr(), + collection_uri_mutate.collection_name().clone(), + collection_uri_mutate.old_uri().clone(), + collection_uri_mutate.new_uri().clone(), + ); + Ok(ContractEventV1::new( + key, + sequence_number, + COLLECTION_URI_MUTATE_EVENT_TYPE.clone(), + bcs::to_bytes(&collection_mutation_event)?, + )) + } +} + +struct CollectionMaximumMutateTranslator; +impl EventV2Translator for CollectionMaximumMutateTranslator { + fn translate_event_v2_to_v1( + &self, + v2: &ContractEventV2, + engine: &EventV2TranslationEngine, + ) -> Result { + let collection_max_mutate = CollectionMaximumMutate::try_from_bytes(v2.event_data())?; + let struct_tag = StructTag::from_str("0x3::token_event_store::TokenEventStoreV1")?; + let (key, sequence_number) = if let Some(state_value_bytes) = engine + .get_state_value_bytes_for_resource(collection_max_mutate.creator_addr(), &struct_tag)? + { + let object_resource: TokenEventStoreV1Resource = bcs::from_bytes(&state_value_bytes)?; + let key = *object_resource.collection_maximum_mutate_events().key(); + let sequence_number = engine.get_next_sequence_number( + &key, + object_resource.collection_maximum_mutate_events().count(), + )?; + (key, sequence_number) + } else { + // If the TokenEventStoreV1 resource is not found, we skip the event translation to + // avoid panic because the creation number cannot be decided. + return Err(AptosDbError::from(anyhow::format_err!( + "TokenEventStoreV1 resource not found" + ))); + }; + let collection_mutation_event = CollectionMaximumMutateEvent::new( + *collection_max_mutate.creator_addr(), + collection_max_mutate.collection_name().clone(), + *collection_max_mutate.old_maximum(), + *collection_max_mutate.new_maximum(), + ); + Ok(ContractEventV1::new( + key, + sequence_number, + COLLECTION_MAXIMUM_MUTATE_EVENT_TYPE.clone(), + bcs::to_bytes(&collection_mutation_event)?, + )) + } +} + +struct UriMutationTranslator; +impl EventV2Translator for UriMutationTranslator { + fn translate_event_v2_to_v1( + &self, + v2: &ContractEventV2, + engine: &EventV2TranslationEngine, + ) -> Result { + let uri_mutation = UriMutation::try_from_bytes(v2.event_data())?; + let struct_tag = StructTag::from_str("0x3::token_event_store::TokenEventStoreV1")?; + let (key, sequence_number) = if let Some(state_value_bytes) = + engine.get_state_value_bytes_for_resource(uri_mutation.creator(), &struct_tag)? + { + let object_resource: TokenEventStoreV1Resource = bcs::from_bytes(&state_value_bytes)?; + let key = *object_resource.uri_mutate_events().key(); + let sequence_number = engine + .get_next_sequence_number(&key, object_resource.uri_mutate_events().count())?; + (key, sequence_number) + } else { + // If the TokenEventStoreV1 resource is not found, we skip the event translation to + // avoid panic because the creation number cannot be decided. + return Err(AptosDbError::from(anyhow::format_err!( + "TokenEventStoreV1 resource not found" + ))); + }; + let uri_mutation_event = UriMutationEvent::new( + *uri_mutation.creator(), + uri_mutation.collection().clone(), + uri_mutation.token().clone(), + uri_mutation.old_uri().clone(), + uri_mutation.new_uri().clone(), + ); + Ok(ContractEventV1::new( + key, + sequence_number, + URI_MUTATION_EVENT_TYPE.clone(), + bcs::to_bytes(&uri_mutation_event)?, + )) + } +} + +struct DefaultPropertyMutateTranslator; +impl EventV2Translator for DefaultPropertyMutateTranslator { + fn translate_event_v2_to_v1( + &self, + v2: &ContractEventV2, + engine: &EventV2TranslationEngine, + ) -> Result { + let default_property_mutate = DefaultPropertyMutate::try_from_bytes(v2.event_data())?; + let struct_tag = StructTag::from_str("0x3::token_event_store::TokenEventStoreV1")?; + let (key, sequence_number) = if let Some(state_value_bytes) = engine + .get_state_value_bytes_for_resource(default_property_mutate.creator(), &struct_tag)? + { + let object_resource: TokenEventStoreV1Resource = bcs::from_bytes(&state_value_bytes)?; + let key = *object_resource.default_property_mutate_events().key(); + let sequence_number = engine.get_next_sequence_number( + &key, + object_resource.default_property_mutate_events().count(), + )?; + (key, sequence_number) + } else { + // If the TokenEventStoreV1 resource is not found, we skip the event translation to + // avoid panic because the creation number cannot be decided. + return Err(AptosDbError::from(anyhow::format_err!( + "TokenEventStoreV1 resource not found" + ))); + }; + let default_property_mutate_event = DefaultPropertyMutateEvent::new( + *default_property_mutate.creator(), + default_property_mutate.collection().clone(), + default_property_mutate.token().clone(), + default_property_mutate.keys().clone(), + default_property_mutate.old_values().clone(), + default_property_mutate.new_values().clone(), + ); + Ok(ContractEventV1::new( + key, + sequence_number, + DEFAULT_PROPERTY_MUTATE_EVENT_TYPE.clone(), + bcs::to_bytes(&default_property_mutate_event)?, + )) + } +} + +struct DescriptionMutateTranslator; +impl EventV2Translator for DescriptionMutateTranslator { + fn translate_event_v2_to_v1( + &self, + v2: &ContractEventV2, + engine: &EventV2TranslationEngine, + ) -> Result { + let description_mutation = DescriptionMutate::try_from_bytes(v2.event_data())?; + let struct_tag = StructTag::from_str("0x3::token_event_store::TokenEventStoreV1")?; + let (key, sequence_number) = if let Some(state_value_bytes) = engine + .get_state_value_bytes_for_resource(description_mutation.creator(), &struct_tag)? + { + let object_resource: TokenEventStoreV1Resource = bcs::from_bytes(&state_value_bytes)?; + let key = *object_resource.description_mutate_events().key(); + let sequence_number = engine.get_next_sequence_number( + &key, + object_resource.description_mutate_events().count(), + )?; + (key, sequence_number) + } else { + // If the TokenEventStoreV1 resource is not found, we skip the event translation to + // avoid panic because the creation number cannot be decided. + return Err(AptosDbError::from(anyhow::format_err!( + "TokenEventStoreV1 resource not found" + ))); + }; + let description_mutation_event = DescriptionMutateEvent::new( + *description_mutation.creator(), + description_mutation.collection().clone(), + description_mutation.token().clone(), + description_mutation.old_description().clone(), + description_mutation.new_description().clone(), + ); + Ok(ContractEventV1::new( + key, + sequence_number, + DESCRIPTION_MUTATE_EVENT_TYPE.clone(), + bcs::to_bytes(&description_mutation_event)?, + )) + } +} + +struct RoyaltyMutateTranslator; +impl EventV2Translator for RoyaltyMutateTranslator { + fn translate_event_v2_to_v1( + &self, + v2: &ContractEventV2, + engine: &EventV2TranslationEngine, + ) -> Result { + let royalty_mutation = RoyaltyMutate::try_from_bytes(v2.event_data())?; + let struct_tag = StructTag::from_str("0x3::token_event_store::TokenEventStoreV1")?; + let (key, sequence_number) = if let Some(state_value_bytes) = + engine.get_state_value_bytes_for_resource(royalty_mutation.creator(), &struct_tag)? + { + let object_resource: TokenEventStoreV1Resource = bcs::from_bytes(&state_value_bytes)?; + let key = *object_resource.royalty_mutate_events().key(); + let sequence_number = engine + .get_next_sequence_number(&key, object_resource.royalty_mutate_events().count())?; + (key, sequence_number) + } else { + // If the TokenEventStoreV1 resource is not found, we skip the event translation to + // avoid panic because the creation number cannot be decided. + return Err(AptosDbError::from(anyhow::format_err!( + "TokenEventStoreV1 resource not found" + ))); + }; + let royalty_mutation_event = RoyaltyMutateEvent::new( + *royalty_mutation.creator(), + royalty_mutation.collection().clone(), + royalty_mutation.token().clone(), + *royalty_mutation.old_royalty_numerator(), + *royalty_mutation.old_royalty_denominator(), + *royalty_mutation.old_royalty_payee_addr(), + *royalty_mutation.new_royalty_numerator(), + *royalty_mutation.new_royalty_denominator(), + *royalty_mutation.new_royalty_payee_addr(), + ); + Ok(ContractEventV1::new( + key, + sequence_number, + ROYALTY_MUTATE_EVENT_TYPE.clone(), + bcs::to_bytes(&royalty_mutation_event)?, + )) + } +} + +struct MaximumMutateTranslator; +impl EventV2Translator for MaximumMutateTranslator { + fn translate_event_v2_to_v1( + &self, + v2: &ContractEventV2, + engine: &EventV2TranslationEngine, + ) -> Result { + let maximum_mutation = MaximumMutate::try_from_bytes(v2.event_data())?; + let struct_tag = StructTag::from_str("0x3::token_event_store::TokenEventStoreV1")?; + let (key, sequence_number) = if let Some(state_value_bytes) = + engine.get_state_value_bytes_for_resource(maximum_mutation.creator(), &struct_tag)? + { + let object_resource: TokenEventStoreV1Resource = bcs::from_bytes(&state_value_bytes)?; + let key = *object_resource.maximum_mutate_events().key(); + let sequence_number = engine + .get_next_sequence_number(&key, object_resource.maximum_mutate_events().count())?; + (key, sequence_number) + } else { + // If the TokenEventStoreV1 resource is not found, we skip the event translation to + // avoid panic because the creation number cannot be decided. + return Err(AptosDbError::from(anyhow::format_err!( + "TokenEventStoreV1 resource not found" + ))); + }; + let maximum_mutation_event = MaximumMutateEvent::new( + *maximum_mutation.creator(), + maximum_mutation.collection().clone(), + maximum_mutation.token().clone(), + *maximum_mutation.old_maximum(), + *maximum_mutation.new_maximum(), + ); + Ok(ContractEventV1::new( + key, + sequence_number, + MAXIMUM_MUTATE_EVENT_TYPE.clone(), + bcs::to_bytes(&maximum_mutation_event)?, + )) + } +} + +struct OptInTransferTranslator; +impl EventV2Translator for OptInTransferTranslator { + fn translate_event_v2_to_v1( + &self, + v2: &ContractEventV2, + engine: &EventV2TranslationEngine, + ) -> Result { + let opt_in_transfer = OptInTransfer::try_from_bytes(v2.event_data())?; + let struct_tag = StructTag::from_str("0x3::token_event_store::TokenEventStoreV1")?; + let (key, sequence_number) = if let Some(state_value_bytes) = engine + .get_state_value_bytes_for_resource(opt_in_transfer.account_address(), &struct_tag)? + { + let object_resource: TokenEventStoreV1Resource = bcs::from_bytes(&state_value_bytes)?; + let key = *object_resource.opt_in_events().key(); + let sequence_number = + engine.get_next_sequence_number(&key, object_resource.opt_in_events().count())?; + (key, sequence_number) + } else { + // If the TokenEventStoreV1 resource is not found, we skip the event translation to + // avoid panic because the creation number cannot be decided. + return Err(AptosDbError::from(anyhow::format_err!( + "TokenEventStoreV1 resource not found" + ))); + }; + let opt_in_transfer_event = OptInTransferEvent::new(*opt_in_transfer.opt_in()); + Ok(ContractEventV1::new( + key, + sequence_number, + OPT_IN_TRANSFER_EVENT_TYPE.clone(), + bcs::to_bytes(&opt_in_transfer_event)?, + )) + } +} diff --git a/storage/indexer/src/indexer_reader.rs b/storage/indexer/src/indexer_reader.rs index f82b1ba6aad8a..8143b9dd88cbd 100644 --- a/storage/indexer/src/indexer_reader.rs +++ b/storage/indexer/src/indexer_reader.rs @@ -5,7 +5,7 @@ use crate::{db_indexer::DBIndexer, db_v2::IndexerAsyncV2}; use anyhow::anyhow; use aptos_types::{ account_address::AccountAddress, - contract_event::EventWithVersion, + contract_event::{ContractEventV1, ContractEventV2, EventWithVersion}, event::EventKey, indexer::indexer_db_reader::{IndexerReader, Order}, state_store::{ @@ -164,4 +164,35 @@ impl IndexerReader for IndexerReaders { } anyhow::bail!("DB indexer reader is not available") } + + fn get_translated_v1_event_by_version_and_index( + &self, + version: Version, + index: u64, + ) -> anyhow::Result { + if let Some(db_indexer_reader) = &self.db_indexer_reader { + if db_indexer_reader.indexer_db.event_v2_translation_enabled() { + return Ok(db_indexer_reader + .indexer_db + .get_translated_v1_event_by_version_and_index(version, index)?); + } else { + anyhow::bail!("Event translation is not enabled") + } + } + anyhow::bail!("DB indexer reader is not available") + } + + fn translate_event_v2_to_v1( + &self, + v2: &ContractEventV2, + ) -> anyhow::Result> { + if let Some(db_indexer_reader) = &self.db_indexer_reader { + if db_indexer_reader.indexer_db.event_v2_translation_enabled() { + return Ok(db_indexer_reader.translate_event_v2_to_v1(v2)?); + } else { + anyhow::bail!("Event translation is not enabled") + } + } + anyhow::bail!("DB indexer reader is not available") + } } diff --git a/storage/indexer/src/lib.rs b/storage/indexer/src/lib.rs index 34331dd702c31..2929953d787a9 100644 --- a/storage/indexer/src/lib.rs +++ b/storage/indexer/src/lib.rs @@ -6,6 +6,7 @@ mod db; pub mod db_indexer; pub mod db_ops; pub mod db_v2; +pub mod event_v2_translator; pub mod indexer_reader; mod metrics; mod utils; diff --git a/storage/indexer_schemas/src/metadata.rs b/storage/indexer_schemas/src/metadata.rs index 940f724da79d0..0168eb34470b8 100644 --- a/storage/indexer_schemas/src/metadata.rs +++ b/storage/indexer_schemas/src/metadata.rs @@ -38,6 +38,7 @@ pub enum MetadataKey { EventVersion, StateVersion, TransactionVersion, + EventV2TranslationVersion, } #[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)] diff --git a/storage/indexer_schemas/src/schema/event_sequence_number/mod.rs b/storage/indexer_schemas/src/schema/event_sequence_number/mod.rs new file mode 100644 index 0000000000000..5f50a75c46aed --- /dev/null +++ b/storage/indexer_schemas/src/schema/event_sequence_number/mod.rs @@ -0,0 +1,53 @@ +// Copyright © Aptos Foundation +// Parts of the project are originally copyright © Meta Platforms, Inc. +// SPDX-License-Identifier: Apache-2.0 + +//! This module defines physical storage schema for event sequence numbers for associated event keys, +//! specifically for translated v1 events. +//! +//! ```text +//! |<--key---->|<-value->| +//! | event_key | seq_num | +//! ``` + +use crate::schema::EVENT_SEQUENCE_NUMBER_CF_NAME; +use anyhow::Result; +use aptos_schemadb::{ + define_pub_schema, + schema::{KeyCodec, ValueCodec}, +}; +use aptos_types::event::EventKey; + +define_pub_schema!( + EventSequenceNumberSchema, + Key, + Value, + EVENT_SEQUENCE_NUMBER_CF_NAME +); + +type SeqNum = u64; +type Key = EventKey; +type Value = SeqNum; + +impl KeyCodec for Key { + fn encode_key(&self) -> Result> { + Ok(bcs::to_bytes(self)?) + } + + fn decode_key(data: &[u8]) -> Result { + Ok(bcs::from_bytes(data)?) + } +} + +impl ValueCodec for Value { + fn encode_value(&self) -> Result> { + Ok(bcs::to_bytes(self)?) + } + + fn decode_value(data: &[u8]) -> Result { + Ok(bcs::from_bytes(data)?) + } +} + +#[cfg(test)] +mod test; diff --git a/storage/indexer_schemas/src/schema/event_sequence_number/test.rs b/storage/indexer_schemas/src/schema/event_sequence_number/test.rs new file mode 100644 index 0000000000000..dc078e160ff87 --- /dev/null +++ b/storage/indexer_schemas/src/schema/event_sequence_number/test.rs @@ -0,0 +1,19 @@ +// Copyright © Aptos Foundation +// Parts of the project are originally copyright © Meta Platforms, Inc. +// SPDX-License-Identifier: Apache-2.0 + +use super::*; +use aptos_schemadb::{schema::fuzzing::assert_encode_decode, test_no_panic_decoding}; +use proptest::prelude::*; + +proptest! { + #[test] + fn test_encode_decode( + event_key in any::(), + seq_num in any::(), + ) { + assert_encode_decode::(&event_key, &seq_num); + } +} + +test_no_panic_decoding!(EventSequenceNumberSchema); diff --git a/storage/indexer_schemas/src/schema/mod.rs b/storage/indexer_schemas/src/schema/mod.rs index 0f4dfd4c7bcd6..31c7e6c25267e 100644 --- a/storage/indexer_schemas/src/schema/mod.rs +++ b/storage/indexer_schemas/src/schema/mod.rs @@ -8,10 +8,14 @@ pub mod event_by_key; pub mod event_by_version; +pub mod event_sequence_number; pub mod indexer_metadata; pub mod state_keys; pub mod table_info; pub mod transaction_by_account; +pub mod translated_v1_event; + +use anyhow::ensure; use aptos_schemadb::ColumnFamilyName; pub const DEFAULT_COLUMN_FAMILY_NAME: ColumnFamilyName = "default"; @@ -22,6 +26,8 @@ pub const EVENT_BY_KEY_CF_NAME: ColumnFamilyName = "event_by_key"; pub const EVENT_BY_VERSION_CF_NAME: ColumnFamilyName = "event_by_version"; pub const TRANSACTION_BY_ACCOUNT_CF_NAME: ColumnFamilyName = "transaction_by_account"; pub const STATE_KEYS_CF_NAME: ColumnFamilyName = "state_keys"; +pub const TRANSLATED_V1_EVENT_CF_NAME: ColumnFamilyName = "translated_v1_event"; +pub const EVENT_SEQUENCE_NUMBER_CF_NAME: ColumnFamilyName = "event_sequence_number"; pub fn column_families() -> Vec { vec![ @@ -39,5 +45,17 @@ pub fn internal_indexer_column_families() -> Vec { EVENT_BY_VERSION_CF_NAME, TRANSACTION_BY_ACCOUNT_CF_NAME, STATE_KEYS_CF_NAME, + TRANSLATED_V1_EVENT_CF_NAME, + EVENT_SEQUENCE_NUMBER_CF_NAME, ] } + +fn ensure_slice_len_eq(data: &[u8], len: usize) -> anyhow::Result<()> { + ensure!( + data.len() == len, + "Unexpected data len {}, expected {}.", + data.len(), + len, + ); + Ok(()) +} diff --git a/storage/indexer_schemas/src/schema/translated_v1_event/mod.rs b/storage/indexer_schemas/src/schema/translated_v1_event/mod.rs new file mode 100644 index 0000000000000..9f196482389d8 --- /dev/null +++ b/storage/indexer_schemas/src/schema/translated_v1_event/mod.rs @@ -0,0 +1,66 @@ +// Copyright © Aptos Foundation +// Parts of the project are originally copyright © Meta Platforms, Inc. +// SPDX-License-Identifier: Apache-2.0 + +//! This module defines physical storage schema for the contract events. +//! +//! A translated v1 event is keyed by the version of the transaction it belongs to and the index of +//! the original v2 event among all events yielded by the same transaction. +//! ```text +//! |<-------key----->|<---value--->| +//! | version | index | event bytes | +//! ``` + +use crate::schema::{ensure_slice_len_eq, TRANSLATED_V1_EVENT_CF_NAME}; +use anyhow::Result; +use aptos_schemadb::{ + define_pub_schema, + schema::{KeyCodec, ValueCodec}, +}; +use aptos_types::{contract_event::ContractEventV1, transaction::Version}; +use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; +use std::mem::size_of; + +define_pub_schema!( + TranslatedV1EventSchema, + Key, + ContractEventV1, + TRANSLATED_V1_EVENT_CF_NAME +); + +type Index = u64; +type Key = (Version, Index); + +impl KeyCodec for Key { + fn encode_key(&self) -> Result> { + let (version, index) = *self; + + let mut encoded_key = Vec::with_capacity(size_of::() + size_of::()); + encoded_key.write_u64::(version)?; + encoded_key.write_u64::(index)?; + Ok(encoded_key) + } + + fn decode_key(data: &[u8]) -> Result { + ensure_slice_len_eq(data, size_of::())?; + + let version_size = size_of::(); + + let version = (&data[..version_size]).read_u64::()?; + let index = (&data[version_size..]).read_u64::()?; + Ok((version, index)) + } +} + +impl ValueCodec for ContractEventV1 { + fn encode_value(&self) -> Result> { + bcs::to_bytes(self).map_err(Into::into) + } + + fn decode_value(data: &[u8]) -> Result { + bcs::from_bytes(data).map_err(Into::into) + } +} + +#[cfg(test)] +mod test; diff --git a/storage/indexer_schemas/src/schema/translated_v1_event/test.rs b/storage/indexer_schemas/src/schema/translated_v1_event/test.rs new file mode 100644 index 0000000000000..d28c191121c04 --- /dev/null +++ b/storage/indexer_schemas/src/schema/translated_v1_event/test.rs @@ -0,0 +1,20 @@ +// Copyright © Aptos Foundation +// Parts of the project are originally copyright © Meta Platforms, Inc. +// SPDX-License-Identifier: Apache-2.0 + +use super::*; +use aptos_schemadb::{schema::fuzzing::assert_encode_decode, test_no_panic_decoding}; +use proptest::prelude::*; + +proptest! { + #[test] + fn test_encode_decode( + version in any::(), + index in any::(), + event in any::(), + ) { + assert_encode_decode::(&(version, index), &event); + } +} + +test_no_panic_decoding!(TranslatedV1EventSchema); diff --git a/third_party/move/move-core/types/src/language_storage.rs b/third_party/move/move-core/types/src/language_storage.rs index a957675bd9606..821b2e22c43d0 100644 --- a/third_party/move/move-core/types/src/language_storage.rs +++ b/third_party/move/move-core/types/src/language_storage.rs @@ -21,6 +21,8 @@ pub const RESOURCE_TAG: u8 = 1; /// Hex address: 0x1 pub const CORE_CODE_ADDRESS: AccountAddress = AccountAddress::ONE; +pub const TOKEN_ADDRESS: AccountAddress = AccountAddress::THREE; +pub const TOKEN_OBJECTS_ADDRESS: AccountAddress = AccountAddress::FOUR; #[derive(Serialize, Deserialize, Debug, PartialEq, Hash, Eq, Clone, PartialOrd, Ord)] #[cfg_attr( diff --git a/types/src/account_config/events/burn.rs b/types/src/account_config/events/burn.rs new file mode 100644 index 0000000000000..c6ba78604d877 --- /dev/null +++ b/types/src/account_config/events/burn.rs @@ -0,0 +1,73 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v2::MoveEventV2Type; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_OBJECTS_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +pub struct Burn { + collection: AccountAddress, + index: u64, + token: AccountAddress, + previous_owner: AccountAddress, +} + +impl Burn { + pub fn new( + collection: AccountAddress, + index: u64, + token: AccountAddress, + previous_owner: AccountAddress, + ) -> Self { + Self { + collection, + index, + token, + previous_owner, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> anyhow::Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn collection(&self) -> &AccountAddress { + &self.collection + } + + pub fn index(&self) -> &u64 { + &self.index + } + + pub fn token(&self) -> &AccountAddress { + &self.token + } + + pub fn previous_owner(&self) -> &AccountAddress { + &self.previous_owner + } +} + +impl MoveStructType for Burn { + const MODULE_NAME: &'static IdentStr = ident_str!("collection"); + const STRUCT_NAME: &'static IdentStr = ident_str!("Burn"); +} + +impl MoveEventV2Type for Burn {} + +pub static BURN_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_OBJECTS_ADDRESS, + module: ident_str!("collection").to_owned(), + name: ident_str!("Burn").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/burn_event.rs b/types/src/account_config/events/burn_event.rs new file mode 100644 index 0000000000000..e6ce676ead0be --- /dev/null +++ b/types/src/account_config/events/burn_event.rs @@ -0,0 +1,53 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v1::MoveEventV1Type; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_OBJECTS_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +pub struct BurnEvent { + index: u64, + token: AccountAddress, +} + +impl BurnEvent { + pub fn new(index: u64, token: AccountAddress) -> Self { + Self { index, token } + } + + pub fn try_from_bytes(bytes: &[u8]) -> anyhow::Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn index(&self) -> &u64 { + &self.index + } + + pub fn token(&self) -> &AccountAddress { + &self.token + } +} + +impl MoveStructType for BurnEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("collection"); + const STRUCT_NAME: &'static IdentStr = ident_str!("BurnEvent"); +} + +impl MoveEventV1Type for BurnEvent {} + +pub static BURN_EVENT_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_OBJECTS_ADDRESS, + module: ident_str!("collection").to_owned(), + name: ident_str!("BurnEvent").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/burn_token.rs b/types/src/account_config/events/burn_token.rs new file mode 100644 index 0000000000000..1c0a4e01d84e3 --- /dev/null +++ b/types/src/account_config/events/burn_token.rs @@ -0,0 +1,63 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::{account_config::TokenId, move_utils::move_event_v2::MoveEventV2Type}; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct BurnToken { + account: AccountAddress, + id: TokenId, + amount: u64, +} + +impl BurnToken { + pub fn new(account: AccountAddress, id: TokenId, amount: u64) -> Self { + Self { + account, + id, + amount, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn account(&self) -> &AccountAddress { + &self.account + } + + pub fn id(&self) -> &TokenId { + &self.id + } + + pub fn amount(&self) -> u64 { + self.amount + } +} + +impl MoveStructType for BurnToken { + const MODULE_NAME: &'static IdentStr = ident_str!("token"); + const STRUCT_NAME: &'static IdentStr = ident_str!("Burn"); +} + +impl MoveEventV2Type for BurnToken {} + +pub static BURN_TOKEN_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token").to_owned(), + name: ident_str!("Burn").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/burn_token_event.rs b/types/src/account_config/events/burn_token_event.rs new file mode 100644 index 0000000000000..bee2068800e32 --- /dev/null +++ b/types/src/account_config/events/burn_token_event.rs @@ -0,0 +1,53 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::{account_config::TokenId, move_utils::move_event_v1::MoveEventV1Type}; +use anyhow::Result; +use move_core_types::{ + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct BurnTokenEvent { + id: TokenId, + amount: u64, +} + +impl BurnTokenEvent { + pub fn new(id: TokenId, amount: u64) -> Self { + Self { id, amount } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn id(&self) -> &TokenId { + &self.id + } + + pub fn amount(&self) -> u64 { + self.amount + } +} + +impl MoveStructType for BurnTokenEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("token"); + const STRUCT_NAME: &'static IdentStr = ident_str!("BurnTokenEvent"); +} + +impl MoveEventV1Type for BurnTokenEvent {} + +pub static BURN_TOKEN_EVENT_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token").to_owned(), + name: ident_str!("BurnTokenEvent").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/cancel_offer.rs b/types/src/account_config/events/cancel_offer.rs new file mode 100644 index 0000000000000..0af298e251b6f --- /dev/null +++ b/types/src/account_config/events/cancel_offer.rs @@ -0,0 +1,74 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::{account_config::TokenId, move_utils::move_event_v2::MoveEventV2Type}; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct CancelOffer { + account: AccountAddress, + to_address: AccountAddress, + token_id: TokenId, + amount: u64, +} + +impl CancelOffer { + pub fn new( + account: AccountAddress, + to_address: AccountAddress, + token_id: TokenId, + amount: u64, + ) -> Self { + Self { + account, + to_address, + token_id, + amount, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn account(&self) -> &AccountAddress { + &self.account + } + + pub fn to_address(&self) -> &AccountAddress { + &self.to_address + } + + pub fn token_id(&self) -> &TokenId { + &self.token_id + } + + pub fn amount(&self) -> u64 { + self.amount + } +} + +impl MoveStructType for CancelOffer { + const MODULE_NAME: &'static IdentStr = ident_str!("token_transfers"); + const STRUCT_NAME: &'static IdentStr = ident_str!("CancelOffer"); +} + +impl MoveEventV2Type for CancelOffer {} + +pub static CANCEL_OFFER_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token_transfers").to_owned(), + name: ident_str!("CancelOffer").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/claim.rs b/types/src/account_config/events/claim.rs new file mode 100644 index 0000000000000..57846d2bcc8b9 --- /dev/null +++ b/types/src/account_config/events/claim.rs @@ -0,0 +1,74 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::{account_config::TokenId, move_utils::move_event_v2::MoveEventV2Type}; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct Claim { + account: AccountAddress, + to_address: AccountAddress, + token_id: TokenId, + amount: u64, +} + +impl Claim { + pub fn new( + account: AccountAddress, + to_address: AccountAddress, + token_id: TokenId, + amount: u64, + ) -> Self { + Self { + account, + to_address, + token_id, + amount, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn account(&self) -> &AccountAddress { + &self.account + } + + pub fn to_address(&self) -> &AccountAddress { + &self.to_address + } + + pub fn token_id(&self) -> &TokenId { + &self.token_id + } + + pub fn amount(&self) -> u64 { + self.amount + } +} + +impl MoveStructType for Claim { + const MODULE_NAME: &'static IdentStr = ident_str!("token_transfers"); + const STRUCT_NAME: &'static IdentStr = ident_str!("Claim"); +} + +impl MoveEventV2Type for Claim {} + +pub static CLAIM_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token_transfers").to_owned(), + name: ident_str!("Claim").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/coin.rs b/types/src/account_config/events/coin.rs deleted file mode 100644 index 1a0cf5844e7e5..0000000000000 --- a/types/src/account_config/events/coin.rs +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright © Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - -use crate::{ - account_config::TypeInfoResource, - move_utils::{move_event_v1::MoveEventV1Type, move_event_v2::MoveEventV2Type}, -}; -use anyhow::Result; -use move_core_types::{ - account_address::AccountAddress, ident_str, identifier::IdentStr, move_resource::MoveStructType, -}; -use serde::{Deserialize, Serialize}; - -/// Struct that represents a SentPaymentEvent. -#[derive(Debug, Serialize, Deserialize)] -pub struct WithdrawEvent { - pub amount: u64, -} - -impl WithdrawEvent { - pub fn try_from_bytes(bytes: &[u8]) -> Result { - bcs::from_bytes(bytes).map_err(Into::into) - } - - /// Get the amount sent or received - pub fn amount(&self) -> u64 { - self.amount - } -} - -impl MoveStructType for WithdrawEvent { - const MODULE_NAME: &'static IdentStr = ident_str!("coin"); - const STRUCT_NAME: &'static IdentStr = ident_str!("WithdrawEvent"); -} - -impl MoveEventV1Type for WithdrawEvent {} - -#[derive(Debug, Serialize, Deserialize)] -pub struct CoinWithdraw { - pub coin_type: String, - pub account: AccountAddress, - pub amount: u64, -} - -impl CoinWithdraw { - pub fn try_from_bytes(bytes: &[u8]) -> Result { - bcs::from_bytes(bytes).map_err(Into::into) - } -} - -impl MoveStructType for CoinWithdraw { - const MODULE_NAME: &'static IdentStr = ident_str!("coin"); - const STRUCT_NAME: &'static IdentStr = ident_str!("CoinWithdraw"); -} - -impl MoveEventV2Type for CoinWithdraw {} - -/// Struct that represents a DepositPaymentEvent. -#[derive(Debug, Serialize, Deserialize)] -pub struct DepositEvent { - pub amount: u64, -} - -impl DepositEvent { - pub fn try_from_bytes(bytes: &[u8]) -> Result { - bcs::from_bytes(bytes).map_err(Into::into) - } - - /// Get the amount sent or received - pub fn amount(&self) -> u64 { - self.amount - } -} - -impl MoveStructType for DepositEvent { - const MODULE_NAME: &'static IdentStr = ident_str!("coin"); - const STRUCT_NAME: &'static IdentStr = ident_str!("DepositEvent"); -} - -impl MoveEventV1Type for DepositEvent {} - -#[derive(Debug, Serialize, Deserialize)] -pub struct CoinDeposit { - pub coin_type: String, - pub account: AccountAddress, - pub amount: u64, -} - -impl CoinDeposit { - pub fn try_from_bytes(bytes: &[u8]) -> Result { - bcs::from_bytes(bytes).map_err(Into::into) - } -} - -impl MoveStructType for CoinDeposit { - const MODULE_NAME: &'static IdentStr = ident_str!("coin"); - const STRUCT_NAME: &'static IdentStr = ident_str!("CoinDeposit"); -} - -impl MoveEventV2Type for CoinDeposit {} - -#[derive(Debug, Serialize, Deserialize)] -pub struct CoinRegister { - pub account: AccountAddress, - pub type_info: TypeInfoResource, -} - -impl MoveStructType for CoinRegister { - const MODULE_NAME: &'static IdentStr = ident_str!("account"); - const STRUCT_NAME: &'static IdentStr = ident_str!("CoinRegister"); -} - -impl MoveEventV2Type for CoinRegister {} diff --git a/types/src/account_config/events/coin_deposit.rs b/types/src/account_config/events/coin_deposit.rs new file mode 100644 index 0000000000000..230d1ed27e7a6 --- /dev/null +++ b/types/src/account_config/events/coin_deposit.rs @@ -0,0 +1,62 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v2::MoveEventV2Type; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, CORE_CODE_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +pub struct CoinDeposit { + pub coin_type: String, + pub account: AccountAddress, + pub amount: u64, +} + +impl CoinDeposit { + pub fn new(coin_type: String, account: AccountAddress, amount: u64) -> Self { + Self { + coin_type, + account, + amount, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> anyhow::Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn coin_type(&self) -> &str { + &self.coin_type + } + + pub fn account(&self) -> &AccountAddress { + &self.account + } + + pub fn amount(&self) -> u64 { + self.amount + } +} + +impl MoveStructType for CoinDeposit { + const MODULE_NAME: &'static IdentStr = ident_str!("coin"); + const STRUCT_NAME: &'static IdentStr = ident_str!("CoinDeposit"); +} + +impl MoveEventV2Type for CoinDeposit {} + +pub static COIN_DEPOSIT_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: CORE_CODE_ADDRESS, + module: ident_str!("coin").to_owned(), + name: ident_str!("CoinDeposit").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/coin_register.rs b/types/src/account_config/events/coin_register.rs new file mode 100644 index 0000000000000..0e947aed35eab --- /dev/null +++ b/types/src/account_config/events/coin_register.rs @@ -0,0 +1,50 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::{account_config::TypeInfoResource, move_utils::move_event_v2::MoveEventV2Type}; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, CORE_CODE_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize)] +pub struct CoinRegister { + pub account: AccountAddress, + pub type_info: TypeInfoResource, +} + +impl CoinRegister { + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn account(&self) -> &AccountAddress { + &self.account + } + + pub fn type_info(&self) -> &TypeInfoResource { + &self.type_info + } +} + +impl MoveStructType for CoinRegister { + const MODULE_NAME: &'static IdentStr = ident_str!("account"); + const STRUCT_NAME: &'static IdentStr = ident_str!("CoinRegister"); +} + +impl MoveEventV2Type for CoinRegister {} + +pub static COIN_REGISTER_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: CORE_CODE_ADDRESS, + module: ident_str!("account").to_owned(), + name: ident_str!("CoinRegister").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/coin_register_event.rs b/types/src/account_config/events/coin_register_event.rs new file mode 100644 index 0000000000000..08fa7a363abaa --- /dev/null +++ b/types/src/account_config/events/coin_register_event.rs @@ -0,0 +1,44 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::{account_config::TypeInfoResource, move_utils::move_event_v1::MoveEventV1Type}; +use anyhow::Result; +use move_core_types::{ + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, CORE_CODE_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize)] +pub struct CoinRegisterEvent { + type_info: TypeInfoResource, +} + +impl CoinRegisterEvent { + pub fn new(type_info: TypeInfoResource) -> Self { + Self { type_info } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } +} + +impl MoveStructType for CoinRegisterEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("account"); + const STRUCT_NAME: &'static IdentStr = ident_str!("CoinRegisterEvent"); +} + +impl MoveEventV1Type for CoinRegisterEvent {} + +pub static COIN_REGISTER_EVENT_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: CORE_CODE_ADDRESS, + module: ident_str!("account").to_owned(), + name: ident_str!("CoinRegisterEvent").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/coin_withdraw.rs b/types/src/account_config/events/coin_withdraw.rs new file mode 100644 index 0000000000000..7edcd6438a68a --- /dev/null +++ b/types/src/account_config/events/coin_withdraw.rs @@ -0,0 +1,62 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v2::MoveEventV2Type; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, CORE_CODE_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +pub struct CoinWithdraw { + pub coin_type: String, + pub account: AccountAddress, + pub amount: u64, +} + +impl CoinWithdraw { + pub fn new(coin_type: String, account: AccountAddress, amount: u64) -> Self { + Self { + coin_type, + account, + amount, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> anyhow::Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn coin_type(&self) -> &str { + &self.coin_type + } + + pub fn account(&self) -> &AccountAddress { + &self.account + } + + pub fn amount(&self) -> u64 { + self.amount + } +} + +impl MoveStructType for CoinWithdraw { + const MODULE_NAME: &'static IdentStr = ident_str!("coin"); + const STRUCT_NAME: &'static IdentStr = ident_str!("CoinWithdraw"); +} + +impl MoveEventV2Type for CoinWithdraw {} + +pub static COIN_WITHDRAW_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: CORE_CODE_ADDRESS, + module: ident_str!("coin").to_owned(), + name: ident_str!("CoinWithdraw").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/collection_description_mutate.rs b/types/src/account_config/events/collection_description_mutate.rs new file mode 100644 index 0000000000000..a727548d8b8f3 --- /dev/null +++ b/types/src/account_config/events/collection_description_mutate.rs @@ -0,0 +1,74 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v2::MoveEventV2Type; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct CollectionDescriptionMutate { + creator_addr: AccountAddress, + collection_name: String, + old_description: String, + new_description: String, +} + +impl CollectionDescriptionMutate { + pub fn new( + creator_addr: AccountAddress, + collection_name: String, + old_description: String, + new_description: String, + ) -> Self { + Self { + creator_addr, + collection_name, + old_description, + new_description, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn creator_addr(&self) -> &AccountAddress { + &self.creator_addr + } + + pub fn collection_name(&self) -> &String { + &self.collection_name + } + + pub fn old_description(&self) -> &String { + &self.old_description + } + + pub fn new_description(&self) -> &String { + &self.new_description + } +} + +impl MoveStructType for CollectionDescriptionMutate { + const MODULE_NAME: &'static IdentStr = ident_str!("token_event_store"); + const STRUCT_NAME: &'static IdentStr = ident_str!("CollectionDescriptionMutate"); +} + +impl MoveEventV2Type for CollectionDescriptionMutate {} + +pub static COLLECTION_DESCRIPTION_MUTATE_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token_event_store").to_owned(), + name: ident_str!("CollectionDescriptionMutate").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/collection_description_mutate_event.rs b/types/src/account_config/events/collection_description_mutate_event.rs new file mode 100644 index 0000000000000..9df55ce686361 --- /dev/null +++ b/types/src/account_config/events/collection_description_mutate_event.rs @@ -0,0 +1,74 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v1::MoveEventV1Type; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct CollectionDescriptionMutateEvent { + creator_addr: AccountAddress, + collection_name: String, + old_description: String, + new_description: String, +} + +impl CollectionDescriptionMutateEvent { + pub fn new( + creator_addr: AccountAddress, + collection_name: String, + old_description: String, + new_description: String, + ) -> Self { + Self { + creator_addr, + collection_name, + old_description, + new_description, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn creator_addr(&self) -> &AccountAddress { + &self.creator_addr + } + + pub fn collection_name(&self) -> &String { + &self.collection_name + } + + pub fn old_description(&self) -> &String { + &self.old_description + } + + pub fn new_description(&self) -> &String { + &self.new_description + } +} + +impl MoveStructType for CollectionDescriptionMutateEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("token_event_store"); + const STRUCT_NAME: &'static IdentStr = ident_str!("CollectionDescriptionMutateEvent"); +} + +impl MoveEventV1Type for CollectionDescriptionMutateEvent {} + +pub static COLLECTION_DESCRIPTION_MUTATE_EVENT_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token_event_store").to_owned(), + name: ident_str!("CollectionDescriptionMutateEvent").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/collection_maximum_mutate.rs b/types/src/account_config/events/collection_maximum_mutate.rs new file mode 100644 index 0000000000000..a1242bf57528b --- /dev/null +++ b/types/src/account_config/events/collection_maximum_mutate.rs @@ -0,0 +1,74 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v2::MoveEventV2Type; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct CollectionMaximumMutate { + creator_addr: AccountAddress, + collection_name: String, + old_maximum: u64, + new_maximum: u64, +} + +impl CollectionMaximumMutate { + pub fn new( + creator_addr: AccountAddress, + collection_name: String, + old_maximum: u64, + new_maximum: u64, + ) -> Self { + Self { + creator_addr, + collection_name, + old_maximum, + new_maximum, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn creator_addr(&self) -> &AccountAddress { + &self.creator_addr + } + + pub fn collection_name(&self) -> &String { + &self.collection_name + } + + pub fn old_maximum(&self) -> &u64 { + &self.old_maximum + } + + pub fn new_maximum(&self) -> &u64 { + &self.new_maximum + } +} + +impl MoveStructType for CollectionMaximumMutate { + const MODULE_NAME: &'static IdentStr = ident_str!("token_event_store"); + const STRUCT_NAME: &'static IdentStr = ident_str!("CollectionMaximumMutate"); +} + +impl MoveEventV2Type for CollectionMaximumMutate {} + +pub static COLLECTION_MAXIMUM_MUTATE_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token_event_store").to_owned(), + name: ident_str!("CollectionMaximumMutate").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/collection_maximum_mutate_event.rs b/types/src/account_config/events/collection_maximum_mutate_event.rs new file mode 100644 index 0000000000000..6e9f289629bfe --- /dev/null +++ b/types/src/account_config/events/collection_maximum_mutate_event.rs @@ -0,0 +1,76 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v1::MoveEventV1Type; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct CollectionMaximumMutateEvent { + creator_addr: AccountAddress, + collection_name: String, + old_maximum: u64, + new_maximum: u64, +} + +impl CollectionMaximumMutateEvent { + pub fn new( + creator_addr: AccountAddress, + collection_name: String, + old_maximum: u64, + new_maximum: u64, + ) -> Self { + Self { + creator_addr, + collection_name, + old_maximum, + new_maximum, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn creator_addr(&self) -> &AccountAddress { + &self.creator_addr + } + + pub fn collection_name(&self) -> &String { + &self.collection_name + } + + pub fn old_maximum(&self) -> &u64 { + &self.old_maximum + } + + pub fn new_maximum(&self) -> &u64 { + &self.new_maximum + } +} + +impl MoveStructType for CollectionMaximumMutateEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("token_event_store"); + // The struct name in the Move code contains a typo. + const STRUCT_NAME: &'static IdentStr = ident_str!("CollectionMaxiumMutateEvent"); +} + +impl MoveEventV1Type for CollectionMaximumMutateEvent {} + +pub static COLLECTION_MAXIMUM_MUTATE_EVENT_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token_event_store").to_owned(), + // The struct name in the Move code contains a typo. + name: ident_str!("CollectionMaxiumMutateEvent").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/collection_mutation.rs b/types/src/account_config/events/collection_mutation.rs new file mode 100644 index 0000000000000..57a5f7e254127 --- /dev/null +++ b/types/src/account_config/events/collection_mutation.rs @@ -0,0 +1,72 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::{account_config::Object, move_utils::move_event_v2::MoveEventV2Type}; +use move_core_types::{ + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_OBJECTS_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +pub struct CollectionMutation { + mutated_field_name: String, + collection: Object, + old_value: String, + new_value: String, +} + +impl CollectionMutation { + pub fn new( + mutated_field_name: String, + collection: Object, + old_value: String, + new_value: String, + ) -> Self { + Self { + mutated_field_name, + collection, + old_value, + new_value, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> anyhow::Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn mutated_field_name(&self) -> &String { + &self.mutated_field_name + } + + pub fn collection(&self) -> &Object { + &self.collection + } + + pub fn old_value(&self) -> &String { + &self.old_value + } + + pub fn new_value(&self) -> &String { + &self.new_value + } +} + +impl MoveStructType for CollectionMutation { + const MODULE_NAME: &'static IdentStr = ident_str!("collection"); + const STRUCT_NAME: &'static IdentStr = ident_str!("Mutation"); +} + +impl MoveEventV2Type for CollectionMutation {} + +pub static COLLECTION_MUTATION_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_OBJECTS_ADDRESS, + module: ident_str!("collection").to_owned(), + name: ident_str!("Mutation").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/collection_mutation_event.rs b/types/src/account_config/events/collection_mutation_event.rs new file mode 100644 index 0000000000000..cc50d1b49c906 --- /dev/null +++ b/types/src/account_config/events/collection_mutation_event.rs @@ -0,0 +1,47 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v1::MoveEventV1Type; +use move_core_types::{ + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_OBJECTS_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +pub struct CollectionMutationEvent { + mutated_field_name: String, +} + +impl CollectionMutationEvent { + pub fn new(mutated_field_name: String) -> Self { + Self { mutated_field_name } + } + + pub fn try_from_bytes(bytes: &[u8]) -> anyhow::Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn mutated_field_name(&self) -> &String { + &self.mutated_field_name + } +} + +impl MoveStructType for CollectionMutationEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("collection"); + const STRUCT_NAME: &'static IdentStr = ident_str!("MutationEvent"); +} + +impl MoveEventV1Type for CollectionMutationEvent {} + +pub static COLLECTION_MUTATION_EVENT_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_OBJECTS_ADDRESS, + module: ident_str!("collection").to_owned(), + name: ident_str!("MutationEvent").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/collection_uri_mutate.rs b/types/src/account_config/events/collection_uri_mutate.rs new file mode 100644 index 0000000000000..f61342c940d63 --- /dev/null +++ b/types/src/account_config/events/collection_uri_mutate.rs @@ -0,0 +1,74 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v2::MoveEventV2Type; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct CollectionUriMutate { + creator_addr: AccountAddress, + collection_name: String, + old_uri: String, + new_uri: String, +} + +impl CollectionUriMutate { + pub fn new( + creator_addr: AccountAddress, + collection_name: String, + old_uri: String, + new_uri: String, + ) -> Self { + Self { + creator_addr, + collection_name, + old_uri, + new_uri, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn creator_addr(&self) -> &AccountAddress { + &self.creator_addr + } + + pub fn collection_name(&self) -> &String { + &self.collection_name + } + + pub fn old_uri(&self) -> &String { + &self.old_uri + } + + pub fn new_uri(&self) -> &String { + &self.new_uri + } +} + +impl MoveStructType for CollectionUriMutate { + const MODULE_NAME: &'static IdentStr = ident_str!("token_event_store"); + const STRUCT_NAME: &'static IdentStr = ident_str!("CollectionUriMutate"); +} + +impl MoveEventV2Type for CollectionUriMutate {} + +pub static COLLECTION_URI_MUTATE_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token_event_store").to_owned(), + name: ident_str!("CollectionUriMutate").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/collection_uri_mutate_event.rs b/types/src/account_config/events/collection_uri_mutate_event.rs new file mode 100644 index 0000000000000..1de06ce4946c6 --- /dev/null +++ b/types/src/account_config/events/collection_uri_mutate_event.rs @@ -0,0 +1,74 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v1::MoveEventV1Type; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct CollectionUriMutateEvent { + creator_addr: AccountAddress, + collection_name: String, + old_uri: String, + new_uri: String, +} + +impl CollectionUriMutateEvent { + pub fn new( + creator_addr: AccountAddress, + collection_name: String, + old_uri: String, + new_uri: String, + ) -> Self { + Self { + creator_addr, + collection_name, + old_uri, + new_uri, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn creator_addr(&self) -> &AccountAddress { + &self.creator_addr + } + + pub fn collection_name(&self) -> &String { + &self.collection_name + } + + pub fn old_uri(&self) -> &String { + &self.old_uri + } + + pub fn new_uri(&self) -> &String { + &self.new_uri + } +} + +impl MoveStructType for CollectionUriMutateEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("token_event_store"); + const STRUCT_NAME: &'static IdentStr = ident_str!("CollectionUriMutateEvent"); +} + +impl MoveEventV1Type for CollectionUriMutateEvent {} + +pub static COLLECTION_URI_MUTATE_EVENT_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token_event_store").to_owned(), + name: ident_str!("CollectionUriMutateEvent").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/create_collection.rs b/types/src/account_config/events/create_collection.rs new file mode 100644 index 0000000000000..89ebe3e41da4d --- /dev/null +++ b/types/src/account_config/events/create_collection.rs @@ -0,0 +1,81 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v2::MoveEventV2Type; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct CreateCollection { + creator: AccountAddress, + collection_name: String, + uri: String, + description: String, + maximum: u64, +} + +impl CreateCollection { + pub fn new( + creator: AccountAddress, + collection_name: String, + uri: String, + description: String, + maximum: u64, + ) -> Self { + Self { + creator, + collection_name, + uri, + description, + maximum, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn creator(&self) -> &AccountAddress { + &self.creator + } + + pub fn collection_name(&self) -> &String { + &self.collection_name + } + + pub fn uri(&self) -> &String { + &self.uri + } + + pub fn description(&self) -> &String { + &self.description + } + + pub fn maximum(&self) -> u64 { + self.maximum + } +} + +impl MoveStructType for CreateCollection { + const MODULE_NAME: &'static IdentStr = ident_str!("token"); + const STRUCT_NAME: &'static IdentStr = ident_str!("CreateCollection"); +} + +impl MoveEventV2Type for CreateCollection {} + +pub static CREATE_COLLECTION_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token").to_owned(), + name: ident_str!("CreateCollection").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/create_collection_event.rs b/types/src/account_config/events/create_collection_event.rs new file mode 100644 index 0000000000000..a2bae7788cb57 --- /dev/null +++ b/types/src/account_config/events/create_collection_event.rs @@ -0,0 +1,81 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v1::MoveEventV1Type; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct CreateCollectionEvent { + creator: AccountAddress, + collection_name: String, + uri: String, + description: String, + maximum: u64, +} + +impl CreateCollectionEvent { + pub fn new( + creator: AccountAddress, + collection_name: String, + uri: String, + description: String, + maximum: u64, + ) -> Self { + Self { + creator, + collection_name, + uri, + description, + maximum, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn creator(&self) -> &AccountAddress { + &self.creator + } + + pub fn collection_name(&self) -> &String { + &self.collection_name + } + + pub fn uri(&self) -> &String { + &self.uri + } + + pub fn description(&self) -> &String { + &self.description + } + + pub fn maximum(&self) -> u64 { + self.maximum + } +} + +impl MoveStructType for CreateCollectionEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("token"); + const STRUCT_NAME: &'static IdentStr = ident_str!("CreateCollectionEvent"); +} + +impl MoveEventV1Type for CreateCollectionEvent {} + +pub static CREATE_COLLECTION_EVENT_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token").to_owned(), + name: ident_str!("CreateCollectionEvent").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/create_token_data_event.rs b/types/src/account_config/events/create_token_data_event.rs new file mode 100644 index 0000000000000..2ed40791fd34c --- /dev/null +++ b/types/src/account_config/events/create_token_data_event.rs @@ -0,0 +1,133 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::{ + account_config::{TokenDataId, TokenMutabilityConfig}, + move_utils::move_event_v1::MoveEventV1Type, +}; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct CreateTokenDataEvent { + id: TokenDataId, + description: String, + maximum: u64, + uri: String, + royalty_payee_address: AccountAddress, + royalty_points_denominator: u64, + royalty_points_numerator: u64, + name: String, + mutability_config: TokenMutabilityConfig, + property_keys: Vec, + property_values: Vec>, + property_types: Vec, +} + +impl CreateTokenDataEvent { + pub fn new( + id: TokenDataId, + description: String, + maximum: u64, + uri: String, + royalty_payee_address: AccountAddress, + royalty_points_denominator: u64, + royalty_points_numerator: u64, + name: String, + mutability_config: TokenMutabilityConfig, + property_keys: Vec, + property_values: Vec>, + property_types: Vec, + ) -> Self { + Self { + id, + description, + maximum, + uri, + royalty_payee_address, + royalty_points_denominator, + royalty_points_numerator, + name, + mutability_config, + property_keys, + property_values, + property_types, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn id(&self) -> &TokenDataId { + &self.id + } + + pub fn description(&self) -> &String { + &self.description + } + + pub fn maximum(&self) -> u64 { + self.maximum + } + + pub fn uri(&self) -> &String { + &self.uri + } + + pub fn royalty_payee_address(&self) -> &AccountAddress { + &self.royalty_payee_address + } + + pub fn royalty_points_denominator(&self) -> u64 { + self.royalty_points_denominator + } + + pub fn royalty_points_numerator(&self) -> u64 { + self.royalty_points_numerator + } + + pub fn name(&self) -> &String { + &self.name + } + + pub fn mutability_config(&self) -> &TokenMutabilityConfig { + &self.mutability_config + } + + pub fn property_keys(&self) -> &Vec { + &self.property_keys + } + + pub fn property_values(&self) -> &Vec> { + &self.property_values + } + + pub fn property_types(&self) -> &Vec { + &self.property_types + } +} + +impl MoveStructType for CreateTokenDataEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("token"); + const STRUCT_NAME: &'static IdentStr = ident_str!("CreateTokenDataEvent"); +} + +impl MoveEventV1Type for CreateTokenDataEvent {} + +pub static CREATE_TOKEN_DATA_EVENT_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token").to_owned(), + name: ident_str!("CreateTokenDataEvent").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/default_property_mutate.rs b/types/src/account_config/events/default_property_mutate.rs new file mode 100644 index 0000000000000..16bb46299a089 --- /dev/null +++ b/types/src/account_config/events/default_property_mutate.rs @@ -0,0 +1,99 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v2::MoveEventV2Type; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct DefaultPropertyMutate { + creator: AccountAddress, + collection: String, + token: String, + keys: Vec, + old_values: Vec>, + new_values: Vec, +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct OptionType { + vec: Vec, +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct PropertyValue { + value: Vec, + typ: String, +} + +impl DefaultPropertyMutate { + pub fn new( + creator: AccountAddress, + collection: String, + token: String, + keys: Vec, + old_values: Vec>, + new_values: Vec, + ) -> Self { + Self { + creator, + collection, + token, + keys, + old_values, + new_values, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn creator(&self) -> &AccountAddress { + &self.creator + } + + pub fn collection(&self) -> &String { + &self.collection + } + + pub fn token(&self) -> &String { + &self.token + } + + pub fn keys(&self) -> &Vec { + &self.keys + } + + pub fn old_values(&self) -> &Vec> { + &self.old_values + } + + pub fn new_values(&self) -> &Vec { + &self.new_values + } +} + +impl MoveStructType for DefaultPropertyMutate { + const MODULE_NAME: &'static IdentStr = ident_str!("token_event_store"); + const STRUCT_NAME: &'static IdentStr = ident_str!("DefaultPropertyMutate"); +} + +impl MoveEventV2Type for DefaultPropertyMutate {} + +pub static DEFAULT_PROPERTY_MUTATE_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token_event_store").to_owned(), + name: ident_str!("DefaultPropertyMutate").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/default_property_mutate_event.rs b/types/src/account_config/events/default_property_mutate_event.rs new file mode 100644 index 0000000000000..0e430bebad274 --- /dev/null +++ b/types/src/account_config/events/default_property_mutate_event.rs @@ -0,0 +1,91 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::{ + account_config::{OptionType, PropertyValue}, + move_utils::move_event_v1::MoveEventV1Type, +}; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct DefaultPropertyMutateEvent { + creator: AccountAddress, + collection: String, + token: String, + keys: Vec, + old_values: Vec>, + new_values: Vec, +} + +impl DefaultPropertyMutateEvent { + pub fn new( + creator: AccountAddress, + collection: String, + token: String, + keys: Vec, + old_values: Vec>, + new_values: Vec, + ) -> Self { + Self { + creator, + collection, + token, + keys, + old_values, + new_values, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn creator(&self) -> &AccountAddress { + &self.creator + } + + pub fn collection(&self) -> &String { + &self.collection + } + + pub fn token(&self) -> &String { + &self.token + } + + pub fn keys(&self) -> &Vec { + &self.keys + } + + pub fn old_values(&self) -> &Vec> { + &self.old_values + } + + pub fn new_values(&self) -> &Vec { + &self.new_values + } +} + +impl MoveStructType for DefaultPropertyMutateEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("token_event_store"); + const STRUCT_NAME: &'static IdentStr = ident_str!("DefaultPropertyMutateEvent"); +} + +impl MoveEventV1Type for DefaultPropertyMutateEvent {} + +pub static DEFAULT_PROPERTY_MUTATE_EVENT_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token_event_store").to_owned(), + name: ident_str!("DefaultPropertyMutateEvent").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/deposit_event.rs b/types/src/account_config/events/deposit_event.rs new file mode 100644 index 0000000000000..925a534fc9c3e --- /dev/null +++ b/types/src/account_config/events/deposit_event.rs @@ -0,0 +1,49 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v1::MoveEventV1Type; +use anyhow::Result; +use move_core_types::{ + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, CORE_CODE_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize)] +pub struct DepositEvent { + amount: u64, +} + +impl DepositEvent { + pub fn new(amount: u64) -> Self { + Self { amount } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + /// Get the amount sent or received + pub fn amount(&self) -> u64 { + self.amount + } +} + +impl MoveStructType for DepositEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("coin"); + const STRUCT_NAME: &'static IdentStr = ident_str!("DepositEvent"); +} + +impl MoveEventV1Type for DepositEvent {} + +pub static DEPOSIT_EVENT_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: CORE_CODE_ADDRESS, + module: ident_str!("coin").to_owned(), + name: ident_str!("DepositEvent").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/description_mutate.rs b/types/src/account_config/events/description_mutate.rs new file mode 100644 index 0000000000000..a618a4576e00a --- /dev/null +++ b/types/src/account_config/events/description_mutate.rs @@ -0,0 +1,81 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v2::MoveEventV2Type; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct DescriptionMutate { + creator: AccountAddress, + collection: String, + token: String, + old_description: String, + new_description: String, +} + +impl DescriptionMutate { + pub fn new( + creator: AccountAddress, + collection: String, + token: String, + old_description: String, + new_description: String, + ) -> Self { + Self { + creator, + collection, + token, + old_description, + new_description, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn creator(&self) -> &AccountAddress { + &self.creator + } + + pub fn collection(&self) -> &String { + &self.collection + } + + pub fn token(&self) -> &String { + &self.token + } + + pub fn old_description(&self) -> &String { + &self.old_description + } + + pub fn new_description(&self) -> &String { + &self.new_description + } +} + +impl MoveStructType for DescriptionMutate { + const MODULE_NAME: &'static IdentStr = ident_str!("token_event_store"); + const STRUCT_NAME: &'static IdentStr = ident_str!("DescriptionMutate"); +} + +impl MoveEventV2Type for DescriptionMutate {} + +pub static DESCRIPTION_MUTATE_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token_event_store").to_owned(), + name: ident_str!("DescriptionMutate").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/description_mutate_event.rs b/types/src/account_config/events/description_mutate_event.rs new file mode 100644 index 0000000000000..c984a0df37c00 --- /dev/null +++ b/types/src/account_config/events/description_mutate_event.rs @@ -0,0 +1,81 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v1::MoveEventV1Type; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct DescriptionMutateEvent { + creator: AccountAddress, + collection: String, + token: String, + old_description: String, + new_description: String, +} + +impl DescriptionMutateEvent { + pub fn new( + creator: AccountAddress, + collection: String, + token: String, + old_description: String, + new_description: String, + ) -> Self { + Self { + creator, + collection, + token, + old_description, + new_description, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn creator(&self) -> &AccountAddress { + &self.creator + } + + pub fn collection(&self) -> &String { + &self.collection + } + + pub fn token(&self) -> &String { + &self.token + } + + pub fn old_description(&self) -> &String { + &self.old_description + } + + pub fn new_description(&self) -> &String { + &self.new_description + } +} + +impl MoveStructType for DescriptionMutateEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("token_event_store"); + const STRUCT_NAME: &'static IdentStr = ident_str!("DescriptionMutateEvent"); +} + +impl MoveEventV1Type for DescriptionMutateEvent {} + +pub static DESCRIPTION_MUTATE_EVENT_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token_event_store").to_owned(), + name: ident_str!("DescriptionMutateEvent").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/key_rotation.rs b/types/src/account_config/events/key_rotation.rs new file mode 100644 index 0000000000000..c2b24c4564e1e --- /dev/null +++ b/types/src/account_config/events/key_rotation.rs @@ -0,0 +1,55 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v2::MoveEventV2Type; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, CORE_CODE_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize)] +pub struct KeyRotation { + account: AccountAddress, + old_authentication_key: Vec, + new_authentication_key: Vec, +} + +impl KeyRotation { + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn account(&self) -> &AccountAddress { + &self.account + } + + pub fn old_authentication_key(&self) -> &Vec { + &self.old_authentication_key + } + + pub fn new_authentication_key(&self) -> &Vec { + &self.new_authentication_key + } +} + +impl MoveStructType for KeyRotation { + const MODULE_NAME: &'static IdentStr = ident_str!("account"); + const STRUCT_NAME: &'static IdentStr = ident_str!("KeyRotation"); +} + +impl MoveEventV2Type for KeyRotation {} + +pub static KEY_ROTATION_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: CORE_CODE_ADDRESS, + module: ident_str!("account").to_owned(), + name: ident_str!("KeyRotation").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/key_rotation_event.rs b/types/src/account_config/events/key_rotation_event.rs new file mode 100644 index 0000000000000..f9c80ccee5ab2 --- /dev/null +++ b/types/src/account_config/events/key_rotation_event.rs @@ -0,0 +1,56 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v1::MoveEventV1Type; +use anyhow::Result; +use move_core_types::{ + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, CORE_CODE_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize)] +pub struct KeyRotationEvent { + old_authentication_key: Vec, + new_authentication_key: Vec, +} + +impl KeyRotationEvent { + pub fn new(old_authentication_key: Vec, new_authentication_key: Vec) -> Self { + Self { + old_authentication_key, + new_authentication_key, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn old_authentication_key(&self) -> &Vec { + &self.old_authentication_key + } + + pub fn new_authentication_key(&self) -> &Vec { + &self.new_authentication_key + } +} + +impl MoveStructType for KeyRotationEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("account"); + const STRUCT_NAME: &'static IdentStr = ident_str!("KeyRotationEvent"); +} + +impl MoveEventV1Type for KeyRotationEvent {} + +pub static KEY_ROTATION_EVENT_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: CORE_CODE_ADDRESS, + module: ident_str!("account").to_owned(), + name: ident_str!("KeyRotationEvent").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/maximum_mutate.rs b/types/src/account_config/events/maximum_mutate.rs new file mode 100644 index 0000000000000..aba5ea32c8632 --- /dev/null +++ b/types/src/account_config/events/maximum_mutate.rs @@ -0,0 +1,81 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v2::MoveEventV2Type; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct MaximumMutate { + creator: AccountAddress, + collection: String, + token: String, + old_maximum: u64, + new_maximum: u64, +} + +impl MaximumMutate { + pub fn new( + creator: AccountAddress, + collection: String, + token: String, + old_maximum: u64, + new_maximum: u64, + ) -> Self { + Self { + creator, + collection, + token, + old_maximum, + new_maximum, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn creator(&self) -> &AccountAddress { + &self.creator + } + + pub fn collection(&self) -> &String { + &self.collection + } + + pub fn token(&self) -> &String { + &self.token + } + + pub fn old_maximum(&self) -> &u64 { + &self.old_maximum + } + + pub fn new_maximum(&self) -> &u64 { + &self.new_maximum + } +} + +impl MoveStructType for MaximumMutate { + const MODULE_NAME: &'static IdentStr = ident_str!("token_event_store"); + const STRUCT_NAME: &'static IdentStr = ident_str!("MaximumMutate"); +} + +impl MoveEventV2Type for MaximumMutate {} + +pub static MAXIMUM_MUTATE_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token_event_store").to_owned(), + name: ident_str!("MaximumMutate").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/maximum_mutate_event.rs b/types/src/account_config/events/maximum_mutate_event.rs new file mode 100644 index 0000000000000..5774e13a897b8 --- /dev/null +++ b/types/src/account_config/events/maximum_mutate_event.rs @@ -0,0 +1,83 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v1::MoveEventV1Type; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct MaximumMutateEvent { + creator: AccountAddress, + collection: String, + token: String, + old_maximum: u64, + new_maximum: u64, +} + +impl MaximumMutateEvent { + pub fn new( + creator: AccountAddress, + collection: String, + token: String, + old_maximum: u64, + new_maximum: u64, + ) -> Self { + Self { + creator, + collection, + token, + old_maximum, + new_maximum, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn creator(&self) -> &AccountAddress { + &self.creator + } + + pub fn collection(&self) -> &String { + &self.collection + } + + pub fn token(&self) -> &String { + &self.token + } + + pub fn old_maximum(&self) -> &u64 { + &self.old_maximum + } + + pub fn new_maximum(&self) -> &u64 { + &self.new_maximum + } +} + +impl MoveStructType for MaximumMutateEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("token_event_store"); + // The struct name in the Move code contains a typo. + const STRUCT_NAME: &'static IdentStr = ident_str!("MaxiumMutateEvent"); +} + +impl MoveEventV1Type for MaximumMutateEvent {} + +pub static MAXIMUM_MUTATE_EVENT_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token_event_store").to_owned(), + // The struct name in the Move code contains a typo. + name: ident_str!("MaxiumMutateEvent").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/mint.rs b/types/src/account_config/events/mint.rs new file mode 100644 index 0000000000000..e8defcf73f28c --- /dev/null +++ b/types/src/account_config/events/mint.rs @@ -0,0 +1,69 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::{ + account_config::aggregator::AggregatorSnapshotResource, + move_utils::move_event_v2::MoveEventV2Type, +}; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_OBJECTS_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize)] +pub struct Mint { + collection: AccountAddress, + index: AggregatorSnapshotResource, + token: AccountAddress, +} + +impl Mint { + pub fn new( + collection: AccountAddress, + index: AggregatorSnapshotResource, + token: AccountAddress, + ) -> Self { + Self { + collection, + index, + token, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> anyhow::Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn collection(&self) -> &AccountAddress { + &self.collection + } + + pub fn index(&self) -> &AggregatorSnapshotResource { + &self.index + } + + pub fn token(&self) -> &AccountAddress { + &self.token + } +} + +impl MoveStructType for Mint { + const MODULE_NAME: &'static IdentStr = ident_str!("collection"); + const STRUCT_NAME: &'static IdentStr = ident_str!("Mint"); +} + +impl MoveEventV2Type for Mint {} + +pub static MINT_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_OBJECTS_ADDRESS, + module: ident_str!("collection").to_owned(), + name: ident_str!("Mint").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/mint_event.rs b/types/src/account_config/events/mint_event.rs new file mode 100644 index 0000000000000..b68209b30f562 --- /dev/null +++ b/types/src/account_config/events/mint_event.rs @@ -0,0 +1,53 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v1::MoveEventV1Type; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_OBJECTS_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize)] +pub struct MintEvent { + index: u64, + token: AccountAddress, +} + +impl MintEvent { + pub fn new(index: u64, token: AccountAddress) -> Self { + Self { index, token } + } + + pub fn try_from_bytes(bytes: &[u8]) -> anyhow::Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn index(&self) -> &u64 { + &self.index + } + + pub fn token(&self) -> &AccountAddress { + &self.token + } +} + +impl MoveStructType for MintEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("collection"); + const STRUCT_NAME: &'static IdentStr = ident_str!("MintEvent"); +} + +impl MoveEventV1Type for MintEvent {} + +pub static MINT_EVENT_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_OBJECTS_ADDRESS, + module: ident_str!("collection").to_owned(), + name: ident_str!("MintEvent").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/mint_token.rs b/types/src/account_config/events/mint_token.rs new file mode 100644 index 0000000000000..835be186d5234 --- /dev/null +++ b/types/src/account_config/events/mint_token.rs @@ -0,0 +1,63 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::{account_config::TokenDataId, move_utils::move_event_v2::MoveEventV2Type}; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct MintToken { + creator: AccountAddress, + id: TokenDataId, + amount: u64, +} + +impl MintToken { + pub fn new(creator: AccountAddress, id: TokenDataId, amount: u64) -> Self { + Self { + creator, + id, + amount, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn creator(&self) -> &AccountAddress { + &self.creator + } + + pub fn id(&self) -> &TokenDataId { + &self.id + } + + pub fn amount(&self) -> u64 { + self.amount + } +} + +impl MoveStructType for MintToken { + const MODULE_NAME: &'static IdentStr = ident_str!("token"); + const STRUCT_NAME: &'static IdentStr = ident_str!("Mint"); +} + +impl MoveEventV2Type for MintToken {} + +pub static MINT_TOKEN_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token").to_owned(), + name: ident_str!("Mint").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/mint_token_event.rs b/types/src/account_config/events/mint_token_event.rs new file mode 100644 index 0000000000000..83dc126908eb0 --- /dev/null +++ b/types/src/account_config/events/mint_token_event.rs @@ -0,0 +1,53 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::{account_config::TokenDataId, move_utils::move_event_v1::MoveEventV1Type}; +use anyhow::Result; +use move_core_types::{ + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct MintTokenEvent { + id: TokenDataId, + amount: u64, +} + +impl MintTokenEvent { + pub fn new(id: TokenDataId, amount: u64) -> Self { + Self { id, amount } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn id(&self) -> &TokenDataId { + &self.id + } + + pub fn amount(&self) -> u64 { + self.amount + } +} + +impl MoveStructType for MintTokenEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("token"); + const STRUCT_NAME: &'static IdentStr = ident_str!("MintTokenEvent"); +} + +impl MoveEventV1Type for MintTokenEvent {} + +pub static MINT_TOKEN_EVENT_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token").to_owned(), + name: ident_str!("MintTokenEvent").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/mod.rs b/types/src/account_config/events/mod.rs index 83950b07a8774..d350297716b8b 100644 --- a/types/src/account_config/events/mod.rs +++ b/types/src/account_config/events/mod.rs @@ -2,15 +2,125 @@ // Parts of the project are originally copyright © Meta Platforms, Inc. // SPDX-License-Identifier: Apache-2.0 -pub mod coin; +pub mod burn; +pub mod burn_event; +pub mod burn_token; +pub mod burn_token_event; +pub mod cancel_offer; +pub mod claim; +pub mod coin_deposit; +pub mod coin_register; +pub mod coin_register_event; +pub mod coin_withdraw; +pub mod collection_description_mutate; +pub mod collection_description_mutate_event; +pub mod collection_maximum_mutate; +pub mod collection_maximum_mutate_event; +pub mod collection_mutation; +pub mod collection_mutation_event; +pub mod collection_uri_mutate; +pub mod collection_uri_mutate_event; +pub mod create_collection; +pub mod create_collection_event; +pub mod create_token_data_event; +pub mod default_property_mutate; +pub mod default_property_mutate_event; +pub mod deposit_event; +pub mod description_mutate; +pub mod description_mutate_event; pub mod fungible_asset; +pub mod key_rotation; +pub mod key_rotation_event; +pub mod maximum_mutate; +pub mod maximum_mutate_event; +pub mod mint; +pub mod mint_event; +pub mod mint_token; +pub mod mint_token_event; +pub mod mutate_property_map; +pub mod mutate_token_property_map_event; pub mod new_block; pub mod new_epoch; +pub mod offer; +pub mod opt_in_transfer; +pub mod opt_in_transfer_event; +pub mod royalty_mutate; +pub mod royalty_mutate_event; +pub mod token_cancel_offer_event; +pub mod token_claim_event; +pub mod token_data_creation; +pub mod token_deposit; +pub mod token_deposit_event; +pub mod token_mutation; +pub mod token_mutation_event; +pub mod token_offer_event; +pub mod token_withdraw; +pub mod token_withdraw_event; +pub mod transfer; +pub mod transfer_event; +pub mod uri_mutation; +pub mod uri_mutation_event; +pub mod withdraw_event; -pub use coin::*; +pub use burn::*; +pub use burn_event::*; +pub use burn_token::*; +pub use burn_token_event::*; +pub use cancel_offer::*; +pub use claim::*; +pub use coin_deposit::*; +pub use coin_register::*; +pub use coin_register_event::*; +pub use coin_withdraw::*; +pub use collection_description_mutate::*; +pub use collection_description_mutate_event::*; +pub use collection_maximum_mutate::*; +pub use collection_maximum_mutate_event::*; +pub use collection_mutation::*; +pub use collection_mutation_event::*; +pub use collection_uri_mutate::*; +pub use collection_uri_mutate_event::*; +pub use create_collection::*; +pub use create_collection_event::*; +pub use create_token_data_event::*; +pub use default_property_mutate::*; +pub use default_property_mutate_event::*; +pub use deposit_event::*; +pub use description_mutate::*; +pub use description_mutate_event::*; pub use fungible_asset::*; +pub use key_rotation::*; +pub use key_rotation_event::*; +pub use maximum_mutate::*; +pub use maximum_mutate_event::*; +pub use mint::*; +pub use mint_event::*; +pub use mint_token::*; +pub use mint_token_event::*; +pub use mutate_property_map::*; +pub use mutate_token_property_map_event::*; pub use new_block::*; pub use new_epoch::*; +pub use offer::*; +pub use opt_in_transfer::*; +pub use opt_in_transfer_event::*; +pub use royalty_mutate::*; +pub use royalty_mutate_event::*; +pub use token_cancel_offer_event::*; +pub use token_claim_event::*; +pub use token_data_creation::*; +pub use token_deposit::*; +pub use token_deposit_event::*; +pub use token_mutation::*; +pub use token_mutation_event::*; +pub use token_offer_event::*; +pub use token_withdraw::*; +pub use token_withdraw_event::*; +pub use transfer::*; +pub use transfer_event::*; +pub use uri_mutation::*; +pub use uri_mutation_event::*; +pub use withdraw_event::*; pub fn is_aptos_governance_create_proposal_event(event_type: &str) -> bool { event_type == "0x1::aptos_governance::CreateProposal" diff --git a/types/src/account_config/events/mutate_property_map.rs b/types/src/account_config/events/mutate_property_map.rs new file mode 100644 index 0000000000000..5abb900183a21 --- /dev/null +++ b/types/src/account_config/events/mutate_property_map.rs @@ -0,0 +1,88 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::{account_config::TokenId, move_utils::move_event_v2::MoveEventV2Type}; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct MutatePropertyMap { + account: AccountAddress, + old_id: TokenId, + new_id: TokenId, + keys: Vec, + values: Vec>, + types: Vec, +} + +impl MutatePropertyMap { + pub fn new( + account: AccountAddress, + old_id: TokenId, + new_id: TokenId, + keys: Vec, + values: Vec>, + types: Vec, + ) -> Self { + Self { + account, + old_id, + new_id, + keys, + values, + types, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn account(&self) -> &AccountAddress { + &self.account + } + + pub fn old_id(&self) -> &TokenId { + &self.old_id + } + + pub fn new_id(&self) -> &TokenId { + &self.new_id + } + + pub fn keys(&self) -> &Vec { + &self.keys + } + + pub fn values(&self) -> &Vec> { + &self.values + } + + pub fn types(&self) -> &Vec { + &self.types + } +} + +impl MoveStructType for MutatePropertyMap { + const MODULE_NAME: &'static IdentStr = ident_str!("token"); + const STRUCT_NAME: &'static IdentStr = ident_str!("MutatePropertyMap"); +} + +impl MoveEventV2Type for MutatePropertyMap {} + +pub static MUTATE_PROPERTY_MAP_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token").to_owned(), + name: ident_str!("MutatePropertyMap").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/mutate_token_property_map_event.rs b/types/src/account_config/events/mutate_token_property_map_event.rs new file mode 100644 index 0000000000000..e1d6134a477fc --- /dev/null +++ b/types/src/account_config/events/mutate_token_property_map_event.rs @@ -0,0 +1,80 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::{account_config::TokenId, move_utils::move_event_v1::MoveEventV1Type}; +use anyhow::Result; +use move_core_types::{ + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct MutateTokenPropertyMapEvent { + old_id: TokenId, + new_id: TokenId, + keys: Vec, + values: Vec>, + types: Vec, +} + +impl MutateTokenPropertyMapEvent { + pub fn new( + old_id: TokenId, + new_id: TokenId, + keys: Vec, + values: Vec>, + types: Vec, + ) -> Self { + Self { + old_id, + new_id, + keys, + values, + types, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn old_id(&self) -> &TokenId { + &self.old_id + } + + pub fn new_id(&self) -> &TokenId { + &self.new_id + } + + pub fn keys(&self) -> &Vec { + &self.keys + } + + pub fn values(&self) -> &Vec> { + &self.values + } + + pub fn types(&self) -> &Vec { + &self.types + } +} + +impl MoveStructType for MutateTokenPropertyMapEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("token"); + const STRUCT_NAME: &'static IdentStr = ident_str!("MutateTokenPropertyMapEvent"); +} + +impl MoveEventV1Type for MutateTokenPropertyMapEvent {} + +pub static MUTATE_TOKEN_PROPERTY_MAP_EVENT_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token").to_owned(), + name: ident_str!("MutateTokenPropertyMapEvent").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/offer.rs b/types/src/account_config/events/offer.rs new file mode 100644 index 0000000000000..7453a4507c582 --- /dev/null +++ b/types/src/account_config/events/offer.rs @@ -0,0 +1,74 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::{account_config::TokenId, move_utils::move_event_v2::MoveEventV2Type}; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct Offer { + account: AccountAddress, + to_address: AccountAddress, + token_id: TokenId, + amount: u64, +} + +impl Offer { + pub fn new( + account: AccountAddress, + to_address: AccountAddress, + token_id: TokenId, + amount: u64, + ) -> Self { + Self { + account, + to_address, + token_id, + amount, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn account(&self) -> &AccountAddress { + &self.account + } + + pub fn to_address(&self) -> &AccountAddress { + &self.to_address + } + + pub fn token_id(&self) -> &TokenId { + &self.token_id + } + + pub fn amount(&self) -> u64 { + self.amount + } +} + +impl MoveStructType for Offer { + const MODULE_NAME: &'static IdentStr = ident_str!("token_transfers"); + const STRUCT_NAME: &'static IdentStr = ident_str!("Offer"); +} + +impl MoveEventV2Type for Offer {} + +pub static OFFER_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token_transfers").to_owned(), + name: ident_str!("Offer").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/opt_in_transfer.rs b/types/src/account_config/events/opt_in_transfer.rs new file mode 100644 index 0000000000000..1c6bcd0834755 --- /dev/null +++ b/types/src/account_config/events/opt_in_transfer.rs @@ -0,0 +1,57 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v2::MoveEventV2Type; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct OptInTransfer { + account_address: AccountAddress, + opt_in: bool, +} + +impl OptInTransfer { + pub fn new(account_address: AccountAddress, opt_in: bool) -> Self { + Self { + account_address, + opt_in, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn account_address(&self) -> &AccountAddress { + &self.account_address + } + + pub fn opt_in(&self) -> &bool { + &self.opt_in + } +} + +impl MoveStructType for OptInTransfer { + const MODULE_NAME: &'static IdentStr = ident_str!("token_event_store"); + const STRUCT_NAME: &'static IdentStr = ident_str!("OptInTransfer"); +} + +impl MoveEventV2Type for OptInTransfer {} + +pub static OPT_IN_TRANSFER_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token_event_store").to_owned(), + name: ident_str!("OptInTransfer").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/opt_in_transfer_event.rs b/types/src/account_config/events/opt_in_transfer_event.rs new file mode 100644 index 0000000000000..06156b8eafc71 --- /dev/null +++ b/types/src/account_config/events/opt_in_transfer_event.rs @@ -0,0 +1,48 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v1::MoveEventV1Type; +use anyhow::Result; +use move_core_types::{ + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct OptInTransferEvent { + opt_in: bool, +} + +impl OptInTransferEvent { + pub fn new(opt_in: bool) -> Self { + Self { opt_in } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn opt_in(&self) -> &bool { + &self.opt_in + } +} + +impl MoveStructType for OptInTransferEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("token_event_store"); + const STRUCT_NAME: &'static IdentStr = ident_str!("OptInTransferEvent"); +} + +impl MoveEventV1Type for OptInTransferEvent {} + +pub static OPT_IN_TRANSFER_EVENT_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token_event_store").to_owned(), + name: ident_str!("OptInTransferEvent").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/royalty_mutate.rs b/types/src/account_config/events/royalty_mutate.rs new file mode 100644 index 0000000000000..813abc5978e11 --- /dev/null +++ b/types/src/account_config/events/royalty_mutate.rs @@ -0,0 +1,109 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v2::MoveEventV2Type; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct RoyaltyMutate { + creator: AccountAddress, + collection: String, + token: String, + old_royalty_numerator: u64, + old_royalty_denominator: u64, + old_royalty_payee_addr: AccountAddress, + new_royalty_numerator: u64, + new_royalty_denominator: u64, + new_royalty_payee_addr: AccountAddress, +} + +impl RoyaltyMutate { + pub fn new( + creator: AccountAddress, + collection: String, + token: String, + old_royalty_numerator: u64, + old_royalty_denominator: u64, + old_royalty_payee_addr: AccountAddress, + new_royalty_numerator: u64, + new_royalty_denominator: u64, + new_royalty_payee_addr: AccountAddress, + ) -> Self { + Self { + creator, + collection, + token, + old_royalty_numerator, + old_royalty_denominator, + old_royalty_payee_addr, + new_royalty_numerator, + new_royalty_denominator, + new_royalty_payee_addr, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn creator(&self) -> &AccountAddress { + &self.creator + } + + pub fn collection(&self) -> &String { + &self.collection + } + + pub fn token(&self) -> &String { + &self.token + } + + pub fn old_royalty_numerator(&self) -> &u64 { + &self.old_royalty_numerator + } + + pub fn old_royalty_denominator(&self) -> &u64 { + &self.old_royalty_denominator + } + + pub fn old_royalty_payee_addr(&self) -> &AccountAddress { + &self.old_royalty_payee_addr + } + + pub fn new_royalty_numerator(&self) -> &u64 { + &self.new_royalty_numerator + } + + pub fn new_royalty_denominator(&self) -> &u64 { + &self.new_royalty_denominator + } + + pub fn new_royalty_payee_addr(&self) -> &AccountAddress { + &self.new_royalty_payee_addr + } +} + +impl MoveStructType for RoyaltyMutate { + const MODULE_NAME: &'static IdentStr = ident_str!("token_event_store"); + const STRUCT_NAME: &'static IdentStr = ident_str!("RoyaltyMutate"); +} + +impl MoveEventV2Type for RoyaltyMutate {} + +pub static ROYALTY_MUTATE_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token_event_store").to_owned(), + name: ident_str!("RoyaltyMutate").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/royalty_mutate_event.rs b/types/src/account_config/events/royalty_mutate_event.rs new file mode 100644 index 0000000000000..b6d86f7b71f3c --- /dev/null +++ b/types/src/account_config/events/royalty_mutate_event.rs @@ -0,0 +1,109 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v1::MoveEventV1Type; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct RoyaltyMutateEvent { + creator: AccountAddress, + collection: String, + token: String, + old_royalty_numerator: u64, + old_royalty_denominator: u64, + old_royalty_payee_addr: AccountAddress, + new_royalty_numerator: u64, + new_royalty_denominator: u64, + new_royalty_payee_addr: AccountAddress, +} + +impl RoyaltyMutateEvent { + pub fn new( + creator: AccountAddress, + collection: String, + token: String, + old_royalty_numerator: u64, + old_royalty_denominator: u64, + old_royalty_payee_addr: AccountAddress, + new_royalty_numerator: u64, + new_royalty_denominator: u64, + new_royalty_payee_addr: AccountAddress, + ) -> Self { + Self { + creator, + collection, + token, + old_royalty_numerator, + old_royalty_denominator, + old_royalty_payee_addr, + new_royalty_numerator, + new_royalty_denominator, + new_royalty_payee_addr, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn creator(&self) -> &AccountAddress { + &self.creator + } + + pub fn collection(&self) -> &String { + &self.collection + } + + pub fn token(&self) -> &String { + &self.token + } + + pub fn old_royalty_numerator(&self) -> &u64 { + &self.old_royalty_numerator + } + + pub fn old_royalty_denominator(&self) -> &u64 { + &self.old_royalty_denominator + } + + pub fn old_royalty_payee_addr(&self) -> &AccountAddress { + &self.old_royalty_payee_addr + } + + pub fn new_royalty_numerator(&self) -> &u64 { + &self.new_royalty_numerator + } + + pub fn new_royalty_denominator(&self) -> &u64 { + &self.new_royalty_denominator + } + + pub fn new_royalty_payee_addr(&self) -> &AccountAddress { + &self.new_royalty_payee_addr + } +} + +impl MoveStructType for RoyaltyMutateEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("token_event_store"); + const STRUCT_NAME: &'static IdentStr = ident_str!("RoyaltyMutateEvent"); +} + +impl MoveEventV1Type for RoyaltyMutateEvent {} + +pub static ROYALTY_MUTATE_EVENT_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token_event_store").to_owned(), + name: ident_str!("RoyaltyMutateEvent").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/token_cancel_offer_event.rs b/types/src/account_config/events/token_cancel_offer_event.rs new file mode 100644 index 0000000000000..b902cdf1893e8 --- /dev/null +++ b/types/src/account_config/events/token_cancel_offer_event.rs @@ -0,0 +1,63 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::{account_config::TokenId, move_utils::move_event_v1::MoveEventV1Type}; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct TokenCancelOfferEvent { + to_address: AccountAddress, + token_id: TokenId, + amount: u64, +} + +impl TokenCancelOfferEvent { + pub fn new(to_address: AccountAddress, token_id: TokenId, amount: u64) -> Self { + Self { + to_address, + token_id, + amount, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn to_address(&self) -> &AccountAddress { + &self.to_address + } + + pub fn token_id(&self) -> &TokenId { + &self.token_id + } + + pub fn amount(&self) -> u64 { + self.amount + } +} + +impl MoveStructType for TokenCancelOfferEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("token_transfers"); + const STRUCT_NAME: &'static IdentStr = ident_str!("TokenCancelOfferEvent"); +} + +impl MoveEventV1Type for TokenCancelOfferEvent {} + +pub static TOKEN_CANCEL_OFFER_EVENT_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token_transfers").to_owned(), + name: ident_str!("TokenCancelOfferEvent").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/token_claim_event.rs b/types/src/account_config/events/token_claim_event.rs new file mode 100644 index 0000000000000..83ce8cf8ddc06 --- /dev/null +++ b/types/src/account_config/events/token_claim_event.rs @@ -0,0 +1,63 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::{account_config::TokenId, move_utils::move_event_v1::MoveEventV1Type}; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct TokenClaimEvent { + to_address: AccountAddress, + token_id: TokenId, + amount: u64, +} + +impl TokenClaimEvent { + pub fn new(to_address: AccountAddress, token_id: TokenId, amount: u64) -> Self { + Self { + to_address, + token_id, + amount, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn to_address(&self) -> &AccountAddress { + &self.to_address + } + + pub fn token_id(&self) -> &TokenId { + &self.token_id + } + + pub fn amount(&self) -> u64 { + self.amount + } +} + +impl MoveStructType for TokenClaimEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("token_transfers"); + const STRUCT_NAME: &'static IdentStr = ident_str!("TokenClaimEvent"); +} + +impl MoveEventV1Type for TokenClaimEvent {} + +pub static TOKEN_CLAIM_EVENT_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token_transfers").to_owned(), + name: ident_str!("TokenClaimEvent").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/token_data_creation.rs b/types/src/account_config/events/token_data_creation.rs new file mode 100644 index 0000000000000..ac87b5cadf505 --- /dev/null +++ b/types/src/account_config/events/token_data_creation.rs @@ -0,0 +1,145 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::{account_config::TokenDataId, move_utils::move_event_v2::MoveEventV2Type}; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct TokenDataCreation { + creator: AccountAddress, + id: TokenDataId, + description: String, + maximum: u64, + uri: String, + royalty_payee_address: AccountAddress, + royalty_points_denominator: u64, + royalty_points_numerator: u64, + name: String, + mutability_config: TokenMutabilityConfig, + property_keys: Vec, + property_values: Vec>, + property_types: Vec, +} +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct TokenMutabilityConfig { + maximum: bool, + uri: bool, + royalty: bool, + description: bool, + properties: bool, +} + +impl TokenDataCreation { + pub fn new( + creator: AccountAddress, + id: TokenDataId, + description: String, + maximum: u64, + uri: String, + royalty_payee_address: AccountAddress, + royalty_points_denominator: u64, + royalty_points_numerator: u64, + name: String, + mutability_config: TokenMutabilityConfig, + property_keys: Vec, + property_values: Vec>, + property_types: Vec, + ) -> Self { + Self { + creator, + id, + description, + maximum, + uri, + royalty_payee_address, + royalty_points_denominator, + royalty_points_numerator, + name, + mutability_config, + property_keys, + property_values, + property_types, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn creator(&self) -> &AccountAddress { + &self.creator + } + + pub fn id(&self) -> &TokenDataId { + &self.id + } + + pub fn description(&self) -> &String { + &self.description + } + + pub fn maximum(&self) -> u64 { + self.maximum + } + + pub fn uri(&self) -> &String { + &self.uri + } + + pub fn royalty_payee_address(&self) -> &AccountAddress { + &self.royalty_payee_address + } + + pub fn royalty_points_denominator(&self) -> u64 { + self.royalty_points_denominator + } + + pub fn royalty_points_numerator(&self) -> u64 { + self.royalty_points_numerator + } + + pub fn name(&self) -> &String { + &self.name + } + + pub fn mutability_config(&self) -> &TokenMutabilityConfig { + &self.mutability_config + } + + pub fn property_keys(&self) -> &Vec { + &self.property_keys + } + + pub fn property_values(&self) -> &Vec> { + &self.property_values + } + + pub fn property_types(&self) -> &Vec { + &self.property_types + } +} + +impl MoveStructType for TokenDataCreation { + const MODULE_NAME: &'static IdentStr = ident_str!("token"); + const STRUCT_NAME: &'static IdentStr = ident_str!("TokenDataCreation"); +} + +impl MoveEventV2Type for TokenDataCreation {} + +pub static TOKEN_DATA_CREATION_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token").to_owned(), + name: ident_str!("TokenDataCreation").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/token_deposit.rs b/types/src/account_config/events/token_deposit.rs new file mode 100644 index 0000000000000..06e2afb1a39a1 --- /dev/null +++ b/types/src/account_config/events/token_deposit.rs @@ -0,0 +1,76 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v2::MoveEventV2Type; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct TokenDeposit { + account: AccountAddress, + id: TokenId, + amount: u64, +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct TokenId { + token_data_id: TokenDataId, + property_version: u64, +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct TokenDataId { + creator: AccountAddress, + collection: String, + name: String, +} + +impl TokenDeposit { + pub fn new(account: AccountAddress, id: TokenId, amount: u64) -> Self { + Self { + account, + id, + amount, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn account(&self) -> &AccountAddress { + &self.account + } + + pub fn id(&self) -> &TokenId { + &self.id + } + + pub fn amount(&self) -> u64 { + self.amount + } +} + +impl MoveStructType for TokenDeposit { + const MODULE_NAME: &'static IdentStr = ident_str!("token"); + const STRUCT_NAME: &'static IdentStr = ident_str!("TokenDeposit"); +} + +impl MoveEventV2Type for TokenDeposit {} + +pub static TOKEN_DEPOSIT_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token").to_owned(), + name: ident_str!("TokenDeposit").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/token_deposit_event.rs b/types/src/account_config/events/token_deposit_event.rs new file mode 100644 index 0000000000000..88c2472737c69 --- /dev/null +++ b/types/src/account_config/events/token_deposit_event.rs @@ -0,0 +1,53 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::{account_config::TokenId, move_utils::move_event_v1::MoveEventV1Type}; +use anyhow::Result; +use move_core_types::{ + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct TokenDepositEvent { + id: TokenId, + amount: u64, +} + +impl TokenDepositEvent { + pub fn new(id: TokenId, amount: u64) -> Self { + Self { id, amount } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn id(&self) -> &TokenId { + &self.id + } + + pub fn amount(&self) -> u64 { + self.amount + } +} + +impl MoveStructType for TokenDepositEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("token"); + const STRUCT_NAME: &'static IdentStr = ident_str!("DepositEvent"); +} + +impl MoveEventV1Type for TokenDepositEvent {} + +pub static TOKEN_DEPOSIT_EVENT_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token").to_owned(), + name: ident_str!("DepositEvent").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/token_mutation.rs b/types/src/account_config/events/token_mutation.rs new file mode 100644 index 0000000000000..da044a4ccb598 --- /dev/null +++ b/types/src/account_config/events/token_mutation.rs @@ -0,0 +1,73 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v2::MoveEventV2Type; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_OBJECTS_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +pub struct TokenMutation { + token_address: AccountAddress, + mutated_field_name: String, + old_value: String, + new_value: String, +} + +impl TokenMutation { + pub fn new( + token_address: AccountAddress, + mutated_field_name: String, + old_value: String, + new_value: String, + ) -> Self { + Self { + token_address, + mutated_field_name, + old_value, + new_value, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> anyhow::Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn token_address(&self) -> &AccountAddress { + &self.token_address + } + + pub fn mutated_field_name(&self) -> &String { + &self.mutated_field_name + } + + pub fn old_value(&self) -> &String { + &self.old_value + } + + pub fn new_value(&self) -> &String { + &self.new_value + } +} + +impl MoveStructType for TokenMutation { + const MODULE_NAME: &'static IdentStr = ident_str!("token"); + const STRUCT_NAME: &'static IdentStr = ident_str!("Mutation"); +} + +impl MoveEventV2Type for TokenMutation {} + +pub static TOKEN_MUTATION_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_OBJECTS_ADDRESS, + module: ident_str!("token").to_owned(), + name: ident_str!("Mutation").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/token_mutation_event.rs b/types/src/account_config/events/token_mutation_event.rs new file mode 100644 index 0000000000000..557ec7aebc6fc --- /dev/null +++ b/types/src/account_config/events/token_mutation_event.rs @@ -0,0 +1,61 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v1::MoveEventV1Type; +use move_core_types::{ + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_OBJECTS_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +pub struct TokenMutationEvent { + mutated_field_name: String, + old_value: String, + new_value: String, +} + +impl TokenMutationEvent { + pub fn new(mutated_field_name: String, old_value: String, new_value: String) -> Self { + Self { + mutated_field_name, + old_value, + new_value, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> anyhow::Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn mutated_field_name(&self) -> &String { + &self.mutated_field_name + } + + pub fn old_value(&self) -> &String { + &self.old_value + } + + pub fn new_value(&self) -> &String { + &self.new_value + } +} + +impl MoveStructType for TokenMutationEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("token"); + const STRUCT_NAME: &'static IdentStr = ident_str!("MutationEvent"); +} + +impl MoveEventV1Type for TokenMutationEvent {} + +pub static TOKEN_MUTATION_EVENT_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_OBJECTS_ADDRESS, + module: ident_str!("token").to_owned(), + name: ident_str!("MutationEvent").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/token_offer_event.rs b/types/src/account_config/events/token_offer_event.rs new file mode 100644 index 0000000000000..c2f8d391c3941 --- /dev/null +++ b/types/src/account_config/events/token_offer_event.rs @@ -0,0 +1,63 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::{account_config::TokenId, move_utils::move_event_v1::MoveEventV1Type}; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct TokenOfferEvent { + to_address: AccountAddress, + token_id: TokenId, + amount: u64, +} + +impl TokenOfferEvent { + pub fn new(to_address: AccountAddress, token_id: TokenId, amount: u64) -> Self { + Self { + to_address, + token_id, + amount, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn to_address(&self) -> &AccountAddress { + &self.to_address + } + + pub fn token_id(&self) -> &TokenId { + &self.token_id + } + + pub fn amount(&self) -> u64 { + self.amount + } +} + +impl MoveStructType for TokenOfferEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("token_transfers"); + const STRUCT_NAME: &'static IdentStr = ident_str!("TokenOfferEvent"); +} + +impl MoveEventV1Type for TokenOfferEvent {} + +pub static TOKEN_OFFER_EVENT_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token_transfers").to_owned(), + name: ident_str!("TokenOfferEvent").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/token_withdraw.rs b/types/src/account_config/events/token_withdraw.rs new file mode 100644 index 0000000000000..6ad71998de35c --- /dev/null +++ b/types/src/account_config/events/token_withdraw.rs @@ -0,0 +1,63 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::{account_config::TokenId, move_utils::move_event_v2::MoveEventV2Type}; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct TokenWithdraw { + account: AccountAddress, + id: TokenId, + amount: u64, +} + +impl TokenWithdraw { + pub fn new(account: AccountAddress, id: TokenId, amount: u64) -> Self { + Self { + account, + id, + amount, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn account(&self) -> &AccountAddress { + &self.account + } + + pub fn id(&self) -> &TokenId { + &self.id + } + + pub fn amount(&self) -> u64 { + self.amount + } +} + +impl MoveStructType for TokenWithdraw { + const MODULE_NAME: &'static IdentStr = ident_str!("token"); + const STRUCT_NAME: &'static IdentStr = ident_str!("TokenWithdraw"); +} + +impl MoveEventV2Type for TokenWithdraw {} + +pub static TOKEN_WITHDRAW_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token").to_owned(), + name: ident_str!("TokenWithdraw").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/token_withdraw_event.rs b/types/src/account_config/events/token_withdraw_event.rs new file mode 100644 index 0000000000000..3a81da0200e44 --- /dev/null +++ b/types/src/account_config/events/token_withdraw_event.rs @@ -0,0 +1,53 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::{account_config::TokenId, move_utils::move_event_v1::MoveEventV1Type}; +use anyhow::Result; +use move_core_types::{ + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct TokenWithdrawEvent { + id: TokenId, + amount: u64, +} + +impl TokenWithdrawEvent { + pub fn new(id: TokenId, amount: u64) -> Self { + Self { id, amount } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn id(&self) -> &TokenId { + &self.id + } + + pub fn amount(&self) -> u64 { + self.amount + } +} + +impl MoveStructType for TokenWithdrawEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("token"); + const STRUCT_NAME: &'static IdentStr = ident_str!("WithdrawEvent"); +} + +impl MoveEventV1Type for TokenWithdrawEvent {} + +pub static TOKEN_WITHDRAW_EVENT_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token").to_owned(), + name: ident_str!("WithdrawEvent").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/transfer.rs b/types/src/account_config/events/transfer.rs new file mode 100644 index 0000000000000..2ed4d65046d8f --- /dev/null +++ b/types/src/account_config/events/transfer.rs @@ -0,0 +1,58 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v2::MoveEventV2Type; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, CORE_CODE_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +pub struct Transfer { + object: AccountAddress, + from: AccountAddress, + to: AccountAddress, +} + +impl Transfer { + pub fn new(object: AccountAddress, from: AccountAddress, to: AccountAddress) -> Self { + Self { object, from, to } + } + + pub fn try_from_bytes(bytes: &[u8]) -> anyhow::Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn object(&self) -> &AccountAddress { + &self.object + } + + pub fn from(&self) -> &AccountAddress { + &self.from + } + + pub fn to(&self) -> &AccountAddress { + &self.to + } +} + +impl MoveStructType for Transfer { + const MODULE_NAME: &'static IdentStr = ident_str!("object"); + const STRUCT_NAME: &'static IdentStr = ident_str!("Transfer"); +} + +impl MoveEventV2Type for Transfer {} + +pub static TRANSFER_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: CORE_CODE_ADDRESS, + module: ident_str!("object").to_owned(), + name: ident_str!("Transfer").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/transfer_event.rs b/types/src/account_config/events/transfer_event.rs new file mode 100644 index 0000000000000..e805ec1ffc177 --- /dev/null +++ b/types/src/account_config/events/transfer_event.rs @@ -0,0 +1,58 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v1::MoveEventV1Type; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, CORE_CODE_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +pub struct TransferEvent { + object: AccountAddress, + from: AccountAddress, + to: AccountAddress, +} + +impl TransferEvent { + pub fn new(object: AccountAddress, from: AccountAddress, to: AccountAddress) -> Self { + Self { object, from, to } + } + + pub fn try_from_bytes(bytes: &[u8]) -> anyhow::Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn object(&self) -> &AccountAddress { + &self.object + } + + pub fn from(&self) -> &AccountAddress { + &self.from + } + + pub fn to(&self) -> &AccountAddress { + &self.to + } +} + +impl MoveStructType for TransferEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("object"); + const STRUCT_NAME: &'static IdentStr = ident_str!("TransferEvent"); +} + +impl MoveEventV1Type for TransferEvent {} + +pub static TRANSFER_EVENT_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: CORE_CODE_ADDRESS, + module: ident_str!("object").to_owned(), + name: ident_str!("TransferEvent").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/uri_mutation.rs b/types/src/account_config/events/uri_mutation.rs new file mode 100644 index 0000000000000..dc67b99337c39 --- /dev/null +++ b/types/src/account_config/events/uri_mutation.rs @@ -0,0 +1,81 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v2::MoveEventV2Type; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct UriMutation { + creator: AccountAddress, + collection: String, + token: String, + old_uri: String, + new_uri: String, +} + +impl UriMutation { + pub fn new( + creator: AccountAddress, + collection: String, + token: String, + old_uri: String, + new_uri: String, + ) -> Self { + Self { + creator, + collection, + token, + old_uri, + new_uri, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn creator(&self) -> &AccountAddress { + &self.creator + } + + pub fn collection(&self) -> &String { + &self.collection + } + + pub fn token(&self) -> &String { + &self.token + } + + pub fn old_uri(&self) -> &String { + &self.old_uri + } + + pub fn new_uri(&self) -> &String { + &self.new_uri + } +} + +impl MoveStructType for UriMutation { + const MODULE_NAME: &'static IdentStr = ident_str!("token_event_store"); + const STRUCT_NAME: &'static IdentStr = ident_str!("UriMutation"); +} + +impl MoveEventV2Type for UriMutation {} + +pub static URI_MUTATION_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token_event_store").to_owned(), + name: ident_str!("UriMutation").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/uri_mutation_event.rs b/types/src/account_config/events/uri_mutation_event.rs new file mode 100644 index 0000000000000..4bb25e0ccc7eb --- /dev/null +++ b/types/src/account_config/events/uri_mutation_event.rs @@ -0,0 +1,81 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v1::MoveEventV1Type; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, TOKEN_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct UriMutationEvent { + creator: AccountAddress, + collection: String, + token: String, + old_uri: String, + new_uri: String, +} + +impl UriMutationEvent { + pub fn new( + creator: AccountAddress, + collection: String, + token: String, + old_uri: String, + new_uri: String, + ) -> Self { + Self { + creator, + collection, + token, + old_uri, + new_uri, + } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn creator(&self) -> &AccountAddress { + &self.creator + } + + pub fn collection(&self) -> &String { + &self.collection + } + + pub fn token(&self) -> &String { + &self.token + } + + pub fn old_uri(&self) -> &String { + &self.old_uri + } + + pub fn new_uri(&self) -> &String { + &self.new_uri + } +} + +impl MoveStructType for UriMutationEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("token_event_store"); + const STRUCT_NAME: &'static IdentStr = ident_str!("UriMutationEvent"); +} + +impl MoveEventV1Type for UriMutationEvent {} + +pub static URI_MUTATION_EVENT_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: TOKEN_ADDRESS, + module: ident_str!("token_event_store").to_owned(), + name: ident_str!("UriMutationEvent").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/events/withdraw_event.rs b/types/src/account_config/events/withdraw_event.rs new file mode 100644 index 0000000000000..ff386b8f97d68 --- /dev/null +++ b/types/src/account_config/events/withdraw_event.rs @@ -0,0 +1,49 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v1::MoveEventV1Type; +use anyhow::Result; +use move_core_types::{ + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, CORE_CODE_ADDRESS}, + move_resource::MoveStructType, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +/// Struct that represents a SentPaymentEvent. +#[derive(Debug, Serialize, Deserialize)] +pub struct WithdrawEvent { + amount: u64, +} + +impl WithdrawEvent { + pub fn new(amount: u64) -> Self { + Self { amount } + } + + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + pub fn amount(&self) -> u64 { + self.amount + } +} + +impl MoveStructType for WithdrawEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("coin"); + const STRUCT_NAME: &'static IdentStr = ident_str!("WithdrawEvent"); +} + +impl MoveEventV1Type for WithdrawEvent {} + +pub static WITHDRAW_EVENT_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: CORE_CODE_ADDRESS, + module: ident_str!("coin").to_owned(), + name: ident_str!("WithdrawEvent").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/resources/aggregator.rs b/types/src/account_config/resources/aggregator.rs index cf8fdcc34c023..794d29ca52ac0 100644 --- a/types/src/account_config/resources/aggregator.rs +++ b/types/src/account_config/resources/aggregator.rs @@ -27,7 +27,7 @@ impl AggregatorResource { #[derive(Debug, Serialize, Deserialize)] pub struct AggregatorSnapshotResource { - value: T, + pub value: T, } #[derive(Debug, Serialize, Deserialize)] diff --git a/types/src/account_config/resources/any.rs b/types/src/account_config/resources/any.rs new file mode 100644 index 0000000000000..719a92b13f8d9 --- /dev/null +++ b/types/src/account_config/resources/any.rs @@ -0,0 +1,40 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use anyhow::Result; +use move_core_types::{ + ident_str, + identifier::IdentStr, + language_storage::{StructTag, TypeTag, CORE_CODE_ADDRESS}, + move_resource::{MoveResource, MoveStructType}, +}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] +pub struct AnyResource { + type_name: String, + data: Vec, +} + +impl AnyResource { + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } +} + +impl MoveStructType for AnyResource { + const MODULE_NAME: &'static IdentStr = ident_str!("any"); + const STRUCT_NAME: &'static IdentStr = ident_str!("Any"); +} + +impl MoveResource for AnyResource {} + +pub static ANY_RESOURCE_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: CORE_CODE_ADDRESS, + module: ident_str!("any").to_owned(), + name: ident_str!("Any").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/resources/collection.rs b/types/src/account_config/resources/collection.rs new file mode 100644 index 0000000000000..a975b27db4651 --- /dev/null +++ b/types/src/account_config/resources/collection.rs @@ -0,0 +1,65 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::event::EventHandle; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + move_resource::{MoveResource, MoveStructType}, +}; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Eq, PartialEq, Serialize, Deserialize)] +pub struct CollectionResource { + creator: AccountAddress, + description: String, + name: String, + uri: String, + mutation_events: EventHandle, +} + +impl CollectionResource { + pub fn new( + creator: AccountAddress, + description: String, + name: String, + uri: String, + mutation_events: EventHandle, + ) -> Self { + Self { + creator, + description, + name, + uri, + mutation_events, + } + } + + pub fn creator(&self) -> &AccountAddress { + &self.creator + } + + pub fn description(&self) -> &String { + &self.description + } + + pub fn name(&self) -> &String { + &self.name + } + + pub fn uri(&self) -> &String { + &self.uri + } + + pub fn mutation_events(&self) -> &EventHandle { + &self.mutation_events + } +} + +impl MoveStructType for CollectionResource { + const MODULE_NAME: &'static IdentStr = ident_str!("collection"); + const STRUCT_NAME: &'static IdentStr = ident_str!("Collection"); +} + +impl MoveResource for CollectionResource {} diff --git a/types/src/account_config/resources/collections.rs b/types/src/account_config/resources/collections.rs new file mode 100644 index 0000000000000..0f9f958f282d2 --- /dev/null +++ b/types/src/account_config/resources/collections.rs @@ -0,0 +1,64 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::{account_config::Table, event::EventHandle}; +use move_core_types::{ + ident_str, + identifier::IdentStr, + move_resource::{MoveResource, MoveStructType}, +}; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize)] +pub struct CollectionsResource { + collection_data: Table, + token_data: Table, + create_collection_events: EventHandle, + create_token_data_events: EventHandle, + mint_token_events: EventHandle, +} + +impl CollectionsResource { + pub fn new( + collection_data: Table, + token_data: Table, + create_collection_events: EventHandle, + create_token_data_events: EventHandle, + mint_token_events: EventHandle, + ) -> Self { + Self { + collection_data, + token_data, + create_collection_events, + create_token_data_events, + mint_token_events, + } + } + + pub fn collection_data(&self) -> &Table { + &self.collection_data + } + + pub fn token_data(&self) -> &Table { + &self.token_data + } + + pub fn create_collection_events(&self) -> &EventHandle { + &self.create_collection_events + } + + pub fn create_token_data_events(&self) -> &EventHandle { + &self.create_token_data_events + } + + pub fn mint_token_events(&self) -> &EventHandle { + &self.mint_token_events + } +} + +impl MoveStructType for CollectionsResource { + const MODULE_NAME: &'static IdentStr = ident_str!("token"); + const STRUCT_NAME: &'static IdentStr = ident_str!("Collections"); +} + +impl MoveResource for CollectionsResource {} diff --git a/types/src/account_config/resources/fixed_supply.rs b/types/src/account_config/resources/fixed_supply.rs new file mode 100644 index 0000000000000..9b37151c96da2 --- /dev/null +++ b/types/src/account_config/resources/fixed_supply.rs @@ -0,0 +1,64 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::event::EventHandle; +use move_core_types::{ + ident_str, + identifier::IdentStr, + move_resource::{MoveResource, MoveStructType}, +}; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Eq, PartialEq, Serialize, Deserialize)] +pub struct FixedSupplyResource { + current_supply: u64, + max_supply: u64, + total_minted: u64, + burn_events: EventHandle, + mint_events: EventHandle, +} + +impl FixedSupplyResource { + pub fn new( + current_supply: u64, + max_supply: u64, + total_minted: u64, + burn_events: EventHandle, + mint_events: EventHandle, + ) -> Self { + Self { + current_supply, + max_supply, + total_minted, + burn_events, + mint_events, + } + } + + pub fn current_supply(&self) -> u64 { + self.current_supply + } + + pub fn max_supply(&self) -> u64 { + self.max_supply + } + + pub fn total_minted(&self) -> u64 { + self.total_minted + } + + pub fn burn_events(&self) -> &EventHandle { + &self.burn_events + } + + pub fn mint_events(&self) -> &EventHandle { + &self.mint_events + } +} + +impl MoveStructType for FixedSupplyResource { + const MODULE_NAME: &'static IdentStr = ident_str!("collection"); + const STRUCT_NAME: &'static IdentStr = ident_str!("FixedSupply"); +} + +impl MoveResource for FixedSupplyResource {} diff --git a/types/src/account_config/resources/mod.rs b/types/src/account_config/resources/mod.rs index cbe90b7599639..8f2ea28eaca5f 100644 --- a/types/src/account_config/resources/mod.rs +++ b/types/src/account_config/resources/mod.rs @@ -3,22 +3,41 @@ // SPDX-License-Identifier: Apache-2.0 pub mod aggregator; +pub mod any; pub mod chain_id; pub mod challenge; pub mod coin_info; pub mod coin_store; +pub mod collection; +pub mod collections; pub mod core_account; +pub mod fixed_supply; pub mod fungible_asset_metadata; pub mod fungible_store; pub mod object; +pub mod pending_claims; +pub mod token; +pub mod token_event_store_v1; +pub mod token_store; pub mod type_info; +pub mod unlimited_supply; +pub use aggregator::*; +pub use any::*; pub use chain_id::*; pub use challenge::*; pub use coin_info::*; pub use coin_store::*; +pub use collection::*; +pub use collections::*; pub use core_account::*; +pub use fixed_supply::*; pub use fungible_asset_metadata::*; pub use fungible_store::*; pub use object::*; +pub use pending_claims::*; +pub use token::*; +pub use token_event_store_v1::*; +pub use token_store::*; pub use type_info::*; +pub use unlimited_supply::*; diff --git a/types/src/account_config/resources/object.rs b/types/src/account_config/resources/object.rs index e2e821844e547..e6179af601fdf 100644 --- a/types/src/account_config/resources/object.rs +++ b/types/src/account_config/resources/object.rs @@ -61,6 +61,10 @@ impl ObjectCoreResource { transfer_events, } } + + pub fn transfer_events(&self) -> &EventHandle { + &self.transfer_events + } } impl MoveStructType for ObjectCoreResource { @@ -69,3 +73,18 @@ impl MoveStructType for ObjectCoreResource { } impl MoveResource for ObjectCoreResource {} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct Object { + inner: AccountAddress, +} + +impl Object { + pub fn new(inner: AccountAddress) -> Self { + Self { inner } + } + + pub fn inner(&self) -> &AccountAddress { + &self.inner + } +} diff --git a/types/src/account_config/resources/pending_claims.rs b/types/src/account_config/resources/pending_claims.rs new file mode 100644 index 0000000000000..3f1c6adb23772 --- /dev/null +++ b/types/src/account_config/resources/pending_claims.rs @@ -0,0 +1,57 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::{account_config::Table, event::EventHandle}; +use move_core_types::{ + ident_str, + identifier::IdentStr, + move_resource::{MoveResource, MoveStructType}, +}; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize)] +pub struct PendingClaimsResource { + pending_claims: Table, + offer_events: EventHandle, + cancel_offer_events: EventHandle, + claim_events: EventHandle, +} + +impl PendingClaimsResource { + pub fn new( + pending_claims: Table, + offer_events: EventHandle, + cancel_offer_events: EventHandle, + claim_events: EventHandle, + ) -> Self { + Self { + pending_claims, + offer_events, + cancel_offer_events, + claim_events, + } + } + + pub fn pending_claims(&self) -> &Table { + &self.pending_claims + } + + pub fn offer_events(&self) -> &EventHandle { + &self.offer_events + } + + pub fn cancel_offer_events(&self) -> &EventHandle { + &self.cancel_offer_events + } + + pub fn claim_events(&self) -> &EventHandle { + &self.claim_events + } +} + +impl MoveStructType for PendingClaimsResource { + const MODULE_NAME: &'static IdentStr = ident_str!("token"); + const STRUCT_NAME: &'static IdentStr = ident_str!("PendingClaims"); +} + +impl MoveResource for PendingClaimsResource {} diff --git a/types/src/account_config/resources/token.rs b/types/src/account_config/resources/token.rs new file mode 100644 index 0000000000000..cdcddb1960ccf --- /dev/null +++ b/types/src/account_config/resources/token.rs @@ -0,0 +1,71 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::{account_config::Object, event::EventHandle}; +use move_core_types::{ + ident_str, + identifier::IdentStr, + move_resource::{MoveResource, MoveStructType}, +}; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Eq, PartialEq, Serialize, Deserialize)] +pub struct TokenResource { + pub collection: Object, + pub index: u64, + description: String, + name: String, + uri: String, + mutation_events: EventHandle, +} + +impl TokenResource { + pub fn new( + collection: Object, + index: u64, + description: String, + name: String, + uri: String, + mutation_events: EventHandle, + ) -> Self { + Self { + collection, + index, + description, + name, + uri, + mutation_events, + } + } + + pub fn collection(&self) -> &Object { + &self.collection + } + + pub fn index(&self) -> &u64 { + &self.index + } + + pub fn description(&self) -> &String { + &self.description + } + + pub fn name(&self) -> &String { + &self.name + } + + pub fn uri(&self) -> &String { + &self.uri + } + + pub fn mutation_events(&self) -> &EventHandle { + &self.mutation_events + } +} + +impl MoveStructType for TokenResource { + const MODULE_NAME: &'static IdentStr = ident_str!("token"); + const STRUCT_NAME: &'static IdentStr = ident_str!("Token"); +} + +impl MoveResource for TokenResource {} diff --git a/types/src/account_config/resources/token_event_store_v1.rs b/types/src/account_config/resources/token_event_store_v1.rs new file mode 100644 index 0000000000000..70f0d63d5b6bf --- /dev/null +++ b/types/src/account_config/resources/token_event_store_v1.rs @@ -0,0 +1,99 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::{account_config::AnyResource, event::EventHandle}; +use move_core_types::{ + ident_str, + identifier::IdentStr, + move_resource::{MoveResource, MoveStructType}, +}; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize)] +pub struct TokenEventStoreV1Resource { + collection_uri_mutate_events: EventHandle, + collection_maximum_mutate_events: EventHandle, + collection_description_mutate_events: EventHandle, + opt_in_events: EventHandle, + uri_mutate_events: EventHandle, + default_property_mutate_events: EventHandle, + description_mutate_events: EventHandle, + royalty_mutate_events: EventHandle, + maximum_mutate_events: EventHandle, + extension: Option, +} + +impl TokenEventStoreV1Resource { + pub fn new( + collection_uri_mutate_events: EventHandle, + collection_maximum_mutate_events: EventHandle, + collection_description_mutate_events: EventHandle, + opt_in_events: EventHandle, + uri_mutate_events: EventHandle, + default_property_mutate_events: EventHandle, + description_mutate_events: EventHandle, + royalty_mutate_events: EventHandle, + maximum_mutate_events: EventHandle, + extension: Option, + ) -> Self { + Self { + collection_uri_mutate_events, + collection_maximum_mutate_events, + collection_description_mutate_events, + opt_in_events, + uri_mutate_events, + default_property_mutate_events, + description_mutate_events, + royalty_mutate_events, + maximum_mutate_events, + extension, + } + } + + pub fn collection_uri_mutate_events(&self) -> &EventHandle { + &self.collection_uri_mutate_events + } + + pub fn collection_maximum_mutate_events(&self) -> &EventHandle { + &self.collection_maximum_mutate_events + } + + pub fn collection_description_mutate_events(&self) -> &EventHandle { + &self.collection_description_mutate_events + } + + pub fn opt_in_events(&self) -> &EventHandle { + &self.opt_in_events + } + + pub fn uri_mutate_events(&self) -> &EventHandle { + &self.uri_mutate_events + } + + pub fn default_property_mutate_events(&self) -> &EventHandle { + &self.default_property_mutate_events + } + + pub fn description_mutate_events(&self) -> &EventHandle { + &self.description_mutate_events + } + + pub fn royalty_mutate_events(&self) -> &EventHandle { + &self.royalty_mutate_events + } + + pub fn maximum_mutate_events(&self) -> &EventHandle { + &self.maximum_mutate_events + } + + pub fn extension(&self) -> &Option { + &self.extension + } +} + +impl MoveStructType for TokenEventStoreV1Resource { + const MODULE_NAME: &'static IdentStr = ident_str!("token_event_store"); + const STRUCT_NAME: &'static IdentStr = ident_str!("TokenEventStoreV1"); +} + +impl MoveResource for TokenEventStoreV1Resource {} diff --git a/types/src/account_config/resources/token_store.rs b/types/src/account_config/resources/token_store.rs new file mode 100644 index 0000000000000..a24f938ecb16c --- /dev/null +++ b/types/src/account_config/resources/token_store.rs @@ -0,0 +1,77 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::event::EventHandle; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + move_resource::{MoveResource, MoveStructType}, +}; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize)] +pub struct TokenStoreResource { + tokens: Table, + direct_transfer: bool, + deposit_events: EventHandle, + withdraw_events: EventHandle, + burn_events: EventHandle, + mutate_token_property_events: EventHandle, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct Table { + handle: AccountAddress, +} + +impl TokenStoreResource { + pub fn new( + tokens: Table, + direct_transfer: bool, + deposit_events: EventHandle, + withdraw_events: EventHandle, + burn_events: EventHandle, + mutate_token_property_events: EventHandle, + ) -> Self { + Self { + tokens, + direct_transfer, + deposit_events, + withdraw_events, + burn_events, + mutate_token_property_events, + } + } + + pub fn tokens(&self) -> &Table { + &self.tokens + } + + pub fn direct_transfer(&self) -> bool { + self.direct_transfer + } + + pub fn deposit_events(&self) -> &EventHandle { + &self.deposit_events + } + + pub fn withdraw_events(&self) -> &EventHandle { + &self.withdraw_events + } + + pub fn burn_events(&self) -> &EventHandle { + &self.burn_events + } + + pub fn mutate_token_property_events(&self) -> &EventHandle { + &self.mutate_token_property_events + } +} + +impl MoveStructType for TokenStoreResource { + const MODULE_NAME: &'static IdentStr = ident_str!("token"); + const STRUCT_NAME: &'static IdentStr = ident_str!("TokenStore"); +} + +impl MoveResource for TokenStoreResource {} diff --git a/types/src/account_config/resources/type_info.rs b/types/src/account_config/resources/type_info.rs index aa4328e17cb06..230ee46646a01 100644 --- a/types/src/account_config/resources/type_info.rs +++ b/types/src/account_config/resources/type_info.rs @@ -1,25 +1,43 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 +use anyhow::Result; use move_core_types::{ account_address::AccountAddress, ident_str, identifier::IdentStr, + language_storage::{StructTag, TypeTag, CORE_CODE_ADDRESS}, move_resource::{MoveResource, MoveStructType}, }; +use once_cell::sync::Lazy; use serde::{Deserialize, Serialize}; /// A Rust representation of TypeInfo. -#[derive(Debug, Eq, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] pub struct TypeInfoResource { pub account_address: AccountAddress, pub module_name: Vec, pub struct_name: Vec, } +impl TypeInfoResource { + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } +} + impl MoveStructType for TypeInfoResource { const MODULE_NAME: &'static IdentStr = ident_str!("type_info"); const STRUCT_NAME: &'static IdentStr = ident_str!("TypeInfo"); } impl MoveResource for TypeInfoResource {} + +pub static TYPE_INFO_RESOURCE_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: CORE_CODE_ADDRESS, + module: ident_str!("type_info").to_owned(), + name: ident_str!("TypeInfo").to_owned(), + type_args: vec![], + })) +}); diff --git a/types/src/account_config/resources/unlimited_supply.rs b/types/src/account_config/resources/unlimited_supply.rs new file mode 100644 index 0000000000000..843623e75202f --- /dev/null +++ b/types/src/account_config/resources/unlimited_supply.rs @@ -0,0 +1,57 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::event::EventHandle; +use move_core_types::{ + ident_str, + identifier::IdentStr, + move_resource::{MoveResource, MoveStructType}, +}; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Eq, PartialEq, Serialize, Deserialize)] +pub struct UnlimitedSupplyResource { + current_supply: u64, + total_minted: u64, + burn_events: EventHandle, + mint_events: EventHandle, +} + +impl UnlimitedSupplyResource { + pub fn new( + current_supply: u64, + total_minted: u64, + burn_events: EventHandle, + mint_events: EventHandle, + ) -> Self { + Self { + current_supply, + total_minted, + burn_events, + mint_events, + } + } + + pub fn current_supply(&self) -> u64 { + self.current_supply + } + + pub fn total_minted(&self) -> u64 { + self.total_minted + } + + pub fn burn_events(&self) -> &EventHandle { + &self.burn_events + } + + pub fn mint_events(&self) -> &EventHandle { + &self.mint_events + } +} + +impl MoveStructType for UnlimitedSupplyResource { + const MODULE_NAME: &'static IdentStr = ident_str!("collection"); + const STRUCT_NAME: &'static IdentStr = ident_str!("UnlimitedSupply"); +} + +impl MoveResource for UnlimitedSupplyResource {} diff --git a/types/src/contract_event.rs b/types/src/contract_event.rs index a89e3d88a9f26..52647747eb6a7 100644 --- a/types/src/contract_event.rs +++ b/types/src/contract_event.rs @@ -169,6 +169,7 @@ impl ContractEvent { /// Entry produced via a call to the `emit_event` builtin. #[derive(Hash, Clone, Eq, PartialEq, Serialize, Deserialize, CryptoHasher)] +#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))] pub struct ContractEventV1 { /// The unique key that the event was emitted to key: EventKey, diff --git a/types/src/indexer/indexer_db_reader.rs b/types/src/indexer/indexer_db_reader.rs index 0ab962c826374..ddd68f108b17b 100644 --- a/types/src/indexer/indexer_db_reader.rs +++ b/types/src/indexer/indexer_db_reader.rs @@ -3,7 +3,7 @@ use crate::{ account_address::AccountAddress, - contract_event::EventWithVersion, + contract_event::{ContractEventV1, ContractEventV2, EventWithVersion}, event::EventKey, state_store::{ state_key::{prefix::StateKeyPrefix, StateKey}, @@ -73,4 +73,11 @@ pub trait IndexerReader: Send + Sync { Ok(()) } + fn get_translated_v1_event_by_version_and_index( + &self, + version: Version, + index: u64, + ) -> Result; + + fn translate_event_v2_to_v1(&self, v2: &ContractEventV2) -> Result>; } diff --git a/types/src/utility_coin.rs b/types/src/utility_coin.rs index 625f63e823109..13e674fcb2465 100644 --- a/types/src/utility_coin.rs +++ b/types/src/utility_coin.rs @@ -43,3 +43,23 @@ impl MoveStructType for AptosCoinType { const MODULE_NAME: &'static IdentStr = ident_str!("aptos_coin"); const STRUCT_NAME: &'static IdentStr = ident_str!("AptosCoin"); } + +pub static DUMMY_COIN_TYPE: Lazy = Lazy::new(|| { + TypeTag::Struct(Box::new(StructTag { + address: AccountAddress::ONE, + module: ident_str!("dummy_coin").to_owned(), + name: ident_str!("DummyCoin").to_owned(), + type_args: vec![], + })) +}); + +pub struct DummyCoinType; +impl CoinType for DummyCoinType { + fn type_tag() -> TypeTag { + DUMMY_COIN_TYPE.clone() + } + + fn coin_info_address() -> AccountAddress { + AccountAddress::ONE + } +} From d1230b991dd8cf56e2adcd3fded2602e349acf75 Mon Sep 17 00:00:00 2001 From: Guoteng Rao <3603304+grao1991@users.noreply.github.com> Date: Wed, 4 Dec 2024 23:37:36 -0800 Subject: [PATCH 20/78] [Storage] Open db in parallel when storage sharding is enabled. (#15504) --- storage/aptosdb/src/db_debugger/validation.rs | 2 +- storage/aptosdb/src/db_options.rs | 9 +- storage/aptosdb/src/ledger_db/mod.rs | 134 +++++++++++------- storage/aptosdb/src/state_kv_db.rs | 45 +++--- storage/aptosdb/src/state_merkle_db.rs | 25 +++- 5 files changed, 127 insertions(+), 88 deletions(-) diff --git a/storage/aptosdb/src/db_debugger/validation.rs b/storage/aptosdb/src/db_debugger/validation.rs index c06a61d27b56e..85c2022b8f50c 100644 --- a/storage/aptosdb/src/db_debugger/validation.rs +++ b/storage/aptosdb/src/db_debugger/validation.rs @@ -118,7 +118,7 @@ pub fn verify_state_kvs( ) -> Result<()> { println!("Validating db statekeys"); let storage_dir = StorageDirPaths::from_path(db_root_path); - let state_kv_db = StateKvDb::open(&storage_dir, RocksdbConfig::default(), false, true)?; + let state_kv_db = StateKvDb::open_sharded(&storage_dir, RocksdbConfig::default(), false)?; //read all statekeys from internal db and store them in mem let mut all_internal_keys = HashSet::new(); diff --git a/storage/aptosdb/src/db_options.rs b/storage/aptosdb/src/db_options.rs index e41de403b30b3..d703375e81521 100644 --- a/storage/aptosdb/src/db_options.rs +++ b/storage/aptosdb/src/db_options.rs @@ -221,15 +221,10 @@ pub(super) fn gen_state_merkle_cfds(rocksdb_config: &RocksdbConfig) -> Vec Vec { - let cfs = if enable_sharding { - state_kv_db_new_key_column_families() - } else { - state_kv_db_column_families() - }; + let cfs = state_kv_db_new_key_column_families(); gen_cfds(rocksdb_config, cfs, with_state_key_extractor_processor) } diff --git a/storage/aptosdb/src/ledger_db/mod.rs b/storage/aptosdb/src/ledger_db/mod.rs index da5d8377fbb26..96d886360bd3b 100644 --- a/storage/aptosdb/src/ledger_db/mod.rs +++ b/storage/aptosdb/src/ledger_db/mod.rs @@ -24,6 +24,7 @@ use crate::{ schema::db_metadata::{DbMetadataKey, DbMetadataSchema}, }; use aptos_config::config::{RocksdbConfig, RocksdbConfigs}; +use aptos_experimental_runtimes::thread_manager::THREAD_MANAGER; use aptos_logger::prelude::info; use aptos_rocksdb_options::gen_rocksdb_options; use aptos_schemadb::{ColumnFamilyDescriptor, ColumnFamilyName, SchemaBatch, DB}; @@ -155,60 +156,95 @@ impl LedgerDb { let ledger_db_folder = db_root_path.as_ref().join(LEDGER_DB_FOLDER_NAME); - let event_db_raw = Arc::new(Self::open_rocksdb( - ledger_db_folder.join(EVENT_DB_NAME), - EVENT_DB_NAME, - &rocksdb_configs.ledger_db_config, - readonly, - )?); - let event_db = EventDb::new(event_db_raw.clone(), EventStore::new(event_db_raw)); - - let transaction_accumulator_db = - TransactionAccumulatorDb::new(Arc::new(Self::open_rocksdb( - ledger_db_folder.join(TRANSACTION_ACCUMULATOR_DB_NAME), - TRANSACTION_ACCUMULATOR_DB_NAME, - &rocksdb_configs.ledger_db_config, - readonly, - )?)); - - let transaction_auxiliary_data_db = - TransactionAuxiliaryDataDb::new(Arc::new(Self::open_rocksdb( - ledger_db_folder.join(TRANSACTION_AUXILIARY_DATA_DB_NAME), - TRANSACTION_AUXILIARY_DATA_DB_NAME, - &rocksdb_configs.ledger_db_config, - readonly, - )?)); - let transaction_db = TransactionDb::new(Arc::new(Self::open_rocksdb( - ledger_db_folder.join(TRANSACTION_DB_NAME), - TRANSACTION_DB_NAME, - &rocksdb_configs.ledger_db_config, - readonly, - )?)); - - let transaction_info_db = TransactionInfoDb::new(Arc::new(Self::open_rocksdb( - ledger_db_folder.join(TRANSACTION_INFO_DB_NAME), - TRANSACTION_INFO_DB_NAME, - &rocksdb_configs.ledger_db_config, - readonly, - )?)); - - let write_set_db = WriteSetDb::new(Arc::new(Self::open_rocksdb( - ledger_db_folder.join(WRITE_SET_DB_NAME), - WRITE_SET_DB_NAME, - &rocksdb_configs.ledger_db_config, - readonly, - )?)); + let mut event_db = None; + let mut transaction_accumulator_db = None; + let mut transaction_auxiliary_data_db = None; + let mut transaction_db = None; + let mut transaction_info_db = None; + let mut write_set_db = None; + THREAD_MANAGER.get_non_exe_cpu_pool().scope(|s| { + s.spawn(|_| { + let event_db_raw = Arc::new( + Self::open_rocksdb( + ledger_db_folder.join(EVENT_DB_NAME), + EVENT_DB_NAME, + &rocksdb_configs.ledger_db_config, + readonly, + ) + .unwrap(), + ); + event_db = Some(EventDb::new( + event_db_raw.clone(), + EventStore::new(event_db_raw), + )); + }); + s.spawn(|_| { + transaction_accumulator_db = Some(TransactionAccumulatorDb::new(Arc::new( + Self::open_rocksdb( + ledger_db_folder.join(TRANSACTION_ACCUMULATOR_DB_NAME), + TRANSACTION_ACCUMULATOR_DB_NAME, + &rocksdb_configs.ledger_db_config, + readonly, + ) + .unwrap(), + ))); + }); + s.spawn(|_| { + transaction_auxiliary_data_db = Some(TransactionAuxiliaryDataDb::new(Arc::new( + Self::open_rocksdb( + ledger_db_folder.join(TRANSACTION_AUXILIARY_DATA_DB_NAME), + TRANSACTION_AUXILIARY_DATA_DB_NAME, + &rocksdb_configs.ledger_db_config, + readonly, + ) + .unwrap(), + ))) + }); + s.spawn(|_| { + transaction_db = Some(TransactionDb::new(Arc::new( + Self::open_rocksdb( + ledger_db_folder.join(TRANSACTION_DB_NAME), + TRANSACTION_DB_NAME, + &rocksdb_configs.ledger_db_config, + readonly, + ) + .unwrap(), + ))); + }); + s.spawn(|_| { + transaction_info_db = Some(TransactionInfoDb::new(Arc::new( + Self::open_rocksdb( + ledger_db_folder.join(TRANSACTION_INFO_DB_NAME), + TRANSACTION_INFO_DB_NAME, + &rocksdb_configs.ledger_db_config, + readonly, + ) + .unwrap(), + ))); + }); + s.spawn(|_| { + write_set_db = Some(WriteSetDb::new(Arc::new( + Self::open_rocksdb( + ledger_db_folder.join(WRITE_SET_DB_NAME), + WRITE_SET_DB_NAME, + &rocksdb_configs.ledger_db_config, + readonly, + ) + .unwrap(), + ))); + }); + }); // TODO(grao): Handle data inconsistency. Ok(Self { ledger_metadata_db: LedgerMetadataDb::new(ledger_metadata_db), - event_db, - transaction_accumulator_db, - transaction_auxiliary_data_db, - transaction_db, - transaction_info_db, - write_set_db, + event_db: event_db.unwrap(), + transaction_accumulator_db: transaction_accumulator_db.unwrap(), + transaction_auxiliary_data_db: transaction_auxiliary_data_db.unwrap(), + transaction_db: transaction_db.unwrap(), + transaction_info_db: transaction_info_db.unwrap(), + write_set_db: write_set_db.unwrap(), enable_storage_sharding: true, }) } diff --git a/storage/aptosdb/src/state_kv_db.rs b/storage/aptosdb/src/state_kv_db.rs index 35c1d01e3bbda..331b170084b5d 100644 --- a/storage/aptosdb/src/state_kv_db.rs +++ b/storage/aptosdb/src/state_kv_db.rs @@ -4,7 +4,7 @@ #![forbid(unsafe_code)] use crate::{ - db_options::gen_state_kv_cfds, + db_options::gen_state_kv_shard_cfds, metrics::OTHER_TIMERS_SECONDS, schema::{ db_metadata::{DbMetadataKey, DbMetadataSchema, DbMetadataValue}, @@ -25,6 +25,7 @@ use aptos_types::{ transaction::Version, }; use arr_macro::arr; +use rayon::prelude::*; use std::{ path::{Path, PathBuf}, sync::Arc, @@ -56,19 +57,13 @@ impl StateKvDb { }); } - Self::open( - db_paths, - rocksdb_configs.state_kv_db_config, - readonly, - sharding, - ) + Self::open_sharded(db_paths, rocksdb_configs.state_kv_db_config, readonly) } - pub(crate) fn open( + pub(crate) fn open_sharded( db_paths: &StorageDirPaths, state_kv_db_config: RocksdbConfig, readonly: bool, - enable_sharding: bool, ) -> Result { let state_kv_metadata_db_path = Self::metadata_db_path(db_paths.state_kv_db_metadata_root_path()); @@ -78,7 +73,6 @@ impl StateKvDb { STATE_KV_METADATA_DB_NAME, &state_kv_db_config, readonly, - enable_sharding, )?); info!( @@ -86,15 +80,22 @@ impl StateKvDb { "Opened state kv metadata db!" ); - let mut shard_id: usize = 0; - let state_kv_db_shards = { - arr![{ + let state_kv_db_shards = (0..NUM_STATE_SHARDS) + .into_par_iter() + .map(|shard_id| { let shard_root_path = db_paths.state_kv_db_shard_root_path(shard_id as u8); - let db = Self::open_shard(shard_root_path, shard_id as u8, &state_kv_db_config, readonly, enable_sharding)?; - shard_id += 1; + let db = Self::open_shard( + shard_root_path, + shard_id as u8, + &state_kv_db_config, + readonly, + ) + .unwrap_or_else(|e| panic!("Failed to open state kv db shard {shard_id}: {e:?}.")); Arc::new(db) - }; 16] - }; + }) + .collect::>() + .try_into() + .unwrap(); let state_kv_db = Self { state_kv_metadata_db, @@ -171,11 +172,10 @@ impl StateKvDb { cp_root_path: impl AsRef, ) -> Result<()> { // TODO(grao): Support path override here. - let state_kv_db = Self::open( + let state_kv_db = Self::open_sharded( &StorageDirPaths::from_path(db_root_path), RocksdbConfig::default(), false, - true, )?; let cp_state_kv_db_path = cp_root_path.as_ref().join(STATE_KV_DB_FOLDER_NAME); @@ -247,7 +247,6 @@ impl StateKvDb { shard_id: u8, state_kv_db_config: &RocksdbConfig, readonly: bool, - enable_sharding: bool, ) -> Result { let db_name = format!("state_kv_db_shard_{}", shard_id); Self::open_db( @@ -255,7 +254,6 @@ impl StateKvDb { &db_name, state_kv_db_config, readonly, - enable_sharding, ) } @@ -264,21 +262,20 @@ impl StateKvDb { name: &str, state_kv_db_config: &RocksdbConfig, readonly: bool, - enable_sharding: bool, ) -> Result { Ok(if readonly { DB::open_cf_readonly( &gen_rocksdb_options(state_kv_db_config, true), path, name, - gen_state_kv_cfds(state_kv_db_config, enable_sharding), + gen_state_kv_shard_cfds(state_kv_db_config), )? } else { DB::open_cf( &gen_rocksdb_options(state_kv_db_config, false), path, name, - gen_state_kv_cfds(state_kv_db_config, enable_sharding), + gen_state_kv_shard_cfds(state_kv_db_config), )? }) } diff --git a/storage/aptosdb/src/state_merkle_db.rs b/storage/aptosdb/src/state_merkle_db.rs index 7d7ad649d0431..10d75f5b164f5 100644 --- a/storage/aptosdb/src/state_merkle_db.rs +++ b/storage/aptosdb/src/state_merkle_db.rs @@ -583,13 +583,24 @@ impl StateMerkleDb { "Opened state merkle metadata db!" ); - let mut shard_id: usize = 0; - let state_merkle_db_shards = arr![{ - let shard_root_path = db_paths.state_merkle_db_shard_root_path(shard_id as u8); - let db = Self::open_shard(shard_root_path, shard_id as u8, &state_merkle_db_config, readonly)?; - shard_id += 1; - Arc::new(db) - }; 16]; + let state_merkle_db_shards = (0..NUM_STATE_SHARDS) + .into_par_iter() + .map(|shard_id| { + let shard_root_path = db_paths.state_merkle_db_shard_root_path(shard_id as u8); + let db = Self::open_shard( + shard_root_path, + shard_id as u8, + &state_merkle_db_config, + readonly, + ) + .unwrap_or_else(|e| { + panic!("Failed to open state merkle db shard {shard_id}: {e:?}.") + }); + Arc::new(db) + }) + .collect::>() + .try_into() + .unwrap(); let state_merkle_db = Self { state_merkle_metadata_db, From 95e0d68972fc4d5f87aaaa682972b5ed15aa4265 Mon Sep 17 00:00:00 2001 From: George Mitenkov Date: Thu, 5 Dec 2024 19:08:44 +0000 Subject: [PATCH 21/78] [move] Use workspace dependencies for third-party/move (#15461) --- Cargo.lock | 22 +++++----- Cargo.toml | 22 +++++----- aptos-move/framework/move-stdlib/Cargo.toml | 22 +++++----- testsuite/fuzzer/Cargo.toml | 6 +-- third_party/move/evm/exec-utils/Cargo.toml | 5 +-- third_party/move/evm/move-to-yul/Cargo.toml | 17 ++++---- .../move-table-extension/Cargo.toml | 14 +++---- .../move/move-binary-format/Cargo.toml | 4 +- .../serializer-tests/Cargo.toml | 4 +- .../move/move-bytecode-verifier/Cargo.toml | 12 ++---- .../bytecode-verifier-tests/Cargo.toml | 8 ++-- .../src/unit_tests/bounds_tests.rs | 8 ++-- .../src/unit_tests/signature_tests.rs | 2 +- .../move-bytecode-verifier/fuzz/Cargo.toml | 9 ++-- .../invalid-mutations/Cargo.toml | 9 ++-- .../transactional-tests/Cargo.toml | 2 +- .../move/move-command-line-common/Cargo.toml | 3 +- third_party/move/move-compiler-v2/Cargo.toml | 34 ++++++++------- .../transactional-tests/Cargo.toml | 8 ++-- third_party/move/move-compiler/Cargo.toml | 18 ++++---- third_party/move/move-compiler/TODO | 41 ------------------- .../transactional-tests/Cargo.toml | 2 +- third_party/move/move-examples/Cargo.toml | 2 +- .../diem-framework/crates/cli/Cargo.toml | 11 ++--- .../diem-framework/crates/natives/Cargo.toml | 10 ++--- third_party/move/move-ir-compiler/Cargo.toml | 16 +++----- .../move-bytecode-source-map/Cargo.toml | 15 +++---- .../move-ir-to-bytecode/Cargo.toml | 14 +++---- .../move-ir-to-bytecode/syntax/Cargo.toml | 8 ++-- .../transactional-tests/Cargo.toml | 2 +- third_party/move/move-ir/types/Cargo.toml | 7 ++-- third_party/move/move-model/Cargo.toml | 21 ++++------ .../move-model/bytecode-test-utils/Cargo.toml | 12 +++--- .../move/move-model/bytecode/Cargo.toml | 11 +++-- .../abstract_domain_derive/Cargo.toml | 2 +- third_party/move/move-prover/Cargo.toml | 25 +++++------ .../move-prover/boogie-backend/Cargo.toml | 14 +++---- .../move-prover/bytecode-pipeline/Cargo.toml | 14 +++---- third_party/move/move-prover/lab/Cargo.toml | 26 ++++-------- .../move/move-prover/move-abigen/Cargo.toml | 18 ++++---- .../move/move-prover/move-docgen/Cargo.toml | 13 +++--- .../move-prover/move-errmapgen/Cargo.toml | 11 ++--- .../move/move-prover/test-utils/Cargo.toml | 2 +- third_party/move/move-stdlib/Cargo.toml | 24 +++++------ .../move/move-vm/integration-tests/Cargo.toml | 21 ++++------ .../move/move-vm/paranoid-tests/Cargo.toml | 2 +- third_party/move/move-vm/runtime/Cargo.toml | 19 ++++----- .../move/move-vm/test-utils/Cargo.toml | 11 +++-- .../move-vm/transactional-tests/Cargo.toml | 2 +- third_party/move/move-vm/types/Cargo.toml | 7 ++-- .../module-generation/Cargo.toml | 13 +++--- .../transactional-test-runner/Cargo.toml | 35 ++++++++-------- .../move/tools/move-bytecode-utils/Cargo.toml | 4 +- .../tools/move-bytecode-viewer/Cargo.toml | 7 ++-- third_party/move/tools/move-cli/Cargo.toml | 35 ++++++++-------- .../move/tools/move-coverage/Cargo.toml | 14 +++---- .../move/tools/move-decompiler/Cargo.toml | 3 +- .../move/tools/move-disassembler/Cargo.toml | 18 ++++---- .../move/tools/move-explain/Cargo.toml | 7 ++-- third_party/move/tools/move-linter/Cargo.toml | 17 ++++---- .../move/tools/move-package/Cargo.toml | 34 +++++++-------- .../tools/move-resource-viewer/Cargo.toml | 6 +-- .../move/tools/move-unit-test/Cargo.toml | 40 ++++++++---------- 63 files changed, 360 insertions(+), 485 deletions(-) delete mode 100644 third_party/move/move-compiler/TODO diff --git a/Cargo.lock b/Cargo.lock index 4b2486bf5ad72..ca3e47878f1d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5914,9 +5914,9 @@ version = "0.1.0" dependencies = [ "fail", "hex", - "invalid-mutations", "move-binary-format", "move-bytecode-verifier", + "move-bytecode-verifier-invalid-mutations", "move-core-types", "petgraph 0.6.5", "proptest", @@ -9926,15 +9926,6 @@ dependencies = [ "parking_lot 0.12.1", ] -[[package]] -name = "invalid-mutations" -version = "0.1.0" -dependencies = [ - "move-binary-format", - "move-core-types", - "proptest", -] - [[package]] name = "io-lifetimes" version = "1.0.11" @@ -11058,15 +11049,24 @@ version = "0.1.0" dependencies = [ "fail", "hex-literal", - "invalid-mutations", "move-binary-format", "move-borrow-graph", + "move-bytecode-verifier-invalid-mutations", "move-core-types", "petgraph 0.6.5", "serde", "typed-arena", ] +[[package]] +name = "move-bytecode-verifier-invalid-mutations" +version = "0.1.0" +dependencies = [ + "move-binary-format", + "move-core-types", + "proptest", +] + [[package]] name = "move-bytecode-viewer" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 47644e807048a..cc429d5c1435d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -623,6 +623,7 @@ http = "0.2.9" httpmock = "0.6.8" hyper = { version = "0.14.18", features = ["full"] } hyper-tls = "0.5.0" +im = "15.0.0" image = "0.24.5" indexmap = "1.9.3" include_dir = { version = "0.7.2", features = ["glob"] } @@ -840,8 +841,12 @@ z3tracer = "0.8.0" # MOVE DEPENDENCIES move-abigen = { path = "third_party/move/move-prover/move-abigen" } move-binary-format = { path = "third_party/move/move-binary-format" } +move-borrow-graph = { path = "third_party/move/move-borrow-graph" } +move-bytecode-source-map = { path = "third_party/move/move-ir-compiler/move-bytecode-source-map" } move-bytecode-spec = { path = "third_party/move/move-bytecode-spec" } move-bytecode-verifier = { path = "third_party/move/move-bytecode-verifier" } +move-bytecode-verifier-invalid-mutations = { path = "third_party/move/move-bytecode-verifier/invalid-mutations" } +move-bytecode-viewer = { path = "third_party/move/tools/move-bytecode-viewer" } move-bytecode-utils = { path = "third_party/move/tools/move-bytecode-utils" } move-cli = { path = "third_party/move/tools/move-cli" } move-command-line-common = { path = "third_party/move/move-command-line-common" } @@ -852,32 +857,29 @@ move-core-types = { path = "third_party/move/move-core/types" } move-decompiler = { path = "third_party/move/tools/move-decompiler" } move-docgen = { path = "third_party/move/move-prover/move-docgen" } move-disassembler = { path = "third_party/move/tools/move-disassembler" } +move-errmapgen = { path = "third_party/move/move-prover/move-errmapgen" } move-ir-types = { path = "third_party/move/move-ir/types" } move-ir-compiler = { path = "third_party/move/move-ir-compiler" } +move-ir-to-bytecode = { path = "third_party/move/move-ir-compiler/move-ir-to-bytecode" } move-linter = { path = "third_party/move/tools/move-linter" } -move-bytecode-source-map = { path = "third_party/move/move-ir-compiler/move-bytecode-source-map" } move-model = { path = "third_party/move/move-model" } move-package = { path = "third_party/move/tools/move-package" } move-prover = { path = "third_party/move/move-prover" } move-prover-boogie-backend = { path = "third_party/move/move-prover/boogie-backend" } move-prover-bytecode-pipeline = { path = "third_party/move/move-prover/bytecode-pipeline" } -move-stackless-bytecode = { path = "third_party/move/move-model/bytecode" } -move-stackless-bytecode-test-utils = { path = "third_party/move/move-model/bytecode-test-utils" } +move-prover-test-utils = { path = "third_party/move/move-prover/test-utils" } aptos-move-stdlib = { path = "aptos-move/framework/move-stdlib" } aptos-table-natives = { path = "aptos-move/framework/table-natives" } -move-prover-test-utils = { path = "third_party/move/move-prover/test-utils" } move-resource-viewer = { path = "third_party/move/tools/move-resource-viewer" } +move-stackless-bytecode = { path = "third_party/move/move-model/bytecode" } +move-stackless-bytecode-test-utils = { path = "third_party/move/move-model/bytecode-test-utils" } move-symbol-pool = { path = "third_party/move/move-symbol-pool" } move-table-extension = { path = "third_party/move/extensions/move-table-extension" } move-transactional-test-runner = { path = "third_party/move/testing-infra/transactional-test-runner" } -move-unit-test = { path = "third_party/move/tools/move-unit-test", features = [ - "table-extension", -] } +move-unit-test = { path = "third_party/move/tools/move-unit-test", features = ["table-extension"] } move-vm-metrics = { path = "third_party/move/move-vm/metrics" } move-vm-runtime = { path = "third_party/move/move-vm/runtime" } -move-vm-test-utils = { path = "third_party/move/move-vm/test-utils", features = [ - "table-extension", -] } +move-vm-test-utils = { path = "third_party/move/move-vm/test-utils", features = ["table-extension"] } move-vm-types = { path = "third_party/move/move-vm/types" } [profile.release] diff --git a/aptos-move/framework/move-stdlib/Cargo.toml b/aptos-move/framework/move-stdlib/Cargo.toml index c14625d18dbd6..4aa6fd1223f0b 100644 --- a/aptos-move/framework/move-stdlib/Cargo.toml +++ b/aptos-move/framework/move-stdlib/Cargo.toml @@ -15,20 +15,20 @@ aptos-gas-schedule = { workspace = true } aptos-native-interface = { workspace = true } aptos-types = { workspace = true } bcs = { workspace = true } -move-core-types = { path = "../../../third_party/move/move-core/types" } -move-vm-runtime = { path = "../../../third_party/move/move-vm/runtime" } -move-vm-types = { path = "../../../third_party/move/move-vm/types" } -sha2 = "0.9.3" -sha3 = "0.9.1" -smallvec = "1.6.1" +move-core-types = { workspace = true } +move-vm-runtime = { workspace = true } +move-vm-types = { workspace = true } +sha2 = { workspace = true } +sha3 = { workspace = true } +smallvec = { workspace = true } [dev-dependencies] dir-diff = "0.3.2" file_diff = "1.0.0" -move-cli = { path = "../../../third_party/move/tools/move-cli" } -move-package = { path = "../../../third_party/move/tools/move-package" } -move-unit-test = { path = "../../../third_party/move/tools/move-unit-test" } -tempfile = "3.2.0" +move-cli = { workspace = true } +move-package = { workspace = true } +move-unit-test = { workspace = true } +tempfile = { workspace = true } [features] -testing = [] \ No newline at end of file +testing = [] diff --git a/testsuite/fuzzer/Cargo.toml b/testsuite/fuzzer/Cargo.toml index 4d8b3d26f2e78..8bad486071812 100644 --- a/testsuite/fuzzer/Cargo.toml +++ b/testsuite/fuzzer/Cargo.toml @@ -10,10 +10,10 @@ aptos-types = { workspace = true } arbitrary = { workspace = true } base64 = "0.21.7" bcs = { workspace = true } -clap = "4.5.20" -csv = "1.3.0" +clap = { workspace = true } +csv = { workspace = true } dearbitrary = { workspace = true } -hex = "0.4.3" +hex = { workspace = true } move-binary-format = { workspace = true, features = ["fuzzing"] } move-core-types = { workspace = true, features = ["fuzzing"] } sha2 = { workspace = true } diff --git a/third_party/move/evm/exec-utils/Cargo.toml b/third_party/move/evm/exec-utils/Cargo.toml index 80736821c5912..faf398bc4de1d 100644 --- a/third_party/move/evm/exec-utils/Cargo.toml +++ b/third_party/move/evm/exec-utils/Cargo.toml @@ -12,10 +12,7 @@ anyhow = { workspace = true } evm = { workspace = true } evm-runtime = { workspace = true } hex = { workspace = true } +move-command-line-common = { workspace = true } primitive-types = { workspace = true } -# external dependencies sha3 = { workspace = true } tempfile = { workspace = true } - -# move dependencies -move-command-line-common = { path = "../../move-command-line-common" } diff --git a/third_party/move/evm/move-to-yul/Cargo.toml b/third_party/move/evm/move-to-yul/Cargo.toml index b979d3af1ff3d..7f8c0704e2c01 100644 --- a/third_party/move/evm/move-to-yul/Cargo.toml +++ b/third_party/move/evm/move-to-yul/Cargo.toml @@ -8,15 +8,6 @@ edition = "2021" license = "Apache-2.0" [dependencies] -move-command-line-common = { path = "../../move-command-line-common" } -move-compiler = { path = "../../move-compiler" } -move-core-types = { path = "../../move-core/types" } -move-ethereum-abi = { path = "../move-ethereum-abi" } -move-model = { path = "../../move-model" } -# move dependencies -move-stackless-bytecode = { path = "../../move-model/bytecode" } - -# external dependencies anyhow = { workspace = true } atty = { workspace = true } clap = { workspace = true } @@ -26,6 +17,12 @@ ethnum = { workspace = true } evm = { workspace = true } itertools = { workspace = true } maplit = { workspace = true } +move-command-line-common = { workspace = true } +move-compiler = { workspace = true } +move-core-types = { workspace = true } +move-ethereum-abi = { path = "../move-ethereum-abi" } +move-model = { workspace = true } +move-stackless-bytecode = { workspace = true } once_cell = { workspace = true } primitive-types = { workspace = true } regex = { workspace = true } @@ -36,7 +33,7 @@ sha3 = { workspace = true } datatest-stable = { workspace = true } evm = { workspace = true } evm-exec-utils = { path = "../exec-utils" } -move-prover-test-utils = { path = "../../move-prover/test-utils" } +move-prover-test-utils = { workspace = true } move-stdlib = { path = "../../move-stdlib" } tempfile = { workspace = true } walkdir = { workspace = true } diff --git a/third_party/move/extensions/move-table-extension/Cargo.toml b/third_party/move/extensions/move-table-extension/Cargo.toml index 1dee926a611e0..07a9759b45b56 100644 --- a/third_party/move/extensions/move-table-extension/Cargo.toml +++ b/third_party/move/extensions/move-table-extension/Cargo.toml @@ -11,16 +11,16 @@ publish = false [dependencies] better_any = { workspace = true } bytes = { workspace = true } -move-binary-format = { path = "../../move-binary-format" } -move-core-types = { path = "../../move-core/types" } -move-vm-runtime = { path = "../../move-vm/runtime" } -move-vm-types = { path = "../../move-vm/types" } +move-binary-format = { workspace = true } +move-core-types = { workspace = true } +move-vm-runtime = { workspace = true } +move-vm-types = { workspace = true } sha3 = { workspace = true } smallvec = { workspace = true } [dev-dependencies] -move-cli = { path = "../../tools/move-cli" } -move-package = { path = "../../tools/move-package" } +move-cli = { workspace = true } +move-package = { workspace = true } move-stdlib = { path = "../../move-stdlib", features = ["testing"] } -move-unit-test = { path = "../../tools/move-unit-test", features = ["table-extension"] } +move-unit-test = { workspace = true, features = ["table-extension"] } tempfile = { workspace = true } diff --git a/third_party/move/move-binary-format/Cargo.toml b/third_party/move/move-binary-format/Cargo.toml index 18024c2d91669..a701e9992c192 100644 --- a/third_party/move/move-binary-format/Cargo.toml +++ b/third_party/move/move-binary-format/Cargo.toml @@ -16,7 +16,7 @@ backtrace = { workspace = true } dearbitrary = { workspace = true, optional = true, features = ["derive"] } indexmap = { workspace = true } move-bytecode-spec = { workspace = true } -move-core-types = { path = "../move-core/types" } +move-core-types = { workspace = true } proptest = { workspace = true, optional = true } proptest-derive = { workspace = true, optional = true } ref-cast = { workspace = true } @@ -24,7 +24,7 @@ serde = { workspace = true } variant_count = { workspace = true } [dev-dependencies] -move-core-types = { path = "../move-core/types", features = ["fuzzing"] } +move-core-types = { workspace = true, features = ["fuzzing"] } proptest = { workspace = true } proptest-derive = { workspace = true } serde_json = { workspace = true } diff --git a/third_party/move/move-binary-format/serializer-tests/Cargo.toml b/third_party/move/move-binary-format/serializer-tests/Cargo.toml index b83bf8a437565..8dd29651dec5c 100644 --- a/third_party/move/move-binary-format/serializer-tests/Cargo.toml +++ b/third_party/move/move-binary-format/serializer-tests/Cargo.toml @@ -10,8 +10,8 @@ publish = false edition = "2021" [dev-dependencies] -move-binary-format = { path = "../", features = ["fuzzing"] } -move-core-types = { path = "../../move-core/types" } +move-binary-format = { workspace = true, features = ["fuzzing"] } +move-core-types = { workspace = true } proptest = { workspace = true } proptest-derive = { workspace = true } diff --git a/third_party/move/move-bytecode-verifier/Cargo.toml b/third_party/move/move-bytecode-verifier/Cargo.toml index 9085bb1816373..2f506216981e2 100644 --- a/third_party/move/move-bytecode-verifier/Cargo.toml +++ b/third_party/move/move-bytecode-verifier/Cargo.toml @@ -11,17 +11,13 @@ edition = "2021" [dependencies] fail = { workspace = true } -move-binary-format = { path = "../move-binary-format" } +move-binary-format = { workspace = true } +move-borrow-graph = { workspace = true } +move-core-types = { workspace = true } petgraph = { workspace = true } serde = { workspace = true } typed-arena = { workspace = true } -move-borrow-graph = { path = "../move-borrow-graph" } -move-core-types = { path = "../move-core/types" } - [dev-dependencies] hex-literal = { workspace = true } -invalid-mutations = { path = "invalid-mutations" } - -[features] -default = [] +move-bytecode-verifier-invalid-mutations = { workspace = true } diff --git a/third_party/move/move-bytecode-verifier/bytecode-verifier-tests/Cargo.toml b/third_party/move/move-bytecode-verifier/bytecode-verifier-tests/Cargo.toml index 4e5c437cddfdb..30c43d5d75f32 100644 --- a/third_party/move/move-bytecode-verifier/bytecode-verifier-tests/Cargo.toml +++ b/third_party/move/move-bytecode-verifier/bytecode-verifier-tests/Cargo.toml @@ -12,10 +12,10 @@ edition = "2021" [dev-dependencies] fail = { workspace = true, features = ['failpoints'] } hex = { workspace = true } -invalid-mutations = { path = "../invalid-mutations" } -move-binary-format = { path = "../../move-binary-format", features = ["fuzzing"] } -move-bytecode-verifier = { path = "../" } -move-core-types = { path = "../../move-core/types" } +move-binary-format = { workspace = true, features = ["fuzzing"] } +move-bytecode-verifier = { workspace = true } +move-bytecode-verifier-invalid-mutations = { workspace = true } +move-core-types = { workspace = true } petgraph = { workspace = true } proptest = { workspace = true } diff --git a/third_party/move/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/bounds_tests.rs b/third_party/move/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/bounds_tests.rs index 506a027f75778..081ed67a5f4ff 100644 --- a/third_party/move/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/bounds_tests.rs +++ b/third_party/move/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/bounds_tests.rs @@ -2,14 +2,14 @@ // Copyright (c) The Move Contributors // SPDX-License-Identifier: Apache-2.0 -use invalid_mutations::bounds::{ - ApplyCodeUnitBoundsContext, ApplyOutOfBoundsContext, CodeUnitBoundsMutation, - OutOfBoundsMutation, -}; use move_binary_format::{ check_bounds::BoundsChecker, file_format::*, file_format_common, proptest_types::CompiledModuleStrategyGen, }; +use move_bytecode_verifier_invalid_mutations::bounds::{ + ApplyCodeUnitBoundsContext, ApplyOutOfBoundsContext, CodeUnitBoundsMutation, + OutOfBoundsMutation, +}; use move_core_types::{ account_address::AccountAddress, identifier::Identifier, vm_status::StatusCode, }; diff --git a/third_party/move/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/signature_tests.rs b/third_party/move/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/signature_tests.rs index e7b9f123d8b86..4010c58543315 100644 --- a/third_party/move/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/signature_tests.rs +++ b/third_party/move/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/signature_tests.rs @@ -2,13 +2,13 @@ // Copyright (c) The Move Contributors // SPDX-License-Identifier: Apache-2.0 -use invalid_mutations::signature::{FieldRefMutation, SignatureRefMutation}; use move_binary_format::file_format::{ Bytecode::*, CompiledModule, SignatureToken::*, Visibility::Public, *, }; use move_bytecode_verifier::{ verify_module, verify_module_with_config_for_test, SignatureChecker, VerifierConfig, }; +use move_bytecode_verifier_invalid_mutations::signature::{FieldRefMutation, SignatureRefMutation}; use move_core_types::{ account_address::AccountAddress, identifier::Identifier, vm_status::StatusCode, }; diff --git a/third_party/move/move-bytecode-verifier/fuzz/Cargo.toml b/third_party/move/move-bytecode-verifier/fuzz/Cargo.toml index c89658cc77f8c..7de0a965aba79 100644 --- a/third_party/move/move-bytecode-verifier/fuzz/Cargo.toml +++ b/third_party/move/move-bytecode-verifier/fuzz/Cargo.toml @@ -12,12 +12,9 @@ cargo-fuzz = true [dependencies] arbitrary = { workspace = true } libfuzzer-sys = { workspace = true } -move-binary-format = { path = "../../move-binary-format", features = ["fuzzing"] } -move-bytecode-verifier = { path = "../" } -move-core-types = { path = "../../move-core/types", features = ["fuzzing"] } -# Prevent this from interfering with workspaces -#[workspace] -#members = ["."] +move-binary-format = { workspace = true, features = ["fuzzing"] } +move-bytecode-verifier = { workspace = true } +move-core-types = { workspace = true, features = ["fuzzing"] } [[bin]] name = "code_unit" diff --git a/third_party/move/move-bytecode-verifier/invalid-mutations/Cargo.toml b/third_party/move/move-bytecode-verifier/invalid-mutations/Cargo.toml index 77a835ecfbb2d..db099869774ec 100644 --- a/third_party/move/move-bytecode-verifier/invalid-mutations/Cargo.toml +++ b/third_party/move/move-bytecode-verifier/invalid-mutations/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "invalid-mutations" +name = "move-bytecode-verifier-invalid-mutations" version = "0.1.0" edition = "2021" authors = ["Diem Association "] @@ -10,9 +10,6 @@ license = "Apache-2.0" publish = false [dependencies] -move-binary-format = { path = "../../move-binary-format" } -move-core-types = { path = "../../move-core/types" } +move-binary-format = { workspace = true } +move-core-types = { workspace = true } proptest = { workspace = true } - -[features] -default = [] diff --git a/third_party/move/move-bytecode-verifier/transactional-tests/Cargo.toml b/third_party/move/move-bytecode-verifier/transactional-tests/Cargo.toml index 2e346e12b13d9..c65d4f675b63f 100644 --- a/third_party/move/move-bytecode-verifier/transactional-tests/Cargo.toml +++ b/third_party/move/move-bytecode-verifier/transactional-tests/Cargo.toml @@ -8,7 +8,7 @@ license = "Apache-2.0" [dev-dependencies] datatest-stable = { workspace = true } -move-transactional-test-runner = { path = "../../testing-infra/transactional-test-runner" } +move-transactional-test-runner = { workspace = true } [[test]] name = "tests" diff --git a/third_party/move/move-command-line-common/Cargo.toml b/third_party/move/move-command-line-common/Cargo.toml index 4030dbe59abe9..7fc21855f506b 100644 --- a/third_party/move/move-command-line-common/Cargo.toml +++ b/third_party/move/move-command-line-common/Cargo.toml @@ -14,10 +14,9 @@ anyhow = { workspace = true } difference = { workspace = true } dirs-next = { workspace = true } hex = { workspace = true } +move-core-types = { workspace = true } num-bigint = { workspace = true } once_cell = { workspace = true } serde = { workspace = true, features = ["derive"] } sha2 = { workspace = true } walkdir = { workspace = true } - -move-core-types = { path = "../move-core/types" } diff --git a/third_party/move/move-compiler-v2/Cargo.toml b/third_party/move/move-compiler-v2/Cargo.toml index 90255ab170a9c..f24853b9f9b2b 100644 --- a/third_party/move/move-compiler-v2/Cargo.toml +++ b/third_party/move/move-compiler-v2/Cargo.toml @@ -13,37 +13,35 @@ edition = "2021" abstract-domain-derive = { path = "../move-model/bytecode/abstract_domain_derive" } anyhow = { workspace = true } bcs = { workspace = true } -move-binary-format = { path = "../move-binary-format" } -move-borrow-graph = { path = "../move-borrow-graph" } -move-bytecode-source-map = { path = "../move-ir-compiler/move-bytecode-source-map" } -move-bytecode-verifier = { path = "../move-bytecode-verifier" } -move-command-line-common = { path = "../move-command-line-common" } -move-compiler = { path = "../move-compiler" } -move-core-types = { path = "../move-core/types" } -move-disassembler = { path = "../tools/move-disassembler" } -move-ir-types = { path = "../move-ir/types" } -move-model = { path = "../move-model" } -move-stackless-bytecode = { path = "../move-model/bytecode" } -move-symbol-pool = { path = "../move-symbol-pool" } - clap = { workspace = true, features = ["derive", "env"] } codespan-reporting = { workspace = true, features = ["serde", "serialization"] } ethnum = { workspace = true } flexi_logger = { workspace = true } -im = "15.0.0" +im = { workspace = true } itertools = { workspace = true } log = { workspace = true, features = ["serde"] } +move-binary-format = { workspace = true } +move-borrow-graph = { workspace = true } +move-bytecode-source-map = { workspace = true } +move-bytecode-verifier = { workspace = true } +move-command-line-common = { workspace = true } +move-compiler = { workspace = true } +move-core-types = { workspace = true } +move-disassembler = { workspace = true } +move-ir-types = { workspace = true } +move-model = { workspace = true } +move-stackless-bytecode = { workspace = true } +move-symbol-pool = { workspace = true } num = { workspace = true } once_cell = { workspace = true } -#paste = "1.0.5" petgraph = { workspace = true } [dev-dependencies] anyhow = { workspace = true } datatest-stable = { workspace = true } -move-command-line-common = { path = "../move-command-line-common" } -move-ir-types = { path = "../move-ir/types" } -move-prover-test-utils = { path = "../move-prover/test-utils" } +move-command-line-common = { workspace = true } +move-ir-types = { workspace = true } +move-prover-test-utils = { workspace = true } move-stdlib = { path = "../move-stdlib" } walkdir = { workspace = true } diff --git a/third_party/move/move-compiler-v2/transactional-tests/Cargo.toml b/third_party/move/move-compiler-v2/transactional-tests/Cargo.toml index d8110ee7ae77f..8a8cccc3dd363 100644 --- a/third_party/move/move-compiler-v2/transactional-tests/Cargo.toml +++ b/third_party/move/move-compiler-v2/transactional-tests/Cargo.toml @@ -7,15 +7,15 @@ edition = "2021" license = "Apache-2.0" [dependencies] -move-command-line-common = { path = "../../move-command-line-common" } +move-command-line-common = { workspace = true } once_cell = { workspace = true } [dev-dependencies] datatest-stable = { workspace = true } itertools = { workspace = true } -move-compiler-v2 = { path = ".." } -move-model = { path = "../../move-model" } -move-transactional-test-runner = { path = "../../testing-infra/transactional-test-runner" } +move-compiler-v2 = { workspace = true } +move-model = { workspace = true } +move-transactional-test-runner = { workspace = true } walkdir = { workspace = true } [[test]] diff --git a/third_party/move/move-compiler/Cargo.toml b/third_party/move/move-compiler/Cargo.toml index 038362bf81b09..522ec440dcc87 100644 --- a/third_party/move/move-compiler/Cargo.toml +++ b/third_party/move/move-compiler/Cargo.toml @@ -19,15 +19,15 @@ tempfile = { workspace = true } bcs = { workspace = true } -move-binary-format = { path = "../move-binary-format" } -move-borrow-graph = { path = "../move-borrow-graph" } -move-bytecode-source-map = { path = "../move-ir-compiler/move-bytecode-source-map" } -move-bytecode-verifier = { path = "../move-bytecode-verifier" } -move-command-line-common = { path = "../move-command-line-common" } -move-core-types = { path = "../move-core/types" } -move-ir-to-bytecode = { path = "../move-ir-compiler/move-ir-to-bytecode" } -move-ir-types = { path = "../move-ir/types" } -move-symbol-pool = { path = "../move-symbol-pool" } +move-binary-format = { workspace = true } +move-borrow-graph = { workspace = true } +move-bytecode-source-map = { workspace = true } +move-bytecode-verifier = { workspace = true } +move-command-line-common = { workspace = true } +move-core-types = { workspace = true } +move-ir-to-bytecode = { workspace = true } +move-ir-types = { workspace = true } +move-symbol-pool = { workspace = true } [dev-dependencies] datatest-stable = { workspace = true } diff --git a/third_party/move/move-compiler/TODO b/third_party/move/move-compiler/TODO deleted file mode 100644 index fc8a05e8052c6..0000000000000 --- a/third_party/move/move-compiler/TODO +++ /dev/null @@ -1,41 +0,0 @@ -# P0 - -## Soundness - -* SCC generic check - -## Cohesion - -* Type inference nonsense (overtightened in types from parsing to typing) - -# P1 - -* Function args with `_` - -# P2 - -* suggest copy or *& on inferred duplicate move of affine types -* Traits on AST/Context -* Context in separate files -* location stack tracking - if (true) R{} else R{} points to unused resource really weirdly -* Better messages for unexpected exps in Expansion passes -* Stop using box::leak and atomicusize, pass around compilation context -* Address aliases -* Using all sorts of aliases in error messages - * i.e. 0x00000000000000384028920984.M.S becomes Sender.M.S - -# P3 - -* Dead resource/struct decls -* Dead field decls -* Unused type params -* Plurals in errors -* .. patterns in lvalues for structs -* move out of owned struct fields - * supporting x.f where x: S (i.e. move x.f) - -# P4 - -* improve language character set -* improve comments diff --git a/third_party/move/move-compiler/transactional-tests/Cargo.toml b/third_party/move/move-compiler/transactional-tests/Cargo.toml index 4a61fbf336685..cad9ae2a4bcef 100644 --- a/third_party/move/move-compiler/transactional-tests/Cargo.toml +++ b/third_party/move/move-compiler/transactional-tests/Cargo.toml @@ -8,7 +8,7 @@ license = "Apache-2.0" [dev-dependencies] datatest-stable = { workspace = true } -move-transactional-test-runner = { path = "../../testing-infra/transactional-test-runner" } +move-transactional-test-runner = { workspace = true } [[test]] name = "tests" diff --git a/third_party/move/move-examples/Cargo.toml b/third_party/move/move-examples/Cargo.toml index 89f791811f482..0df69fbb215cf 100644 --- a/third_party/move/move-examples/Cargo.toml +++ b/third_party/move/move-examples/Cargo.toml @@ -10,7 +10,7 @@ publish = false [dependencies] [dev-dependencies] -move-cli = { path = "../tools/move-cli" } +move-cli = { workspace = true } move-stdlib = { path = "../move-stdlib" } [features] diff --git a/third_party/move/move-examples/diem-framework/crates/cli/Cargo.toml b/third_party/move/move-examples/diem-framework/crates/cli/Cargo.toml index 54191f06121d6..a8dfc0cced206 100644 --- a/third_party/move/move-examples/diem-framework/crates/cli/Cargo.toml +++ b/third_party/move/move-examples/diem-framework/crates/cli/Cargo.toml @@ -10,14 +10,11 @@ edition = "2021" [dependencies] anyhow = { workspace = true } clap = { workspace = true, features = ["derive"] } - -move-cli = { path = "../../../../../tools/move-cli" } -move-core-types = { path = "../../../../../move-core/types" } - -move-stdlib = { path = "../../../../../move-stdlib" } -move-vm-test-utils = { path = "../../../../../move-vm/test-utils" } - diem-framework-natives = { path = "../natives" } +move-cli = { workspace = true } +move-core-types = { workspace = true } +move-stdlib = { path = "../../../../move-stdlib" } +move-vm-test-utils = { workspace = true } [dev-dependencies] datatest-stable = { workspace = true } diff --git a/third_party/move/move-examples/diem-framework/crates/natives/Cargo.toml b/third_party/move/move-examples/diem-framework/crates/natives/Cargo.toml index bb093436b9f69..86171b086b8ec 100644 --- a/third_party/move/move-examples/diem-framework/crates/natives/Cargo.toml +++ b/third_party/move/move-examples/diem-framework/crates/natives/Cargo.toml @@ -7,11 +7,9 @@ edition = "2021" license = "Apache-2.0" [dependencies] -move-binary-format = { path = "../../../../../move-binary-format" } -move-core-types = { path = "../../../../../move-core/types" } -move-vm-runtime = { path = "../../../../../move-vm/runtime" } -move-vm-types = { path = "../../../../../move-vm/types" } - diem-crypto = { path = "../crypto" } - +move-binary-format = { workspace = true } +move-core-types = { workspace = true } +move-vm-runtime = { workspace = true } +move-vm-types = { workspace = true } smallvec = { workspace = true } diff --git a/third_party/move/move-ir-compiler/Cargo.toml b/third_party/move/move-ir-compiler/Cargo.toml index 4a558246d37ec..0b3752139faf1 100644 --- a/third_party/move/move-ir-compiler/Cargo.toml +++ b/third_party/move/move-ir-compiler/Cargo.toml @@ -11,15 +11,11 @@ edition = "2021" [dependencies] anyhow = { workspace = true } +bcs = { workspace = true } clap = { workspace = true, features = ["derive"] } -move-binary-format = { path = "../move-binary-format" } -move-bytecode-source-map = { path = "move-bytecode-source-map" } -move-bytecode-verifier = { path = "../move-bytecode-verifier" } -move-command-line-common = { path = "../move-command-line-common" } -move-ir-to-bytecode = { path = "move-ir-to-bytecode" } +move-binary-format = { workspace = true } +move-bytecode-source-map = { workspace = true } +move-bytecode-verifier = { workspace = true } +move-command-line-common = { workspace = true } +move-ir-to-bytecode = { workspace = true } serde_json = { workspace = true } - -bcs = { workspace = true } - -[features] -default = [] diff --git a/third_party/move/move-ir-compiler/move-bytecode-source-map/Cargo.toml b/third_party/move/move-ir-compiler/move-bytecode-source-map/Cargo.toml index 434bccf85ac8d..b7428bba98985 100644 --- a/third_party/move/move-ir-compiler/move-bytecode-source-map/Cargo.toml +++ b/third_party/move/move-ir-compiler/move-bytecode-source-map/Cargo.toml @@ -8,15 +8,10 @@ edition = "2021" [dependencies] anyhow = { workspace = true } -move-binary-format = { path = "../../move-binary-format" } -move-command-line-common = { path = "../../move-command-line-common" } -move-core-types = { path = "../../move-core/types" } -move-ir-types = { path = "../../move-ir/types" } -move-symbol-pool = { path = "../../move-symbol-pool" } - bcs = { workspace = true } - +move-binary-format = { workspace = true } +move-command-line-common = { workspace = true } +move-core-types = { workspace = true } +move-ir-types = { workspace = true } +move-symbol-pool = { workspace = true } serde = { workspace = true } - -[features] -default = [] diff --git a/third_party/move/move-ir-compiler/move-ir-to-bytecode/Cargo.toml b/third_party/move/move-ir-compiler/move-ir-to-bytecode/Cargo.toml index cf897818ea2ad..27d17fbbefb69 100644 --- a/third_party/move/move-ir-compiler/move-ir-to-bytecode/Cargo.toml +++ b/third_party/move/move-ir-compiler/move-ir-to-bytecode/Cargo.toml @@ -13,14 +13,12 @@ edition = "2021" anyhow = { workspace = true } codespan-reporting = { workspace = true } log = { workspace = true } -move-binary-format = { path = "../../move-binary-format" } -move-bytecode-source-map = { path = "../move-bytecode-source-map" } -move-command-line-common = { path = "../../move-command-line-common" } -move-core-types = { path = "../../move-core/types" } +move-binary-format = { workspace = true } +move-bytecode-source-map = { workspace = true } +move-command-line-common = { workspace = true } +move-core-types = { workspace = true } move-ir-to-bytecode-syntax = { path = "syntax" } -move-ir-types = { path = "../../move-ir/types" } -move-symbol-pool = { path = "../../move-symbol-pool" } +move-ir-types = { workspace = true } +move-symbol-pool = { workspace = true } ouroboros = { workspace = true } -[features] -default = [] diff --git a/third_party/move/move-ir-compiler/move-ir-to-bytecode/syntax/Cargo.toml b/third_party/move/move-ir-compiler/move-ir-to-bytecode/syntax/Cargo.toml index 35e53bfe51bae..438ecddaef18b 100644 --- a/third_party/move/move-ir-compiler/move-ir-to-bytecode/syntax/Cargo.toml +++ b/third_party/move/move-ir-compiler/move-ir-to-bytecode/syntax/Cargo.toml @@ -12,10 +12,10 @@ edition = "2021" [dependencies] anyhow = { workspace = true } hex = { workspace = true } -move-command-line-common = { path = "../../../move-command-line-common" } -move-core-types = { path = "../../../move-core/types" } -move-ir-types = { path = "../../../move-ir/types" } -move-symbol-pool = { path = "../../../move-symbol-pool" } +move-command-line-common = { workspace = true } +move-core-types = { workspace = true } +move-ir-types = { workspace = true } +move-symbol-pool = { workspace = true } [features] default = [] diff --git a/third_party/move/move-ir-compiler/transactional-tests/Cargo.toml b/third_party/move/move-ir-compiler/transactional-tests/Cargo.toml index 84bd5b1309565..cdbe4757857f5 100644 --- a/third_party/move/move-ir-compiler/transactional-tests/Cargo.toml +++ b/third_party/move/move-ir-compiler/transactional-tests/Cargo.toml @@ -8,7 +8,7 @@ license = "Apache-2.0" [dev-dependencies] datatest-stable = { workspace = true } -move-transactional-test-runner = { path = "../../testing-infra/transactional-test-runner" } +move-transactional-test-runner = { workspace = true } [[test]] name = "tests" diff --git a/third_party/move/move-ir/types/Cargo.toml b/third_party/move/move-ir/types/Cargo.toml index adf98dc221ace..9b040edc45b1f 100644 --- a/third_party/move/move-ir/types/Cargo.toml +++ b/third_party/move/move-ir/types/Cargo.toml @@ -12,9 +12,8 @@ edition = "2021" [dependencies] hex = { workspace = true } -move-command-line-common = { path = "../../move-command-line-common" } +move-command-line-common = { workspace = true } +move-core-types = { workspace = true } +move-symbol-pool = { workspace = true } once_cell = { workspace = true } serde = { workspace = true, features = ["derive"] } - -move-core-types = { path = "../../move-core/types" } -move-symbol-pool = { path = "../../move-symbol-pool" } diff --git a/third_party/move/move-model/Cargo.toml b/third_party/move/move-model/Cargo.toml index 820a2b5b5af9b..a63e2cc297897 100644 --- a/third_party/move/move-model/Cargo.toml +++ b/third_party/move/move-model/Cargo.toml @@ -8,23 +8,20 @@ license = "Apache-2.0" [dependencies] anyhow = { workspace = true } -move-binary-format = { path = "../move-binary-format" } -move-bytecode-source-map = { path = "../move-ir-compiler/move-bytecode-source-map" } -move-command-line-common = { path = "../move-command-line-common" } -# diem dependencies -move-compiler = { path = "../move-compiler" } -move-core-types = { path = "../move-core/types" } -move-disassembler = { path = "../tools/move-disassembler" } -move-ir-types = { path = "../move-ir/types" } -move-symbol-pool = { path = "../move-symbol-pool" } - -# external dependencies codespan = { workspace = true } codespan-reporting = { workspace = true } either = { workspace = true } internment = { workspace = true, features = ["arc"] } itertools = { workspace = true } log = { workspace = true } +move-binary-format = { workspace = true } +move-bytecode-source-map = { workspace = true } +move-command-line-common = { workspace = true } +move-compiler = { workspace = true } +move-core-types = { workspace = true } +move-disassembler = { workspace = true } +move-ir-types = { workspace = true } +move-symbol-pool = { workspace = true } num = { workspace = true } num-traits = { workspace = true } once_cell = { workspace = true } @@ -33,7 +30,7 @@ serde = { workspace = true, features = ["derive"] } [dev-dependencies] datatest-stable = { workspace = true } -move-prover-test-utils = { path = "../move-prover/test-utils" } +move-prover-test-utils = { workspace = true } [[test]] name = "testsuite" diff --git a/third_party/move/move-model/bytecode-test-utils/Cargo.toml b/third_party/move/move-model/bytecode-test-utils/Cargo.toml index eb622da8f865b..2b31cc3b0a509 100644 --- a/third_party/move/move-model/bytecode-test-utils/Cargo.toml +++ b/third_party/move/move-model/bytecode-test-utils/Cargo.toml @@ -12,10 +12,10 @@ edition = "2021" [dependencies] anyhow = { workspace = true } codespan-reporting = { workspace = true, features = ["serde", "serialization"] } -move-command-line-common = { path = "../../move-command-line-common" } -move-compiler = { path = "../../move-compiler" } -move-compiler-v2 = { path = "../../move-compiler-v2" } -move-model = { path = ".." } -move-prover-test-utils = { path = "../../move-prover/test-utils" } -move-stackless-bytecode = { path = "../bytecode" } +move-command-line-common = { workspace = true } +move-compiler = { workspace = true } +move-compiler-v2 = { workspace = true } +move-model = { workspace = true } +move-prover-test-utils = { workspace = true } +move-stackless-bytecode = { workspace = true } move-stdlib = { path = "../../move-stdlib" } diff --git a/third_party/move/move-model/bytecode/Cargo.toml b/third_party/move/move-model/bytecode/Cargo.toml index 55fca5723dfb2..8770e6f4b981c 100644 --- a/third_party/move/move-model/bytecode/Cargo.toml +++ b/third_party/move/move-model/bytecode/Cargo.toml @@ -11,16 +11,15 @@ edition = "2021" [dependencies] abstract-domain-derive = { path = "./abstract_domain_derive" } -move-binary-format = { path = "../../move-binary-format" } -move-core-types = { path = "../../move-core/types" } -move-model = { path = ".." } - anyhow = { workspace = true } codespan-reporting = { workspace = true, features = ["serde", "serialization"] } ethnum = { workspace = true } -im = "15.0.0" +im = { workspace = true } itertools = { workspace = true } log = { workspace = true } +move-binary-format = { workspace = true } +move-core-types = { workspace = true } +move-model = { workspace = true } num = { workspace = true } paste = { workspace = true } petgraph = { workspace = true } @@ -30,7 +29,7 @@ try_match = { workspace = true } [dev-dependencies] anyhow = { workspace = true } datatest-stable = { workspace = true } -move-stackless-bytecode-test-utils = { path = "../bytecode-test-utils" } +move-stackless-bytecode-test-utils = { workspace = true } [features] default = [] diff --git a/third_party/move/move-model/bytecode/abstract_domain_derive/Cargo.toml b/third_party/move/move-model/bytecode/abstract_domain_derive/Cargo.toml index 27a8a2c0fb76f..2c183c6388408 100644 --- a/third_party/move/move-model/bytecode/abstract_domain_derive/Cargo.toml +++ b/third_party/move/move-model/bytecode/abstract_domain_derive/Cargo.toml @@ -15,4 +15,4 @@ quote = { workspace = true } proc-macro2 = { workspace = true } [dev-dependencies] -move-stackless-bytecode = { path = ".." } +move-stackless-bytecode = { workspace = true } diff --git a/third_party/move/move-prover/Cargo.toml b/third_party/move/move-prover/Cargo.toml index 2609f4abd3c10..12b76dec75697 100644 --- a/third_party/move/move-prover/Cargo.toml +++ b/third_party/move/move-prover/Cargo.toml @@ -8,24 +8,21 @@ license = "Apache-2.0" [dependencies] anyhow = { workspace = true } -move-abigen = { path = "move-abigen" } -move-command-line-common = { path = "../move-command-line-common" } -move-compiler = { path = "../move-compiler" } -move-compiler-v2 = { path = "../move-compiler-v2" } -move-docgen = { path = "move-docgen" } -move-errmapgen = { path = "move-errmapgen" } -move-model = { path = "../move-model" } -# move dependencies -move-prover-boogie-backend = { path = "boogie-backend" } -move-prover-bytecode-pipeline = { path = "bytecode-pipeline" } -move-stackless-bytecode = { path = "../move-model/bytecode" } - -# external dependencies atty = { workspace = true } clap = { workspace = true, features = ["derive"] } codespan-reporting = { workspace = true } itertools = { workspace = true } log = { workspace = true, features = ["serde"] } +move-abigen = { workspace = true } +move-command-line-common = { workspace = true } +move-compiler = { workspace = true } +move-compiler-v2 = { workspace = true } +move-docgen = { workspace = true } +move-errmapgen = { workspace = true } +move-model = { workspace = true } +move-prover-boogie-backend = { workspace = true } +move-prover-bytecode-pipeline = { workspace = true } +move-stackless-bytecode = { workspace = true } once_cell = { workspace = true } serde = { workspace = true, features = ["derive"] } simplelog = { workspace = true } @@ -33,7 +30,7 @@ toml = { workspace = true } [dev-dependencies] datatest-stable = { workspace = true } -move-prover-test-utils = { path = "test-utils" } +move-prover-test-utils = { workspace = true } shell-words = { workspace = true } tempfile = { workspace = true } walkdir = { workspace = true } diff --git a/third_party/move/move-prover/boogie-backend/Cargo.toml b/third_party/move/move-prover/boogie-backend/Cargo.toml index 690d070040639..7ba19d237e570 100644 --- a/third_party/move/move-prover/boogie-backend/Cargo.toml +++ b/third_party/move/move-prover/boogie-backend/Cargo.toml @@ -15,13 +15,13 @@ codespan-reporting = { workspace = true } futures = { workspace = true } itertools = { workspace = true } log = { workspace = true } -move-binary-format = { path = "../../move-binary-format" } -move-command-line-common = { path = "../../move-command-line-common" } -move-compiler = { path = "../../move-compiler" } -move-core-types = { path = "../../move-core/types" } -move-model = { path = "../../move-model" } -move-prover-bytecode-pipeline = { path = "../bytecode-pipeline" } -move-stackless-bytecode = { path = "../../move-model/bytecode" } +move-binary-format = { workspace = true } +move-command-line-common = { workspace = true } +move-compiler = { workspace = true } +move-core-types = { workspace = true } +move-model = { workspace = true } +move-prover-bytecode-pipeline = { workspace = true } +move-stackless-bytecode = { workspace = true } num = { workspace = true } once_cell = { workspace = true } pretty = { workspace = true } diff --git a/third_party/move/move-prover/bytecode-pipeline/Cargo.toml b/third_party/move/move-prover/bytecode-pipeline/Cargo.toml index 4a0fc40b37588..366973ed14db2 100644 --- a/third_party/move/move-prover/bytecode-pipeline/Cargo.toml +++ b/third_party/move/move-prover/bytecode-pipeline/Cargo.toml @@ -9,22 +9,18 @@ license = "Apache-2.0" [dependencies] abstract-domain-derive = { path = "../../move-model/bytecode/abstract_domain_derive" } anyhow = { workspace = true } -move-binary-format = { path = "../../move-binary-format" } -move-core-types = { path = "../../move-core/types" } -move-model = { path = "../../move-model" } - -# move dependencies -move-stackless-bytecode = { path = "../../move-model/bytecode" } - -# external dependencies codespan-reporting = { workspace = true } itertools = { workspace = true } log = { workspace = true, features = ["serde"] } +move-binary-format = { workspace = true } +move-core-types = { workspace = true } +move-model = { workspace = true } +move-stackless-bytecode = { workspace = true } serde = { workspace = true, features = ["derive"] } [dev-dependencies] datatest-stable = { workspace = true } -move-stackless-bytecode-test-utils = { path = "../../move-model/bytecode-test-utils" } +move-stackless-bytecode-test-utils = { workspace = true } shell-words = { workspace = true } tempfile = { workspace = true } walkdir = { workspace = true } diff --git a/third_party/move/move-prover/lab/Cargo.toml b/third_party/move/move-prover/lab/Cargo.toml index b8a23eca6e5ec..5ebf0e18075a0 100644 --- a/third_party/move/move-prover/lab/Cargo.toml +++ b/third_party/move/move-prover/lab/Cargo.toml @@ -7,26 +7,18 @@ edition = "2021" license = "Apache-2.0" [dependencies] -# Move dependencies -move-compiler = { path = "../../move-compiler" } -move-compiler-v2 = { path = "../../move-compiler-v2" } -move-model = { path = "../../move-model" } -move-prover = { path = ".." } -move-prover-boogie-backend = { path = "../boogie-backend" } -move-prover-bytecode-pipeline = { path = "../bytecode-pipeline" } - -# FB external dependencies -z3tracer = { workspace = true } - -# external dependencies anyhow = { workspace = true } chrono = { workspace = true } clap = { workspace = true, features = ["derive"] } codespan-reporting = { workspace = true } itertools = { workspace = true } log = { workspace = true, features = ["serde"] } -plotters = { workspace = true, features = [ - "evcxr", - "line_series", - "histogram", -] } +move-compiler = { workspace = true } +move-compiler-v2 = { workspace = true } +move-model = { workspace = true } +move-prover = { workspace = true } +move-prover-boogie-backend = { workspace = true } +move-prover-bytecode-pipeline = { workspace = true } +plotters = { workspace = true, features = ["evcxr", "line_series", "histogram"] } +z3tracer = { workspace = true } + diff --git a/third_party/move/move-prover/move-abigen/Cargo.toml b/third_party/move/move-prover/move-abigen/Cargo.toml index 13880ec1606f9..d9da5ad60f5d1 100644 --- a/third_party/move/move-prover/move-abigen/Cargo.toml +++ b/third_party/move/move-prover/move-abigen/Cargo.toml @@ -8,25 +8,21 @@ license = "Apache-2.0" [dependencies] anyhow = { workspace = true } -move-binary-format = { path = "../../move-binary-format" } -move-bytecode-verifier = { path = "../../move-bytecode-verifier" } -move-command-line-common = { path = "../../move-command-line-common" } -move-core-types = { path = "../../move-core/types" } -# Move dependencies -move-model = { path = "../../move-model" } - bcs = { workspace = true } heck = { workspace = true } - -# external dependencies log = { workspace = true } +move-binary-format = { workspace = true } +move-bytecode-verifier = { workspace = true } +move-command-line-common = { workspace = true } +move-core-types = { workspace = true } +move-model = { workspace = true } serde = { workspace = true, features = ["derive"] } [dev-dependencies] codespan-reporting = { workspace = true } datatest-stable = { workspace = true } -move-prover = { path = ".." } -move-prover-test-utils = { path = "../test-utils" } +move-prover = { workspace = true } +move-prover-test-utils = { workspace = true } tempfile = { workspace = true } # force more deterministic tests diff --git a/third_party/move/move-prover/move-docgen/Cargo.toml b/third_party/move/move-prover/move-docgen/Cargo.toml index c1193b4947ba5..dd4e617cdf217 100644 --- a/third_party/move/move-prover/move-docgen/Cargo.toml +++ b/third_party/move/move-prover/move-docgen/Cargo.toml @@ -8,25 +8,22 @@ license = "Apache-2.0" [dependencies] anyhow = { workspace = true } -# diem dependencies -move-compiler = { path = "../../move-compiler" } -move-core-types = { path = "../../move-core/types" } -move-model = { path = "../../move-model" } - -# external dependencies clap = { workspace = true } codespan = { workspace = true } codespan-reporting = { workspace = true } itertools = { workspace = true } log = { workspace = true } +move-compiler = { workspace = true } +move-core-types = { workspace = true } +move-model = { workspace = true } once_cell = { workspace = true } regex = { workspace = true } serde = { workspace = true, features = ["derive"] } [dev-dependencies] datatest-stable = { workspace = true } -move-prover = { path = ".." } -move-prover-test-utils = { path = "../test-utils" } +move-prover = { workspace = true } +move-prover-test-utils = { workspace = true } tempfile = { workspace = true } [[test]] diff --git a/third_party/move/move-prover/move-errmapgen/Cargo.toml b/third_party/move/move-prover/move-errmapgen/Cargo.toml index 6b726107fbf97..9e448d8bd17d9 100644 --- a/third_party/move/move-prover/move-errmapgen/Cargo.toml +++ b/third_party/move/move-prover/move-errmapgen/Cargo.toml @@ -8,15 +8,12 @@ license = "Apache-2.0" [dependencies] anyhow = { workspace = true } -# Move dependencies -move-command-line-common = { path = "../../move-command-line-common" } -move-core-types = { path = "../../move-core/types" } -move-model = { path = "../../move-model" } - -# external dependencies +move-command-line-common = { workspace = true } +move-core-types ={ workspace = true } +move-model = { workspace = true } serde = { workspace = true, features = ["derive"] } [dev-dependencies] codespan-reporting = { workspace = true } datatest-stable = { workspace = true } -move-prover = { path = ".." } +move-prover = { workspace = true } diff --git a/third_party/move/move-prover/test-utils/Cargo.toml b/third_party/move/move-prover/test-utils/Cargo.toml index 576de1ab67db2..d18e3baec45f1 100644 --- a/third_party/move/move-prover/test-utils/Cargo.toml +++ b/third_party/move/move-prover/test-utils/Cargo.toml @@ -8,6 +8,6 @@ license = "Apache-2.0" [dependencies] anyhow = { workspace = true } -move-command-line-common = { path = "../../move-command-line-common" } +move-command-line-common = { workspace = true } prettydiff = { workspace = true } regex = { workspace = true } diff --git a/third_party/move/move-stdlib/Cargo.toml b/third_party/move/move-stdlib/Cargo.toml index 6d643779e4db5..164491155f2c4 100644 --- a/third_party/move/move-stdlib/Cargo.toml +++ b/third_party/move/move-stdlib/Cargo.toml @@ -14,15 +14,15 @@ publish = false anyhow = { workspace = true } hex = { workspace = true } log = { workspace = true } -move-binary-format = { path = "../move-binary-format" } -move-command-line-common = { path = "../move-command-line-common" } -move-compiler = { path = "../move-compiler" } -move-core-types = { path = "../move-core/types" } -move-docgen = { path = "../move-prover/move-docgen" } -move-errmapgen = { path = "../move-prover/move-errmapgen" } -move-prover = { path = "../move-prover" } -move-vm-runtime = { path = "../move-vm/runtime" } -move-vm-types = { path = "../move-vm/types" } +move-binary-format = { workspace = true } +move-command-line-common = { workspace = true } +move-compiler ={ workspace = true } +move-core-types = { workspace = true } +move-docgen = { workspace = true } +move-errmapgen = { workspace = true } +move-prover = { workspace = true } +move-vm-runtime = { workspace = true } +move-vm-types = { workspace = true } sha2 = { workspace = true } sha3 = { workspace = true } smallvec = { workspace = true } @@ -31,9 +31,9 @@ walkdir = { workspace = true } [dev-dependencies] dir-diff = { workspace = true } file_diff = { workspace = true } -move-cli = { path = "../tools/move-cli" } -move-package = { path = "../tools/move-package" } -move-unit-test = { path = "../tools/move-unit-test" } +move-cli = { workspace = true } +move-package = { workspace = true } +move-unit-test = { workspace = true } tempfile = { workspace = true } [features] diff --git a/third_party/move/move-vm/integration-tests/Cargo.toml b/third_party/move/move-vm/integration-tests/Cargo.toml index 99a7339b94520..9a592c082f8e3 100644 --- a/third_party/move/move-vm/integration-tests/Cargo.toml +++ b/third_party/move/move-vm/integration-tests/Cargo.toml @@ -14,20 +14,17 @@ edition = "2021" anyhow = { workspace = true } bytes = { workspace = true } memory-stats = { workspace = true } -move-binary-format = { path = "../../move-binary-format", features = ["testing"] } -move-bytecode-verifier = { path = "../../move-bytecode-verifier" } -move-compiler = { path = "../../move-compiler" } +move-binary-format = { workspace = true, features = ["testing"] } +move-bytecode-verifier = { workspace = true } +move-compiler = { workspace = true } +move-core-types = { workspace = true } +move-stdlib = { path = "../../move-stdlib" } +move-vm-runtime = { workspace = true, features = ["testing"] } +move-vm-test-utils = { workspace = true } +move-vm-types = { workspace = true } smallvec = { workspace = true } tempfile = { workspace = true } -move-core-types = { path = "../../move-core/types" } -move-stdlib = { path = "../../move-stdlib" } -move-vm-runtime = { path = "../runtime", features = ["testing"] } -move-vm-test-utils = { path = "../test-utils" } -move-vm-types = { path = "../types" } - [features] default = [] -table-extension = [ - "move-vm-test-utils/table-extension" -] +table-extension = ["move-vm-test-utils/table-extension"] diff --git a/third_party/move/move-vm/paranoid-tests/Cargo.toml b/third_party/move/move-vm/paranoid-tests/Cargo.toml index bf4e6bb08686f..8cfbe663bb364 100644 --- a/third_party/move/move-vm/paranoid-tests/Cargo.toml +++ b/third_party/move/move-vm/paranoid-tests/Cargo.toml @@ -9,7 +9,7 @@ license = "Apache-2.0" [dev-dependencies] datatest-stable = { workspace = true } fail = { workspace = true, features = ['failpoints'] } -move-transactional-test-runner = { path = "../../testing-infra/transactional-test-runner", features = ['failpoints'] } +move-transactional-test-runner = { workspace = true, features = ['failpoints'] } [[test]] name = "tests" diff --git a/third_party/move/move-vm/runtime/Cargo.toml b/third_party/move/move-vm/runtime/Cargo.toml index d571a94607332..4b20b934b638c 100644 --- a/third_party/move/move-vm/runtime/Cargo.toml +++ b/third_party/move/move-vm/runtime/Cargo.toml @@ -19,7 +19,11 @@ fail = { workspace = true } hashbrown = { workspace = true } lazy_static = { workspace = true } lru = { workspace = true } -move-binary-format = { path = "../../move-binary-format" } +move-binary-format = { workspace = true } +move-bytecode-verifier = { workspace = true } +move-core-types = { workspace = true } +move-vm-metrics = { workspace = true } +move-vm-types = { workspace = true } once_cell = { workspace = true } parking_lot = { workspace = true } serde = { workspace = true } @@ -27,18 +31,13 @@ sha3 = { workspace = true } triomphe = { workspace = true } typed-arena = { workspace = true } -move-bytecode-verifier = { path = "../../move-bytecode-verifier" } -move-core-types = { path = "../../move-core/types" } -move-vm-metrics = { workspace = true } -move-vm-types = { path = "../types" } - [dev-dependencies] anyhow = { workspace = true } hex = { workspace = true } -move-binary-format = { path = "../../move-binary-format", features = ["fuzzing"] } -move-compiler = { path = "../../move-compiler" } -move-ir-compiler = { path = "../../move-ir-compiler" } -move-vm-test-utils = { path = "../test-utils" } +move-binary-format = { workspace = true, features = ["fuzzing"] } +move-compiler = { workspace = true } +move-ir-compiler = { workspace = true } +move-vm-test-utils ={ workspace = true } proptest = { workspace = true } [features] diff --git a/third_party/move/move-vm/test-utils/Cargo.toml b/third_party/move/move-vm/test-utils/Cargo.toml index 1d075c08cca17..5073ddbdf150d 100644 --- a/third_party/move/move-vm/test-utils/Cargo.toml +++ b/third_party/move/move-vm/test-utils/Cargo.toml @@ -13,15 +13,14 @@ edition = "2021" [dependencies] anyhow = { workspace = true } bytes = { workspace = true } +move-binary-format = { workspace = true } +move-bytecode-utils = { workspace = true } +move-core-types = { workspace = true } +move-table-extension = { workspace = true, optional = true } +move-vm-types = { workspace = true } once_cell = { workspace = true } serde = { workspace = true, features = ["derive", "rc"] } -move-binary-format = { path = "../../move-binary-format" } -move-bytecode-utils = { path = "../../tools/move-bytecode-utils" } -move-core-types = { path = "../../move-core/types" } -move-table-extension = { path = "../../extensions/move-table-extension", optional = true } -move-vm-types = { path = "../types" } - [features] default = [] table-extension = ["move-table-extension"] diff --git a/third_party/move/move-vm/transactional-tests/Cargo.toml b/third_party/move/move-vm/transactional-tests/Cargo.toml index 6d30685ac1ed5..f8c26618772ab 100644 --- a/third_party/move/move-vm/transactional-tests/Cargo.toml +++ b/third_party/move/move-vm/transactional-tests/Cargo.toml @@ -8,7 +8,7 @@ license = "Apache-2.0" [dev-dependencies] datatest-stable = { workspace = true } -move-transactional-test-runner = { path = "../../testing-infra/transactional-test-runner" } +move-transactional-test-runner = { workspace = true } [[test]] name = "tests" diff --git a/third_party/move/move-vm/types/Cargo.toml b/third_party/move/move-vm/types/Cargo.toml index e98295f82d738..858a924fc1641 100644 --- a/third_party/move/move-vm/types/Cargo.toml +++ b/third_party/move/move-vm/types/Cargo.toml @@ -18,6 +18,8 @@ dashmap = { workspace = true } derivative = { workspace = true } hashbrown = { workspace = true } itertools = { workspace = true } +move-binary-format = { workspace = true } +move-core-types = { workspace = true } proptest = { workspace = true, optional = true } serde = { workspace = true, features = ["derive", "rc"] } sha3 = { workspace = true } @@ -25,12 +27,9 @@ smallbitvec = { workspace = true } smallvec = { workspace = true } triomphe = { workspace = true } -move-binary-format = { path = "../../move-binary-format" } -move-core-types = { path = "../../move-core/types" } - [dev-dependencies] claims = { workspace = true } -move-binary-format = { path = "../../move-binary-format", features = ["fuzzing"] } +move-binary-format = { workspace = true, features = ["fuzzing"] } proptest = { workspace = true } rand = { workspace = true } diff --git a/third_party/move/testing-infra/module-generation/Cargo.toml b/third_party/move/testing-infra/module-generation/Cargo.toml index ca6088cdec1ca..3179dab7209c3 100644 --- a/third_party/move/testing-infra/module-generation/Cargo.toml +++ b/third_party/move/testing-infra/module-generation/Cargo.toml @@ -10,16 +10,15 @@ publish = false edition = "2021" [dependencies] -move-binary-format = { path = "../../move-binary-format" } +move-binary-format = { workspace = true } +move-bytecode-verifier = { workspace = true } +move-core-types = { workspace = true } +move-ir-to-bytecode = { workspace = true } +move-ir-types = { workspace = true } +move-symbol-pool = { workspace = true } # Cannot use workspace version as aptos-core currently cannot be upgraded # to newer rand. See https://github.com/aptos-labs/aptos-core/issues/13031 rand = { version = "0.8.5" } -move-bytecode-verifier = { path = "../../move-bytecode-verifier" } -move-core-types = { path = "../../move-core/types" } -move-ir-to-bytecode = { path = "../../move-ir-compiler/move-ir-to-bytecode" } -move-ir-types = { path = "../../move-ir/types" } -move-symbol-pool = { path = "../../move-symbol-pool" } - [features] default = [] diff --git a/third_party/move/testing-infra/transactional-test-runner/Cargo.toml b/third_party/move/testing-infra/transactional-test-runner/Cargo.toml index 3249bb20ec279..f7b71119528b0 100644 --- a/third_party/move/testing-infra/transactional-test-runner/Cargo.toml +++ b/third_party/move/testing-infra/transactional-test-runner/Cargo.toml @@ -12,29 +12,28 @@ edition = "2021" [dependencies] anyhow = { workspace = true } clap = { workspace = true, features = ["derive"] } -move-binary-format = { path = "../../move-binary-format", features = ["testing"] } -move-bytecode-source-map = { path = "../../move-ir-compiler/move-bytecode-source-map" } -move-bytecode-verifier = { path = "../../move-bytecode-verifier" } -move-command-line-common = { path = "../../move-command-line-common" } -move-compiler = { path = "../../move-compiler" } -move-compiler-v2 = { path = "../../move-compiler-v2" } -move-core-types = { path = "../../move-core/types" } -move-disassembler = { path = "../../tools/move-disassembler" } -move-ir-compiler = { path = "../../move-ir-compiler" } -move-ir-types = { path = "../../move-ir/types" } -move-model = { path = "../../move-model" } -move-resource-viewer = { path = "../../tools/move-resource-viewer" } +move-binary-format = { workspace = true, features = ["testing"] } +move-bytecode-source-map = { workspace = true } +move-bytecode-verifier = { workspace = true } +move-command-line-common = { workspace = true } +move-compiler = { workspace = true } +move-compiler-v2 = { workspace = true } +move-core-types = { workspace = true } +move-disassembler = { workspace = true } +move-ir-compiler = { workspace = true } +move-ir-types = { workspace = true } +move-model = { workspace = true } +move-resource-viewer = { workspace = true } +move-stdlib = { path = "../../move-stdlib", features = ["testing"] } +move-symbol-pool = { workspace = true } +move-vm-runtime = { workspace = true, features = ["testing"] } +move-vm-test-utils = { workspace = true } +move-vm-types = { workspace = true } once_cell = { workspace = true } regex = { workspace = true } tempfile = { workspace = true } termcolor = { workspace = true } -move-stdlib = { path = "../../move-stdlib", features = ["testing"] } -move-symbol-pool = { path = "../../move-symbol-pool" } -move-vm-runtime = { path = "../../move-vm/runtime", features = ["testing"] } -move-vm-test-utils = { path = "../../move-vm/test-utils" } -move-vm-types = { path = "../../move-vm/types" } - [dev-dependencies] datatest-stable = { workspace = true } difference = { workspace = true } diff --git a/third_party/move/tools/move-bytecode-utils/Cargo.toml b/third_party/move/tools/move-bytecode-utils/Cargo.toml index aa14f2a099841..a85724ca75940 100644 --- a/third_party/move/tools/move-bytecode-utils/Cargo.toml +++ b/third_party/move/tools/move-bytecode-utils/Cargo.toml @@ -11,7 +11,7 @@ edition = "2021" [dependencies] anyhow = { workspace = true } -move-binary-format = { path = "../../move-binary-format" } -move-core-types = { path = "../../move-core/types" } +move-binary-format = { workspace = true } +move-core-types = { workspace = true } petgraph = { workspace = true } serde-reflection = { workspace = true } diff --git a/third_party/move/tools/move-bytecode-viewer/Cargo.toml b/third_party/move/tools/move-bytecode-viewer/Cargo.toml index e3a51224a71a7..ac4a3de10bf65 100644 --- a/third_party/move/tools/move-bytecode-viewer/Cargo.toml +++ b/third_party/move/tools/move-bytecode-viewer/Cargo.toml @@ -11,12 +11,11 @@ edition = "2021" anyhow = { workspace = true } clap = { workspace = true, features = ["derive"] } crossterm = { workspace = true } -move-binary-format = { path = "../../move-binary-format" } -move-bytecode-source-map = { path = "../../move-ir-compiler/move-bytecode-source-map" } +move-binary-format = { workspace = true } +move-bytecode-source-map = { workspace = true } +move-disassembler = { workspace = true } regex = { workspace = true } tui = { workspace = true } -move-disassembler = { path = "../move-disassembler" } - [features] default = [] diff --git a/third_party/move/tools/move-cli/Cargo.toml b/third_party/move/tools/move-cli/Cargo.toml index f7ee5cf507ff3..a3e8a3a623293 100644 --- a/third_party/move/tools/move-cli/Cargo.toml +++ b/third_party/move/tools/move-cli/Cargo.toml @@ -14,27 +14,26 @@ anyhow = { workspace = true } clap = { workspace = true, features = ["derive"] } codespan-reporting = { workspace = true } colored = { workspace = true } +move-binary-format = { workspace = true } +move-bytecode-viewer = { workspace = true } +move-command-line-common = { workspace = true } +move-compiler = { workspace = true } +move-compiler-v2 = { workspace = true } +move-core-types = { workspace = true } +move-coverage = { workspace = true } +move-disassembler = { workspace = true } +move-docgen = { workspace = true } +move-errmapgen = { workspace = true } +move-model = { workspace = true } +move-package = { workspace = true } +move-prover = { workspace = true } +move-stdlib = { path = "../../move-stdlib" } +move-unit-test = { workspace = true } +move-vm-runtime = { workspace = true, features = ["debugging"] } +move-vm-test-utils = { workspace = true } once_cell = { workspace = true } tempfile = { workspace = true } -move-binary-format = { path = "../../move-binary-format" } -move-bytecode-viewer = { path = "../move-bytecode-viewer" } -move-command-line-common = { path = "../../move-command-line-common" } -move-compiler = { path = "../../move-compiler" } -move-compiler-v2 = { path = "../../move-compiler-v2" } -move-core-types = { path = "../../move-core/types" } -move-coverage = { path = "../move-coverage" } -move-disassembler = { path = "../move-disassembler" } -move-docgen = { path = "../../move-prover/move-docgen" } -move-errmapgen = { path = "../../move-prover/move-errmapgen" } -move-model = { path = "../../move-model" } -move-package = { path = "../move-package" } -move-prover = { path = "../../move-prover" } -move-stdlib = { path = "../../move-stdlib" } -move-unit-test = { path = "../move-unit-test" } -move-vm-runtime = { path = "../../move-vm/runtime", features = ["debugging"] } -move-vm-test-utils = { path = "../../move-vm/test-utils" } - [dev-dependencies] datatest-stable = { workspace = true } httpmock = { workspace = true } diff --git a/third_party/move/tools/move-coverage/Cargo.toml b/third_party/move/tools/move-coverage/Cargo.toml index 276754c9b3ca3..a3342f30ef767 100644 --- a/third_party/move/tools/move-coverage/Cargo.toml +++ b/third_party/move/tools/move-coverage/Cargo.toml @@ -11,19 +11,17 @@ edition = "2021" [dependencies] anyhow = { workspace = true } +bcs = { workspace = true } clap = { workspace = true, features = ["derive"] } codespan = { workspace = true, features = ["serialization"] } colored = { workspace = true } +move-binary-format = { workspace = true } +move-bytecode-source-map = { workspace = true } +move-command-line-common = { workspace = true } +move-core-types = { workspace = true } +move-ir-types = { workspace = true } petgraph = { workspace = true } serde = { workspace = true } -bcs = { workspace = true } -move-binary-format = { path = "../../move-binary-format" } -move-bytecode-source-map = { path = "../../move-ir-compiler/move-bytecode-source-map" } - -move-command-line-common = { path = "../../move-command-line-common" } -move-core-types = { path = "../../move-core/types" } -move-ir-types = { path = "../../move-ir/types" } - [features] default = [] diff --git a/third_party/move/tools/move-decompiler/Cargo.toml b/third_party/move/tools/move-decompiler/Cargo.toml index 2c331cdca315a..723f296dbfdb0 100644 --- a/third_party/move/tools/move-decompiler/Cargo.toml +++ b/third_party/move/tools/move-decompiler/Cargo.toml @@ -11,11 +11,10 @@ edition = "2021" [dependencies] anyhow = { workspace = true } +bcs = { workspace = true } clap = { workspace = true, features = ["derive"] } codespan = { workspace = true } codespan-reporting = { workspace = true, features = ["serde", "serialization"] } - -bcs = { workspace = true } move-binary-format = { workspace = true } move-bytecode-source-map = { workspace = true } move-bytecode-verifier = { workspace = true } diff --git a/third_party/move/tools/move-disassembler/Cargo.toml b/third_party/move/tools/move-disassembler/Cargo.toml index 33babe7a7f674..b2ae37947a63c 100644 --- a/third_party/move/tools/move-disassembler/Cargo.toml +++ b/third_party/move/tools/move-disassembler/Cargo.toml @@ -9,17 +9,15 @@ edition = "2021" [dependencies] anyhow = { workspace = true } -colored = { workspace = true } -move-binary-format = { path = "../../move-binary-format" } -move-bytecode-source-map = { path = "../../move-ir-compiler/move-bytecode-source-map" } - -move-command-line-common = { path = "../../move-command-line-common" } -move-compiler = { path = "../../move-compiler" } -move-core-types = { path = "../../move-core/types" } -move-coverage = { path = "../move-coverage" } -move-ir-types = { path = "../../move-ir/types" } - clap = { workspace = true, features = ["derive"] } +colored = { workspace = true } +move-binary-format = { workspace = true } +move-bytecode-source-map = { workspace = true } +move-command-line-common = { workspace = true } +move-compiler = { workspace = true } +move-core-types = { workspace = true } +move-coverage = { workspace = true } +move-ir-types = { workspace = true } [features] default = [] diff --git a/third_party/move/tools/move-explain/Cargo.toml b/third_party/move/tools/move-explain/Cargo.toml index a6d982f3caa0e..7002b14395079 100644 --- a/third_party/move/tools/move-explain/Cargo.toml +++ b/third_party/move/tools/move-explain/Cargo.toml @@ -10,11 +10,10 @@ publish = false edition = "2021" [dependencies] -clap = { workspace = true, features = ["derive"] } -move-command-line-common = { path = "../../move-command-line-common" } -move-core-types = { path = "../../move-core/types" } - bcs = { workspace = true } +clap = { workspace = true, features = ["derive"] } +move-command-line-common = { workspace = true } +move-core-types = { workspace = true } [features] default = [] diff --git a/third_party/move/tools/move-linter/Cargo.toml b/third_party/move/tools/move-linter/Cargo.toml index e4db9861a9971..947f77132d42b 100644 --- a/third_party/move/tools/move-linter/Cargo.toml +++ b/third_party/move/tools/move-linter/Cargo.toml @@ -1,13 +1,16 @@ [package] name = "move-linter" -version = "0.1.0" -authors = ["Aptos Labs"] description = "The Move Linter" -repository = "https://github.com/aptos-labs/aptos-core" -homepage = "https://aptosfoundation.org/" -license = "Apache-2.0" -publish = false -edition = "2021" +version = "0.1.0" + +# Workspace inherited keys +authors = { workspace = true } +edition = { workspace = true } +homepage = { workspace = true } +license = { workspace = true } +publish = { workspace = true } +repository = { workspace = true } +rust-version = { workspace = true } [dependencies] codespan-reporting = { workspace = true } diff --git a/third_party/move/tools/move-package/Cargo.toml b/third_party/move/tools/move-package/Cargo.toml index 7c57f7cffc06b..9d9193497db55 100644 --- a/third_party/move/tools/move-package/Cargo.toml +++ b/third_party/move/tools/move-package/Cargo.toml @@ -11,7 +11,21 @@ edition = "2021" anyhow = { workspace = true } clap = { workspace = true, features = ["derive"] } colored = { workspace = true } +evm-exec-utils = { path = "../../evm/exec-utils", optional = true } +hex = { workspace = true, optional = true } itertools = { workspace = true } +move-abigen = { workspace = true } +move-binary-format = { workspace = true } +move-bytecode-source-map = { workspace = true } +move-bytecode-utils = { workspace = true } +move-command-line-common = { workspace = true } +move-compiler = { workspace = true } +move-compiler-v2 = { workspace = true } +move-core-types = { workspace = true } +move-docgen = { workspace = true } +move-model = { workspace = true } +move-symbol-pool = { workspace = true } +move-to-yul = { path = "../../evm/move-to-yul", optional = true } named-lock = { workspace = true } once_cell = { workspace = true } petgraph = { workspace = true } @@ -20,27 +34,9 @@ serde = { workspace = true, features = ["derive"] } serde_yaml = { workspace = true } sha2 = { workspace = true } tempfile = { workspace = true } +termcolor = { workspace = true } toml = { workspace = true } walkdir = { workspace = true } - -evm-exec-utils = { path = "../../evm/exec-utils", optional = true } -hex = { workspace = true, optional = true } -move-abigen = { path = "../../move-prover/move-abigen" } - -move-binary-format = { path = "../../move-binary-format" } -move-bytecode-source-map = { path = "../../move-ir-compiler/move-bytecode-source-map" } -move-bytecode-utils = { path = "../move-bytecode-utils" } -move-command-line-common = { path = "../../move-command-line-common" } -move-compiler = { path = "../../move-compiler" } -move-compiler-v2 = { path = "../../move-compiler-v2" } -move-core-types = { path = "../../move-core/types" } -move-docgen = { path = "../../move-prover/move-docgen" } -move-model = { path = "../../move-model" } -move-symbol-pool = { path = "../../move-symbol-pool" } - -move-to-yul = { path = "../../evm/move-to-yul", optional = true } -termcolor = { workspace = true } - whoami = { workspace = true } [dev-dependencies] diff --git a/third_party/move/tools/move-resource-viewer/Cargo.toml b/third_party/move/tools/move-resource-viewer/Cargo.toml index 962de569ff390..e57a8a80444d6 100644 --- a/third_party/move/tools/move-resource-viewer/Cargo.toml +++ b/third_party/move/tools/move-resource-viewer/Cargo.toml @@ -10,9 +10,9 @@ publish = false edition = "2021" [dependencies] -move-binary-format = { path = "../../move-binary-format" } -move-bytecode-utils = { path = "../move-bytecode-utils" } -move-core-types = { path = "../../move-core/types" } +move-binary-format = { workspace = true } +move-bytecode-utils = { workspace = true } +move-core-types = { workspace = true } serde = { workspace = true, features = ["derive", "rc"] } anyhow = { workspace = true } diff --git a/third_party/move/tools/move-unit-test/Cargo.toml b/third_party/move/tools/move-unit-test/Cargo.toml index c0e29367cb1a0..da90b2bc4684d 100644 --- a/third_party/move/tools/move-unit-test/Cargo.toml +++ b/third_party/move/tools/move-unit-test/Cargo.toml @@ -15,34 +15,30 @@ better_any = { workspace = true } clap = { workspace = true, features = ["derive"] } codespan-reporting = { workspace = true } colored = { workspace = true } +evm = { workspace = true, optional = true } evm-exec-utils = { path = "../../evm/exec-utils", optional = true } itertools = { workspace = true } -move-binary-format = { path = "../../move-binary-format" } -move-bytecode-utils = { path = "../move-bytecode-utils" } -once_cell = { workspace = true } -rayon = { workspace = true } -regex = { workspace = true } - -move-command-line-common = { path = "../../move-command-line-common" } -move-compiler = { path = "../../move-compiler" } -move-compiler-v2 = { path = "../../move-compiler-v2" } -move-core-types = { path = "../../move-core/types" } -move-ir-types = { path = "../../move-ir/types" } -move-model = { path = "../../move-model" } -move-package = { path = "../move-package" } -move-resource-viewer = { path = "../move-resource-viewer" } +move-binary-format = { workspace = true } +move-bytecode-utils = { workspace = true } +move-command-line-common = { workspace = true } +move-compiler = { workspace = true } +move-compiler-v2 = { workspace = true } +move-core-types = { workspace = true } +move-ir-types = { workspace = true } +move-model = { workspace = true } +move-package = { workspace = true } +move-resource-viewer = { workspace = true } move-stdlib = { path = "../../move-stdlib", features = ["testing"] } -move-symbol-pool = { path = "../../move-symbol-pool" } +move-symbol-pool = { workspace = true } move-table-extension = { path = "../../extensions/move-table-extension" } -move-vm-runtime = { path = "../../move-vm/runtime", features = ["testing"] } -move-vm-test-utils = { path = "../../move-vm/test-utils" } -move-vm-types = { path = "../../move-vm/types" } - -# EVM-specific dependencies move-to-yul = { path = "../../evm/move-to-yul", optional = true } - -evm = { workspace = true, optional = true } +move-vm-runtime = { workspace = true, features = ["testing"] } +move-vm-test-utils = { workspace = true } +move-vm-types = { workspace = true } +once_cell = { workspace = true } primitive-types = { workspace = true, optional = true } +rayon = { workspace = true } +regex = { workspace = true } [dev-dependencies] datatest-stable = { workspace = true } From 5902ff090d9ba38a1da57ae9bc32a0b2cff01ad2 Mon Sep 17 00:00:00 2001 From: igor-aptos <110557261+igor-aptos@users.noreply.github.com> Date: Thu, 5 Dec 2024 18:01:01 -0800 Subject: [PATCH 22/78] [move-stdlib] Use vector::move_range inside vector, and evaluate performance / calibrate gas (#14862) ## Description Use vector::move_range inside of vector, to optimize `insert`, `remove`, `append`, `trim`. Extend aptos-move/e2e-benchmark/src/main.rs to track gas and gas/s, to allow for quick calibration. Adding workloads to txn-emitter to be able to use it throughput. Additionally add a missing `replace` method, which replaces value at particular index. Running on extended set of params: https://gist.github.com/igor-aptos/e8d4e21edcbc75dddcb9382d4e077665 Summary of the performance tests: - performance doesn't depend on the size of the values (unless they are primitive), as vector modifies only pointers to them. - operation depends very little on how many elements we need to move - moving 1000 elements (i.e. to insert into a vector 1000 elements from the end) is only (!!) 2x slower than moving 1 element, end-to-end. For gas calibration, on the variety of workloads, current implementation has decent variance. After tuning params to match the averages, variance seems much smaller. --- .../e2e-benchmark/data/calibration_values.tsv | 9 + aptos-move/e2e-benchmark/src/main.rs | 60 ++++++ .../framework/move-stdlib/doc/features.md | 57 +++++ .../framework/move-stdlib/doc/vector.md | 131 ++++++++++-- .../framework/move-stdlib/doc/vector_ext.md | 201 ++++++++++++++++++ .../move-stdlib/sources/configs/features.move | 8 + .../framework/move-stdlib/sources/mem.move | 1 + .../framework/move-stdlib/sources/vector.move | 105 +++++++-- .../move-stdlib/tests/vector_tests.move | 129 ++++++++++- crates/transaction-generator-lib/src/args.rs | 18 ++ .../src/publishing/module_simple.rs | 73 +++++++ .../src/publishing/raw_module_data.rs | 62 +++++- .../sources/vector_example.move | 47 ++++ testsuite/single_node_performance.py | 3 + testsuite/single_node_performance_values.tsv | 2 + 15 files changed, 870 insertions(+), 36 deletions(-) create mode 100644 aptos-move/framework/move-stdlib/doc/vector_ext.md create mode 100644 testsuite/module-publish/src/packages/framework_usecases/sources/vector_example.move diff --git a/aptos-move/e2e-benchmark/data/calibration_values.tsv b/aptos-move/e2e-benchmark/data/calibration_values.tsv index 0c373cd15b35f..f8f8281e3b772 100644 --- a/aptos-move/e2e-benchmark/data/calibration_values.tsv +++ b/aptos-move/e2e-benchmark/data/calibration_values.tsv @@ -24,3 +24,12 @@ FungibleAssetMint 60 0.930 1.098 235.8 IncGlobalMilestoneAggV2 { milestone_every: 1 } 60 0.914 1.051 33.5 IncGlobalMilestoneAggV2 { milestone_every: 2 } 60 0.914 1.105 19.0 EmitEvents { count: 1000 } 60 0.937 1.158 8818.7 +VectorTrimAppend { vec_len: 3000, element_len: 1, index: 0, repeats: 0 } 6 0.925 1.001 6058.1 +VectorTrimAppend { vec_len: 3000, element_len: 1, index: 100, repeats: 1000 } 6 0.925 1.001 34000.0 +VectorTrimAppend { vec_len: 3000, element_len: 1, index: 2990, repeats: 1000 } 6 0.925 1.001 17626.5 +VectorRemoveInsert { vec_len: 3000, element_len: 1, index: 100, repeats: 1000 } 6 0.925 1.001 30870.3 +VectorRemoveInsert { vec_len: 3000, element_len: 1, index: 2998, repeats: 1000 } 6 0.925 1.001 20343.2 +VectorRangeMove { vec_len: 3000, element_len: 1, index: 1000, move_len: 500, repeats: 1000 } 6 0.925 1.001 65311 +VectorTrimAppend { vec_len: 100, element_len: 100, index: 0, repeats: 0 } 6 0.925 1.001 277.0 +VectorTrimAppend { vec_len: 100, element_len: 100, index: 10, repeats: 1000 } 6 0.925 1.001 12146.6 +VectorRangeMove { vec_len: 100, element_len: 100, index: 50, move_len: 10, repeats: 1000 } 6 0.925 1.001 7098 \ No newline at end of file diff --git a/aptos-move/e2e-benchmark/src/main.rs b/aptos-move/e2e-benchmark/src/main.rs index fd6365284d56d..fd343e1ff15b7 100644 --- a/aptos-move/e2e-benchmark/src/main.rs +++ b/aptos-move/e2e-benchmark/src/main.rs @@ -176,6 +176,66 @@ fn main() { EntryPoints::IncGlobalMilestoneAggV2 { milestone_every: 1 }, EntryPoints::IncGlobalMilestoneAggV2 { milestone_every: 2 }, EntryPoints::EmitEvents { count: 1000 }, + // long vectors with small elements + EntryPoints::VectorTrimAppend { + // baseline, only vector creation + vec_len: 3000, + element_len: 1, + index: 0, + repeats: 0, + }, + EntryPoints::VectorTrimAppend { + vec_len: 3000, + element_len: 1, + index: 100, + repeats: 1000, + }, + EntryPoints::VectorTrimAppend { + vec_len: 3000, + element_len: 1, + index: 2990, + repeats: 1000, + }, + EntryPoints::VectorRemoveInsert { + vec_len: 3000, + element_len: 1, + index: 100, + repeats: 1000, + }, + EntryPoints::VectorRemoveInsert { + vec_len: 3000, + element_len: 1, + index: 2998, + repeats: 1000, + }, + // EntryPoints::VectorRangeMove { + // vec_len: 3000, + // element_len: 1, + // index: 1000, + // move_len: 500, + // repeats: 1000, + // }, + // vectors with large elements + EntryPoints::VectorTrimAppend { + // baseline, only vector creation + vec_len: 100, + element_len: 100, + index: 0, + repeats: 0, + }, + EntryPoints::VectorTrimAppend { + vec_len: 100, + element_len: 100, + index: 10, + repeats: 1000, + }, + // EntryPoints::VectorRangeMove { + // vec_len: 100, + // element_len: 100, + // index: 50, + // move_len: 10, + // repeats: 1000, + // }, ]; let mut failures = Vec::new(); diff --git a/aptos-move/framework/move-stdlib/doc/features.md b/aptos-move/framework/move-stdlib/doc/features.md index 3b9ad226d2e09..ba635d008abad 100644 --- a/aptos-move/framework/move-stdlib/doc/features.md +++ b/aptos-move/framework/move-stdlib/doc/features.md @@ -133,6 +133,8 @@ return true. - [Function `transaction_simulation_enhancement_enabled`](#0x1_features_transaction_simulation_enhancement_enabled) - [Function `get_collection_owner_feature`](#0x1_features_get_collection_owner_feature) - [Function `is_collection_owner_enabled`](#0x1_features_is_collection_owner_enabled) +- [Function `get_native_memory_operations_feature`](#0x1_features_get_native_memory_operations_feature) +- [Function `is_native_memory_operations_enabled`](#0x1_features_is_native_memory_operations_enabled) - [Function `change_feature_flags`](#0x1_features_change_feature_flags) - [Function `change_feature_flags_internal`](#0x1_features_change_feature_flags_internal) - [Function `change_feature_flags_for_next_epoch`](#0x1_features_change_feature_flags_for_next_epoch) @@ -671,6 +673,15 @@ Lifetime: transient + + + + +
const NATIVE_MEMORY_OPERATIONS: u64 = 80;
+
+ + + Lifetime: transient @@ -3274,6 +3285,52 @@ Deprecated feature + + + + +## Function `get_native_memory_operations_feature` + + + +
public fun get_native_memory_operations_feature(): u64
+
+ + + +
+Implementation + + +
public fun get_native_memory_operations_feature(): u64 { NATIVE_MEMORY_OPERATIONS }
+
+ + + +
+ + + +## Function `is_native_memory_operations_enabled` + + + +
public fun is_native_memory_operations_enabled(): bool
+
+ + + +
+Implementation + + +
public fun is_native_memory_operations_enabled(): bool acquires Features {
+    is_enabled(NATIVE_MEMORY_OPERATIONS)
+}
+
+ + +
diff --git a/aptos-move/framework/move-stdlib/doc/vector.md b/aptos-move/framework/move-stdlib/doc/vector.md index b56160dbaf27e..9e837c9c1cfae 100644 --- a/aptos-move/framework/move-stdlib/doc/vector.md +++ b/aptos-move/framework/move-stdlib/doc/vector.md @@ -40,6 +40,7 @@ the return on investment didn't seem worth it for these simple functions. - [Function `remove`](#0x1_vector_remove) - [Function `remove_value`](#0x1_vector_remove_value) - [Function `swap_remove`](#0x1_vector_swap_remove) +- [Function `replace`](#0x1_vector_replace) - [Function `for_each`](#0x1_vector_for_each) - [Function `for_each_reverse`](#0x1_vector_for_each_reverse) - [Function `for_each_ref`](#0x1_vector_for_each_ref) @@ -146,6 +147,18 @@ The length of the vectors are not equal. + + +Whether to utilize native vector::move_range +Vector module cannot call features module, due to cyclic dependency, +so this is a constant. + + +
const USE_MOVE_RANGE: bool = true;
+
+ + + ## Function `empty` @@ -482,8 +495,15 @@ Pushes all of the elements of the other vector into the self<
public fun append<Element>(self: &mut vector<Element>, other: vector<Element>) {
-    reverse(&mut other);
-    reverse_append(self, other);
+    if (USE_MOVE_RANGE) {
+        let self_length = length(self);
+        let other_length = length(&other);
+        move_range(&mut other, 0, other_length, self, self_length);
+        destroy_empty(other);
+    } else {
+        reverse(&mut other);
+        reverse_append(self, other);
+    }
 }
 
@@ -525,7 +545,11 @@ Pushes all of the elements of the other vector into the self< ## Function `trim` -Trim a vector to a smaller size, returning the evicted elements in order +Splits (trims) the collection into two at the given index. +Returns a newly allocated vector containing the elements in the range [new_len, len). +After the call, the original vector will be left containing the elements [0, new_len) +with its previous capacity unchanged. +In many languages this is also called split_off.
public fun trim<Element>(self: &mut vector<Element>, new_len: u64): vector<Element>
@@ -538,9 +562,21 @@ Trim a vector to a smaller size, returning the evicted elements in order
 
 
 
public fun trim<Element>(self: &mut vector<Element>, new_len: u64): vector<Element> {
-    let res = trim_reverse(self, new_len);
-    reverse(&mut res);
-    res
+    let len = length(self);
+    assert!(new_len <= len, EINDEX_OUT_OF_BOUNDS);
+
+    let other = empty();
+    if (USE_MOVE_RANGE) {
+        move_range(self, new_len, len - new_len, &mut other, 0);
+    } else {
+        while (len > new_len) {
+            push_back(&mut other, pop_back(self));
+            len = len - 1;
+        };
+        reverse(&mut other);
+    };
+
+    other
 }
 
@@ -728,10 +764,27 @@ Aborts if out of bounds.
public fun insert<Element>(self: &mut vector<Element>, i: u64, e: Element) {
     let len = length(self);
     assert!(i <= len, EINDEX_OUT_OF_BOUNDS);
-    push_back(self, e);
-    while (i < len) {
-        swap(self, i, len);
-        i = i + 1;
+
+    if (USE_MOVE_RANGE) {
+        if (i + 2 >= len) {
+            // When we are close to the end, it is cheaper to not create
+            // a temporary vector, and swap directly
+            push_back(self, e);
+            while (i < len) {
+                swap(self, i, len);
+                i = i + 1;
+            };
+        } else {
+            let other = singleton(e);
+            move_range(&mut other, 0, 1, self, i);
+            destroy_empty(other);
+        }
+    } else {
+        push_back(self, e);
+        while (i < len) {
+            swap(self, i, len);
+            i = i + 1;
+        };
     };
 }
 
@@ -763,9 +816,25 @@ Aborts if i is out of bounds. // i out of bounds; abort if (i >= len) abort EINDEX_OUT_OF_BOUNDS; - len = len - 1; - while (i < len) swap(self, i, { i = i + 1; i }); - pop_back(self) + if (USE_MOVE_RANGE) { + // When we are close to the end, it is cheaper to not create + // a temporary vector, and swap directly + if (i + 3 >= len) { + len = len - 1; + while (i < len) swap(self, i, { i = i + 1; i }); + pop_back(self) + } else { + let other = empty(); + move_range(self, i, 1, &mut other, 0); + let result = pop_back(&mut other); + destroy_empty(other); + result + } + } else { + len = len - 1; + while (i < len) swap(self, i, { i = i + 1; i }); + pop_back(self) + } }
@@ -838,6 +907,42 @@ Aborts if i is out of bounds. + + + + +## Function `replace` + +Replace the ith element of the vector self with the given value, and return +to the caller the value that was there before. +Aborts if i is out of bounds. + + +
public fun replace<Element>(self: &mut vector<Element>, i: u64, val: Element): Element
+
+ + + +
+Implementation + + +
public fun replace<Element>(self: &mut vector<Element>, i: u64, val: Element): Element {
+    let last_idx = length(self);
+    assert!(i < last_idx, EINDEX_OUT_OF_BOUNDS);
+    // TODO: Enable after tests are fixed.
+    // if (USE_MOVE_RANGE) {
+    //     mem::replace(borrow_mut(self, i), val)
+    // } else {
+    push_back(self, val);
+    swap(self, i, last_idx);
+    pop_back(self)
+    // }
+}
+
+ + +
diff --git a/aptos-move/framework/move-stdlib/doc/vector_ext.md b/aptos-move/framework/move-stdlib/doc/vector_ext.md new file mode 100644 index 0000000000000..1fa207f777813 --- /dev/null +++ b/aptos-move/framework/move-stdlib/doc/vector_ext.md @@ -0,0 +1,201 @@ + + + +# Module `0x1::vector_ext` + + + +- [Constants](#@Constants_0) +- [Function `range_move`](#0x1_vector_ext_range_move) +- [Function `split_off`](#0x1_vector_ext_split_off) +- [Function `append`](#0x1_vector_ext_append) +- [Function `insert`](#0x1_vector_ext_insert) +- [Function `remove`](#0x1_vector_ext_remove) + + +
use 0x1::vector;
+
+ + + + + +## Constants + + + + +The index into the vector is out of bounds + + +
const EINDEX_OUT_OF_BOUNDS: u64 = 131072;
+
+ + + + + +## Function `range_move` + + + +
public fun range_move<T>(from: &mut vector<T>, removal_position: u64, length: u64, to: &mut vector<T>, insert_position: u64)
+
+ + + +
+Implementation + + +
public native fun range_move<T>(from: &mut vector<T>, removal_position: u64, length: u64, to: &mut vector<T>, insert_position: u64);
+
+ + + +
+ + + +## Function `split_off` + +Splits the collection into two at the given index. +Returns a newly allocated vector containing the elements in the range [at, len). +After the call, the original vector will be left containing the elements [0, at) +with its previous capacity unchanged. + + +
public fun split_off<Element>(self: &mut vector<Element>, at: u64): vector<Element>
+
+ + + +
+Implementation + + +
public fun split_off<Element>(self: &mut vector<Element>, at: u64): vector<Element> {
+    let len = vector::length(self);
+    assert!(at <= len, EINDEX_OUT_OF_BOUNDS);
+
+    let other = vector::empty();
+    range_move(self, at, len - at, &mut other, 0);
+
+    // let other = empty();
+    // while (len > at) {
+    //     push_back(&mut other, pop_back(self));
+    //     len = len - 1;
+    // };
+    // reverse(&mut other);
+    other
+}
+
+ + + +
+ + + +## Function `append` + +Pushes all of the elements of the other vector into the self vector. + + +
public fun append<Element>(self: &mut vector<Element>, other: vector<Element>)
+
+ + + +
+Implementation + + +
public fun append<Element>(self: &mut vector<Element>, other: vector<Element>) {
+    let self_length = self.length();
+    let other_length = other.length();
+    range_move(&mut other, 0, other_length, self, self_length);
+    other.destroy_empty();
+    // reverse(&mut other);
+    // reverse_append(self, other);
+}
+
+ + + +
+ + + +## Function `insert` + + + +
public fun insert<Element>(self: &mut vector<Element>, i: u64, e: Element)
+
+ + + +
+Implementation + + +
public fun insert<Element>(self: &mut vector<Element>, i: u64, e: Element) {
+    let len = self.length();
+    assert!(i <= len, EINDEX_OUT_OF_BOUNDS);
+
+    if (i == len) {
+        self.push_back(e);
+    } else {
+        let other = vector::singleton(e);
+        range_move(&mut other, 0, 1, self, i);
+        other.destroy_empty();
+    }
+}
+
+ + + +
+ + + +## Function `remove` + +Remove the ith element of the vector self, shifting all subsequent elements. +This is O(n) and preserves ordering of elements in the vector. +Aborts if i is out of bounds. + + +
public fun remove<Element>(self: &mut vector<Element>, i: u64): Element
+
+ + + +
+Implementation + + +
public fun remove<Element>(self: &mut vector<Element>, i: u64): Element {
+    let len = self.length();
+    // i out of bounds; abort
+    if (i >= len) abort EINDEX_OUT_OF_BOUNDS;
+
+    if (i + 1 == len) {
+        self.pop_back()
+    } else {
+        let other = vector::empty();
+        range_move(self, i, 1, &mut other, 0);
+        let result = other.pop_back();
+        other.destroy_empty();
+        result
+    }
+}
+
+ + + +
+ + +[move-book]: https://aptos.dev/move/book/SUMMARY diff --git a/aptos-move/framework/move-stdlib/sources/configs/features.move b/aptos-move/framework/move-stdlib/sources/configs/features.move index 2bdba4056eaae..2b3a5291c600d 100644 --- a/aptos-move/framework/move-stdlib/sources/configs/features.move +++ b/aptos-move/framework/move-stdlib/sources/configs/features.move @@ -607,6 +607,14 @@ module std::features { is_enabled(COLLECTION_OWNER) } + const NATIVE_MEMORY_OPERATIONS: u64 = 80; + + public fun get_native_memory_operations_feature(): u64 { NATIVE_MEMORY_OPERATIONS } + + public fun is_native_memory_operations_enabled(): bool acquires Features { + is_enabled(NATIVE_MEMORY_OPERATIONS) + } + // ============================================================================================ // Feature Flag Implementation diff --git a/aptos-move/framework/move-stdlib/sources/mem.move b/aptos-move/framework/move-stdlib/sources/mem.move index 424766f4a2124..cf2eae276f9a5 100644 --- a/aptos-move/framework/move-stdlib/sources/mem.move +++ b/aptos-move/framework/move-stdlib/sources/mem.move @@ -2,6 +2,7 @@ module std::mem { // TODO - functions here are `public(friend)` here for one release, // and to be changed to `public` one release later. + // friend std::vector; #[test_only] friend std::mem_tests; diff --git a/aptos-move/framework/move-stdlib/sources/vector.move b/aptos-move/framework/move-stdlib/sources/vector.move index 2d67042ef4fef..b7add1eb2112a 100644 --- a/aptos-move/framework/move-stdlib/sources/vector.move +++ b/aptos-move/framework/move-stdlib/sources/vector.move @@ -9,6 +9,8 @@ /// Move functions here because many have loops, requiring loop invariants to prove, and /// the return on investment didn't seem worth it for these simple functions. module std::vector { + // use std::mem; + /// The index into the vector is out of bounds const EINDEX_OUT_OF_BOUNDS: u64 = 0x20000; @@ -24,6 +26,11 @@ module std::vector { /// The range in `slice` is invalid. const EINVALID_SLICE_RANGE: u64 = 0x20004; + /// Whether to utilize native vector::move_range + /// Vector module cannot call features module, due to cyclic dependency, + /// so this is a constant. + const USE_MOVE_RANGE: bool = true; + #[bytecode_instruction] /// Create an empty vector. native public fun empty(): vector; @@ -121,8 +128,15 @@ module std::vector { /// Pushes all of the elements of the `other` vector into the `self` vector. public fun append(self: &mut vector, other: vector) { - reverse(&mut other); - reverse_append(self, other); + if (USE_MOVE_RANGE) { + let self_length = length(self); + let other_length = length(&other); + move_range(&mut other, 0, other_length, self, self_length); + destroy_empty(other); + } else { + reverse(&mut other); + reverse_append(self, other); + } } spec append { pragma intrinsic = true; @@ -144,11 +158,27 @@ module std::vector { pragma intrinsic = true; } - /// Trim a vector to a smaller size, returning the evicted elements in order + /// Splits (trims) the collection into two at the given index. + /// Returns a newly allocated vector containing the elements in the range [new_len, len). + /// After the call, the original vector will be left containing the elements [0, new_len) + /// with its previous capacity unchanged. + /// In many languages this is also called `split_off`. public fun trim(self: &mut vector, new_len: u64): vector { - let res = trim_reverse(self, new_len); - reverse(&mut res); - res + let len = length(self); + assert!(new_len <= len, EINDEX_OUT_OF_BOUNDS); + + let other = empty(); + if (USE_MOVE_RANGE) { + move_range(self, new_len, len - new_len, &mut other, 0); + } else { + while (len > new_len) { + push_back(&mut other, pop_back(self)); + len = len - 1; + }; + reverse(&mut other); + }; + + other } spec trim { pragma intrinsic = true; @@ -229,10 +259,27 @@ module std::vector { public fun insert(self: &mut vector, i: u64, e: Element) { let len = length(self); assert!(i <= len, EINDEX_OUT_OF_BOUNDS); - push_back(self, e); - while (i < len) { - swap(self, i, len); - i = i + 1; + + if (USE_MOVE_RANGE) { + if (i + 2 >= len) { + // When we are close to the end, it is cheaper to not create + // a temporary vector, and swap directly + push_back(self, e); + while (i < len) { + swap(self, i, len); + i = i + 1; + }; + } else { + let other = singleton(e); + move_range(&mut other, 0, 1, self, i); + destroy_empty(other); + } + } else { + push_back(self, e); + while (i < len) { + swap(self, i, len); + i = i + 1; + }; }; } spec insert { @@ -247,9 +294,25 @@ module std::vector { // i out of bounds; abort if (i >= len) abort EINDEX_OUT_OF_BOUNDS; - len = len - 1; - while (i < len) swap(self, i, { i = i + 1; i }); - pop_back(self) + if (USE_MOVE_RANGE) { + // When we are close to the end, it is cheaper to not create + // a temporary vector, and swap directly + if (i + 3 >= len) { + len = len - 1; + while (i < len) swap(self, i, { i = i + 1; i }); + pop_back(self) + } else { + let other = empty(); + move_range(self, i, 1, &mut other, 0); + let result = pop_back(&mut other); + destroy_empty(other); + result + } + } else { + len = len - 1; + while (i < len) swap(self, i, { i = i + 1; i }); + pop_back(self) + } } spec remove { pragma intrinsic = true; @@ -288,6 +351,22 @@ module std::vector { pragma intrinsic = true; } + /// Replace the `i`th element of the vector `self` with the given value, and return + /// to the caller the value that was there before. + /// Aborts if `i` is out of bounds. + public fun replace(self: &mut vector, i: u64, val: Element): Element { + let last_idx = length(self); + assert!(i < last_idx, EINDEX_OUT_OF_BOUNDS); + // TODO: Enable after tests are fixed. + // if (USE_MOVE_RANGE) { + // mem::replace(borrow_mut(self, i), val) + // } else { + push_back(self, val); + swap(self, i, last_idx); + pop_back(self) + // } + } + /// Apply the function to each element in the vector, consuming it. public inline fun for_each(self: vector, f: |Element|) { reverse(&mut self); // We need to reverse the vector to consume it efficiently diff --git a/aptos-move/framework/move-stdlib/tests/vector_tests.move b/aptos-move/framework/move-stdlib/tests/vector_tests.move index ce558bc3e9cfc..c01674a6dd4ff 100644 --- a/aptos-move/framework/move-stdlib/tests/vector_tests.move +++ b/aptos-move/framework/move-stdlib/tests/vector_tests.move @@ -105,7 +105,18 @@ module std::vector_tests { let v = vector[1, 2]; assert!(&V::trim(&mut v, 0) == &vector[1, 2], 3); }; + { + let v = vector[1, 2, 3, 4, 5, 6]; + let other = V::trim(&mut v, 4); + assert!(v == vector[1, 2, 3, 4], 4); + assert!(other == vector[5, 6], 5); + + let other_empty = V::trim(&mut v, 4); + assert!(v == vector[1, 2, 3, 4], 6); + assert!(other_empty == vector[], 7); + }; } + #[test] #[expected_failure(abort_code = V::EINDEX_OUT_OF_BOUNDS)] fun test_trim_fail() { @@ -113,6 +124,13 @@ module std::vector_tests { V::trim(&mut v, 2); } + #[test] + #[expected_failure(abort_code = V::EINDEX_OUT_OF_BOUNDS)] + fun test_trim_fail_2() { + let v = vector[1, 2, 3]; + V::trim(&mut v, 4); + } + #[test] #[expected_failure(vector_error, minor_status = 1, location = Self)] fun borrow_out_of_range() { @@ -266,6 +284,52 @@ module std::vector_tests { V::remove(&mut v, 1); } + fun remove_more_cases() { + let v :vector = vector[1]; + assert!(V::remove(&mut v, 0) == 1, 1); + assert!(&v == &vector[], 1); + + let v :vector = vector[2, 1]; + assert!(V::remove(&mut v, 0) == 2, 1); + assert!(&v == &vector[1], 1); + + let v :vector = vector[1, 2]; + assert!(V::remove(&mut v, 1) == 2, 1); + assert!(&v == &vector[1], 1); + + let v :vector = vector[3, 1, 2]; + assert!(V::remove(&mut v, 0) == 3, 1); + assert!(&v == &vector[1, 2], 1); + + let v :vector = vector[1, 3, 2]; + assert!(V::remove(&mut v, 1) == 3, 1); + assert!(&v == &vector[1, 2], 1); + + let v :vector = vector[1, 2, 3]; + assert!(V::remove(&mut v, 2) == 3, 1); + assert!(&v == &vector[1, 2], 1); + + let v :vector = vector[4, 1, 2, 3]; + assert!(V::remove(&mut v, 0) == 4, 1); + assert!(&v == &vector[1, 2, 3], 1); + + let v :vector = vector[5, 1, 2, 3, 4]; + assert!(V::remove(&mut v, 0) == 5, 1); + assert!(&v == &vector[1, 2, 3, 4], 1); + + let v :vector = vector[1, 5, 2, 3, 4]; + assert!(V::remove(&mut v, 1) == 5, 1); + assert!(&v == &vector[1, 2, 3, 4], 1); + + let v :vector = vector[1, 2, 5, 3, 4]; + assert!(V::remove(&mut v, 2) == 5, 1); + assert!(&v == &vector[1, 2, 3, 4], 1); + + let v :vector = vector[1, 2, 3, 4, 5]; + assert!(V::remove(&mut v, 4) == 5, 1); + assert!(&v == &vector[1, 2, 3, 4], 1); + } + #[test] fun remove_value_singleton_vector() { let v = V::empty(); @@ -873,11 +937,55 @@ module std::vector_tests { fun test_insert() { let v:vector = vector[1, 2, 3, 4, 5]; - vector::insert(&mut v,2, 6); + V::insert(&mut v,2, 6); assert!(&v == &vector[1, 2, 6, 3, 4, 5], 1); - vector::insert(&mut v,6, 7); + V::insert(&mut v,6, 7); assert!(&v == &vector[1, 2, 6, 3, 4, 5, 7], 1); + + let v :vector = vector[]; + V::insert(&mut v, 0, 1); + assert!(&v == &vector[1], 1); + + let v :vector = vector[1]; + V::insert(&mut v, 0, 2); + assert!(&v == &vector[2, 1], 1); + + let v :vector = vector[1]; + V::insert(&mut v, 1, 2); + assert!(&v == &vector[1, 2], 1); + + let v :vector = vector[1, 2]; + V::insert(&mut v, 0, 3); + assert!(&v == &vector[3, 1, 2], 1); + + let v :vector = vector[1, 2]; + V::insert(&mut v, 1, 3); + assert!(&v == &vector[1, 3, 2], 1); + + let v :vector = vector[1, 2]; + V::insert(&mut v, 2, 3); + assert!(&v == &vector[1, 2, 3], 1); + + let v :vector = vector[1, 2, 3]; + V::insert(&mut v, 0, 4); + assert!(&v == &vector[4, 1, 2, 3], 1); + + let v :vector = vector[1, 2, 3, 4]; + V::insert(&mut v, 0, 5); + assert!(&v == &vector[5, 1, 2, 3, 4], 1); + + let v :vector = vector[1, 2, 3, 4]; + V::insert(&mut v, 1, 5); + assert!(&v == &vector[1, 5, 2, 3, 4], 1); + + let v :vector = vector[1, 2, 3, 4]; + V::insert(&mut v, 2, 5); + assert!(&v == &vector[1, 2, 5, 3, 4], 1); + + let v :vector = vector[1, 2, 3, 4]; + V::insert(&mut v, 4, 5); + assert!(&v == &vector[1, 2, 3, 4, 5], 1); } #[test] @@ -952,7 +1060,7 @@ module std::vector_tests { #[test] fun test_destroy() { let v = vector[MoveOnly {}]; - vector::destroy(v, |m| { let MoveOnly {} = m; }) + V::destroy(v, |m| { let MoveOnly {} = m; }) } #[test] @@ -964,4 +1072,19 @@ module std::vector_tests { assert!(&v == &vector[3, 6], 0); assert!(&w == &vector[1, 4, 5, 2], 0); } + + #[test] + #[expected_failure(abort_code = V::EINDEX_OUT_OF_BOUNDS)] + fun test_replace_empty_abort() { + let v = vector[]; + let MoveOnly {} = V::replace(&mut v, 0, MoveOnly {}); + V::destroy_empty(v); + } + + #[test] + fun test_replace() { + let v = vector[1, 2, 3, 4]; + V::replace(&mut v, 1, 17); + assert!(v == vector[1, 17, 3, 4], 0); + } } diff --git a/crates/transaction-generator-lib/src/args.rs b/crates/transaction-generator-lib/src/args.rs index fb0cc7779d427..da2a5e5a5f385 100644 --- a/crates/transaction-generator-lib/src/args.rs +++ b/crates/transaction-generator-lib/src/args.rs @@ -45,6 +45,8 @@ pub enum TransactionTypeArg { CreateObjects100, CreateObjects100WithPayload10k, CreateObjectsConflict100WithPayload10k, + VectorTrimAppendLen3000Size1, + VectorRemoveInsertLen3000Size1, ResourceGroupsGlobalWriteTag1KB, ResourceGroupsGlobalWriteAndReadTag1KB, ResourceGroupsSenderWriteTag1KB, @@ -222,6 +224,22 @@ impl TransactionTypeArg { object_payload_size: 10 * 1024, }) }, + TransactionTypeArg::VectorTrimAppendLen3000Size1 => { + call_custom_module(EntryPoints::VectorTrimAppend { + vec_len: 3000, + element_len: 1, + index: 100, + repeats: 1000, + }) + }, + TransactionTypeArg::VectorRemoveInsertLen3000Size1 => { + call_custom_module(EntryPoints::VectorRemoveInsert { + vec_len: 3000, + element_len: 1, + index: 100, + repeats: 1000, + }) + }, TransactionTypeArg::ResourceGroupsGlobalWriteTag1KB => { call_custom_module(EntryPoints::ResourceGroupsGlobalWriteTag { string_length: 1024, diff --git a/crates/transaction-generator-lib/src/publishing/module_simple.rs b/crates/transaction-generator-lib/src/publishing/module_simple.rs index f1b338bb23a16..de1ed2776c96a 100644 --- a/crates/transaction-generator-lib/src/publishing/module_simple.rs +++ b/crates/transaction-generator-lib/src/publishing/module_simple.rs @@ -229,6 +229,25 @@ pub enum EntryPoints { num_objects: u64, object_payload_size: u64, }, + VectorTrimAppend { + vec_len: u64, + element_len: u64, + index: u64, + repeats: u64, + }, + VectorRemoveInsert { + vec_len: u64, + element_len: u64, + index: u64, + repeats: u64, + }, + VectorRangeMove { + vec_len: u64, + element_len: u64, + index: u64, + move_len: u64, + repeats: u64, + }, /// Initialize Token V1 NFT collection TokenV1InitializeCollection, /// Mint an NFT token. Should be called only after InitializeCollection is called @@ -306,6 +325,9 @@ impl EntryPoints { | EntryPoints::ModifyGlobalBoundedAggV2 { .. } | EntryPoints::CreateObjects { .. } | EntryPoints::CreateObjectsConflict { .. } + | EntryPoints::VectorTrimAppend { .. } + | EntryPoints::VectorRemoveInsert { .. } + | EntryPoints::VectorRangeMove { .. } | EntryPoints::TokenV1InitializeCollection | EntryPoints::TokenV1MintAndStoreNFTParallel | EntryPoints::TokenV1MintAndStoreNFTSequential @@ -365,6 +387,9 @@ impl EntryPoints { EntryPoints::CreateObjects { .. } | EntryPoints::CreateObjectsConflict { .. } => { "objects" }, + EntryPoints::VectorTrimAppend { .. } + | EntryPoints::VectorRemoveInsert { .. } + | EntryPoints::VectorRangeMove { .. } => "vector_example", EntryPoints::TokenV1InitializeCollection | EntryPoints::TokenV1MintAndStoreNFTParallel | EntryPoints::TokenV1MintAndStoreNFTSequential @@ -556,6 +581,51 @@ impl EntryPoints { bcs::to_bytes(other.expect("Must provide other")).unwrap(), ], ), + EntryPoints::VectorTrimAppend { + vec_len, + element_len, + index, + repeats, + } + | EntryPoints::VectorRemoveInsert { + vec_len, + element_len, + index, + repeats, + } => get_payload( + module_id, + ident_str!( + if let EntryPoints::VectorTrimAppend { .. } = self { + "test_trim_append" + } else { + "test_remove_insert" + } + ) + .to_owned(), + vec![ + bcs::to_bytes(vec_len).unwrap(), + bcs::to_bytes(element_len).unwrap(), + bcs::to_bytes(index).unwrap(), + bcs::to_bytes(repeats).unwrap(), + ], + ), + EntryPoints::VectorRangeMove { + vec_len, + element_len, + index, + move_len, + repeats, + } => get_payload( + module_id, + ident_str!("test_middle_range_move").to_owned(), + vec![ + bcs::to_bytes(vec_len).unwrap(), + bcs::to_bytes(element_len).unwrap(), + bcs::to_bytes(index).unwrap(), + bcs::to_bytes(move_len).unwrap(), + bcs::to_bytes(repeats).unwrap(), + ], + ), EntryPoints::TokenV1InitializeCollection => get_payload_void( module_id, ident_str!("token_v1_initialize_collection").to_owned(), @@ -825,6 +895,9 @@ impl EntryPoints { EntryPoints::CreateObjects { .. } | EntryPoints::CreateObjectsConflict { .. } => { AutomaticArgs::Signer }, + EntryPoints::VectorTrimAppend { .. } + | EntryPoints::VectorRemoveInsert { .. } + | EntryPoints::VectorRangeMove { .. } => AutomaticArgs::None, EntryPoints::TokenV1InitializeCollection | EntryPoints::TokenV1MintAndStoreNFTParallel | EntryPoints::TokenV1MintAndStoreNFTSequential diff --git a/crates/transaction-generator-lib/src/publishing/raw_module_data.rs b/crates/transaction-generator-lib/src/publishing/raw_module_data.rs index 195b894efff28..8ea4ea55f9a03 100644 --- a/crates/transaction-generator-lib/src/publishing/raw_module_data.rs +++ b/crates/transaction-generator-lib/src/publishing/raw_module_data.rs @@ -1000,11 +1000,11 @@ pub static MODULES_SIMPLE: Lazy>> = Lazy::new(|| { vec![ pub static PACKAGE_FRAMEWORK_USECASES_METADATA: Lazy> = Lazy::new(|| { vec![ 17, 70, 114, 97, 109, 101, 119, 111, 114, 107, 85, 115, 101, 99, 97, 115, 101, 115, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 64, 55, 49, 50, 55, 50, 50, 66, 65, - 65, 50, 67, 49, 53, 66, 70, 54, 65, 70, 53, 70, 55, 52, 65, 67, 69, 56, - 51, 68, 53, 66, 66, 54, 66, 67, 56, 56, 49, 69, 66, 67, 68, 66, 66, 57, - 52, 48, 49, 54, 66, 66, 53, 66, 67, 48, 49, 51, 56, 49, 49, 50, 51, 53, - 66, 50, 215, 1, 31, 139, 8, 0, 0, 0, 0, 0, 2, 255, 165, 144, 187, 142, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 64, 67, 51, 69, 57, 51, 69, 69, 54, + 70, 68, 66, 54, 67, 65, 65, 55, 52, 70, 50, 48, 50, 55, 70, 56, 68, 54, + 65, 51, 55, 70, 69, 70, 68, 50, 65, 69, 69, 54, 56, 70, 56, 65, 57, 57, + 70, 54, 55, 70, 65, 48, 57, 52, 65, 48, 68, 50, 67, 56, 57, 70, 54, 56, + 48, 55, 215, 1, 31, 139, 8, 0, 0, 0, 0, 0, 2, 255, 165, 144, 187, 142, 194, 64, 12, 69, 251, 249, 10, 107, 182, 38, 236, 15, 108, 193, 238, 138, 150, 6, 170, 8, 33, 51, 49, 33, 100, 176, 163, 241, 240, 144, 16, 255, 78, 44, 30, 130, 22, 100, 23, 215, 246, 189, 167, 112, 217, 97, 104, 177, 166, 185, 99, 220, 18, 252, @@ -1016,13 +1016,14 @@ pub static PACKAGE_FRAMEWORK_USECASES_METADATA: Lazy> = Lazy::new(|| { 134, 107, 160, 99, 88, 35, 215, 38, 101, 5, 65, 88, 51, 114, 6, 172, 170, 68, 170, 96, 20, 5, 236, 5, 197, 88, 184, 242, 182, 183, 231, 117, 187, 101, 108, 116, 77, 105, 113, 55, 219, 163, 143, 163, 223, 191, 127, 239, 46, 112, 10, 188, 112, 161, - 1, 0, 0, 6, 18, 97, 103, 103, 114, 101, 103, 97, 116, 111, 114, 95, 101, 120, + 1, 0, 0, 7, 18, 97, 103, 103, 114, 101, 103, 97, 116, 111, 114, 95, 101, 120, 97, 109, 112, 108, 101, 0, 0, 0, 12, 99, 111, 105, 110, 95, 101, 120, 97, 109, 112, 108, 101, 0, 0, 0, 22, 102, 117, 110, 103, 105, 98, 108, 101, 95, 97, 115, 115, 101, 116, 95, 101, 120, 97, 109, 112, 108, 101, 0, 0, 0, 7, 111, 98, 106, 101, 99, 116, 115, 0, 0, 0, 23, 114, 101, 115, 111, 117, 114, 99, 101, 95, 103, 114, 111, 117, 112, 115, 95, 101, 120, 97, 109, 112, 108, 101, 0, 0, 0, 8, 116, - 111, 107, 101, 110, 95, 118, 49, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, + 111, 107, 101, 110, 95, 118, 49, 0, 0, 0, 14, 118, 101, 99, 116, 111, 114, 95, + 101, 120, 97, 109, 112, 108, 101, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 14, 65, 112, 116, 111, 115, 70, 114, 97, 109, 101, 119, 111, 114, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1602,6 +1603,52 @@ pub static MODULE_FRAMEWORK_USECASES_TOKEN_V1: Lazy> = Lazy::new(|| { ] }); +#[rustfmt::skip] +pub static MODULE_FRAMEWORK_USECASES_VECTOR_EXAMPLE: Lazy> = Lazy::new(|| { + vec![ + 161, 28, 235, 11, 7, 0, 0, 10, 8, 1, 0, 4, 3, 4, 46, 4, 50, 8, + 5, 58, 81, 7, 139, 1, 97, 8, 236, 1, 64, 16, 172, 2, 31, 12, 203, 2, + 213, 2, 0, 0, 1, 3, 0, 1, 0, 1, 0, 1, 0, 2, 5, 6, 0, 1, + 1, 4, 7, 8, 1, 0, 1, 1, 5, 9, 6, 1, 0, 1, 0, 6, 5, 6, + 0, 1, 1, 7, 7, 11, 1, 0, 1, 1, 8, 12, 6, 1, 0, 1, 2, 3, + 3, 3, 5, 3, 6, 3, 2, 3, 3, 1, 10, 10, 3, 1, 3, 1, 10, 3, + 11, 10, 3, 3, 1, 3, 10, 10, 3, 1, 3, 3, 10, 3, 7, 3, 10, 10, + 3, 4, 3, 3, 3, 3, 0, 2, 7, 10, 9, 0, 3, 1, 9, 0, 3, 7, + 10, 9, 0, 3, 9, 0, 3, 10, 10, 3, 1, 10, 3, 1, 10, 9, 0, 2, + 7, 10, 9, 0, 10, 9, 0, 3, 10, 10, 3, 1, 10, 10, 3, 14, 118, 101, + 99, 116, 111, 114, 95, 101, 120, 97, 109, 112, 108, 101, 12, 103, 101, 110, 101, 114, + 97, 116, 101, 95, 118, 101, 99, 18, 116, 101, 115, 116, 95, 114, 101, 109, 111, 118, + 101, 95, 105, 110, 115, 101, 114, 116, 6, 118, 101, 99, 116, 111, 114, 6, 114, 101, + 109, 111, 118, 101, 6, 105, 110, 115, 101, 114, 116, 16, 116, 101, 115, 116, 95, 116, + 114, 105, 109, 95, 97, 112, 112, 101, 110, 100, 4, 116, 114, 105, 109, 6, 97, 112, + 112, 101, 110, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 205, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 20, 99, 111, 109, + 112, 105, 108, 97, 116, 105, 111, 110, 95, 109, 101, 116, 97, 100, 97, 116, 97, 9, + 0, 3, 50, 46, 48, 3, 50, 46, 49, 0, 0, 0, 0, 4, 65, 64, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 12, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 12, 3, 9, 12, 4, 5, 8, 5, 23, 10, 4, 4, 62, 11, 3, 6, 1, 0, + 0, 0, 0, 0, 0, 0, 22, 12, 3, 10, 3, 10, 1, 35, 3, 19, 5, 23, + 13, 2, 10, 3, 68, 2, 5, 6, 64, 3, 0, 0, 0, 0, 0, 0, 0, 0, + 12, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 12, 5, 9, 12, 7, 11, 0, + 12, 8, 5, 33, 5, 57, 10, 7, 4, 59, 11, 5, 6, 1, 0, 0, 0, 0, + 0, 0, 0, 22, 12, 5, 10, 5, 10, 8, 35, 3, 44, 5, 57, 10, 2, 12, + 10, 13, 10, 6, 0, 0, 0, 0, 0, 0, 0, 0, 67, 2, 12, 11, 10, 5, + 11, 11, 21, 13, 6, 11, 10, 68, 3, 5, 31, 11, 6, 2, 8, 12, 7, 5, + 39, 8, 12, 4, 5, 14, 1, 1, 4, 0, 10, 34, 11, 0, 11, 1, 17, 0, + 12, 4, 6, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 9, 12, 5, 5, 10, + 5, 30, 10, 5, 4, 31, 11, 0, 6, 1, 0, 0, 0, 0, 0, 0, 0, 22, + 12, 0, 10, 0, 10, 3, 35, 3, 21, 5, 30, 13, 4, 10, 2, 56, 0, 12, + 6, 13, 4, 10, 2, 11, 6, 56, 1, 5, 8, 2, 8, 12, 5, 5, 16, 4, + 1, 4, 0, 13, 33, 11, 0, 11, 1, 17, 0, 12, 4, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 12, 0, 9, 12, 5, 5, 10, 5, 29, 10, 5, 4, 30, 11, + 0, 6, 1, 0, 0, 0, 0, 0, 0, 0, 22, 12, 0, 10, 0, 10, 3, 35, + 3, 21, 5, 29, 13, 4, 10, 2, 56, 2, 12, 6, 13, 4, 11, 6, 56, 3, + 5, 8, 2, 8, 12, 5, 5, 16, 0, + ] +}); + #[rustfmt::skip] pub static MODULES_FRAMEWORK_USECASES: Lazy>> = Lazy::new(|| { vec![ MODULE_FRAMEWORK_USECASES_AGGREGATOR_EXAMPLE.to_vec(), @@ -1610,6 +1657,7 @@ pub static MODULES_FRAMEWORK_USECASES: Lazy>> = Lazy::new(|| { vec![ MODULE_FRAMEWORK_USECASES_OBJECTS.to_vec(), MODULE_FRAMEWORK_USECASES_RESOURCE_GROUPS_EXAMPLE.to_vec(), MODULE_FRAMEWORK_USECASES_TOKEN_V1.to_vec(), + MODULE_FRAMEWORK_USECASES_VECTOR_EXAMPLE.to_vec(), ]}); #[rustfmt::skip] pub static PACKAGE_AMBASSADOR_TOKEN_METADATA: Lazy> = Lazy::new(|| { diff --git a/testsuite/module-publish/src/packages/framework_usecases/sources/vector_example.move b/testsuite/module-publish/src/packages/framework_usecases/sources/vector_example.move new file mode 100644 index 0000000000000..6dbff776a0d8f --- /dev/null +++ b/testsuite/module-publish/src/packages/framework_usecases/sources/vector_example.move @@ -0,0 +1,47 @@ + +/// test speed of vector operations +module 0xABCD::vector_example { + use std::vector; + + fun generate_vec(vec_len: u64, element_len: u64): vector> { + let elem = vector::empty(); + for (i in 0..element_len) { + vector::push_back(&mut elem, i); + }; + let vec = vector::empty(); + for (i in 0..vec_len) { + let cur = elem; + cur[0] = i; + vector::push_back(&mut vec, cur); + }; + vec + } + + public entry fun test_trim_append(vec_len: u64, element_len: u64, index: u64, repeats: u64) { + let vec = generate_vec(vec_len, element_len); + + for (i in 0..repeats) { + let part = vector::trim(&mut vec, index); + vector::append(&mut vec, part); + }; + } + + public entry fun test_remove_insert(vec_len: u64, element_len: u64, index: u64, repeats: u64) { + let vec = generate_vec(vec_len, element_len); + + for (i in 0..repeats) { + let part = vector::remove(&mut vec, index); + vector::insert(&mut vec, index, part); + }; + } + + // public entry fun test_middle_range_move(vec_len: u64, element_len: u64, index: u64, move_len: u64, repeats: u64) { + // let vec1 = generate_vec(vec_len, element_len); + // let vec2 = generate_vec(vec_len, element_len); + + // for (i in 0..repeats) { + // vector::move_range(&mut vec1, index, move_len, &mut vec2, index); + // vector::move_range(&mut vec2, index, move_len, &mut vec1, index); + // }; + // } +} diff --git a/testsuite/single_node_performance.py b/testsuite/single_node_performance.py index 69a571cbadbc6..119ba8a250efd 100755 --- a/testsuite/single_node_performance.py +++ b/testsuite/single_node_performance.py @@ -253,6 +253,9 @@ class RunGroupConfig: RunGroupConfig(key=RunGroupKey("no-op-fee-payer", module_working_set_size=DEFAULT_MODULE_WORKING_SET_SIZE), included_in=Flow.CONTINUOUS), RunGroupConfig(key=RunGroupKey("simple-script"), included_in=LAND_BLOCKING_AND_C), + RunGroupConfig(key=RunGroupKey("vector-trim-append-len3000-size1"), included_in=Flow.CONTINUOUS, waived=True), + RunGroupConfig(key=RunGroupKey("vector-remove-insert-len3000-size1"), included_in=Flow.CONTINUOUS, waived=True), + RunGroupConfig(expected_tps=50000, key=RunGroupKey("coin_transfer_connected_components", executor_type="sharded"), key_extra=RunGroupKeyExtra(sharding_traffic_flags="--connected-tx-grps 5000", transaction_type_override=""), included_in=Flow.REPRESENTATIVE, waived=True), RunGroupConfig(expected_tps=50000, key=RunGroupKey("coin_transfer_hotspot", executor_type="sharded"), key_extra=RunGroupKeyExtra(sharding_traffic_flags="--hotspot-probability 0.8", transaction_type_override=""), included_in=Flow.REPRESENTATIVE, waived=True), diff --git a/testsuite/single_node_performance_values.tsv b/testsuite/single_node_performance_values.tsv index 49145e221deac..279fe00d20f45 100644 --- a/testsuite/single_node_performance_values.tsv +++ b/testsuite/single_node_performance_values.tsv @@ -42,6 +42,8 @@ deserialize-u256 1 VM 60 0.869 1.021 37002.8 no-op-fee-payer 1 VM 60 0.952 1.026 2058.3 no-op-fee-payer 100 VM 60 0.828 1.016 32284.2 simple-script 1 VM 60 0.830 1.024 37707.7 +vector-trim-append-len3000-size1 1 VM 60 0.830 1.024 535 +vector-remove-insert-len3000-size1 1 VM 60 0.830 1.024 514 no_commit_apt-fa-transfer 1 VM 60 0.927 1.015 29357.5 no_commit_apt-fa-transfer 1 NativeVM 60 0.922 1.021 44946.3 no_commit_apt-fa-transfer 1 AptosVMSpeculative 60 0.953 1.010 1851.9 From 8a1016ad0af92f05da2df5cc5e8cede84040b9c1 Mon Sep 17 00:00:00 2001 From: Aaron Date: Thu, 5 Dec 2024 21:31:55 -0600 Subject: [PATCH 23/78] [fa migration] refactor with coin withdraw event and bypass sanity check (#15520) --- aptos-move/framework/aptos-framework/doc/coin.md | 14 +++++++++++--- .../framework/aptos-framework/sources/coin.move | 14 +++++++++++--- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/aptos-move/framework/aptos-framework/doc/coin.md b/aptos-move/framework/aptos-framework/doc/coin.md index 98f56f007e8b3..0b5b91cec523c 100644 --- a/aptos-move/framework/aptos-framework/doc/coin.md +++ b/aptos-move/framework/aptos-framework/doc/coin.md @@ -2054,13 +2054,21 @@ or disallow upgradability of total supply. deleted_withdraw_event_handle_creation_number: guid::creation_num(event::guid(&withdraw_events)) } ); - event::destroy_handle(deposit_events); - event::destroy_handle(withdraw_events); if (coin.value == 0) { destroy_zero(coin); } else { - fungible_asset::deposit(store, coin_to_fungible_asset(coin)); + if (std::features::module_event_migration_enabled()) { + event::emit(CoinWithdraw { coin_type: type_name<CoinType>(), account, amount: coin.value }); + } else { + event::emit_event<WithdrawEvent>( + &mut withdraw_events, + WithdrawEvent { amount: coin.value }, + ); + }; + fungible_asset::deposit_internal(object_address(&store), coin_to_fungible_asset(coin)); }; + event::destroy_handle(deposit_events); + event::destroy_handle(withdraw_events); // Note: // It is possible the primary fungible store may already exist before this function call. // In this case, if the account owns a frozen CoinStore and an unfrozen primary fungible store, this diff --git a/aptos-move/framework/aptos-framework/sources/coin.move b/aptos-move/framework/aptos-framework/sources/coin.move index 2ea6aca5762ec..3887fe31c8f76 100644 --- a/aptos-move/framework/aptos-framework/sources/coin.move +++ b/aptos-move/framework/aptos-framework/sources/coin.move @@ -581,13 +581,21 @@ module aptos_framework::coin { deleted_withdraw_event_handle_creation_number: guid::creation_num(event::guid(&withdraw_events)) } ); - event::destroy_handle(deposit_events); - event::destroy_handle(withdraw_events); if (coin.value == 0) { destroy_zero(coin); } else { - fungible_asset::deposit(store, coin_to_fungible_asset(coin)); + if (std::features::module_event_migration_enabled()) { + event::emit(CoinWithdraw { coin_type: type_name(), account, amount: coin.value }); + } else { + event::emit_event( + &mut withdraw_events, + WithdrawEvent { amount: coin.value }, + ); + }; + fungible_asset::deposit_internal(object_address(&store), coin_to_fungible_asset(coin)); }; + event::destroy_handle(deposit_events); + event::destroy_handle(withdraw_events); // Note: // It is possible the primary fungible store may already exist before this function call. // In this case, if the account owns a frozen CoinStore and an unfrozen primary fungible store, this From 3c6e693a27339e73520f41030dce8fc9cd504967 Mon Sep 17 00:00:00 2001 From: Balaji Arun Date: Fri, 6 Dec 2024 10:45:45 -0800 Subject: [PATCH 24/78] [forge] bump graceful_overload mem threshold temporarily (#15511) --- testsuite/forge-cli/src/suites/realistic_environment.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/testsuite/forge-cli/src/suites/realistic_environment.rs b/testsuite/forge-cli/src/suites/realistic_environment.rs index dfa3ba868b885..cfb527e5dec85 100644 --- a/testsuite/forge-cli/src/suites/realistic_environment.rs +++ b/testsuite/forge-cli/src/suites/realistic_environment.rs @@ -262,9 +262,10 @@ pub(crate) fn realistic_env_graceful_overload(duration: Duration) -> ForgeConfig // overload test uses more CPUs than others, so increase the limit // Check that we don't use more than 28 CPU cores for 20% of the time. MetricsThreshold::new(28.0, 20), - // Memory starts around 7GB, and grows around 8GB/hr in this test. + // TODO(ibalajiarun): Investigate the high utilization and adjust accordingly. + // Memory starts around 8GB, and grows around 8GB/hr in this test. // Check that we don't use more than final expected memory for more than 20% of the time. - MetricsThreshold::new_gb(7.5 + 8.0 * (duration.as_secs_f64() / 3600.0), 20), + MetricsThreshold::new_gb(8.5 + 8.0 * (duration.as_secs_f64() / 3600.0), 20), )) .add_latency_threshold(10.0, LatencyType::P50) .add_latency_threshold(30.0, LatencyType::P90) From 809457f269bbca15e08cbd442e0740c625cbe0f9 Mon Sep 17 00:00:00 2001 From: George Mitenkov Date: Fri, 6 Dec 2024 21:17:09 +0000 Subject: [PATCH 25/78] [move] Benchmarking historical transactions (#15329) A tool to benchmark execution of past transactions. The user has to provide first and last versions of the interval that need to be benchmarked. The tool partitions transactions in the specified closed interval into blocks, and runs all blocks end-to-end, measuring the time. During this run, executor is shared (and so are environment and module caches). There is no commit here, only execution time. For each block, we maintain the state (read-set estimated from 1 run before the benchmarks) on top of which it should run. And so, the benchmark just runs in sequence blocks on top of their initial states (outputs are only used for comparison against the on-chain data). The tool allows one to override configs to experiment with new features, or with how the execution would look like without some features. For now, we support: - enabling features - disabling features In the future, we can add more overrides: gas schedule, modules, etc. --- Cargo.lock | 21 + Cargo.toml | 2 + .../aptos-debugger/src/aptos_debugger.rs | 73 ++-- .../src/transaction_bench_state.rs | 69 ++-- aptos-move/aptos-vm/src/aptos_vm.rs | 67 ++-- aptos-move/aptos-vm/src/block_executor/mod.rs | 2 +- aptos-move/replay-benchmark/Cargo.toml | 30 ++ aptos-move/replay-benchmark/README.md | 84 ++++ aptos-move/replay-benchmark/src/block.rs | 154 +++++++ aptos-move/replay-benchmark/src/diff.rs | 376 ++++++++++++++++++ aptos-move/replay-benchmark/src/generator.rs | 105 +++++ aptos-move/replay-benchmark/src/lib.rs | 10 + aptos-move/replay-benchmark/src/main.rs | 187 +++++++++ aptos-move/replay-benchmark/src/overrides.rs | 90 +++++ aptos-move/replay-benchmark/src/runner.rs | 127 ++++++ aptos-move/replay-benchmark/src/state_view.rs | 82 ++++ aptos-move/replay-benchmark/src/workload.rs | 51 +++ crates/aptos-logger/src/metadata.rs | 108 +++-- .../transaction_slice_metadata.rs | 9 + types/src/write_set.rs | 4 + 20 files changed, 1506 insertions(+), 145 deletions(-) create mode 100644 aptos-move/replay-benchmark/Cargo.toml create mode 100644 aptos-move/replay-benchmark/README.md create mode 100644 aptos-move/replay-benchmark/src/block.rs create mode 100644 aptos-move/replay-benchmark/src/diff.rs create mode 100644 aptos-move/replay-benchmark/src/generator.rs create mode 100644 aptos-move/replay-benchmark/src/lib.rs create mode 100644 aptos-move/replay-benchmark/src/main.rs create mode 100644 aptos-move/replay-benchmark/src/overrides.rs create mode 100644 aptos-move/replay-benchmark/src/runner.rs create mode 100644 aptos-move/replay-benchmark/src/state_view.rs create mode 100644 aptos-move/replay-benchmark/src/workload.rs diff --git a/Cargo.lock b/Cargo.lock index ca3e47878f1d8..80a48ae3ef7c5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3566,6 +3566,27 @@ dependencies = [ "tokio-retry", ] +[[package]] +name = "aptos-replay-benchmark" +version = "0.1.0" +dependencies = [ + "anyhow", + "aptos-block-executor", + "aptos-logger", + "aptos-move-debugger", + "aptos-push-metrics", + "aptos-rest-client", + "aptos-types", + "aptos-vm", + "bcs 0.1.4", + "claims", + "clap 4.5.21", + "parking_lot 0.12.1", + "serde", + "tokio", + "url", +] + [[package]] name = "aptos-resource-viewer" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index cc429d5c1435d..7bb1b9b0c15e0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,6 +42,7 @@ members = [ "aptos-move/move-examples", "aptos-move/mvhashmap", "aptos-move/package-builder", + "aptos-move/replay-benchmark", "aptos-move/script-composer", "aptos-move/vm-genesis", "aptos-node", @@ -419,6 +420,7 @@ aptos-push-metrics = { path = "crates/aptos-push-metrics" } aptos-rate-limiter = { path = "crates/aptos-rate-limiter" } aptos-release-builder = { path = "aptos-move/aptos-release-builder" } aptos-reliable-broadcast = { path = "crates/reliable-broadcast" } +aptos-replay-benchmark = { path = "aptos-move/replay-benchmark" } aptos-resource-viewer = { path = "aptos-move/aptos-resource-viewer" } aptos-rest-client = { path = "crates/aptos-rest-client" } aptos-retrier = { path = "crates/aptos-retrier" } diff --git a/aptos-move/aptos-debugger/src/aptos_debugger.rs b/aptos-move/aptos-debugger/src/aptos_debugger.rs index 2dc191812cc1a..a27281eceb672 100644 --- a/aptos-move/aptos-debugger/src/aptos_debugger.rs +++ b/aptos-move/aptos-debugger/src/aptos_debugger.rs @@ -1,12 +1,8 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -use anyhow::{bail, format_err, Result}; -use aptos_block_executor::{ - code_cache_global_manager::AptosModuleCacheManager, - txn_commit_hook::NoOpTransactionCommitHook, - txn_provider::{default::DefaultTxnProvider, TxnProvider}, -}; +use anyhow::{bail, format_err}; +use aptos_block_executor::txn_provider::{default::DefaultTxnProvider, TxnProvider}; use aptos_gas_profiling::{GasProfiler, TransactionGasLog}; use aptos_rest_client::Client; use aptos_types::{ @@ -28,9 +24,7 @@ use aptos_validator_interface::{ AptosValidatorInterface, DBDebuggerInterface, DebuggerStateView, RestDebuggerInterface, }; use aptos_vm::{ - block_executor::{AptosTransactionOutput, AptosVMBlockExecutorWrapper}, - data_cache::AsMoveResolver, - AptosVM, + aptos_vm::AptosVMBlockExecutor, data_cache::AsMoveResolver, AptosVM, VMBlockExecutor, }; use aptos_vm_environment::environment::AptosEnvironment; use aptos_vm_logging::log_schema::AdapterLogSchema; @@ -47,23 +41,31 @@ impl AptosDebugger { Self { debugger } } - pub fn rest_client(rest_client: Client) -> Result { + pub fn rest_client(rest_client: Client) -> anyhow::Result { Ok(Self::new(Arc::new(RestDebuggerInterface::new(rest_client)))) } - pub fn db + Clone>(db_root_path: P) -> Result { + pub fn db + Clone>(db_root_path: P) -> anyhow::Result { Ok(Self::new(Arc::new(DBDebuggerInterface::open( db_root_path, )?))) } + pub async fn get_committed_transactions( + &self, + begin: Version, + limit: u64, + ) -> anyhow::Result<(Vec, Vec)> { + self.debugger.get_committed_transactions(begin, limit).await + } + pub fn execute_transactions_at_version( &self, version: Version, txns: Vec, repeat_execution_times: u64, concurrency_levels: &[usize], - ) -> Result> { + ) -> anyhow::Result> { let sig_verified_txns: Vec = txns.into_iter().map(|x| x.into()).collect::>(); let txn_provider = DefaultTxnProvider::new(sig_verified_txns); @@ -114,7 +116,7 @@ impl AptosDebugger { &self, version: Version, txn: SignedTransaction, - ) -> Result<(VMStatus, VMOutput, TransactionGasLog)> { + ) -> anyhow::Result<(VMStatus, VMOutput, TransactionGasLog)> { let state_view = DebuggerStateView::new(self.debugger.clone(), version); let log_context = AdapterLogSchema::new(state_view.id(), 0); let txn = txn @@ -166,11 +168,8 @@ impl AptosDebugger { use_same_block_boundaries: bool, repeat_execution_times: u64, concurrency_levels: &[usize], - ) -> Result> { - let (txns, txn_infos) = self - .debugger - .get_committed_transactions(begin, limit) - .await?; + ) -> anyhow::Result> { + let (txns, txn_infos) = self.get_committed_transactions(begin, limit).await?; if use_same_block_boundaries { // when going block by block, no need to worry about epoch boundaries @@ -238,7 +237,7 @@ impl AptosDebugger { txns: Vec, repeat_execution_times: u64, concurrency_levels: &[usize], - ) -> Result> { + ) -> anyhow::Result> { let results = self.execute_transactions_at_version( begin, txns, @@ -268,7 +267,7 @@ impl AptosDebugger { repeat_execution_times: u64, concurrency_levels: &[usize], mut txn_infos: Vec, - ) -> Result> { + ) -> anyhow::Result> { let mut ret = vec![]; while limit != 0 { println!( @@ -301,7 +300,7 @@ impl AptosDebugger { txns: Vec, repeat_execution_times: u64, concurrency_levels: &[usize], - ) -> Result> { + ) -> anyhow::Result> { let mut ret = vec![]; let mut cur = vec![]; let mut cur_version = begin; @@ -336,7 +335,7 @@ impl AptosDebugger { &self, account: AccountAddress, seq: u64, - ) -> Result> { + ) -> anyhow::Result> { self.debugger .get_version_by_account_sequence(account, seq) .await @@ -345,7 +344,7 @@ impl AptosDebugger { pub async fn get_committed_transaction_at_version( &self, version: Version, - ) -> Result<(Transaction, TransactionInfo)> { + ) -> anyhow::Result<(Transaction, TransactionInfo)> { let (mut txns, mut info) = self.debugger.get_committed_transactions(version, 1).await?; let txn = txns.pop().expect("there must be exactly 1 txn in the vec"); @@ -434,20 +433,16 @@ fn execute_block_no_limit( state_view: &DebuggerStateView, concurrency_level: usize, ) -> Result, VMStatus> { - AptosVMBlockExecutorWrapper::execute_block::< - _, - NoOpTransactionCommitHook, - DefaultTxnProvider, - >( - txn_provider, - state_view, - &AptosModuleCacheManager::new(), - BlockExecutorConfig { - local: BlockExecutorLocalConfig::default_with_concurrency_level(concurrency_level), - onchain: BlockExecutorConfigFromOnchain::new_no_block_limit(), - }, - TransactionSliceMetadata::unknown(), - None, - ) - .map(BlockOutput::into_transaction_outputs_forced) + let executor = AptosVMBlockExecutor::new(); + executor + .execute_block_with_config( + txn_provider, + state_view, + BlockExecutorConfig { + local: BlockExecutorLocalConfig::default_with_concurrency_level(concurrency_level), + onchain: BlockExecutorConfigFromOnchain::new_no_block_limit(), + }, + TransactionSliceMetadata::unknown(), + ) + .map(BlockOutput::into_transaction_outputs_forced) } diff --git a/aptos-move/aptos-transaction-benchmarks/src/transaction_bench_state.rs b/aptos-move/aptos-transaction-benchmarks/src/transaction_bench_state.rs index f250de5c60758..81db4cbded0c2 100644 --- a/aptos-move/aptos-transaction-benchmarks/src/transaction_bench_state.rs +++ b/aptos-move/aptos-transaction-benchmarks/src/transaction_bench_state.rs @@ -3,11 +3,7 @@ use crate::transactions; use aptos_bitvec::BitVec; -use aptos_block_executor::{ - code_cache_global_manager::AptosModuleCacheManager, - txn_commit_hook::NoOpTransactionCommitHook, - txn_provider::{default::DefaultTxnProvider, TxnProvider}, -}; +use aptos_block_executor::txn_provider::{default::DefaultTxnProvider, TxnProvider}; use aptos_block_partitioner::{ v2::config::PartitionerV2Config, BlockPartitioner, PartitionerConfig, }; @@ -32,15 +28,15 @@ use aptos_types::{ }, ExecutionStatus, Transaction, TransactionOutput, TransactionStatus, }, - vm_status::VMStatus, }; use aptos_vm::{ - block_executor::{AptosTransactionOutput, AptosVMBlockExecutorWrapper}, + aptos_vm::AptosVMBlockExecutor, data_cache::AsMoveResolver, sharded_block_executor::{ local_executor_shard::{LocalExecutorClient, LocalExecutorService}, ShardedBlockExecutor, }, + VMBlockExecutor, }; use proptest::{collection::vec, prelude::Strategy, strategy::ValueTree, test_runner::TestRunner}; use std::{net::SocketAddr, sync::Arc, time::Instant}; @@ -217,20 +213,18 @@ where ) -> (Vec, usize) { let block_size = txn_provider.num_txns(); let timer = Instant::now(); - let output = AptosVMBlockExecutorWrapper::execute_block::< - _, - NoOpTransactionCommitHook, - DefaultTxnProvider, - >( - txn_provider, - self.state_view.as_ref(), - &AptosModuleCacheManager::new(), - BlockExecutorConfig::new_maybe_block_limit(1, maybe_block_gas_limit), - TransactionSliceMetadata::unknown(), - None, - ) - .expect("VM should not fail to start") - .into_transaction_outputs_forced(); + + let executor = AptosVMBlockExecutor::new(); + let output = executor + .execute_block_with_config( + txn_provider, + self.state_view.as_ref(), + BlockExecutorConfig::new_maybe_block_limit(1, maybe_block_gas_limit), + TransactionSliceMetadata::unknown(), + ) + .expect("Sequential block execution should succeed") + .into_transaction_outputs_forced(); + let exec_time = timer.elapsed().as_millis(); (output, block_size * 1000 / exec_time as usize) @@ -263,28 +257,25 @@ where fn execute_benchmark_parallel( &self, txn_provider: &DefaultTxnProvider, - concurrency_level_per_shard: usize, + concurrency_level: usize, maybe_block_gas_limit: Option, ) -> (Vec, usize) { let block_size = txn_provider.num_txns(); let timer = Instant::now(); - let output = AptosVMBlockExecutorWrapper::execute_block::< - _, - NoOpTransactionCommitHook, - DefaultTxnProvider, - >( - txn_provider, - self.state_view.as_ref(), - &AptosModuleCacheManager::new(), - BlockExecutorConfig::new_maybe_block_limit( - concurrency_level_per_shard, - maybe_block_gas_limit, - ), - TransactionSliceMetadata::unknown(), - None, - ) - .expect("VM should not fail to start") - .into_transaction_outputs_forced(); + + let executor = AptosVMBlockExecutor::new(); + let output = executor + .execute_block_with_config( + txn_provider, + self.state_view.as_ref(), + BlockExecutorConfig::new_maybe_block_limit( + concurrency_level, + maybe_block_gas_limit, + ), + TransactionSliceMetadata::unknown(), + ) + .expect("Parallel block execution should succeed") + .into_transaction_outputs_forced(); let exec_time = timer.elapsed().as_millis(); (output, block_size * 1000 / exec_time as usize) diff --git a/aptos-move/aptos-vm/src/aptos_vm.rs b/aptos-move/aptos-vm/src/aptos_vm.rs index 1b469bcd82c9a..9e3cc84baaa4a 100644 --- a/aptos-move/aptos-vm/src/aptos_vm.rs +++ b/aptos-move/aptos-vm/src/aptos_vm.rs @@ -2780,35 +2780,31 @@ pub struct AptosVMBlockExecutor { module_cache_manager: AptosModuleCacheManager, } -impl VMBlockExecutor for AptosVMBlockExecutor { - fn new() -> Self { - Self { - module_cache_manager: AptosModuleCacheManager::new(), - } - } - - fn execute_block( +impl AptosVMBlockExecutor { + /// Executes transactions with the specified [BlockExecutorConfig] and returns output for each + /// one of them. + pub fn execute_block_with_config( &self, txn_provider: &DefaultTxnProvider, state_view: &(impl StateView + Sync), - onchain_config: BlockExecutorConfigFromOnchain, + config: BlockExecutorConfig, transaction_slice_metadata: TransactionSliceMetadata, ) -> Result, VMStatus> { - fail_point!("move_adapter::execute_block", |_| { + fail_point!("aptos_vm_block_executor::execute_block_with_config", |_| { Err(VMStatus::error( StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR, None, )) }); + let log_context = AdapterLogSchema::new(state_view.id(), 0); + let num_txns = txn_provider.num_txns(); info!( log_context, - "Executing block, transaction count: {}", - txn_provider.num_txns() + "Executing block, transaction count: {}", num_txns ); - let count = txn_provider.num_txns(); - let ret = AptosVMBlockExecutorWrapper::execute_block::< + let result = AptosVMBlockExecutorWrapper::execute_block::< _, NoOpTransactionCommitHook, DefaultTxnProvider, @@ -2816,23 +2812,42 @@ impl VMBlockExecutor for AptosVMBlockExecutor { txn_provider, state_view, &self.module_cache_manager, - BlockExecutorConfig { - local: BlockExecutorLocalConfig { - concurrency_level: AptosVM::get_concurrency_level(), - allow_fallback: true, - discard_failed_blocks: AptosVM::get_discard_failed_blocks(), - module_cache_config: BlockExecutorModuleCacheLocalConfig::default(), - }, - onchain: onchain_config, - }, + config, transaction_slice_metadata, None, ); - if ret.is_ok() { + if result.is_ok() { // Record the histogram count for transactions per block. - BLOCK_TRANSACTION_COUNT.observe(count as f64); + BLOCK_TRANSACTION_COUNT.observe(num_txns as f64); } - ret + result + } +} + +impl VMBlockExecutor for AptosVMBlockExecutor { + fn new() -> Self { + Self { + module_cache_manager: AptosModuleCacheManager::new(), + } + } + + fn execute_block( + &self, + txn_provider: &DefaultTxnProvider, + state_view: &(impl StateView + Sync), + onchain_config: BlockExecutorConfigFromOnchain, + transaction_slice_metadata: TransactionSliceMetadata, + ) -> Result, VMStatus> { + let config = BlockExecutorConfig { + local: BlockExecutorLocalConfig { + concurrency_level: AptosVM::get_concurrency_level(), + allow_fallback: true, + discard_failed_blocks: AptosVM::get_discard_failed_blocks(), + module_cache_config: BlockExecutorModuleCacheLocalConfig::default(), + }, + onchain: onchain_config, + }; + self.execute_block_with_config(txn_provider, state_view, config, transaction_slice_metadata) } fn execute_block_sharded>( diff --git a/aptos-move/aptos-vm/src/block_executor/mod.rs b/aptos-move/aptos-vm/src/block_executor/mod.rs index d5c55eeb957c4..168b1bb4a3719 100644 --- a/aptos-move/aptos-vm/src/block_executor/mod.rs +++ b/aptos-move/aptos-vm/src/block_executor/mod.rs @@ -481,7 +481,7 @@ impl< } /// Uses shared thread pool to execute blocks. - pub fn execute_block< + pub(crate) fn execute_block< S: StateView + Sync, L: TransactionCommitHook, TP: TxnProvider + Sync, diff --git a/aptos-move/replay-benchmark/Cargo.toml b/aptos-move/replay-benchmark/Cargo.toml new file mode 100644 index 0000000000000..e531876d494de --- /dev/null +++ b/aptos-move/replay-benchmark/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "aptos-replay-benchmark" +version = "0.1.0" +description = "A tool to replay and locally benchmark on-chain transactions." + +# Workspace inherited keys +authors = { workspace = true } +edition = { workspace = true } +homepage = { workspace = true } +license = { workspace = true } +publish = { workspace = true } +repository = { workspace = true } +rust-version = { workspace = true } + +[dependencies] +anyhow = { workspace = true } +aptos-block-executor = { workspace = true } +aptos-logger = { workspace = true } +aptos-move-debugger = { workspace = true } +aptos-push-metrics = { workspace = true } +aptos-rest-client = { workspace = true } +aptos-types = { workspace = true } +aptos-vm = { workspace = true } +bcs = { workspace = true } +claims = { workspace = true } +clap = { workspace = true } +parking_lot = { workspace = true } +serde = { workspace = true } +tokio = { workspace = true } +url = { workspace = true } diff --git a/aptos-move/replay-benchmark/README.md b/aptos-move/replay-benchmark/README.md new file mode 100644 index 0000000000000..15563eb4212fb --- /dev/null +++ b/aptos-move/replay-benchmark/README.md @@ -0,0 +1,84 @@ +## A tool to replay and benchmark past Aptos transactions + + +### Benchmarking and measurements + +This tool allows to benchmark an ordered sequence of past transactions, specifying the first (`--begin-version B`) and the last (`--end-version E`) versions. +Transactions are split into blocks, to mimic on-chain behaviour, and blocks are executed one-by-one using an executor. +During the execution, the time is measured. +Each block runs based on the pre-computed state, so there is no "commit" of block execution outputs. +Similarly, signature verification is also left out. +Hence, the benchmark reports the runtime only. + +The tool supports two ways to measure the time: + + 1. Measuring total execution time for all transactions (default). + 2. Measuring execution time for each of the executed blocks, and reporting all. + To enable this, use `--measure-block-times` flag. + +In both cases, the measurement is repeated at least 3 times (this can be configured by specifying the number of repeats, `N`, using `--num-repeats N`), and the minimum, maximum, average and median times are reported (in microseconds). + +When benchmarking, a list of concurrency levels (`--concurrency-levels L1 L2 ...`) has to be provided. +Concurrency level specifies the number of threads Block-STM will use to execute a block of transactions. +Typically, you want to have the concurrency level to match the number of cores. +If multiple concurrency levels are provided, the benchmark is run for all, reporting the measurements. +This way it is possible to see how concurrency affects the runtime. + +Finally, in order to differentiate between cold and warm states, there is an option to skip measurement for the first few blocks. +By specifying `--num-block-to-skip N`, the tool will not ignore measurements when reporting for the first `N` blocks. + +### State overriding + +The benchmark runs every block on top of the corresponding on-chain state. +However, it is possible to override the state. +Currently, the only supported overrides are feature flags: + + 1. Feature flags can be forcefully enabled (`--enable-features F1 F2 ...`). + 2. Feature flags can be forcefully disabled (`--disable-features F1 F2 ...`). + +Feature flags should be spelled in capital letters, e.g., `ENABLE_LOADER_V2`. +For the full list of available features, see [here](../../types/src/on_chain_config/aptos_features.rs). + +Overriding the feature flags allows to see how having some feature on or off affects the runtime. +For example, if there is a new feature that improves the performance of MoveVM, with overrides it is possible to evaluate it on past transactions. + +### Comparison to on-chain behavior + +Overriding the state can change the execution behavior. +Hence, if any overrides are provided, the tool compares the on-chain outputs to new outputs obtained when execution on top of a modified state. +The diff of comparison is logged, and the users of the tool can evaluate if the differences are significant or not. +If the differences are not significant (e.g., only the gas usage has changed), the execution behaviour still stays the same. +Hence, the time measurements are still representative of the on-chain behavior. + +### HTTP request rate limit quotas + +Transactions are fetched from the fullnode via REST API. +Users should provide fullnode's REST API query endpoint using `--rest-endpoint E` flag. +For example, to fetch mainnet transactions, specify `--rest-endpoint https://mainnet.aptoslabs.com/v1`. + +If too many transactions are fetched and executed (preparing the benchmark pre-executes the specified transactions and reads the state from the remote), it is possible to run into HTTP request rate limits. +To learn more about the API quotas, see https://developers.aptoslabs.com/docs/api-access/quotas. + +It is possible to increase your quota by creating an API key in Aptos Build. +For that, follow instructions here: https://developers.aptoslabs.com/docs/api-access/api-keys. +Then, when using the tool the key can be specified using `--api-key K` flag. + +### Examples + +An end-to-end example for using the tool: + +```commandline +aptos-replay-benchmark --begin-version 1944524532 \ + --end-version 1944524714 \ + --rest-endpoint https://mainnet.aptoslabs.com/v1 \ + --concurrency-levels 2 4 \ + --num-repeats 10 \ + --num-blocks-to-skip 1 \ + --enable-features ENABLE_LOADER_V2 +``` + +Here, mainnet transactions from versions 1944524532 to 1944524714 are benchmarked. +There are two measurements: when Block-STM uses 2 threads, or 4 threads per block. +Each measurement is repeated 10 times, and the overall execution time is reported for each level. +Note that the reported time excludes the first block. +Additionally, `ENABLE_LOADER_V2` feature flag is forcefully enabled to see how it impacts the runtime for past transactions. diff --git a/aptos-move/replay-benchmark/src/block.rs b/aptos-move/replay-benchmark/src/block.rs new file mode 100644 index 0000000000000..f545a2b71116b --- /dev/null +++ b/aptos-move/replay-benchmark/src/block.rs @@ -0,0 +1,154 @@ +// Copyright (c) Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::{ + diff::TransactionDiff, + state_view::{ReadSet, ReadSetCapturingStateView}, + workload::Workload, +}; +use aptos_logger::error; +use aptos_types::{ + block_executor::config::{ + BlockExecutorConfig, BlockExecutorConfigFromOnchain, BlockExecutorLocalConfig, + BlockExecutorModuleCacheLocalConfig, + }, + state_store::{state_key::StateKey, state_value::StateValue, StateView}, + transaction::{TransactionOutput, Version}, +}; +use aptos_vm::{aptos_vm::AptosVMBlockExecutor, VMBlockExecutor}; +use std::collections::HashMap; + +/// Block execution config used for replay benchmarking. +fn block_execution_config(concurrency_level: usize) -> BlockExecutorConfig { + BlockExecutorConfig { + local: BlockExecutorLocalConfig { + concurrency_level, + allow_fallback: true, + discard_failed_blocks: false, + module_cache_config: BlockExecutorModuleCacheLocalConfig::default(), + }, + // For replay, there is no block limit. + onchain: BlockExecutorConfigFromOnchain::new_no_block_limit(), + } +} + +/// Represents a single benchmarking unit: a block of transactions with the input pre-block state. +/// Also stores the comparison of outputs based on the input state to on-chain outputs (recall that +/// input state may contain an override and differ from on-chain pre-block state). +pub struct Block { + /// Stores all data needed to execute this block. + inputs: ReadSet, + /// Stores transactions to execute and benchmark. + workload: Workload, + /// Stores diff results for each transaction output. The number of diffs is always equal to the + /// number of transactions, but they may or may not be empty. + diffs: Vec, +} + +impl Block { + /// Creates a new block for benchmarking by executing transactions on top of an overridden + /// state. If there are any state overrides, transactions are first executed based on the + /// on-chain state for later comparison (otherwise, if there are no overrides diffs are empty). + /// + /// Note: transaction execution is sequential, so that multiple blocks can be constructed in + /// parallel. + pub(crate) fn new( + workload: Workload, + state_view: &(impl StateView + Sync), + state_override: HashMap, + ) -> Self { + // Execute transactions without overrides. + let state_view_without_override = + ReadSetCapturingStateView::new(state_view, HashMap::new()); + let onchain_outputs = execute_workload( + &AptosVMBlockExecutor::new(), + &workload, + &state_view_without_override, + 1, + ); + let _onchain_inputs = state_view_without_override.into_read_set(); + + // Check on-chain outputs do not modify the state we override. If so, benchmarking results + // may not be correct. + let begin = workload + .transaction_slice_metadata() + .begin_version() + .expect("Transaction metadata must be a chunk"); + for (idx, on_chain_output) in onchain_outputs.iter().enumerate() { + for (state_key, _) in on_chain_output.write_set() { + if state_override.contains_key(state_key) { + error!( + "Transaction {} writes to overridden state value for {:?}", + begin + idx as Version, + state_key + ); + } + } + } + + // Execute transactions with an override. + let state_view_with_override = ReadSetCapturingStateView::new(state_view, state_override); + let outputs = execute_workload( + &AptosVMBlockExecutor::new(), + &workload, + &state_view_with_override, + 1, + ); + let inputs = state_view_with_override.into_read_set(); + + // Compute the differences between outputs. + // TODO: We can also compute the differences between the read sets. Maybe we should add it? + let diffs = onchain_outputs + .into_iter() + .zip(outputs) + .map(|(onchain_output, output)| TransactionDiff::from_outputs(onchain_output, output)) + .collect(); + + Self { + inputs, + workload, + diffs, + } + } + + /// Prints the difference in transaction outputs when running with overrides. + pub fn print_diffs(&self) { + let begin = self + .workload + .transaction_slice_metadata() + .begin_version() + .expect("Transaction metadata is a chunk"); + for (idx, diff) in self.diffs.iter().enumerate() { + if !diff.is_empty() { + println!("Transaction {} diff:\n {}\n", begin + idx as Version, diff); + } + } + } + + /// Executes the workload for benchmarking. + pub(crate) fn run(&self, executor: &AptosVMBlockExecutor, concurrency_level: usize) { + execute_workload(executor, &self.workload, &self.inputs, concurrency_level); + } +} + +fn execute_workload( + executor: &AptosVMBlockExecutor, + workload: &Workload, + state_view: &(impl StateView + Sync), + concurrency_level: usize, +) -> Vec { + executor + .execute_block_with_config( + workload.txn_provider(), + state_view, + block_execution_config(concurrency_level), + workload.transaction_slice_metadata(), + ) + .unwrap_or_else(|err| { + panic!( + "Block execution should not fail, but returned an error: {:?}", + err + ) + }) + .into_transaction_outputs_forced() +} diff --git a/aptos-move/replay-benchmark/src/diff.rs b/aptos-move/replay-benchmark/src/diff.rs new file mode 100644 index 0000000000000..ba10c8c1c9701 --- /dev/null +++ b/aptos-move/replay-benchmark/src/diff.rs @@ -0,0 +1,376 @@ +// Copyright (c) Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use aptos_types::{ + contract_event::ContractEvent, + state_store::state_key::StateKey, + transaction::{ExecutionStatus, TransactionOutput}, + write_set::{WriteOp, WriteSet}, +}; +use claims::assert_ok; +use std::collections::BTreeMap; + +/// Different parts of [TransactionOutput] that can be different: +/// 1. gas used, +/// 2. status (must be kept since transactions are replayed), +/// 3. events, +/// 4. writes. +/// Note that fine-grained comparison allows for some differences to be okay, e.g., using more gas +/// implies that the fee statement event, the account balance of the fee payer, and the total token +/// supply are different. +#[derive(Eq, PartialEq)] +enum Diff { + GasUsed { + left: u64, + right: u64, + }, + ExecutionStatus { + left: ExecutionStatus, + right: ExecutionStatus, + }, + Event { + left: Option, + right: Option, + }, + WriteSet { + state_key: StateKey, + left: Option, + right: Option, + }, +} + +/// Holds all differences for a pair of transaction outputs. +pub(crate) struct TransactionDiff { + diffs: Vec, +} + +impl TransactionDiff { + /// Given a pair of transaction outputs, computes its [TransactionDiff] that includes the gas + /// used, execution status, events and write sets. + // TODO: Make comparison configurable, so we can skip gas differences, etc. + pub(crate) fn from_outputs(left: TransactionOutput, right: TransactionOutput) -> Self { + let (left_write_set, left_events, left_gas_used, left_transaction_status, _) = + left.unpack(); + let (right_write_set, right_events, right_gas_used, right_transaction_status, _) = + right.unpack(); + + let mut diffs = vec![]; + + // All statuses must be kept, since we are replaying transactions. + let left_execution_status = assert_ok!(left_transaction_status.as_kept_status()); + let right_execution_status = assert_ok!(right_transaction_status.as_kept_status()); + if left_execution_status != right_execution_status { + diffs.push(Diff::ExecutionStatus { + left: left_execution_status, + right: right_execution_status, + }); + } + + if left_gas_used != right_gas_used { + diffs.push(Diff::GasUsed { + left: left_gas_used, + right: right_gas_used, + }); + } + + Self::diff_events(&mut diffs, left_events, right_events); + Self::diff_write_sets(&mut diffs, left_write_set, right_write_set); + + Self { diffs } + } + + /// Returns true if the diff is empty, and transaction outputs match. + pub(crate) fn is_empty(&self) -> bool { + self.diffs.is_empty() + } + + /// Computes the differences between a pair of event vectors, and adds them to the diff. + fn diff_events(diffs: &mut Vec, left: Vec, right: Vec) { + let event_vec_to_map = |events: Vec| { + events + .into_iter() + .map(|event| (event.type_tag().clone(), event)) + .collect::>() + }; + + let left = event_vec_to_map(left); + let mut right = event_vec_to_map(right); + + for (left_ty_tag, left_event) in left { + let maybe_right_event = right.remove(&left_ty_tag); + if maybe_right_event + .as_ref() + .is_some_and(|right_event| left_event.event_data() == right_event.event_data()) + { + continue; + } + + diffs.push(Diff::Event { + left: Some(left_event), + right: maybe_right_event, + }); + } + + for right_event in right.into_values() { + diffs.push(Diff::Event { + left: None, + right: Some(right_event), + }); + } + } + + /// Computes the differences between a pair of write sets, and adds them to the diff. + fn diff_write_sets(diffs: &mut Vec, left: WriteSet, right: WriteSet) { + let left = left.into_mut().into_inner(); + let mut right = right.into_mut().into_inner(); + + for (left_state_key, left_write_op) in left { + let maybe_right_write_op = right.remove(&left_state_key); + if maybe_right_write_op + .as_ref() + .is_some_and(|right_write_op| right_write_op == &left_write_op) + { + continue; + } + + diffs.push(Diff::WriteSet { + state_key: left_state_key, + left: Some(left_write_op), + right: maybe_right_write_op, + }); + } + + for (right_state_key, right_write_op) in right { + diffs.push(Diff::WriteSet { + state_key: right_state_key, + left: None, + right: Some(right_write_op), + }); + } + } +} + +impl std::fmt::Display for TransactionDiff { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + writeln!(f, " >>>>> ")?; + for diff in &self.diffs { + match diff { + Diff::GasUsed { left, right } => { + writeln!(f, "[gas used] before: {}, after: {}", left, right)?; + }, + Diff::ExecutionStatus { left, right } => { + writeln!( + f, + "[execution status] before: {:?}, after: {:?}", + left, right + )?; + }, + Diff::Event { left, right } => { + let left = left.as_ref(); + let right = right.as_ref(); + + if left.is_none() { + writeln!( + f, + "[event] {} was not emitted before", + right.unwrap().type_tag().to_canonical_string() + )?; + } else if right.is_none() { + writeln!( + f, + "[event] {} is not emitted anymore", + left.unwrap().type_tag().to_canonical_string() + )?; + } else { + writeln!( + f, + "[event] {} has changed its data", + left.unwrap().type_tag().to_canonical_string() + )?; + } + }, + Diff::WriteSet { + state_key, + left, + right, + } => { + let left = left.as_ref(); + let right = right.as_ref(); + + if left.is_none() { + writeln!(f, "[write] {:?} was not written to before", state_key)?; + } else if right.is_none() { + writeln!(f, "[write] {:?} is not written to anymore", state_key)?; + } else { + writeln!(f, "[write] {:?} has changed its value", state_key)?; + } + }, + } + } + writeln!(f, " <<<<< ") + } +} + +#[cfg(test)] +mod test { + use super::*; + use aptos_types::{ + on_chain_config::CurrentTimeMicroseconds, state_store::state_value::StateValueMetadata, + write_set::WriteSetMut, + }; + + #[test] + fn test_diff_events() { + let mut diffs = vec![]; + + let events_1 = vec![ + ContractEvent::new_v2_with_type_tag_str("0x1::event::EventA", vec![0, 1, 2]), + ContractEvent::new_v2_with_type_tag_str("0x1::event::EventB", vec![0, 1, 2]), + ContractEvent::new_v2_with_type_tag_str("0x1::event::EventD", vec![0, 1, 2]), + ]; + + let events_2 = vec![ + ContractEvent::new_v2_with_type_tag_str("0x1::event::EventA", vec![0, 1, 2]), + ContractEvent::new_v2_with_type_tag_str("0x1::event::EventC", vec![0, 1, 2]), + ContractEvent::new_v2_with_type_tag_str("0x1::event::EventD", vec![0, 1, 3]), + ]; + + let expected_diffs = vec![ + Diff::Event { + left: Some(ContractEvent::new_v2_with_type_tag_str( + "0x1::event::EventB", + vec![0, 1, 2], + )), + right: None, + }, + Diff::Event { + left: None, + right: Some(ContractEvent::new_v2_with_type_tag_str( + "0x1::event::EventC", + vec![0, 1, 2], + )), + }, + Diff::Event { + left: Some(ContractEvent::new_v2_with_type_tag_str( + "0x1::event::EventD", + vec![0, 1, 2], + )), + right: Some(ContractEvent::new_v2_with_type_tag_str( + "0x1::event::EventD", + vec![0, 1, 3], + )), + }, + ]; + + TransactionDiff::diff_events(&mut diffs, events_1, events_2); + + assert_eq!(diffs.len(), 3); + assert!(diffs.iter().all(|diff| expected_diffs.contains(diff))); + } + + #[test] + fn test_diff_write_sets() { + let mut diffs = vec![]; + + let write_set_1 = WriteSetMut::new(vec![ + // Same in 2nd write set. + ( + StateKey::raw(b"key-1"), + WriteOp::legacy_creation(vec![0, 1, 2].into()), + ), + // Does not exist in 2nd write set. + ( + StateKey::raw(b"key-2"), + WriteOp::legacy_creation(vec![0, 1, 2].into()), + ), + // Different from 2nd write-set. + ( + StateKey::raw(b"key-4"), + WriteOp::legacy_creation(vec![0, 1, 2].into()), + ), + ( + StateKey::raw(b"key-5"), + WriteOp::legacy_creation(vec![0, 1, 2].into()), + ), + ( + StateKey::raw(b"key-6"), + WriteOp::creation( + vec![0, 1, 2].into(), + StateValueMetadata::new(1, 2, &CurrentTimeMicroseconds { microseconds: 100 }), + ), + ), + ]) + .freeze() + .unwrap(); + + let write_set_2 = WriteSetMut::new(vec![ + // Same in 1st write set. + ( + StateKey::raw(b"key-1"), + WriteOp::legacy_creation(vec![0, 1, 2].into()), + ), + // Does nto exist in 1st write set. + ( + StateKey::raw(b"key-3"), + WriteOp::legacy_creation(vec![0, 1, 2].into()), + ), + // Different from 1st write-set. + ( + StateKey::raw(b"key-4"), + WriteOp::legacy_creation(vec![0, 1, 3].into()), + ), + ( + StateKey::raw(b"key-5"), + WriteOp::legacy_modification(vec![0, 1, 2].into()), + ), + ( + StateKey::raw(b"key-6"), + WriteOp::creation( + vec![0, 1, 2].into(), + StateValueMetadata::new(1, 2, &CurrentTimeMicroseconds { microseconds: 200 }), + ), + ), + ]) + .freeze() + .unwrap(); + + let expected_diffs = vec![ + Diff::WriteSet { + state_key: StateKey::raw(b"key-2"), + left: Some(WriteOp::legacy_creation(vec![0, 1, 2].into())), + right: None, + }, + Diff::WriteSet { + state_key: StateKey::raw(b"key-3"), + left: None, + right: Some(WriteOp::legacy_creation(vec![0, 1, 2].into())), + }, + Diff::WriteSet { + state_key: StateKey::raw(b"key-4"), + left: Some(WriteOp::legacy_creation(vec![0, 1, 2].into())), + right: Some(WriteOp::legacy_creation(vec![0, 1, 3].into())), + }, + Diff::WriteSet { + state_key: StateKey::raw(b"key-5"), + left: Some(WriteOp::legacy_creation(vec![0, 1, 2].into())), + right: Some(WriteOp::legacy_modification(vec![0, 1, 2].into())), + }, + Diff::WriteSet { + state_key: StateKey::raw(b"key-6"), + left: Some(WriteOp::creation( + vec![0, 1, 2].into(), + StateValueMetadata::new(1, 2, &CurrentTimeMicroseconds { microseconds: 100 }), + )), + right: Some(WriteOp::creation( + vec![0, 1, 2].into(), + StateValueMetadata::new(1, 2, &CurrentTimeMicroseconds { microseconds: 200 }), + )), + }, + ]; + + TransactionDiff::diff_write_sets(&mut diffs, write_set_1, write_set_2); + + assert_eq!(diffs.len(), 5); + assert!(diffs.iter().all(|diff| expected_diffs.contains(diff))); + } +} diff --git a/aptos-move/replay-benchmark/src/generator.rs b/aptos-move/replay-benchmark/src/generator.rs new file mode 100644 index 0000000000000..089d6a36acbfb --- /dev/null +++ b/aptos-move/replay-benchmark/src/generator.rs @@ -0,0 +1,105 @@ +// Copyright (c) Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::{block::Block, overrides::OverrideConfig, workload::Workload}; +use aptos_move_debugger::aptos_debugger::AptosDebugger; +use aptos_types::transaction::{Transaction, Version}; +use std::{ + sync::{ + atomic::{AtomicU64, Ordering}, + Arc, + }, + time::Instant, +}; + +pub struct BenchmarkGenerator { + debugger: AptosDebugger, + begin_version: Version, + end_version: Version, + override_config: OverrideConfig, +} + +impl BenchmarkGenerator { + /// Generates a sequence of [Block] for benchmarking. + pub async fn generate_blocks( + debugger: AptosDebugger, + begin_version: Version, + end_version: Version, + override_config: OverrideConfig, + ) -> anyhow::Result> { + let generator = Arc::new(Self { + debugger, + begin_version, + end_version, + override_config, + }); + + let limit = generator.end_version - generator.begin_version + 1; + let (txns, _) = generator + .debugger + .get_committed_transactions(generator.begin_version, limit) + .await?; + let txn_blocks = generator.partition(txns); + + let num_generated = Arc::new(AtomicU64::new(0)); + let num_blocks = txn_blocks.len(); + + let mut tasks = Vec::with_capacity(num_blocks); + for (begin, txn_block) in txn_blocks { + let task = tokio::task::spawn_blocking({ + let generator = generator.clone(); + let num_generated = num_generated.clone(); + move || { + let start_time = Instant::now(); + let block = generator.generate_block(begin, txn_block); + let time = start_time.elapsed().as_secs(); + println!( + "Generated block {}/{} in {}s", + num_generated.fetch_add(1, Ordering::SeqCst) + 1, + num_blocks, + time + ); + block + } + }); + tasks.push(task); + } + + let mut blocks = Vec::with_capacity(tasks.len()); + for task in tasks { + blocks.push(task.await?); + } + + Ok(blocks) + } + + /// Generates a single [Block] for benchmarking. + fn generate_block(&self, begin: Version, txns: Vec) -> Block { + let workload = Workload::new(begin, txns); + let state_view = self.debugger.state_view_at_version(begin); + let state_override = self.override_config.get_state_override(&state_view); + Block::new(workload, &state_view, state_override) + } + + /// Partitions a sequence of transactions into blocks. + fn partition(&self, txns: Vec) -> Vec<(Version, Vec)> { + let mut begin_versions_and_blocks = Vec::with_capacity(txns.len()); + + let mut curr_begin = self.begin_version; + let mut curr_block = Vec::with_capacity(txns.len()); + + for txn in txns { + if txn.is_block_start() && !curr_block.is_empty() { + let block_size = curr_block.len(); + begin_versions_and_blocks.push((curr_begin, std::mem::take(&mut curr_block))); + curr_begin += block_size as Version; + } + curr_block.push(txn); + } + if !curr_block.is_empty() { + begin_versions_and_blocks.push((curr_begin, curr_block)); + } + + begin_versions_and_blocks + } +} diff --git a/aptos-move/replay-benchmark/src/lib.rs b/aptos-move/replay-benchmark/src/lib.rs new file mode 100644 index 0000000000000..0792bc55e5f4f --- /dev/null +++ b/aptos-move/replay-benchmark/src/lib.rs @@ -0,0 +1,10 @@ +// Copyright (c) Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +pub mod block; +mod diff; +pub mod generator; +pub mod overrides; +pub mod runner; +mod state_view; +mod workload; diff --git a/aptos-move/replay-benchmark/src/main.rs b/aptos-move/replay-benchmark/src/main.rs new file mode 100644 index 0000000000000..051e0edc0e950 --- /dev/null +++ b/aptos-move/replay-benchmark/src/main.rs @@ -0,0 +1,187 @@ +// Copyright (c) Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use aptos_logger::{Level, Logger}; +use aptos_move_debugger::aptos_debugger::AptosDebugger; +use aptos_push_metrics::MetricsPusher; +use aptos_replay_benchmark::{ + generator::BenchmarkGenerator, overrides::OverrideConfig, runner::BenchmarkRunner, +}; +use aptos_rest_client::{AptosBaseUrl, Client}; +use aptos_types::{on_chain_config::FeatureFlag, transaction::Version}; +use clap::Parser; +use url::Url; + +/// Minimum number of times to execute blocks of transactions and measure the time taken. +const MIN_NUM_REPEATS: usize = 3; + +#[derive(Parser)] +#[command(about)] +pub struct Command { + #[clap(long, default_value_t = Level::Error)] + log_level: Level, + + #[clap( + long, + help = "Fullnode's REST API query endpoint, e.g., https://mainnet.aptoslabs.com/v1 for \ + mainnet." + )] + rest_endpoint: String, + + #[clap( + long, + help = "Optional API key to increase HTTP request rate limit quota." + )] + api_key: Option, + + #[clap(long, help = "First transaction to include for benchmarking.")] + begin_version: Version, + + #[clap(long, help = "Last transaction to include for benchmarking.")] + end_version: Version, + + #[clap( + long, + default_value_t = 0, + help = "Number of blocks to skip for time measurement. Allows to warm-up caches." + )] + num_blocks_to_skip: usize, + + #[clap( + long, + num_args = 1.., + help = "List of space-separated concurrency levels that define how many threads Block-STM \ + is using to execute a block of transactions. For each level, the time taken to \ + execute blocks of transactions is measured and reported." + )] + concurrency_levels: Vec, + + #[clap( + long, + default_value_t = MIN_NUM_REPEATS, + help = "Number of times to execute blocks of transactions and measure the timr taken for \ + each concurrency level." + )] + num_repeats: usize, + + #[clap( + long, + help = "If true, measure time taken to execute each block separately. If false, measure \ + the overall time to execute all blocks." + )] + measure_block_times: bool, + + #[clap( + long, + num_args = 1.., + value_delimiter = ' ', + help = "List of space-separated feature flags to enable, in capital letters. For example, \ + GAS_PAYER_ENABLED or EMIT_FEE_STATEMENT. For the full list of feature flags, see \ + aptos-core/types/src/on_chain_config/aptos_features.rs." + )] + enable_features: Vec, + + #[clap( + long, + num_args = 1.., + value_delimiter = ' ', + help = "List of space-separated feature flags to disable, in capital letters. For \ + example, GAS_PAYER_ENABLED or EMIT_FEE_STATEMENT. For the full list of feature \ + flags, see aptos-core/types/src/on_chain_config/aptos_features.rs." + )] + disable_features: Vec, +} + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + let command = Command::parse(); + + let mut logger = Logger::new(); + logger.level(command.log_level); + logger.init(); + + let _mp = MetricsPusher::start(vec![]); + + // Sanity checks for provided commands. + assert!( + command.begin_version <= command.end_version, + "Transaction versions should be a valid closed interval. Instead got begin: {}, end: {}", + command.begin_version, + command.end_version, + ); + assert!( + !command.concurrency_levels.is_empty(), + "At least one concurrency level must be provided", + ); + assert!( + command.num_repeats >= MIN_NUM_REPEATS, + "Number of repeats must be at least {}", + MIN_NUM_REPEATS, + ); + assert!( + command + .enable_features + .iter() + .all(|f| !command.disable_features.contains(f)), + "Enable and disable feature flags cannot overlap", + ); + + // TODO: + // Right now we fetch transactions from debugger, but ideally we need a way to save them + // locally (with corresponding read-sets) so we can use this for CI. + let builder = Client::builder(AptosBaseUrl::Custom(Url::parse(&command.rest_endpoint)?)); + let client = if let Some(api_key) = command.api_key { + builder.api_key(&api_key)?.build() + } else { + builder.build() + }; + let debugger = AptosDebugger::rest_client(client)?; + + // TODO: + // Right now, only features can be overridden. In general, this can be allowed for anything: + // 1. Framework code, e.g., to test performance of new natives or compiler, + // 2. Gas schedule, to track the costs of charging gas or tracking limits. + // We probably should support at least these. + let override_config = OverrideConfig::new(command.enable_features, command.disable_features); + + let blocks = BenchmarkGenerator::generate_blocks( + debugger, + command.begin_version, + command.end_version, + override_config, + ) + .await?; + + // Ensure we have at least one block to benchmark. + assert!( + command.num_blocks_to_skip < blocks.len(), + "There are only {} blocks, but skipping {}", + blocks.len(), + command.num_blocks_to_skip + ); + + for block in &blocks { + block.print_diffs(); + } + + BenchmarkRunner::new( + command.concurrency_levels, + command.num_repeats, + command.measure_block_times, + command.num_blocks_to_skip, + ) + .measure_execution_time(&blocks); + + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn verify_tool() { + use clap::CommandFactory; + Command::command().debug_assert(); + } +} diff --git a/aptos-move/replay-benchmark/src/overrides.rs b/aptos-move/replay-benchmark/src/overrides.rs new file mode 100644 index 0000000000000..8e0270bbb898b --- /dev/null +++ b/aptos-move/replay-benchmark/src/overrides.rs @@ -0,0 +1,90 @@ +// Copyright (c) Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +//! Defines different overrides for on-chain state used for benchmarking. With overrides, past +//! transactions can be replayed on top of a modified state, and we can evaluate how it impacts +//! performance or other things. + +use aptos_logger::error; +use aptos_types::{ + on_chain_config::{FeatureFlag, Features, OnChainConfig}, + state_store::{state_key::StateKey, state_value::StateValue, StateView}, +}; +use serde::Serialize; +use std::collections::HashMap; + +/// Stores feature flags to enable/disable, essentially overriding on-chain state. +pub struct OverrideConfig { + additional_enabled_features: Vec, + additional_disabled_features: Vec, +} + +impl OverrideConfig { + pub fn new( + additional_enabled_features: Vec, + additional_disabled_features: Vec, + ) -> Self { + Self { + additional_enabled_features, + additional_disabled_features, + } + } + + pub(crate) fn get_state_override( + &self, + state_view: &impl StateView, + ) -> HashMap { + let mut state_override = HashMap::new(); + + // Enable/disable features. + let (features_state_key, features_state_value) = + config_override::(state_view, |features| { + for feature in &self.additional_enabled_features { + if features.is_enabled(*feature) { + error!("Feature {:?} is already enabled", feature); + } + features.enable(*feature); + } + for feature in &self.additional_disabled_features { + if !features.is_enabled(*feature) { + error!("Feature {:?} is already disabled", feature); + } + features.disable(*feature); + } + }); + state_override.insert(features_state_key, features_state_value); + state_override + } +} + +/// Returns the state key for on-chain config type. +fn config_state_key() -> StateKey { + StateKey::resource(T::address(), &T::struct_tag()) + .expect("Constructing state key for on-chain config must succeed") +} + +/// Fetches the config from the storage, and modifies it based on the passed function. Panics if +/// there is a storage error, config does not exist or fails to (de-)serialize. +fn config_override( + state_view: &impl StateView, + override_func: F, +) -> (StateKey, StateValue) { + let state_key = config_state_key::(); + let state_value = state_view + .get_state_value(&state_key) + .unwrap_or_else(|err| { + panic!( + "Failed to fetch on-chain config for {:?}: {:?}", + state_key, err + ) + }) + .unwrap_or_else(|| panic!("On-chain config for {:?} must always exist", state_key)); + + let mut config = T::deserialize_into_config(state_value.bytes()) + .expect("On-chain config must be deserializable"); + override_func(&mut config); + let config_bytes = bcs::to_bytes(&config).expect("On-chain config must be serializable"); + + let new_state_value = state_value.map_bytes(|_| Ok(config_bytes.into())).unwrap(); + (state_key, new_state_value) +} diff --git a/aptos-move/replay-benchmark/src/runner.rs b/aptos-move/replay-benchmark/src/runner.rs new file mode 100644 index 0000000000000..ed546ec40ff7b --- /dev/null +++ b/aptos-move/replay-benchmark/src/runner.rs @@ -0,0 +1,127 @@ +// Copyright (c) Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::block::Block; +use aptos_vm::{aptos_vm::AptosVMBlockExecutor, VMBlockExecutor}; +use std::time::Instant; + +/// Holds configuration for running the benchmarks and measuring the time taken. +pub struct BenchmarkRunner { + concurrency_levels: Vec, + num_repeats: usize, + measure_per_block_instead_of_overall_time: bool, + num_blocks_to_skip: usize, +} + +impl BenchmarkRunner { + pub fn new( + concurrency_levels: Vec, + num_repeats: usize, + measure_per_block_instead_of_overall_time: bool, + num_blocks_to_skip: usize, + ) -> Self { + Self { + concurrency_levels, + num_repeats, + measure_per_block_instead_of_overall_time, + num_blocks_to_skip, + } + } + + // TODO: + // This measures execution time from a cold-start. Ideally, we want to warm-up with executing + // 1-2 blocks prior to selected range, but not timing them. + pub fn measure_execution_time(&self, blocks: &[Block]) { + for concurrency_level in &self.concurrency_levels { + if self.measure_per_block_instead_of_overall_time { + self.measure_block_execution_times(blocks, *concurrency_level); + } else { + self.measure_overall_execution_time(blocks, *concurrency_level); + } + } + } + + /// Runs a sequence of blocks, measuring execution time for each block. The median is reported. + fn measure_block_execution_times(&self, blocks: &[Block], concurrency_level: usize) { + let mut times = (0..blocks.len()) + .map(|_| Vec::with_capacity(self.num_repeats)) + .collect::>(); + + for i in 0..self.num_repeats { + let executor = AptosVMBlockExecutor::new(); + for (idx, block) in blocks.iter().enumerate() { + let start_time = Instant::now(); + block.run(&executor, concurrency_level); + let time = start_time.elapsed().as_micros(); + if idx >= self.num_blocks_to_skip { + println!( + "[{}/{}] Block {} execution time is {}us", + i + 1, + self.num_repeats, + idx + 1, + time, + ); + } + times[idx].push(time); + } + } + + for (idx, mut time) in times.into_iter().enumerate() { + if idx >= self.num_blocks_to_skip { + time.sort(); + let min_time = *time.first().unwrap(); + let average_time = time.iter().sum::() as f64 / self.num_repeats as f64; + let median_time = time[self.num_repeats / 2]; + let max_time = *time.last().unwrap(); + + println!( + "Block {} execution time: min {}us, average {:.2}us, median {}us, max {}us\n", + idx + 1, + min_time, + average_time, + median_time, + max_time, + ); + } + } + } + + /// Runs the sequence of blocks, measuring end-to-end execution time. + fn measure_overall_execution_time(&self, blocks: &[Block], concurrency_level: usize) { + let mut times = Vec::with_capacity(self.num_repeats); + for i in 0..self.num_repeats { + let executor = AptosVMBlockExecutor::new(); + + // Warm-up. + for block in &blocks[..self.num_blocks_to_skip] { + block.run(&executor, concurrency_level); + } + + // Actual measurement. + let start_time = Instant::now(); + for block in &blocks[self.num_blocks_to_skip..] { + block.run(&executor, concurrency_level); + } + let time = start_time.elapsed().as_micros(); + + println!( + "[{}/{}] Overall execution time is {}us", + i + 1, + self.num_repeats, + time, + ); + times.push(time); + } + + times.sort(); + let min_time = *times.first().unwrap(); + let average_time = times.iter().sum::() as f64 / self.num_repeats as f64; + let median_time = times[self.num_repeats / 2]; + let max_time = *times.last().unwrap(); + + println!( + "Overall execution time (blocks {}-{}): min {}us, average {:.2}us, median {}us, max {}us\n", + self.num_blocks_to_skip + 1, blocks.len(), min_time, average_time, median_time, max_time, + ); + } +} diff --git a/aptos-move/replay-benchmark/src/state_view.rs b/aptos-move/replay-benchmark/src/state_view.rs new file mode 100644 index 0000000000000..0de19abc37dfd --- /dev/null +++ b/aptos-move/replay-benchmark/src/state_view.rs @@ -0,0 +1,82 @@ +// Copyright (c) Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use aptos_types::state_store::{ + state_key::StateKey, state_storage_usage::StateStorageUsage, state_value::StateValue, + StateView, StateViewResult, TStateView, +}; +use parking_lot::Mutex; +use std::collections::HashMap; + +/// Represents the read-set obtained when executing transactions. +pub(crate) struct ReadSet { + data: HashMap, +} + +impl TStateView for ReadSet { + type Key = StateKey; + + fn get_state_value(&self, state_key: &Self::Key) -> StateViewResult> { + Ok(self.data.get(state_key).cloned()) + } + + fn get_usage(&self) -> StateViewResult { + unreachable!("Should not be called when benchmarking") + } +} + +/// [StateView] implementation that records all execution reads. Captured reads can be converted +/// into a [ReadSet]. +pub(crate) struct ReadSetCapturingStateView<'s, S> { + captured_reads: Mutex>, + state_view: &'s S, +} + +impl<'s, S: StateView> ReadSetCapturingStateView<'s, S> { + pub(crate) fn new(state_view: &'s S, initial_read_set: HashMap) -> Self { + Self { + captured_reads: Mutex::new(initial_read_set), + state_view, + } + } + + pub(crate) fn into_read_set(self) -> ReadSet { + ReadSet { + data: self.captured_reads.into_inner(), + } + } +} + +impl<'s, S: StateView> TStateView for ReadSetCapturingStateView<'s, S> { + type Key = StateKey; + + fn get_state_value(&self, state_key: &Self::Key) -> StateViewResult> { + // Check the read-set first. + if let Some(state_value) = self.captured_reads.lock().get(state_key) { + return Ok(Some(state_value.clone())); + } + + // We do not allow failures because then benchmarking will not be correct (we miss a read). + // Plus, these failures should not happen when replaying past transactions. + let maybe_state_value = self + .state_view + .get_state_value(state_key) + .unwrap_or_else(|err| { + panic!("Failed to fetch state value for {:?}: {:?}", state_key, err) + }); + + // Capture the read on first access. + if let Some(state_value) = &maybe_state_value { + let mut captured_reads = self.captured_reads.lock(); + if !captured_reads.contains_key(state_key) { + captured_reads.insert(state_key.clone(), state_value.clone()); + } + } + + Ok(maybe_state_value) + } + + fn get_usage(&self) -> StateViewResult { + unreachable!("Should not be called when benchmarking") + } +} diff --git a/aptos-move/replay-benchmark/src/workload.rs b/aptos-move/replay-benchmark/src/workload.rs new file mode 100644 index 0000000000000..ccc9ed1ea2f73 --- /dev/null +++ b/aptos-move/replay-benchmark/src/workload.rs @@ -0,0 +1,51 @@ +// Copyright (c) Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use aptos_block_executor::txn_provider::default::DefaultTxnProvider; +use aptos_types::{ + block_executor::transaction_slice_metadata::TransactionSliceMetadata, + transaction::{ + signature_verified_transaction::{ + into_signature_verified_block, SignatureVerifiedTransaction, + }, + Transaction, Version, + }, +}; + +/// A workload to benchmark. Contains signature verified transactions, and metadata specifying the +/// start and end versions of these transactions. +pub(crate) struct Workload { + /// Stores a block of transactions for execution. Always has at least one transaction. + txn_provider: DefaultTxnProvider, + /// Stores metadata for the version range of a block. It is always set to + /// [TransactionSliceMetadata::Chunk]. + transaction_slice_metadata: TransactionSliceMetadata, +} + +impl Workload { + /// Returns a new workload to execute transactions at specified version. + pub(crate) fn new(begin: Version, txns: Vec) -> Self { + assert!(!txns.is_empty()); + + let end = begin + txns.len() as Version; + let transaction_slice_metadata = TransactionSliceMetadata::chunk(begin, end); + + let signature_verified_txns = into_signature_verified_block(txns); + let txn_provider = DefaultTxnProvider::new(signature_verified_txns); + + Workload { + txn_provider, + transaction_slice_metadata, + } + } + + /// Returns the signature verified transactions in the workload. + pub(crate) fn txn_provider(&self) -> &DefaultTxnProvider { + &self.txn_provider + } + + /// Returns transaction metadata corresponding to [begin, end) versions of the workload. + pub(crate) fn transaction_slice_metadata(&self) -> TransactionSliceMetadata { + self.transaction_slice_metadata + } +} diff --git a/crates/aptos-logger/src/metadata.rs b/crates/aptos-logger/src/metadata.rs index aba5b7503ce61..6ef82530c0a06 100644 --- a/crates/aptos-logger/src/metadata.rs +++ b/crates/aptos-logger/src/metadata.rs @@ -3,7 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 use serde::{Deserialize, Serialize}; -use std::{fmt, str::FromStr}; +use strum_macros::{Display, EnumString, FromRepr}; /// Associated metadata with every log to identify what kind of log and where it came from #[derive(Clone, Copy, Debug, Serialize, Deserialize)] @@ -60,68 +60,96 @@ impl Metadata { } } -static LOG_LEVEL_NAMES: &[&str] = &["ERROR", "WARN", "INFO", "DEBUG", "TRACE"]; - /// Logging levels, used for stratifying logs, and disabling less important ones for performance reasons #[repr(usize)] -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Serialize, Deserialize)] +#[derive( + Copy, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Debug, + Hash, + Serialize, + Deserialize, + FromRepr, + EnumString, + Display, +)] #[serde(rename_all = "UPPERCASE")] pub enum Level { /// The "error" level. /// /// Designates very serious errors. + #[strum(ascii_case_insensitive)] + #[strum(to_string = "ERROR")] Error = 0, /// The "warn" level. /// /// Designates hazardous situations. - Warn, + #[strum(ascii_case_insensitive)] + #[strum(to_string = "WARN")] + Warn = 1, /// The "info" level. /// /// Designates useful information. - Info, + #[strum(ascii_case_insensitive)] + #[strum(to_string = "INFO")] + Info = 2, /// The "debug" level. /// /// Designates lower priority information. - Debug, + #[strum(ascii_case_insensitive)] + #[strum(to_string = "DEBUG")] + Debug = 3, /// The "trace" level. /// /// Designates very low priority, often extremely verbose, information. - Trace, + #[strum(ascii_case_insensitive)] + #[strum(to_string = "TRACE")] + Trace = 4, } -impl Level { - fn from_usize(idx: usize) -> Option { - let lvl = match idx { - 0 => Level::Error, - 1 => Level::Warn, - 2 => Level::Info, - 3 => Level::Debug, - 4 => Level::Trace, - _ => return None, - }; - - Some(lvl) +#[cfg(test)] +mod test { + use super::*; + use std::str::FromStr; + + #[test] + fn test_log_level_from_string() { + assert_eq!(Level::Error, Level::from_str("ERROR").unwrap()); + assert_eq!(Level::Error, Level::from_str("Error").unwrap()); + assert_eq!(Level::Error, Level::from_str("error").unwrap()); + + assert_eq!(Level::Warn, Level::from_str("WARN").unwrap()); + assert_eq!(Level::Warn, Level::from_str("wArN").unwrap()); + assert_eq!(Level::Warn, Level::from_str("warn").unwrap()); + + assert_eq!(Level::Info, Level::from_str("INFO").unwrap()); + assert_eq!(Level::Info, Level::from_str("infO").unwrap()); + assert_eq!(Level::Info, Level::from_str("info").unwrap()); + + assert_eq!(Level::Debug, Level::from_str("DEBUG").unwrap()); + assert_eq!(Level::Debug, Level::from_str("Debug").unwrap()); + assert_eq!(Level::Debug, Level::from_str("debug").unwrap()); + + assert_eq!(Level::Trace, Level::from_str("TRACE").unwrap()); + assert_eq!(Level::Trace, Level::from_str("trAce").unwrap()); + assert_eq!(Level::Trace, Level::from_str("trace").unwrap()); + + assert!(Level::from_str("ERR").is_err()); + assert!(Level::from_str("err_or").is_err()); + assert!(Level::from_str("INF").is_err()); + assert!(Level::from_str("tracey").is_err()); } -} - -/// An error given when no `Level` matches the inputted string -#[derive(Debug)] -pub struct LevelParseError; - -impl FromStr for Level { - type Err = LevelParseError; - - fn from_str(level: &str) -> Result { - LOG_LEVEL_NAMES - .iter() - .position(|name| name.eq_ignore_ascii_case(level)) - .map(|idx| Level::from_usize(idx).unwrap()) - .ok_or(LevelParseError) - } -} -impl fmt::Display for Level { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.pad(LOG_LEVEL_NAMES[*self as usize]) + #[test] + fn test_log_level_to_string() { + assert_eq!(String::from("ERROR"), Level::Error.to_string()); + assert_eq!(String::from("WARN"), Level::Warn.to_string()); + assert_eq!(String::from("INFO"), Level::Info.to_string()); + assert_eq!(String::from("DEBUG"), Level::Debug.to_string()); + assert_eq!(String::from("TRACE"), Level::Trace.to_string()); } } diff --git a/types/src/block_executor/transaction_slice_metadata.rs b/types/src/block_executor/transaction_slice_metadata.rs index 8df707552253f..381259b2da3f1 100644 --- a/types/src/block_executor/transaction_slice_metadata.rs +++ b/types/src/block_executor/transaction_slice_metadata.rs @@ -76,6 +76,15 @@ impl TransactionSliceMetadata { (Chunk { end, .. }, Chunk { begin, .. }) => begin == end, } } + + /// Returns the first transaction version for [TransactionSliceMetadata::Chunk], and [None] + /// otherwise. + pub fn begin_version(&self) -> Option { + if let TransactionSliceMetadata::Chunk { begin, .. } = self { + return Some(*begin); + } + None + } } #[cfg(test)] diff --git a/types/src/write_set.rs b/types/src/write_set.rs index e939b70d1346a..0da5b6b89dcd5 100644 --- a/types/src/write_set.rs +++ b/types/src/write_set.rs @@ -568,6 +568,10 @@ impl WriteSetMut { &mut self.write_set } + pub fn into_inner(self) -> BTreeMap { + self.write_set + } + pub fn squash(mut self, other: Self) -> Result { use btree_map::Entry::*; From dacbfc32fc653c7e34b968ba7f8043e2c31c45fa Mon Sep 17 00:00:00 2001 From: Bo Wu Date: Sat, 7 Dec 2024 16:13:20 -0800 Subject: [PATCH 26/78] small fix and explicity delete unused disk --- ...provision-replay-verify-archive-disks.yaml | 5 +- .../workflows/replay-verify-on-archive.yaml | 2 +- ...workflow-run-replay-verify-on-archive.yaml | 29 +- testsuite/replay-verify/archive_disk_utils.py | 277 ++++++++++++------ testsuite/replay-verify/main.py | 24 +- testsuite/replay-verify/poetry.lock | 17 +- testsuite/replay-verify/pyproject.toml | 1 + testsuite/replay-verify/xfs-disk-repair.yaml | 4 +- 8 files changed, 248 insertions(+), 111 deletions(-) diff --git a/.github/workflows/provision-replay-verify-archive-disks.yaml b/.github/workflows/provision-replay-verify-archive-disks.yaml index 067c3dafbbc27..0cf64b7790c28 100644 --- a/.github/workflows/provision-replay-verify-archive-disks.yaml +++ b/.github/workflows/provision-replay-verify-archive-disks.yaml @@ -14,7 +14,7 @@ on: - ".github/workflows/provision-replay-verify-archive-disks.yaml" - ".github/workflows/workflow-run-replay-verify-archive-storage-provision.yaml" schedule: - - cron: "0 22 * * 1,3,5" # This runs every Mon,Wed,Fri + - cron: "0 8 * * 1,3,5" # This runs every Mon,Wed,Fri UTC 08:00 permissions: contents: read @@ -56,8 +56,7 @@ jobs: provision-mainnet: if: | github.event_name == 'schedule' || - github.event_name == 'push' || - github.event_name == 'workflow_dispatch' && (inputs.NETWORK == 'testnet' || inputs.NETWORK == 'all') + github.event_name == 'workflow_dispatch' && (inputs.NETWORK == 'mainnet' || inputs.NETWORK == 'all') needs: determine-test-metadata uses: ./.github/workflows/workflow-run-replay-verify-archive-storage-provision.yaml secrets: inherit diff --git a/.github/workflows/replay-verify-on-archive.yaml b/.github/workflows/replay-verify-on-archive.yaml index 3effdbc23f0e0..ffa58f9d52c97 100644 --- a/.github/workflows/replay-verify-on-archive.yaml +++ b/.github/workflows/replay-verify-on-archive.yaml @@ -31,7 +31,7 @@ on: - ".github/workflows/replay-verify-on-archive.yaml" - ".github/workflows/workflow-run-replay-verify-on-archive.yaml" schedule: - - cron: "0 22 * * 0,2,4" # The main branch cadence. This runs every Sun,Tues,Thurs + - cron: "0 8 * * 0,2,4" # The main branch cadence. This runs every Sun,Tues,Thurs UTC 08:00 permissions: contents: read diff --git a/.github/workflows/workflow-run-replay-verify-on-archive.yaml b/.github/workflows/workflow-run-replay-verify-on-archive.yaml index 8fb3954ebe45a..97102c8fda218 100644 --- a/.github/workflows/workflow-run-replay-verify-on-archive.yaml +++ b/.github/workflows/workflow-run-replay-verify-on-archive.yaml @@ -55,6 +55,7 @@ jobs: GCP_SERVICE_ACCOUNT_EMAIL: ${{ secrets.GCP_SERVICE_ACCOUNT_EMAIL }} EXPORT_GCP_PROJECT_VARIABLES: "false" GIT_CREDENTIALS: ${{ secrets.GIT_CREDENTIALS }} + GCP_AUTH_DURATION: "10800" # Authenticate to Google Cloud the project is aptos-ci with credentails files generated - name: Authenticate to Google Cloud @@ -100,11 +101,12 @@ jobs: CMD="$CMD --end ${{ inputs.END_VERSION }}" fi - if [ -n "${{ inputs.IMAGE_TAG }}" ]; then - CMD="$CMD --end ${{ inputs.IMAGE_TAG }}" + if [ -n "${{ inputs.IMAGE_TAG }}" ]; then + CMD="$CMD --image_tag ${{ inputs.IMAGE_TAG }}" fi eval $CMD + timeout-minutes: 120 # This is in case user manually cancel the step above, we still want to cleanup the resources - name: Post-run cleanup env: @@ -112,8 +114,29 @@ jobs: if: ${{ always() }} run: | cd testsuite/replay-verify - poetry run python main.py --network ${{ inputs.NETWORK }} --cleanup + CMD="poetry run python main.py --network ${{ inputs.NETWORK }} --cleanup" + if [ -n "${{ inputs.IMAGE_TAG }}" ]; then + CMD="$CMD --image_tag ${{ inputs.IMAGE_TAG }}" + fi + eval $CMD echo "Cleanup completed" + # List all disks in the project that are not in use and finished creating. There is a rare chance that the disk is being created and won't be used in future due to csi retry errors + # But this disk will be deleted in the next workflow run since its status is READY then + - name: Delete all unsed disks in the project + env: + GOOGLE_CLOUD_PROJECT: aptos-devinfra-0 + if: ${{ always() }} + run: | + + DISK_URIS=$(gcloud compute disks list --filter="-users:* AND status=READY" --format "value(uri())") + echo "Disks to be deleted:" + echo "$DISK_URIS" + + if [ -n "$DISK_URIS" ]; then + gcloud compute disks delete $DISK_URIS + else + echo "No unused disks found." + fi diff --git a/testsuite/replay-verify/archive_disk_utils.py b/testsuite/replay-verify/archive_disk_utils.py index 14d2194c2309f..b6ddf2379d55a 100644 --- a/testsuite/replay-verify/archive_disk_utils.py +++ b/testsuite/replay-verify/archive_disk_utils.py @@ -1,12 +1,17 @@ import argparse from google.cloud import compute_v1 from kubernetes import client, config -import time import logging import concurrent.futures import time import yaml from kubernetes.client.rest import ApiException +from tenacity import ( + retry, + stop_after_attempt, + wait_exponential, + retry_if_exception_type, +) # Constants @@ -21,6 +26,12 @@ TESTNET_SNAPSHOT_NAME = "testnet-archive" MAINNET_SNAPSHOT_NAME = "mainnet-archive" +PROJECT = "aptos-devinfra-0" +REGION = "us-central1" +CLUSTER_NAME = "devinfra-usce1-0" +NAMESPACE = "replay-verify" +ZONE = "us-central1-a" + def get_region_from_zone(zone): return zone.rsplit("-", 1)[0] @@ -126,7 +137,7 @@ def create_snapshot_with_gcloud( delete_operation = snapshot_client.delete( project=target_project, snapshot=snapshot_name ) - del_res = delete_operation.result() + del_res = delete_operation.result(timeout=1800) logger.info(f"Snapshot {snapshot_name} {del_res}.") except Exception as e: logger.info( @@ -178,10 +189,45 @@ def delete_disk(disk_client, project, zone, disk_name): logger.info(f"Disk {e} {disk_name} does not exist, no delete needed.") +def generate_disk_name(run_id, snapshot_name, pvc_id): + return f"{snapshot_name}-{run_id}-{pvc_id}" + + +@retry( + stop=stop_after_attempt(3), + wait=wait_exponential(multiplier=1, min=4, max=10), + retry=retry_if_exception_type((ApiException, Exception)), + before_sleep=lambda retry_state: logger.warning( + f"Retrying initial disk creation after error: {retry_state.outcome.exception()}" + ), +) +def create_disk_from_snapshot( + disk_client, snapshot_client, project, zone, snapshot_name, disk_name +): + start_time = time.time() + delete_disk(disk_client, project, zone, disk_name) + + # Create a new disk from the snapshot + logger.info(f"Creating disk {disk_name} from snapshot {snapshot_name}.") + snapshot = snapshot_client.get(project=project, snapshot=snapshot_name) + disk_body = compute_v1.Disk( + name=disk_name, + source_snapshot=snapshot.self_link, + type=f"projects/{project}/zones/{zone}/diskTypes/pd-ssd", + ) + + operation = disk_client.insert(project=project, zone=zone, disk_resource=disk_body) + wait_for_operation(project, zone, operation.name, compute_v1.ZoneOperationsClient()) + duration = time.time() - start_time + logger.info( + f"Disk {disk_name} created from snapshot {snapshot_name} with {duration}." + ) + + # Creating disk from import snapshots # require getting a hold of the kubectrl of the cluster # eg: gcloud container clusters get-credentials replay-on-archive --region us-central1 --project replay-verify -def create_disk_pv_pvc_from_snapshot( +def create_final_snapshot( project, zone, cluster_name, @@ -194,21 +240,14 @@ def create_disk_pv_pvc_from_snapshot( ): disk_client = compute_v1.DisksClient() snapshot_client = compute_v1.SnapshotsClient() - delete_disk(disk_client, project, zone, disk_name) - - # Create a new disk from the snapshot - logger.info(f"Creating disk {disk_name} from snapshot {og_snapshot_name}.") - snapshot = snapshot_client.get(project=project, snapshot=og_snapshot_name) - disk_body = compute_v1.Disk( - name=disk_name, - source_snapshot=snapshot.self_link, - type=f"projects/{project}/zones/{zone}/diskTypes/pd-ssd", + create_disk_from_snapshot( + disk_client, + snapshot_client, + project, + zone, + og_snapshot_name, + disk_name, ) - - operation = disk_client.insert(project=project, zone=zone, disk_resource=disk_body) - wait_for_operation(project, zone, operation.name, compute_v1.ZoneOperationsClient()) - logger.info(f"Disk {disk_name} created from snapshot {og_snapshot_name}.") - region_name = get_region_from_zone(zone) get_kubectl_credentials(project, region_name, cluster_name) # create_persistent_volume(disk_name, pv_name, pvc_name, namespace, True) @@ -243,6 +282,8 @@ def create_disk_pv_pvc_from_snapshot( logger.info("deleting repair disks") # delete the disk used for repair delete_disk(disk_client, project, zone, disk_name) + # delete the pv and pvc + delete_pv_and_pvc(repair_pv, repair_pvc, namespace) def is_job_pod_cleanedup(namespace, job_name): @@ -250,54 +291,85 @@ def is_job_pod_cleanedup(namespace, job_name): v1 = client.BatchV1Api() try: job = v1.read_namespaced_job(job_name, namespace) + # Check if job has timed out (active for too long) + if job.status.start_time: + job_duration = time.time() - job.status.start_time.timestamp() + if job_duration > 240: + logger.error( + f"Job {job_name} has been running for over {job_duration:.0f} seconds" + ) + return True return False - except Exception as e: + except client.exceptions.ApiException as e: + if e.status != 404: + logger.error(f"Error checking job {job_name}: {e}") return True def wait_for_operation(project, zone, operation_name, zone_operations_client): + start_time = time.time() + timeout = 3600 # 1 hour timeout + while True: + if time.time() - start_time > timeout: + raise TimeoutError( + f"Operation {operation_name} timed out after {timeout} seconds" + ) + result = zone_operations_client.get( project=project, zone=zone, operation=operation_name ) logger.info(f"Waiting for operation {operation_name} {result}") if result.status == compute_v1.Operation.Status.DONE: - if "error" in result: + if hasattr(result, "error") and result.error: raise Exception(result.error) return result time.sleep(20) +def delete_pv_and_pvc(pv_name, pvc_name, namespace): + config.load_kube_config() + v1 = client.CoreV1Api() + try: + v1.delete_namespaced_persistent_volume_claim(name=pvc_name, namespace=namespace) + logger.info(f"PVC {pvc_name} deleted.") + except client.exceptions.ApiException as e: + if e.status != 404: + logger.error(f"Error deleting PVC {pvc_name}: {e}") + try: + v1.delete_persistent_volume(name=pv_name) + logger.info(f"PV {pv_name} deleted.") + except client.exceptions.ApiException as e: + if e.status != 404: + logger.error(f"Error deleting PV {pv_name}: {e}") + + def create_persistent_volume( - project, zone, disk_name, pv_name, pvc_name, namespace, read_only + project, zone, disk_name, pv_name, pvc_name, namespace, read_only, label="" ): config.load_kube_config() v1 = client.CoreV1Api() + access_mode = "ReadWriteOnce" if not read_only else "ReadOnlyMany" + storage_size = "10Ti" if TESTNET_SNAPSHOT_NAME in disk_name else "8Ti" # Delete existing PVC if it exists try: - existing_pvc = v1.read_namespaced_persistent_volume_claim( - name=pvc_name, namespace=namespace - ) - if existing_pvc: - logger.info(f"PVC {pvc_name} already exists. Deleting it.") - v1.delete_namespaced_persistent_volume_claim( - name=pvc_name, namespace=namespace - ) - logger.info(f"PVC {pvc_name} deleted.") + v1.read_namespaced_persistent_volume_claim(name=pvc_name, namespace=namespace) + logger.info(f"PVC {pvc_name} already exists. Deleting it.") + v1.delete_namespaced_persistent_volume_claim(name=pvc_name, namespace=namespace) + logger.info(f"PVC {pvc_name} deleted.") except client.exceptions.ApiException as e: if e.status != 404: raise # Delete existing PV if it exists try: - existing_pv = v1.read_persistent_volume(name=pv_name) - if existing_pv: - logger.info(f"PV {pv_name} already exists. Deleting it.") - v1.delete_persistent_volume(name=pv_name) - logger.info(f"PV {pv_name} deleted.") + v1.read_persistent_volume(name=pv_name) + logger.info(f"PV {pv_name} already exists. Deleting it.") + v1.delete_persistent_volume(name=pv_name) + logger.info(f"PV {pv_name} deleted.") except client.exceptions.ApiException as e: if e.status != 404: raise @@ -307,17 +379,23 @@ def create_persistent_volume( pv = client.V1PersistentVolume( api_version="v1", kind="PersistentVolume", - metadata=client.V1ObjectMeta(name=pv_name), + metadata=client.V1ObjectMeta( + name=pv_name, + labels={ + "run": f"{label}", + "topology.kubernetes.io/zone": zone, # Add zone label to PV + }, + ), spec=client.V1PersistentVolumeSpec( - capacity={"storage": "10000Gi"}, - access_modes=["ReadWriteOnce"], + capacity={"storage": storage_size}, + access_modes=[access_mode], csi=client.V1CSIPersistentVolumeSource( driver="pd.csi.storage.gke.io", volume_handle=volume_handle, fs_type="xfs", read_only=read_only, ), - persistent_volume_reclaim_policy="Retain", # this is to delete the PV and disk separately to speed up pv deletion + persistent_volume_reclaim_policy="Delete", storage_class_name="ssd-data-xfs", ), ) @@ -326,12 +404,16 @@ def create_persistent_volume( pvc = client.V1PersistentVolumeClaim( api_version="v1", kind="PersistentVolumeClaim", - metadata=client.V1ObjectMeta(name=pvc_name, namespace=namespace), + metadata=client.V1ObjectMeta( + name=pvc_name, + namespace=namespace, + ), spec=client.V1PersistentVolumeClaimSpec( - access_modes=["ReadWriteOnce"], - resources=client.V1ResourceRequirements(requests={"storage": "10000Gi"}), + access_modes=[access_mode], + resources=client.V1ResourceRequirements(requests={"storage": storage_size}), storage_class_name="ssd-data-xfs", volume_name=pv_name, + # Remove the selector since we're using volume_name for direct binding ), ) @@ -339,6 +421,50 @@ def create_persistent_volume( v1.create_namespaced_persistent_volume_claim(namespace=namespace, body=pvc) +def create_repair_disk_and_its_snapshot( + project, zone, cluster_name, og_snapshot_name, snapshot_name, prefix, namespace +): + tasks = [] + + for copy in range(DISK_COPIES): + disk_name = f"{prefix}-repair-{copy}" + pv_name = f"{prefix}-{copy}" + pvc_name = f"{prefix}-claim-{copy}" + tasks.append( + ( + project, + zone, + cluster_name, + og_snapshot_name, + snapshot_name, + disk_name, + pv_name, + pvc_name, + namespace, + ) + ) + + # Execute tasks in parallel + with concurrent.futures.ThreadPoolExecutor() as executor: + futures = [executor.submit(create_final_snapshot, *task) for task in tasks] + for future in concurrent.futures.as_completed(futures, timeout=3600): + try: + result = future.result() + logger.info(f"Task result: {result}") + except Exception as e: + logger.error(f"Task generated an exception: {e}") + + +def parse_args(): + parser = argparse.ArgumentParser( + formatter_class=argparse.RawDescriptionHelpFormatter, + description=__doc__, + ) + parser.add_argument("--network", required=True, choices=["testnet", "mainnet"]) + args = parser.parse_args() + return args + + def create_one_pvc_from_snapshot(pvc_name, snapshot_name, namespace, label): config.load_kube_config() api_instance = client.CoreV1Api() @@ -373,9 +499,12 @@ def create_one_pvc_from_snapshot(pvc_name, snapshot_name, namespace, label): return pvc_name -def create_pvcs_from_snapshot(run_id, snapshot_name, namespace, pvc_num, label): +def create_replay_verify_pvcs_from_snapshot( + run_id, snapshot_name, namespace, pvc_num, label +): config.load_kube_config() api_instance = client.CustomObjectsApi() + volume_snapshot_content = { "apiVersion": "snapshot.storage.k8s.io/v1", "kind": "VolumeSnapshotContent", @@ -426,9 +555,13 @@ def create_pvcs_from_snapshot(run_id, snapshot_name, namespace, pvc_num, label): if e.status != 409: logger.error(f"Error creating new volumesnapshots: {e}") - # Execute tasks in parallel tasks = [ - (f"{run_id}-{snapshot_name}-{pvc_id}", snapshot_name, namespace, label) + ( + generate_disk_name(run_id, snapshot_name, pvc_id), + snapshot_name, + namespace, + label, + ) for pvc_id in range(pvc_num) ] res = [] @@ -446,62 +579,16 @@ def create_pvcs_from_snapshot(run_id, snapshot_name, namespace, pvc_num, label): return res -def create_repair_disk_and_its_snapshot( - project, zone, cluster_name, og_snapshot_name, snapshot_name, prefix, namespace -): - tasks = [] - - for copy in range(DISK_COPIES): - disk_name = f"{prefix}-{copy}" - pv_name = f"{prefix}-{copy}" - pvc_name = f"{prefix}-claim-{copy}" - tasks.append( - ( - project, - zone, - cluster_name, - og_snapshot_name, - snapshot_name, - disk_name, - pv_name, - pvc_name, - namespace, - ) - ) - - # Execute tasks in parallel - with concurrent.futures.ThreadPoolExecutor() as executor: - futures = [ - executor.submit(create_disk_pv_pvc_from_snapshot, *task) for task in tasks - ] - for future in concurrent.futures.as_completed(futures): - try: - result = future.result() - logger.info(f"Task result: {result}") - except Exception as e: - logger.error(f"Task generated an exception: {e}") - - -def parse_args(): - parser = argparse.ArgumentParser( - formatter_class=argparse.RawDescriptionHelpFormatter, - description=__doc__, - ) - parser.add_argument("--network", required=True, choices=["testnet", "mainnet"]) - args = parser.parse_args() - return args - - if __name__ == "__main__": # check input arg network args = parse_args() network = args.network source_project_id = "aptos-platform-compute-0" - region = "us-central1" - project_id = "aptos-devinfra-0" - target_namespace = "default" - zone = "us-central1-a" - cluster_name = "devinfra-usce1-0" + region = REGION + project_id = PROJECT + target_namespace = NAMESPACE + zone = ZONE + cluster_name = CLUSTER_NAME if network == "testnet": source_cluster_id = "general-usce1-0" diff --git a/testsuite/replay-verify/main.py b/testsuite/replay-verify/main.py index 771c9417d7976..2d661dee11366 100644 --- a/testsuite/replay-verify/main.py +++ b/testsuite/replay-verify/main.py @@ -17,7 +17,7 @@ from archive_disk_utils import ( TESTNET_SNAPSHOT_NAME, MAINNET_SNAPSHOT_NAME, - create_pvcs_from_snapshot, + create_replay_verify_pvcs_from_snapshot, get_kubectl_credentials, ) @@ -362,7 +362,7 @@ def create_pvc_from_snapshot(self): if self.network == Network.TESTNET else MAINNET_SNAPSHOT_NAME ) - pvcs = create_pvcs_from_snapshot( + pvcs = create_replay_verify_pvcs_from_snapshot( self.id, snapshot_name, self.namespace, @@ -500,7 +500,9 @@ def parse_args(): parser.add_argument("--end", required=False, type=int) parser.add_argument("--worker_cnt", required=False, type=int) parser.add_argument("--range_size", required=False, type=int) - parser.add_argument("--namespace", required=False, type=str, default="default") + parser.add_argument( + "--namespace", required=False, type=str, default="replay-verify" + ) parser.add_argument("--image_tag", required=False, type=str) parser.add_argument("--cleanup", required=False, action="store_true", default=False) args = parser.parse_args() @@ -548,6 +550,16 @@ def print_logs(failed_workpod_logs, txn_mismatch_logs): config = ReplayConfig(network) worker_cnt = args.worker_cnt if args.worker_cnt else config.pvc_number * 7 range_size = args.range_size if args.range_size else config.range_size + + if args.start is not None: + assert ( + args.start >= start + ), f"start version {args.start} is out of range {start} - {end}" + if args.end is not None: + assert ( + args.end <= end + ), f"end version {args.end} is out of range {start} - {end}" + scheduler = ReplayScheduler( run_id, start if args.start is None else args.start, @@ -572,9 +584,9 @@ def print_logs(failed_workpod_logs, txn_mismatch_logs): (failed_logs, txn_mismatch_logs) = scheduler.collect_all_failed_logs() scheduler.print_stats() print_logs(failed_logs, txn_mismatch_logs) - if txn_mismatch_logs: - logger.error("Transaction mismatch logs found.") - exit(1) + if txn_mismatch_logs: + logger.error("Transaction mismatch logs found.") + exit(1) finally: scheduler.cleanup() diff --git a/testsuite/replay-verify/poetry.lock b/testsuite/replay-verify/poetry.lock index a383c32e1a31e..3267b3492cd25 100644 --- a/testsuite/replay-verify/poetry.lock +++ b/testsuite/replay-verify/poetry.lock @@ -852,6 +852,21 @@ files = [ {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] +[[package]] +name = "tenacity" +version = "9.0.0" +description = "Retry code until it succeeds" +optional = false +python-versions = ">=3.8" +files = [ + {file = "tenacity-9.0.0-py3-none-any.whl", hash = "sha256:93de0c98785b27fcf659856aa9f54bfbd399e29969b0621bc7f762bd441b4539"}, + {file = "tenacity-9.0.0.tar.gz", hash = "sha256:807f37ca97d62aa361264d497b0e31e92b8027044942bfa756160d908320d73b"}, +] + +[package.extras] +doc = ["reno", "sphinx"] +test = ["pytest", "tornado (>=4.5)", "typeguard"] + [[package]] name = "tomli" version = "2.1.0" @@ -910,4 +925,4 @@ test = ["websockets"] [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "1122681d83360921d2b63f007b65c3436823b10b3d579d0fec4cf8b5e07fed59" +content-hash = "6323a0fd0a9e990e2cb17997bb2a9689930e3465c9a392397ef012e243222820" diff --git a/testsuite/replay-verify/pyproject.toml b/testsuite/replay-verify/pyproject.toml index 63b0bac43b699..e893e923c0b19 100644 --- a/testsuite/replay-verify/pyproject.toml +++ b/testsuite/replay-verify/pyproject.toml @@ -12,6 +12,7 @@ google-cloud-compute = "^1.20.1" google-cloud-container = "^2.53.0" google-cloud-storage = "^2.18.2" psutil = "^6.1.0" +tenacity = "^9.0.0" [tool.poetry.group.dev.dependencies] diff --git a/testsuite/replay-verify/xfs-disk-repair.yaml b/testsuite/replay-verify/xfs-disk-repair.yaml index e07427cc56bdc..1b571b7443022 100644 --- a/testsuite/replay-verify/xfs-disk-repair.yaml +++ b/testsuite/replay-verify/xfs-disk-repair.yaml @@ -3,7 +3,7 @@ kind: Job metadata: name: self-deleting-job spec: - ttlSecondsAfterFinished: 60 + ttlSecondsAfterFinished: 60 template: metadata: name: self-deleting-job @@ -11,7 +11,7 @@ spec: containers: - name: self-deleting-container image: gcr.io/google.com/cloudsdktool/google-cloud-cli:latest - command: ["sh", "-c", "ls /mnt/* && sleep 10"] + command: ["sh", "-c", "ls /mnt/* && sync && sleep 10"] volumeMounts: - name: my-volume mountPath: /mnt From 42d47eeacabb62d464d3126b95e22b9beb4164ee Mon Sep 17 00:00:00 2001 From: Greg Nazario Date: Mon, 9 Dec 2024 14:39:53 -0500 Subject: [PATCH 27/78] [consensus] Remove dead code in warnings (#15543) --- consensus/src/epoch_manager.rs | 1 - consensus/src/quorum_store/quorum_store_builder.rs | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/consensus/src/epoch_manager.rs b/consensus/src/epoch_manager.rs index 9f44243ca4524..a1be0f289de64 100644 --- a/consensus/src/epoch_manager.rs +++ b/consensus/src/epoch_manager.rs @@ -1825,7 +1825,6 @@ pub enum NoRandomnessReason { DKGCompletedSessionResourceMissing, CompletedSessionTooOld, NotInValidatorSet, - ConsensusKeyUnavailable, ErrConvertingConsensusKeyToDecryptionKey(anyhow::Error), TranscriptDeserializationError(bcs::Error), SecretShareDecryptionFailed(anyhow::Error), diff --git a/consensus/src/quorum_store/quorum_store_builder.rs b/consensus/src/quorum_store/quorum_store_builder.rs index 069fa3d241eda..73a4d4f49880e 100644 --- a/consensus/src/quorum_store/quorum_store_builder.rs +++ b/consensus/src/quorum_store/quorum_store_builder.rs @@ -129,7 +129,7 @@ pub struct InnerBuilder { network_sender: NetworkSender, verifier: Arc, proof_cache: ProofCache, - backend: SecureBackend, + _backend: SecureBackend, coordinator_tx: Sender, coordinator_rx: Option>, batch_generator_cmd_tx: tokio::sync::mpsc::Sender, @@ -205,7 +205,7 @@ impl InnerBuilder { network_sender, verifier, proof_cache, - backend, + _backend: backend, coordinator_tx, coordinator_rx: Some(coordinator_rx), batch_generator_cmd_tx, From f3319d18632b73af05c819766a5f611dcafd7f4d Mon Sep 17 00:00:00 2001 From: GhostWalker562 <43276017+GhostWalker562@users.noreply.github.com> Date: Mon, 9 Dec 2024 14:17:01 -0800 Subject: [PATCH 28/78] Fix private key field being required (#15546) --- crates/aptos/CHANGELOG.md | 2 ++ crates/aptos/src/common/types.rs | 7 +++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/crates/aptos/CHANGELOG.md b/crates/aptos/CHANGELOG.md index ffd001a799283..1e2d3237362da 100644 --- a/crates/aptos/CHANGELOG.md +++ b/crates/aptos/CHANGELOG.md @@ -4,6 +4,8 @@ All notable changes to the Aptos CLI will be captured in this file. This project # Unreleased +- [`Fix`] CLI config should not always require a private key field to be present. + ## [4.6.0] - 2024/11/29 - Add `--node-api-key` flag to `aptos move replay` to allow for querying the fullnode with an API key. - Add `--chunk-size` flag to allow configuring chunk size for chunked publish mode. diff --git a/crates/aptos/src/common/types.rs b/crates/aptos/src/common/types.rs index d6fb1d3855dc9..13c600ba209f8 100644 --- a/crates/aptos/src/common/types.rs +++ b/crates/aptos/src/common/types.rs @@ -250,8 +250,11 @@ pub struct ProfileConfig { #[serde(skip_serializing_if = "Option::is_none")] pub network: Option, /// Private key for commands. - #[serde(skip_serializing_if = "Option::is_none")] - #[serde(deserialize_with = "deserialize_private_key_with_prefix")] + #[serde( + skip_serializing_if = "Option::is_none", + default, + deserialize_with = "deserialize_private_key_with_prefix" + )] pub private_key: Option, /// Public key for commands #[serde(skip_serializing_if = "Option::is_none")] From e8289d12f84bd4ddf8de6f5d698bfb55615af7cf Mon Sep 17 00:00:00 2001 From: Bo Wu Date: Tue, 26 Nov 2024 09:58:16 -0800 Subject: [PATCH 29/78] fix flaky test --- storage/aptosdb/src/state_store/state_store_test.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/aptosdb/src/state_store/state_store_test.rs b/storage/aptosdb/src/state_store/state_store_test.rs index 5eb8b543e17a5..2308deb9d97f5 100644 --- a/storage/aptosdb/src/state_store/state_store_test.rs +++ b/storage/aptosdb/src/state_store/state_store_test.rs @@ -469,7 +469,7 @@ proptest! { (input, batch1_size) in hash_map(any::(), any::(), 2..1000) .prop_flat_map(|input| { let len = input.len(); - (Just(input), 2..len) + (Just(input), 2..=len) }) ) { let tmp_dir1 = TempPath::new(); From 6dbfb31d27e02617ee6c69abc58330caa743e2c1 Mon Sep 17 00:00:00 2001 From: Gerardo Di Giacomo Date: Tue, 10 Dec 2024 12:30:38 -0800 Subject: [PATCH 30/78] add CompiledModule and CompiledScript deserializer fuzzer (#15494) * add CompiledModule and CompiledScript deserializer fuzzer --- testsuite/fuzzer/fuzz.sh | 20 +++-- testsuite/fuzzer/fuzz/Cargo.toml | 6 ++ .../move/deserialize_script_module.rs | 77 +++++++++++++++++++ 3 files changed, 98 insertions(+), 5 deletions(-) create mode 100644 testsuite/fuzzer/fuzz/fuzz_targets/move/deserialize_script_module.rs diff --git a/testsuite/fuzzer/fuzz.sh b/testsuite/fuzzer/fuzz.sh index c08db0e44faf3..355d1a548d5df 100755 --- a/testsuite/fuzzer/fuzz.sh +++ b/testsuite/fuzzer/fuzz.sh @@ -166,11 +166,22 @@ function build-oss-fuzz() { done } +function install-coverage-tools() { + cargo +$NIGHTLY_VERSION install cargo-binutils + cargo +$NIGHTLY_VERSION install rustfilt +} + function coverage() { if [ -z "$1" ]; then usage coverage fi fuzz_target=$1 + + if ! cargo +$NIGHTLY_VERSION cov -V &> /dev/null; then + install-coverage-tools + fi + + clean-coverage $fuzz_target local corpus_dir="fuzz/corpus/$fuzz_target" local coverage_dir="./fuzz/coverage/$fuzz_target/report" mkdir -p $coverage_dir @@ -184,7 +195,7 @@ function coverage() { fuzz_target_bin=$(find ./target/*/coverage -name $fuzz_target -type f -perm /111) #$(find target/*/coverage -name $fuzz_target -type f) echo "Found fuzz target binary: $fuzz_target_bin" # Generate the coverage report - cargo +nightly cov -- show $fuzz_target_bin \ + cargo +$NIGHTLY_VERSION cov -- show $fuzz_target_bin \ --format=html \ --instr-profile=fuzz/coverage/$fuzz_target/coverage.profdata \ --show-directory-coverage \ @@ -200,12 +211,11 @@ function clean-coverage() { fi local fuzz_target="$1" - local coverage_dir="./fuzz/coverage/$fuzz_target/" - if [ "$fuzz_target" == "all" ]; then - rm -rf coverage + rm -rf ./fuzz/coverage else - rm -rf $target_dir + local coverage_dir="./fuzz/coverage/$fuzz_target/" + rm -rf $coverage_dir fi } diff --git a/testsuite/fuzzer/fuzz/Cargo.toml b/testsuite/fuzzer/fuzz/Cargo.toml index 13a630e928217..7c3c7b4e84997 100644 --- a/testsuite/fuzzer/fuzz/Cargo.toml +++ b/testsuite/fuzzer/fuzz/Cargo.toml @@ -88,3 +88,9 @@ name = "use_case_aware_shuffler" path = "fuzz_targets/use_case_aware_shuffler.rs" test = false doc = false + +[[bin]] +name = "deserialize_script_module" +path = "fuzz_targets/move/deserialize_script_module.rs" +test = false +doc = false diff --git a/testsuite/fuzzer/fuzz/fuzz_targets/move/deserialize_script_module.rs b/testsuite/fuzzer/fuzz/fuzz_targets/move/deserialize_script_module.rs new file mode 100644 index 0000000000000..bbd6d5a063918 --- /dev/null +++ b/testsuite/fuzzer/fuzz/fuzz_targets/move/deserialize_script_module.rs @@ -0,0 +1,77 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +#![no_main] +use arbitrary::Arbitrary; +use libfuzzer_sys::{fuzz_target, Corpus}; +// mod utils; +use move_binary_format::{ + deserializer::DeserializerConfig, file_format::CompiledScript, CompiledModule, +}; + +#[derive(Arbitrary, Debug)] +enum ExecVariant { + Module(CompiledModule), + Script(CompiledScript), + Raw(Vec), +} + +fuzz_target!(|fuzz_data: ExecVariant| -> Corpus { run_case(&fuzz_data) }); + +fn run_case(data: &ExecVariant) -> Corpus { + match data { + ExecVariant::Module(module) => run_case_module(module), + ExecVariant::Script(script) => run_case_script(script), + ExecVariant::Raw(raw_data) => run_case_raw(raw_data), + } +} + +fn run_case_module(module: &CompiledModule) -> Corpus { + let mut module_code = vec![]; + if module.serialize(&mut module_code).is_err() { + return Corpus::Reject; + } + match CompiledModule::deserialize_with_config(&module_code, &DeserializerConfig::default()) { + Ok(mut m) => { + m.version = module.version; + assert_eq!(*module, m); + Corpus::Keep + }, + Err(_) => Corpus::Reject, + } +} + +fn run_case_script(script: &CompiledScript) -> Corpus { + let mut script_code = vec![]; + if script.serialize(&mut script_code).is_err() { + return Corpus::Reject; + } + match CompiledScript::deserialize_with_config(&script_code, &DeserializerConfig::default()) { + Ok(mut s) => { + s.version = script.version; + assert_eq!(*script, s); + Corpus::Keep + }, + Err(_) => Corpus::Reject, + } +} + +fn run_case_raw(raw_data: &Vec) -> Corpus { + if let Ok(m) = CompiledModule::deserialize_with_config(raw_data, &DeserializerConfig::default()) + { + let mut module_code = vec![]; + m.serialize(&mut module_code).unwrap(); + assert_eq!(*raw_data, module_code); + return Corpus::Keep; + } + + if let Ok(s) = CompiledScript::deserialize_with_config(raw_data, &DeserializerConfig::default()) + { + let mut script_code = vec![]; + s.serialize(&mut script_code).unwrap(); + assert_eq!(*raw_data, script_code); + return Corpus::Keep; + } + + Corpus::Reject +} From 7edaeaf17a3a537f9ff6144c28d553347512f79e Mon Sep 17 00:00:00 2001 From: Satya Vusirikala Date: Tue, 10 Dec 2024 12:31:43 -0800 Subject: [PATCH 31/78] Fix round manager tests (#15369) --- consensus/src/round_manager_test.rs | 213 +++++++++++++++------------- 1 file changed, 117 insertions(+), 96 deletions(-) diff --git a/consensus/src/round_manager_test.rs b/consensus/src/round_manager_test.rs index b999662d82070..1123f33352919 100644 --- a/consensus/src/round_manager_test.rs +++ b/consensus/src/round_manager_test.rs @@ -40,6 +40,7 @@ use aptos_consensus_types::{ }, block_retrieval::{BlockRetrievalRequest, BlockRetrievalStatus}, common::{Author, Payload, Round}, + order_vote_msg::OrderVoteMsg, pipeline::commit_decision::CommitDecision, proposal_msg::ProposalMsg, round_timeout::RoundTimeoutMsg, @@ -86,6 +87,7 @@ use futures::{ }; use maplit::hashmap; use std::{ + collections::VecDeque, iter::FromIterator, sync::{ atomic::{AtomicBool, Ordering}, @@ -117,6 +119,11 @@ pub struct NodeSetup { local_consensus_config: ConsensusConfig, onchain_randomness_config: OnChainRandomnessConfig, onchain_jwk_consensus_config: OnChainJWKConsensusConfig, + vote_queue: VecDeque, + order_vote_queue: VecDeque, + proposal_queue: VecDeque, + round_timeout_queue: VecDeque, + commit_decision_queue: VecDeque, } impl NodeSetup { @@ -316,8 +323,7 @@ impl NodeSetup { let (round_manager_tx, _) = aptos_channel::new(QueueStyle::LIFO, 1, None); - let mut local_config = local_consensus_config.clone(); - local_config.enable_broadcast_vote(false); + let local_config = local_consensus_config.clone(); let mut round_manager = RoundManager::new( epoch_state, @@ -354,6 +360,11 @@ impl NodeSetup { local_consensus_config, onchain_randomness_config, onchain_jwk_consensus_config, + vote_queue: VecDeque::new(), + order_vote_queue: VecDeque::new(), + proposal_queue: VecDeque::new(), + round_timeout_queue: VecDeque::new(), + commit_decision_queue: VecDeque::new(), } } @@ -401,8 +412,8 @@ impl NodeSetup { } } - pub async fn next_network_message(&mut self) -> ConsensusMsg { - match self.next_network_event().await { + pub async fn next_network_message(&mut self) { + let consensus_msg = match self.next_network_event().await { Event::Message(_, msg) => msg, Event::RpcRequest(_, msg, _, _) if matches!(msg, ConsensusMsg::CommitMessage(_)) => msg, Event::RpcRequest(_, msg, _, _) => { @@ -412,6 +423,37 @@ impl NodeSetup { self.identity_desc() ) }, + }; + + match consensus_msg { + ConsensusMsg::ProposalMsg(proposal) => { + self.proposal_queue.push_back(*proposal); + }, + ConsensusMsg::VoteMsg(vote) => { + self.vote_queue.push_back(*vote); + }, + ConsensusMsg::OrderVoteMsg(order_vote) => { + self.order_vote_queue.push_back(*order_vote); + }, + ConsensusMsg::RoundTimeoutMsg(round_timeout) => { + self.round_timeout_queue.push_back(*round_timeout); + }, + ConsensusMsg::CommitDecisionMsg(commit_decision) => { + self.commit_decision_queue.push_back(*commit_decision); + }, + ConsensusMsg::CommitMessage(d) if matches!(*d, CommitMessage::Decision(_)) => { + match *d { + CommitMessage::Decision(commit_decision) => { + self.commit_decision_queue.push_back(commit_decision); + }, + _ => unreachable!(), + } + }, + msg => panic!( + "Unexpected Consensus Message: {:?} on node {}", + msg, + self.identity_desc() + ), } } @@ -427,53 +469,38 @@ impl NodeSetup { } pub async fn next_proposal(&mut self) -> ProposalMsg { - match self.next_network_message().await { - ConsensusMsg::ProposalMsg(p) => *p, - msg => panic!( - "Unexpected Consensus Message: {:?} on node {}", - msg, - self.identity_desc() - ), + while self.proposal_queue.is_empty() { + self.next_network_message().await; } + self.proposal_queue.pop_front().unwrap() } pub async fn next_vote(&mut self) -> VoteMsg { - match self.next_network_message().await { - ConsensusMsg::VoteMsg(v) => *v, - msg => panic!( - "Unexpected Consensus Message: {:?} on node {}", - msg, - self.identity_desc() - ), + while self.vote_queue.is_empty() { + self.next_network_message().await; } + self.vote_queue.pop_front().unwrap() + } + + pub async fn next_order_vote(&mut self) -> OrderVoteMsg { + while self.order_vote_queue.is_empty() { + self.next_network_message().await; + } + self.order_vote_queue.pop_front().unwrap() } pub async fn next_timeout(&mut self) -> RoundTimeoutMsg { - match self.next_network_message().await { - ConsensusMsg::RoundTimeoutMsg(v) => *v, - msg => panic!( - "Unexpected Consensus Message: {:?} on node {}", - msg, - self.identity_desc() - ), + while self.round_timeout_queue.is_empty() { + self.next_network_message().await; } + self.round_timeout_queue.pop_front().unwrap() } pub async fn next_commit_decision(&mut self) -> CommitDecision { - match self.next_network_message().await { - ConsensusMsg::CommitDecisionMsg(v) => *v, - ConsensusMsg::CommitMessage(d) if matches!(*d, CommitMessage::Decision(_)) => { - match *d { - CommitMessage::Decision(d) => d, - _ => unreachable!(), - } - }, - msg => panic!( - "Unexpected Consensus Message: {:?} on node {}", - msg, - self.identity_desc() - ), + while self.commit_decision_queue.is_empty() { + self.next_network_message().await; } + self.commit_decision_queue.pop_front().unwrap() } pub async fn poll_block_retreival(&mut self) -> Option { @@ -628,53 +655,47 @@ fn process_and_vote_on_proposal( .unwrap(); info!("Finish process proposal on {}", node.identity_desc()); num_votes += 1; + } + } - if let Some(prev_proposer) = apply_commit_prev_proposer { - if prev_proposer != node.id && expected_round > 2 { + for node in nodes.iter_mut() { + info!( + "Fetching {} votes in round {} on node {}", + num_votes, + expected_round, + node.identity_desc() + ); + if down_nodes.contains(&node.id) { + // Drop the votes on down nodes + info!("Dropping votes on down node {}", node.identity_desc()); + for _ in 0..num_votes { + timed_block_on(runtime, node.next_vote()); + } + } else { + let mut votes = Vec::new(); + for _ in 0..num_votes { + votes.push(timed_block_on(runtime, node.next_vote())); + } + + info!("Processing votes on node {}", node.identity_desc()); + if process_votes { + for vote_msg in votes { + timed_block_on(runtime, node.round_manager.process_vote_msg(vote_msg)).unwrap(); + } + if apply_commit_prev_proposer.is_some() + && expected_round > 1 + && apply_commit_on_votes + { info!( - "Applying commit {} on node {}", + "Applying next commit {} on proposer node {}", expected_round - 2, node.identity_desc() ); - timed_block_on(runtime, node.commit_next_ordered(&[expected_round - 2])); + timed_block_on(runtime, node.commit_next_ordered(&[expected_round - 1])); } } } } - - let proposer_node = nodes.get_mut(next_proposer).unwrap(); - info!( - "Fetching {} votes in round {} on node {}", - num_votes, - expected_round, - proposer_node.identity_desc() - ); - let mut votes = Vec::new(); - for _ in 0..num_votes { - votes.push(timed_block_on(runtime, proposer_node.next_vote())); - } - - info!("Processing votes on node {}", proposer_node.identity_desc()); - if process_votes { - for vote_msg in votes { - timed_block_on( - runtime, - proposer_node.round_manager.process_vote_msg(vote_msg), - ) - .unwrap(); - } - if apply_commit_prev_proposer.is_some() && expected_round > 1 && apply_commit_on_votes { - info!( - "Applying next commit {} on proposer node {}", - expected_round - 2, - proposer_node.identity_desc() - ); - timed_block_on( - runtime, - proposer_node.commit_next_ordered(&[expected_round - 1]), - ); - } - } } #[test] @@ -2170,7 +2191,7 @@ pub fn forking_retrieval_test() { ); timed_block_on(&runtime, async { - println!("Insert local timeout to all nodes on next round"); + info!("Insert local timeout to all nodes on next round"); let mut timeout_votes = 0; for node in nodes.iter_mut() { if node.id != behind_node && node.id != forking_node { @@ -2182,13 +2203,13 @@ pub fn forking_retrieval_test() { } } - println!("Process all local timeouts"); + info!("Process all local timeouts"); for node in nodes.iter_mut() { - println!("Timeouts on {}", node.id); + info!("Timeouts on {}", node.id); for i in 0..timeout_votes { - println!("Timeout {} on {}", i, node.id); + info!("Timeout {} on {}", i, node.id); if node.id == forking_node && (2..4).contains(&i) { - println!("Got {}", node.next_commit_decision().await); + info!("Got {}", node.next_commit_decision().await); } let vote_msg_on_timeout = node.next_vote().await; @@ -2215,7 +2236,7 @@ pub fn forking_retrieval_test() { assert!(vote_msg_on_timeout.vote().is_timeout()); } - println!("Got {}", nodes[forking_node].next_commit_decision().await); + info!("Got {}", nodes[forking_node].next_commit_decision().await); }); info!("Create forked block"); @@ -2267,7 +2288,7 @@ pub fn forking_retrieval_test() { proposals.push(node.next_proposal().await); } - println!( + info!( "Processing proposals for behind node {}", behind_node_obj.identity_desc() ); @@ -2311,19 +2332,19 @@ pub fn forking_retrieval_test() { 3, ); - let next_message = timed_block_on(&runtime, nodes[proposal_node].next_network_message()); - match next_message { - ConsensusMsg::VoteMsg(_) => info!("Skip extra vote msg"), - ConsensusMsg::ProposalMsg(msg) => { - // put the message back in the queue. - // actual peer doesn't matter, it is ignored, so use self. - let peer = nodes[proposal_node].signer.author(); - nodes[proposal_node] - .pending_network_events - .push(Event::Message(peer, ConsensusMsg::ProposalMsg(msg))) - }, - _ => panic!("unexpected network message {:?}", next_message), - } + // let next_message = timed_block_on(&runtime, nodes[proposal_node].next_network_message()); + // match next_message { + // ConsensusMsg::VoteMsg(_) => info!("Skip extra vote msg"), + // ConsensusMsg::ProposalMsg(msg) => { + // // put the message back in the queue. + // // actual peer doesn't matter, it is ignored, so use self. + // let peer = nodes[proposal_node].signer.author(); + // nodes[proposal_node] + // .pending_network_events + // .push(Event::Message(peer, ConsensusMsg::ProposalMsg(msg))) + // }, + // _ => panic!("unexpected network message {:?}", next_message), + // } process_and_vote_on_proposal( &runtime, &mut nodes, From 1d194b808f481436ca9f72ffb352cd592554945f Mon Sep 17 00:00:00 2001 From: Josh Lind Date: Thu, 5 Dec 2024 09:45:30 -0500 Subject: [PATCH 32/78] [Inspection Service] Add simple consensus health check endpoint. --- .../src/server/index.rs | 6 +- .../src/server/metrics.rs | 38 +++++++++++ .../src/server/mod.rs | 6 ++ state-sync/state-sync-driver/src/driver.rs | 63 +++++++++++-------- state-sync/state-sync-driver/src/metrics.rs | 15 ++++- 5 files changed, 99 insertions(+), 29 deletions(-) diff --git a/crates/aptos-inspection-service/src/server/index.rs b/crates/aptos-inspection-service/src/server/index.rs index ef8ccfea8f24a..d57f80bfde383 100644 --- a/crates/aptos-inspection-service/src/server/index.rs +++ b/crates/aptos-inspection-service/src/server/index.rs @@ -2,8 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{ - server::utils::CONTENT_TYPE_TEXT, CONFIGURATION_PATH, FORGE_METRICS_PATH, JSON_METRICS_PATH, - METRICS_PATH, PEER_INFORMATION_PATH, SYSTEM_INFORMATION_PATH, + server::utils::CONTENT_TYPE_TEXT, CONFIGURATION_PATH, CONSENSUS_HEALTH_CHECK_PATH, + FORGE_METRICS_PATH, JSON_METRICS_PATH, METRICS_PATH, PEER_INFORMATION_PATH, + SYSTEM_INFORMATION_PATH, }; use hyper::{Body, StatusCode}; @@ -25,6 +26,7 @@ fn get_index_response() -> String { index_response.push("Welcome to the Aptos Inspection Service!".into()); index_response.push("The following endpoints are available:".into()); index_response.push(format!("\t- {}", CONFIGURATION_PATH)); + index_response.push(format!("\t- {}", CONSENSUS_HEALTH_CHECK_PATH)); index_response.push(format!("\t- {}", FORGE_METRICS_PATH)); index_response.push(format!("\t- {}", JSON_METRICS_PATH)); index_response.push(format!("\t- {}", METRICS_PATH)); diff --git a/crates/aptos-inspection-service/src/server/metrics.rs b/crates/aptos-inspection-service/src/server/metrics.rs index a762688cd9525..9857927e5afd8 100644 --- a/crates/aptos-inspection-service/src/server/metrics.rs +++ b/crates/aptos-inspection-service/src/server/metrics.rs @@ -6,9 +6,47 @@ use crate::server::{ utils, utils::{CONTENT_TYPE_JSON, CONTENT_TYPE_TEXT}, }; +use aptos_config::config::NodeConfig; use hyper::{Body, StatusCode}; use prometheus::TextEncoder; +// The metric key for the consensus execution gauge +const CONSENSUS_EXECUTION_GAUGE: &str = "aptos_state_sync_consensus_executing_gauge{}"; + +/// Handles a consensus health check request. This method returns +/// 200 if the node is currently participating in consensus. +/// +/// Note: we assume that this endpoint will only be used every few seconds. +pub async fn handle_consensus_health_check(node_config: &NodeConfig) -> (StatusCode, Body, String) { + // Verify the node is a validator. If not, return an error. + if !node_config.base.role.is_validator() { + return ( + StatusCode::BAD_REQUEST, + Body::from("This node is not a validator!"), + CONTENT_TYPE_TEXT.into(), + ); + } + + // Check the value of the consensus execution gauge + let metrics = utils::get_all_metrics(); + if let Some(gauge_value) = metrics.get(CONSENSUS_EXECUTION_GAUGE) { + if gauge_value == "1" { + return ( + StatusCode::OK, + Body::from("Consensus health check passed!"), + CONTENT_TYPE_TEXT.into(), + ); + } + } + + // Otherwise, consensus is not executing + ( + StatusCode::INTERNAL_SERVER_ERROR, + Body::from("Consensus health check failed! Consensus is not executing!"), + CONTENT_TYPE_TEXT.into(), + ) +} + /// Handles a new forge metrics request pub fn handle_forge_metrics() -> (StatusCode, Body, String) { // Get and encode the metrics diff --git a/crates/aptos-inspection-service/src/server/mod.rs b/crates/aptos-inspection-service/src/server/mod.rs index c352d4de373a8..5b442e3a3518e 100644 --- a/crates/aptos-inspection-service/src/server/mod.rs +++ b/crates/aptos-inspection-service/src/server/mod.rs @@ -30,6 +30,7 @@ mod tests; // The list of endpoints offered by the inspection service pub const CONFIGURATION_PATH: &str = "/configuration"; +pub const CONSENSUS_HEALTH_CHECK_PATH: &str = "/consensus_health_check"; pub const FORGE_METRICS_PATH: &str = "/forge_metrics"; pub const INDEX_PATH: &str = "/"; pub const JSON_METRICS_PATH: &str = "/json_metrics"; @@ -111,6 +112,11 @@ async fn serve_requests( // Exposes the node configuration configuration::handle_configuration_request(&node_config) }, + CONSENSUS_HEALTH_CHECK_PATH => { + // /consensus_health_check + // Exposes the consensus health check + metrics::handle_consensus_health_check(&node_config).await + }, FORGE_METRICS_PATH => { // /forge_metrics // Exposes forge encoded metrics diff --git a/state-sync/state-sync-driver/src/driver.rs b/state-sync/state-sync-driver/src/driver.rs index 2ed74268af4cf..2542665851a25 100644 --- a/state-sync/state-sync-driver/src/driver.rs +++ b/state-sync/state-sync-driver/src/driver.rs @@ -655,6 +655,9 @@ impl< /// Checks that state sync is making progress async fn drive_progress(&mut self) { + // Update the executing component metrics + self.update_executing_component_metrics(); + // Fetch the global data summary and verify we have active peers let global_data_summary = self.aptos_data_client.get_global_data_summary(); if global_data_summary.is_empty() { @@ -673,15 +676,6 @@ impl< // If consensus or consensus observer is executing, there's nothing to do if self.check_if_consensus_or_observer_executing() { - let executing_component = if self.driver_configuration.role.is_validator() { - ExecutingComponent::Consensus - } else { - ExecutingComponent::ConsensusObserver - }; - metrics::increment_counter( - &metrics::EXECUTING_COMPONENT, - executing_component.get_label(), - ); return; } @@ -691,10 +685,6 @@ impl< let consensus_sync_request = self.consensus_notification_handler.get_sync_request(); // Attempt to continuously sync - metrics::increment_counter( - &metrics::EXECUTING_COMPONENT, - ExecutingComponent::ContinuousSyncer.get_label(), - ); if let Err(error) = self .continuous_syncer .drive_progress(consensus_sync_request) @@ -708,20 +698,43 @@ impl< ); metrics::increment_counter(&metrics::CONTINUOUS_SYNCER_ERRORS, error.get_label()); } - } else { - metrics::increment_counter( - &metrics::EXECUTING_COMPONENT, - ExecutingComponent::Bootstrapper.get_label(), + } else if let Err(error) = self.bootstrapper.drive_progress(&global_data_summary).await { + sample!( + SampleRate::Duration(Duration::from_secs(DRIVER_ERROR_LOG_FREQ_SECS)), + warn!(LogSchema::new(LogEntry::Driver) + .error(&error) + .message("Error found when checking the bootstrapper progress!")); ); - if let Err(error) = self.bootstrapper.drive_progress(&global_data_summary).await { - sample!( - SampleRate::Duration(Duration::from_secs(DRIVER_ERROR_LOG_FREQ_SECS)), - warn!(LogSchema::new(LogEntry::Driver) - .error(&error) - .message("Error found when checking the bootstrapper progress!")); - ); - metrics::increment_counter(&metrics::BOOTSTRAPPER_ERRORS, error.get_label()); + metrics::increment_counter(&metrics::BOOTSTRAPPER_ERRORS, error.get_label()); + }; + } + + /// Updates the executing component metrics for the driver + fn update_executing_component_metrics(&self) { + // Determine the executing component + let executing_component = if self.check_if_consensus_or_observer_executing() { + if self.driver_configuration.role.is_validator() { + ExecutingComponent::Consensus + } else { + ExecutingComponent::ConsensusObserver } + } else if self.bootstrapper.is_bootstrapped() { + ExecutingComponent::ContinuousSyncer + } else { + ExecutingComponent::Bootstrapper }; + + // Increment the executing component counter + metrics::increment_counter( + &metrics::EXECUTING_COMPONENT, + executing_component.get_label(), + ); + + // Set the consensus executing gauge + if executing_component == ExecutingComponent::Consensus { + metrics::CONSENSUS_EXECUTING_GAUGE.set(1); + } else { + metrics::CONSENSUS_EXECUTING_GAUGE.set(0); + } } } diff --git a/state-sync/state-sync-driver/src/metrics.rs b/state-sync/state-sync-driver/src/metrics.rs index dae906ff5016a..777c506e05e11 100644 --- a/state-sync/state-sync-driver/src/metrics.rs +++ b/state-sync/state-sync-driver/src/metrics.rs @@ -3,7 +3,8 @@ use aptos_metrics_core::{ exponential_buckets, histogram_opts, register_histogram_vec, register_int_counter_vec, - register_int_gauge_vec, HistogramTimer, HistogramVec, IntCounterVec, IntGaugeVec, + register_int_gauge, register_int_gauge_vec, HistogramTimer, HistogramVec, IntCounterVec, + IntGauge, IntGaugeVec, }; use once_cell::sync::Lazy; use std::time::Instant; @@ -42,6 +43,7 @@ pub const STORAGE_SYNCHRONIZER_COMMIT_POST_PROCESSOR: &str = "commit_post_proces pub const STORAGE_SYNCHRONIZER_STATE_SNAPSHOT_RECEIVER: &str = "state_snapshot_receiver"; /// An enum representing the component currently executing +#[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum ExecutingComponent { Bootstrapper, Consensus, @@ -105,6 +107,15 @@ pub static BOOTSTRAPPER_ERRORS: Lazy = Lazy::new(|| { .unwrap() }); +/// Gauge indicating whether consensus is currently executing +pub static CONSENSUS_EXECUTING_GAUGE: Lazy = Lazy::new(|| { + register_int_gauge!( + "aptos_state_sync_consensus_executing_gauge", + "Gauge indicating whether consensus is currently executing" + ) + .unwrap() +}); + /// Gauge for state sync continuous syncer fallback mode pub static CONTINUOUS_SYNCER_ERRORS: Lazy = Lazy::new(|| { register_int_counter_vec!( @@ -146,7 +157,7 @@ pub static DRIVER_FALLBACK_MODE: Lazy = Lazy::new(|| { .unwrap() }); -/// Counters related to the currently executing component +/// Counters related to the currently executing component in the main driver loop pub static EXECUTING_COMPONENT: Lazy = Lazy::new(|| { register_int_counter_vec!( "aptos_state_sync_executing_component_counters", From 7e0aaa2ad12759f6afd6bac04bc55c2ea8046676 Mon Sep 17 00:00:00 2001 From: Greg Nazario Date: Tue, 10 Dec 2024 16:47:46 -0500 Subject: [PATCH 33/78] [cli] Release 4.7.0 (#15556) --- Cargo.lock | 2 +- crates/aptos/CHANGELOG.md | 1 + crates/aptos/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 80a48ae3ef7c5..5873f265bcaa3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -275,7 +275,7 @@ dependencies = [ [[package]] name = "aptos" -version = "4.6.0" +version = "4.7.0" dependencies = [ "anyhow", "aptos-api-types", diff --git a/crates/aptos/CHANGELOG.md b/crates/aptos/CHANGELOG.md index 1e2d3237362da..6dc1d8fd14967 100644 --- a/crates/aptos/CHANGELOG.md +++ b/crates/aptos/CHANGELOG.md @@ -4,6 +4,7 @@ All notable changes to the Aptos CLI will be captured in this file. This project # Unreleased +## [4.7.0] - 2024/12/10 - [`Fix`] CLI config should not always require a private key field to be present. ## [4.6.0] - 2024/11/29 diff --git a/crates/aptos/Cargo.toml b/crates/aptos/Cargo.toml index c137909d6a649..99797d06b3113 100644 --- a/crates/aptos/Cargo.toml +++ b/crates/aptos/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "aptos" description = "Aptos tool for management of nodes and interacting with the blockchain" -version = "4.6.0" +version = "4.7.0" # Workspace inherited keys authors = { workspace = true } From 06f18246ad24aeeae075342133aecc47310c0867 Mon Sep 17 00:00:00 2001 From: "Daniel Porteous (dport)" Date: Tue, 10 Dec 2024 15:07:08 -0800 Subject: [PATCH 34/78] [Faucet] Support ratelimiting on Firebase JWT (#15525) --- Cargo.lock | 13 ++ Cargo.toml | 1 + .../aptos-faucet/configs/testing_redis.yaml | 4 +- .../configs/testing_redis_minter_local.yaml | 4 +- crates/aptos-faucet/core/Cargo.toml | 1 + .../core/src/bypasser/auth_token.rs | 7 + .../core/src/checkers/auth_token.rs | 6 + .../core/src/checkers/memory_ratelimit.rs | 4 +- .../core/src/checkers/redis_ratelimit.rs | 143 +++++++++++++----- .../aptos-faucet/core/src/endpoints/errors.rs | 12 +- .../aptos-faucet/core/src/endpoints/fund.rs | 2 + crates/aptos-faucet/core/src/firebase_jwt.rs | 113 ++++++++++++++ crates/aptos-faucet/core/src/lib.rs | 1 + crates/aptos-faucet/core/src/server/run.rs | 8 +- crates/aptos-faucet/integration-tests/main.py | 25 +-- 15 files changed, 289 insertions(+), 55 deletions(-) create mode 100644 crates/aptos-faucet/core/src/firebase_jwt.rs diff --git a/Cargo.lock b/Cargo.lock index 5873f265bcaa3..c3cef51aea56f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1723,6 +1723,7 @@ dependencies = [ "clap 4.5.21", "deadpool-redis", "enum_dispatch", + "firebase-token", "futures", "hex", "ipnet", @@ -8222,6 +8223,18 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6" +[[package]] +name = "firebase-token" +version = "0.3.0" +source = "git+https://github.com/aptos-labs/firebase-token?rev=34ea512d3d1fad6c11df3e7d82ff72beccc05836#34ea512d3d1fad6c11df3e7d82ff72beccc05836" +dependencies = [ + "jsonwebtoken 8.3.0", + "reqwest 0.11.23", + "serde", + "tokio", + "tracing", +] + [[package]] name = "firestore" version = "0.43.0" diff --git a/Cargo.toml b/Cargo.toml index 7bb1b9b0c15e0..711e90130c8c9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -595,6 +595,7 @@ fail = "0.5.0" ff = { version = "0.13", features = ["derive"] } field_count = "0.1.1" file_diff = "1.0.0" +firebase-token = { git = "https://github.com/aptos-labs/firebase-token", rev = "34ea512d3d1fad6c11df3e7d82ff72beccc05836" } firestore = "0.43.0" fixed = "1.25.1" flate2 = "1.0.24" diff --git a/crates/aptos-faucet/configs/testing_redis.yaml b/crates/aptos-faucet/configs/testing_redis.yaml index f8770f845a790..f1a9204a6235c 100644 --- a/crates/aptos-faucet/configs/testing_redis.yaml +++ b/crates/aptos-faucet/configs/testing_redis.yaml @@ -7,7 +7,9 @@ bypasser_configs: [] checker_configs: - type: "RedisRatelimit" database_address: "127.0.0.1" - max_requests_per_ip_per_day: 3 + max_requests_per_day: 3 + ratelimit_key_provider_config: + type: "Ip" funder_config: type: "FakeFunder" handler_config: diff --git a/crates/aptos-faucet/configs/testing_redis_minter_local.yaml b/crates/aptos-faucet/configs/testing_redis_minter_local.yaml index 8c489fc4b5cfb..612085f68ae61 100644 --- a/crates/aptos-faucet/configs/testing_redis_minter_local.yaml +++ b/crates/aptos-faucet/configs/testing_redis_minter_local.yaml @@ -8,7 +8,9 @@ bypasser_configs: [] checker_configs: - type: "RedisRatelimit" database_address: "127.0.0.1" - max_requests_per_ip_per_day: 50000 + max_requests_per_day: 50000 + ratelimit_key_provider_config: + type: "Ip" funder_config: type: "MintFunder" node_url: "http://127.0.0.1:8080" diff --git a/crates/aptos-faucet/core/Cargo.toml b/crates/aptos-faucet/core/Cargo.toml index 7d3ffa848d9fb..a078e9c95dec0 100644 --- a/crates/aptos-faucet/core/Cargo.toml +++ b/crates/aptos-faucet/core/Cargo.toml @@ -24,6 +24,7 @@ captcha = { version = "0.0.9" } clap = { workspace = true } deadpool-redis = { version = "0.11.1", features = ["rt_tokio_1"], default-features = false } enum_dispatch = { workspace = true } +firebase-token = { workspace = true } futures = { workspace = true } hex = { workspace = true } ipnet = { workspace = true } diff --git a/crates/aptos-faucet/core/src/bypasser/auth_token.rs b/crates/aptos-faucet/core/src/bypasser/auth_token.rs index 41426eb6e6d36..592b4a3d93aa3 100644 --- a/crates/aptos-faucet/core/src/bypasser/auth_token.rs +++ b/crates/aptos-faucet/core/src/bypasser/auth_token.rs @@ -5,6 +5,7 @@ use super::BypasserTrait; use crate::{ checkers::CheckerData, common::{ListManager, ListManagerConfig}, + firebase_jwt::X_IS_JWT_HEADER, }; use anyhow::Result; use aptos_logger::info; @@ -29,6 +30,11 @@ impl AuthTokenBypasser { #[async_trait] impl BypasserTrait for AuthTokenBypasser { async fn request_can_bypass(&self, data: CheckerData) -> Result { + // Don't check if the request has X_IS_JWT_HEADER set. + if data.headers.contains_key(X_IS_JWT_HEADER) { + return Ok(false); + } + let auth_token = match data .headers .get(AUTHORIZATION) @@ -38,6 +44,7 @@ impl BypasserTrait for AuthTokenBypasser { Some(auth_token) => auth_token, None => return Ok(false), }; + Ok(self.manager.contains(auth_token)) } } diff --git a/crates/aptos-faucet/core/src/checkers/auth_token.rs b/crates/aptos-faucet/core/src/checkers/auth_token.rs index 6716343e01f4f..2652edb9a94e9 100644 --- a/crates/aptos-faucet/core/src/checkers/auth_token.rs +++ b/crates/aptos-faucet/core/src/checkers/auth_token.rs @@ -5,6 +5,7 @@ use super::{CheckerData, CheckerTrait}; use crate::{ common::{ListManager, ListManagerConfig}, endpoints::{AptosTapError, RejectionReason, RejectionReasonCode}, + firebase_jwt::X_IS_JWT_HEADER, }; use anyhow::Result; use aptos_logger::info; @@ -33,6 +34,11 @@ impl CheckerTrait for AuthTokenChecker { data: CheckerData, _dry_run: bool, ) -> Result, AptosTapError> { + // Don't check if the request has X_IS_JWT_HEADER set. + if data.headers.contains_key(X_IS_JWT_HEADER) { + return Ok(vec![]); + } + let auth_token = match data .headers .get(AUTHORIZATION) diff --git a/crates/aptos-faucet/core/src/checkers/memory_ratelimit.rs b/crates/aptos-faucet/core/src/checkers/memory_ratelimit.rs index 3d2f4e969c9da..26d8524aac366 100644 --- a/crates/aptos-faucet/core/src/checkers/memory_ratelimit.rs +++ b/crates/aptos-faucet/core/src/checkers/memory_ratelimit.rs @@ -27,7 +27,7 @@ impl MemoryRatelimitCheckerConfig { } /// Simple in memory storage that rejects if we've ever seen a request from an -/// IP that has succeeded. +/// IP that has succeeded. This does not support JWT-based ratelimiting. pub struct MemoryRatelimitChecker { pub max_requests_per_day: u32, @@ -81,7 +81,7 @@ impl CheckerTrait for MemoryRatelimitChecker { "IP {} has exceeded the daily limit of {} requests", data.source_ip, self.max_requests_per_day ), - RejectionReasonCode::IpUsageLimitExhausted, + RejectionReasonCode::UsageLimitExhausted, )]); } else if !dry_run { *requests_today += 1; diff --git a/crates/aptos-faucet/core/src/checkers/redis_ratelimit.rs b/crates/aptos-faucet/core/src/checkers/redis_ratelimit.rs index 16f7fb7b68a98..2d94149c4ce5c 100644 --- a/crates/aptos-faucet/core/src/checkers/redis_ratelimit.rs +++ b/crates/aptos-faucet/core/src/checkers/redis_ratelimit.rs @@ -4,16 +4,52 @@ use super::{CheckerData, CheckerTrait, CompleteData}; use crate::{ endpoints::{AptosTapError, AptosTapErrorCode, RejectionReason, RejectionReasonCode}, + firebase_jwt::{FirebaseJwtVerifier, FirebaseJwtVerifierConfig}, helpers::{days_since_tap_epoch, get_current_time_secs, seconds_until_next_day}, }; use anyhow::{Context, Result}; use async_trait::async_trait; use deadpool_redis::{ - redis::{AsyncCommands, ConnectionAddr, ConnectionInfo, RedisConnectionInfo}, + redis::{self, AsyncCommands, ConnectionAddr, ConnectionInfo, RedisConnectionInfo}, Config, Connection, Pool, Runtime, }; use serde::{Deserialize, Serialize}; -use std::net::IpAddr; + +#[derive(Clone, Debug, Default, Deserialize, Serialize)] +#[serde(tag = "type")] +pub enum RatelimitKeyProviderConfig { + #[default] + Ip, + Jwt(FirebaseJwtVerifierConfig), +} + +/// This is what produces the key we use for ratelimiting in Redis. +pub enum RatelimitKeyProvider { + Ip, + Jwt(FirebaseJwtVerifier), +} + +impl RatelimitKeyProvider { + pub fn ratelimit_key_prefix(&self) -> &'static str { + match self { + RatelimitKeyProvider::Ip => "ip", + RatelimitKeyProvider::Jwt(_) => "jwt", + } + } + + /// If the faucet is configured to ratelimit by IP, this will be the client's IP + /// address. If the faucet is configured to ratelimit by JWT, we verify the JWT + /// first. If it is valid, this will be the user's Firebase UID (taken from the + /// JWT's `sub` field). + pub async fn ratelimit_key_value(&self, data: &CheckerData) -> Result { + match self { + RatelimitKeyProvider::Ip => Ok(data.source_ip.to_string()), + RatelimitKeyProvider::Jwt(jwt_verifier) => { + jwt_verifier.validate_jwt(data.headers.clone()).await + }, + } + } +} #[derive(Clone, Debug, Deserialize, Serialize)] pub struct RedisRatelimitCheckerConfig { @@ -35,9 +71,13 @@ pub struct RedisRatelimitCheckerConfig { /// The password of the given user, if necessary. pub database_password: Option, - /// Max number of requests per IP per day. 500s are not counted, because - /// they are not the user's fault, but everything else is. - pub max_requests_per_ip_per_day: u32, + /// Max number of requests per key per day. 500s are not counted, because they are + /// not the user's fault, but everything else is. + pub max_requests_per_day: u32, + + /// This defines how we ratelimit, e.g. either by IP or by JWT (Firebase UID). + #[serde(default)] + pub ratelimit_key_provider_config: RatelimitKeyProviderConfig, } impl RedisRatelimitCheckerConfig { @@ -76,10 +116,12 @@ impl RedisRatelimitCheckerConfig { /// request. Instead, it uses counters to track limits. This is heavily inspired /// by https://redis.com/redis-best-practices/basic-rate-limiting/. /// +/// We use a generic key (e.g. IP address or Firebase UID). +/// /// If we're not careful, it is possible for people to exceed the intended limit -/// by sending many requests simulatenously. We avoid this problem with this +/// by sending many requests simultaneously. We avoid this problem with this /// order of operations: -/// 1. Read the current value of the limit for source IP. +/// 1. Read the current value of the limit for the given key (e.g. IP / Firebase UID). /// 2. If value is greater than limit, reject. /// 3. Otherwise, increment and set TTL if necessary. /// 4. Increment returns the new value. Check if this is greater than the limit also. @@ -95,15 +137,16 @@ impl RedisRatelimitCheckerConfig { /// Note: Previously I made an attempt (d4fbf6db675e9036a967b52bf8d13e1b2566787e) at /// doing these steps atomically, but it became very unwieldy: /// 1. Start a transaction. -/// 2. Increment current value for limit for source IP, set TTL if necessary. +/// 2. Increment current value for limit for source key, set TTL if necessary. /// 3. If value is greater than limit, revert the transaction. /// /// This second way leaves a small window for someone to slip in multiple requests, -/// therein blowing past the configured limit, but it's a very small window, so -/// we'll worry about it as a followup: https://github.com/aptos-labs/aptos-tap/issues/15. +/// therein blowing past the configured limit, but it's a very small window, so we'll +/// worry about it as a followup: https://github.com/aptos-labs/aptos-tap/issues/15. pub struct RedisRatelimitChecker { args: RedisRatelimitCheckerConfig, db_pool: Pool, + ratelimit_key_provider: RatelimitKeyProvider, } impl RedisRatelimitChecker { @@ -116,7 +159,18 @@ impl RedisRatelimitChecker { .await .context("Failed to connect to redis on startup")?; - Ok(Self { args, db_pool }) + let ratelimit_key_provider = match args.ratelimit_key_provider_config.clone() { + RatelimitKeyProviderConfig::Ip => RatelimitKeyProvider::Ip, + RatelimitKeyProviderConfig::Jwt(config) => { + RatelimitKeyProvider::Jwt(FirebaseJwtVerifier::new(config).await?) + }, + }; + + Ok(Self { + args, + db_pool, + ratelimit_key_provider, + }) } pub async fn get_redis_connection(&self) -> Result { @@ -129,27 +183,35 @@ impl RedisRatelimitChecker { } // Returns the key and the seconds until the next day. - fn get_key_and_secs_until_next_day(&self, source_ip: &IpAddr) -> (String, u64) { + fn get_key_and_secs_until_next_day( + &self, + ratelimit_key_prefix: &str, + ratelimit_key_value: &str, + ) -> (String, u64) { let now_secs = get_current_time_secs(); let seconds_until_next_day = seconds_until_next_day(now_secs); - let key = format!("ip:{}:{}", source_ip, days_since_tap_epoch(now_secs)); + let key = format!( + "{}:{}:{}", + ratelimit_key_prefix, + ratelimit_key_value, + days_since_tap_epoch(now_secs) + ); (key, seconds_until_next_day) } fn check_limit_value( &self, - data: &CheckerData, limit_value: Option, seconds_until_next_day: u64, ) -> Option { - if limit_value.unwrap_or(0) > self.args.max_requests_per_ip_per_day as i64 { + if limit_value.unwrap_or(0) > self.args.max_requests_per_day as i64 { Some( RejectionReason::new( format!( - "IP {} has reached the maximum allowed number of requests per day: {}", - data.source_ip, self.args.max_requests_per_ip_per_day + "You have reached the maximum allowed number of requests per day: {}", + self.args.max_requests_per_day ), - RejectionReasonCode::IpUsageLimitExhausted, + RejectionReasonCode::UsageLimitExhausted, ) .retry_after(seconds_until_next_day), ) @@ -171,11 +233,17 @@ impl CheckerTrait for RedisRatelimitChecker { .await .map_err(|e| AptosTapError::new_with_error_code(e, AptosTapErrorCode::StorageError))?; - // Generate a key corresponding to this IP address and the current day. - let (key, seconds_until_next_day) = self.get_key_and_secs_until_next_day(&data.source_ip); + // Generate a key corresponding to this identifier and the current day. + let key_prefix = self.ratelimit_key_provider.ratelimit_key_prefix(); + let key_value = self + .ratelimit_key_provider + .ratelimit_key_value(&data) + .await?; + let (key, seconds_until_next_day) = + self.get_key_and_secs_until_next_day(key_prefix, &key_value); - // Get the value for the key, indicating how many non-500 requests we - // have serviced for this it today. + // Get the value for the key, indicating how many non-500 requests we have + // serviced for it today. let limit_value: Option = conn.get(&key).await.map_err(|e| { AptosTapError::new_with_error_code( format!("Failed to get value for redis key {}: {}", key, e), @@ -183,18 +251,16 @@ impl CheckerTrait for RedisRatelimitChecker { ) })?; - // If the limit value is greater than what we allow per day, signal - // that we should reject this request. - if let Some(rejection_reason) = - self.check_limit_value(&data, limit_value, seconds_until_next_day) + // If the limit value is greater than what we allow per day, signal that we + // should reject this request. + if let Some(rejection_reason) = self.check_limit_value(limit_value, seconds_until_next_day) { return Ok(vec![rejection_reason]); } - // Atomically increment the counter for the given IP, creating it and - // setting the expiration time if it doesn't already exist. + // Atomically increment the counter for the given key, creating it and setting + // the expiration time if it doesn't already exist. if !dry_run { - // If the limit value already exists, just increment. let incremented_limit_value = match limit_value { Some(_) => conn.incr(&key, 1).await.map_err(|e| { AptosTapError::new_with_error_code( @@ -228,7 +294,7 @@ impl CheckerTrait for RedisRatelimitChecker { // Check limit again, to ensure there wasn't a get / set race. if let Some(rejection_reason) = - self.check_limit_value(&data, Some(incremented_limit_value), seconds_until_next_day) + self.check_limit_value(Some(incremented_limit_value), seconds_until_next_day) { return Ok(vec![rejection_reason]); } @@ -237,8 +303,8 @@ impl CheckerTrait for RedisRatelimitChecker { Ok(vec![]) } - /// All we have to do here is decrement the counter if the request was a - /// failure due to something wrong on our end. + /// All we have to do here is decrement the counter if the request was a failure due + /// to something wrong on our end. async fn complete(&self, data: CompleteData) -> Result<(), AptosTapError> { if !data.response_is_500 { return Ok(()); @@ -249,8 +315,15 @@ impl CheckerTrait for RedisRatelimitChecker { .await .map_err(|e| AptosTapError::new_with_error_code(e, AptosTapErrorCode::StorageError))?; - // Generate a key corresponding to this IP address and the current day. - let (key, _) = self.get_key_and_secs_until_next_day(&data.checker_data.source_ip); + // Generate a key corresponding to this identifier and the current day. In the + // JWT case we re-verify the JWT. This is inefficient, but these failures are + // extremely rare so I don't refactor for now. + let key_prefix = self.ratelimit_key_provider.ratelimit_key_prefix(); + let key_value = self + .ratelimit_key_provider + .ratelimit_key_value(&data.checker_data) + .await?; + let (key, _) = self.get_key_and_secs_until_next_day(key_prefix, &key_value); conn.decr(&key, 1).await.map_err(|e| { AptosTapError::new_with_error_code( @@ -262,6 +335,6 @@ impl CheckerTrait for RedisRatelimitChecker { } fn cost(&self) -> u8 { - 50 + 100 } } diff --git a/crates/aptos-faucet/core/src/endpoints/errors.rs b/crates/aptos-faucet/core/src/endpoints/errors.rs index db18257a73b8c..9caab60b0e111 100644 --- a/crates/aptos-faucet/core/src/endpoints/errors.rs +++ b/crates/aptos-faucet/core/src/endpoints/errors.rs @@ -64,7 +64,7 @@ impl AptosTapError { pub fn status_and_retry_after(&self) -> (StatusCode, Option) { let (mut status_code, mut retry_after) = (self.error_code.status(), None); for rejection_reason in &self.rejection_reasons { - if rejection_reason.code == RejectionReasonCode::IpUsageLimitExhausted { + if rejection_reason.code == RejectionReasonCode::UsageLimitExhausted { status_code = StatusCode::TOO_MANY_REQUESTS; retry_after = rejection_reason.retry_after; break; @@ -134,6 +134,9 @@ pub enum AptosTapErrorCode { /// The user tried to call an endpoint that is not enabled. EndpointNotEnabled = 45, + /// The user provided an invalid auth token. + AuthTokenInvalid = 46, + /// Failed when making requests to the Aptos API. AptosApiError = 50, @@ -170,7 +173,8 @@ impl AptosTapErrorCode { | AptosTapErrorCode::EndpointNotEnabled => StatusCode::BAD_REQUEST, AptosTapErrorCode::Rejected | AptosTapErrorCode::SourceIpMissing - | AptosTapErrorCode::TransactionFailed => StatusCode::FORBIDDEN, + | AptosTapErrorCode::TransactionFailed + | AptosTapErrorCode::AuthTokenInvalid => StatusCode::FORBIDDEN, AptosTapErrorCode::AptosApiError | AptosTapErrorCode::TransactionTimedOut | AptosTapErrorCode::SerializationError @@ -233,8 +237,8 @@ pub enum RejectionReasonCode { /// Account already has funds. AccountAlreadyExists = 100, - /// IP has exhausted its usage limit. - IpUsageLimitExhausted = 101, + /// Key (IP / Firebase UID) has exhausted its usage limit. + UsageLimitExhausted = 101, /// IP is in the blocklist. IpInBlocklist = 102, diff --git a/crates/aptos-faucet/core/src/endpoints/fund.rs b/crates/aptos-faucet/core/src/endpoints/fund.rs index f43ded751a971..c916e00f63390 100644 --- a/crates/aptos-faucet/core/src/endpoints/fund.rs +++ b/crates/aptos-faucet/core/src/endpoints/fund.rs @@ -9,6 +9,7 @@ use crate::{ bypasser::{Bypasser, BypasserTrait}, checkers::{Checker, CheckerData, CheckerTrait, CompleteData}, endpoints::AptosTapErrorCode, + firebase_jwt::jwt_sub, funder::{Funder, FunderTrait}, helpers::{get_current_time_secs, transaction_hashes}, }; @@ -307,6 +308,7 @@ impl FundApiComponents { // Include some additional logging that the logging middleware doesn't do. info!( source_ip = checker_data.source_ip, + jwt_sub = jwt_sub(checker_data.headers.clone()).ok(), address = checker_data.receiver, requested_amount = fund_request.amount, txn_hashes = txn_hashes, diff --git a/crates/aptos-faucet/core/src/firebase_jwt.rs b/crates/aptos-faucet/core/src/firebase_jwt.rs new file mode 100644 index 0000000000000..99047fd44b8f8 --- /dev/null +++ b/crates/aptos-faucet/core/src/firebase_jwt.rs @@ -0,0 +1,113 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::endpoints::{AptosTapError, AptosTapErrorCode}; +use anyhow::Result; +use firebase_token::JwkAuth; +use poem::http::{header::AUTHORIZATION, HeaderMap}; +use serde::{Deserialize, Serialize}; +use std::sync::Arc; + +pub const X_IS_JWT_HEADER: &str = "x-is-jwt"; + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct FirebaseJwtVerifierConfig { + pub identity_platform_gcp_project: String, +} + +/// This verifies that the value in the Authorization header is a valid Firebase JWT. +/// Since we already have achecker that looks for API keys using the Authorization +/// header, we mandate that a `x-is-jwt` header is present as well. +pub struct FirebaseJwtVerifier { + pub jwt_verifier: JwkAuth, +} + +impl FirebaseJwtVerifier { + pub async fn new(config: FirebaseJwtVerifierConfig) -> Result { + let jwt_verifier = JwkAuth::new(config.identity_platform_gcp_project).await; + Ok(Self { jwt_verifier }) + } + + /// First, we mandate that the caller indicated that they're including a JWT by + /// checking for the presence of X_IS_JWT_HEADER. If they didn't include this + /// header, we reject them immediately. We need this because we already have a + /// checker that looks for API keys using the Authorization header, and we want + /// to differentiate these two cases. + /// + /// If they did include X_IS_JWT_HEADER and the Authorization header was present + /// and well-formed, we extract the token from the Authorization header and verify + /// it with Firebase. If the token is invalid, we reject them. If it is valid, we + /// return the UID (from the sub field). + pub async fn validate_jwt(&self, headers: Arc) -> Result { + let auth_token = jwt_sub(headers)?; + + let verify = self.jwt_verifier.verify::(&auth_token); + let token_data = match verify.await { + Some(token_data) => token_data, + None => { + return Err(AptosTapError::new( + "Failed to verify JWT token".to_string(), + AptosTapErrorCode::AuthTokenInvalid, + )); + }, + }; + let claims = token_data.claims; + + if !claims.email_verified { + return Err(AptosTapError::new( + "The JWT token is not verified".to_string(), + AptosTapErrorCode::AuthTokenInvalid, + )); + } + + Ok(claims.sub) + } +} + +/// Returns the sub field from a JWT if it is present (the Firebase UID). +/// The X_IS_JWT_HEADER must be present and the value must be "true". +pub fn jwt_sub(headers: Arc) -> Result { + let is_jwt = headers + .get(X_IS_JWT_HEADER) + .and_then(|v| v.to_str().ok()) + .map(|v| v.eq_ignore_ascii_case("true")) + .ok_or_else(|| { + AptosTapError::new( + format!( + "The {} header must be present and set to 'true'", + X_IS_JWT_HEADER + ), + AptosTapErrorCode::AuthTokenInvalid, + ) + })?; + + if !is_jwt { + return Err(AptosTapError::new( + format!("The {} header must be set to 'true'", X_IS_JWT_HEADER), + AptosTapErrorCode::AuthTokenInvalid, + )); + } + + match headers + .get(AUTHORIZATION) + .and_then(|v| v.to_str().ok()) + .and_then(|v| v.split_whitespace().nth(1)) + { + Some(auth_token) => Ok(auth_token.to_string()), + None => Err(AptosTapError::new( + "Either the Authorization header is missing or it is not in the form of 'Bearer '".to_string(), + AptosTapErrorCode::AuthTokenInvalid, + )), + } +} + +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] +pub struct JwtClaims { + pub aud: String, + pub exp: i64, + pub iss: String, + pub sub: String, + pub iat: i64, + pub email: String, + pub email_verified: bool, +} diff --git a/crates/aptos-faucet/core/src/lib.rs b/crates/aptos-faucet/core/src/lib.rs index 65e2b0b8b832e..382d1a24b83c2 100644 --- a/crates/aptos-faucet/core/src/lib.rs +++ b/crates/aptos-faucet/core/src/lib.rs @@ -5,6 +5,7 @@ pub mod bypasser; pub mod checkers; pub mod common; pub mod endpoints; +pub mod firebase_jwt; pub mod funder; pub mod helpers; pub mod middleware; diff --git a/crates/aptos-faucet/core/src/server/run.rs b/crates/aptos-faucet/core/src/server/run.rs index b5b80e6440377..d210eceb3f857 100644 --- a/crates/aptos-faucet/core/src/server/run.rs +++ b/crates/aptos-faucet/core/src/server/run.rs @@ -388,12 +388,12 @@ mod test { types::{account_address::AccountAddress, transaction::authenticator::AuthenticationKey}, }; use once_cell::sync::OnceCell; - use poem::http::header::{AUTHORIZATION, CONTENT_TYPE, REFERER}; use poem_openapi::types::{ParseFromJSON, ToJSON}; use rand::{ rngs::{OsRng, StdRng}, Rng, SeedableRng, }; + use reqwest::header::{AUTHORIZATION, CONTENT_TYPE, REFERER}; use std::{collections::HashSet, io::Write, str::FromStr, time::Duration}; use tokio::task::JoinHandle; @@ -685,7 +685,7 @@ mod test { .into_iter() .map(|r| r.get_code()) .collect(); - assert!(rejection_reason_codes.contains(&RejectionReasonCode::IpUsageLimitExhausted)); + assert!(rejection_reason_codes.contains(&RejectionReasonCode::UsageLimitExhausted)); Ok(()) } @@ -836,7 +836,9 @@ mod test { // Assert that the account exists now with the expected balance. let response = aptos_node_api_client - .view_account_balance(AccountAddress::from_str(&fund_request.address.unwrap()).unwrap()) + .view_apt_account_balance( + AccountAddress::from_str(&fund_request.address.unwrap()).unwrap(), + ) .await?; assert_eq!(response.into_inner(), 10); diff --git a/crates/aptos-faucet/integration-tests/main.py b/crates/aptos-faucet/integration-tests/main.py index fd8006ffc0095..80e6429500516 100644 --- a/crates/aptos-faucet/integration-tests/main.py +++ b/crates/aptos-faucet/integration-tests/main.py @@ -66,6 +66,11 @@ def parse_args(): 'from. If "custom", --tag must be set.' ), ) + parser.add_argument( + "--skip-node", + action="store_true", + help="Skip running the node. You must run it yourself and copy the mint key yourself.", + ) parser.add_argument( "--tag", help=( @@ -114,20 +119,22 @@ def main(): # something is listening at the expected port. check_redis_is_running() - # Run a node and wait for it to start up. - container_name = run_node( - network, args.image_repo_with_project, args.external_test_dir - ) - wait_for_startup(container_name, args.base_startup_timeout) + if not args.skip_node: + # Run a node and wait for it to start up. + container_name = run_node( + network, args.image_repo_with_project, args.external_test_dir + ) + wait_for_startup(container_name, args.base_startup_timeout) - # Copy the mint key from the node to where the integration tests expect it to be. - copy_mint_key(args.external_test_dir) + # Copy the mint key from the node to where the integration tests expect it to be. + copy_mint_key(args.external_test_dir) # Build and run the faucet integration tests. run_faucet_integration_tests() - # Stop the localnet. - stop_node(container_name) + if not args.skip_node: + # Stop the localnet. + stop_node(container_name) return True From 807a2dbb186f088f347d568e0de63b1da6a6129e Mon Sep 17 00:00:00 2001 From: Stelian Ionescu Date: Tue, 10 Dec 2024 15:45:02 -0500 Subject: [PATCH 35/78] Forge: mark runner and validator pods as non-evictable --- testsuite/forge-test-runner-template.yaml | 2 ++ .../backend/k8s/helm-values/aptos-node-default-values.yaml | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/testsuite/forge-test-runner-template.yaml b/testsuite/forge-test-runner-template.yaml index 1d856ca269c04..2a4dc3abfdc46 100644 --- a/testsuite/forge-test-runner-template.yaml +++ b/testsuite/forge-test-runner-template.yaml @@ -9,6 +9,8 @@ metadata: forge-image-tag: {FORGE_IMAGE_TAG} forge-test-suite: {FORGE_TEST_SUITE} forge-username: {FORGE_USERNAME} + annotations: + "cluster-autoscaler.kubernetes.io/safe-to-evict": "false" spec: restartPolicy: Never serviceAccountName: forge diff --git a/testsuite/forge/src/backend/k8s/helm-values/aptos-node-default-values.yaml b/testsuite/forge/src/backend/k8s/helm-values/aptos-node-default-values.yaml index 4487bd3b70c3c..4e6023da4bf87 100644 --- a/testsuite/forge/src/backend/k8s/helm-values/aptos-node-default-values.yaml +++ b/testsuite/forge/src/backend/k8s/helm-values/aptos-node-default-values.yaml @@ -11,6 +11,8 @@ validator: enable_storage_sharding: true indexer_db_config: enable_event: true + podAnnotations: + "cluster-autoscaler.kubernetes.io/safe-to-evict": "false" fullnode: # at most one VFN per validator, depending on numFullnodeGroups @@ -28,6 +30,8 @@ fullnode: enable_storage_sharding: true indexer_db_config: enable_event: true + podAnnotations: + "cluster-autoscaler.kubernetes.io/safe-to-evict": "false" service: validator: From eb23d6f5ab0436c6dcfd6b58a135200c61bb3863 Mon Sep 17 00:00:00 2001 From: Junkil Park Date: Tue, 10 Dec 2024 21:04:03 -0800 Subject: [PATCH 36/78] Enable partial_governance_voting (#15553) - Enable the feature flag partial_governance_voting by default - Adjust the Move unit tests --- .../sources/main.move | 10 ++++++--- aptos-move/e2e-move-tests/src/tests/vote.rs | 21 +++++++++++++------ .../sources/aptos_governance.move | 21 +++++++++++++++---- types/src/on_chain_config/aptos_features.rs | 1 + 4 files changed, 40 insertions(+), 13 deletions(-) diff --git a/aptos-move/e2e-move-tests/src/tests/vote.data/enable_partial_governance_voting/sources/main.move b/aptos-move/e2e-move-tests/src/tests/vote.data/enable_partial_governance_voting/sources/main.move index 60b8843709463..99bb9161506e3 100644 --- a/aptos-move/e2e-move-tests/src/tests/vote.data/enable_partial_governance_voting/sources/main.move +++ b/aptos-move/e2e-move-tests/src/tests/vote.data/enable_partial_governance_voting/sources/main.move @@ -2,11 +2,15 @@ script { use aptos_framework::aptos_governance; use std::features; - fun main(core_resources: &signer) { + fun main(core_resources: &signer, enable_partial_governance_voting: bool) { let framework_signer = aptos_governance::get_signer_testnet_only(core_resources, @aptos_framework); - aptos_governance::initialize_partial_voting(&framework_signer); let feature = features::get_partial_governance_voting(); - features::change_feature_flags_for_next_epoch(&framework_signer, vector[feature], vector[]); + if (enable_partial_governance_voting) { + aptos_governance::initialize_partial_voting(&framework_signer); + features::change_feature_flags_for_next_epoch(&framework_signer, vector[feature], vector[]); + } else { + features::change_feature_flags_for_next_epoch(&framework_signer, vector[], vector[feature]); + }; aptos_governance::force_end_epoch(&framework_signer); } } diff --git a/aptos-move/e2e-move-tests/src/tests/vote.rs b/aptos-move/e2e-move-tests/src/tests/vote.rs index ebba2e3654ef9..a5d9f10ff0705 100644 --- a/aptos-move/e2e-move-tests/src/tests/vote.rs +++ b/aptos-move/e2e-move-tests/src/tests/vote.rs @@ -6,6 +6,7 @@ use crate::{ tests::common, MoveHarness, }; use aptos_types::account_address::AccountAddress; +use move_core_types::transaction_argument::TransactionArgument; use once_cell::sync::Lazy; use std::collections::BTreeMap; @@ -33,6 +34,17 @@ fn test_vote() { assert_success!(setup_staking(&mut harness, &validator_2, stake_amount_2)); assert_success!(increase_lockup(&mut harness, &validator_2)); + // Disable partial governance voting. + let core_resources = + harness.new_account_at(AccountAddress::from_hex_literal("0xA550C18").unwrap()); + let script_code = PROPOSAL_SCRIPTS + .get("enable_partial_governance_voting") + .expect("proposal script should be built"); + let txn = harness.create_script(&core_resources, script_code.clone(), vec![], vec![ + TransactionArgument::Bool(false), + ]); + assert_success!(harness.run(txn)); + let mut proposal_id: u64 = 0; assert_success!(create_proposal_v2( &mut harness, @@ -59,12 +71,9 @@ fn test_vote() { ); // Enable partial governance voting. In production it requires governance. - let core_resources = - harness.new_account_at(AccountAddress::from_hex_literal("0xA550C18").unwrap()); - let script_code = PROPOSAL_SCRIPTS - .get("enable_partial_governance_voting") - .expect("proposal script should be built"); - let txn = harness.create_script(&core_resources, script_code.clone(), vec![], vec![]); + let txn = harness.create_script(&core_resources, script_code.clone(), vec![], vec![ + TransactionArgument::Bool(true), + ]); assert_success!(harness.run(txn)); // If a voter has already voted on a proposal before partial voting is enabled, the voter cannot vote on the proposal again. diff --git a/aptos-move/framework/aptos-framework/sources/aptos_governance.move b/aptos-move/framework/aptos-framework/sources/aptos_governance.move index f44ba1b3239fc..5d8d0e99b0598 100644 --- a/aptos-move/framework/aptos-framework/sources/aptos_governance.move +++ b/aptos-move/framework/aptos-framework/sources/aptos_governance.move @@ -811,7 +811,7 @@ module aptos_framework::aptos_governance { multi_step: bool, use_generic_resolve_function: bool, ) acquires ApprovedExecutionHashes, GovernanceConfig, GovernanceResponsbility, VotingRecords, VotingRecordsV2, GovernanceEvents { - setup_voting(&aptos_framework, &proposer, &yes_voter, &no_voter); + setup_partial_voting(&aptos_framework, &proposer, &yes_voter, &no_voter); let execution_hash = vector::empty(); vector::push_back(&mut execution_hash, 1); @@ -898,7 +898,7 @@ module aptos_framework::aptos_governance { no_voter: signer, multi_step: bool, ) acquires ApprovedExecutionHashes, GovernanceConfig, GovernanceResponsbility, VotingRecords, VotingRecordsV2, GovernanceEvents { - setup_voting(&aptos_framework, &proposer, &yes_voter, &no_voter); + setup_partial_voting(&aptos_framework, &proposer, &yes_voter, &no_voter); create_proposal_for_test(&proposer, multi_step); vote(&yes_voter, signer::address_of(&yes_voter), 0, true); @@ -1134,6 +1134,7 @@ module aptos_framework::aptos_governance { voter_1: signer, voter_2: signer, ) acquires ApprovedExecutionHashes, GovernanceConfig, GovernanceResponsbility, VotingRecords, VotingRecordsV2, GovernanceEvents { + features::change_feature_flags_for_testing(&aptos_framework, vector[], vector[features::get_partial_governance_voting()]); setup_voting(&aptos_framework, &proposer, &voter_1, &voter_2); let execution_hash = vector::empty(); vector::push_back(&mut execution_hash, 1); @@ -1171,7 +1172,7 @@ module aptos_framework::aptos_governance { voter_1: signer, voter_2: signer, ) acquires GovernanceConfig, GovernanceResponsbility, VotingRecords, VotingRecordsV2, GovernanceEvents { - setup_voting_with_initialized_stake(&aptos_framework, &proposer, &voter_1, &voter_2); + setup_partial_voting_with_initialized_stake(&aptos_framework, &proposer, &voter_1, &voter_2); let execution_hash = vector::empty(); vector::push_back(&mut execution_hash, 1); let proposer_addr = signer::address_of(&proposer); @@ -1299,6 +1300,18 @@ module aptos_framework::aptos_governance { stake::end_epoch(); } + #[test_only] + public fun setup_partial_voting_with_initialized_stake( + aptos_framework: &signer, + proposer: &signer, + yes_voter: &signer, + no_voter: &signer, + ) acquires GovernanceResponsbility { + initialize_partial_voting(aptos_framework); + features::change_feature_flags_for_testing(aptos_framework, vector[features::get_partial_governance_voting()], vector[]); + setup_voting_with_initialized_stake(aptos_framework, proposer, yes_voter, no_voter); + } + #[test_only] public fun setup_partial_voting( aptos_framework: &signer, @@ -1340,7 +1353,7 @@ module aptos_framework::aptos_governance { yes_voter: signer, no_voter: signer, ) acquires GovernanceResponsbility, GovernanceConfig, ApprovedExecutionHashes, VotingRecords, VotingRecordsV2, GovernanceEvents { - setup_voting(&aptos_framework, &proposer, &yes_voter, &no_voter); + setup_partial_voting(&aptos_framework, &proposer, &yes_voter, &no_voter); create_proposal_for_test(&proposer, true); vote(&yes_voter, signer::address_of(&yes_voter), 0, true); diff --git a/types/src/on_chain_config/aptos_features.rs b/types/src/on_chain_config/aptos_features.rs index 70bc4f18aa546..2247a60edb152 100644 --- a/types/src/on_chain_config/aptos_features.rs +++ b/types/src/on_chain_config/aptos_features.rs @@ -122,6 +122,7 @@ impl FeatureFlag { FeatureFlag::BLS12_381_STRUCTURES, FeatureFlag::ED25519_PUBKEY_VALIDATE_RETURN_FALSE_WRONG_LENGTH, FeatureFlag::STRUCT_CONSTRUCTORS, + FeatureFlag::PARTIAL_GOVERNANCE_VOTING, FeatureFlag::SIGNATURE_CHECKER_V2, FeatureFlag::STORAGE_SLOT_METADATA, FeatureFlag::CHARGE_INVARIANT_VIOLATION, From b66813724b13c4e16f5cb115d6c3d3797dc843af Mon Sep 17 00:00:00 2001 From: "Daniel Porteous (dport)" Date: Wed, 11 Dec 2024 10:21:32 -0800 Subject: [PATCH 37/78] [CLI] Direct users to dev docs for testnet faucet, improve messaging (#15545) --- Cargo.lock | 31 ++++++++++++ Cargo.toml | 1 + crates/aptos/CHANGELOG.md | 1 + crates/aptos/Cargo.toml | 1 + crates/aptos/src/common/init.rs | 83 +++++++++++++++++++++++--------- crates/aptos/src/common/types.rs | 54 ++++++++++++++++----- crates/aptos/src/test/mod.rs | 6 ++- 7 files changed, 140 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c3cef51aea56f..027aa2b39d7b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -347,6 +347,7 @@ dependencies = [ "move-symbol-pool", "move-unit-test", "move-vm-runtime", + "open", "pathsearch", "poem", "processor", @@ -9986,6 +9987,15 @@ dependencies = [ "ipnet", ] +[[package]] +name = "is-docker" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "928bae27f42bc99b60d9ac7334e3a21d10ad8f1835a4e12ec3ec0464765ed1b3" +dependencies = [ + "once_cell", +] + [[package]] name = "is-terminal" version = "0.4.10" @@ -9997,6 +10007,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "is-wsl" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "173609498df190136aa7dea1a91db051746d339e18476eed5ca40521f02d7aa5" +dependencies = [ + "is-docker", + "once_cell", +] + [[package]] name = "is_debug" version = "1.0.1" @@ -12440,6 +12460,17 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +[[package]] +name = "open" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ecd52f0b8d15c40ce4820aa251ed5de032e5d91fab27f7db2f40d42a8bdf69c" +dependencies = [ + "is-wsl", + "libc", + "pathdiff", +] + [[package]] name = "openssl" version = "0.10.66" diff --git a/Cargo.toml b/Cargo.toml index 711e90130c8c9..bca2044043628 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -670,6 +670,7 @@ num-derive = "0.3.3" num-integer = "0.1.42" num-traits = "0.2.15" once_cell = "1.10.0" +open = "5.3.1" ordered-float = "3.9.1" ouroboros = "0.15.6" owo-colors = "3.5.0" diff --git a/crates/aptos/CHANGELOG.md b/crates/aptos/CHANGELOG.md index 6dc1d8fd14967..cbde53c60f9ac 100644 --- a/crates/aptos/CHANGELOG.md +++ b/crates/aptos/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to the Aptos CLI will be captured in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) and the format set out by [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). # Unreleased +- [**Breaking Change**] `aptos init` and `aptos account fund-with-faucet` no longer work directly with testnet, you must now use the minting page at [Aptos Learn](https://aptos.dev/network/faucet). ## [4.7.0] - 2024/12/10 - [`Fix`] CLI config should not always require a private key field to be present. diff --git a/crates/aptos/Cargo.toml b/crates/aptos/Cargo.toml index 99797d06b3113..fbdd44f377aa5 100644 --- a/crates/aptos/Cargo.toml +++ b/crates/aptos/Cargo.toml @@ -84,6 +84,7 @@ move-prover-boogie-backend = { workspace = true } move-symbol-pool = { workspace = true } move-unit-test = { workspace = true, features = ["debugging"] } move-vm-runtime = { workspace = true, features = ["testing"] } +open = { workspace = true } pathsearch = { workspace = true } poem = { workspace = true } # We set default-features to false so we don't onboard the libpq dep. See more here: diff --git a/crates/aptos/src/common/init.rs b/crates/aptos/src/common/init.rs index 9a416e274b5b9..2dee996cbd185 100644 --- a/crates/aptos/src/common/init.rs +++ b/crates/aptos/src/common/init.rs @@ -1,13 +1,15 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 +use super::types::FaucetOptions; use crate::{ account::key_rotation::lookup_address, common::{ types::{ - account_address_from_public_key, CliCommand, CliConfig, CliError, CliTypedResult, - ConfigSearchMode, EncodingOptions, HardwareWalletOptions, PrivateKeyInputOptions, - ProfileConfig, ProfileOptions, PromptOptions, RngArgs, DEFAULT_PROFILE, + account_address_from_public_key, get_mint_site_url, CliCommand, CliConfig, CliError, + CliTypedResult, ConfigSearchMode, EncodingOptions, HardwareWalletOptions, + PrivateKeyInputOptions, ProfileConfig, ProfileOptions, PromptOptions, RngArgs, + DEFAULT_PROFILE, }, utils::{ explorer_account_link, fund_account, prompt_yes_with_override, read_line, @@ -49,14 +51,8 @@ pub struct InitTool { #[clap(long)] pub rest_url: Option, - /// URL for the Faucet endpoint - #[clap(long)] - pub faucet_url: Option, - - /// Auth token, if we're using the faucet. This is only used this time, we don't - /// store it. - #[clap(long, env)] - pub faucet_auth_token: Option, + #[clap(flatten)] + pub faucet_options: FaucetOptions, /// Whether to skip the faucet for a non-faucet endpoint #[clap(long)] @@ -129,6 +125,19 @@ impl CliCommand<()> for InitTool { } }; + if network != Network::Custom { + if self.rest_url.is_some() { + return Err(CliError::CommandArgumentError( + "--rest-url can only be used with --network custom".to_string(), + )); + } + if self.faucet_options.faucet_url.is_some() { + return Err(CliError::CommandArgumentError( + "--faucet-url can only be used with --network custom".to_string(), + )); + } + } + // Ensure the config contains the network used profile_config.network = Some(network); @@ -142,8 +151,12 @@ impl CliCommand<()> for InitTool { Network::Testnet => { profile_config.rest_url = Some("https://fullnode.testnet.aptoslabs.com".to_string()); - profile_config.faucet_url = - Some("https://faucet.testnet.aptoslabs.com".to_string()); + // The faucet in testnet is only accessible with some kind of bypass. + // For regular users this can only really mean an auth token. So if + // there is no auth token set, we don't set the faucet URL. If the user + // is confident they want to use the testnet faucet without a token + // they can set it manually with `--network custom` and `--faucet-url`. + profile_config.faucet_url = None; }, Network::Devnet => { profile_config.rest_url = Some("https://fullnode.devnet.aptoslabs.com".to_string()); @@ -323,7 +336,7 @@ impl CliCommand<()> for InitTool { client, Url::parse(faucet_url) .map_err(|err| CliError::UnableToParse("rest_url", err.to_string()))?, - self.faucet_auth_token.as_deref(), + self.faucet_options.faucet_auth_token.as_deref(), address, NUM_DEFAULT_OCTAS, ) @@ -331,9 +344,9 @@ impl CliCommand<()> for InitTool { eprintln!("Account {} funded successfully", address); } } else if account_exists { - eprintln!("Account {} has been already found onchain", address); - } else if network == Network::Mainnet { - eprintln!("Account {} does not exist, you will need to create and fund the account by transferring funds from another account", address); + eprintln!("Account {} has been already found on chain", address); + } else if network == Network::Mainnet || network == Network::Testnet { + // Do nothing, we print information later. } else { eprintln!("Account {} has been initialized locally, but you must transfer coins to it to create the account onchain", address); } @@ -348,16 +361,42 @@ impl CliCommand<()> for InitTool { .expect("Must have profiles, as created above") .insert(profile_name.to_string(), profile_config); config.save()?; + let profile_name = self .profile_options .profile_name() .unwrap_or(DEFAULT_PROFILE); + eprintln!( - "\n---\nAptos CLI is now set up for account {} as profile {}!\n See the account here: {}\n Run `aptos --help` for more information about commands", - address, - profile_name, - explorer_account_link(address, Some(network)) + "\n---\nAptos CLI is now set up for account {} as profile {}!\n---\n", + address, profile_name, ); + + match network { + Network::Mainnet => { + eprintln!("The account has not been created on chain yet, you will need to create and fund the account by transferring funds from another account"); + }, + Network::Testnet => { + let mint_site_url = get_mint_site_url(Some(address)); + eprintln!("The account has not been created on chain yet. To create the account and get APT on testnet you must visit {}", mint_site_url); + // We don't use `prompt_yes_with_override` here because we only want to + // automatically open the minting site if they're in an interactive setting. + if !self.prompt_options.assume_yes { + eprint!("Press [Enter] to go there now > "); + read_line("Confirmation")?; + open::that(&mint_site_url).map_err(|err| { + CliError::UnexpectedError(format!("Failed to open minting site: {}", err)) + })?; + } + }, + wildcard => { + eprintln!( + "See the account here: {}", + explorer_account_link(address, Some(wildcard)) + ); + }, + } + Ok(()) } } @@ -399,7 +438,7 @@ impl InitTool { let faucet_url = if self.skip_faucet { eprintln!("Not configuring a faucet because --skip-faucet was provided"); None - } else if let Some(ref faucet_url) = self.faucet_url { + } else if let Some(ref faucet_url) = self.faucet_options.faucet_url { eprintln!("Using command line argument for faucet URL {}", faucet_url); Some(faucet_url.to_string()) } else { diff --git a/crates/aptos/src/common/types.rs b/crates/aptos/src/common/types.rs index 13c600ba209f8..3feec4ebcb12d 100644 --- a/crates/aptos/src/common/types.rs +++ b/crates/aptos/src/common/types.rs @@ -1514,12 +1514,12 @@ pub struct ChangeSummary { pub struct FaucetOptions { /// URL for the faucet endpoint e.g. `https://faucet.devnet.aptoslabs.com` #[clap(long)] - faucet_url: Option, + pub faucet_url: Option, /// Auth token to bypass faucet ratelimits. You can also set this as an environment /// variable with FAUCET_AUTH_TOKEN. #[clap(long, env)] - faucet_auth_token: Option, + pub faucet_auth_token: Option, } impl FaucetOptions { @@ -1530,19 +1530,38 @@ impl FaucetOptions { } } - fn faucet_url(&self, profile: &ProfileOptions) -> CliTypedResult { + fn faucet_url(&self, profile_options: &ProfileOptions) -> CliTypedResult { if let Some(ref faucet_url) = self.faucet_url { - Ok(faucet_url.clone()) - } else if let Some(Some(url)) = CliConfig::load_profile( - profile.profile_name(), + return Ok(faucet_url.clone()); + } + let profile = CliConfig::load_profile( + profile_options.profile_name(), ConfigSearchMode::CurrentDirAndParents, - )? - .map(|profile| profile.faucet_url) - { - reqwest::Url::parse(&url) - .map_err(|err| CliError::UnableToParse("config faucet_url", err.to_string())) - } else { - Err(CliError::CommandArgumentError("No faucet given. Please add --faucet-url or add a faucet URL to the .aptos/config.yaml for the current profile".to_string())) + )?; + let profile = match profile { + Some(profile) => profile, + None => { + return Err(CliError::CommandArgumentError(format!( + "Profile \"{}\" not found.", + profile_options.profile_name().unwrap_or(DEFAULT_PROFILE) + ))) + }, + }; + + match profile.faucet_url { + Some(url) => reqwest::Url::parse(&url) + .map_err(|err| CliError::UnableToParse("config faucet_url", err.to_string())), + None => match profile.network { + Some(Network::Mainnet) => { + Err(CliError::CommandArgumentError("There is no faucet for mainnet. Please create and fund the account by transferring funds from another account. If you are confident you want to use a faucet, set --faucet-url or add a faucet URL to .aptos/config.yaml for the current profile".to_string())) + }, + Some(Network::Testnet) => { + Err(CliError::CommandArgumentError(format!("To get testnet APT you must visit {}. If you are confident you want to use a faucet programmatically, set --faucet-url or add a faucet URL to .aptos/config.yaml for the current profile", get_mint_site_url(None)))) + }, + _ => { + Err(CliError::CommandArgumentError("No faucet given. Please set --faucet-url or add a faucet URL to .aptos/config.yaml for the current profile".to_string())) + }, + }, } } @@ -2386,3 +2405,12 @@ pub struct ChunkedPublishOption { #[clap(long, default_value_t = CHUNK_SIZE_IN_BYTES)] pub(crate) chunk_size: usize, } + +/// For minting testnet APT. +pub fn get_mint_site_url(address: Option) -> String { + let params = match address { + Some(address) => format!("?address={}", address.to_standard_string()), + None => "".to_string(), + }; + format!("https://aptos.dev/network/faucet{}", params) +} diff --git a/crates/aptos/src/test/mod.rs b/crates/aptos/src/test/mod.rs index eee3d6e19a5d9..206fb5e80a64f 100644 --- a/crates/aptos/src/test/mod.rs +++ b/crates/aptos/src/test/mod.rs @@ -559,8 +559,10 @@ impl CliTestFramework { InitTool { network: Some(Network::Custom), rest_url: Some(self.endpoint.clone()), - faucet_url: Some(self.faucet_endpoint.clone()), - faucet_auth_token: None, + faucet_options: FaucetOptions { + faucet_url: Some(self.faucet_endpoint.clone()), + faucet_auth_token: None, + }, rng_args: RngArgs::from_seed([0; 32]), private_key_options: PrivateKeyInputOptions::from_private_key(private_key)?, profile_options: Default::default(), From ab6d0ee1f3ceb295d152d4dd1a07a6cb9c5c678e Mon Sep 17 00:00:00 2001 From: "Daniel Porteous (dport)" Date: Wed, 11 Dec 2024 11:54:23 -0800 Subject: [PATCH 38/78] [CLI] Bump version to 5.0.0 (#15562) --- Cargo.lock | 2 +- crates/aptos/CHANGELOG.md | 3 ++- crates/aptos/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 027aa2b39d7b5..f2757456dbe81 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -275,7 +275,7 @@ dependencies = [ [[package]] name = "aptos" -version = "4.7.0" +version = "5.0.0" dependencies = [ "anyhow", "aptos-api-types", diff --git a/crates/aptos/CHANGELOG.md b/crates/aptos/CHANGELOG.md index cbde53c60f9ac..353ac9f1f9458 100644 --- a/crates/aptos/CHANGELOG.md +++ b/crates/aptos/CHANGELOG.md @@ -3,8 +3,9 @@ All notable changes to the Aptos CLI will be captured in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) and the format set out by [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). # Unreleased -- [**Breaking Change**] `aptos init` and `aptos account fund-with-faucet` no longer work directly with testnet, you must now use the minting page at [Aptos Learn](https://aptos.dev/network/faucet). +## [5.0.0] - 2024/12/11 +- [**Breaking Change**] `aptos init` and `aptos account fund-with-faucet` no longer work directly with testnet, you must now use the minting page at the [Aptos dev docs](https://aptos.dev/network/faucet). ## [4.7.0] - 2024/12/10 - [`Fix`] CLI config should not always require a private key field to be present. diff --git a/crates/aptos/Cargo.toml b/crates/aptos/Cargo.toml index fbdd44f377aa5..9970cad41819d 100644 --- a/crates/aptos/Cargo.toml +++ b/crates/aptos/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "aptos" description = "Aptos tool for management of nodes and interacting with the blockchain" -version = "4.7.0" +version = "5.0.0" # Workspace inherited keys authors = { workspace = true } From 1dab35285b1679245f8e89b0955a8ab25dfd02f9 Mon Sep 17 00:00:00 2001 From: Aleks Zi <137826094+ziaptos@users.noreply.github.com> Date: Wed, 11 Dec 2024 15:54:43 -0500 Subject: [PATCH 39/78] [VM][Code cache v2] Some improvements in code cache (#15537) * some improvements in code cache * more refactoring * fixed comments --- .../move-vm/runtime/src/loader/modules.rs | 2 +- .../move/move-vm/runtime/src/loader/script.rs | 5 +- .../runtime/src/storage/environment.rs | 14 +- .../src/storage/struct_name_index_map.rs | 122 +++++++----------- 4 files changed, 61 insertions(+), 82 deletions(-) diff --git a/third_party/move/move-vm/runtime/src/loader/modules.rs b/third_party/move/move-vm/runtime/src/loader/modules.rs index f7faa99f5416d..388363f1ded0e 100644 --- a/third_party/move/move-vm/runtime/src/loader/modules.rs +++ b/third_party/move/move-vm/runtime/src/loader/modules.rs @@ -323,7 +323,7 @@ impl Module { module: module_id, name: struct_name.to_owned(), }; - struct_idxs.push(struct_name_index_map.struct_name_to_idx(struct_name.clone())?); + struct_idxs.push(struct_name_index_map.struct_name_to_idx(&struct_name)?); struct_names.push(struct_name) } diff --git a/third_party/move/move-vm/runtime/src/loader/script.rs b/third_party/move/move-vm/runtime/src/loader/script.rs index 2473cd8104abb..cddfdea0f3548 100644 --- a/third_party/move/move-vm/runtime/src/loader/script.rs +++ b/third_party/move/move-vm/runtime/src/loader/script.rs @@ -47,10 +47,11 @@ impl Script { let struct_name = script.identifier_at(struct_handle.name); let module_handle = script.module_handle_at(struct_handle.module); let module_id = script.module_id_for_handle(module_handle); - struct_names.push(struct_name_index_map.struct_name_to_idx(StructIdentifier { + let struct_name = StructIdentifier { module: module_id, name: struct_name.to_owned(), - })?); + }; + struct_names.push(struct_name_index_map.struct_name_to_idx(&struct_name)?); } let mut function_refs = vec![]; diff --git a/third_party/move/move-vm/runtime/src/storage/environment.rs b/third_party/move/move-vm/runtime/src/storage/environment.rs index 5f53db11161e9..7d5ae85f0640e 100644 --- a/third_party/move/move-vm/runtime/src/storage/environment.rs +++ b/third_party/move/move-vm/runtime/src/storage/environment.rs @@ -56,11 +56,13 @@ pub struct RuntimeEnvironment { /// /// SAFETY: /// Here we informally show that it is safe to share type cache across multiple threads. - /// 1) Struct has been already published. - /// In this case, it is fine to have multiple transactions concurrently accessing and - /// caching struct tags, layouts and depth formulas. Even if transaction failed due to - /// speculation, and is re-executed later, the speculative aborted execution cached a non- - /// speculative existing struct information. It is safe for other threads to access it. + /// + /// 1) Struct has been already published. + /// In this case, it is fine to have multiple transactions concurrently accessing and + /// caching struct tags, layouts and depth formulas. Even if transaction failed due to + /// speculation, and is re-executed later, the speculative aborted execution cached a non- + /// speculative existing struct information. It is safe for other threads to access it. + /// /// 2) Struct is being published with a module. /// The design of V2 loader ensures that when modules are published, i.e., staged on top of /// the existing module storage, the runtime environment is cloned. Hence, it is not even @@ -291,7 +293,7 @@ impl RuntimeEnvironment { &self, struct_name: StructIdentifier, ) -> PartialVMResult { - self.struct_name_index_map.struct_name_to_idx(struct_name) + self.struct_name_index_map.struct_name_to_idx(&struct_name) } } diff --git a/third_party/move/move-vm/runtime/src/storage/struct_name_index_map.rs b/third_party/move/move-vm/runtime/src/storage/struct_name_index_map.rs index 5603c6d3fe513..98329a6845a73 100644 --- a/third_party/move/move-vm/runtime/src/storage/struct_name_index_map.rs +++ b/third_party/move/move-vm/runtime/src/storage/struct_name_index_map.rs @@ -42,39 +42,50 @@ impl StructNameIndexMap { /// if A == B, they have the same indices. pub(crate) fn struct_name_to_idx( &self, - struct_name: StructIdentifier, + struct_name: &StructIdentifier, ) -> PartialVMResult { - // Note that we take a write lock here once, instead of (*): taking a read lock, checking - // if the index is cached, re-acquiring the (write) lock, and checking again, as it makes - // things faster. - // Note that even if we do (*), we MUST check if another thread has cached the index before - // we reached this point for correctness. If we do not do this, we can end up evicting the - // previous index, and end up with multiple indices corresponding to the same struct. As - // indices are stored inside types, type comparison breaks! - let mut index_map = self.0.write(); - - // Index is cached, return early. - if let Some(idx) = index_map.forward_map.get(&struct_name) { - return Ok(StructNameIndex(*idx)); + { + let index_map = self.0.read(); + if let Some(idx) = index_map.forward_map.get(struct_name) { + return Ok(StructNameIndex(*idx)); + } } - // Otherwise, the cache is locked and the struct name is not present. We simply add it - // to the cache and return the corresponding index. - let idx = index_map.backward_map.len(); - let prev_idx = index_map.forward_map.insert(struct_name.clone(), idx); - index_map.backward_map.push(Arc::new(struct_name)); + // Possibly need to insert, so make the copies outside of the lock. + let forward_key = struct_name.clone(); + let backward_value = Arc::new(struct_name.clone()); - // Unlock the cache. - drop(index_map); + let idx = { + let mut index_map = self.0.write(); + + if let Some(idx) = index_map.forward_map.get(struct_name) { + return Ok(StructNameIndex(*idx)); + } + + let idx = index_map.backward_map.len(); + index_map.backward_map.push(backward_value); + index_map.forward_map.insert(forward_key, idx); + idx + }; - if prev_idx.is_some() { - return Err(panic_error!( - "Indexing map should never evict cached entries" - )); - } Ok(StructNameIndex(idx)) } + fn idx_to_struct_name_helper<'a>( + index_map: &'a parking_lot::RwLockReadGuard>, + idx: StructNameIndex, + ) -> PartialVMResult<&'a Arc> { + index_map.backward_map.get(idx.0).ok_or_else(|| { + let msg = format!( + "Index out of bounds when accessing struct name reference \ + at index {}, backward map length: {}", + idx.0, + index_map.backward_map.len() + ); + panic_error!(msg) + }) + } + /// Returns the reference of the struct name corresponding to the index. Here, we wrap the /// name into an [Arc] to ensure that the lock is released. pub(crate) fn idx_to_struct_name_ref( @@ -82,19 +93,7 @@ impl StructNameIndexMap { idx: StructNameIndex, ) -> PartialVMResult> { let index_map = self.0.read(); - Ok(index_map - .backward_map - .get(idx.0) - .ok_or_else(|| { - let msg = format!( - "Index out of bounds when accessing struct name reference \ - at index {}, backward map length: {}", - idx.0, - index_map.backward_map.len() - ); - panic_error!(msg) - })? - .clone()) + Ok(Self::idx_to_struct_name_helper(&index_map, idx)?.clone()) } /// Returns the clone of the struct name corresponding to the index. The clone ensures that the @@ -104,18 +103,7 @@ impl StructNameIndexMap { idx: StructNameIndex, ) -> PartialVMResult { let index_map = self.0.read(); - Ok(index_map - .backward_map - .get(idx.0) - .ok_or_else(|| { - let msg = format!( - "Index out of bounds when accessing struct name at index {}, \ - backward map length: {}", - idx.0, - index_map.backward_map.len() - ); - panic_error!(msg) - })? + Ok(Self::idx_to_struct_name_helper(&index_map, idx)? .as_ref() .clone()) } @@ -127,19 +115,7 @@ impl StructNameIndexMap { ty_args: Vec, ) -> PartialVMResult { let index_map = self.0.read(); - let struct_name = index_map - .backward_map - .get(idx.0) - .ok_or_else(|| { - let msg = format!( - "Index out of bounds when constructing a struct tag \ - for struct name at index {}, backward map length: {}", - idx.0, - index_map.backward_map.len() - ); - panic_error!(msg) - })? - .as_ref(); + let struct_name = Self::idx_to_struct_name_helper(&index_map, idx)?.as_ref(); Ok(StructTag { address: *struct_name.module.address(), module: struct_name.module.name().to_owned(), @@ -151,10 +127,10 @@ impl StructNameIndexMap { /// Returns the number of cached entries. Asserts that the number of cached indices is equal to /// the number of cached struct names. pub(crate) fn checked_len(&self) -> PartialVMResult { - let index_map = self.0.read(); - let forward_map_len = index_map.forward_map.len(); - let backward_map_len = index_map.backward_map.len(); - drop(index_map); + let (forward_map_len, backward_map_len) = { + let index_map = self.0.read(); + (index_map.forward_map.len(), index_map.backward_map.len()) + }; if forward_map_len != backward_map_len { let msg = format!( @@ -205,11 +181,11 @@ mod test { // First-time access. let foo = make_struct_name("foo", "Foo"); - let foo_idx = assert_ok!(struct_name_idx_map.struct_name_to_idx(foo.clone())); + let foo_idx = assert_ok!(struct_name_idx_map.struct_name_to_idx(&foo)); assert_eq!(foo_idx.0, 0); let bar = make_struct_name("bar", "Bar"); - let bar_idx = assert_ok!(struct_name_idx_map.struct_name_to_idx(bar.clone())); + let bar_idx = assert_ok!(struct_name_idx_map.struct_name_to_idx(&bar)); assert_eq!(bar_idx.0, 1); // Check that struct names actually correspond to indices. @@ -219,9 +195,9 @@ mod test { assert_eq!(returned_bar.as_ref(), &bar); // Re-check indices on second access. - let foo_idx = assert_ok!(struct_name_idx_map.struct_name_to_idx(foo)); + let foo_idx = assert_ok!(struct_name_idx_map.struct_name_to_idx(&foo)); assert_eq!(foo_idx.0, 0); - let bar_idx = assert_ok!(struct_name_idx_map.struct_name_to_idx(bar)); + let bar_idx = assert_ok!(struct_name_idx_map.struct_name_to_idx(&bar)); assert_eq!(bar_idx.0, 1); let len = assert_ok!(struct_name_idx_map.checked_len()); @@ -251,7 +227,7 @@ mod test { s.spawn({ let struct_name_idx_map = struct_name_idx_map.clone(); move || { - let idx = assert_ok!(struct_name_idx_map.struct_name_to_idx(struct_name.clone())); + let idx = assert_ok!(struct_name_idx_map.struct_name_to_idx(struct_name)); let actual_struct_name = assert_ok!(struct_name_idx_map.idx_to_struct_name_ref(idx)); assert_eq!(actual_struct_name.as_ref(), struct_name); } @@ -273,7 +249,7 @@ mod test { let struct_name_idx_map = struct_name_idx_map.clone(); let struct_name = struct_name.clone(); move || { - assert_ok!(struct_name_idx_map.struct_name_to_idx(struct_name)); + assert_ok!(struct_name_idx_map.struct_name_to_idx(&struct_name)); } }); } From 652be07201dbf011cd1afe58150bd8d474748b5a Mon Sep 17 00:00:00 2001 From: Junkil Park Date: Wed, 11 Dec 2024 13:57:15 -0800 Subject: [PATCH 40/78] Enable DELEGATION_POOL_PARTIAL_GOVERNANCE_VOTING by default (#15549) - enable DELEGATION_POOL_PARTIAL_GOVERNANCE_VOTING - fix the broken tests due to that. --- .../sources/delegation_pool.move | 72 +++++++++++++++++++ types/src/on_chain_config/aptos_features.rs | 1 + 2 files changed, 73 insertions(+) diff --git a/aptos-move/framework/aptos-framework/sources/delegation_pool.move b/aptos-move/framework/aptos-framework/sources/delegation_pool.move index 1db2438ed4241..bab7f756ca311 100644 --- a/aptos-move/framework/aptos-framework/sources/delegation_pool.move +++ b/aptos-move/framework/aptos-framework/sources/delegation_pool.move @@ -2402,6 +2402,12 @@ module aptos_framework::delegation_pool { validator: &signer, ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(aptos_framework); + // This test case checks the scenario where delegation_pool_partial_governance_voting is disabled. + features::change_feature_flags_for_testing( + aptos_framework, + vector[], + vector[features::get_delegation_pool_partial_governance_voting()] + ); let validator_address = signer::address_of(validator); initialize_delegation_pool(validator, 0, vector::empty()); @@ -2435,10 +2441,33 @@ module aptos_framework::delegation_pool { validator: &signer, ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(aptos_framework); + // This test case checks the scenario where delegation_pool_partial_governance_voting is disabled. + features::change_feature_flags_for_testing( + aptos_framework, + vector[], + vector[features::get_delegation_pool_partial_governance_voting()] + ); // account does not own any delegation pool set_delegated_voter(validator, @0x112); } + #[test(aptos_framework = @aptos_framework, validator = @0x123)] + #[expected_failure(abort_code = 0x3000C, location = Self)] + public entry fun test_cannot_set_delegated_voter_if_partial_governance_voting( + aptos_framework: &signer, + validator: &signer, + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + initialize_for_test(aptos_framework); + // This test case checks the scenario where delegation_pool_partial_governance_voting is enabled. + features::change_feature_flags_for_testing( + aptos_framework, + vector[features::get_delegation_pool_partial_governance_voting()], + vector[] + ); + // cannot call this deprecated function anymore + set_delegated_voter(validator, @0x112); + } + #[test(aptos_framework = @aptos_framework, validator = @0x123)] #[expected_failure(abort_code = 0x80002, location = Self)] public entry fun test_already_owns_delegation_pool( @@ -2467,6 +2496,12 @@ module aptos_framework::delegation_pool { validator: &signer, ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(aptos_framework); + // This test case checks the scenario where delegation_pool_partial_governance_voting is disabled. + features::change_feature_flags_for_testing( + aptos_framework, + vector[], + vector[features::get_delegation_pool_partial_governance_voting()] + ); let validator_address = signer::address_of(validator); initialize_delegation_pool(validator, 1234, vector::empty()); @@ -2477,6 +2512,7 @@ module aptos_framework::delegation_pool { assert!(stake::stake_pool_exists(pool_address), 0); assert!(stake::get_operator(pool_address) == validator_address, 0); + // pool created before partial governance voting, owner account is delegated voter assert!(stake::get_delegated_voter(pool_address) == validator_address, 0); assert!(observed_lockup_cycle(pool_address) == 0, 0); @@ -4429,6 +4465,12 @@ module aptos_framework::delegation_pool { 1000, ); aptos_governance::initialize_partial_voting(aptos_framework); + // This test case checks the scenario where delegation_pool_partial_governance_voting is disabled. + features::change_feature_flags_for_testing( + aptos_framework, + vector[], + vector[features::get_delegation_pool_partial_governance_voting()] + ); initialize_test_validator(validator, 100 * ONE_APT, true, false); @@ -4592,6 +4634,12 @@ module aptos_framework::delegation_pool { voter1: &signer, voter2: &signer, ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage, DelegationPoolAllowlisting { + // This test case checks the scenario where delegation_pool_partial_governance_voting is disabled. + features::change_feature_flags_for_testing( + aptos_framework, + vector[], + vector[features::get_delegation_pool_partial_governance_voting()] + ); // partial voing hasn't been enabled yet. A proposal has been created by the validator. let proposal1_id = setup_vote(aptos_framework, validator, false); @@ -4685,6 +4733,12 @@ module aptos_framework::delegation_pool { delegator1: &signer, voter1: &signer, ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage, DelegationPoolAllowlisting { + // This test case checks the scenario where delegation_pool_partial_governance_voting is disabled. + features::change_feature_flags_for_testing( + aptos_framework, + vector[], + vector[features::get_delegation_pool_partial_governance_voting()] + ); // partial voing hasn't been enabled yet. A proposal has been created by the validator. let proposal1_id = setup_vote(aptos_framework, validator, false); @@ -4722,6 +4776,12 @@ module aptos_framework::delegation_pool { delegator1: &signer, voter1: &signer, ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage, DelegationPoolAllowlisting { + // This test case checks the scenario where delegation_pool_partial_governance_voting is disabled. + features::change_feature_flags_for_testing( + aptos_framework, + vector[], + vector[features::get_delegation_pool_partial_governance_voting()] + ); // partial voing hasn't been enabled yet. A proposal has been created by the validator. let proposal1_id = setup_vote(aptos_framework, validator, false); @@ -4761,6 +4821,12 @@ module aptos_framework::delegation_pool { validator: &signer, delegator1: &signer, ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage, DelegationPoolAllowlisting { + // This test case checks the scenario where delegation_pool_partial_governance_voting is disabled. + features::change_feature_flags_for_testing( + aptos_framework, + vector[], + vector[features::get_delegation_pool_partial_governance_voting()] + ); // partial voing hasn't been enabled yet. A proposal has been created by the validator. let proposal1_id = setup_vote(aptos_framework, validator, true); @@ -4780,6 +4846,12 @@ module aptos_framework::delegation_pool { delegator1: &signer, voter1: &signer, ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage, DelegationPoolAllowlisting { + // This test case checks the scenario where delegation_pool_partial_governance_voting is disabled. + features::change_feature_flags_for_testing( + aptos_framework, + vector[], + vector[features::get_delegation_pool_partial_governance_voting()] + ); // partial voing hasn't been enabled yet. A proposal has been created by the validator. setup_vote(aptos_framework, validator, true); diff --git a/types/src/on_chain_config/aptos_features.rs b/types/src/on_chain_config/aptos_features.rs index 2247a60edb152..99d61d7d6b513 100644 --- a/types/src/on_chain_config/aptos_features.rs +++ b/types/src/on_chain_config/aptos_features.rs @@ -126,6 +126,7 @@ impl FeatureFlag { FeatureFlag::SIGNATURE_CHECKER_V2, FeatureFlag::STORAGE_SLOT_METADATA, FeatureFlag::CHARGE_INVARIANT_VIOLATION, + FeatureFlag::DELEGATION_POOL_PARTIAL_GOVERNANCE_VOTING, FeatureFlag::APTOS_UNIQUE_IDENTIFIERS, FeatureFlag::GAS_PAYER_ENABLED, FeatureFlag::BULLETPROOFS_NATIVES, From 2ee2c339df1fb3d18b1a4f5bed6b81c9767fbaf3 Mon Sep 17 00:00:00 2001 From: Zekun Li Date: Wed, 4 Dec 2024 16:15:25 -0800 Subject: [PATCH 41/78] [pipeline] fixes [pipeline] expect cancellation error [pipeline] block callback until notification finishes [pipeline] avoid panic when parent fut doesn't exist during epoch ending --- .../consensus-types/src/pipelined_block.rs | 26 +++++++++++++------ consensus/src/block_storage/block_store.rs | 6 ++--- consensus/src/pipeline/pipeline_builder.rs | 5 +++- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/consensus/consensus-types/src/pipelined_block.rs b/consensus/consensus-types/src/pipelined_block.rs index 10fa28f9227ba..b0cc069aff768 100644 --- a/consensus/consensus-types/src/pipelined_block.rs +++ b/consensus/consensus-types/src/pipelined_block.rs @@ -17,7 +17,7 @@ use aptos_executor_types::{ state_compute_result::StateComputeResult, ExecutorError, ExecutorResult, }; use aptos_infallible::Mutex; -use aptos_logger::{error, warn}; +use aptos_logger::{error, info, warn}; use aptos_types::{ block_info::BlockInfo, contract_event::ContractEvent, @@ -427,7 +427,9 @@ impl PipelinedBlock { /// Pipeline related functions impl PipelinedBlock { pub fn pipeline_enabled(&self) -> bool { - self.pipeline_futs.lock().is_some() + // if the pipeline_tx is set, the pipeline is enabled, + // we don't use pipeline fut here because it can't be taken when abort + self.pipeline_tx.lock().is_some() } pub fn pipeline_futs(&self) -> Option { @@ -451,6 +453,12 @@ impl PipelinedBlock { } pub fn abort_pipeline(&self) -> Option { + info!( + "[Pipeline] Aborting pipeline for block {} {} {}", + self.id(), + self.epoch(), + self.round() + ); if let Some(abort_handles) = self.pipeline_abort_handle.lock().take() { for handle in abort_handles { handle.abort(); @@ -461,7 +469,9 @@ impl PipelinedBlock { pub async fn wait_for_compute_result(&self) -> ExecutorResult<(StateComputeResult, Duration)> { self.pipeline_futs() - .expect("Pipeline needs to be enabled") + .ok_or(ExecutorError::InternalError { + error: "Pipeline aborted".to_string(), + })? .ledger_update_fut .await .map(|(compute_result, execution_time, _)| (compute_result, execution_time)) @@ -471,11 +481,11 @@ impl PipelinedBlock { } pub async fn wait_for_commit_ledger(&self) { - self.pipeline_futs() - .expect("Pipeline needs to be enabled") - .commit_ledger_fut - .await - .expect("Commit ledger should succeed"); + // may be aborted (e.g. by reset) + if let Some(fut) = self.pipeline_futs() { + // this may be cancelled + let _ = fut.commit_ledger_fut.await; + } } } diff --git a/consensus/src/block_storage/block_store.rs b/consensus/src/block_storage/block_store.rs index ae20e0a5b01cc..b8c8146121e0a 100644 --- a/consensus/src/block_storage/block_store.rs +++ b/consensus/src/block_storage/block_store.rs @@ -400,9 +400,9 @@ impl BlockStore { }); pipeline_builder.build( &pipelined_block, - parent_block - .pipeline_futs() - .expect("Futures should exist when pipeline enabled"), + parent_block.pipeline_futs().ok_or_else(|| { + anyhow::anyhow!("Parent future doesn't exist, potentially epoch ended") + })?, callback, ); } diff --git a/consensus/src/pipeline/pipeline_builder.rs b/consensus/src/pipeline/pipeline_builder.rs index cb6a90d463498..94577fad0511b 100644 --- a/consensus/src/pipeline/pipeline_builder.rs +++ b/consensus/src/pipeline/pipeline_builder.rs @@ -348,6 +348,7 @@ impl PipelineBuilder { Self::post_commit_ledger( pre_commit_fut.clone(), commit_ledger_fut.clone(), + post_pre_commit_fut.clone(), parent.post_commit_fut.clone(), self.payload_manager.clone(), block_store_callback, @@ -679,11 +680,12 @@ impl PipelineBuilder { Ok(Some(ledger_info_with_sigs)) } - /// Precondition: 1. commit ledger finishes, 2. parent block's phase finishes + /// Precondition: 1. commit ledger finishes, 2. parent block's phase finishes 3. post pre commit finishes /// What it does: Update counters for the block, and notify block tree about the commit async fn post_commit_ledger( pre_commit_fut: TaskFuture, commit_ledger_fut: TaskFuture, + post_pre_commit_fut: TaskFuture, parent_post_commit: TaskFuture, payload_manager: Arc, block_store_callback: Box, @@ -692,6 +694,7 @@ impl PipelineBuilder { parent_post_commit.await?; let maybe_ledger_info_with_sigs = commit_ledger_fut.await?; let compute_result = pre_commit_fut.await?; + post_pre_commit_fut.await?; let _tracker = Tracker::new("post_commit_ledger", &block); update_counters_for_block(&block); From d3028e92266a3b81173e02b32bfec6737ae9de28 Mon Sep 17 00:00:00 2001 From: Zekun Li Date: Thu, 5 Dec 2024 14:31:06 -0800 Subject: [PATCH 42/78] [Pipeline] add counters --- consensus/src/counters.rs | 15 ++++- consensus/src/lib.rs | 2 +- consensus/src/pipeline/pipeline_builder.rs | 74 ++++++++++++++++------ 3 files changed, 69 insertions(+), 22 deletions(-) diff --git a/consensus/src/counters.rs b/consensus/src/counters.rs index f55d9d4ff9f37..8c901c7bbd599 100644 --- a/consensus/src/counters.rs +++ b/consensus/src/counters.rs @@ -836,7 +836,7 @@ pub static NUM_BYTES_PER_BLOCK: Lazy = Lazy::new(|| { // * 0.3 to 2.0: step 0.1 // * 2.0 to 4.0: step 0.2 // * 4.0 to 7.5: step 0.5 -const BLOCK_TRACING_BUCKETS: &[f64] = &[ +const TRACING_BUCKETS: &[f64] = &[ 0.005, 0.01, 0.025, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 10.0, @@ -848,7 +848,18 @@ pub static BLOCK_TRACING: Lazy = Lazy::new(|| { "aptos_consensus_block_tracing", "Histogram for different stages of a block", &["stage"], - BLOCK_TRACING_BUCKETS.to_vec() + TRACING_BUCKETS.to_vec() + ) + .unwrap() +}); + +/// Traces pipeline stages +pub static PIPELINE_TRACING: Lazy = Lazy::new(|| { + register_histogram_vec!( + "aptos_consensus_pipeline_tracing", + "Histogram for different stages of a block's pipeline", + &["stage", "type"], + TRACING_BUCKETS.to_vec() ) .unwrap() }); diff --git a/consensus/src/lib.rs b/consensus/src/lib.rs index aa1bc3234558e..a38b66912e191 100644 --- a/consensus/src/lib.rs +++ b/consensus/src/lib.rs @@ -75,7 +75,7 @@ pub use quorum_store::quorum_store_db::QUORUM_STORE_DB_NAME; #[cfg(feature = "fuzzing")] pub use round_manager::round_manager_fuzzing; -struct IntGaugeGuard { +pub struct IntGaugeGuard { gauge: IntGauge, } diff --git a/consensus/src/pipeline/pipeline_builder.rs b/consensus/src/pipeline/pipeline_builder.rs index 94577fad0511b..a71f9927fed3c 100644 --- a/consensus/src/pipeline/pipeline_builder.rs +++ b/consensus/src/pipeline/pipeline_builder.rs @@ -10,6 +10,7 @@ use crate::{ monitor, payload_manager::TPayloadManager, txn_notifier::TxnNotifier, + IntGaugeGuard, }; use anyhow::anyhow; use aptos_consensus_notifications::ConsensusNotificationSender; @@ -104,18 +105,30 @@ struct Tracker { block_id: HashValue, epoch: u64, round: Round, + created_at: Instant, + started_at: Option, + running_guard: Option, } impl Tracker { - pub fn new(name: &'static str, block: &Block) -> Self { - let ret = Self { + fn start_waiting(name: &'static str, block: &Block) -> Self { + Self { name, block_id: block.id(), epoch: block.epoch(), round: block.round(), - }; - ret.log_start(); - ret + created_at: Instant::now(), + started_at: None, + running_guard: None, + } + } + + fn start_working(&mut self) { + self.started_at = Some(Instant::now()); + self.running_guard = Some(IntGaugeGuard::new( + counters::OP_COUNTERS.gauge(&format!("{}_running", self.name)), + )); + self.log_start(); } fn log_start(&self) { @@ -126,9 +139,25 @@ impl Tracker { } fn log_end(&self) { + let Some(started_at) = self.started_at else { + return; + }; + let wait_time = started_at.duration_since(self.created_at); + let work_time = Instant::now().duration_since(started_at); + counters::PIPELINE_TRACING + .with_label_values(&[self.name, "wait_time"]) + .observe(wait_time.as_secs_f64()); + counters::PIPELINE_TRACING + .with_label_values(&[self.name, "work_time"]) + .observe(work_time.as_secs_f64()); info!( - "[Pipeline] Block {} {} {} finishes {}", - self.block_id, self.epoch, self.round, self.name + "[Pipeline] Block {} {} {} finishes {}, waits {}, takes {}", + self.block_id, + self.epoch, + self.round, + self.name, + wait_time.as_millis(), + work_time.as_millis() ); } } @@ -139,7 +168,6 @@ impl Drop for Tracker { } } -// TODO: add counters for each phase impl PipelineBuilder { pub fn new( block_preparer: Arc, @@ -379,7 +407,8 @@ impl PipelineBuilder { /// Precondition: Block is inserted into block tree (all ancestors are available) /// What it does: Wait for all data becomes available and verify transaction signatures async fn prepare(preparer: Arc, block: Arc) -> TaskResult { - let _tracker = Tracker::new("prepare", &block); + let mut tracker = Tracker::start_waiting("prepare", &block); + tracker.start_working(); // the loop can only be abort by the caller let input_txns = loop { match preparer.prepare_block(&block).await { @@ -420,13 +449,14 @@ impl PipelineBuilder { validator: Arc<[AccountAddress]>, onchain_execution_config: BlockExecutorConfigFromOnchain, ) -> TaskResult { + let mut tracker = Tracker::start_waiting("execute", &block); parent_block_execute_phase.await?; let user_txns = prepare_phase.await?; let maybe_rand = randomness_rx .await .map_err(|_| anyhow!("randomness tx cancelled"))?; - let _tracker = Tracker::new("execute", &block); + tracker.start_working(); let metadata_txn = if is_randomness_enabled { block.new_metadata_with_randomness(&validator, maybe_rand) } else { @@ -471,9 +501,11 @@ impl PipelineBuilder { executor: Arc, block: Arc, ) -> TaskResult { + let mut tracker = Tracker::start_waiting("ledger_update", &block); let (_, _, prev_epoch_end_timestamp) = parent_block_ledger_update_phase.await?; let execution_time = execute_phase.await?; - let _tracker = Tracker::new("ledger_update", &block); + + tracker.start_working(); let timestamp = block.timestamp_usecs(); let result = tokio::task::spawn_blocking(move || { executor @@ -501,10 +533,11 @@ impl PipelineBuilder { mempool_notifier: Arc, block: Arc, ) -> TaskResult { + let mut tracker = Tracker::start_waiting("post_ledger_update", &block); let user_txns = prepare_fut.await?; let (compute_result, _, _) = ledger_update.await?; - let _tracker = Tracker::new("post_ledger_update", &block); + tracker.start_working(); let compute_status = compute_result.compute_status_for_input_txns(); // the length of compute_status is user_txns.len() + num_vtxns + 1 due to having blockmetadata if user_txns.len() >= compute_status.len() { @@ -551,6 +584,7 @@ impl PipelineBuilder { signer: Arc, block: Arc, ) -> TaskResult { + let mut tracker = Tracker::start_waiting("sign_commit_vote", &block); let (compute_result, _, epoch_end_timestamp) = ledger_update_phase.await?; // either order_vote_rx or order_proof_fut can trigger the next phase select! { @@ -564,8 +598,8 @@ impl PipelineBuilder { return Err(anyhow!("all receivers dropped"))?; } } + tracker.start_working(); - let _tracker = Tracker::new("sign_commit_vote", &block); let mut block_info = block.gen_block_info( compute_result.root_hash(), compute_result.last_version_or_0(), @@ -601,6 +635,7 @@ impl PipelineBuilder { executor: Arc, block: Arc, ) -> TaskResult { + let mut tracker = Tracker::start_waiting("pre_commit", &block); let (compute_result, _, _) = ledger_update_phase.await?; parent_block_pre_commit_phase.await?; @@ -610,7 +645,7 @@ impl PipelineBuilder { commit_proof_fut.await?; } - let _tracker = Tracker::new("pre_commit", &block); + tracker.start_working(); tokio::task::spawn_blocking(move || { executor .pre_commit_block(block.id()) @@ -630,12 +665,11 @@ impl PipelineBuilder { state_sync_notifier: Arc, block: Arc, ) -> TaskResult { + let mut tracker = Tracker::start_waiting("post_pre_commit", &block); let compute_result = pre_commit.await?; parent_post_pre_commit.await?; - let _tracker = Tracker::new("post_pre_commit", &block); - let _timer = counters::OP_COUNTERS.timer("pre_commit_notify"); - + tracker.start_working(); let txns = compute_result.transactions_to_commit().to_vec(); let subscribable_events = compute_result.subscribable_events().to_vec(); if let Err(e) = monitor!( @@ -659,6 +693,7 @@ impl PipelineBuilder { executor: Arc, block: Arc, ) -> TaskResult { + let mut tracker = Tracker::start_waiting("commit_ledger", &block); parent_block_commit_phase.await?; pre_commit_fut.await?; let ledger_info_with_sigs = commit_proof_fut.await?; @@ -668,7 +703,7 @@ impl PipelineBuilder { return Ok(None); } - let _tracker = Tracker::new("commit_ledger", &block); + tracker.start_working(); let ledger_info_with_sigs_clone = ledger_info_with_sigs.clone(); tokio::task::spawn_blocking(move || { executor @@ -691,12 +726,13 @@ impl PipelineBuilder { block_store_callback: Box, block: Arc, ) -> TaskResult { + let mut tracker = Tracker::start_waiting("post_commit_ledger", &block); parent_post_commit.await?; let maybe_ledger_info_with_sigs = commit_ledger_fut.await?; let compute_result = pre_commit_fut.await?; post_pre_commit_fut.await?; - let _tracker = Tracker::new("post_commit_ledger", &block); + tracker.start_working(); update_counters_for_block(&block); update_counters_for_compute_result(&compute_result); From 803b7fda81ab9f17fa82b630fcd50954cee25039 Mon Sep 17 00:00:00 2001 From: Victor Gao <10379359+vgao1996@users.noreply.github.com> Date: Wed, 11 Dec 2024 16:40:54 -0800 Subject: [PATCH 43/78] [CLI] move out localnet logic + add command for Aptos Workspace (#15508) --- .dockerignore | 2 +- Cargo.lock | 28 ++- Cargo.toml | 3 + aptos-move/aptos-workspace-server/Cargo.toml | 2 +- aptos-move/aptos-workspace-server/src/lib.rs | 183 +++++++++++++++ aptos-move/aptos-workspace-server/src/main.rs | 184 +-------------- .../src/services/docker_common.rs | 2 +- .../src/services/faucet.rs | 2 +- .../src/services/indexer_api.rs | 4 +- .../src/services/node.rs | 2 +- .../src/services/postgres.rs | 8 +- .../src/services/processors.rs | 2 +- crates/aptos-localnet/Cargo.toml | 34 +++ crates/aptos-localnet/src/docker.rs | 92 ++++++++ .../src}/hasura_metadata.json | 0 crates/aptos-localnet/src/health_checker.rs | 216 ++++++++++++++++++ crates/aptos-localnet/src/indexer_api.rs | 122 ++++++++++ crates/aptos-localnet/src/lib.rs | 13 ++ crates/aptos-localnet/src/processors.rs | 66 ++++++ crates/aptos/Cargo.toml | 3 +- crates/aptos/src/lib.rs | 4 + crates/aptos/src/node/local_testnet/docker.rs | 88 +------ .../src/node/local_testnet/indexer_api.rs | 90 +------- .../src/node/local_testnet/processors.rs | 68 +----- crates/aptos/src/workspace/mod.rs | 38 +++ 25 files changed, 821 insertions(+), 435 deletions(-) create mode 100644 aptos-move/aptos-workspace-server/src/lib.rs create mode 100644 crates/aptos-localnet/Cargo.toml create mode 100644 crates/aptos-localnet/src/docker.rs rename crates/{aptos/src/node/local_testnet => aptos-localnet/src}/hasura_metadata.json (100%) create mode 100644 crates/aptos-localnet/src/health_checker.rs create mode 100644 crates/aptos-localnet/src/indexer_api.rs create mode 100644 crates/aptos-localnet/src/lib.rs create mode 100644 crates/aptos-localnet/src/processors.rs create mode 100644 crates/aptos/src/workspace/mod.rs diff --git a/.dockerignore b/.dockerignore index a6274ffa46194..7777cad9ecf3f 100644 --- a/.dockerignore +++ b/.dockerignore @@ -25,7 +25,7 @@ !aptos-move/framework/ !aptos-move/move-examples/hello_blockchain/ !crates/aptos/src/move_tool/*.bpl -!crates/aptos/src/node/local_testnet/hasura_metadata.json +!crates/aptos-localnet/src/hasura_metadata.json !crates/aptos-faucet/doc/ !crates/transaction-emitter-lib/src/emitter/test_proofs_for_localnet_txn_emitter.txt !api/doc/ diff --git a/Cargo.lock b/Cargo.lock index f2757456dbe81..9c5d1f9def8f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -297,6 +297,7 @@ dependencies = [ "aptos-indexer-grpc-utils", "aptos-keygen", "aptos-ledger", + "aptos-localnet", "aptos-logger", "aptos-move-debugger", "aptos-network-checker", @@ -313,6 +314,7 @@ dependencies = [ "aptos-vm-genesis", "aptos-vm-logging", "aptos-vm-types", + "aptos-workspace-server", "async-trait", "base64 0.13.1", "bcs 0.1.4", @@ -369,7 +371,6 @@ dependencies = [ "tracing", "tracing-subscriber 0.3.18", "url", - "version-compare", ] [[package]] @@ -2721,6 +2722,29 @@ dependencies = [ "thiserror", ] +[[package]] +name = "aptos-localnet" +version = "0.1.0" +dependencies = [ + "anyhow", + "aptos-indexer-grpc-utils", + "aptos-protos 1.3.1", + "aptos-rest-client", + "bollard", + "diesel", + "diesel-async", + "dirs 5.0.1", + "futures", + "processor", + "reqwest 0.11.23", + "serde", + "serde_json", + "tokio", + "tonic 0.11.0", + "tracing", + "version-compare", +] + [[package]] name = "aptos-log-derive" version = "0.1.0" @@ -4713,10 +4737,10 @@ name = "aptos-workspace-server" version = "0.1.0" dependencies = [ "anyhow", - "aptos", "aptos-cached-packages", "aptos-config", "aptos-faucet-core", + "aptos-localnet", "aptos-node", "aptos-types", "bollard", diff --git a/Cargo.toml b/Cargo.toml index bca2044043628..85473f6bb3de5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -78,6 +78,7 @@ members = [ "crates/aptos-jwk-consensus", "crates/aptos-keygen", "crates/aptos-ledger", + "crates/aptos-localnet", "crates/aptos-log-derive", "crates/aptos-logger", "crates/aptos-metrics-core", @@ -380,6 +381,7 @@ aptos-jwk-utils = { path = "crates/jwk-utils" } aptos-keygen = { path = "crates/aptos-keygen" } aptos-language-e2e-tests = { path = "aptos-move/e2e-tests" } aptos-ledger = { path = "crates/aptos-ledger" } +aptos-localnet = { path = "crates/aptos-localnet" } aptos-log-derive = { path = "crates/aptos-log-derive" } aptos-logger = { path = "crates/aptos-logger" } aptos-memory-usage-tracker = { path = "aptos-move/aptos-memory-usage-tracker" } @@ -466,6 +468,7 @@ aptos-vm-logging = { path = "aptos-move/aptos-vm-logging" } aptos-vm-genesis = { path = "aptos-move/vm-genesis" } aptos-vm-types = { path = "aptos-move/aptos-vm-types" } aptos-vm-validator = { path = "vm-validator" } +aptos-workspace-server = { path = "aptos-move/aptos-workspace-server" } aptos-warp-webserver = { path = "crates/aptos-warp-webserver" } aptos-cargo-cli = { path = "devtools/aptos-cargo-cli" } diff --git a/aptos-move/aptos-workspace-server/Cargo.toml b/aptos-move/aptos-workspace-server/Cargo.toml index e72f59d6b7d2a..505a4e8620c5b 100644 --- a/aptos-move/aptos-workspace-server/Cargo.toml +++ b/aptos-move/aptos-workspace-server/Cargo.toml @@ -13,10 +13,10 @@ rust-version = { workspace = true } [dependencies] # aptos deps -aptos = { workspace = true } aptos-cached-packages = { workspace = true } aptos-config = { workspace = true } aptos-faucet-core = { workspace = true } +aptos-localnet = { workspace = true } aptos-node = { workspace = true } aptos-types = { workspace = true } diff --git a/aptos-move/aptos-workspace-server/src/lib.rs b/aptos-move/aptos-workspace-server/src/lib.rs new file mode 100644 index 0000000000000..f27102d335ea0 --- /dev/null +++ b/aptos-move/aptos-workspace-server/src/lib.rs @@ -0,0 +1,183 @@ +// Copyright (c) Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +//! This library runs and manages a set of services that makes up a local Aptos network. +//! - node +//! - node API +//! - indexer grpc +//! - faucet +//! - indexer +//! - postgres db +//! - processors +//! - indexer API +//! +//! The services are bound to unique OS-assigned ports to allow for multiple local networks +//! to operate simultaneously, enabling testing and development in isolated environments. +//! +//! ## Key Features: +//! - Shared Futures +//! - The code makes extensive use of shared futures across multiple services, +//! ensuring orderly startup while maximizing parallel execution. +//! - Graceful Shutdown +//! - When a `Ctrl-C` signal is received or if any of the services fail to start +//! or exit unexpectedly, the system attempts to gracefully shut down all services, +//! cleaning up resources like Docker containers, volumes and networks. + +mod common; +mod services; + +use anyhow::{Context, Result}; +use common::make_shared; +use futures::TryFutureExt; +use services::{ + docker_common::create_docker_network, indexer_api::start_indexer_api, + processors::start_all_processors, +}; +use tokio_util::sync::CancellationToken; +use uuid::Uuid; + +pub async fn run_all_services() -> Result<()> { + let test_dir = tempfile::tempdir()?; + let test_dir = test_dir.path(); + println!("Created test directory: {}", test_dir.display()); + + let instance_id = Uuid::new_v4(); + + // Phase 0: Register the signal handler for ctrl-c. + let shutdown = CancellationToken::new(); + { + // TODO: Find a way to register the signal handler in a blocking manner without + // waiting for it to trigger. + let shutdown = shutdown.clone(); + tokio::spawn(async move { + tokio::signal::ctrl_c().await.unwrap(); + + println!("\nCtrl-C received. Shutting down services. This may take a while.\n"); + + shutdown.cancel(); + }); + } + + // Phase 1: Start all services. + // Node + let (fut_node_api, fut_indexer_grpc, fut_node_finish) = services::node::start_node(test_dir)?; + + let fut_node_api = make_shared(fut_node_api); + let fut_indexer_grpc = make_shared(fut_indexer_grpc); + + // Faucet + let (fut_faucet, fut_faucet_finish) = services::faucet::start_faucet( + test_dir.to_owned(), + fut_node_api.clone(), + fut_indexer_grpc.clone(), + ); + + // Docker Network + let docker_network_name = format!("aptos-workspace-{}", instance_id); + let (fut_docker_network, fut_docker_network_clean_up) = + create_docker_network(shutdown.clone(), docker_network_name); + + // Indexer part 1: postgres db + let (fut_postgres, fut_postgres_finish, fut_postgres_clean_up) = + services::postgres::start_postgres( + shutdown.clone(), + fut_docker_network.clone(), + instance_id, + ); + let fut_postgres = make_shared(fut_postgres); + + // Indexer part 2: processors + let (fut_all_processors_ready, fut_any_processor_finish) = start_all_processors( + fut_node_api.clone(), + fut_indexer_grpc.clone(), + fut_postgres.clone(), + ); + let fut_all_processors_ready = make_shared(fut_all_processors_ready); + + // Indexer part 3: indexer API + let (fut_indexer_api, fut_indexer_api_finish, fut_indexer_api_clean_up) = start_indexer_api( + instance_id, + shutdown.clone(), + fut_docker_network.clone(), + fut_postgres.clone(), + fut_all_processors_ready.clone(), + ); + + // Phase 2: Wait for all services to be up. + let all_services_up = async move { + tokio::try_join!( + fut_node_api.map_err(anyhow::Error::msg), + fut_indexer_grpc.map_err(anyhow::Error::msg), + fut_faucet, + fut_postgres.map_err(anyhow::Error::msg), + fut_all_processors_ready.map_err(anyhow::Error::msg), + fut_indexer_api, + ) + }; + let clean_up_all = async move { + eprintln!("Running shutdown steps"); + fut_indexer_api_clean_up.await; + fut_postgres_clean_up.await; + fut_docker_network_clean_up.await; + }; + tokio::select! { + _ = shutdown.cancelled() => { + clean_up_all.await; + + return Ok(()) + } + res = all_services_up => { + match res.context("one or more services failed to start") { + Ok(_) => println!("ALL SERVICES UP"), + Err(err) => { + eprintln!("\nOne or more services failed to start, will run shutdown steps\n"); + clean_up_all.await; + + return Err(err) + } + } + } + } + + // Phase 3: Wait for services to stop, which should only happen in case of an error, or + // the shutdown signal to be received. + tokio::select! { + _ = shutdown.cancelled() => (), + res = fut_node_finish => { + eprintln!("Node exited unexpectedly"); + if let Err(err) = res { + eprintln!("Error: {}", err); + } + } + res = fut_faucet_finish => { + eprintln!("Faucet exited unexpectedly"); + if let Err(err) = res { + eprintln!("Error: {}", err); + } + } + res = fut_postgres_finish => { + eprintln!("Postgres exited unexpectedly"); + if let Err(err) = res { + eprintln!("Error: {}", err); + } + } + res = fut_any_processor_finish => { + eprintln!("One of the processors exited unexpectedly"); + if let Err(err) = res { + eprintln!("Error: {}", err); + } + } + res = fut_indexer_api_finish => { + eprintln!("Indexer API exited unexpectedly"); + if let Err(err) = res { + eprintln!("Error: {}", err); + } + } + } + + clean_up_all.await; + + println!("Finished running all services"); + + Ok(()) +} diff --git a/aptos-move/aptos-workspace-server/src/main.rs b/aptos-move/aptos-workspace-server/src/main.rs index 34a66ea96f942..a142293ef5ae1 100644 --- a/aptos-move/aptos-workspace-server/src/main.rs +++ b/aptos-move/aptos-workspace-server/src/main.rs @@ -1,191 +1,11 @@ // Copyright (c) Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -//! This binary runs and manages a set of services that makes up a local Aptos network. -//! - node -//! - node API -//! - indexer grpc -//! - faucet -//! - indexer -//! - postgres db -//! - processors -//! - indexer API -//! -//! The services are bound to unique OS-assigned ports to allow for multiple local networks -//! to operate simultaneously, enabling testing and development in isolated environments. -//! -//! ## Key Features: -//! - Shared Futures -//! - The code makes extensive use of shared futures across multiple services, -//! ensuring orderly startup while maximizing parallel execution. -//! - Graceful Shutdown -//! - When a `Ctrl-C` signal is received or if any of the services fail to start -//! or exit unexpectedly, the system attempts to gracefully shut down all services, -//! cleaning up resources like Docker containers, volumes and networks. - -mod common; -mod services; - -use anyhow::{Context, Result}; -use common::make_shared; -use futures::TryFutureExt; -use services::{ - docker_common::create_docker_network, indexer_api::start_indexer_api, - processors::start_all_processors, -}; -use std::path::Path; -use tokio_util::sync::CancellationToken; -use uuid::Uuid; - -async fn run_all_services(test_dir: &Path) -> Result<()> { - let instance_id = Uuid::new_v4(); - - // Phase 0: Register the signal handler for ctrl-c. - let shutdown = CancellationToken::new(); - { - // TODO: Find a way to register the signal handler in a blocking manner without - // waiting for it to trigger. - let shutdown = shutdown.clone(); - tokio::spawn(async move { - tokio::signal::ctrl_c().await.unwrap(); - - println!("\nCtrl-C received. Shutting down services. This may take a while.\n"); - - shutdown.cancel(); - }); - } - - // Phase 1: Start all services. - // Node - let (fut_node_api, fut_indexer_grpc, fut_node_finish) = services::node::start_node(test_dir)?; - - let fut_node_api = make_shared(fut_node_api); - let fut_indexer_grpc = make_shared(fut_indexer_grpc); - - // Faucet - let (fut_faucet, fut_faucet_finish) = services::faucet::start_faucet( - test_dir.to_owned(), - fut_node_api.clone(), - fut_indexer_grpc.clone(), - ); - - // Docker Network - let docker_network_name = format!("aptos-workspace-{}", instance_id); - let (fut_docker_network, fut_docker_network_clean_up) = - create_docker_network(shutdown.clone(), docker_network_name); - - // Indexer part 1: postgres db - let (fut_postgres, fut_postgres_finish, fut_postgres_clean_up) = - services::postgres::start_postgres( - shutdown.clone(), - fut_docker_network.clone(), - instance_id, - ); - let fut_postgres = make_shared(fut_postgres); - - // Indexer part 2: processors - let (fut_all_processors_ready, fut_any_processor_finish) = start_all_processors( - fut_node_api.clone(), - fut_indexer_grpc.clone(), - fut_postgres.clone(), - ); - let fut_all_processors_ready = make_shared(fut_all_processors_ready); - - // Indexer part 3: indexer API - let (fut_indexer_api, fut_indexer_api_finish, fut_indexer_api_clean_up) = start_indexer_api( - instance_id, - shutdown.clone(), - fut_docker_network.clone(), - fut_postgres.clone(), - fut_all_processors_ready.clone(), - ); - - // Phase 2: Wait for all services to be up. - let all_services_up = async move { - tokio::try_join!( - fut_node_api.map_err(anyhow::Error::msg), - fut_indexer_grpc.map_err(anyhow::Error::msg), - fut_faucet, - fut_postgres.map_err(anyhow::Error::msg), - fut_all_processors_ready.map_err(anyhow::Error::msg), - fut_indexer_api, - ) - }; - let clean_up_all = async move { - eprintln!("Running shutdown steps"); - fut_indexer_api_clean_up.await; - fut_postgres_clean_up.await; - fut_docker_network_clean_up.await; - }; - tokio::select! { - _ = shutdown.cancelled() => { - clean_up_all.await; - - return Ok(()) - } - res = all_services_up => { - match res.context("one or more services failed to start") { - Ok(_) => println!("ALL SERVICES UP"), - Err(err) => { - eprintln!("\nOne or more services failed to start, will run shutdown steps\n"); - clean_up_all.await; - - return Err(err) - } - } - } - } - - // Phase 3: Wait for services to stop, which should only happen in case of an error, or - // the shutdown signal to be received. - tokio::select! { - _ = shutdown.cancelled() => (), - res = fut_node_finish => { - eprintln!("Node exited unexpectedly"); - if let Err(err) = res { - eprintln!("Error: {}", err); - } - } - res = fut_faucet_finish => { - eprintln!("Faucet exited unexpectedly"); - if let Err(err) = res { - eprintln!("Error: {}", err); - } - } - res = fut_postgres_finish => { - eprintln!("Postgres exited unexpectedly"); - if let Err(err) = res { - eprintln!("Error: {}", err); - } - } - res = fut_any_processor_finish => { - eprintln!("One of the processors exited unexpectedly"); - if let Err(err) = res { - eprintln!("Error: {}", err); - } - } - res = fut_indexer_api_finish => { - eprintln!("Indexer API exited unexpectedly"); - if let Err(err) = res { - eprintln!("Error: {}", err); - } - } - } - - clean_up_all.await; - - Ok(()) -} +use anyhow::Result; #[tokio::main] async fn main() -> Result<()> { - let test_dir = tempfile::tempdir()?; - - println!("Test directory: {}", test_dir.path().display()); - - run_all_services(test_dir.path()).await?; - - println!("Finished running all services"); + aptos_workspace_server::run_all_services().await?; Ok(()) } diff --git a/aptos-move/aptos-workspace-server/src/services/docker_common.rs b/aptos-move/aptos-workspace-server/src/services/docker_common.rs index 7315a0fd28391..c49da313502fe 100644 --- a/aptos-move/aptos-workspace-server/src/services/docker_common.rs +++ b/aptos-move/aptos-workspace-server/src/services/docker_common.rs @@ -3,7 +3,7 @@ use crate::common::make_shared; use anyhow::{anyhow, bail, Context, Result}; -use aptos::node::local_testnet::docker; +use aptos_localnet::docker; use bollard::{ container::{CreateContainerOptions, InspectContainerOptions, StartContainerOptions}, network::CreateNetworkOptions, diff --git a/aptos-move/aptos-workspace-server/src/services/faucet.rs b/aptos-move/aptos-workspace-server/src/services/faucet.rs index d44c8a7d4bd71..ed9ea036e68b9 100644 --- a/aptos-move/aptos-workspace-server/src/services/faucet.rs +++ b/aptos-move/aptos-workspace-server/src/services/faucet.rs @@ -3,8 +3,8 @@ use crate::common::IP_LOCAL_HOST; use anyhow::{anyhow, Context, Result}; -use aptos::node::local_testnet::HealthChecker; use aptos_faucet_core::server::{FunderKeyEnum, RunConfig}; +use aptos_localnet::health_checker::HealthChecker; use futures::channel::oneshot; use std::{future::Future, path::PathBuf, sync::Arc}; use url::Url; diff --git a/aptos-move/aptos-workspace-server/src/services/indexer_api.rs b/aptos-move/aptos-workspace-server/src/services/indexer_api.rs index 159470709912b..62043db8cf407 100644 --- a/aptos-move/aptos-workspace-server/src/services/indexer_api.rs +++ b/aptos-move/aptos-workspace-server/src/services/indexer_api.rs @@ -7,10 +7,10 @@ use super::{ }; use crate::common::{make_shared, IP_LOCAL_HOST}; use anyhow::{anyhow, Context, Result}; -use aptos::node::local_testnet::{ +use aptos_localnet::{ docker, + health_checker::HealthChecker, indexer_api::{post_metadata, HASURA_IMAGE, HASURA_METADATA}, - HealthChecker, }; use bollard::{ container::{CreateContainerOptions, WaitContainerOptions}, diff --git a/aptos-move/aptos-workspace-server/src/services/node.rs b/aptos-move/aptos-workspace-server/src/services/node.rs index 0ceb165606426..3809023c05de5 100644 --- a/aptos-move/aptos-workspace-server/src/services/node.rs +++ b/aptos-move/aptos-workspace-server/src/services/node.rs @@ -3,8 +3,8 @@ use crate::common::IP_LOCAL_HOST; use anyhow::{bail, Result}; -use aptos::node::local_testnet::HealthChecker; use aptos_config::config::{NodeConfig, TableInfoServiceMode}; +use aptos_localnet::health_checker::HealthChecker; use aptos_node::{load_node_config, start_and_report_ports}; use aptos_types::network_address::{NetworkAddress, Protocol}; use futures::channel::oneshot; diff --git a/aptos-move/aptos-workspace-server/src/services/postgres.rs b/aptos-move/aptos-workspace-server/src/services/postgres.rs index 1a84798a626d1..3ff53471ada94 100644 --- a/aptos-move/aptos-workspace-server/src/services/postgres.rs +++ b/aptos-move/aptos-workspace-server/src/services/postgres.rs @@ -1,10 +1,12 @@ // Copyright (c) Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -use super::docker_common::{create_docker_volume, create_start_and_inspect_container}; -use crate::common::{make_shared, IP_LOCAL_HOST}; +use crate::{ + common::{make_shared, IP_LOCAL_HOST}, + services::docker_common::{create_docker_volume, create_start_and_inspect_container}, +}; use anyhow::{anyhow, Context, Result}; -use aptos::node::local_testnet::{docker, HealthChecker}; +use aptos_localnet::{docker, health_checker::HealthChecker}; use bollard::{ container::{CreateContainerOptions, WaitContainerOptions}, secret::{ContainerInspectResponse, HostConfig, PortBinding}, diff --git a/aptos-move/aptos-workspace-server/src/services/processors.rs b/aptos-move/aptos-workspace-server/src/services/processors.rs index 97a0dc38a64c0..70d99b7b88b46 100644 --- a/aptos-move/aptos-workspace-server/src/services/processors.rs +++ b/aptos-move/aptos-workspace-server/src/services/processors.rs @@ -4,7 +4,7 @@ use super::{node::get_data_service_url, postgres::get_postgres_connection_string}; use crate::common::make_shared; use anyhow::{anyhow, Context, Result}; -use aptos::node::local_testnet::{processors::get_processor_config, HealthChecker}; +use aptos_localnet::{health_checker::HealthChecker, processors::get_processor_config}; use diesel::Connection; use diesel_async::{async_connection_wrapper::AsyncConnectionWrapper, pg::AsyncPgConnection}; use futures::{future::try_join_all, stream::FuturesUnordered, StreamExt}; diff --git a/crates/aptos-localnet/Cargo.toml b/crates/aptos-localnet/Cargo.toml new file mode 100644 index 0000000000000..370ddebccdf73 --- /dev/null +++ b/crates/aptos-localnet/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "aptos-localnet" +version = "0.1.0" + +# Workspace inherited keys +authors = { workspace = true } +edition = { workspace = true } +homepage = { workspace = true } +license = { workspace = true } +publish = { workspace = true } +repository = { workspace = true } +rust-version = { workspace = true } + +[dependencies] +anyhow = { workspace = true } +aptos-indexer-grpc-utils = { workspace = true } +bollard = { workspace = true } +dirs = { workspace = true } +futures = { workspace = true } +tracing = { workspace = true } +version-compare = { workspace = true } + +aptos-protos = { workspace = true } +aptos-rest-client = { workspace = true } +diesel = { workspace = true, features = [ + "postgres_backend", +] } +diesel-async = { workspace = true } +processor = { git = "https://github.com/aptos-labs/aptos-indexer-processors.git", rev = "51a34901b40d7f75767ac907b4d2478104d6a515", default-features = false } +reqwest = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +tokio = { workspace = true } +tonic = { workspace = true } diff --git a/crates/aptos-localnet/src/docker.rs b/crates/aptos-localnet/src/docker.rs new file mode 100644 index 0000000000000..4a899cb7cc57e --- /dev/null +++ b/crates/aptos-localnet/src/docker.rs @@ -0,0 +1,92 @@ +// Copyright (c) Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use anyhow::{Context, Result}; +use bollard::Docker; +#[cfg(unix)] +use bollard::API_DEFAULT_VERSION; +use tracing::{info, warn}; +use version_compare::Version; + +const ERROR_MESSAGE: &str = "Docker is not available, confirm it is installed and running. See https://aptos.dev/guides/local-development-network#faq for assistance."; + +/// This function returns a Docker client. Before returning, it confirms that it can +/// actually query the API and checks that the API version is sufficient. It first +/// tries to connect at the default socket location and if that fails, it tries to find +/// a socket in the user's home directory. On Windows NT it doesn't try that since +/// there no second location, there is just the one named pipe. +pub async fn get_docker() -> Result { + let docker = Docker::connect_with_local_defaults() + .context(format!("{} (init_default)", ERROR_MESSAGE)) + .inspect_err(|e| eprintln!("{:#}", e))?; + + // We have to specify the type because the compiler can't figure out the error + // in the case where the system is Unix. + let out: Result<(Docker, bollard::system::Version), bollard::errors::Error> = + match docker.version().await { + Ok(version) => Ok((docker, version)), + Err(err) => { + warn!( + "Received this error trying to use default Docker socket location: {:#}", + err + ); + // Look for the socket in ~/.docker/run + // We don't have to do this if this issue gets addressed: + // https://github.com/fussybeaver/bollard/issues/345 + #[cfg(unix)] + { + let path = dirs::home_dir() + .context(format!("{} (home_dir)", ERROR_MESSAGE))? + .join(".docker") + .join("run") + .join("docker.sock"); + info!("Looking for Docker socket at {}", path.display()); + let path = path.to_str().context(format!("{} (path)", ERROR_MESSAGE))?; + let docker = Docker::connect_with_socket(path, 120, API_DEFAULT_VERSION) + .context(format!("{} (init_home)", ERROR_MESSAGE))?; + let version = docker + .version() + .await + .context(format!("{} (version_home)", ERROR_MESSAGE))?; + Ok((docker, version)) + } + // Just return the original error. + #[cfg(not(unix))] + Err(err) + }, + }; + let (docker, version) = out?; + + // Try to warn the user about their Docker version being too old. We don't error + // out if the version is too old in case we're wrong about the minimum version + // for their particular system. We just print a warning. + match version.api_version { + Some(current_api_version) => match Version::from(¤t_api_version) { + Some(current_api_version) => { + let minimum_api_version = Version::from("1.42").unwrap(); + if current_api_version < minimum_api_version { + eprintln!( + "WARNING: Docker API version {} is too old, minimum required version is {}. Please update Docker!", + current_api_version, + minimum_api_version, + ); + } else { + info!("Docker version is sufficient: {}", current_api_version); + } + }, + None => { + eprintln!( + "WARNING: Failed to parse Docker API version: {}", + current_api_version + ); + }, + }, + None => { + eprintln!( + "WARNING: Failed to determine Docker version, confirm your Docker is up to date!" + ); + }, + } + + Ok(docker) +} diff --git a/crates/aptos/src/node/local_testnet/hasura_metadata.json b/crates/aptos-localnet/src/hasura_metadata.json similarity index 100% rename from crates/aptos/src/node/local_testnet/hasura_metadata.json rename to crates/aptos-localnet/src/hasura_metadata.json diff --git a/crates/aptos-localnet/src/health_checker.rs b/crates/aptos-localnet/src/health_checker.rs new file mode 100644 index 0000000000000..19edd2fb561aa --- /dev/null +++ b/crates/aptos-localnet/src/health_checker.rs @@ -0,0 +1,216 @@ +// Copyright (c) Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::indexer_api::confirm_metadata_applied; +use anyhow::{anyhow, Context, Result}; +use aptos_protos::indexer::v1::GetTransactionsRequest; +use diesel::{ExpressionMethods, OptionalExtension, QueryDsl}; +use diesel_async::{pg::AsyncPgConnection, AsyncConnection, RunQueryDsl}; +use futures::StreamExt; +use processor::schema::processor_status; +use reqwest::Url; +use serde::Serialize; +use std::time::Duration; +use tokio::time::Instant; +use tracing::info; + +const MAX_WAIT_S: u64 = 60; +const WAIT_INTERVAL_MS: u64 = 200; + +/// This provides a single place to define a variety of different healthchecks. In +/// cases where the name of the service being checked isn't obvious, the enum will take +/// a string arg that names it. +#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize)] +pub enum HealthChecker { + /// Check that a HTTP API is up. The second param is the name of the HTTP service. + Http(Url, String), + /// Check that the node API is up. This is just a specific case of Http for extra + /// guarantees around liveliness. + NodeApi(Url), + /// Check that a data service GRPC stream is up. + DataServiceGrpc(Url), + /// Check that a postgres instance is up. + Postgres(String), + /// Check that a processor is successfully processing txns. The first value is the + /// postgres connection string. The second is the name of the processor. We check + /// the that last_success_version in the processor_status table is present and > 0. + Processor(String, String), + /// Check that the indexer API is up and the metadata has been applied. We only use + /// this one in the ready server. + IndexerApiMetadata(Url), +} + +impl HealthChecker { + pub async fn check(&self) -> Result<()> { + match self { + HealthChecker::Http(url, _) => { + reqwest::get(Url::clone(url)) + .await + .with_context(|| format!("Failed to GET {}", url))?; + Ok(()) + }, + HealthChecker::NodeApi(url) => { + aptos_rest_client::Client::new(Url::clone(url)) + .get_index() + .await?; + Ok(()) + }, + HealthChecker::DataServiceGrpc(url) => { + let mut client = aptos_indexer_grpc_utils::create_data_service_grpc_client( + url.clone(), + Some(Duration::from_secs(5)), + ) + .await?; + let request = tonic::Request::new(GetTransactionsRequest { + starting_version: Some(0), + ..Default::default() + }); + // Make sure we can stream the first message from the stream. + client + .get_transactions(request) + .await + .context("GRPC connection error")? + .into_inner() + .next() + .await + .context("Did not receive init signal from data service GRPC stream")? + .context("Error processing first message from GRPC stream")?; + Ok(()) + }, + HealthChecker::Postgres(connection_string) => { + AsyncPgConnection::establish(connection_string) + .await + .context("Failed to connect to postgres to check DB liveness")?; + Ok(()) + }, + HealthChecker::Processor(connection_string, processor_name) => { + let mut connection = AsyncPgConnection::establish(connection_string) + .await + .context("Failed to connect to postgres to check processor status")?; + let result = processor_status::table + .select((processor_status::last_success_version,)) + .filter(processor_status::processor.eq(processor_name)) + .first::<(i64,)>(&mut connection) + .await + .optional() + .context("Failed to look up processor status")?; + match result { + Some(result) => { + // This is last_success_version. + if result.0 > 0 { + info!( + "Processor {} started processing successfully (currently at version {})", + processor_name, result.0 + ); + Ok(()) + } else { + Err(anyhow!( + "Processor {} found in DB but last_success_version is zero", + processor_name + )) + } + }, + None => Err(anyhow!( + "Processor {} has not processed any transactions", + processor_name + )), + } + }, + HealthChecker::IndexerApiMetadata(url) => { + confirm_metadata_applied(url.clone()).await?; + Ok(()) + }, + } + } + + /// Wait up to MAX_WAIT_S seconds for a service to start up. + pub async fn wait( + &self, + // The service, if any, waiting for this service to start up. + waiting_service: Option<&str>, + ) -> Result<()> { + let prefix = self.to_string(); + wait_for_startup(|| self.check(), match waiting_service { + Some(waiting_service) => { + format!( + "{} at {} did not start up before {}", + prefix, + self.address_str(), + waiting_service, + ) + }, + None => format!("{} at {} did not start up", prefix, self.address_str()), + }) + .await + } + + /// This is only ever used for display purposes. If possible, this should be the + /// endpoint of the service that this HealthChecker is checking. + pub fn address_str(&self) -> &str { + match self { + HealthChecker::Http(url, _) => url.as_str(), + HealthChecker::NodeApi(url) => url.as_str(), + HealthChecker::DataServiceGrpc(url) => url.as_str(), + HealthChecker::Postgres(url) => url.as_str(), + HealthChecker::Processor(_, processor_name) => processor_name.as_str(), + HealthChecker::IndexerApiMetadata(url) => url.as_str(), + } + } + + /// Given a port, make an instance of HealthChecker::Http targeting 127.0.0.1. + pub fn http_checker_from_port(port: u16, name: String) -> Self { + Self::Http( + Url::parse(&format!("http://127.0.0.1:{}", port,)).unwrap(), + name, + ) + } +} + +impl std::fmt::Display for HealthChecker { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + HealthChecker::Http(_, name) => write!(f, "{}", name), + HealthChecker::NodeApi(_) => write!(f, "Node API"), + HealthChecker::DataServiceGrpc(_) => write!(f, "Transaction stream"), + HealthChecker::Postgres(_) => write!(f, "Postgres"), + HealthChecker::Processor(_, processor_name) => write!(f, "{}", processor_name), + HealthChecker::IndexerApiMetadata(_) => write!(f, "Indexer API with metadata applied"), + } + } +} + +async fn wait_for_startup(check_fn: F, error_message: String) -> Result<()> +where + F: Fn() -> Fut, + Fut: futures::Future>, +{ + let max_wait = Duration::from_secs(MAX_WAIT_S); + let wait_interval = Duration::from_millis(WAIT_INTERVAL_MS); + + let start = Instant::now(); + let mut started_successfully = false; + + let mut last_error_message = None; + while start.elapsed() < max_wait { + match check_fn().await { + Ok(_) => { + started_successfully = true; + break; + }, + Err(err) => { + last_error_message = Some(format!("{:#}", err)); + }, + } + tokio::time::sleep(wait_interval).await + } + + if !started_successfully { + let error_message = match last_error_message { + Some(last_error_message) => format!("{}: {}", error_message, last_error_message), + None => error_message, + }; + return Err(anyhow!(error_message)); + } + + Ok(()) +} diff --git a/crates/aptos-localnet/src/indexer_api.rs b/crates/aptos-localnet/src/indexer_api.rs new file mode 100644 index 0000000000000..673add052b68a --- /dev/null +++ b/crates/aptos-localnet/src/indexer_api.rs @@ -0,0 +1,122 @@ +// Copyright (c) Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use anyhow::{anyhow, Context, Result}; +use reqwest::Url; +use tracing::info; + +pub const HASURA_IMAGE: &str = "hasura/graphql-engine:v2.44.0-ce"; + +/// This Hasura metadata originates from the aptos-indexer-processors repo. +/// +/// This metadata here should come from the same revision as the `processor` dep. +/// +/// The metadata file is not taken verbatim, it is currently edited by hand to remove +/// any references to tables that aren't created by the Rust processor migrations. +/// +/// To arrive at the final edited file I normally start with the new metadata file, +/// try to start the localnet, and check .aptos/testnet/main/tracing.log to +/// see what error Hasura returned. Remove the culprit from the metadata, which is +/// generally a few tables and relations to those tables, and try again. Repeat until +/// it accepts the metadata. +/// +/// This works fine today since all the key processors you'd need in a localnet +/// are in the set of processors written in Rust. If this changes, we can explore +/// alternatives, e.g. running processors in other languages using containers. +pub const HASURA_METADATA: &str = include_str!("hasura_metadata.json"); + +/// This submits a POST request to apply metadata to a Hasura API. +pub async fn post_metadata(url: Url, metadata_content: &str) -> Result<()> { + // Parse the metadata content as JSON. + let metadata_json: serde_json::Value = serde_json::from_str(metadata_content)?; + + // Make the request. + info!("Submitting request to apply Hasura metadata"); + let response = + make_hasura_metadata_request(url, "replace_metadata", Some(metadata_json)).await?; + info!( + "Received response for applying Hasura metadata: {:?}", + response + ); + + // Confirm that the metadata was applied successfully and there is no inconsistency + // between the schema and the underlying DB schema. + if let Some(obj) = response.as_object() { + if let Some(is_consistent_val) = obj.get("is_consistent") { + if is_consistent_val.as_bool() == Some(true) { + return Ok(()); + } + } + } + + Err(anyhow!( + "Something went wrong applying the Hasura metadata, perhaps it is not consistent with the DB. Response: {:#?}", + response + )) +} + +/// This confirms that the metadata has been applied. We use this in the health +/// checker. +pub async fn confirm_metadata_applied(url: Url) -> Result<()> { + // Make the request. + info!("Confirming Hasura metadata applied..."); + let response = make_hasura_metadata_request(url, "export_metadata", None).await?; + info!( + "Received response for confirming Hasura metadata applied: {:?}", + response + ); + + // If the sources field is set it means the metadata was applied successfully. + if let Some(obj) = response.as_object() { + if let Some(sources) = obj.get("sources") { + if let Some(sources) = sources.as_array() { + if !sources.is_empty() { + return Ok(()); + } + } + } + } + + Err(anyhow!( + "The Hasura metadata has not been applied yet. Response: {:#?}", + response + )) +} + +/// The /v1/metadata endpoint supports a few different operations based on the `type` +/// field in the request body. All requests have a similar format, with these `type` +/// and `args` fields. +pub async fn make_hasura_metadata_request( + mut url: Url, + typ: &str, + args: Option, +) -> Result { + let client = reqwest::Client::new(); + + // Update the query path. + url.set_path("/v1/metadata"); + + // Construct the payload. + let mut payload = serde_json::Map::new(); + payload.insert( + "type".to_string(), + serde_json::Value::String(typ.to_string()), + ); + + // If args is provided, use that. Otherwise use an empty object. We have to set it + // no matter what because the API expects the args key to be set. + let args = match args { + Some(args) => args, + None => serde_json::Value::Object(serde_json::Map::new()), + }; + payload.insert("args".to_string(), args); + + // Send the POST request. + let response = client.post(url).json(&payload).send().await?; + + // Return the response as a JSON value. + response + .json() + .await + .context("Failed to parse response as JSON") +} diff --git a/crates/aptos-localnet/src/lib.rs b/crates/aptos-localnet/src/lib.rs new file mode 100644 index 0000000000000..cfcf78d6d8fb3 --- /dev/null +++ b/crates/aptos-localnet/src/lib.rs @@ -0,0 +1,13 @@ +// Copyright (c) Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +//! This is a library that provides functionalities required for running a local Aptos network, +//! use by `aptos-workspace-server`` and the CLI's localnet command. +//! +//! Currently it only contains some utility functions, but more code will be moved here over +//! time. + +pub mod docker; +pub mod health_checker; +pub mod indexer_api; +pub mod processors; diff --git a/crates/aptos-localnet/src/processors.rs b/crates/aptos-localnet/src/processors.rs new file mode 100644 index 0000000000000..350de43e2d667 --- /dev/null +++ b/crates/aptos-localnet/src/processors.rs @@ -0,0 +1,66 @@ +// Copyright (c) Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use anyhow::{bail, Result}; +use processor::processors::{ + objects_processor::ObjectsProcessorConfig, stake_processor::StakeProcessorConfig, + token_v2_processor::TokenV2ProcessorConfig, ProcessorConfig, ProcessorName, +}; + +pub fn get_processor_config(processor_name: &ProcessorName) -> Result { + Ok(match processor_name { + ProcessorName::AccountTransactionsProcessor => { + ProcessorConfig::AccountTransactionsProcessor + }, + ProcessorName::AnsProcessor => { + bail!("ANS processor is not supported in the localnet") + }, + ProcessorName::DefaultProcessor => ProcessorConfig::DefaultProcessor, + ProcessorName::EventsProcessor => ProcessorConfig::EventsProcessor, + ProcessorName::FungibleAssetProcessor => ProcessorConfig::FungibleAssetProcessor, + ProcessorName::MonitoringProcessor => { + bail!("Monitoring processor is not supported in the localnet") + }, + ProcessorName::NftMetadataProcessor => { + bail!("NFT Metadata processor is not supported in the localnet") + }, + ProcessorName::ObjectsProcessor => { + ProcessorConfig::ObjectsProcessor(ObjectsProcessorConfig { + query_retries: Default::default(), + query_retry_delay_ms: Default::default(), + }) + }, + ProcessorName::ParquetDefaultProcessor => { + bail!("ParquetDefaultProcessor is not supported in the localnet") + }, + ProcessorName::ParquetFungibleAssetProcessor => { + bail!("ParquetFungibleAssetProcessor is not supported in the localnet") + }, + ProcessorName::ParquetTransactionMetadataProcessor => { + bail!("ParquetTransactionMetadataProcessor is not supported in the localnet") + }, + ProcessorName::ParquetAnsProcessor => { + bail!("ParquetAnsProcessor is not supported in the localnet") + }, + ProcessorName::ParquetEventsProcessor => { + bail!("ParquetEventsProcessor is not supported in the localnet") + }, + ProcessorName::ParquetTokenV2Processor => { + bail!("ParquetTokenV2Processor is not supported in the localnet") + }, + ProcessorName::StakeProcessor => ProcessorConfig::StakeProcessor(StakeProcessorConfig { + query_retries: Default::default(), + query_retry_delay_ms: Default::default(), + }), + ProcessorName::TokenV2Processor => { + ProcessorConfig::TokenV2Processor(TokenV2ProcessorConfig { + query_retries: Default::default(), + query_retry_delay_ms: Default::default(), + }) + }, + ProcessorName::TransactionMetadataProcessor => { + ProcessorConfig::TransactionMetadataProcessor + }, + ProcessorName::UserTransactionProcessor => ProcessorConfig::UserTransactionProcessor, + }) +} diff --git a/crates/aptos/Cargo.toml b/crates/aptos/Cargo.toml index 9970cad41819d..4e8c393472f65 100644 --- a/crates/aptos/Cargo.toml +++ b/crates/aptos/Cargo.toml @@ -33,6 +33,7 @@ aptos-indexer-grpc-server-framework = { workspace = true } aptos-indexer-grpc-utils = { workspace = true } aptos-keygen = { workspace = true } aptos-ledger = { workspace = true } +aptos-localnet = { workspace = true } aptos-logger = { workspace = true } aptos-move-debugger = { workspace = true } aptos-network-checker = { workspace = true } @@ -49,6 +50,7 @@ aptos-vm-environment = { workspace = true } aptos-vm-genesis = { workspace = true } aptos-vm-logging = { workspace = true } aptos-vm-types = { workspace = true } +aptos-workspace-server = { workspace = true } async-trait = { workspace = true } base64 = { workspace = true } bcs = { workspace = true } @@ -107,7 +109,6 @@ tonic = { workspace = true } tracing = { workspace = true } tracing-subscriber = { workspace = true } url = { workspace = true } -version-compare = { workspace = true } [target.'cfg(unix)'.dependencies] jemallocator = { workspace = true } diff --git a/crates/aptos/src/lib.rs b/crates/aptos/src/lib.rs index 49a0d3c79816b..5dbe6413482d2 100644 --- a/crates/aptos/src/lib.rs +++ b/crates/aptos/src/lib.rs @@ -16,6 +16,7 @@ pub mod stake; #[cfg(any(test, feature = "fuzzing"))] pub mod test; pub mod update; +pub mod workspace; use crate::common::{ types::{CliCommand, CliResult, CliTypedResult}, @@ -51,6 +52,8 @@ pub enum Tool { Stake(stake::StakeTool), #[clap(subcommand)] Update(update::UpdateTool), + #[clap(subcommand, hide(true))] + Workspace(workspace::WorkspaceTool), } impl Tool { @@ -70,6 +73,7 @@ impl Tool { Node(tool) => tool.execute().await, Stake(tool) => tool.execute().await, Update(tool) => tool.execute().await, + Workspace(tool) => tool.execute().await, } } } diff --git a/crates/aptos/src/node/local_testnet/docker.rs b/crates/aptos/src/node/local_testnet/docker.rs index a118c6eea598c..c1eeff465fc59 100644 --- a/crates/aptos/src/node/local_testnet/docker.rs +++ b/crates/aptos/src/node/local_testnet/docker.rs @@ -3,107 +3,21 @@ use super::traits::ShutdownStep; use anyhow::{Context, Result}; +pub use aptos_localnet::docker::get_docker; use async_trait::async_trait; -#[cfg(unix)] -use bollard::API_DEFAULT_VERSION; use bollard::{ container::{RemoveContainerOptions, StopContainerOptions}, errors::Error as BollardError, image::CreateImageOptions, network::CreateNetworkOptions, volume::{CreateVolumeOptions, RemoveVolumeOptions}, - Docker, }; use futures::TryStreamExt; use std::{fs::create_dir_all, path::Path}; use tracing::{info, warn}; -use version_compare::Version; - -const ERROR_MESSAGE: &str = "Docker is not available, confirm it is installed and running. See https://aptos.dev/guides/local-development-network#faq for assistance."; pub const CONTAINER_NETWORK_NAME: &str = "aptos-local-testnet-network"; -/// This function returns a Docker client. Before returning, it confirms that it can -/// actually query the API and checks that the API version is sufficient. It first -/// tries to connect at the default socket location and if that fails, it tries to find -/// a socket in the user's home directory. On Windows NT it doesn't try that since -/// there no second location, there is just the one named pipe. -pub async fn get_docker() -> Result { - let docker = Docker::connect_with_local_defaults() - .context(format!("{} (init_default)", ERROR_MESSAGE)) - .inspect_err(|e| eprintln!("{:#}", e))?; - - // We have to specify the type because the compiler can't figure out the error - // in the case where the system is Unix. - let out: Result<(Docker, bollard::system::Version), bollard::errors::Error> = - match docker.version().await { - Ok(version) => Ok((docker, version)), - Err(err) => { - warn!( - "Received this error trying to use default Docker socket location: {:#}", - err - ); - // Look for the socket in ~/.docker/run - // We don't have to do this if this issue gets addressed: - // https://github.com/fussybeaver/bollard/issues/345 - #[cfg(unix)] - { - let path = dirs::home_dir() - .context(format!("{} (home_dir)", ERROR_MESSAGE))? - .join(".docker") - .join("run") - .join("docker.sock"); - info!("Looking for Docker socket at {}", path.display()); - let path = path.to_str().context(format!("{} (path)", ERROR_MESSAGE))?; - let docker = Docker::connect_with_socket(path, 120, API_DEFAULT_VERSION) - .context(format!("{} (init_home)", ERROR_MESSAGE))?; - let version = docker - .version() - .await - .context(format!("{} (version_home)", ERROR_MESSAGE))?; - Ok((docker, version)) - } - // Just return the original error. - #[cfg(not(unix))] - Err(err) - }, - }; - let (docker, version) = out?; - - // Try to warn the user about their Docker version being too old. We don't error - // out if the version is too old in case we're wrong about the minimum version - // for their particular system. We just print a warning. - match version.api_version { - Some(current_api_version) => match Version::from(¤t_api_version) { - Some(current_api_version) => { - let minimum_api_version = Version::from("1.42").unwrap(); - if current_api_version < minimum_api_version { - eprintln!( - "WARNING: Docker API version {} is too old, minimum required version is {}. Please update Docker!", - current_api_version, - minimum_api_version, - ); - } else { - info!("Docker version is sufficient: {}", current_api_version); - } - }, - None => { - eprintln!( - "WARNING: Failed to parse Docker API version: {}", - current_api_version - ); - }, - }, - None => { - eprintln!( - "WARNING: Failed to determine Docker version, confirm your Docker is up to date!" - ); - }, - } - - Ok(docker) -} - /// Delete a container. If the container doesn't exist, that's fine, just move on. pub async fn delete_container(container_name: &str) -> Result<()> { info!( diff --git a/crates/aptos/src/node/local_testnet/indexer_api.rs b/crates/aptos/src/node/local_testnet/indexer_api.rs index 7c9dc6dafe3ed..5d0ca124f0ddf 100644 --- a/crates/aptos/src/node/local_testnet/indexer_api.rs +++ b/crates/aptos/src/node/local_testnet/indexer_api.rs @@ -11,6 +11,9 @@ use super::{ RunLocalnet, }; use anyhow::{anyhow, Context, Result}; +pub use aptos_localnet::indexer_api::{ + make_hasura_metadata_request, post_metadata, HASURA_IMAGE, HASURA_METADATA, +}; use async_trait::async_trait; use bollard::{ container::{Config, CreateContainerOptions, StartContainerOptions, WaitContainerOptions}, @@ -24,25 +27,6 @@ use std::{collections::HashSet, path::PathBuf, time::Duration}; use tracing::{info, warn}; const INDEXER_API_CONTAINER_NAME: &str = "local-testnet-indexer-api"; -pub const HASURA_IMAGE: &str = "hasura/graphql-engine:v2.44.0-ce"; - -/// This Hasura metadata originates from the aptos-indexer-processors repo. -/// -/// This metadata here should come from the same revision as the `processor` dep. -/// -/// The metadata file is not taken verbatim, it is currently edited by hand to remove -/// any references to tables that aren't created by the Rust processor migrations. -/// -/// To arrive at the final edited file I normally start with the new metadata file, -/// try to start the localnet, and check .aptos/testnet/main/tracing.log to -/// see what error Hasura returned. Remove the culprit from the metadata, which is -/// generally a few tables and relations to those tables, and try again. Repeat until -/// it accepts the metadata. -/// -/// This works fine today since all the key processors you'd need in a localnet -/// are in the set of processors written in Rust. If this changes, we can explore -/// alternatives, e.g. running processors in other languages using containers. -pub const HASURA_METADATA: &str = include_str!("hasura_metadata.json"); /// Args related to running an indexer API for the localnet. #[derive(Debug, Parser)] @@ -336,36 +320,6 @@ impl ServiceManager for IndexerApiManager { } } -/// This submits a POST request to apply metadata to a Hasura API. -pub async fn post_metadata(url: Url, metadata_content: &str) -> Result<()> { - // Parse the metadata content as JSON. - let metadata_json: serde_json::Value = serde_json::from_str(metadata_content)?; - - // Make the request. - info!("Submitting request to apply Hasura metadata"); - let response = - make_hasura_metadata_request(url, "replace_metadata", Some(metadata_json)).await?; - info!( - "Received response for applying Hasura metadata: {:?}", - response - ); - - // Confirm that the metadata was applied successfully and there is no inconsistency - // between the schema and the underlying DB schema. - if let Some(obj) = response.as_object() { - if let Some(is_consistent_val) = obj.get("is_consistent") { - if is_consistent_val.as_bool() == Some(true) { - return Ok(()); - } - } - } - - Err(anyhow!( - "Something went wrong applying the Hasura metadata, perhaps it is not consistent with the DB. Response: {:#?}", - response - )) -} - /// This confirms that the metadata has been applied. We use this in the health /// checker. pub async fn confirm_metadata_applied(url: Url) -> Result<()> { @@ -393,41 +347,3 @@ pub async fn confirm_metadata_applied(url: Url) -> Result<()> { response )) } - -/// The /v1/metadata endpoint supports a few different operations based on the `type` -/// field in the request body. All requests have a similar format, with these `type` -/// and `args` fields. -async fn make_hasura_metadata_request( - mut url: Url, - typ: &str, - args: Option, -) -> Result { - let client = reqwest::Client::new(); - - // Update the query path. - url.set_path("/v1/metadata"); - - // Construct the payload. - let mut payload = serde_json::Map::new(); - payload.insert( - "type".to_string(), - serde_json::Value::String(typ.to_string()), - ); - - // If args is provided, use that. Otherwise use an empty object. We have to set it - // no matter what because the API expects the args key to be set. - let args = match args { - Some(args) => args, - None => serde_json::Value::Object(serde_json::Map::new()), - }; - payload.insert("args".to_string(), args); - - // Send the POST request. - let response = client.post(url).json(&payload).send().await?; - - // Return the response as a JSON value. - response - .json() - .await - .context("Failed to parse response as JSON") -} diff --git a/crates/aptos/src/node/local_testnet/processors.rs b/crates/aptos/src/node/local_testnet/processors.rs index 4be69ac2e5bf2..e8fbf21ab376b 100644 --- a/crates/aptos/src/node/local_testnet/processors.rs +++ b/crates/aptos/src/node/local_testnet/processors.rs @@ -3,19 +3,15 @@ use super::{health_checker::HealthChecker, traits::ServiceManager, RunLocalnet}; use anyhow::{bail, Context, Result}; +pub use aptos_localnet::processors::get_processor_config; use async_trait::async_trait; use clap::Parser; use diesel::Connection; use diesel_async::{async_connection_wrapper::AsyncConnectionWrapper, pg::AsyncPgConnection}; use maplit::hashset; use processor::{ - gap_detectors::DEFAULT_GAP_DETECTION_BATCH_SIZE, - processors::{ - objects_processor::ObjectsProcessorConfig, stake_processor::StakeProcessorConfig, - token_v2_processor::TokenV2ProcessorConfig, ProcessorConfig, ProcessorName, - }, - utils::database::run_pending_migrations, - IndexerGrpcProcessorConfig, + gap_detectors::DEFAULT_GAP_DETECTION_BATCH_SIZE, processors::ProcessorName, + utils::database::run_pending_migrations, IndexerGrpcProcessorConfig, }; use reqwest::Url; use server_framework::RunnableConfig; @@ -57,64 +53,6 @@ pub struct ProcessorManager { prerequisite_health_checkers: HashSet, } -pub fn get_processor_config(processor_name: &ProcessorName) -> Result { - Ok(match processor_name { - ProcessorName::AccountTransactionsProcessor => { - ProcessorConfig::AccountTransactionsProcessor - }, - ProcessorName::AnsProcessor => { - bail!("ANS processor is not supported in the localnet") - }, - ProcessorName::DefaultProcessor => ProcessorConfig::DefaultProcessor, - ProcessorName::EventsProcessor => ProcessorConfig::EventsProcessor, - ProcessorName::FungibleAssetProcessor => ProcessorConfig::FungibleAssetProcessor, - ProcessorName::MonitoringProcessor => { - bail!("Monitoring processor is not supported in the localnet") - }, - ProcessorName::NftMetadataProcessor => { - bail!("NFT Metadata processor is not supported in the localnet") - }, - ProcessorName::ObjectsProcessor => { - ProcessorConfig::ObjectsProcessor(ObjectsProcessorConfig { - query_retries: Default::default(), - query_retry_delay_ms: Default::default(), - }) - }, - ProcessorName::ParquetDefaultProcessor => { - bail!("ParquetDefaultProcessor is not supported in the localnet") - }, - ProcessorName::ParquetFungibleAssetProcessor => { - bail!("ParquetFungibleAssetProcessor is not supported in the localnet") - }, - ProcessorName::ParquetTransactionMetadataProcessor => { - bail!("ParquetTransactionMetadataProcessor is not supported in the localnet") - }, - ProcessorName::ParquetAnsProcessor => { - bail!("ParquetAnsProcessor is not supported in the localnet") - }, - ProcessorName::ParquetEventsProcessor => { - bail!("ParquetEventsProcessor is not supported in the localnet") - }, - ProcessorName::ParquetTokenV2Processor => { - bail!("ParquetTokenV2Processor is not supported in the localnet") - }, - ProcessorName::StakeProcessor => ProcessorConfig::StakeProcessor(StakeProcessorConfig { - query_retries: Default::default(), - query_retry_delay_ms: Default::default(), - }), - ProcessorName::TokenV2Processor => { - ProcessorConfig::TokenV2Processor(TokenV2ProcessorConfig { - query_retries: Default::default(), - query_retry_delay_ms: Default::default(), - }) - }, - ProcessorName::TransactionMetadataProcessor => { - ProcessorConfig::TransactionMetadataProcessor - }, - ProcessorName::UserTransactionProcessor => ProcessorConfig::UserTransactionProcessor, - }) -} - impl ProcessorManager { fn new( processor_name: &ProcessorName, diff --git a/crates/aptos/src/workspace/mod.rs b/crates/aptos/src/workspace/mod.rs new file mode 100644 index 0000000000000..8b4827d8f8c3c --- /dev/null +++ b/crates/aptos/src/workspace/mod.rs @@ -0,0 +1,38 @@ +// Copyright (c) Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::common::types::{CliCommand, CliResult, CliTypedResult}; +use async_trait::async_trait; +use clap::Parser; + +/// Tool for operations related to Aptos Workspace +#[derive(Parser)] +pub enum WorkspaceTool { + Run(RunWorkspace), +} + +impl WorkspaceTool { + pub async fn execute(self) -> CliResult { + use WorkspaceTool::*; + + match self { + Run(cmd) => cmd.execute_serialized_without_logger().await, + } + } +} + +#[derive(Parser)] +pub struct RunWorkspace; + +#[async_trait] +impl CliCommand<()> for RunWorkspace { + fn command_name(&self) -> &'static str { + "RunWorkspace" + } + + async fn execute(self) -> CliTypedResult<()> { + aptos_workspace_server::run_all_services().await?; + + Ok(()) + } +} From 8616cb618d91d18e3e4df6dfe53a89552d2d83a5 Mon Sep 17 00:00:00 2001 From: Bo Wu Date: Mon, 2 Dec 2024 10:32:39 -0800 Subject: [PATCH 44/78] write blockinfo schemas when restoring sharded db --- Cargo.lock | 2 + storage/aptosdb/src/backup/restore_utils.rs | 17 +++ storage/db-tool/Cargo.toml | 2 + storage/db-tool/src/tests.rs | 134 +++++++++++++++----- storage/indexer/src/lib.rs | 2 +- 5 files changed, 123 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9c5d1f9def8f1..57d19e14925d9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1267,9 +1267,11 @@ dependencies = [ "aptos-block-executor", "aptos-config", "aptos-db", + "aptos-db-indexer", "aptos-executor", "aptos-executor-test-helpers", "aptos-executor-types", + "aptos-indexer-grpc-table-info", "aptos-logger", "aptos-storage-interface", "aptos-temppath", diff --git a/storage/aptosdb/src/backup/restore_utils.rs b/storage/aptosdb/src/backup/restore_utils.rs index df8a7400eff62..21b4acdb015d5 100644 --- a/storage/aptosdb/src/backup/restore_utils.rs +++ b/storage/aptosdb/src/backup/restore_utils.rs @@ -22,6 +22,7 @@ use aptos_storage_interface::{ db_ensure as ensure, state_store::state_delta::StateDelta, AptosDbError, Result, }; use aptos_types::{ + account_config::new_block_event_key, contract_event::ContractEvent, ledger_info::LedgerInfoWithSignatures, proof::{ @@ -229,6 +230,22 @@ pub(crate) fn save_transactions_impl( events, &ledger_db_batch.event_db_batches, )?; + + if ledger_db.enable_storage_sharding() { + for (idx, txn_events) in events.iter().enumerate() { + for event in txn_events { + if let Some(event_key) = event.event_key() { + if *event_key == new_block_event_key() { + LedgerMetadataDb::put_block_info( + first_version + idx as Version, + event, + &ledger_db_batch.ledger_metadata_db_batches, + )?; + } + } + } + } + } // insert changes in write set schema batch for (idx, ws) in write_sets.iter().enumerate() { WriteSetDb::put_write_set( diff --git a/storage/db-tool/Cargo.toml b/storage/db-tool/Cargo.toml index cfdbaff99bc22..f9e02d09ccff8 100644 --- a/storage/db-tool/Cargo.toml +++ b/storage/db-tool/Cargo.toml @@ -17,6 +17,7 @@ aptos-backup-cli = { workspace = true } aptos-block-executor = { workspace = true } aptos-config = { workspace = true } aptos-db = { workspace = true, features = ["db-debugger"] } +aptos-db-indexer = { workspace = true } aptos-executor = { workspace = true } aptos-executor-types = { workspace = true } aptos-logger = { workspace = true } @@ -35,3 +36,4 @@ tokio = { workspace = true } aptos-backup-cli = { workspace = true, features = ["testing"] } aptos-backup-service = { workspace = true } aptos-executor-test-helpers = { workspace = true } +aptos-indexer-grpc-table-info = { workspace = true } diff --git a/storage/db-tool/src/tests.rs b/storage/db-tool/src/tests.rs index 578110a408b93..3368026aca9a2 100644 --- a/storage/db-tool/src/tests.rs +++ b/storage/db-tool/src/tests.rs @@ -80,7 +80,6 @@ mod dbtool_tests { storage::{local_fs::LocalFs, BackupStorage}, utils::test_utils::start_local_backup_service, }; - use aptos_config::config::{RocksdbConfigs, StorageDirPaths}; use aptos_db::AptosDB; use aptos_executor_test_helpers::integration_test_impl::{ test_execution_with_storage_impl, test_execution_with_storage_impl_inner, @@ -288,10 +287,15 @@ mod dbtool_tests { new_db_dir: PathBuf, force_sharding: bool, ) -> (Runtime, String) { + use aptos_config::config::{ + RocksdbConfigs, StorageDirPaths, BUFFERED_STATE_TARGET_ITEMS_FOR_TEST, + NO_OP_STORAGE_PRUNER_CONFIG, + }; use aptos_db::utils::iterators::PrefixedStateValueIterator; + use aptos_db_indexer::utils::PrefixedStateValueIterator as IndexerPrefixedStateValueIterator; + use aptos_indexer_grpc_table_info::internal_indexer_db_service::InternalIndexerDBService; use itertools::zip_eq; - - let db = test_execution_with_storage_impl_inner(force_sharding, old_db_dir.as_path()); + let db = test_execution_with_storage_impl_inner(false, old_db_dir.as_path()); let (rt, port) = start_local_backup_service(Arc::clone(&db)); let server_addr = format!(" http://localhost:{}", port); // Backup the local_test DB @@ -443,7 +447,7 @@ mod dbtool_tests { backup_dir.as_path().to_str().unwrap().to_string(), ]; if force_sharding { - let additional_args = vec!["--enable-storage-sharding"] + let additional_args = vec!["--enable-storage-sharding", "--enable-state-indices"] .into_iter() .map(|s| s.to_string()) .collect::>(); @@ -461,49 +465,115 @@ mod dbtool_tests { ..Default::default() } }; - let (_ledger_db, tree_db, state_kv_db) = - AptosDB::open_dbs(&StorageDirPaths::from_path(new_db_dir), db_config, false, 0) - .unwrap(); // assert the kv are the same in db and new_db // current all the kv are still stored in the ledger db // - for ver in start..=end { - let new_iter = PrefixedStateValueIterator::new( - &state_kv_db, + + if !force_sharding { + let (_ledger_db, tree_db, state_kv_db) = + AptosDB::open_dbs(&StorageDirPaths::from_path(new_db_dir), db_config, false, 0) + .unwrap(); + for ver in start..=end { + let new_iter = PrefixedStateValueIterator::new( + &state_kv_db, + StateKeyPrefix::new(AccessPath, b"".to_vec()), + None, + ver, + ) + .unwrap(); + + let old_iter = db + .deref() + .get_prefixed_state_value_iterator( + &StateKeyPrefix::new(AccessPath, b"".to_vec()), + None, + ver, + ) + .unwrap(); + + zip_eq(new_iter, old_iter).for_each(|(new, old)| { + let (new_key, new_value) = new.unwrap(); + let (old_key, old_value) = old.unwrap(); + assert_eq!(new_key, old_key); + assert_eq!(new_value, old_value); + }); + // first snapshot tree not recovered + assert!( + tree_db.get_root_hash(0).is_err() || tree_db.get_leaf_count(0).unwrap() == 0, + "tree at version 0 should not be restored" + ); + // second snapshot tree recovered + let second_snapshot_version: Version = 13; + assert!( + tree_db.get_root_hash(second_snapshot_version).is_ok(), + "root hash at version {} doesn't exist", + second_snapshot_version, + ); + } + } else { + let internal_indexer_db = + InternalIndexerDBService::get_indexer_db_for_restore(new_db_dir.as_path()).unwrap(); + + let aptos_db: Arc = Arc::new( + AptosDB::open( + StorageDirPaths::from_path(new_db_dir), + false, + NO_OP_STORAGE_PRUNER_CONFIG, + db_config, + false, + BUFFERED_STATE_TARGET_ITEMS_FOR_TEST, + 1000, + Some(internal_indexer_db.clone()), + ) + .unwrap(), + ); + + // Only state key at and by the snapshot version are restored in internal indexer + let snapshot_version = if start == 0 { + 0 + } else if start > 0 && start < 15 { + 1 + } else { + 15 + }; + + let new_iter = IndexerPrefixedStateValueIterator::new( + aptos_db.clone(), + internal_indexer_db.get_inner_db_ref(), StateKeyPrefix::new(AccessPath, b"".to_vec()), None, - ver, + snapshot_version, ) .unwrap(); + let old_iter = db .deref() .get_prefixed_state_value_iterator( &StateKeyPrefix::new(AccessPath, b"".to_vec()), None, - ver, + snapshot_version, ) .unwrap(); - zip_eq(new_iter, old_iter).for_each(|(new, old)| { - let (new_key, new_value) = new.unwrap(); - let (old_key, old_value) = old.unwrap(); - assert_eq!(new_key, old_key); - assert_eq!(new_value, old_value); - }); + // collect all the keys in the new_iter + let mut new_keys = new_iter.map(|e| e.unwrap().0).collect::>(); + new_keys.sort(); + let mut old_keys = old_iter.map(|e| e.unwrap().0).collect::>(); + old_keys.sort(); + assert_eq!(new_keys, old_keys); + + let ledger_version = aptos_db.get_latest_ledger_info_version().unwrap(); + for ver in start..=ledger_version { + let old_block_res = db.get_block_info_by_version(ver); + let new_block_res = aptos_db.get_block_info_by_version(ver); + let (old_block_version, old_block_height, _) = old_block_res.unwrap(); + let (new_block_version, new_block_height, _) = new_block_res.unwrap(); + assert_eq!(old_block_version, new_block_version); + assert_eq!(old_block_height, new_block_height); + } } - // first snapshot tree not recovered - assert!( - tree_db.get_root_hash(0).is_err() || tree_db.get_leaf_count(0).unwrap() == 0, - "tree at version 0 should not be restored" - ); - // second snapshot tree recovered - let second_snapshot_version: Version = 13; - assert!( - tree_db.get_root_hash(second_snapshot_version).is_ok(), - "root hash at version {} doesn't exist", - second_snapshot_version, - ); + (rt, server_addr) } #[test] @@ -589,8 +659,6 @@ mod dbtool_tests { } #[test] - #[ignore] - // TODO(grao): Re-enable this test. fn test_restore_with_sharded_db() { let backup_dir = TempPath::new(); backup_dir.create_as_dir().unwrap(); @@ -598,7 +666,7 @@ mod dbtool_tests { let old_db_dir = TempPath::new(); let (rt, _) = db_restore_test_setup( - 16, + 0, 16, PathBuf::from(backup_dir.path()), PathBuf::from(old_db_dir.path()), diff --git a/storage/indexer/src/lib.rs b/storage/indexer/src/lib.rs index 2929953d787a9..86229a0ff26ae 100644 --- a/storage/indexer/src/lib.rs +++ b/storage/indexer/src/lib.rs @@ -9,7 +9,7 @@ pub mod db_v2; pub mod event_v2_translator; pub mod indexer_reader; mod metrics; -mod utils; +pub mod utils; use crate::db::INDEX_DB_NAME; use aptos_config::config::RocksdbConfig; From 75308c1d25675f48e7b704d8671f0fb92f0e8da7 Mon Sep 17 00:00:00 2001 From: Junkil Park Date: Thu, 12 Dec 2024 12:46:58 -0800 Subject: [PATCH 45/78] enable the periodical_reward_rate_decrease feature on devnet by default (#15565) - Enabled the periodical_reward_rate_decrease feature by default on the devnet. - Fixed the broken tests resulting from this change. - Initialize VotingRecordsV2 (for partial voting) and StakingRewardsConfig (for periodical_reward_rate_decrease) in genesis --- .../Move.toml | 0 .../sources/main.move | 7 +----- aptos-move/e2e-move-tests/src/tests/stake.rs | 4 +-- .../sources/main.move | 1 - .../aptos-framework/doc/aptos_governance.md | 3 +++ .../framework/aptos-framework/doc/genesis.md | 2 +- .../aptos-framework/doc/staking_config.md | 15 +++++++++++ .../sources/aptos_governance.move | 4 +-- .../sources/aptos_governance.spec.move | 2 ++ .../sources/configs/staking_config.move | 25 ++++++++++++++++--- .../sources/configs/staking_config.spec.move | 4 +++ .../sources/delegation_pool.move | 8 ------ .../aptos-framework/sources/genesis.move | 2 +- .../aptos-framework/sources/stake.move | 5 ++++ .../sources/staking_contract.move | 9 ++----- .../aptos-framework/sources/vesting.move | 9 ++----- .../executor/tests/internal_indexer_test.rs | 2 ++ types/src/on_chain_config/aptos_features.rs | 1 + 18 files changed, 64 insertions(+), 39 deletions(-) rename aptos-move/e2e-move-tests/src/tests/stake.data/{enable_rewards_rate_decrease => update_rewards_config}/Move.toml (100%) rename aptos-move/e2e-move-tests/src/tests/stake.data/{enable_rewards_rate_decrease => update_rewards_config}/sources/main.move (64%) diff --git a/aptos-move/e2e-move-tests/src/tests/stake.data/enable_rewards_rate_decrease/Move.toml b/aptos-move/e2e-move-tests/src/tests/stake.data/update_rewards_config/Move.toml similarity index 100% rename from aptos-move/e2e-move-tests/src/tests/stake.data/enable_rewards_rate_decrease/Move.toml rename to aptos-move/e2e-move-tests/src/tests/stake.data/update_rewards_config/Move.toml diff --git a/aptos-move/e2e-move-tests/src/tests/stake.data/enable_rewards_rate_decrease/sources/main.move b/aptos-move/e2e-move-tests/src/tests/stake.data/update_rewards_config/sources/main.move similarity index 64% rename from aptos-move/e2e-move-tests/src/tests/stake.data/enable_rewards_rate_decrease/sources/main.move rename to aptos-move/e2e-move-tests/src/tests/stake.data/update_rewards_config/sources/main.move index af5cb346d449e..c5c60ef7d20f1 100644 --- a/aptos-move/e2e-move-tests/src/tests/stake.data/enable_rewards_rate_decrease/sources/main.move +++ b/aptos-move/e2e-move-tests/src/tests/stake.data/update_rewards_config/sources/main.move @@ -1,22 +1,17 @@ script { use aptos_framework::aptos_governance; use aptos_framework::staking_config; - use aptos_framework::timestamp; use aptos_std::fixed_point64; - use std::features; fun main(core_resources: &signer) { let framework_signer = aptos_governance::get_signer_testnet_only(core_resources, @aptos_framework); - staking_config::initialize_rewards( + staking_config::update_rewards_config( &framework_signer, fixed_point64::create_from_rational(1, 100), fixed_point64::create_from_rational(3, 1000), 365 * 24 * 60 * 60, - timestamp::now_seconds(), fixed_point64::create_from_rational(50, 100), ); - let feature = features::get_periodical_reward_rate_decrease_feature(); - features::change_feature_flags_for_next_epoch(&framework_signer, vector[feature], vector[]); aptos_governance::force_end_epoch(&framework_signer); } } diff --git a/aptos-move/e2e-move-tests/src/tests/stake.rs b/aptos-move/e2e-move-tests/src/tests/stake.rs index 14dd0afad42e3..8b7f3db69864f 100644 --- a/aptos-move/e2e-move-tests/src/tests/stake.rs +++ b/aptos-move/e2e-move-tests/src/tests/stake.rs @@ -15,7 +15,7 @@ pub static PROPOSAL_SCRIPTS: Lazy>> = Lazy::new(build_s fn build_scripts() -> BTreeMap> { let package_folder = "stake.data"; - let package_names = vec!["enable_rewards_rate_decrease"]; + let package_names = vec!["update_rewards_config"]; common::build_scripts(package_folder, package_names) } @@ -194,7 +194,7 @@ fn test_staking_rewards() { let core_resources = harness.new_account_at(AccountAddress::from_hex_literal("0xA550C18").unwrap()); let script_code = PROPOSAL_SCRIPTS - .get("enable_rewards_rate_decrease") + .get("update_rewards_config") .expect("proposal script should be built"); let txn = harness.create_script(&core_resources, script_code.clone(), vec![], vec![]); assert_success!(harness.run(txn)); diff --git a/aptos-move/e2e-move-tests/src/tests/vote.data/enable_partial_governance_voting/sources/main.move b/aptos-move/e2e-move-tests/src/tests/vote.data/enable_partial_governance_voting/sources/main.move index 99bb9161506e3..a250ad3a4ea5c 100644 --- a/aptos-move/e2e-move-tests/src/tests/vote.data/enable_partial_governance_voting/sources/main.move +++ b/aptos-move/e2e-move-tests/src/tests/vote.data/enable_partial_governance_voting/sources/main.move @@ -6,7 +6,6 @@ script { let framework_signer = aptos_governance::get_signer_testnet_only(core_resources, @aptos_framework); let feature = features::get_partial_governance_voting(); if (enable_partial_governance_voting) { - aptos_governance::initialize_partial_voting(&framework_signer); features::change_feature_flags_for_next_epoch(&framework_signer, vector[feature], vector[]); } else { features::change_feature_flags_for_next_epoch(&framework_signer, vector[], vector[feature]); diff --git a/aptos-move/framework/aptos-framework/doc/aptos_governance.md b/aptos-move/framework/aptos-framework/doc/aptos_governance.md index c90cc82da7e23..ef3a011b5ed74 100644 --- a/aptos-move/framework/aptos-framework/doc/aptos_governance.md +++ b/aptos-move/framework/aptos-framework/doc/aptos_governance.md @@ -885,6 +885,7 @@ This function is private because it's called directly from the vm. system_addresses::assert_aptos_framework(aptos_framework); voting::register<GovernanceProposal>(aptos_framework); + initialize_partial_voting(aptos_framework); move_to(aptos_framework, GovernanceConfig { voting_duration_secs, min_voting_threshold, @@ -2164,6 +2165,7 @@ Limit addition overflow. ensures exists<GovernanceEvents>(addr); ensures exists<VotingRecords>(addr); ensures exists<ApprovedExecutionHashes>(addr); +ensures exists<VotingRecordsV2>(addr);
@@ -2236,6 +2238,7 @@ Abort if structs have already been created. aborts_if exists<VotingRecords>(addr); aborts_if exists<ApprovedExecutionHashes>(addr); aborts_if !exists<account::Account>(addr); + aborts_if exists<VotingRecordsV2>(addr); }
diff --git a/aptos-move/framework/aptos-framework/doc/genesis.md b/aptos-move/framework/aptos-framework/doc/genesis.md index 4df4a2f99b301..015b274af8f7e 100644 --- a/aptos-move/framework/aptos-framework/doc/genesis.md +++ b/aptos-move/framework/aptos-framework/doc/genesis.md @@ -343,6 +343,7 @@ Genesis step 1: Initialize aptos framework account and core modules on chain. execution_config::set(&aptos_framework_account, execution_config); version::initialize(&aptos_framework_account, initial_version); stake::initialize(&aptos_framework_account); + timestamp::set_time_has_started(&aptos_framework_account); staking_config::initialize( &aptos_framework_account, minimum_stake, @@ -363,7 +364,6 @@ Genesis step 1: Initialize aptos framework account and core modules on chain. reconfiguration::initialize(&aptos_framework_account); block::initialize(&aptos_framework_account, epoch_interval_microsecs); state_storage::initialize(&aptos_framework_account); - timestamp::set_time_has_started(&aptos_framework_account); } diff --git a/aptos-move/framework/aptos-framework/doc/staking_config.md b/aptos-move/framework/aptos-framework/doc/staking_config.md index 244ed0c23647e..6d6890b608e43 100644 --- a/aptos-move/framework/aptos-framework/doc/staking_config.md +++ b/aptos-move/framework/aptos-framework/doc/staking_config.md @@ -386,6 +386,17 @@ Only called during genesis. rewards_rate_denominator, voting_power_increase_limit, }); + + // Initialize StakingRewardsConfig with the given rewards_rate and rewards_rate_denominator, + // while setting min_rewards_rate and rewards_rate_decrease_rate to 0. + initialize_rewards( + aptos_framework, + fixed_point64::create_from_rational((rewards_rate as u128), (rewards_rate_denominator as u128)), + fixed_point64::create_from_rational(0, 1000), + ONE_YEAR_IN_SECS, + 0, + fixed_point64::create_from_rational(0, 1000), + ); } @@ -1072,6 +1083,7 @@ Can only be called as part of the Aptos governance proposal process established
invariant [suspendable] chain_status::is_operating() ==> exists<StakingConfig>(@aptos_framework);
+invariant [suspendable] chain_status::is_operating() ==> exists<StakingRewardsConfig>(@aptos_framework);
 pragma verify = true;
 pragma aborts_if_is_strict;
 
@@ -1223,6 +1235,7 @@ StakingConfig does not exist under the aptos_framework before creating it.
let addr = signer::address_of(aptos_framework);
+requires exists<timestamp::CurrentTimeMicroseconds>(@aptos_framework);
 // This enforces high-level requirement 1:
 aborts_if addr != @aptos_framework;
 aborts_if minimum_stake > maximum_stake || maximum_stake == 0;
@@ -1234,7 +1247,9 @@ StakingConfig does not exist under the aptos_framework before creating it.
 aborts_if rewards_rate > MAX_REWARDS_RATE;
 aborts_if rewards_rate > rewards_rate_denominator;
 aborts_if exists<StakingConfig>(addr);
+aborts_if exists<StakingRewardsConfig>(addr);
 ensures exists<StakingConfig>(addr);
+ensures exists<StakingRewardsConfig>(addr);
 
diff --git a/aptos-move/framework/aptos-framework/sources/aptos_governance.move b/aptos-move/framework/aptos-framework/sources/aptos_governance.move index 5d8d0e99b0598..fb1469bc7e684 100644 --- a/aptos-move/framework/aptos-framework/sources/aptos_governance.move +++ b/aptos-move/framework/aptos-framework/sources/aptos_governance.move @@ -199,6 +199,7 @@ module aptos_framework::aptos_governance { system_addresses::assert_aptos_framework(aptos_framework); voting::register(aptos_framework); + initialize_partial_voting(aptos_framework); move_to(aptos_framework, GovernanceConfig { voting_duration_secs, min_voting_threshold, @@ -1148,7 +1149,6 @@ module aptos_framework::aptos_governance { assert!(get_remaining_voting_power(voter_1_addr, 0) == 0, 1); assert!(get_remaining_voting_power(voter_2_addr, 0) == 10, 2); - initialize_partial_voting(&aptos_framework); features::change_feature_flags_for_testing(&aptos_framework, vector[features::get_partial_governance_voting()], vector[]); coin::register(&voter_1); @@ -1307,7 +1307,6 @@ module aptos_framework::aptos_governance { yes_voter: &signer, no_voter: &signer, ) acquires GovernanceResponsbility { - initialize_partial_voting(aptos_framework); features::change_feature_flags_for_testing(aptos_framework, vector[features::get_partial_governance_voting()], vector[]); setup_voting_with_initialized_stake(aptos_framework, proposer, yes_voter, no_voter); } @@ -1319,7 +1318,6 @@ module aptos_framework::aptos_governance { voter_1: &signer, voter_2: &signer, ) acquires GovernanceResponsbility { - initialize_partial_voting(aptos_framework); features::change_feature_flags_for_testing(aptos_framework, vector[features::get_partial_governance_voting()], vector[]); setup_voting(aptos_framework, proposer, voter_1, voter_2); } diff --git a/aptos-move/framework/aptos-framework/sources/aptos_governance.spec.move b/aptos-move/framework/aptos-framework/sources/aptos_governance.spec.move index 41e31d566be6f..c3d18d593533c 100644 --- a/aptos-move/framework/aptos-framework/sources/aptos_governance.spec.move +++ b/aptos-move/framework/aptos-framework/sources/aptos_governance.spec.move @@ -76,6 +76,7 @@ spec aptos_framework::aptos_governance { ensures exists(addr); ensures exists(addr); ensures exists(addr); + ensures exists(addr); } /// Signer address must be @aptos_framework. @@ -104,6 +105,7 @@ spec aptos_framework::aptos_governance { aborts_if exists(addr); aborts_if exists(addr); aborts_if !exists(addr); + aborts_if exists(addr); } /// Signer address must be @aptos_framework. diff --git a/aptos-move/framework/aptos-framework/sources/configs/staking_config.move b/aptos-move/framework/aptos-framework/sources/configs/staking_config.move index aff41b494f8c9..ecb8fbc1525a2 100644 --- a/aptos-move/framework/aptos-framework/sources/configs/staking_config.move +++ b/aptos-move/framework/aptos-framework/sources/configs/staking_config.move @@ -132,6 +132,17 @@ module aptos_framework::staking_config { rewards_rate_denominator, voting_power_increase_limit, }); + + // Initialize StakingRewardsConfig with the given rewards_rate and rewards_rate_denominator, + // while setting min_rewards_rate and rewards_rate_decrease_rate to 0. + initialize_rewards( + aptos_framework, + fixed_point64::create_from_rational((rewards_rate as u128), (rewards_rate_denominator as u128)), + fixed_point64::create_from_rational(0, 1000), + ONE_YEAR_IN_SECS, + 0, + fixed_point64::create_from_rational(0, 1000), + ); } #[view] @@ -395,7 +406,9 @@ module aptos_framework::staking_config { #[test(aptos_framework = @aptos_framework)] public entry fun test_change_staking_configs(aptos_framework: signer) acquires StakingConfig { - initialize(&aptos_framework, 0, 1, 1, false, 1, 1, 1); + initialize_for_test(&aptos_framework, 0, 1, 1, false, 1, 1, 1); + // This test case checks the behavior when the periodical_reward_rate_decrease feature is disabled. + features::change_feature_flags_for_testing(&aptos_framework, vector[], vector[features::get_periodical_reward_rate_decrease_feature()]); update_required_stake(&aptos_framework, 100, 1000); update_recurring_lockup_duration_secs(&aptos_framework, 10000); @@ -501,9 +514,11 @@ module aptos_framework::staking_config { update_recurring_lockup_duration_secs(&account, 1); } - #[test(account = @0x123)] + #[test(aptos_framework = @0x1, account = @0x123)] #[expected_failure(abort_code = 0x50003, location = aptos_framework::system_addresses)] - public entry fun test_update_rewards_unauthorized_should_fail(account: signer) acquires StakingConfig { + public entry fun test_update_rewards_unauthorized_should_fail(aptos_framework: signer, account: signer) acquires StakingConfig { + // This test case checks the behavior when the periodical_reward_rate_decrease feature is disabled. + features::change_feature_flags_for_testing(&aptos_framework, vector[], vector[features::get_periodical_reward_rate_decrease_feature()]); update_rewards_rate(&account, 1, 10); } @@ -547,6 +562,8 @@ module aptos_framework::staking_config { #[test(aptos_framework = @aptos_framework)] #[expected_failure(abort_code = 0x10002, location = Self)] public entry fun test_update_rewards_invalid_denominator_should_fail(aptos_framework: signer) acquires StakingConfig { + // This test case checks the behavior when the periodical_reward_rate_decrease feature is disabled. + features::change_feature_flags_for_testing(&aptos_framework, vector[], vector[features::get_periodical_reward_rate_decrease_feature()]); update_rewards_rate(&aptos_framework, 1, 0); } @@ -625,6 +642,8 @@ module aptos_framework::staking_config { public entry fun test_update_voting_power_increase_limit_to_zero_should_fail( aptos_framework: signer ) acquires StakingConfig { + // This test case checks the behavior when the periodical_reward_rate_decrease feature is disabled. + features::change_feature_flags_for_testing(&aptos_framework, vector[], vector[features::get_periodical_reward_rate_decrease_feature()]); update_voting_power_increase_limit(&aptos_framework, 0); } diff --git a/aptos-move/framework/aptos-framework/sources/configs/staking_config.spec.move b/aptos-move/framework/aptos-framework/sources/configs/staking_config.spec.move index 270abef9cec86..881a8344628c2 100644 --- a/aptos-move/framework/aptos-framework/sources/configs/staking_config.spec.move +++ b/aptos-move/framework/aptos-framework/sources/configs/staking_config.spec.move @@ -58,6 +58,7 @@ spec aptos_framework::staking_config { spec module { use aptos_framework::chain_status; invariant [suspendable] chain_status::is_operating() ==> exists(@aptos_framework); + invariant [suspendable] chain_status::is_operating() ==> exists(@aptos_framework); pragma verify = true; pragma aborts_if_is_strict; } @@ -106,6 +107,7 @@ spec aptos_framework::staking_config { ) { use std::signer; let addr = signer::address_of(aptos_framework); + requires exists(@aptos_framework); /// [high-level-req-1.1] aborts_if addr != @aptos_framework; aborts_if minimum_stake > maximum_stake || maximum_stake == 0; @@ -117,7 +119,9 @@ spec aptos_framework::staking_config { aborts_if rewards_rate > MAX_REWARDS_RATE; aborts_if rewards_rate > rewards_rate_denominator; aborts_if exists(addr); + aborts_if exists(addr); ensures exists(addr); + ensures exists(addr); } /// Caller must be @aptos_framework. diff --git a/aptos-move/framework/aptos-framework/sources/delegation_pool.move b/aptos-move/framework/aptos-framework/sources/delegation_pool.move index bab7f756ca311..0e21967dcb53b 100644 --- a/aptos-move/framework/aptos-framework/sources/delegation_pool.move +++ b/aptos-move/framework/aptos-framework/sources/delegation_pool.move @@ -4211,7 +4211,6 @@ module aptos_framework::delegation_pool { 100 * ONE_APT, 1000, ); - aptos_governance::initialize_partial_voting(aptos_framework); features::change_feature_flags_for_testing( aptos_framework, vector[features::get_partial_governance_voting(), features::get_delegation_pool_partial_governance_voting( @@ -4257,7 +4256,6 @@ module aptos_framework::delegation_pool { 100 * ONE_APT, 1000, ); - aptos_governance::initialize_partial_voting(aptos_framework); features::change_feature_flags_for_testing( aptos_framework, vector[features::get_partial_governance_voting(), features::get_delegation_pool_partial_governance_voting( @@ -4313,7 +4311,6 @@ module aptos_framework::delegation_pool { 100 * ONE_APT, 1000, ); - aptos_governance::initialize_partial_voting(aptos_framework); features::change_feature_flags_for_testing( aptos_framework, vector[features::get_partial_governance_voting(), features::get_delegation_pool_partial_governance_voting( @@ -4464,7 +4461,6 @@ module aptos_framework::delegation_pool { 100 * ONE_APT, 1000, ); - aptos_governance::initialize_partial_voting(aptos_framework); // This test case checks the scenario where delegation_pool_partial_governance_voting is disabled. features::change_feature_flags_for_testing( aptos_framework, @@ -4552,7 +4548,6 @@ module aptos_framework::delegation_pool { 100 * ONE_APT, 1000, ); - aptos_governance::initialize_partial_voting(aptos_framework); features::change_feature_flags_for_testing( aptos_framework, vector[features::get_partial_governance_voting(), features::get_delegation_pool_partial_governance_voting( @@ -4879,7 +4874,6 @@ module aptos_framework::delegation_pool { voter2: &signer, ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage, DelegationPoolAllowlisting { initialize_for_test(aptos_framework); - aptos_governance::initialize_partial_voting(aptos_framework); features::change_feature_flags_for_testing( aptos_framework, vector[ @@ -5027,7 +5021,6 @@ module aptos_framework::delegation_pool { voter2: &signer, ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage, DelegationPoolAllowlisting { initialize_for_test(aptos_framework); - aptos_governance::initialize_partial_voting(aptos_framework); features::change_feature_flags_for_testing( aptos_framework, vector[ @@ -5599,7 +5592,6 @@ module aptos_framework::delegation_pool { 100 * ONE_APT, 1000, ); - aptos_governance::initialize_partial_voting(aptos_framework); initialize_test_validator(validator, 100 * ONE_APT, true, false); diff --git a/aptos-move/framework/aptos-framework/sources/genesis.move b/aptos-move/framework/aptos-framework/sources/genesis.move index 207bcf74b351c..66d0087bfdca1 100644 --- a/aptos-move/framework/aptos-framework/sources/genesis.move +++ b/aptos-move/framework/aptos-framework/sources/genesis.move @@ -109,6 +109,7 @@ module aptos_framework::genesis { execution_config::set(&aptos_framework_account, execution_config); version::initialize(&aptos_framework_account, initial_version); stake::initialize(&aptos_framework_account); + timestamp::set_time_has_started(&aptos_framework_account); staking_config::initialize( &aptos_framework_account, minimum_stake, @@ -129,7 +130,6 @@ module aptos_framework::genesis { reconfiguration::initialize(&aptos_framework_account); block::initialize(&aptos_framework_account, epoch_interval_microsecs); state_storage::initialize(&aptos_framework_account); - timestamp::set_time_has_started(&aptos_framework_account); } /// Genesis step 2: Initialize Aptos coin. diff --git a/aptos-move/framework/aptos-framework/sources/stake.move b/aptos-move/framework/aptos-framework/sources/stake.move index 9dd84dee90352..b4f62d3df4004 100644 --- a/aptos-move/framework/aptos-framework/sources/stake.move +++ b/aptos-move/framework/aptos-framework/sources/stake.move @@ -1760,6 +1760,8 @@ module aptos_framework::stake { public fun initialize_for_test(aptos_framework: &signer) { reconfiguration_state::initialize(aptos_framework); initialize_for_test_custom(aptos_framework, 100, 10000, LOCKUP_CYCLE_SECONDS, true, 1, 100, 1000000); + // In the test environment, the periodical_reward_rate_decrease feature is initially turned off. + features::change_feature_flags_for_testing(aptos_framework, vector[], vector[features::get_periodical_reward_rate_decrease_feature()]); } #[test_only] @@ -1820,6 +1822,9 @@ module aptos_framework::stake { store_aptos_coin_mint_cap(aptos_framework, mint_cap); coin::destroy_burn_cap(burn_cap); }; + + // In the test environment, the periodical_reward_rate_decrease feature is initially turned off. + features::change_feature_flags_for_testing(aptos_framework, vector[], vector[features::get_periodical_reward_rate_decrease_feature()]); } // This function assumes the stake module already the capability to mint aptos coins. diff --git a/aptos-move/framework/aptos-framework/sources/staking_contract.move b/aptos-move/framework/aptos-framework/sources/staking_contract.move index 2e6232d798e6a..5e9ba4355b995 100644 --- a/aptos-move/framework/aptos-framework/sources/staking_contract.move +++ b/aptos-move/framework/aptos-framework/sources/staking_contract.move @@ -970,12 +970,6 @@ module aptos_framework::staking_contract { #[test_only] const MAXIMUM_STAKE: u64 = 100000000000000000; // 1B APT coins with 8 decimals. - #[test_only] - const MODULE_EVENT: u64 = 26; - - #[test_only] - const OPERATOR_BENEFICIARY_CHANGE: u64 = 39; - #[test_only] public fun setup(aptos_framework: &signer, staker: &signer, operator: &signer, initial_balance: u64) { // Reward rate of 0.1% per epoch. @@ -1015,7 +1009,8 @@ module aptos_framework::staking_contract { // Voter is initially set to operator but then updated to be staker. create_staking_contract(staker, operator_address, operator_address, amount, commission, vector::empty()); - std::features::change_feature_flags_for_testing(aptos_framework, vector[MODULE_EVENT, OPERATOR_BENEFICIARY_CHANGE], vector[]); + // In the test environment, the periodical_reward_rate_decrease feature is initially turned off. + std::features::change_feature_flags_for_testing(aptos_framework, vector[], vector[features::get_periodical_reward_rate_decrease_feature()]); } #[test(aptos_framework = @0x1, staker = @0x123, operator = @0x234)] diff --git a/aptos-move/framework/aptos-framework/sources/vesting.move b/aptos-move/framework/aptos-framework/sources/vesting.move index 8c3ac239a874a..34424b882a7e3 100644 --- a/aptos-move/framework/aptos-framework/sources/vesting.move +++ b/aptos-move/framework/aptos-framework/sources/vesting.move @@ -1212,12 +1212,6 @@ module aptos_framework::vesting { #[test_only] const VALIDATOR_STATUS_INACTIVE: u64 = 4; - #[test_only] - const MODULE_EVENT: u64 = 26; - - #[test_only] - const OPERATOR_BENEFICIARY_CHANGE: u64 = 39; - #[test_only] public fun setup(aptos_framework: &signer, accounts: &vector
) { use aptos_framework::aptos_account::create_account; @@ -1240,7 +1234,8 @@ module aptos_framework::vesting { }; }); - std::features::change_feature_flags_for_testing(aptos_framework, vector[MODULE_EVENT, OPERATOR_BENEFICIARY_CHANGE], vector[]); + // In the test environment, the periodical_reward_rate_decrease feature is initially turned off. + std::features::change_feature_flags_for_testing(aptos_framework, vector[], vector[std::features::get_periodical_reward_rate_decrease_feature()]); } #[test_only] diff --git a/execution/executor/tests/internal_indexer_test.rs b/execution/executor/tests/internal_indexer_test.rs index 13d03f8092693..b9e9c0c6520a1 100644 --- a/execution/executor/tests/internal_indexer_test.rs +++ b/execution/executor/tests/internal_indexer_test.rs @@ -343,12 +343,14 @@ fn test_db_indexer_data() { (false, "0x1::reconfiguration::Configuration"), (false, "0x1::aptos_governance::VotingRecords"), (false, "0x1::state_storage::StateStorageUsage"), + (false, "0x1::aptos_governance::VotingRecordsV2"), (false, "0x1::consensus_config::ConsensusConfig"), (false, "0x1::execution_config::ExecutionConfig"), (false, "0x1::timestamp::CurrentTimeMicroseconds"), (false, "0x1::aptos_governance::GovernanceConfig"), (false, "0x1::aptos_governance::GovernanceEvents"), (false, "0x1::randomness_config::RandomnessConfig"), + (false, "0x1::staking_config::StakingRewardsConfig"), (false, "0x1::aggregator_factory::AggregatorFactory"), (false, "0x1::transaction_fee::AptosCoinCapabilities"), (false, "0x1::transaction_fee::AptosCoinMintCapability"), diff --git a/types/src/on_chain_config/aptos_features.rs b/types/src/on_chain_config/aptos_features.rs index 99d61d7d6b513..932338a25b623 100644 --- a/types/src/on_chain_config/aptos_features.rs +++ b/types/src/on_chain_config/aptos_features.rs @@ -122,6 +122,7 @@ impl FeatureFlag { FeatureFlag::BLS12_381_STRUCTURES, FeatureFlag::ED25519_PUBKEY_VALIDATE_RETURN_FALSE_WRONG_LENGTH, FeatureFlag::STRUCT_CONSTRUCTORS, + FeatureFlag::PERIODICAL_REWARD_RATE_DECREASE, FeatureFlag::PARTIAL_GOVERNANCE_VOTING, FeatureFlag::SIGNATURE_CHECKER_V2, FeatureFlag::STORAGE_SLOT_METADATA, From 49d64061ba6a6c21b692cc9d02c36d5b934f9ce9 Mon Sep 17 00:00:00 2001 From: Rustie Lin Date: Thu, 12 Dec 2024 13:23:35 -0800 Subject: [PATCH 46/78] [forge] delete orphaned test runners (#15557) * [forge] delete orphaned test runners * [forge] cleanup add dry run mode * [forge] cleanup names by substr robust * [forge] cleanup names by substr robust 2 --- testsuite/forge-cli/src/main.rs | 4 +- .../forge/src/backend/k8s/cluster_helper.rs | 97 +++++++++++-------- testsuite/forge/src/backend/k8s/constants.rs | 4 +- 3 files changed, 64 insertions(+), 41 deletions(-) diff --git a/testsuite/forge-cli/src/main.rs b/testsuite/forge-cli/src/main.rs index b90cf2fa40372..6ea4d0c495788 100644 --- a/testsuite/forge-cli/src/main.rs +++ b/testsuite/forge-cli/src/main.rs @@ -170,6 +170,8 @@ struct CleanUp { help = "The kubernetes namespace to clean up. If unset, attemps to cleanup all by using forge-management configmaps" )] namespace: Option, + #[clap(long, help = "If set, skips the actual cleanup")] + dry_run: bool, } #[derive(Parser, Debug)] @@ -345,7 +347,7 @@ fn main() -> Result<()> { if let Some(namespace) = cleanup.namespace { runtime.block_on(uninstall_testnet_resources(namespace))?; } else { - runtime.block_on(cleanup_cluster_with_management())?; + runtime.block_on(cleanup_cluster_with_management(cleanup.dry_run))?; } Ok(()) }, diff --git a/testsuite/forge/src/backend/k8s/cluster_helper.rs b/testsuite/forge/src/backend/k8s/cluster_helper.rs index 93fe76c773d59..eaebf6e10b9de 100644 --- a/testsuite/forge/src/backend/k8s/cluster_helper.rs +++ b/testsuite/forge/src/backend/k8s/cluster_helper.rs @@ -10,8 +10,8 @@ use crate::{ DEFAULT_TEST_SUITE_NAME, DEFAULT_USERNAME, FORGE_KEY_SEED, FORGE_TESTNET_DEPLOYER_DOCKER_IMAGE_REPO, FULLNODE_HAPROXY_SERVICE_SUFFIX, FULLNODE_SERVICE_SUFFIX, HELM_BIN, KUBECTL_BIN, MANAGEMENT_CONFIGMAP_PREFIX, - NAMESPACE_CLEANUP_THRESHOLD_SECS, POD_CLEANUP_THRESHOLD_SECS, VALIDATOR_HAPROXY_SERVICE_SUFFIX, - VALIDATOR_SERVICE_SUFFIX, + NAMESPACE_CLEANUP_THRESHOLD_SECS, ORPHAN_POD_CLEANUP_THRESHOLD_SECS, + VALIDATOR_HAPROXY_SERVICE_SUFFIX, VALIDATOR_SERVICE_SUFFIX, }; use again::RetryPolicy; use anyhow::{anyhow, bail, format_err}; @@ -978,7 +978,11 @@ pub async fn create_management_configmap( Ok(()) } -pub async fn cleanup_cluster_with_management() -> Result<()> { +pub async fn cleanup_cluster_with_management(dry_run: bool) -> Result<()> { + if dry_run { + info!("Dry run mode, skipping actual cleanup"); + } + let kube_client = create_k8s_client().await?; let start = SystemTime::now(); let time_since_the_epoch = start @@ -986,43 +990,11 @@ pub async fn cleanup_cluster_with_management() -> Result<()> { .expect("Time went backwards") .as_secs(); - let pods_api: Api = Api::namespaced(kube_client.clone(), "default"); - let lp = ListParams::default().labels("app.kubernetes.io/name=forge"); - - // delete all forge test pods over a threshold age - let pods = pods_api - .list(&lp) - .await? - .items - .into_iter() - .filter(|pod| { - let pod_name = pod.name(); - info!("Got pod {}", pod_name); - if let Some(time) = &pod.metadata.creation_timestamp { - let pod_creation_time = time.0.timestamp() as u64; - let pod_uptime = time_since_the_epoch - pod_creation_time; - info!( - "Pod {} has lived for {}/{} seconds", - pod_name, pod_uptime, POD_CLEANUP_THRESHOLD_SECS - ); - if pod_uptime > POD_CLEANUP_THRESHOLD_SECS { - return true; - } - } - false - }) - .collect::>(); - for pod in pods { - let pod_name = pod.name(); - info!("Deleting pod {}", pod_name); - pods_api.delete(&pod_name, &DeleteParams::default()).await?; - } - // delete all forge testnets over a threshold age using their management configmaps // unless they are explicitly set with "keep = true" let configmaps_api: Api = Api::all(kube_client.clone()); let lp = ListParams::default(); - let configmaps = configmaps_api + let old_forge_management_configmaps_to_delete = configmaps_api .list(&lp) .await? .items @@ -1044,9 +1016,58 @@ pub async fn cleanup_cluster_with_management() -> Result<()> { false }) .collect::>(); - for configmap in configmaps { + for configmap in old_forge_management_configmaps_to_delete { let namespace = configmap.namespace().unwrap(); - uninstall_testnet_resources(namespace).await?; + info!("Deleting old namespace {}", namespace); + if !dry_run { + uninstall_testnet_resources(namespace).await?; + } + } + + // delete all orphan forge test pods older than a threshold + let namespace_api: Api = Api::all(kube_client.clone()); + let lp = ListParams::default(); + let forge_namespaces = namespace_api + .list(&lp) + .await? + .items + .into_iter() + .filter(|namespace| namespace.name().starts_with("forge-")) + .collect::>(); + // print all namespace names + for namespace in &forge_namespaces { + info!("Found forge namespace: {}", namespace.name()); + } + let pods_api: Api = Api::namespaced(kube_client.clone(), "default"); + let lp = ListParams::default().labels("app.kubernetes.io/name=forge"); + let orphan_forge_test_runner_pods_to_delete = + pods_api.list(&lp).await?.items.into_iter().filter(|pod| { + let pod_name = pod.name(); + // check if the pod is older than 5min + if let Some(time) = &pod.metadata.creation_timestamp { + let pod_creation_time = time.0.timestamp() as u64; + let pod_uptime = time_since_the_epoch - pod_creation_time; + // If it's not older than the threshold time, it's not elegible for deletion + if pod_uptime < ORPHAN_POD_CLEANUP_THRESHOLD_SECS { + return false; + } + } + // If there is no namespace that matches the pod name, it's an orphan pod + !forge_namespaces + .iter() + .any(|namespace| pod_name.starts_with(namespace.metadata.name.as_ref().unwrap())) + }); + for pod in orphan_forge_test_runner_pods_to_delete { + let pod_name = pod.name(); + let pod_age = + time_since_the_epoch - pod.metadata.creation_timestamp.unwrap().0.timestamp() as u64; + info!( + "Deleting orphaned pod {} with age {} without any corresponding namespace", + pod_name, pod_age + ); + if !dry_run { + pods_api.delete(&pod_name, &DeleteParams::default()).await?; + } } Ok(()) diff --git a/testsuite/forge/src/backend/k8s/constants.rs b/testsuite/forge/src/backend/k8s/constants.rs index 4457483f9d03b..d439afbd2d7ed 100644 --- a/testsuite/forge/src/backend/k8s/constants.rs +++ b/testsuite/forge/src/backend/k8s/constants.rs @@ -22,12 +22,12 @@ pub const GENESIS_HELM_RELEASE_NAME: &str = "genesis"; pub const APTOS_NODE_HELM_CHART_PATH: &str = "terraform/helm/aptos-node"; pub const GENESIS_HELM_CHART_PATH: &str = "terraform/helm/genesis"; -// cleanup namespaces after 30 minutes unless "keep = true" +// cleanup namespaces after 30 minutes unless "keep = true" or they have a cleanup time set pub const NAMESPACE_CLEANUP_THRESHOLD_SECS: u64 = 1800; // Leave a buffer of around 20 minutes for test provisioning and cleanup to be done before cleaning // up underlying resources. pub const NAMESPACE_CLEANUP_DURATION_BUFFER_SECS: u64 = 1200; -pub const POD_CLEANUP_THRESHOLD_SECS: u64 = 86400; +pub const ORPHAN_POD_CLEANUP_THRESHOLD_SECS: u64 = 300; pub const MANAGEMENT_CONFIGMAP_PREFIX: &str = "forge-management"; // this is the port on the validator service itself, as opposed to 80 on the validator haproxy service From 16db0cb5534673d74550a7547715c689190b69bb Mon Sep 17 00:00:00 2001 From: Josh Lind Date: Thu, 12 Dec 2024 17:40:27 -0500 Subject: [PATCH 47/78] [Devsetup] Install the latest rust toolchain --- scripts/dev_setup.sh | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/scripts/dev_setup.sh b/scripts/dev_setup.sh index 84763fa616aed..2fed0701bbf48 100755 --- a/scripts/dev_setup.sh +++ b/scripts/dev_setup.sh @@ -461,13 +461,9 @@ function install_toolchain { } function install_rustup_components_and_nightly { - echo "Printing the rustup version and toolchain list" - rustup --version - rustup show - rustup toolchain list -v - - echo "Updating rustup and installing rustfmt & clippy" + echo "Updating rustup and installing the latest rustc, rustfmt & clippy" rustup update + rustup toolchain install stable # Install the latest toolchain to ensure that dependencies can always be built (even if aptos-core is behind) rustup component add rustfmt rustup component add clippy @@ -490,6 +486,11 @@ function install_rustup_components_and_nightly { if ! rustup component add rustfmt --toolchain nightly; then echo "Failed to install rustfmt nightly using rustup." fi + + echo "Printing the rustup version and toolchain list" + rustup --version + rustup show + rustup toolchain list -v } function install_cargo_sort { From c9b71bc156e409dd96c37aab6bea3c4ed3ea29f0 Mon Sep 17 00:00:00 2001 From: Bo Wu Date: Thu, 12 Dec 2024 15:29:55 -0800 Subject: [PATCH 48/78] replace existing replay verify with new one --- .github/workflows/replay-verify-legacy.yaml | 115 ++++++++++++++++++ .../workflows/replay-verify-on-archive.yaml | 82 ------------- .github/workflows/replay-verify.yaml | 103 +++++----------- 3 files changed, 147 insertions(+), 153 deletions(-) create mode 100644 .github/workflows/replay-verify-legacy.yaml delete mode 100644 .github/workflows/replay-verify-on-archive.yaml diff --git a/.github/workflows/replay-verify-legacy.yaml b/.github/workflows/replay-verify-legacy.yaml new file mode 100644 index 0000000000000..42888f5c35e80 --- /dev/null +++ b/.github/workflows/replay-verify-legacy.yaml @@ -0,0 +1,115 @@ +# This defines a workflow to replay transactions on the given chain with the latest aptos node software. +# In order to trigger it go to the Actions Tab of the Repo, click "replay-verify" and then "Run Workflow". +# +# On PR, a single test case will run. On workflow_dispatch, you may specify the CHAIN_NAME to verify. + +name: "replay-verify" +on: + # Allow triggering manually + workflow_dispatch: + inputs: + GIT_SHA: + required: false + type: string + description: The git SHA1 to test. If not specified, it will use the latest commit on main. + CHAIN_NAME: + required: false + type: choice + options: [testnet, mainnet, all] + default: all + description: The chain name to test. If not specified, it will test both testnet and mainnet. + TESTNET_BUCKET: + required: false + type: string + description: The bucket to use for testnet replay. If not specified, it will use aptos-testnet-backup. + default: aptos-testnet-backup + MAINNET_BUCKET: + required: false + type: string + description: The bucket to use for mainnet replay. If not specified, it will use aptos-mainnet-backup. + default: aptos-mainnet-backup + +# cancel redundant builds +concurrency: + # cancel redundant builds on PRs (only on PR, not on branches) + group: ${{ github.workflow }}-${{ (github.event_name == 'pull_request' && github.ref) || github.sha }} + cancel-in-progress: true + +jobs: + determine-test-metadata: + runs-on: ubuntu-latest + steps: + # checkout the repo first, so check-aptos-core can use it and cancel the workflow if necessary + - uses: actions/checkout@v4 + - uses: ./.github/actions/check-aptos-core + with: + cancel-workflow: ${{ github.event_name == 'schedule' }} # Cancel the workflow if it is scheduled on a fork + + replay-testnet: + if: | + github.event_name == 'schedule' || + github.event_name == 'push' || + github.event_name == 'workflow_dispatch' && (inputs.CHAIN_NAME == 'testnet' || inputs.CHAIN_NAME == 'all') + needs: determine-test-metadata + uses: ./.github/workflows/workflow-run-replay-verify.yaml + secrets: inherit + with: + GIT_SHA: ${{ inputs.GIT_SHA }} + # replay-verify config + BUCKET: ${{ inputs.TESTNET_BUCKET || 'aptos-testnet-backup' }} + SUB_DIR: e1 + HISTORY_START: 862000000 + # to see historical TXNS_TO_SKIP, check out ce6158ac2764ee9d4c8738a85f3bcdc6bd0cadc1 + TXNS_TO_SKIP: "0" + # 1195000000-122000000: https://github.com/aptos-labs/aptos-core/pull/13832 + RANGES_TO_SKIP: "1195000000-1220000000" + BACKUP_CONFIG_TEMPLATE_PATH: terraform/helm/fullnode/files/backup/gcs.yaml + # workflow config + RUNS_ON: "high-perf-docker-with-local-ssd" + TIMEOUT_MINUTES: 180 + MAX_VERSIONS_PER_RANGE: 2000000 + + replay-mainnet: + if: | + github.event_name == 'schedule' || + github.event_name == 'push' || + github.event_name == 'workflow_dispatch' && (inputs.CHAIN_NAME == 'mainnet' || inputs.CHAIN_NAME == 'all' ) + needs: determine-test-metadata + uses: ./.github/workflows/workflow-run-replay-verify.yaml + secrets: inherit + with: + GIT_SHA: ${{ inputs.GIT_SHA }} + # replay-verify config + BUCKET: ${{ inputs.MAINNET_BUCKET || 'aptos-mainnet-backup' }} + SUB_DIR: e1 + HISTORY_START: 518000000 + #TXNS_TO_SKIP: 12253479 12277499 148358668 + TXNS_TO_SKIP: "0" + # 1197378568-1198492648: https://github.com/aptos-labs/aptos-core/pull/13832 + RANGES_TO_SKIP: "1197378568-1198492648" + BACKUP_CONFIG_TEMPLATE_PATH: terraform/helm/fullnode/files/backup/gcs.yaml + # workflow config + RUNS_ON: "high-perf-docker-with-local-ssd" + TIMEOUT_MINUTES: 180 + MAX_VERSIONS_PER_RANGE: 800000 + + test-replay: + if: ${{ (github.event_name == 'pull_request') && contains(github.event.pull_request.labels.*.name, 'CICD:test-replay')}} + needs: determine-test-metadata + uses: ./.github/workflows/workflow-run-replay-verify.yaml + secrets: inherit + with: + GIT_SHA: ${{ github.event.pull_request.head.sha }} + # replay-verify config + BUCKET: ${{ inputs.TESTNET_BUCKET || 'aptos-testnet-backup' }} + SUB_DIR: e1 + HISTORY_START: 862000000 + # to see historical TXNS_TO_SKIP, check out ce6158ac2764ee9d4c8738a85f3bcdc6bd0cadc1 + TXNS_TO_SKIP: "0" + # 1195000000-1220000000: https://github.com/aptos-labs/aptos-core/pull/13832 + RANGES_TO_SKIP: "1195000000-1220000000" + BACKUP_CONFIG_TEMPLATE_PATH: terraform/helm/fullnode/files/backup/gcs.yaml + # workflow config + RUNS_ON: "high-perf-docker-with-local-ssd" + TIMEOUT_MINUTES: 120 # increase test replay timeout to capture more flaky errors + MAX_VERSIONS_PER_RANGE: 2000000 diff --git a/.github/workflows/replay-verify-on-archive.yaml b/.github/workflows/replay-verify-on-archive.yaml deleted file mode 100644 index ffa58f9d52c97..0000000000000 --- a/.github/workflows/replay-verify-on-archive.yaml +++ /dev/null @@ -1,82 +0,0 @@ -# This defines a workflow to replay transactions on the given chain with the latest aptos node software. -# In order to trigger it go to the Actions Tab of the Repo, click "replay-verify" and then "Run Workflow". -# -# On PR, a single test case will run. On workflow_dispatch, you may specify the CHAIN_NAME to verify. - -name: "replay-verify-on-archive" -on: - # Allow triggering manually - workflow_dispatch: - inputs: - NETWORK: - required: true - type: choice - options: [testnet, mainnet, all] - default: all - description: The chain name to test. If not specified, it will test both testnet and mainnet. - IMAGE_TAG: - required: false - type: string - description: The image tag of the feature branch to test, if not specified, it will use the latest commit on current branch. - START_VERSION: - required: false - type: string - description: Optional version to start replaying. If not specified, replay-verify will determines start version itself. - END_VERSION: - required: false - type: string - description: Optional version to end replaying. If not specified, replay-verify will determines end version itself. - pull_request: - paths: - - ".github/workflows/replay-verify-on-archive.yaml" - - ".github/workflows/workflow-run-replay-verify-on-archive.yaml" - schedule: - - cron: "0 8 * * 0,2,4" # The main branch cadence. This runs every Sun,Tues,Thurs UTC 08:00 - -permissions: - contents: read - id-token: write #required for GCP Workload Identity federation which we use to login into Google Artifact Registry - issues: read - pull-requests: read - -# cancel redundant builds -concurrency: - # cancel redundant builds on PRs (only on PR, not on branches) - group: ${{ github.workflow }}-${{ (github.event_name == 'pull_request' && github.ref) || github.sha }} - cancel-in-progress: true - -jobs: - determine-test-metadata: - runs-on: ubuntu-latest-32-core - steps: - # checkout the repo first, so check-aptos-core can use it and cancel the workflow if necessary - - uses: actions/checkout@v4 - - uses: ./.github/actions/check-aptos-core - with: - cancel-workflow: ${{ github.event_name == 'schedule' }} # Cancel the workflow if it is scheduled on a fork - - replay-testnet: - if: | - github.event_name == 'schedule' || - github.event_name == 'workflow_dispatch' && (inputs.NETWORK == 'testnet' || inputs.NETWORK == 'all') - needs: determine-test-metadata - uses: ./.github/workflows/workflow-run-replay-verify-on-archive.yaml - secrets: inherit - with: - NETWORK: "testnet" - IMAGE_TAG: ${{ inputs.IMAGE_TAG }} - START_VERSION: ${{ inputs.START_VERSION }} - END_VERSION: ${{ inputs.END_VERSION }} - - replay-mainnet: - if: | - github.event_name == 'schedule' || - github.event_name == 'workflow_dispatch' && (inputs.NETWORK == 'mainnet' || inputs.NETWORK == 'all' ) - needs: determine-test-metadata - uses: ./.github/workflows/workflow-run-replay-verify-on-archive.yaml - secrets: inherit - with: - NETWORK: "mainnet" - IMAGE_TAG: ${{ inputs.IMAGE_TAG }} - START_VERSION: ${{ inputs.START_VERSION }} - END_VERSION: ${{ inputs.END_VERSION }} \ No newline at end of file diff --git a/.github/workflows/replay-verify.yaml b/.github/workflows/replay-verify.yaml index ac498ad123fc4..8de27ba546a80 100644 --- a/.github/workflows/replay-verify.yaml +++ b/.github/workflows/replay-verify.yaml @@ -3,37 +3,41 @@ # # On PR, a single test case will run. On workflow_dispatch, you may specify the CHAIN_NAME to verify. -name: "replay-verify" +name: "replay-verify-on-archive" on: # Allow triggering manually workflow_dispatch: inputs: - GIT_SHA: - required: false - type: string - description: The git SHA1 to test. If not specified, it will use the latest commit on main. - CHAIN_NAME: - required: false + NETWORK: + required: true type: choice options: [testnet, mainnet, all] default: all description: The chain name to test. If not specified, it will test both testnet and mainnet. - TESTNET_BUCKET: + IMAGE_TAG: + required: false + type: string + description: The image tag of the feature branch to test, if not specified, it will use the latest commit on current branch. + START_VERSION: required: false type: string - description: The bucket to use for testnet replay. If not specified, it will use aptos-testnet-backup. - default: aptos-testnet-backup - MAINNET_BUCKET: + description: Optional version to start replaying. If not specified, replay-verify will determines start version itself. + END_VERSION: required: false type: string - description: The bucket to use for mainnet replay. If not specified, it will use aptos-mainnet-backup. - default: aptos-mainnet-backup + description: Optional version to end replaying. If not specified, replay-verify will determines end version itself. pull_request: paths: - ".github/workflows/replay-verify.yaml" - - ".github/workflows/workflow-run-replay-verify.yaml" + - ".github/workflows/workflow-run-replay-verify-on-archive.yaml" schedule: - - cron: "0 22 * * 0,2,4" # The main branch cadence. This runs every Sun,Tues,Thurs + - cron: "0 8 * * 0,2,4" # The main branch cadence. This runs every Sun,Tues,Thurs UTC 08:00 + +permissions: + contents: read + id-token: write #required for GCP Workload Identity federation which we use to login into Google Artifact Registry + issues: read + pull-requests: read # cancel redundant builds concurrency: @@ -43,7 +47,7 @@ concurrency: jobs: determine-test-metadata: - runs-on: ubuntu-latest + runs-on: ubuntu-latest-32-core steps: # checkout the repo first, so check-aptos-core can use it and cancel the workflow if necessary - uses: actions/checkout@v4 @@ -54,68 +58,25 @@ jobs: replay-testnet: if: | github.event_name == 'schedule' || - github.event_name == 'push' || - github.event_name == 'workflow_dispatch' && (inputs.CHAIN_NAME == 'testnet' || inputs.CHAIN_NAME == 'all') + github.event_name == 'workflow_dispatch' && (inputs.NETWORK == 'testnet' || inputs.NETWORK == 'all') needs: determine-test-metadata - uses: ./.github/workflows/workflow-run-replay-verify.yaml + uses: ./.github/workflows/workflow-run-replay-verify-on-archive.yaml secrets: inherit with: - GIT_SHA: ${{ inputs.GIT_SHA }} - # replay-verify config - BUCKET: ${{ inputs.TESTNET_BUCKET || 'aptos-testnet-backup' }} - SUB_DIR: e1 - HISTORY_START: 862000000 - # to see historical TXNS_TO_SKIP, check out ce6158ac2764ee9d4c8738a85f3bcdc6bd0cadc1 - TXNS_TO_SKIP: "0" - # 1195000000-122000000: https://github.com/aptos-labs/aptos-core/pull/13832 - RANGES_TO_SKIP: "1195000000-1220000000" - BACKUP_CONFIG_TEMPLATE_PATH: terraform/helm/fullnode/files/backup/gcs.yaml - # workflow config - RUNS_ON: "high-perf-docker-with-local-ssd" - TIMEOUT_MINUTES: 180 - MAX_VERSIONS_PER_RANGE: 2000000 + NETWORK: "testnet" + IMAGE_TAG: ${{ inputs.IMAGE_TAG }} + START_VERSION: ${{ inputs.START_VERSION }} + END_VERSION: ${{ inputs.END_VERSION }} replay-mainnet: if: | github.event_name == 'schedule' || - github.event_name == 'push' || - github.event_name == 'workflow_dispatch' && (inputs.CHAIN_NAME == 'mainnet' || inputs.CHAIN_NAME == 'all' ) - needs: determine-test-metadata - uses: ./.github/workflows/workflow-run-replay-verify.yaml - secrets: inherit - with: - GIT_SHA: ${{ inputs.GIT_SHA }} - # replay-verify config - BUCKET: ${{ inputs.MAINNET_BUCKET || 'aptos-mainnet-backup' }} - SUB_DIR: e1 - HISTORY_START: 518000000 - #TXNS_TO_SKIP: 12253479 12277499 148358668 - TXNS_TO_SKIP: "0" - # 1197378568-1198492648: https://github.com/aptos-labs/aptos-core/pull/13832 - RANGES_TO_SKIP: "1197378568-1198492648" - BACKUP_CONFIG_TEMPLATE_PATH: terraform/helm/fullnode/files/backup/gcs.yaml - # workflow config - RUNS_ON: "high-perf-docker-with-local-ssd" - TIMEOUT_MINUTES: 180 - MAX_VERSIONS_PER_RANGE: 800000 - - test-replay: - if: ${{ (github.event_name == 'pull_request') && contains(github.event.pull_request.labels.*.name, 'CICD:test-replay')}} + github.event_name == 'workflow_dispatch' && (inputs.NETWORK == 'mainnet' || inputs.NETWORK == 'all' ) needs: determine-test-metadata - uses: ./.github/workflows/workflow-run-replay-verify.yaml + uses: ./.github/workflows/workflow-run-replay-verify-on-archive.yaml secrets: inherit with: - GIT_SHA: ${{ github.event.pull_request.head.sha }} - # replay-verify config - BUCKET: ${{ inputs.TESTNET_BUCKET || 'aptos-testnet-backup' }} - SUB_DIR: e1 - HISTORY_START: 862000000 - # to see historical TXNS_TO_SKIP, check out ce6158ac2764ee9d4c8738a85f3bcdc6bd0cadc1 - TXNS_TO_SKIP: "0" - # 1195000000-1220000000: https://github.com/aptos-labs/aptos-core/pull/13832 - RANGES_TO_SKIP: "1195000000-1220000000" - BACKUP_CONFIG_TEMPLATE_PATH: terraform/helm/fullnode/files/backup/gcs.yaml - # workflow config - RUNS_ON: "high-perf-docker-with-local-ssd" - TIMEOUT_MINUTES: 120 # increase test replay timeout to capture more flaky errors - MAX_VERSIONS_PER_RANGE: 2000000 + NETWORK: "mainnet" + IMAGE_TAG: ${{ inputs.IMAGE_TAG }} + START_VERSION: ${{ inputs.START_VERSION }} + END_VERSION: ${{ inputs.END_VERSION }} \ No newline at end of file From bd71e35e0c1ceab0828b8fef1f35ba9f154f3295 Mon Sep 17 00:00:00 2001 From: Wolfgang Grieskamp Date: Fri, 13 Dec 2024 13:19:27 -0800 Subject: [PATCH 49/78] [decompiler] Downgrade to bytecode v6 for Revela (#15597) Since the bytecode version default is v7, Revela cannot be used at all anymore. This PR attempts to downgrade to v6 before calling Revela, if possible. This allows to continue to work with Revela until the new decompiler is available. --- crates/aptos/CHANGELOG.md | 1 + crates/aptos/src/move_tool/bytecode.rs | 58 +++++++++++++++++++++++++- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/crates/aptos/CHANGELOG.md b/crates/aptos/CHANGELOG.md index 353ac9f1f9458..b1fc2e380c6d7 100644 --- a/crates/aptos/CHANGELOG.md +++ b/crates/aptos/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to the Aptos CLI will be captured in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) and the format set out by [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). # Unreleased +- Downgrade bytecode version to v6 before calling the Revela decompiler, if possible, i.e. no enum types are used. This allows to continue to use Revela until the new decompiler is ready. ## [5.0.0] - 2024/12/11 - [**Breaking Change**] `aptos init` and `aptos account fund-with-faucet` no longer work directly with testnet, you must now use the minting page at the [Aptos dev docs](https://aptos.dev/network/faucet). diff --git a/crates/aptos/src/move_tool/bytecode.rs b/crates/aptos/src/move_tool/bytecode.rs index fdb77c9d89571..57fcf28d8d17a 100644 --- a/crates/aptos/src/move_tool/bytecode.rs +++ b/crates/aptos/src/move_tool/bytecode.rs @@ -20,7 +20,8 @@ use async_trait::async_trait; use clap::{Args, Parser}; use itertools::Itertools; use move_binary_format::{ - binary_views::BinaryIndexedView, file_format::CompiledScript, CompiledModule, + binary_views::BinaryIndexedView, file_format::CompiledScript, file_format_common, + CompiledModule, }; use move_bytecode_source_map::{mapping::SourceMapping, utils::source_map_from_file}; use move_command_line_common::files::{ @@ -37,6 +38,7 @@ use std::{ process::Command, str, }; +use tempfile::NamedTempFile; const DISASSEMBLER_EXTENSION: &str = "mv.asm"; const DECOMPILER_EXTENSION: &str = "mv.move"; @@ -323,7 +325,14 @@ impl BytecodeCommand { let exe = get_revela_path()?; let to_cli_error = |e| CliError::IO(exe.display().to_string(), e); let mut cmd = Command::new(exe.as_path()); - cmd.arg(format!("--bytecode={}", bytecode_path.display())); + // WORKAROUND: if the bytecode is v7, try to downgrade to v6 since Revela + // does not support v7 + let v6_temp_file = self.downgrade_to_v6(bytecode_path)?; + if let Some(file) = &v6_temp_file { + cmd.arg(format!("--bytecode={}", file.path().display())); + } else { + cmd.arg(format!("--bytecode={}", bytecode_path.display())); + } if self.is_script { cmd.arg("--script"); } @@ -343,4 +352,49 @@ impl BytecodeCommand { ))) } } + + fn downgrade_to_v6(&self, file_path: &Path) -> Result, CliError> { + let error_explanation = || { + format!( + "{} in `{}` contains Move 2 features (e.g. enum types) \ + types which are not yet supported by the decompiler", + if self.is_script { "script " } else { "module" }, + file_path.display() + ) + }; + let create_new_bytecode = |bytes: &[u8]| -> Result { + let temp_file = NamedTempFile::new() + .map_err(|e| CliError::IO("creating v6 temp file".to_string(), e))?; + fs::write(temp_file.path(), bytes) + .map_err(|e| CliError::IO("writing v6 temp file".to_string(), e))?; + Ok(temp_file) + }; + let bytes = read_from_file(file_path)?; + if self.is_script { + let script = CompiledScript::deserialize(&bytes).map_err(|e| { + CliError::UnableToParse("script", format!("cannot deserialize: {}", e)) + })?; + if script.version < file_format_common::VERSION_7 { + return Ok(None); + } + let mut new_bytes = vec![]; + script + .serialize_for_version(Some(file_format_common::VERSION_6), &mut new_bytes) + // The only reason why this can fail is because of Move 2 features + .map_err(|_| CliError::UnexpectedError(error_explanation()))?; + Ok(Some(create_new_bytecode(&new_bytes)?)) + } else { + let module = CompiledModule::deserialize(&bytes).map_err(|e| { + CliError::UnableToParse("script", format!("cannot deserialize: {}", e)) + })?; + if module.version < file_format_common::VERSION_7 { + return Ok(None); + } + let mut new_bytes = vec![]; + module + .serialize_for_version(Some(file_format_common::VERSION_6), &mut new_bytes) + .map_err(|_| CliError::UnexpectedError(error_explanation()))?; + Ok(Some(create_new_bytecode(&new_bytes)?)) + } + } } From 53715404314b3c08be5b3aa0138880ce7a6cf1f6 Mon Sep 17 00:00:00 2001 From: Zekun Li Date: Fri, 13 Dec 2024 12:34:02 -0800 Subject: [PATCH 50/78] [forge] enable pipeline --- testsuite/forge/src/config.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/testsuite/forge/src/config.rs b/testsuite/forge/src/config.rs index 940589e7fb3b1..599cfad0a411b 100644 --- a/testsuite/forge/src/config.rs +++ b/testsuite/forge/src/config.rs @@ -238,6 +238,11 @@ impl ForgeConfig { ["enable_storage_sharding"] = true.into(); helm_values["validator"]["config"]["indexer_db_config"]["enable_event"] = true.into(); helm_values["fullnode"]["config"]["indexer_db_config"]["enable_event"] = true.into(); + + // enable new pipeline + helm_values["validator"]["config"]["consensus"]["enable_pipeline"] = true.into(); + helm_values["fullnode"]["config"]["consensus_observer"]["enable_pipeline"] = + true.into(); })) } From da6317811174c51901220f57ab71ddab4a13eaa2 Mon Sep 17 00:00:00 2001 From: Vineeth Kashyap Date: Fri, 13 Dec 2024 17:50:52 -0500 Subject: [PATCH 51/78] Creating temps for each arg. (#15514) --- .../src/bytecode_generator.rs | 9 +- .../move/move-compiler-v2/src/experiments.rs | 9 + third_party/move/move-compiler-v2/src/lib.rs | 8 +- .../src/pipeline/dead_store_elimination.rs | 76 +- .../src/pipeline/flush_writes_processor.rs | 177 +- .../tests/ability-check/bug_14189.exp | 7 +- .../tests/ability-check/operator_drop.exp | 8 +- .../ability-check/typing/eq_invalid2.exp | 11 +- .../ability-check/typing/neq_invalid2.exp | 6 +- .../borrowed_from_one_path.exp | 604 +++++-- .../tests/ability-transform/by_reference.exp | 751 +++++++++ .../ability-transform/copy_ability_tuple.exp | 221 ++- .../ability-transform/dead_but_borrowed.exp | 86 + .../ability-transform/destroy_after_call.exp | 172 ++ .../ability-transform/drop_after_loop.exp | 436 ++++- .../ability-transform/drop_at_branch.exp | 117 ++ .../foreach_mut_expanded.exp | 938 ++++++++--- .../tests/ability-transform/mutate_return.exp | 138 ++ .../tests/ability-transform/mutate_vector.exp | 198 +++ .../tests/bytecode-generator/assign.exp | 54 +- .../bytecode-generator/assign_inline.exp | 12 + .../tests/bytecode-generator/borrow.exp | 70 + .../borrow_deref_optimize.exp | 60 + .../bug_14300_update_variant_select.exp | 121 ++ .../bug_14300_variant_select_autoref.exp | 26 + .../bug_14471_receiver_inference.exp | 70 +- .../tests/bytecode-generator/bug_14629.exp | 29 + .../bytecode-generator/conditional_borrow.exp | 345 +++- .../bytecode-generator/escape_autoref.exp | 46 + .../tests/bytecode-generator/fields.exp | 122 ++ .../bytecode-generator/freeze_mut_ref.exp | 257 ++- .../tests/bytecode-generator/globals.exp | 57 +- .../tests/bytecode-generator/if_else.exp | 133 +- .../tests/bytecode-generator/inline_specs.exp | 34 +- .../tests/bytecode-generator/loop.exp | 266 ++- .../tests/bytecode-generator/loop_labels.exp | 14 + .../tests/bytecode-generator/matching_ok.exp | 20 +- .../matching_refutable_err.exp | 19 + .../tests/bytecode-generator/operators.exp | 264 ++- .../tests/bytecode-generator/pack_order.exp | 106 +- .../tests/bytecode-generator/pack_unpack.exp | 37 +- .../reference_conversion.exp | 28 + .../bytecode-generator/spec_construct.exp | 21 + .../tests/bytecode-generator/vector.exp | 11 + .../tests/bytecode-generator/wildcard5.exp | 19 + .../bytecode-verify-failure/equality.exp | 24 +- .../bug-10253.off.exp | 4 - .../bug-10253.on.exp | 168 +- .../jump-label.off.exp | 25 +- .../jump-label.on.exp | 25 +- .../args_with_side_effects.exp | 40 +- .../tests/copy-propagation/branch_1.exp | 16 +- .../tests/copy-propagation/bug_12068.exp | 84 +- .../tests/copy-propagation/loop_1.exp | 62 +- .../tests/copy-propagation/loop_2.exp | 62 +- .../tests/copy-propagation/seq_kills_1.exp | 26 +- .../tests/copy-propagation/seq_kills_2.exp | 26 +- .../copy-propagation/straight_line_kills.exp | 26 +- .../tests/eager-pushes/eager_load_03.exp | 19 +- .../eager-pushes/framework_reduced_01.exp | 43 +- .../eager-pushes/framework_reduced_02.exp | 62 +- .../eager-pushes/framework_reduced_03.exp | 92 +- .../eager-pushes/framework_reduced_04.exp | 29 +- .../eager-pushes/framework_reduced_05.exp | 95 +- .../eager-pushes/framework_reduced_06.exp | 107 +- .../eager-pushes/framework_reduced_07.exp | 97 +- .../eager-pushes/framework_reduced_08.exp | 97 +- .../eager-pushes/framework_reduced_09.exp | 116 +- .../eager-pushes/framework_reduced_10.exp | 221 +-- .../eager-pushes/move_stdlib_reduced.exp | 85 +- .../tests/eager-pushes/txn_reduced_01.exp | 179 +- .../file-format-generator/bug_14762.opt.exp | 47 +- .../file-format-generator/eager_push_01.exp | 46 + .../file-format-generator/eager_push_01.move | 11 + .../eager_push_01.opt.exp | 28 + .../file-format-generator/eager_push_02.exp | 20 + .../file-format-generator/eager_push_02.move | 5 + .../eager_push_02.opt.exp | 17 + .../file-format-generator/fields.opt.exp | 14 +- .../framework_reduced_06.opt.exp | 22 +- .../file-format-generator/globals.opt.exp | 22 +- .../file-format-generator/if_else.opt.exp | 2 - .../tests/file-format-generator/loop.opt.exp | 3 - .../file-format-generator/multi_use.opt.exp | 1 - .../file-format-generator/operators.opt.exp | 25 +- .../file-format-generator/opt_load_01.opt.exp | 14 - .../file-format-generator/opt_load_02.opt.exp | 72 +- .../file-format-generator/opt_load_04.opt.exp | 2 - .../file-format-generator/opt_load_05.opt.exp | 7 +- .../file-format-generator/pack_unpack.opt.exp | 13 +- .../pack_unpack_ref.opt.exp | 29 +- .../file-format-generator/vector.opt.exp | 5 +- .../tests/flush-writes/def_use_01.on.exp | 1 + .../tests/flush-writes/def_use_02.on.exp | 1 + .../tests/flush-writes/def_use_03.on.exp | 7 +- .../tests/flush-writes/def_use_04.on.exp | 7 +- .../tests/flush-writes/def_use_05.on.exp | 1 + .../tests/flush-writes/def_use_06.on.exp | 8 +- .../tests/flush-writes/def_use_07.off.exp | 1 - .../tests/flush-writes/def_use_07.on.exp | 14 +- .../tests/flush-writes/def_use_08.on.exp | 3 + .../tests/flush-writes/in_order_use_01.move | 26 + .../flush-writes/in_order_use_01.off.exp | 29 + .../tests/flush-writes/in_order_use_01.on.exp | 83 + .../tests/flush-writes/loop_01.off.exp | 1 - .../tests/flush-writes/loop_01.on.exp | 32 +- .../tests/flush-writes/loop_02.off.exp | 2 - .../tests/flush-writes/loop_02.on.exp | 33 +- .../flush-writes/out_of_order_use_01.on.exp | 6 + .../flush-writes/out_of_order_use_02.off.exp | 13 +- .../flush-writes/out_of_order_use_02.on.exp | 8 +- .../flush-writes/out_of_order_use_03.off.exp | 13 +- .../flush-writes/out_of_order_use_03.on.exp | 21 +- .../flush-writes/out_of_order_use_04.on.exp | 9 +- .../flush-writes/unused_flush_early_02.on.exp | 15 +- .../flush-writes/unused_flush_early_03.on.exp | 56 +- .../inline-parity/non_lambda_arg.lambda.exp | 68 +- .../tests/lambda/non_lambda_arg.lambda.exp | 68 +- .../tests/live-var/bug_9717_looponly.exp | 787 +++++++-- .../tests/live-var/mut_inline.exp | 1484 ++++++++++++++--- .../tests/live-var/mut_inline_typed.exp | 1484 ++++++++++++++--- .../tests/live-var/mut_ref.exp | 232 ++- .../tests/more-v1/liveness/mut_ref.exp | 4 +- .../more-v1/locals/use_after_move_if.exp | 2 +- .../more-v1/locals/use_after_move_if_else.exp | 6 +- .../more-v1/locals/use_after_move_simple.exp | 2 +- .../commands/branch_assigns_then_moves.exp | 2 +- .../move/commands/else_moves_if_doesnt.exp | 2 +- .../move/commands/if_moves_else_doesnt.exp | 2 +- .../move/commands/if_moves_no_else.exp | 2 +- .../moved_var_not_simplified.exp | 2 +- .../tests/op-equal/eval_order.exp | 159 +- .../tests/op-equal/invalid1.exp | 28 +- .../tests/op-equal/valid0.exp | 105 +- .../tests/op-equal/valid1.exp | 53 +- .../tests/reference-safety/duplicate_use.exp | 4 +- .../reference-safety/duplicate_use.old.exp | 4 +- .../tests/reference-safety/freeze.exp | 4 +- .../tests/reference-safety/freeze.old.exp | 4 +- .../reference-safety/multiple_use_invalid.exp | 2 +- .../multiple_use_invalid.old.exp | 13 +- .../v1-borrow-tests/factor_invalid_1.exp | 2 +- .../v1-borrow-tests/factor_invalid_1.old.exp | 12 + .../imm_borrow_global_invalid.exp | 4 +- .../v1-borrow-tests/imm_borrow_loc.old.exp | 6 +- .../imm_borrow_loc_valid.old.exp | 4 +- .../v1-tests/call_mutual_borrows_invalid.exp | 12 +- .../call_mutual_borrows_invalid.old.exp | 60 +- .../v1-tests/copy_full_invalid.exp | 4 +- .../v1-tests/copy_full_invalid.old.exp | 8 +- .../else_assigns_if_doesnt.exp | 2 +- .../if_assigns_else_doesnt.exp | 2 +- .../moved_var_not_simplified.exp | 2 +- .../use_before_assign_loop.exp | 2 +- .../simplifier/moved_var_not_simplified.exp | 2 +- .../move/move-compiler-v2/tests/testsuite.rs | 25 +- .../uninit-use-checker/assign_both_branch.exp | 25 + .../assign_in_one_if_branch_unfoldable.exp | 43 +- ...ign_wrong_if_branch_no_else_unfoldable.exp | 79 +- .../assign_wrong_if_branch_unfoldable.exp | 79 +- .../else_assigns_if_doesnt_unfoldable.exp | 85 +- .../if_assigns_else_doesnt_unfoldable.exp | 85 +- .../if_assigns_no_else_unfoldable.exp | 79 +- .../tests/uninit-use-checker/no_error.exp | 69 +- .../use_twice_before_assign.exp | 19 +- .../uninit-use-checker/uses_before_assign.exp | 15 +- .../v1-borrows/eq_unassigned_local.exp | 31 +- .../v1-commands/assign_in_one_if_branch.exp | 47 +- .../v1-commands/assign_wrong_if_branch.exp | 81 +- .../assign_wrong_if_branch_no_else.exp | 81 +- .../v1-commands/else_assigns_if_doesnt.exp | 87 +- .../v1-commands/if_assigns_else_doesnt.exp | 87 +- .../v1-commands/if_assigns_no_else.exp | 81 +- .../v1-locals/use_before_assign_if.exp | 43 +- .../v1-locals/use_before_assign_loop.exp | 85 +- .../v1-locals/use_before_assign_simple.exp | 41 +- .../unreachable-code-remover/abort_only.exp | 11 + .../abort_or_return_always.exp | 17 + .../always_false_branch.exp | 83 +- .../break_unreachable.exp | 159 +- .../conditional_loop_unreachable.exp | 70 +- .../inter_procedural_abort.exp | 56 +- .../loop_unreachable.exp | 10 + .../return_after_abort.exp | 11 + .../args_with_side_effects.exp | 109 +- .../args_with_side_effects.opt.exp | 109 +- .../tests/variable-coalescing/branch_1.exp | 64 +- .../variable-coalescing/branch_1.opt.exp | 64 +- .../tests/variable-coalescing/bug_12068.exp | 211 +-- .../variable-coalescing/bug_12068.opt.exp | 211 +-- .../tests/variable-coalescing/call_1.exp | 8 +- .../tests/variable-coalescing/call_1.opt.exp | 8 +- .../tests/variable-coalescing/call_2.exp | 13 +- .../tests/variable-coalescing/call_2.opt.exp | 13 +- .../variable-coalescing/cant_coalesce_1.exp | 62 +- .../cant_coalesce_1.opt.exp | 44 +- .../cant_copy_propagate.exp | 72 +- .../cant_copy_propagate.opt.exp | 72 +- .../tests/variable-coalescing/conditional.exp | 67 +- .../tests/variable-coalescing/consume_2.exp | 10 +- .../variable-coalescing/consume_2.opt.exp | 10 +- .../variable-coalescing/cyclic_dead_store.exp | 315 ++-- .../cyclic_dead_store.opt.exp | 315 ++-- .../variable-coalescing/dead_assignment_1.exp | 3 +- .../dead_assignment_1.opt.exp | 3 +- .../variable-coalescing/dead_assignment_2.exp | 3 +- .../dead_assignment_2.opt.exp | 3 +- .../variable-coalescing/dead_assignment_4.exp | 3 +- .../dead_assignment_4.opt.exp | 3 +- .../variable-coalescing/intermingled_1.exp | 64 +- .../intermingled_1.opt.exp | 59 +- .../variable-coalescing/intermingled_2.exp | 109 +- .../intermingled_2.opt.exp | 91 +- .../variable-coalescing/intermingled_3.exp | 84 +- .../intermingled_3.opt.exp | 59 +- .../tests/variable-coalescing/loop_1.exp | 176 +- .../tests/variable-coalescing/loop_1.opt.exp | 176 +- .../tests/variable-coalescing/loop_2.exp | 182 +- .../tests/variable-coalescing/loop_2.opt.exp | 182 +- .../non_overlapping_vars1.exp | 106 +- .../non_overlapping_vars1.opt.exp | 106 +- .../non_overlapping_vars_diff_type.exp | 122 +- .../non_overlapping_vars_diff_type.opt.exp | 122 +- .../variable-coalescing/overlapping_vars.exp | 37 +- .../variable-coalescing/reassigned_var.exp | 29 +- .../reassigned_var.opt.exp | 49 +- .../variable-coalescing/self_assigns.exp | 319 ++-- .../variable-coalescing/self_assigns.opt.exp | 319 ++-- .../tests/variable-coalescing/seq_kills_1.exp | 82 +- .../variable-coalescing/seq_kills_1.opt.exp | 82 +- .../tests/variable-coalescing/seq_kills_2.exp | 82 +- .../variable-coalescing/seq_kills_2.opt.exp | 82 +- .../sequential_assign_struct.exp | 3 +- .../sequential_assign_struct.opt.exp | 3 +- .../simple_sequential_assign.exp | 3 +- .../simple_sequential_assign.opt.exp | 3 +- .../straight_line_kills.exp | 78 +- .../straight_line_kills.opt.exp | 78 +- .../tests/variable-coalescing/swap.exp | 10 +- .../tests/variable-coalescing/swap.opt.exp | 10 +- .../variable-coalescing/swap_in_a_loop.exp | 205 ++- .../swap_in_a_loop.opt.exp | 205 ++- .../tests/variable-coalescing/unused_add.exp | 29 +- .../tests/misc/vector_popback.exp | 3 + .../tests/misc/vector_popback.move | 37 + 245 files changed, 14948 insertions(+), 5400 deletions(-) create mode 100644 third_party/move/move-compiler-v2/tests/file-format-generator/eager_push_01.exp create mode 100644 third_party/move/move-compiler-v2/tests/file-format-generator/eager_push_01.move create mode 100644 third_party/move/move-compiler-v2/tests/file-format-generator/eager_push_01.opt.exp create mode 100644 third_party/move/move-compiler-v2/tests/file-format-generator/eager_push_02.exp create mode 100644 third_party/move/move-compiler-v2/tests/file-format-generator/eager_push_02.move create mode 100644 third_party/move/move-compiler-v2/tests/file-format-generator/eager_push_02.opt.exp create mode 100644 third_party/move/move-compiler-v2/tests/flush-writes/in_order_use_01.move create mode 100644 third_party/move/move-compiler-v2/tests/flush-writes/in_order_use_01.off.exp create mode 100644 third_party/move/move-compiler-v2/tests/flush-writes/in_order_use_01.on.exp create mode 100644 third_party/move/move-compiler-v2/transactional-tests/tests/misc/vector_popback.exp create mode 100644 third_party/move/move-compiler-v2/transactional-tests/tests/misc/vector_popback.move diff --git a/third_party/move/move-compiler-v2/src/bytecode_generator.rs b/third_party/move/move-compiler-v2/src/bytecode_generator.rs index e6be8ca0e80c5..3e6b05bd88d5b 100644 --- a/third_party/move/move-compiler-v2/src/bytecode_generator.rs +++ b/third_party/move/move-compiler-v2/src/bytecode_generator.rs @@ -1110,7 +1110,14 @@ impl<'env> Generator<'env> { fn gen_arg_list(&mut self, exps: &[Exp]) -> Vec { // If all args are side-effect free, we don't need to force temporary generation // to get left-to-right evaluation. - let with_forced_temp = !exps.iter().all(is_definitely_pure); + // TODO: after comparison testing, remove depending on the experiment and always + // have `with_forced_temp` be true. + let options = self + .env() + .get_extension::() + .expect("Options is available"); + let with_forced_temp = options.experiment_on(Experiment::RETAIN_TEMPS_FOR_ARGS) + || !exps.iter().all(is_definitely_pure); let len = exps.len(); // Generate code with (potentially) forced creation of temporaries for all except last arg. let mut args = exps diff --git a/third_party/move/move-compiler-v2/src/experiments.rs b/third_party/move/move-compiler-v2/src/experiments.rs index fd6174e8231bf..c0e7d5178ca60 100644 --- a/third_party/move/move-compiler-v2/src/experiments.rs +++ b/third_party/move/move-compiler-v2/src/experiments.rs @@ -276,6 +276,14 @@ pub static EXPERIMENTS: Lazy> = Lazy::new(|| { description: "Avoid storing to a local during assigns".to_string(), default: Inherited(Experiment::OPTIMIZE_WAITING_FOR_COMPARE_TESTS.to_string()), }, + Experiment { + name: Experiment::RETAIN_TEMPS_FOR_ARGS.to_string(), + description: + "Create temps for each argument of a function call during stackless bytecode \ + generation and retain them until file format bytecode generation" + .to_string(), + default: Inherited(Experiment::OPTIMIZE_WAITING_FOR_COMPARE_TESTS.to_string()), + }, ]; experiments .into_iter() @@ -316,6 +324,7 @@ impl Experiment { pub const RECURSIVE_TYPE_CHECK: &'static str = "recursive-type-check"; pub const REFERENCE_SAFETY: &'static str = "reference-safety"; pub const REFERENCE_SAFETY_V3: &'static str = "reference-safety-v3"; + pub const RETAIN_TEMPS_FOR_ARGS: &'static str = "retain-temps-for-args"; pub const SEQS_IN_BINOPS_CHECK: &'static str = "seqs-in-binops-check"; pub const SPEC_CHECK: &'static str = "spec-check"; pub const SPEC_REWRITE: &'static str = "spec-rewrite"; diff --git a/third_party/move/move-compiler-v2/src/lib.rs b/third_party/move/move-compiler-v2/src/lib.rs index 84eda127b9f03..ecfcfc75dc5c1 100644 --- a/third_party/move/move-compiler-v2/src/lib.rs +++ b/third_party/move/move-compiler-v2/src/lib.rs @@ -465,7 +465,7 @@ pub fn bytecode_pipeline(env: &GlobalEnv) -> FunctionTargetPipeline { pipeline.add_processor(Box::new(UnreachableCodeProcessor {})); pipeline.add_processor(Box::new(UnreachableCodeRemover {})); pipeline.add_processor(Box::new(LiveVarAnalysisProcessor::new(true))); - pipeline.add_processor(Box::new(DeadStoreElimination {})); + pipeline.add_processor(Box::new(DeadStoreElimination::new(true))); } if options.experiment_on(Experiment::VARIABLE_COALESCING) { @@ -484,7 +484,11 @@ pub fn bytecode_pipeline(env: &GlobalEnv) -> FunctionTargetPipeline { if options.experiment_on(Experiment::DEAD_CODE_ELIMINATION) { pipeline.add_processor(Box::new(LiveVarAnalysisProcessor::new(true))); - pipeline.add_processor(Box::new(DeadStoreElimination {})); + // TODO: after comparison testing passes, always call with `eliminate_all_self_assigns` set + // to `false` when instantiating `DeadStoreElimination`. + pipeline.add_processor(Box::new(DeadStoreElimination::new( + !options.experiment_on(Experiment::RETAIN_TEMPS_FOR_ARGS), + ))); } // Run live var analysis again because it could be invalidated by previous pipeline steps, diff --git a/third_party/move/move-compiler-v2/src/pipeline/dead_store_elimination.rs b/third_party/move/move-compiler-v2/src/pipeline/dead_store_elimination.rs index 95f54dba5f04f..62d336cf064cb 100644 --- a/third_party/move/move-compiler-v2/src/pipeline/dead_store_elimination.rs +++ b/third_party/move/move-compiler-v2/src/pipeline/dead_store_elimination.rs @@ -14,6 +14,8 @@ //! this transformation removes dead stores, i.e., assignments and loads to locals which //! are not live afterwards (or are live only in dead code, making them effectively dead). //! In addition, it also removes self-assignments, i.e., assignments of the form `x = x`. +//! One can also remove only those self-assignments where the definition is in the same block +//! before the self-assign by using `eliminate_all_self_assigns=false`. use crate::pipeline::livevar_analysis_processor::LiveVarAnnotation; use move_binary_format::file_format::CodeOffset; @@ -22,6 +24,7 @@ use move_stackless_bytecode::{ function_target::{FunctionData, FunctionTarget}, function_target_pipeline::{FunctionTargetProcessor, FunctionTargetsHolder}, stackless_bytecode::Bytecode, + stackless_control_flow_graph::StacklessControlFlowGraph, }; use std::collections::{BTreeMap, BTreeSet}; @@ -59,19 +62,26 @@ struct ReducedDefUseGraph { impl ReducedDefUseGraph { /// Get the dead stores that are safe to remove from the function `target`. - pub fn dead_stores(target: &FunctionTarget) -> BTreeSet { + /// If `eliminate_all_self_assigns` is true, all self-assignments are removed. + pub fn dead_stores(target: &FunctionTarget, eliminate_all_self_assigns: bool) -> BTreeSet { Self { children: BTreeMap::new(), parents: BTreeMap::new(), defs_alive: BTreeSet::new(), defs_dead: BTreeSet::new(), } - .run_stages(target) + .run_stages(target, eliminate_all_self_assigns) } /// Run various stages to return the dead stores from `target`. - fn run_stages(mut self, target: &FunctionTarget) -> BTreeSet { + /// If `eliminate_all_self_assigns` is true, all self-assignments are removed. + fn run_stages( + mut self, + target: &FunctionTarget, + eliminate_all_self_assigns: bool, + ) -> BTreeSet { let code = target.get_bytecode(); + let cfg = StacklessControlFlowGraph::new_forward(code); let live_vars = target .get_annotations() .get::() @@ -97,8 +107,19 @@ impl ReducedDefUseGraph { for dead_def_leaf in self.defs_dead.clone() { self.disconnect_from_parents(dead_def_leaf); } - // Stage 3: Let's disconnect all the self-assignments from the graph and kill them. + // Stage 3: Let's disconnect self-assignments from the graph and kill them + // (conditioned upon `eliminate_all_self_assigns`). for self_assign in self_assigns { + let eliminate_this_self_assign = Self::should_eliminate_given_self_assign( + self_assign, + code, + &cfg, + live_vars, + eliminate_all_self_assigns, + ); + if !eliminate_this_self_assign { + continue; + } let mut parents = self.disconnect_from_parents(self_assign); let mut children = self.disconnect_from_children(self_assign); // In case there is a cycle of self-assignments in the graph. @@ -208,12 +229,55 @@ impl ReducedDefUseGraph { self.defs_dead.insert(def); // def without a use is dead } } + + /// Should `self_assign` be eliminated? + fn should_eliminate_given_self_assign( + self_assign: CodeOffset, + code: &[Bytecode], + cfg: &StacklessControlFlowGraph, + live_vars: &LiveVarAnnotation, + eliminate_all_self_assigns: bool, + ) -> bool { + if !eliminate_all_self_assigns { + // Eliminate this self assign if the definition for this self-assign is in the same block + // before the self assign. + let block = cfg.enclosing_block(self_assign); + let block_begin_offset = cfg.code_range(block).start; + let self_assign_instr = &code[self_assign as usize]; + let self_assign_temp = self_assign_instr.dests()[0]; + // Is `self_assign_temp` live before this block? + let info = live_vars + .get_info_at(block_begin_offset as CodeOffset) + .before + .get(&self_assign_temp); + match info { + None => true, // must be defined in the block + Some(live) => !live.usage_offsets().contains(&self_assign), + } + } else { + true + } + } } /// A processor which performs dead store elimination transformation. -pub struct DeadStoreElimination {} +pub struct DeadStoreElimination { + /// If true, eliminate all self-assignments of the form `x = x`. + /// Otherwise, only self assignments where the definition is in the same block + /// before the self-assign are removed. + eliminate_all_self_assigns: bool, +} impl DeadStoreElimination { + /// If `eliminate_all_self_assigns` is true, all self-assignments are removed. + /// Otherwise, only self assignments where the definition is in the same block + /// before the self-assign are removed. + pub fn new(eliminate_all_self_assigns: bool) -> Self { + Self { + eliminate_all_self_assigns, + } + } + /// Transforms the `code` of a function by removing the instructions corresponding to /// the code offsets contained in `dead_stores`. /// @@ -242,7 +306,7 @@ impl FunctionTargetProcessor for DeadStoreElimination { return data; } let target = FunctionTarget::new(func_env, &data); - let dead_stores = ReducedDefUseGraph::dead_stores(&target); + let dead_stores = ReducedDefUseGraph::dead_stores(&target, self.eliminate_all_self_assigns); let new_code = Self::transform(&target, dead_stores); // Note that the file format generator will not include unused locals in the generated code, // so we don't need to prune unused locals here for various fields of `data` (like `local_types`). diff --git a/third_party/move/move-compiler-v2/src/pipeline/flush_writes_processor.rs b/third_party/move/move-compiler-v2/src/pipeline/flush_writes_processor.rs index 1a9c6456cb146..d15db4139ac3e 100644 --- a/third_party/move/move-compiler-v2/src/pipeline/flush_writes_processor.rs +++ b/third_party/move/move-compiler-v2/src/pipeline/flush_writes_processor.rs @@ -42,7 +42,11 @@ //! In all these cases, the file format generator can avoid extra stack operations due //! to eager flushing. -use crate::pipeline::livevar_analysis_processor::{LiveVarAnnotation, LiveVarInfoAtCodeOffset}; +use crate::{ + experiments::Experiment, + pipeline::livevar_analysis_processor::{LiveVarAnnotation, LiveVarInfoAtCodeOffset}, + Options, +}; use itertools::Itertools; use move_binary_format::file_format::CodeOffset; use move_model::{ast::TempIndex, model::FunctionEnv}; @@ -176,6 +180,15 @@ impl FunctionTargetProcessor for FlushWritesProcessor { let use_def_links = UseDefLinks::new(code, live_vars); let cfg = StacklessControlFlowGraph::new_forward(code); let mut flush_writes: BTreeMap> = BTreeMap::new(); + // TODO: After comparison testing, remove the `assign_optimize` flag and always + // perform the optimization. It currently is passed around so that existing behavior + // is retained when the flag is off. + let assign_optimize = func_env + .module_env + .env + .get_extension::() + .expect("Options is available") + .experiment_on(Experiment::RETAIN_TEMPS_FOR_ARGS); for block_id in cfg.blocks() { if let Some((lower, upper)) = cfg.instr_offset_bounds(block_id) { Self::extract_flush_writes_in_block( @@ -183,6 +196,7 @@ impl FunctionTargetProcessor for FlushWritesProcessor { code, &use_def_links, &mut flush_writes, + assign_optimize, ); } } @@ -205,19 +219,35 @@ impl FlushWritesProcessor { code: &[Bytecode], use_def_links: &UseDefLinks, flush_writes: &mut BTreeMap>, + assign_optimize: bool, ) { let upper = *block_range.end(); - for offset in block_range { + // Traverse the block in reverse order: for each definition starting from the + // latest in a block, we compute whether is should be flushed away. This + // information is available for subsequent definitions processed. + for offset in block_range.rev() { let instr = &code[offset as usize]; - // Only `Load` and `Call` instructions push temps to the stack. + use Bytecode::{Assign, Call, Load}; + // Only `Assign`, `Call`, and `Load` instructions push temps to the stack. // We need to find if any of these temps are better flushed right away. - if matches!(instr, Bytecode::Load(..) | Bytecode::Call(..)) { - for (dest_index, dest) in instr.dests().into_iter().enumerate() { + if matches!(instr, Assign(..) | Call(..) | Load(..)) { + if !assign_optimize && matches!(instr, Assign(..)) { + // Retain previous behavior. + continue; + } + for (dest_index, dest) in instr.dests().into_iter().enumerate().rev() { let def = DefOrUsePoint { offset, index: dest_index, }; - if Self::could_flush_right_away(def, upper, use_def_links) { + if Self::could_flush_right_away( + def, + upper, + code, + use_def_links, + flush_writes, + assign_optimize, + ) { flush_writes.entry(offset).or_default().insert(dest); } } @@ -230,7 +260,10 @@ impl FlushWritesProcessor { fn could_flush_right_away( def: DefOrUsePoint, block_end: CodeOffset, + code: &[Bytecode], use_def_links: &UseDefLinks, + flush_writes: &BTreeMap>, + assign_optimize: bool, ) -> bool { use_def_links.def_to_use.get(&def).map_or(true, |uses| { let exactly_one_use = uses.len() == 1; @@ -244,8 +277,18 @@ impl FlushWritesProcessor { // If used outside the basic block, flush right away. return true; } - // If has intervening definition, flush right away. - Self::has_intervening_def(def, use_, use_def_links) + // If has intervening definitions, flush right away. + // The first call checks the definitions of preceding uses in the same instruction. + // The second call checks definitions between `def` and `use_`. + Self::has_intervening_def(&def, use_, use_def_links) + || Self::has_flush_causing_defs_in_between( + &def, + use_, + code, + use_def_links, + flush_writes, + assign_optimize, + ) }) } @@ -253,7 +296,7 @@ impl FlushWritesProcessor { /// instruction as `use_`, which has a definition after `def` and before /// the `use_` instruction? fn has_intervening_def( - def: DefOrUsePoint, + def: &DefOrUsePoint, use_: &DefOrUsePoint, use_def_links: &UseDefLinks, ) -> bool { @@ -271,12 +314,126 @@ impl FlushWritesProcessor { .get(&prev_use_at_usage_instr) .map_or(false, |defs| { defs.iter().any(|defs_of_prev_use| { - defs_of_prev_use > &def && defs_of_prev_use.offset < *use_offset + defs_of_prev_use > def && defs_of_prev_use.offset < *use_offset }) }) }) } + /// Check for various conditions where between a `def` and its `use_`, there are other + /// definitions that could cause `def` to be flushed before its `use_`. + fn has_flush_causing_defs_in_between( + def: &DefOrUsePoint, + use_: &DefOrUsePoint, + code: &[Bytecode], + use_def_links: &UseDefLinks, + flush_writes: &BTreeMap>, + assign_optimize: bool, + ) -> bool { + if !assign_optimize { + return false; + } + // For each definition in between `def` and `use_`, is there at least one that is: + // 1. not marked to be flushed right away? + // 2. not consumed before `use_`? + // 3. not used in the same offset as `use_`? + // If so, `def` could be flushed before its `use_`, so we should suggest flush it + // right after definition. + // Note that we expect the code in the block to be processed in the reverse order. + let defs_in_between = Self::get_defs_between(def, use_, use_def_links); + for def_in_between in defs_in_between { + if Self::is_def_flushed_away(&def_in_between, code, flush_writes) { + continue; + } + if Self::consumed_before(&def_in_between, use_, use_def_links) { + continue; + } + if Self::consumed_at(&def_in_between, use_, use_def_links) { + continue; + } + return true; + } + false + } + + /// Has `def` been marked to be flushed right away? + fn is_def_flushed_away( + def: &DefOrUsePoint, + code: &[Bytecode], + flush_writes: &BTreeMap>, + ) -> bool { + if let Some(temps) = flush_writes.get(&def.offset) { + // Some temps were marked to be flushed right away at `instr`. + let instr = &code[def.offset as usize]; + // Was it this `def`? + let def_temp = instr.dests()[def.index]; + return temps.contains(&def_temp); + } + false + } + + /// Is `def` consumed before `use_`? + fn consumed_before( + def: &DefOrUsePoint, + use_: &DefOrUsePoint, + use_def_links: &UseDefLinks, + ) -> bool { + use_def_links + .def_to_use + .get(def) + .map_or(false, |uses| uses.iter().all(|u| u.offset < use_.offset)) + } + + /// Is `def` consumed at `use_`'s offset? + fn consumed_at(def: &DefOrUsePoint, use_: &DefOrUsePoint, use_def_links: &UseDefLinks) -> bool { + let use_offset = use_.offset; + use_def_links + .def_to_use + .get(def) + .map_or(false, |uses| uses.iter().all(|u| u.offset == use_offset)) + } + + /// Get all the definitions between `def` and `use_`. + fn get_defs_between( + def: &DefOrUsePoint, + use_: &DefOrUsePoint, + use_def_links: &UseDefLinks, + ) -> Vec { + let DefOrUsePoint { + offset: def_offset, + index: def_index, + } = def; + let use_offset = use_.offset; + let mut defs = vec![]; + if *def_offset == use_offset { + return defs; + } + // Are there defs at def_offset with index > def_index? + for index in def_index + 1.. { + let potential_def = DefOrUsePoint { + offset: *def_offset, + index, + }; + if use_def_links.def_to_use.contains_key(&potential_def) { + defs.push(potential_def); + } else { + break; + } + } + // Are there defs after def_offset and before use_offset? + for offset in (*def_offset + 1)..use_offset { + for index in 0.. { + let potential_def = DefOrUsePoint { offset, index }; + if use_def_links.def_to_use.contains_key(&potential_def) { + defs.push(potential_def); + } else { + break; + } + } + } + defs + } + /// Registers annotation formatter at the given function target. /// Helps with testing and debugging. pub fn register_formatters(target: &FunctionTarget) { diff --git a/third_party/move/move-compiler-v2/tests/ability-check/bug_14189.exp b/third_party/move/move-compiler-v2/tests/ability-check/bug_14189.exp index 1f466890ce1b3..4d2c8549aa074 100644 --- a/third_party/move/move-compiler-v2/tests/ability-check/bug_14189.exp +++ b/third_party/move/move-compiler-v2/tests/ability-check/bug_14189.exp @@ -1,7 +1,10 @@ Diagnostics: error: local `x1` of type `S2` does not have the `copy` ability - ┌─ tests/ability-check/bug_14189.move:34:18 + ┌─ tests/ability-check/bug_14189.move:34:26 │ 34 │ let x2 = S3 { x: x1, y: x0, z: x1 }; - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^ copy needed here because value is still in use + │ --------^^---------------- + │ │ │ + │ │ copy needed here because value is still in use + │ used here diff --git a/third_party/move/move-compiler-v2/tests/ability-check/operator_drop.exp b/third_party/move/move-compiler-v2/tests/ability-check/operator_drop.exp index 9d3c3eb96312d..4fbd6c57e9049 100644 --- a/third_party/move/move-compiler-v2/tests/ability-check/operator_drop.exp +++ b/third_party/move/move-compiler-v2/tests/ability-check/operator_drop.exp @@ -1,24 +1,24 @@ Diagnostics: -error: local `x` of type `T` does not have the `drop` ability +error: local `y` of type `T` does not have the `drop` ability ┌─ tests/ability-check/operator_drop.move:4:9 │ 4 │ x == y │ ^^^^^^ operator drops value here (consider borrowing the argument) -error: local `y` of type `T` does not have the `drop` ability +error: value of type `T` does not have the `drop` ability ┌─ tests/ability-check/operator_drop.move:4:9 │ 4 │ x == y │ ^^^^^^ operator drops value here (consider borrowing the argument) -error: local `x` of type `T` does not have the `drop` ability +error: local `y` of type `T` does not have the `drop` ability ┌─ tests/ability-check/operator_drop.move:8:9 │ 8 │ x != y │ ^^^^^^ operator drops value here (consider borrowing the argument) -error: local `y` of type `T` does not have the `drop` ability +error: value of type `T` does not have the `drop` ability ┌─ tests/ability-check/operator_drop.move:8:9 │ 8 │ x != y diff --git a/third_party/move/move-compiler-v2/tests/ability-check/typing/eq_invalid2.exp b/third_party/move/move-compiler-v2/tests/ability-check/typing/eq_invalid2.exp index a415502fc4815..0f2e6871fd706 100644 --- a/third_party/move/move-compiler-v2/tests/ability-check/typing/eq_invalid2.exp +++ b/third_party/move/move-compiler-v2/tests/ability-check/typing/eq_invalid2.exp @@ -4,7 +4,10 @@ error: local `r` of type `R` does not have the `copy` ability ┌─ tests/ability-check/typing/eq_invalid2.move:11:9 │ 11 │ r == r; - │ ^^^^^^ copy needed here because value is still in use + │ ^----- + │ │ + │ used here + │ copy needed here because value is still in use error: local `r` of type `R` does not have the `drop` ability ┌─ tests/ability-check/typing/eq_invalid2.move:11:9 @@ -12,6 +15,12 @@ error: local `r` of type `R` does not have the `drop` ability 11 │ r == r; │ ^^^^^^ operator drops value here (consider borrowing the argument) +error: value of type `R` does not have the `drop` ability + ┌─ tests/ability-check/typing/eq_invalid2.move:11:9 + │ +11 │ r == r; + │ ^^^^^^ operator drops value here (consider borrowing the argument) + error: value of type `G1` does not have the `drop` ability ┌─ tests/ability-check/typing/eq_invalid2.move:15:9 │ diff --git a/third_party/move/move-compiler-v2/tests/ability-check/typing/neq_invalid2.exp b/third_party/move/move-compiler-v2/tests/ability-check/typing/neq_invalid2.exp index c07bea1c68b1b..8f68d6cc3dbeb 100644 --- a/third_party/move/move-compiler-v2/tests/ability-check/typing/neq_invalid2.exp +++ b/third_party/move/move-compiler-v2/tests/ability-check/typing/neq_invalid2.exp @@ -6,19 +6,19 @@ error: local `s2` of type `S` does not have the `drop` ability 17 │ s != s2; │ ^^^^^^^ operator drops value here (consider borrowing the argument) -error: local `s` of type `S` does not have the `drop` ability +error: value of type `S` does not have the `drop` ability ┌─ tests/ability-check/typing/neq_invalid2.move:17:9 │ 17 │ s != s2; │ ^^^^^^^ operator drops value here (consider borrowing the argument) -error: local `r1` of type `R` does not have the `drop` ability +error: local `r2` of type `R` does not have the `drop` ability ┌─ tests/ability-check/typing/neq_invalid2.move:22:9 │ 22 │ r1 != r2; │ ^^^^^^^^ operator drops value here (consider borrowing the argument) -error: local `r2` of type `R` does not have the `drop` ability +error: value of type `R` does not have the `drop` ability ┌─ tests/ability-check/typing/neq_invalid2.move:22:9 │ 22 │ r1 != r2; diff --git a/third_party/move/move-compiler-v2/tests/ability-transform/borrowed_from_one_path.exp b/third_party/move/move-compiler-v2/tests/ability-transform/borrowed_from_one_path.exp index 64fd1e4a61b95..10e16f2fa63ea 100644 --- a/third_party/move/move-compiler-v2/tests/ability-transform/borrowed_from_one_path.exp +++ b/third_party/move/move-compiler-v2/tests/ability-transform/borrowed_from_one_path.exp @@ -6,25 +6,29 @@ fun m::f($t0: u8, $t1: &vector): u64 { var $t3: &vector var $t4: bool var $t5: u8 - var $t6: &0x42::m::R - var $t7: address - var $t8: &u64 - var $t9: u64 - 0: $t5 := 0 - 1: $t4 := ==($t0, $t5) - 2: if ($t4) goto 3 else goto 8 - 3: label L0 - 4: $t7 := 0x1 - 5: $t6 := borrow_global<0x42::m::R>($t7) - 6: $t3 := borrow_field<0x42::m::R>.data($t6) - 7: goto 10 - 8: label L1 - 9: $t3 := infer($t1) - 10: label L2 - 11: $t9 := 0 - 12: $t8 := vector::borrow($t3, $t9) - 13: $t2 := read_ref($t8) - 14: return $t2 + var $t6: u8 + var $t7: &0x42::m::R + var $t8: address + var $t9: &u64 + var $t10: &vector + var $t11: u64 + 0: $t5 := infer($t0) + 1: $t6 := 0 + 2: $t4 := ==($t5, $t6) + 3: if ($t4) goto 4 else goto 9 + 4: label L0 + 5: $t8 := 0x1 + 6: $t7 := borrow_global<0x42::m::R>($t8) + 7: $t3 := borrow_field<0x42::m::R>.data($t7) + 8: goto 11 + 9: label L1 + 10: $t3 := infer($t1) + 11: label L2 + 12: $t10 := infer($t3) + 13: $t11 := 0 + 14: $t9 := vector::borrow($t10, $t11) + 15: $t2 := read_ref($t9) + 16: return $t2 } ============ after LiveVarAnalysisProcessor: ================ @@ -35,40 +39,46 @@ fun m::f($t0: u8, $t1: &vector): u64 { var $t3: &vector var $t4: bool var $t5: u8 - var $t6: &0x42::m::R - var $t7: address - var $t8: &u64 - var $t9: u64 + var $t6: u8 + var $t7: &0x42::m::R + var $t8: address + var $t9: &u64 + var $t10: &vector + var $t11: u64 # live vars: $t0, $t1 - 0: $t5 := 0 - # live vars: $t0, $t1, $t5 - 1: $t4 := ==($t0, $t5) + 0: $t5 := infer($t0) + # live vars: $t1, $t5 + 1: $t6 := 0 + # live vars: $t1, $t5, $t6 + 2: $t4 := ==($t5, $t6) # live vars: $t1, $t4 - 2: if ($t4) goto 3 else goto 8 + 3: if ($t4) goto 4 else goto 9 # live vars: $t1 - 3: label L0 + 4: label L0 # live vars: - 4: $t7 := 0x1 + 5: $t8 := 0x1 + # live vars: $t8 + 6: $t7 := borrow_global<0x42::m::R>($t8) # live vars: $t7 - 5: $t6 := borrow_global<0x42::m::R>($t7) - # live vars: $t6 - 6: $t3 := borrow_field<0x42::m::R>.data($t6) + 7: $t3 := borrow_field<0x42::m::R>.data($t7) # live vars: $t3 - 7: goto 10 + 8: goto 11 # live vars: $t1 - 8: label L1 + 9: label L1 # live vars: $t1 - 9: $t3 := infer($t1) + 10: $t3 := infer($t1) # live vars: $t3 - 10: label L2 + 11: label L2 # live vars: $t3 - 11: $t9 := 0 - # live vars: $t3, $t9 - 12: $t8 := vector::borrow($t3, $t9) - # live vars: $t8 - 13: $t2 := read_ref($t8) + 12: $t10 := infer($t3) + # live vars: $t10 + 13: $t11 := 0 + # live vars: $t10, $t11 + 14: $t9 := vector::borrow($t10, $t11) + # live vars: $t9 + 15: $t2 := read_ref($t9) # live vars: $t2 - 14: return $t2 + 16: return $t2 } ============ after LiveVarAnalysisProcessor: ================ @@ -79,40 +89,46 @@ fun m::f($t0: u8, $t1: &vector): u64 { var $t3: &vector var $t4: bool var $t5: u8 - var $t6: &0x42::m::R - var $t7: address - var $t8: &u64 - var $t9: u64 + var $t6: u8 + var $t7: &0x42::m::R + var $t8: address + var $t9: &u64 + var $t10: &vector + var $t11: u64 # live vars: $t0, $t1 - 0: $t5 := 0 - # live vars: $t0, $t1, $t5 - 1: $t4 := ==($t0, $t5) + 0: $t5 := infer($t0) + # live vars: $t1, $t5 + 1: $t6 := 0 + # live vars: $t1, $t5, $t6 + 2: $t4 := ==($t5, $t6) # live vars: $t1, $t4 - 2: if ($t4) goto 3 else goto 8 + 3: if ($t4) goto 4 else goto 9 # live vars: $t1 - 3: label L0 + 4: label L0 # live vars: - 4: $t7 := 0x1 + 5: $t8 := 0x1 + # live vars: $t8 + 6: $t7 := borrow_global<0x42::m::R>($t8) # live vars: $t7 - 5: $t6 := borrow_global<0x42::m::R>($t7) - # live vars: $t6 - 6: $t3 := borrow_field<0x42::m::R>.data($t6) + 7: $t3 := borrow_field<0x42::m::R>.data($t7) # live vars: $t3 - 7: goto 10 + 8: goto 11 # live vars: $t1 - 8: label L1 + 9: label L1 # live vars: $t1 - 9: $t3 := infer($t1) + 10: $t3 := infer($t1) # live vars: $t3 - 10: label L2 + 11: label L2 # live vars: $t3 - 11: $t9 := 0 - # live vars: $t3, $t9 - 12: $t8 := vector::borrow($t3, $t9) - # live vars: $t8 - 13: $t2 := read_ref($t8) + 12: $t10 := infer($t3) + # live vars: $t10 + 13: $t11 := 0 + # live vars: $t10, $t11 + 14: $t9 := vector::borrow($t10, $t11) + # live vars: $t9 + 15: $t2 := read_ref($t9) # live vars: $t2 - 14: return $t2 + 16: return $t2 } ============ after ReferenceSafetyProcessor: ================ @@ -123,10 +139,12 @@ fun m::f($t0: u8, $t1: &vector): u64 { var $t3: &vector var $t4: bool var $t5: u8 - var $t6: &0x42::m::R - var $t7: address - var $t8: &u64 - var $t9: u64 + var $t6: u8 + var $t7: &0x42::m::R + var $t8: address + var $t9: &u64 + var $t10: &vector + var $t11: u64 # live vars: $t0, $t1 # refs: [$t1 => #1] # #1 @@ -134,15 +152,23 @@ fun m::f($t0: u8, $t1: &vector): u64 { # #root # # - 0: $t5 := 0 - # live vars: $t0, $t1, $t5 + 0: $t5 := infer($t0) + # live vars: $t1, $t5 + # refs: [$t1 => #1] + # #1 + # + # #root + # + # + 1: $t6 := 0 + # live vars: $t1, $t5, $t6 # refs: [$t1 => #1] # #1 # # #root # # - 1: $t4 := ==($t0, $t5) + 2: $t4 := ==($t5, $t6) # live vars: $t1, $t4 # refs: [$t1 => #1] # #1 @@ -150,7 +176,7 @@ fun m::f($t0: u8, $t1: &vector): u64 { # #root # # - 2: if ($t4) goto 3 else goto 8 + 3: if ($t4) goto 4 else goto 9 # live vars: $t1 # refs: [$t1 => #1] # #1 @@ -158,23 +184,23 @@ fun m::f($t0: u8, $t1: &vector): u64 { # #root # # - 3: label L0 + 4: label L0 # live vars: # refs: [] # - 4: $t7 := 0x1 - # live vars: $t7 + 5: $t8 := 0x1 + # live vars: $t8 # refs: [] # - 5: $t6 := borrow_global<0x42::m::R>($t7) - # live vars: $t6 - # refs: [$t6 => #6] - # #6 + 6: $t7 := borrow_global<0x42::m::R>($t8) + # live vars: $t7 + # refs: [$t7 => #7] + # #7 # # #root - # -> #6 via [struct `m::R`] at line 12 + # -> #7 via [struct `m::R`] at line 12 # - 6: $t3 := borrow_field<0x42::m::R>.data($t6) + 7: $t3 := borrow_field<0x42::m::R>.data($t7) # live vars: $t3 # refs: [$t3 => #3] # #3 @@ -182,7 +208,7 @@ fun m::f($t0: u8, $t1: &vector): u64 { # #root # -> #3 via [struct `m::R`] at line 12 # - 7: goto 10 + 8: goto 11 # live vars: $t1 # refs: [$t1 => #1] # #1 @@ -190,7 +216,7 @@ fun m::f($t0: u8, $t1: &vector): u64 { # #root # # - 8: label L1 + 9: label L1 # live vars: $t1 # refs: [$t1 => #1] # #1 @@ -198,7 +224,7 @@ fun m::f($t0: u8, $t1: &vector): u64 { # #root # # - 9: $t3 := infer($t1) + 10: $t3 := infer($t1) # live vars: $t3 # refs: [$t3 => #3] # #3 @@ -206,7 +232,7 @@ fun m::f($t0: u8, $t1: &vector): u64 { # #root # -> #3 via [struct `m::R`] at line 12 # - 10: label L2 + 11: label L2 # live vars: $t3 # refs: [$t3 => #3] # #3 @@ -214,27 +240,35 @@ fun m::f($t0: u8, $t1: &vector): u64 { # #root # -> #3 via [struct `m::R`] at line 12 # - 11: $t9 := 0 - # live vars: $t3, $t9 - # refs: [$t3 => #3] - # #3 + 12: $t10 := infer($t3) + # live vars: $t10 + # refs: [$t10 => #10] + # #10 # # #root - # -> #3 via [struct `m::R`] at line 12 + # -> #10 via [struct `m::R`] at line 12 # - 12: $t8 := vector::borrow($t3, $t9) - # live vars: $t8 - # refs: [$t8 => #8] - # #8 + 13: $t11 := 0 + # live vars: $t10, $t11 + # refs: [$t10 => #10] + # #10 + # + # #root + # -> #10 via [struct `m::R`] at line 12 + # + 14: $t9 := vector::borrow($t10, $t11) + # live vars: $t9 + # refs: [$t9 => #9] + # #9 # # #root - # -> #8 via [struct `m::R`] at line 16 + # -> #9 via [struct `m::R`] at line 16 # - 13: $t2 := read_ref($t8) + 15: $t2 := read_ref($t9) # live vars: $t2 # refs: [] # - 14: return $t2 + 16: return $t2 } ============ after AbortAnalysisProcessor: ================ @@ -245,10 +279,12 @@ fun m::f($t0: u8, $t1: &vector): u64 { var $t3: &vector var $t4: bool var $t5: u8 - var $t6: &0x42::m::R - var $t7: address - var $t8: &u64 - var $t9: u64 + var $t6: u8 + var $t7: &0x42::m::R + var $t8: address + var $t9: &u64 + var $t10: &vector + var $t11: u64 # abort state: {returns,aborts} # live vars: $t0, $t1 # refs: [$t1 => #1] @@ -257,16 +293,25 @@ fun m::f($t0: u8, $t1: &vector): u64 { # #root # # - 0: $t5 := 0 + 0: $t5 := infer($t0) # abort state: {returns,aborts} - # live vars: $t0, $t1, $t5 + # live vars: $t1, $t5 # refs: [$t1 => #1] # #1 # # #root # # - 1: $t4 := ==($t0, $t5) + 1: $t6 := 0 + # abort state: {returns,aborts} + # live vars: $t1, $t5, $t6 + # refs: [$t1 => #1] + # #1 + # + # #root + # + # + 2: $t4 := ==($t5, $t6) # abort state: {returns,aborts} # live vars: $t1, $t4 # refs: [$t1 => #1] @@ -275,7 +320,7 @@ fun m::f($t0: u8, $t1: &vector): u64 { # #root # # - 2: if ($t4) goto 3 else goto 8 + 3: if ($t4) goto 4 else goto 9 # abort state: {returns,aborts} # live vars: $t1 # refs: [$t1 => #1] @@ -284,26 +329,26 @@ fun m::f($t0: u8, $t1: &vector): u64 { # #root # # - 3: label L0 + 4: label L0 # abort state: {returns,aborts} # live vars: # refs: [] # - 4: $t7 := 0x1 + 5: $t8 := 0x1 # abort state: {returns,aborts} - # live vars: $t7 + # live vars: $t8 # refs: [] # - 5: $t6 := borrow_global<0x42::m::R>($t7) + 6: $t7 := borrow_global<0x42::m::R>($t8) # abort state: {returns,aborts} - # live vars: $t6 - # refs: [$t6 => #6] - # #6 + # live vars: $t7 + # refs: [$t7 => #7] + # #7 # # #root - # -> #6 via [struct `m::R`] at line 12 + # -> #7 via [struct `m::R`] at line 12 # - 6: $t3 := borrow_field<0x42::m::R>.data($t6) + 7: $t3 := borrow_field<0x42::m::R>.data($t7) # abort state: {returns,aborts} # live vars: $t3 # refs: [$t3 => #3] @@ -312,7 +357,7 @@ fun m::f($t0: u8, $t1: &vector): u64 { # #root # -> #3 via [struct `m::R`] at line 12 # - 7: goto 10 + 8: goto 11 # abort state: {returns,aborts} # live vars: $t1 # refs: [$t1 => #1] @@ -321,7 +366,7 @@ fun m::f($t0: u8, $t1: &vector): u64 { # #root # # - 8: label L1 + 9: label L1 # abort state: {returns,aborts} # live vars: $t1 # refs: [$t1 => #1] @@ -330,7 +375,7 @@ fun m::f($t0: u8, $t1: &vector): u64 { # #root # # - 9: $t3 := infer($t1) + 10: $t3 := infer($t1) # abort state: {returns,aborts} # live vars: $t3 # refs: [$t3 => #3] @@ -339,7 +384,7 @@ fun m::f($t0: u8, $t1: &vector): u64 { # #root # -> #3 via [struct `m::R`] at line 12 # - 10: label L2 + 11: label L2 # abort state: {returns,aborts} # live vars: $t3 # refs: [$t3 => #3] @@ -348,30 +393,39 @@ fun m::f($t0: u8, $t1: &vector): u64 { # #root # -> #3 via [struct `m::R`] at line 12 # - 11: $t9 := 0 + 12: $t10 := infer($t3) # abort state: {returns,aborts} - # live vars: $t3, $t9 - # refs: [$t3 => #3] - # #3 + # live vars: $t10 + # refs: [$t10 => #10] + # #10 # # #root - # -> #3 via [struct `m::R`] at line 12 + # -> #10 via [struct `m::R`] at line 12 + # + 13: $t11 := 0 + # abort state: {returns,aborts} + # live vars: $t10, $t11 + # refs: [$t10 => #10] + # #10 + # + # #root + # -> #10 via [struct `m::R`] at line 12 # - 12: $t8 := vector::borrow($t3, $t9) + 14: $t9 := vector::borrow($t10, $t11) # abort state: {returns} - # live vars: $t8 - # refs: [$t8 => #8] - # #8 + # live vars: $t9 + # refs: [$t9 => #9] + # #9 # # #root - # -> #8 via [struct `m::R`] at line 16 + # -> #9 via [struct `m::R`] at line 16 # - 13: $t2 := read_ref($t8) + 15: $t2 := read_ref($t9) # abort state: {returns} # live vars: $t2 # refs: [] # - 14: return $t2 + 16: return $t2 } ============ after AbilityProcessor: ================ @@ -382,24 +436,272 @@ fun m::f($t0: u8, $t1: &vector): u64 { var $t3: &vector var $t4: bool var $t5: u8 - var $t6: &0x42::m::R - var $t7: address - var $t8: &u64 - var $t9: u64 - 0: $t5 := 0 - 1: $t4 := ==($t0, $t5) - 2: if ($t4) goto 3 else goto 9 - 3: label L0 - 4: drop($t1) - 5: $t7 := 0x1 - 6: $t6 := borrow_global<0x42::m::R>($t7) - 7: $t3 := borrow_field<0x42::m::R>.data($t6) - 8: goto 11 - 9: label L1 - 10: $t3 := move($t1) - 11: label L2 - 12: $t9 := 0 - 13: $t8 := vector::borrow($t3, $t9) - 14: $t2 := read_ref($t8) - 15: return $t2 + var $t6: u8 + var $t7: &0x42::m::R + var $t8: address + var $t9: &u64 + var $t10: &vector + var $t11: u64 + 0: $t5 := move($t0) + 1: $t6 := 0 + 2: $t4 := ==($t5, $t6) + 3: if ($t4) goto 4 else goto 10 + 4: label L0 + 5: drop($t1) + 6: $t8 := 0x1 + 7: $t7 := borrow_global<0x42::m::R>($t8) + 8: $t3 := borrow_field<0x42::m::R>.data($t7) + 9: goto 12 + 10: label L1 + 11: $t3 := move($t1) + 12: label L2 + 13: $t10 := move($t3) + 14: $t11 := 0 + 15: $t9 := vector::borrow($t10, $t11) + 16: $t2 := read_ref($t9) + 17: return $t2 +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun m::f($t0: u8, $t1: &vector): u64 { + var $t2: u64 + var $t3: &vector + var $t4: bool + var $t5: u8 + var $t6: u8 + var $t7: &0x42::m::R + var $t8: address + var $t9: &u64 + var $t10: &vector + var $t11: u64 + # live vars: $t0, $t1 + 0: $t5 := move($t0) + # live vars: $t1, $t5 + 1: $t6 := 0 + # live vars: $t1, $t5, $t6 + 2: $t4 := ==($t5, $t6) + # live vars: $t1, $t4 + 3: if ($t4) goto 4 else goto 15 + # live vars: $t1 + 4: label L0 + # live vars: $t1 + 5: drop($t1) + # live vars: + 6: $t8 := 0x1 + # live vars: $t8 + 7: $t7 := borrow_global<0x42::m::R>($t8) + # live vars: $t7 + 8: $t3 := borrow_field<0x42::m::R>.data($t7) + # live vars: $t3 + 9: label L2 + # live vars: $t3 + 10: $t10 := move($t3) + # live vars: $t10 + 11: $t11 := 0 + # live vars: $t10, $t11 + 12: $t9 := vector::borrow($t10, $t11) + # live vars: $t9 + 13: $t2 := read_ref($t9) + # live vars: $t2 + 14: return $t2 + # live vars: $t1 + 15: label L1 + # live vars: $t1 + 16: $t3 := move($t1) + # live vars: $t3 + 17: goto 9 +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun m::f($t0: u8, $t1: &vector): u64 { + var $t2: u64 + var $t3: &vector + var $t4: bool + var $t5: u8 + var $t6: u8 + var $t7: &0x42::m::R + var $t8: address + var $t9: &u64 + var $t10: &vector + var $t11: u64 + # live vars: $t0, $t1 + 0: $t5 := move($t0) + # live vars: $t1, $t5 + 1: $t6 := 0 + # live vars: $t1, $t5, $t6 + 2: $t4 := ==($t5, $t6) + # live vars: $t1, $t4 + 3: if ($t4) goto 4 else goto 15 + # live vars: $t1 + 4: label L0 + # live vars: $t1 + 5: drop($t1) + # live vars: + 6: $t8 := 0x1 + # live vars: $t8 + 7: $t7 := borrow_global<0x42::m::R>($t8) + # live vars: $t7 + 8: $t3 := borrow_field<0x42::m::R>.data($t7) + # live vars: $t3 + 9: label L2 + # live vars: $t3 + 10: $t10 := move($t3) + # live vars: $t10 + 11: $t11 := 0 + # live vars: $t10, $t11 + 12: $t9 := vector::borrow($t10, $t11) + # live vars: $t9 + 13: $t2 := read_ref($t9) + # live vars: $t2 + 14: return $t2 + # live vars: $t1 + 15: label L1 + # live vars: $t1 + 16: $t3 := move($t1) + # live vars: $t3 + 17: goto 9 +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun m::f($t0: u8, $t1: &vector): u64 { + var $t2: u64 [unused] + var $t3: &vector + var $t4: bool + var $t5: u8 [unused] + var $t6: u8 + var $t7: &0x42::m::R + var $t8: address + var $t9: &u64 + var $t10: &vector + var $t11: u64 + # live vars: $t0, $t1 + 0: $t0 := move($t0) + # live vars: $t0, $t1 + 1: $t6 := 0 + # live vars: $t0, $t1, $t6 + 2: $t4 := ==($t0, $t6) + # live vars: $t1, $t4 + 3: if ($t4) goto 4 else goto 15 + # live vars: $t1 + 4: label L0 + # live vars: $t1 + 5: drop($t1) + # live vars: + 6: $t8 := 0x1 + # live vars: $t8 + 7: $t7 := borrow_global<0x42::m::R>($t8) + # live vars: $t7 + 8: $t3 := borrow_field<0x42::m::R>.data($t7) + # live vars: $t3 + 9: label L2 + # live vars: $t3 + 10: $t10 := move($t3) + # live vars: $t10 + 11: $t11 := 0 + # live vars: $t10, $t11 + 12: $t9 := vector::borrow($t10, $t11) + # live vars: $t9 + 13: $t11 := read_ref($t9) + # live vars: $t11 + 14: return $t11 + # live vars: $t1 + 15: label L1 + # live vars: $t1 + 16: $t3 := move($t1) + # live vars: $t3 + 17: goto 9 +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun m::f($t0: u8, $t1: &vector): u64 { + var $t2: u64 [unused] + var $t3: &vector + var $t4: bool + var $t5: u8 [unused] + var $t6: u8 + var $t7: &0x42::m::R + var $t8: address + var $t9: &u64 + var $t10: &vector + var $t11: u64 + # live vars: $t0, $t1 + 0: $t0 := move($t0) + # live vars: $t0, $t1 + 1: $t6 := 0 + # live vars: $t0, $t1, $t6 + 2: $t4 := ==($t0, $t6) + # live vars: $t1, $t4 + 3: if ($t4) goto 4 else goto 15 + # live vars: $t1 + 4: label L0 + # live vars: $t1 + 5: drop($t1) + # live vars: + 6: $t8 := 0x1 + # live vars: $t8 + 7: $t7 := borrow_global<0x42::m::R>($t8) + # live vars: $t7 + 8: $t3 := borrow_field<0x42::m::R>.data($t7) + # live vars: $t3 + 9: label L2 + # live vars: $t3 + 10: $t10 := move($t3) + # live vars: $t10 + 11: $t11 := 0 + # live vars: $t10, $t11 + 12: $t9 := vector::borrow($t10, $t11) + # live vars: $t9 + 13: $t11 := read_ref($t9) + # live vars: $t11 + 14: return $t11 + # live vars: $t1 + 15: label L1 + # live vars: $t1 + 16: $t3 := move($t1) + # live vars: $t3 + 17: goto 9 +} + + +============ disassembled file-format ================== +// Move bytecode v7 +module 42.m { +struct R has key { + data: vector +} + +f(Arg0: u8, Arg1: &vector): u64 /* def_idx: 0 */ { +L2: loc0: &vector +B0: + 0: MoveLoc[0](Arg0: u8) + 1: LdU8(0) + 2: Eq + 3: BrFalse(15) +B1: + 4: MoveLoc[1](Arg1: &vector) + 5: Pop + 6: LdConst[0](Address: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]) + 7: ImmBorrowGlobal[0](R) + 8: ImmBorrowField[0](R.data: vector) + 9: StLoc[2](loc0: &vector) +B2: + 10: MoveLoc[2](loc0: &vector) + 11: LdU64(0) + 12: VecImmBorrow(1) + 13: ReadRef + 14: Ret +B3: + 15: MoveLoc[1](Arg1: &vector) + 16: StLoc[2](loc0: &vector) + 17: Branch(10) +} } +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/ability-transform/by_reference.exp b/third_party/move/move-compiler-v2/tests/ability-transform/by_reference.exp index 1840279efaab9..cc091f905d208 100644 --- a/third_party/move/move-compiler-v2/tests/ability-transform/by_reference.exp +++ b/third_party/move/move-compiler-v2/tests/ability-transform/by_reference.exp @@ -1567,3 +1567,754 @@ fun _0::check() { 80: label L23 81: return () } + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun _0::check() { + var $t0: bool + var $t1: u64 + var $t2: bool + var $t3: u64 + var $t4: bool + var $t5: u64 + var $t6: u64 + var $t7: u64 + var $t8: bool + var $t9: vector + var $t10: vector + var $t11: u64 + var $t12: &mut u64 + var $t13: u64 + var $t14: u64 + var $t15: &mut vector + var $t16: vector + var $t17: vector + var $t18: bool + var $t19: u64 + var $t20: u64 + var $t21: u64 + var $t22: bool + var $t23: vector + var $t24: vector + var $t25: u64 + var $t26: bool + var $t27: u64 + var $t28: bool + var $t29: u64 + # live vars: + 0: $t0 := true + # live vars: $t0 + 1: if ($t0) goto 2 else goto 63 + # live vars: + 2: label L0 + # live vars: + 3: $t2 := true + # live vars: $t2 + 4: if ($t2) goto 5 else goto 60 + # live vars: + 5: label L3 + # live vars: + 6: $t5 := 0 + # live vars: $t5 + 7: $t6 := 0 + # live vars: $t5, $t6 + 8: $t4 := ==($t5, $t6) + # live vars: $t4 + 9: if ($t4) goto 10 else goto 57 + # live vars: + 10: label L6 + # live vars: + 11: $t9 := [104, 101, 108, 108, 111] + # live vars: $t9 + 12: $t10 := [104, 101, 108, 108, 111] + # live vars: $t9, $t10 + 13: $t8 := ==($t9, $t10) + # live vars: $t8 + 14: if ($t8) goto 15 else goto 54 + # live vars: + 15: label L9 + # live vars: + 16: $t13 := 0 + # live vars: $t13 + 17: $t12 := borrow_local($t13) + # live vars: $t12 + 18: $t14 := 1 + # live vars: $t12, $t14 + 19: write_ref($t12, $t14) + # live vars: $t12 + 20: $t16 := [104, 101, 108, 108, 111] + # live vars: $t12, $t16 + 21: $t15 := borrow_local($t16) + # live vars: $t12, $t15 + 22: $t17 := [98, 121, 101] + # live vars: $t12, $t15, $t17 + 23: write_ref($t15, $t17) + # live vars: $t12, $t15 + 24: $t19 := read_ref($t12) + # live vars: $t15, $t19 + 25: $t20 := 1 + # live vars: $t15, $t19, $t20 + 26: $t18 := ==($t19, $t20) + # live vars: $t15, $t18 + 27: if ($t18) goto 28 else goto 50 + # live vars: $t15 + 28: label L12 + # live vars: $t15 + 29: $t23 := read_ref($t15) + # live vars: $t23 + 30: $t24 := [98, 121, 101] + # live vars: $t23, $t24 + 31: $t22 := ==($t23, $t24) + # live vars: $t22 + 32: if ($t22) goto 33 else goto 47 + # live vars: + 33: label L15 + # live vars: + 34: $t26 := true + # live vars: $t26 + 35: if ($t26) goto 36 else goto 44 + # live vars: + 36: label L18 + # live vars: + 37: $t28 := true + # live vars: $t28 + 38: if ($t28) goto 39 else goto 41 + # live vars: + 39: label L21 + # live vars: + 40: return () + # live vars: + 41: label L22 + # live vars: + 42: $t29 := 42 + # live vars: $t29 + 43: abort($t29) + # live vars: + 44: label L19 + # live vars: + 45: $t27 := 42 + # live vars: $t27 + 46: abort($t27) + # live vars: + 47: label L16 + # live vars: + 48: $t25 := 42 + # live vars: $t25 + 49: abort($t25) + # live vars: $t15 + 50: label L13 + # live vars: $t15 + 51: drop($t15) + # live vars: + 52: $t21 := 42 + # live vars: $t21 + 53: abort($t21) + # live vars: + 54: label L10 + # live vars: + 55: $t11 := 42 + # live vars: $t11 + 56: abort($t11) + # live vars: + 57: label L7 + # live vars: + 58: $t7 := 42 + # live vars: $t7 + 59: abort($t7) + # live vars: + 60: label L4 + # live vars: + 61: $t3 := 42 + # live vars: $t3 + 62: abort($t3) + # live vars: + 63: label L1 + # live vars: + 64: $t1 := 42 + # live vars: $t1 + 65: abort($t1) +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun _0::check() { + var $t0: bool + var $t1: u64 + var $t2: bool + var $t3: u64 + var $t4: bool + var $t5: u64 + var $t6: u64 + var $t7: u64 + var $t8: bool + var $t9: vector + var $t10: vector + var $t11: u64 + var $t12: &mut u64 + var $t13: u64 + var $t14: u64 + var $t15: &mut vector + var $t16: vector + var $t17: vector + var $t18: bool + var $t19: u64 + var $t20: u64 + var $t21: u64 + var $t22: bool + var $t23: vector + var $t24: vector + var $t25: u64 + var $t26: bool + var $t27: u64 + var $t28: bool + var $t29: u64 + # live vars: + 0: $t0 := true + # live vars: $t0 + 1: if ($t0) goto 2 else goto 63 + # live vars: + 2: label L0 + # live vars: + 3: $t2 := true + # live vars: $t2 + 4: if ($t2) goto 5 else goto 60 + # live vars: + 5: label L3 + # live vars: + 6: $t5 := 0 + # live vars: $t5 + 7: $t6 := 0 + # live vars: $t5, $t6 + 8: $t4 := ==($t5, $t6) + # live vars: $t4 + 9: if ($t4) goto 10 else goto 57 + # live vars: + 10: label L6 + # live vars: + 11: $t9 := [104, 101, 108, 108, 111] + # live vars: $t9 + 12: $t10 := [104, 101, 108, 108, 111] + # live vars: $t9, $t10 + 13: $t8 := ==($t9, $t10) + # live vars: $t8 + 14: if ($t8) goto 15 else goto 54 + # live vars: + 15: label L9 + # live vars: + 16: $t13 := 0 + # live vars: $t13 + 17: $t12 := borrow_local($t13) + # live vars: $t12 + 18: $t14 := 1 + # live vars: $t12, $t14 + 19: write_ref($t12, $t14) + # live vars: $t12 + 20: $t16 := [104, 101, 108, 108, 111] + # live vars: $t12, $t16 + 21: $t15 := borrow_local($t16) + # live vars: $t12, $t15 + 22: $t17 := [98, 121, 101] + # live vars: $t12, $t15, $t17 + 23: write_ref($t15, $t17) + # live vars: $t12, $t15 + 24: $t19 := read_ref($t12) + # live vars: $t15, $t19 + 25: $t20 := 1 + # live vars: $t15, $t19, $t20 + 26: $t18 := ==($t19, $t20) + # live vars: $t15, $t18 + 27: if ($t18) goto 28 else goto 50 + # live vars: $t15 + 28: label L12 + # live vars: $t15 + 29: $t23 := read_ref($t15) + # live vars: $t23 + 30: $t24 := [98, 121, 101] + # live vars: $t23, $t24 + 31: $t22 := ==($t23, $t24) + # live vars: $t22 + 32: if ($t22) goto 33 else goto 47 + # live vars: + 33: label L15 + # live vars: + 34: $t26 := true + # live vars: $t26 + 35: if ($t26) goto 36 else goto 44 + # live vars: + 36: label L18 + # live vars: + 37: $t28 := true + # live vars: $t28 + 38: if ($t28) goto 39 else goto 41 + # live vars: + 39: label L21 + # live vars: + 40: return () + # live vars: + 41: label L22 + # live vars: + 42: $t29 := 42 + # live vars: $t29 + 43: abort($t29) + # live vars: + 44: label L19 + # live vars: + 45: $t27 := 42 + # live vars: $t27 + 46: abort($t27) + # live vars: + 47: label L16 + # live vars: + 48: $t25 := 42 + # live vars: $t25 + 49: abort($t25) + # live vars: $t15 + 50: label L13 + # live vars: $t15 + 51: drop($t15) + # live vars: + 52: $t21 := 42 + # live vars: $t21 + 53: abort($t21) + # live vars: + 54: label L10 + # live vars: + 55: $t11 := 42 + # live vars: $t11 + 56: abort($t11) + # live vars: + 57: label L7 + # live vars: + 58: $t7 := 42 + # live vars: $t7 + 59: abort($t7) + # live vars: + 60: label L4 + # live vars: + 61: $t3 := 42 + # live vars: $t3 + 62: abort($t3) + # live vars: + 63: label L1 + # live vars: + 64: $t1 := 42 + # live vars: $t1 + 65: abort($t1) +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun _0::check() { + var $t0: bool + var $t1: u64 [unused] + var $t2: bool [unused] + var $t3: u64 [unused] + var $t4: bool [unused] + var $t5: u64 + var $t6: u64 + var $t7: u64 [unused] + var $t8: bool [unused] + var $t9: vector + var $t10: vector + var $t11: u64 [unused] + var $t12: &mut u64 + var $t13: u64 + var $t14: u64 [unused] + var $t15: &mut vector + var $t16: vector + var $t17: vector [unused] + var $t18: bool [unused] + var $t19: u64 [unused] + var $t20: u64 [unused] + var $t21: u64 [unused] + var $t22: bool [unused] + var $t23: vector [unused] + var $t24: vector [unused] + var $t25: u64 [unused] + var $t26: bool [unused] + var $t27: u64 [unused] + var $t28: bool [unused] + var $t29: u64 [unused] + # live vars: + 0: $t0 := true + # live vars: $t0 + 1: if ($t0) goto 2 else goto 63 + # live vars: + 2: label L0 + # live vars: + 3: $t0 := true + # live vars: $t0 + 4: if ($t0) goto 5 else goto 60 + # live vars: + 5: label L3 + # live vars: + 6: $t5 := 0 + # live vars: $t5 + 7: $t6 := 0 + # live vars: $t5, $t6 + 8: $t0 := ==($t5, $t6) + # live vars: $t0 + 9: if ($t0) goto 10 else goto 57 + # live vars: + 10: label L6 + # live vars: + 11: $t9 := [104, 101, 108, 108, 111] + # live vars: $t9 + 12: $t10 := [104, 101, 108, 108, 111] + # live vars: $t9, $t10 + 13: $t0 := ==($t9, $t10) + # live vars: $t0 + 14: if ($t0) goto 15 else goto 54 + # live vars: + 15: label L9 + # live vars: + 16: $t13 := 0 + # live vars: $t13 + 17: $t12 := borrow_local($t13) + # live vars: $t12 + 18: $t5 := 1 + # live vars: $t5, $t12 + 19: write_ref($t12, $t5) + # live vars: $t12 + 20: $t16 := [104, 101, 108, 108, 111] + # live vars: $t12, $t16 + 21: $t15 := borrow_local($t16) + # live vars: $t12, $t15 + 22: $t9 := [98, 121, 101] + # live vars: $t9, $t12, $t15 + 23: write_ref($t15, $t9) + # live vars: $t12, $t15 + 24: $t5 := read_ref($t12) + # live vars: $t5, $t15 + 25: $t6 := 1 + # live vars: $t5, $t6, $t15 + 26: $t0 := ==($t5, $t6) + # live vars: $t0, $t15 + 27: if ($t0) goto 28 else goto 50 + # live vars: $t15 + 28: label L12 + # live vars: $t15 + 29: $t9 := read_ref($t15) + # live vars: $t9 + 30: $t10 := [98, 121, 101] + # live vars: $t9, $t10 + 31: $t0 := ==($t9, $t10) + # live vars: $t0 + 32: if ($t0) goto 33 else goto 47 + # live vars: + 33: label L15 + # live vars: + 34: $t0 := true + # live vars: $t0 + 35: if ($t0) goto 36 else goto 44 + # live vars: + 36: label L18 + # live vars: + 37: $t0 := true + # live vars: $t0 + 38: if ($t0) goto 39 else goto 41 + # live vars: + 39: label L21 + # live vars: + 40: return () + # live vars: + 41: label L22 + # live vars: + 42: $t5 := 42 + # live vars: $t5 + 43: abort($t5) + # live vars: + 44: label L19 + # live vars: + 45: $t5 := 42 + # live vars: $t5 + 46: abort($t5) + # live vars: + 47: label L16 + # live vars: + 48: $t5 := 42 + # live vars: $t5 + 49: abort($t5) + # live vars: $t15 + 50: label L13 + # live vars: $t15 + 51: drop($t15) + # live vars: + 52: $t5 := 42 + # live vars: $t5 + 53: abort($t5) + # live vars: + 54: label L10 + # live vars: + 55: $t5 := 42 + # live vars: $t5 + 56: abort($t5) + # live vars: + 57: label L7 + # live vars: + 58: $t5 := 42 + # live vars: $t5 + 59: abort($t5) + # live vars: + 60: label L4 + # live vars: + 61: $t5 := 42 + # live vars: $t5 + 62: abort($t5) + # live vars: + 63: label L1 + # live vars: + 64: $t5 := 42 + # live vars: $t5 + 65: abort($t5) +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun _0::check() { + var $t0: bool + var $t1: u64 [unused] + var $t2: bool [unused] + var $t3: u64 [unused] + var $t4: bool [unused] + var $t5: u64 + var $t6: u64 + var $t7: u64 [unused] + var $t8: bool [unused] + var $t9: vector + var $t10: vector + var $t11: u64 [unused] + var $t12: &mut u64 + var $t13: u64 + var $t14: u64 [unused] + var $t15: &mut vector + var $t16: vector + var $t17: vector [unused] + var $t18: bool [unused] + var $t19: u64 [unused] + var $t20: u64 [unused] + var $t21: u64 [unused] + var $t22: bool [unused] + var $t23: vector [unused] + var $t24: vector [unused] + var $t25: u64 [unused] + var $t26: bool [unused] + var $t27: u64 [unused] + var $t28: bool [unused] + var $t29: u64 [unused] + # live vars: + 0: $t0 := true + # live vars: $t0 + 1: if ($t0) goto 2 else goto 63 + # live vars: + 2: label L0 + # live vars: + 3: $t0 := true + # live vars: $t0 + 4: if ($t0) goto 5 else goto 60 + # live vars: + 5: label L3 + # live vars: + 6: $t5 := 0 + # live vars: $t5 + 7: $t6 := 0 + # live vars: $t5, $t6 + 8: $t0 := ==($t5, $t6) + # live vars: $t0 + 9: if ($t0) goto 10 else goto 57 + # live vars: + 10: label L6 + # live vars: + 11: $t9 := [104, 101, 108, 108, 111] + # live vars: $t9 + 12: $t10 := [104, 101, 108, 108, 111] + # live vars: $t9, $t10 + 13: $t0 := ==($t9, $t10) + # live vars: $t0 + 14: if ($t0) goto 15 else goto 54 + # live vars: + 15: label L9 + # live vars: + 16: $t13 := 0 + # live vars: $t13 + 17: $t12 := borrow_local($t13) + # live vars: $t12 + 18: $t5 := 1 + # live vars: $t5, $t12 + 19: write_ref($t12, $t5) + # live vars: $t12 + 20: $t16 := [104, 101, 108, 108, 111] + # live vars: $t12, $t16 + 21: $t15 := borrow_local($t16) + # live vars: $t12, $t15 + 22: $t9 := [98, 121, 101] + # live vars: $t9, $t12, $t15 + 23: write_ref($t15, $t9) + # live vars: $t12, $t15 + 24: $t5 := read_ref($t12) + # live vars: $t5, $t15 + 25: $t6 := 1 + # live vars: $t5, $t6, $t15 + 26: $t0 := ==($t5, $t6) + # live vars: $t0, $t15 + 27: if ($t0) goto 28 else goto 50 + # live vars: $t15 + 28: label L12 + # live vars: $t15 + 29: $t9 := read_ref($t15) + # live vars: $t9 + 30: $t10 := [98, 121, 101] + # live vars: $t9, $t10 + 31: $t0 := ==($t9, $t10) + # live vars: $t0 + 32: if ($t0) goto 33 else goto 47 + # live vars: + 33: label L15 + # live vars: + 34: $t0 := true + # live vars: $t0 + 35: if ($t0) goto 36 else goto 44 + # live vars: + 36: label L18 + # live vars: + 37: $t0 := true + # live vars: $t0 + 38: if ($t0) goto 39 else goto 41 + # live vars: + 39: label L21 + # live vars: + 40: return () + # live vars: + 41: label L22 + # live vars: + 42: $t5 := 42 + # live vars: $t5 + 43: abort($t5) + # live vars: + 44: label L19 + # live vars: + 45: $t5 := 42 + # live vars: $t5 + 46: abort($t5) + # live vars: + 47: label L16 + # live vars: + 48: $t5 := 42 + # live vars: $t5 + 49: abort($t5) + # live vars: $t15 + 50: label L13 + # live vars: $t15 + 51: drop($t15) + # live vars: + 52: $t5 := 42 + # live vars: $t5 + 53: abort($t5) + # live vars: + 54: label L10 + # live vars: + 55: $t5 := 42 + # live vars: $t5 + 56: abort($t5) + # live vars: + 57: label L7 + # live vars: + 58: $t5 := 42 + # live vars: $t5 + 59: abort($t5) + # live vars: + 60: label L4 + # live vars: + 61: $t5 := 42 + # live vars: $t5 + 62: abort($t5) + # live vars: + 63: label L1 + # live vars: + 64: $t5 := 42 + # live vars: $t5 + 65: abort($t5) +} + + +============ disassembled file-format ================== +// Move bytecode v7 +script { + + +main() /* def_idx: 0 */ { +L0: loc0: u64 +L1: loc1: &mut u64 +L2: loc2: vector +L3: loc3: &mut vector +B0: + 0: LdU64(0) + 1: LdU64(0) + 2: Eq + 3: BrFalse(45) +B1: + 4: LdConst[0](Vector(U8): [5, 104, 101, 108, 108, 111]) + 5: LdConst[0](Vector(U8): [5, 104, 101, 108, 108, 111]) + 6: Eq + 7: BrFalse(43) +B2: + 8: LdU64(0) + 9: StLoc[0](loc0: u64) + 10: MutBorrowLoc[0](loc0: u64) + 11: StLoc[1](loc1: &mut u64) + 12: LdU64(1) + 13: CopyLoc[1](loc1: &mut u64) + 14: WriteRef + 15: LdConst[0](Vector(U8): [5, 104, 101, 108, 108, 111]) + 16: StLoc[2](loc2: vector) + 17: MutBorrowLoc[2](loc2: vector) + 18: StLoc[3](loc3: &mut vector) + 19: LdConst[1](Vector(U8): [3, 98, 121, 101]) + 20: CopyLoc[3](loc3: &mut vector) + 21: WriteRef + 22: MoveLoc[1](loc1: &mut u64) + 23: ReadRef + 24: LdU64(1) + 25: Eq + 26: BrFalse(39) +B3: + 27: MoveLoc[3](loc3: &mut vector) + 28: ReadRef + 29: LdConst[1](Vector(U8): [3, 98, 121, 101]) + 30: Eq + 31: BrFalse(37) +B4: + 32: Ret +B5: + 33: LdU64(42) + 34: Abort +B6: + 35: LdU64(42) + 36: Abort +B7: + 37: LdU64(42) + 38: Abort +B8: + 39: MoveLoc[3](loc3: &mut vector) + 40: Pop + 41: LdU64(42) + 42: Abort +B9: + 43: LdU64(42) + 44: Abort +B10: + 45: LdU64(42) + 46: Abort +B11: + 47: LdU64(42) + 48: Abort +B12: + 49: LdU64(42) + 50: Abort +} +} +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/ability-transform/copy_ability_tuple.exp b/third_party/move/move-compiler-v2/tests/ability-transform/copy_ability_tuple.exp index 3af453f1202a4..6631e64df9b64 100644 --- a/third_party/move/move-compiler-v2/tests/ability-transform/copy_ability_tuple.exp +++ b/third_party/move/move-compiler-v2/tests/ability-transform/copy_ability_tuple.exp @@ -15,12 +15,14 @@ public fun M::g($t0: &signer) { var $t1: 0x42::M::R var $t2: u64 var $t3: u64 + var $t4: &signer 0: $t2 := 1 1: $t1 := pack 0x42::M::R($t2) 2: $t3 := 3 3: ($t1, $t3) := M::f($t1) - 4: move_to<0x42::M::R>($t0, $t1) - 5: return () + 4: $t4 := infer($t0) + 5: move_to<0x42::M::R>($t4, $t1) + 6: return () } ============ after LiveVarAnalysisProcessor: ================ @@ -43,6 +45,7 @@ public fun M::g($t0: &signer) { var $t1: 0x42::M::R var $t2: u64 var $t3: u64 + var $t4: &signer # live vars: $t0 0: $t2 := 1 # live vars: $t0, $t2 @@ -52,9 +55,11 @@ public fun M::g($t0: &signer) { # live vars: $t0, $t1 3: ($t1, $t3) := M::f($t1) # live vars: $t0, $t1 - 4: move_to<0x42::M::R>($t0, $t1) + 4: $t4 := infer($t0) + # live vars: $t1, $t4 + 5: move_to<0x42::M::R>($t4, $t1) # live vars: - 5: return () + 6: return () } ============ after LiveVarAnalysisProcessor: ================ @@ -77,6 +82,7 @@ public fun M::g($t0: &signer) { var $t1: 0x42::M::R var $t2: u64 var $t3: u64 + var $t4: &signer # live vars: $t0 0: $t2 := 1 # live vars: $t0, $t2 @@ -86,9 +92,11 @@ public fun M::g($t0: &signer) { # live vars: $t0, $t1 3: ($t1, $t3) := M::f($t1) # live vars: $t0, $t1 - 4: move_to<0x42::M::R>($t0, $t1) + 4: $t4 := infer($t0) + # live vars: $t1, $t4 + 5: move_to<0x42::M::R>($t4, $t1) # live vars: - 5: return () + 6: return () } ============ after ReferenceSafetyProcessor: ================ @@ -117,6 +125,7 @@ public fun M::g($t0: &signer) { var $t1: 0x42::M::R var $t2: u64 var $t3: u64 + var $t4: &signer # live vars: $t0 # refs: [$t0 => #0] # #0 @@ -156,11 +165,19 @@ public fun M::g($t0: &signer) { # #root # # - 4: move_to<0x42::M::R>($t0, $t1) + 4: $t4 := infer($t0) + # live vars: $t1, $t4 + # refs: [$t4 => #4] + # #4 + # + # #root + # + # + 5: move_to<0x42::M::R>($t4, $t1) # live vars: # refs: [] # - 5: return () + 6: return () } ============ after AbortAnalysisProcessor: ================ @@ -192,6 +209,7 @@ public fun M::g($t0: &signer) { var $t1: 0x42::M::R var $t2: u64 var $t3: u64 + var $t4: &signer # abort state: {returns,aborts} # live vars: $t0 # refs: [$t0 => #0] @@ -236,12 +254,21 @@ public fun M::g($t0: &signer) { # #root # # - 4: move_to<0x42::M::R>($t0, $t1) + 4: $t4 := infer($t0) + # abort state: {returns,aborts} + # live vars: $t1, $t4 + # refs: [$t4 => #4] + # #4 + # + # #root + # + # + 5: move_to<0x42::M::R>($t4, $t1) # abort state: {returns} # live vars: # refs: [] # - 5: return () + 6: return () } ============ after AbilityProcessor: ================ @@ -261,10 +288,184 @@ public fun M::g($t0: &signer) { var $t1: 0x42::M::R var $t2: u64 var $t3: u64 + var $t4: &signer 0: $t2 := 1 1: $t1 := pack 0x42::M::R($t2) 2: $t3 := 3 3: ($t1, $t3) := M::f($t1) + 4: $t4 := move($t0) + 5: move_to<0x42::M::R>($t4, $t1) + 6: return () +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +public fun M::f($t0: 0x42::M::R): (0x42::M::R, u64) { + var $t1: 0x42::M::R + var $t2: u64 + # live vars: $t0 + 0: $t1 := move($t0) + # live vars: $t1 + 1: $t2 := 0 + # live vars: $t1, $t2 + 2: return ($t1, $t2) +} + + +[variant baseline] +public fun M::g($t0: &signer) { + var $t1: 0x42::M::R + var $t2: u64 + var $t3: u64 + var $t4: &signer + # live vars: $t0 + 0: $t2 := 1 + # live vars: $t0, $t2 + 1: $t1 := pack 0x42::M::R($t2) + # live vars: $t0, $t1 + 2: $t3 := 3 + # live vars: $t0, $t1 + 3: ($t1, $t3) := M::f($t1) + # live vars: $t0, $t1 + 4: $t4 := move($t0) + # live vars: $t1, $t4 + 5: move_to<0x42::M::R>($t4, $t1) + # live vars: + 6: return () +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +public fun M::f($t0: 0x42::M::R): (0x42::M::R, u64) { + var $t1: 0x42::M::R + var $t2: u64 + # live vars: $t0 + 0: $t1 := move($t0) + # live vars: $t1 + 1: $t2 := 0 + # live vars: $t1, $t2 + 2: return ($t1, $t2) +} + + +[variant baseline] +public fun M::g($t0: &signer) { + var $t1: 0x42::M::R + var $t2: u64 + var $t3: u64 + var $t4: &signer + # live vars: $t0 + 0: $t2 := 1 + # live vars: $t0, $t2 + 1: $t1 := pack 0x42::M::R($t2) + # live vars: $t0, $t1 + 2: ($t1, $t3) := M::f($t1) + # live vars: $t0, $t1 + 3: $t4 := move($t0) + # live vars: $t1, $t4 + 4: move_to<0x42::M::R>($t4, $t1) + # live vars: + 5: return () +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +public fun M::f($t0: 0x42::M::R): (0x42::M::R, u64) { + var $t1: 0x42::M::R [unused] + var $t2: u64 + # live vars: $t0 + 0: $t0 := move($t0) + # live vars: $t0 + 1: $t2 := 0 + # live vars: $t0, $t2 + 2: return ($t0, $t2) +} + + +[variant baseline] +public fun M::g($t0: &signer) { + var $t1: 0x42::M::R + var $t2: u64 + var $t3: u64 [unused] + var $t4: &signer [unused] + # live vars: $t0 + 0: $t2 := 1 + # live vars: $t0, $t2 + 1: $t1 := pack 0x42::M::R($t2) + # live vars: $t0, $t1 + 2: ($t1, $t2) := M::f($t1) + # live vars: $t0, $t1 + 3: $t0 := move($t0) + # live vars: $t0, $t1 4: move_to<0x42::M::R>($t0, $t1) + # live vars: 5: return () } + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +public fun M::f($t0: 0x42::M::R): (0x42::M::R, u64) { + var $t1: 0x42::M::R [unused] + var $t2: u64 + # live vars: $t0 + 0: $t0 := move($t0) + # live vars: $t0 + 1: $t2 := 0 + # live vars: $t0, $t2 + 2: return ($t0, $t2) +} + + +[variant baseline] +public fun M::g($t0: &signer) { + var $t1: 0x42::M::R + var $t2: u64 + var $t3: u64 [unused] + var $t4: &signer [unused] + # live vars: $t0 + 0: $t2 := 1 + # live vars: $t0, $t2 + 1: $t1 := pack 0x42::M::R($t2) + # live vars: $t0, $t1 + 2: ($t1, $t2) := M::f($t1) + # live vars: $t0, $t1 + 3: $t0 := move($t0) + # live vars: $t0, $t1 + 4: move_to<0x42::M::R>($t0, $t1) + # live vars: + 5: return () +} + + +============ disassembled file-format ================== +// Move bytecode v7 +module 42.M { +struct R has key { + f: u64 +} + +public f(Arg0: R): R * u64 /* def_idx: 0 */ { +B0: + 0: MoveLoc[0](Arg0: R) + 1: LdU64(0) + 2: Ret +} +public g(Arg0: &signer) /* def_idx: 1 */ { +L1: loc0: R +B0: + 0: LdU64(1) + 1: Pack[0](R) + 2: Call f(R): R * u64 + 3: Pop + 4: StLoc[1](loc0: R) + 5: MoveLoc[0](Arg0: &signer) + 6: MoveLoc[1](loc0: R) + 7: MoveTo[0](R) + 8: Ret +} +} +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/ability-transform/dead_but_borrowed.exp b/third_party/move/move-compiler-v2/tests/ability-transform/dead_but_borrowed.exp index 7a124dba2860a..45d341c56e269 100644 --- a/third_party/move/move-compiler-v2/tests/ability-transform/dead_but_borrowed.exp +++ b/third_party/move/move-compiler-v2/tests/ability-transform/dead_but_borrowed.exp @@ -119,3 +119,89 @@ fun explicate_drop::test0(): u8 { 2: $t0 := read_ref($t1) 3: return $t0 } + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun explicate_drop::test0(): u8 { + var $t0: u8 + var $t1: &u8 + var $t2: u8 + # live vars: + 0: $t2 := 42 + # live vars: $t2 + 1: $t1 := borrow_local($t2) + # live vars: $t1 + 2: $t0 := read_ref($t1) + # live vars: $t0 + 3: return $t0 +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun explicate_drop::test0(): u8 { + var $t0: u8 + var $t1: &u8 + var $t2: u8 + # live vars: + 0: $t2 := 42 + # live vars: $t2 + 1: $t1 := borrow_local($t2) + # live vars: $t1 + 2: $t0 := read_ref($t1) + # live vars: $t0 + 3: return $t0 +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun explicate_drop::test0(): u8 { + var $t0: u8 + var $t1: &u8 + var $t2: u8 + # live vars: + 0: $t2 := 42 + # live vars: $t2 + 1: $t1 := borrow_local($t2) + # live vars: $t1 + 2: $t0 := read_ref($t1) + # live vars: $t0 + 3: return $t0 +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun explicate_drop::test0(): u8 { + var $t0: u8 + var $t1: &u8 + var $t2: u8 + # live vars: + 0: $t2 := 42 + # live vars: $t2 + 1: $t1 := borrow_local($t2) + # live vars: $t1 + 2: $t0 := read_ref($t1) + # live vars: $t0 + 3: return $t0 +} + + +============ disassembled file-format ================== +// Move bytecode v7 +module 42.explicate_drop { + + +test0(): u8 /* def_idx: 0 */ { +L0: loc0: u8 +B0: + 0: LdU8(42) + 1: StLoc[0](loc0: u8) + 2: ImmBorrowLoc[0](loc0: u8) + 3: ReadRef + 4: Ret +} +} +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/ability-transform/destroy_after_call.exp b/third_party/move/move-compiler-v2/tests/ability-transform/destroy_after_call.exp index fcd3f543c20eb..ed7fd966f9853 100644 --- a/third_party/move/move-compiler-v2/tests/ability-transform/destroy_after_call.exp +++ b/third_party/move/move-compiler-v2/tests/ability-transform/destroy_after_call.exp @@ -255,3 +255,175 @@ fun m::g() { 6: drop($t3) 7: return () } + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun m::f($t0: &mut u64): &mut u64 { + var $t1: &mut u64 + # live vars: $t0 + 0: $t1 := move($t0) + # live vars: $t1 + 1: return $t1 +} + + +[variant baseline] +fun m::g() { + var $t0: u64 + var $t1: &mut u64 + var $t2: &mut u64 + var $t3: &u64 + # live vars: + 0: $t0 := 22 + # live vars: $t0 + 1: $t1 := borrow_local($t0) + # live vars: $t0, $t1 + 2: $t2 := m::f($t1) + # live vars: $t0, $t2 + 3: $t1 := move($t2) + # live vars: $t0, $t1 + 4: drop($t1) + # live vars: $t0 + 5: $t3 := borrow_local($t0) + # live vars: $t3 + 6: drop($t3) + # live vars: + 7: return () +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun m::f($t0: &mut u64): &mut u64 { + var $t1: &mut u64 + # live vars: $t0 + 0: $t1 := move($t0) + # live vars: $t1 + 1: return $t1 +} + + +[variant baseline] +fun m::g() { + var $t0: u64 + var $t1: &mut u64 + var $t2: &mut u64 + var $t3: &u64 + # live vars: + 0: $t0 := 22 + # live vars: $t0 + 1: $t1 := borrow_local($t0) + # live vars: $t0, $t1 + 2: $t2 := m::f($t1) + # live vars: $t0, $t2 + 3: $t1 := move($t2) + # live vars: $t0, $t1 + 4: drop($t1) + # live vars: $t0 + 5: $t3 := borrow_local($t0) + # live vars: $t3 + 6: drop($t3) + # live vars: + 7: return () +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun m::f($t0: &mut u64): &mut u64 { + var $t1: &mut u64 [unused] + # live vars: $t0 + 0: $t0 := move($t0) + # live vars: $t0 + 1: return $t0 +} + + +[variant baseline] +fun m::g() { + var $t0: u64 + var $t1: &mut u64 + var $t2: &mut u64 + var $t3: &u64 + # live vars: + 0: $t0 := 22 + # live vars: $t0 + 1: $t1 := borrow_local($t0) + # live vars: $t0, $t1 + 2: $t2 := m::f($t1) + # live vars: $t0, $t2 + 3: $t1 := move($t2) + # live vars: $t0, $t1 + 4: drop($t1) + # live vars: $t0 + 5: $t3 := borrow_local($t0) + # live vars: $t3 + 6: drop($t3) + # live vars: + 7: return () +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun m::f($t0: &mut u64): &mut u64 { + var $t1: &mut u64 [unused] + # live vars: $t0 + 0: $t0 := move($t0) + # live vars: $t0 + 1: return $t0 +} + + +[variant baseline] +fun m::g() { + var $t0: u64 + var $t1: &mut u64 + var $t2: &mut u64 + var $t3: &u64 + # live vars: + 0: $t0 := 22 + # live vars: $t0 + 1: $t1 := borrow_local($t0) + # live vars: $t0, $t1 + 2: $t2 := m::f($t1) + # live vars: $t0, $t2 + 3: $t1 := move($t2) + # live vars: $t0, $t1 + 4: drop($t1) + # live vars: $t0 + 5: $t3 := borrow_local($t0) + # live vars: $t3 + 6: drop($t3) + # live vars: + 7: return () +} + + +============ disassembled file-format ================== +// Move bytecode v7 +module 42.m { + + +f(Arg0: &mut u64): &mut u64 /* def_idx: 0 */ { +B0: + 0: MoveLoc[0](Arg0: &mut u64) + 1: Ret +} +g() /* def_idx: 1 */ { +L0: loc0: u64 +L1: loc1: &mut u64 +L2: loc2: &u64 +B0: + 0: LdU64(22) + 1: StLoc[0](loc0: u64) + 2: MutBorrowLoc[0](loc0: u64) + 3: Call f(&mut u64): &mut u64 + 4: Pop + 5: ImmBorrowLoc[0](loc0: u64) + 6: Pop + 7: Ret +} +} +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/ability-transform/drop_after_loop.exp b/third_party/move/move-compiler-v2/tests/ability-transform/drop_after_loop.exp index a136f62c2134d..cba211794ffba 100644 --- a/third_party/move/move-compiler-v2/tests/ability-transform/drop_after_loop.exp +++ b/third_party/move/move-compiler-v2/tests/ability-transform/drop_after_loop.exp @@ -10,6 +10,7 @@ fun m::drop_after_loop() { var $t5: bool var $t6: u64 var $t7: u64 + var $t8: u64 0: $t0 := 1 1: $t1 := borrow_local($t0) 2: $t2 := true @@ -26,16 +27,17 @@ fun m::drop_after_loop() { 13: label L4 14: goto 3 15: label L1 - 16: $t6 := 2 - 17: $t5 := ==($t0, $t6) - 18: if ($t5) goto 19 else goto 21 - 19: label L5 - 20: goto 24 - 21: label L6 - 22: $t7 := 0 - 23: abort($t7) - 24: label L7 - 25: return () + 16: $t6 := infer($t0) + 17: $t7 := 2 + 18: $t5 := ==($t6, $t7) + 19: if ($t5) goto 20 else goto 22 + 20: label L5 + 21: goto 25 + 22: label L6 + 23: $t8 := 0 + 24: abort($t8) + 25: label L7 + 26: return () } ============ after LiveVarAnalysisProcessor: ================ @@ -50,6 +52,7 @@ fun m::drop_after_loop() { var $t5: bool var $t6: u64 var $t7: u64 + var $t8: u64 # live vars: 0: $t0 := 1 # live vars: $t0 @@ -83,25 +86,27 @@ fun m::drop_after_loop() { # live vars: $t0 15: label L1 # live vars: $t0 - 16: $t6 := 2 - # live vars: $t0, $t6 - 17: $t5 := ==($t0, $t6) + 16: $t6 := infer($t0) + # live vars: $t6 + 17: $t7 := 2 + # live vars: $t6, $t7 + 18: $t5 := ==($t6, $t7) # live vars: $t5 - 18: if ($t5) goto 19 else goto 21 + 19: if ($t5) goto 20 else goto 22 # live vars: - 19: label L5 + 20: label L5 # live vars: - 20: goto 24 + 21: goto 25 # live vars: - 21: label L6 + 22: label L6 # live vars: - 22: $t7 := 0 - # live vars: $t7 - 23: abort($t7) + 23: $t8 := 0 + # live vars: $t8 + 24: abort($t8) # live vars: - 24: label L7 + 25: label L7 # live vars: - 25: return () + 26: return () } ============ after LiveVarAnalysisProcessor: ================ @@ -116,6 +121,7 @@ fun m::drop_after_loop() { var $t5: bool var $t6: u64 var $t7: u64 + var $t8: u64 # live vars: 0: $t0 := 1 # live vars: $t0 @@ -149,25 +155,27 @@ fun m::drop_after_loop() { # live vars: $t0 15: label L1 # live vars: $t0 - 16: $t6 := 2 - # live vars: $t0, $t6 - 17: $t5 := ==($t0, $t6) + 16: $t6 := infer($t0) + # live vars: $t6 + 17: $t7 := 2 + # live vars: $t6, $t7 + 18: $t5 := ==($t6, $t7) # live vars: $t5 - 18: if ($t5) goto 19 else goto 21 + 19: if ($t5) goto 20 else goto 22 # live vars: - 19: label L5 + 20: label L5 # live vars: - 20: goto 24 + 21: goto 25 # live vars: - 21: label L6 + 22: label L6 # live vars: - 22: $t7 := 0 - # live vars: $t7 - 23: abort($t7) + 23: $t8 := 0 + # live vars: $t8 + 24: abort($t8) # live vars: - 24: label L7 + 25: label L7 # live vars: - 25: return () + 26: return () } ============ after ReferenceSafetyProcessor: ================ @@ -182,6 +190,7 @@ fun m::drop_after_loop() { var $t5: bool var $t6: u64 var $t7: u64 + var $t8: u64 # live vars: # refs: [] # @@ -297,43 +306,47 @@ fun m::drop_after_loop() { # live vars: $t0 # refs: [] # - 16: $t6 := 2 - # live vars: $t0, $t6 + 16: $t6 := infer($t0) + # live vars: $t6 # refs: [] # - 17: $t5 := ==($t0, $t6) + 17: $t7 := 2 + # live vars: $t6, $t7 + # refs: [] + # + 18: $t5 := ==($t6, $t7) # live vars: $t5 # refs: [] # - 18: if ($t5) goto 19 else goto 21 + 19: if ($t5) goto 20 else goto 22 # live vars: # refs: [] # - 19: label L5 + 20: label L5 # live vars: # refs: [] # - 20: goto 24 + 21: goto 25 # live vars: # refs: [] # - 21: label L6 + 22: label L6 # live vars: # refs: [] # - 22: $t7 := 0 - # live vars: $t7 + 23: $t8 := 0 + # live vars: $t8 # refs: [] # - 23: abort($t7) + 24: abort($t8) # live vars: # refs: [] # - 24: label L7 + 25: label L7 # live vars: # refs: [] # - 25: return () + 26: return () } ============ after AbortAnalysisProcessor: ================ @@ -348,6 +361,7 @@ fun m::drop_after_loop() { var $t5: bool var $t6: u64 var $t7: u64 + var $t8: u64 # abort state: {returns,aborts} # live vars: # refs: [] @@ -480,52 +494,57 @@ fun m::drop_after_loop() { # live vars: $t0 # refs: [] # - 16: $t6 := 2 + 16: $t6 := infer($t0) + # abort state: {returns,aborts} + # live vars: $t6 + # refs: [] + # + 17: $t7 := 2 # abort state: {returns,aborts} - # live vars: $t0, $t6 + # live vars: $t6, $t7 # refs: [] # - 17: $t5 := ==($t0, $t6) + 18: $t5 := ==($t6, $t7) # abort state: {returns,aborts} # live vars: $t5 # refs: [] # - 18: if ($t5) goto 19 else goto 21 + 19: if ($t5) goto 20 else goto 22 # abort state: {returns} # live vars: # refs: [] # - 19: label L5 + 20: label L5 # abort state: {returns} # live vars: # refs: [] # - 20: goto 24 + 21: goto 25 # abort state: {aborts} # live vars: # refs: [] # - 21: label L6 + 22: label L6 # abort state: {aborts} # live vars: # refs: [] # - 22: $t7 := 0 + 23: $t8 := 0 # abort state: {aborts} - # live vars: $t7 + # live vars: $t8 # refs: [] # - 23: abort($t7) + 24: abort($t8) # abort state: {returns} # live vars: # refs: [] # - 24: label L7 + 25: label L7 # abort state: {returns} # live vars: # refs: [] # - 25: return () + 26: return () } ============ after AbilityProcessor: ================ @@ -540,6 +559,7 @@ fun m::drop_after_loop() { var $t5: bool var $t6: u64 var $t7: u64 + var $t8: u64 0: $t0 := 1 1: $t1 := borrow_local($t0) 2: $t2 := true @@ -557,14 +577,294 @@ fun m::drop_after_loop() { 14: label L4 15: goto 3 16: label L1 - 17: $t6 := 2 - 18: $t5 := ==($t0, $t6) - 19: if ($t5) goto 20 else goto 22 - 20: label L5 - 21: goto 25 - 22: label L6 - 23: $t7 := 0 - 24: abort($t7) - 25: label L7 - 26: return () + 17: $t6 := move($t0) + 18: $t7 := 2 + 19: $t5 := ==($t6, $t7) + 20: if ($t5) goto 21 else goto 23 + 21: label L5 + 22: goto 26 + 23: label L6 + 24: $t8 := 0 + 25: abort($t8) + 26: label L7 + 27: return () +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun m::drop_after_loop() { + var $t0: u64 + var $t1: &mut u64 + var $t2: bool + var $t3: u64 + var $t4: bool + var $t5: bool + var $t6: u64 + var $t7: u64 + var $t8: u64 + # live vars: + 0: $t0 := 1 + # live vars: $t0 + 1: $t1 := borrow_local($t0) + # live vars: $t0, $t1 + 2: $t2 := true + # live vars: $t0, $t1, $t2 + 3: label L0 + # live vars: $t0, $t1, $t2 + 4: if ($t2) goto 5 else goto 11 + # live vars: $t0, $t1 + 5: label L2 + # live vars: $t0, $t1 + 6: $t3 := 2 + # live vars: $t0, $t1, $t3 + 7: write_ref($t1, $t3) + # live vars: $t0, $t1 + 8: $t4 := false + # live vars: $t0, $t1, $t4 + 9: $t2 := move($t4) + # live vars: $t0, $t1, $t2 + 10: goto 3 + # live vars: $t0, $t1 + 11: label L3 + # live vars: $t0, $t1 + 12: drop($t1) + # live vars: $t0 + 13: $t6 := move($t0) + # live vars: $t6 + 14: $t7 := 2 + # live vars: $t6, $t7 + 15: $t5 := ==($t6, $t7) + # live vars: $t5 + 16: if ($t5) goto 17 else goto 19 + # live vars: + 17: label L5 + # live vars: + 18: return () + # live vars: + 19: label L6 + # live vars: + 20: $t8 := 0 + # live vars: $t8 + 21: abort($t8) +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun m::drop_after_loop() { + var $t0: u64 + var $t1: &mut u64 + var $t2: bool + var $t3: u64 + var $t4: bool + var $t5: bool + var $t6: u64 + var $t7: u64 + var $t8: u64 + # live vars: + 0: $t0 := 1 + # live vars: $t0 + 1: $t1 := borrow_local($t0) + # live vars: $t0, $t1 + 2: $t2 := true + # live vars: $t0, $t1, $t2 + 3: label L0 + # live vars: $t0, $t1, $t2 + 4: if ($t2) goto 5 else goto 11 + # live vars: $t0, $t1 + 5: label L2 + # live vars: $t0, $t1 + 6: $t3 := 2 + # live vars: $t0, $t1, $t3 + 7: write_ref($t1, $t3) + # live vars: $t0, $t1 + 8: $t4 := false + # live vars: $t0, $t1, $t4 + 9: $t2 := move($t4) + # live vars: $t0, $t1, $t2 + 10: goto 3 + # live vars: $t0, $t1 + 11: label L3 + # live vars: $t0, $t1 + 12: drop($t1) + # live vars: $t0 + 13: $t6 := move($t0) + # live vars: $t6 + 14: $t7 := 2 + # live vars: $t6, $t7 + 15: $t5 := ==($t6, $t7) + # live vars: $t5 + 16: if ($t5) goto 17 else goto 19 + # live vars: + 17: label L5 + # live vars: + 18: return () + # live vars: + 19: label L6 + # live vars: + 20: $t8 := 0 + # live vars: $t8 + 21: abort($t8) +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun m::drop_after_loop() { + var $t0: u64 + var $t1: &mut u64 + var $t2: bool + var $t3: u64 + var $t4: bool + var $t5: bool [unused] + var $t6: u64 [unused] + var $t7: u64 + var $t8: u64 [unused] + # live vars: + 0: $t0 := 1 + # live vars: $t0 + 1: $t1 := borrow_local($t0) + # live vars: $t0, $t1 + 2: $t2 := true + # live vars: $t0, $t1, $t2 + 3: label L0 + # live vars: $t0, $t1, $t2 + 4: if ($t2) goto 5 else goto 11 + # live vars: $t0, $t1 + 5: label L2 + # live vars: $t0, $t1 + 6: $t3 := 2 + # live vars: $t0, $t1, $t3 + 7: write_ref($t1, $t3) + # live vars: $t0, $t1 + 8: $t4 := false + # live vars: $t0, $t1, $t4 + 9: $t2 := move($t4) + # live vars: $t0, $t1, $t2 + 10: goto 3 + # live vars: $t0, $t1 + 11: label L3 + # live vars: $t0, $t1 + 12: drop($t1) + # live vars: $t0 + 13: $t3 := move($t0) + # live vars: $t3 + 14: $t7 := 2 + # live vars: $t3, $t7 + 15: $t2 := ==($t3, $t7) + # live vars: $t2 + 16: if ($t2) goto 17 else goto 19 + # live vars: + 17: label L5 + # live vars: + 18: return () + # live vars: + 19: label L6 + # live vars: + 20: $t3 := 0 + # live vars: $t3 + 21: abort($t3) +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun m::drop_after_loop() { + var $t0: u64 + var $t1: &mut u64 + var $t2: bool + var $t3: u64 + var $t4: bool + var $t5: bool [unused] + var $t6: u64 [unused] + var $t7: u64 + var $t8: u64 [unused] + # live vars: + 0: $t0 := 1 + # live vars: $t0 + 1: $t1 := borrow_local($t0) + # live vars: $t0, $t1 + 2: $t2 := true + # live vars: $t0, $t1, $t2 + 3: label L0 + # live vars: $t0, $t1, $t2 + 4: if ($t2) goto 5 else goto 11 + # live vars: $t0, $t1 + 5: label L2 + # live vars: $t0, $t1 + 6: $t3 := 2 + # live vars: $t0, $t1, $t3 + 7: write_ref($t1, $t3) + # live vars: $t0, $t1 + 8: $t4 := false + # live vars: $t0, $t1, $t4 + 9: $t2 := move($t4) + # live vars: $t0, $t1, $t2 + 10: goto 3 + # live vars: $t0, $t1 + 11: label L3 + # live vars: $t0, $t1 + 12: drop($t1) + # live vars: $t0 + 13: $t3 := move($t0) + # live vars: $t3 + 14: $t7 := 2 + # live vars: $t3, $t7 + 15: $t2 := ==($t3, $t7) + # live vars: $t2 + 16: if ($t2) goto 17 else goto 19 + # live vars: + 17: label L5 + # live vars: + 18: return () + # live vars: + 19: label L6 + # live vars: + 20: $t3 := 0 + # live vars: $t3 + 21: abort($t3) +} + + +============ disassembled file-format ================== +// Move bytecode v7 +module 42.m { + + +drop_after_loop() /* def_idx: 0 */ { +L0: loc0: u64 +L1: loc1: &mut u64 +L2: loc2: bool +B0: + 0: LdU64(1) + 1: StLoc[0](loc0: u64) + 2: MutBorrowLoc[0](loc0: u64) + 3: StLoc[1](loc1: &mut u64) + 4: LdTrue + 5: StLoc[2](loc2: bool) +B1: + 6: MoveLoc[2](loc2: bool) + 7: BrFalse(14) +B2: + 8: LdU64(2) + 9: CopyLoc[1](loc1: &mut u64) + 10: WriteRef + 11: LdFalse + 12: StLoc[2](loc2: bool) + 13: Branch(6) +B3: + 14: MoveLoc[1](loc1: &mut u64) + 15: Pop + 16: MoveLoc[0](loc0: u64) + 17: LdU64(2) + 18: Eq + 19: BrFalse(21) +B4: + 20: Ret +B5: + 21: LdU64(0) + 22: Abort +} } +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/ability-transform/drop_at_branch.exp b/third_party/move/move-compiler-v2/tests/ability-transform/drop_at_branch.exp index 3d11eed78fe83..2a72ca3c481ba 100644 --- a/third_party/move/move-compiler-v2/tests/ability-transform/drop_at_branch.exp +++ b/third_party/move/move-compiler-v2/tests/ability-transform/drop_at_branch.exp @@ -159,3 +159,120 @@ fun explicate_drop::drop_at_branch($t0: bool): u8 { 6: label L2 7: return $t1 } + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun explicate_drop::drop_at_branch($t0: bool): u8 { + var $t1: u8 + # live vars: $t0 + 0: if ($t0) goto 1 else goto 5 + # live vars: + 1: label L0 + # live vars: + 2: $t1 := 1 + # live vars: $t1 + 3: label L2 + # live vars: $t1 + 4: return $t1 + # live vars: + 5: label L1 + # live vars: + 6: $t1 := 0 + # live vars: $t1 + 7: goto 3 +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun explicate_drop::drop_at_branch($t0: bool): u8 { + var $t1: u8 + # live vars: $t0 + 0: if ($t0) goto 1 else goto 5 + # live vars: + 1: label L0 + # live vars: + 2: $t1 := 1 + # live vars: $t1 + 3: label L2 + # live vars: $t1 + 4: return $t1 + # live vars: + 5: label L1 + # live vars: + 6: $t1 := 0 + # live vars: $t1 + 7: goto 3 +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun explicate_drop::drop_at_branch($t0: bool): u8 { + var $t1: u8 + # live vars: $t0 + 0: if ($t0) goto 1 else goto 5 + # live vars: + 1: label L0 + # live vars: + 2: $t1 := 1 + # live vars: $t1 + 3: label L2 + # live vars: $t1 + 4: return $t1 + # live vars: + 5: label L1 + # live vars: + 6: $t1 := 0 + # live vars: $t1 + 7: goto 3 +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun explicate_drop::drop_at_branch($t0: bool): u8 { + var $t1: u8 + # live vars: $t0 + 0: if ($t0) goto 1 else goto 5 + # live vars: + 1: label L0 + # live vars: + 2: $t1 := 1 + # live vars: $t1 + 3: label L2 + # live vars: $t1 + 4: return $t1 + # live vars: + 5: label L1 + # live vars: + 6: $t1 := 0 + # live vars: $t1 + 7: goto 3 +} + + +============ disassembled file-format ================== +// Move bytecode v7 +module 42.explicate_drop { + + +drop_at_branch(Arg0: bool): u8 /* def_idx: 0 */ { +L1: loc0: u8 +B0: + 0: MoveLoc[0](Arg0: bool) + 1: BrFalse(6) +B1: + 2: LdU8(1) + 3: StLoc[1](loc0: u8) +B2: + 4: MoveLoc[1](loc0: u8) + 5: Ret +B3: + 6: LdU8(0) + 7: StLoc[1](loc0: u8) + 8: Branch(4) +} +} +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/ability-transform/foreach_mut_expanded.exp b/third_party/move/move-compiler-v2/tests/ability-transform/foreach_mut_expanded.exp index 7ab9fcebe971c..62571bab81005 100644 --- a/third_party/move/move-compiler-v2/tests/ability-transform/foreach_mut_expanded.exp +++ b/third_party/move/move-compiler-v2/tests/ability-transform/foreach_mut_expanded.exp @@ -8,44 +8,52 @@ fun m::test_for_each_mut() { var $t3: &vector var $t4: &mut vector var $t5: bool - var $t6: &mut u64 - var $t7: u64 - var $t8: u64 + var $t6: u64 + var $t7: &mut u64 + var $t8: &mut vector var $t9: u64 - var $t10: bool - var $t11: vector + var $t10: u64 + var $t11: u64 var $t12: u64 + var $t13: bool + var $t14: vector + var $t15: vector + var $t16: u64 0: $t0 := ["1", "2", "3"] 1: $t1 := 0 2: $t3 := borrow_local($t0) 3: $t2 := vector::length($t3) 4: $t4 := borrow_local($t0) 5: label L0 - 6: $t5 := <($t1, $t2) - 7: if ($t5) goto 8 else goto 16 - 8: label L2 - 9: $t6 := vector::borrow_mut($t4, $t1) - 10: $t7 := 2 - 11: write_ref($t6, $t7) - 12: $t9 := 1 - 13: $t8 := +($t1, $t9) - 14: $t1 := infer($t8) - 15: goto 18 - 16: label L3 - 17: goto 20 - 18: label L4 - 19: goto 5 - 20: label L1 - 21: $t11 := ["2", "3", "4"] - 22: $t10 := ==($t0, $t11) - 23: if ($t10) goto 24 else goto 26 - 24: label L5 - 25: goto 29 - 26: label L6 - 27: $t12 := 0 - 28: abort($t12) - 29: label L7 - 30: return () + 6: $t6 := infer($t1) + 7: $t5 := <($t6, $t2) + 8: if ($t5) goto 9 else goto 19 + 9: label L2 + 10: $t8 := infer($t4) + 11: $t7 := vector::borrow_mut($t8, $t1) + 12: $t9 := 2 + 13: write_ref($t7, $t9) + 14: $t11 := infer($t1) + 15: $t12 := 1 + 16: $t10 := +($t11, $t12) + 17: $t1 := infer($t10) + 18: goto 21 + 19: label L3 + 20: goto 23 + 21: label L4 + 22: goto 5 + 23: label L1 + 24: $t14 := infer($t0) + 25: $t15 := ["2", "3", "4"] + 26: $t13 := ==($t14, $t15) + 27: if ($t13) goto 28 else goto 30 + 28: label L5 + 29: goto 33 + 30: label L6 + 31: $t16 := 0 + 32: abort($t16) + 33: label L7 + 34: return () } ============ after LiveVarAnalysisProcessor: ================ @@ -58,13 +66,17 @@ fun m::test_for_each_mut() { var $t3: &vector var $t4: &mut vector var $t5: bool - var $t6: &mut u64 - var $t7: u64 - var $t8: u64 + var $t6: u64 + var $t7: &mut u64 + var $t8: &mut vector var $t9: u64 - var $t10: bool - var $t11: vector + var $t10: u64 + var $t11: u64 var $t12: u64 + var $t13: bool + var $t14: vector + var $t15: vector + var $t16: u64 # live vars: 0: $t0 := ["1", "2", "3"] # live vars: $t0 @@ -78,55 +90,63 @@ fun m::test_for_each_mut() { # live vars: $t0, $t1, $t2, $t4 5: label L0 # live vars: $t0, $t1, $t2, $t4 - 6: $t5 := <($t1, $t2) + 6: $t6 := infer($t1) + # live vars: $t0, $t1, $t2, $t4, $t6 + 7: $t5 := <($t6, $t2) # live vars: $t0, $t1, $t2, $t4, $t5 - 7: if ($t5) goto 8 else goto 16 + 8: if ($t5) goto 9 else goto 19 # live vars: $t0, $t1, $t2, $t4 - 8: label L2 + 9: label L2 # live vars: $t0, $t1, $t2, $t4 - 9: $t6 := vector::borrow_mut($t4, $t1) - # live vars: $t0, $t1, $t2, $t4, $t6 - 10: $t7 := 2 - # live vars: $t0, $t1, $t2, $t4, $t6, $t7 - 11: write_ref($t6, $t7) + 10: $t8 := infer($t4) + # live vars: $t0, $t1, $t2, $t4, $t8 + 11: $t7 := vector::borrow_mut($t8, $t1) + # live vars: $t0, $t1, $t2, $t4, $t7 + 12: $t9 := 2 + # live vars: $t0, $t1, $t2, $t4, $t7, $t9 + 13: write_ref($t7, $t9) # live vars: $t0, $t1, $t2, $t4 - 12: $t9 := 1 - # live vars: $t0, $t1, $t2, $t4, $t9 - 13: $t8 := +($t1, $t9) - # live vars: $t0, $t2, $t4, $t8 - 14: $t1 := infer($t8) + 14: $t11 := infer($t1) + # live vars: $t0, $t2, $t4, $t11 + 15: $t12 := 1 + # live vars: $t0, $t2, $t4, $t11, $t12 + 16: $t10 := +($t11, $t12) + # live vars: $t0, $t2, $t4, $t10 + 17: $t1 := infer($t10) # live vars: $t0, $t1, $t2, $t4 - 15: goto 18 + 18: goto 21 # live vars: $t0, $t1, $t2, $t4 - 16: label L3 + 19: label L3 # live vars: $t0 - 17: goto 20 + 20: goto 23 # live vars: $t0, $t1, $t2, $t4 - 18: label L4 + 21: label L4 # live vars: $t0, $t1, $t2, $t4 - 19: goto 5 + 22: goto 5 # live vars: $t0 - 20: label L1 + 23: label L1 # live vars: $t0 - 21: $t11 := ["2", "3", "4"] - # live vars: $t0, $t11 - 22: $t10 := ==($t0, $t11) - # live vars: $t10 - 23: if ($t10) goto 24 else goto 26 + 24: $t14 := infer($t0) + # live vars: $t14 + 25: $t15 := ["2", "3", "4"] + # live vars: $t14, $t15 + 26: $t13 := ==($t14, $t15) + # live vars: $t13 + 27: if ($t13) goto 28 else goto 30 # live vars: - 24: label L5 + 28: label L5 # live vars: - 25: goto 29 + 29: goto 33 # live vars: - 26: label L6 + 30: label L6 # live vars: - 27: $t12 := 0 - # live vars: $t12 - 28: abort($t12) + 31: $t16 := 0 + # live vars: $t16 + 32: abort($t16) # live vars: - 29: label L7 + 33: label L7 # live vars: - 30: return () + 34: return () } ============ after LiveVarAnalysisProcessor: ================ @@ -139,13 +159,17 @@ fun m::test_for_each_mut() { var $t3: &vector var $t4: &mut vector var $t5: bool - var $t6: &mut u64 - var $t7: u64 - var $t8: u64 + var $t6: u64 + var $t7: &mut u64 + var $t8: &mut vector var $t9: u64 - var $t10: bool - var $t11: vector + var $t10: u64 + var $t11: u64 var $t12: u64 + var $t13: bool + var $t14: vector + var $t15: vector + var $t16: u64 # live vars: 0: $t0 := ["1", "2", "3"] # live vars: $t0 @@ -159,55 +183,63 @@ fun m::test_for_each_mut() { # live vars: $t0, $t1, $t2, $t4 5: label L0 # live vars: $t0, $t1, $t2, $t4 - 6: $t5 := <($t1, $t2) + 6: $t6 := infer($t1) + # live vars: $t0, $t1, $t2, $t4, $t6 + 7: $t5 := <($t6, $t2) # live vars: $t0, $t1, $t2, $t4, $t5 - 7: if ($t5) goto 8 else goto 16 + 8: if ($t5) goto 9 else goto 19 # live vars: $t0, $t1, $t2, $t4 - 8: label L2 + 9: label L2 # live vars: $t0, $t1, $t2, $t4 - 9: $t6 := vector::borrow_mut($t4, $t1) - # live vars: $t0, $t1, $t2, $t4, $t6 - 10: $t7 := 2 - # live vars: $t0, $t1, $t2, $t4, $t6, $t7 - 11: write_ref($t6, $t7) + 10: $t8 := infer($t4) + # live vars: $t0, $t1, $t2, $t4, $t8 + 11: $t7 := vector::borrow_mut($t8, $t1) + # live vars: $t0, $t1, $t2, $t4, $t7 + 12: $t9 := 2 + # live vars: $t0, $t1, $t2, $t4, $t7, $t9 + 13: write_ref($t7, $t9) # live vars: $t0, $t1, $t2, $t4 - 12: $t9 := 1 - # live vars: $t0, $t1, $t2, $t4, $t9 - 13: $t8 := +($t1, $t9) - # live vars: $t0, $t2, $t4, $t8 - 14: $t1 := infer($t8) + 14: $t11 := infer($t1) + # live vars: $t0, $t2, $t4, $t11 + 15: $t12 := 1 + # live vars: $t0, $t2, $t4, $t11, $t12 + 16: $t10 := +($t11, $t12) + # live vars: $t0, $t2, $t4, $t10 + 17: $t1 := infer($t10) # live vars: $t0, $t1, $t2, $t4 - 15: goto 18 + 18: goto 21 # live vars: $t0, $t1, $t2, $t4 - 16: label L3 + 19: label L3 # live vars: $t0 - 17: goto 20 + 20: goto 23 # live vars: $t0, $t1, $t2, $t4 - 18: label L4 + 21: label L4 # live vars: $t0, $t1, $t2, $t4 - 19: goto 5 + 22: goto 5 # live vars: $t0 - 20: label L1 + 23: label L1 # live vars: $t0 - 21: $t11 := ["2", "3", "4"] - # live vars: $t0, $t11 - 22: $t10 := ==($t0, $t11) - # live vars: $t10 - 23: if ($t10) goto 24 else goto 26 + 24: $t14 := infer($t0) + # live vars: $t14 + 25: $t15 := ["2", "3", "4"] + # live vars: $t14, $t15 + 26: $t13 := ==($t14, $t15) + # live vars: $t13 + 27: if ($t13) goto 28 else goto 30 # live vars: - 24: label L5 + 28: label L5 # live vars: - 25: goto 29 + 29: goto 33 # live vars: - 26: label L6 + 30: label L6 # live vars: - 27: $t12 := 0 - # live vars: $t12 - 28: abort($t12) + 31: $t16 := 0 + # live vars: $t16 + 32: abort($t16) # live vars: - 29: label L7 + 33: label L7 # live vars: - 30: return () + 34: return () } ============ after ReferenceSafetyProcessor: ================ @@ -220,13 +252,17 @@ fun m::test_for_each_mut() { var $t3: &vector var $t4: &mut vector var $t5: bool - var $t6: &mut u64 - var $t7: u64 - var $t8: u64 + var $t6: u64 + var $t7: &mut u64 + var $t8: &mut vector var $t9: u64 - var $t10: bool - var $t11: vector + var $t10: u64 + var $t11: u64 var $t12: u64 + var $t13: bool + var $t14: vector + var $t15: vector + var $t16: u64 # live vars: # refs: [] # @@ -266,7 +302,15 @@ fun m::test_for_each_mut() { # #root # => (mut) #4 via [local `v`] at line 9 # - 6: $t5 := <($t1, $t2) + 6: $t6 := infer($t1) + # live vars: $t0, $t1, $t2, $t4, $t6 + # refs: [$t4 => #4] + # #4 + # + # #root + # => (mut) #4 via [local `v`] at line 9 + # + 7: $t5 := <($t6, $t2) # live vars: $t0, $t1, $t2, $t4, $t5 # refs: [$t4 => #4] # #4 @@ -274,7 +318,7 @@ fun m::test_for_each_mut() { # #root # => (mut) #4 via [local `v`] at line 9 # - 7: if ($t5) goto 8 else goto 16 + 8: if ($t5) goto 9 else goto 19 # live vars: $t0, $t1, $t2, $t4 # refs: [$t4 => #4] # #4 @@ -282,7 +326,7 @@ fun m::test_for_each_mut() { # #root # => (mut) #4 via [local `v`] at line 9 # - 8: label L2 + 9: label L2 # live vars: $t0, $t1, $t2, $t4 # refs: [$t4 => #4] # #4 @@ -290,27 +334,37 @@ fun m::test_for_each_mut() { # #root # => (mut) #4 via [local `v`] at line 9 # - 9: $t6 := vector::borrow_mut($t4, $t1) - # live vars: $t0, $t1, $t2, $t4, $t6 - # refs: [$t4 => #4, $t6 => #6] + 10: $t8 := infer($t4) + # live vars: $t0, $t1, $t2, $t4, $t8 + # refs: [$t4 => #4, $t8 => #8] # #4 - # -> (mut) #6 via [] at line 11 - # #6 + # => (mut) #8 via [] at line 11 + # #8 # # #root # => (mut) #4 via [local `v`] at line 9 # - 10: $t7 := 2 - # live vars: $t0, $t1, $t2, $t4, $t6, $t7 - # refs: [$t4 => #4, $t6 => #6] + 11: $t7 := vector::borrow_mut($t8, $t1) + # live vars: $t0, $t1, $t2, $t4, $t7 + # refs: [$t4 => #4, $t7 => #7] + # #4 + # -> (mut) #7 via [] at line 11 + # #7 + # + # #root + # => (mut) #4 via [local `v`] at line 9 + # + 12: $t9 := 2 + # live vars: $t0, $t1, $t2, $t4, $t7, $t9 + # refs: [$t4 => #4, $t7 => #7] # #4 - # -> (mut) #6 via [] at line 11 - # #6 + # -> (mut) #7 via [] at line 11 + # #7 # # #root # => (mut) #4 via [local `v`] at line 9 # - 11: write_ref($t6, $t7) + 13: write_ref($t7, $t9) # live vars: $t0, $t1, $t2, $t4 # refs: [$t4 => #4] # #4 @@ -318,23 +372,31 @@ fun m::test_for_each_mut() { # #root # => (mut) #4 via [local `v`] at line 9 # - 12: $t9 := 1 - # live vars: $t0, $t1, $t2, $t4, $t9 + 14: $t11 := infer($t1) + # live vars: $t0, $t2, $t4, $t11 + # refs: [$t4 => #4] + # #4 + # + # #root + # => (mut) #4 via [local `v`] at line 9 + # + 15: $t12 := 1 + # live vars: $t0, $t2, $t4, $t11, $t12 # refs: [$t4 => #4] # #4 # # #root # => (mut) #4 via [local `v`] at line 9 # - 13: $t8 := +($t1, $t9) - # live vars: $t0, $t2, $t4, $t8 + 16: $t10 := +($t11, $t12) + # live vars: $t0, $t2, $t4, $t10 # refs: [$t4 => #4] # #4 # # #root # => (mut) #4 via [local `v`] at line 9 # - 14: $t1 := infer($t8) + 17: $t1 := infer($t10) # live vars: $t0, $t1, $t2, $t4 # refs: [$t4 => #4] # #4 @@ -342,7 +404,7 @@ fun m::test_for_each_mut() { # #root # => (mut) #4 via [local `v`] at line 9 # - 15: goto 18 + 18: goto 21 # live vars: $t0, $t1, $t2, $t4 # refs: [$t4 => #4] # #4 @@ -350,11 +412,11 @@ fun m::test_for_each_mut() { # #root # => (mut) #4 via [local `v`] at line 9 # - 16: label L3 + 19: label L3 # live vars: $t0 # refs: [] # - 17: goto 20 + 20: goto 23 # live vars: $t0, $t1, $t2, $t4 # refs: [$t4 => #4] # #4 @@ -362,7 +424,7 @@ fun m::test_for_each_mut() { # #root # => (mut) #4 via [local `v`] at line 9 # - 18: label L4 + 21: label L4 # live vars: $t0, $t1, $t2, $t4 # refs: [$t4 => #4] # #4 @@ -370,51 +432,55 @@ fun m::test_for_each_mut() { # #root # => (mut) #4 via [local `v`] at line 9 # - 19: goto 5 + 22: goto 5 # live vars: $t0 # refs: [] # - 20: label L1 + 23: label L1 # live vars: $t0 # refs: [] # - 21: $t11 := ["2", "3", "4"] - # live vars: $t0, $t11 + 24: $t14 := infer($t0) + # live vars: $t14 + # refs: [] + # + 25: $t15 := ["2", "3", "4"] + # live vars: $t14, $t15 # refs: [] # - 22: $t10 := ==($t0, $t11) - # live vars: $t10 + 26: $t13 := ==($t14, $t15) + # live vars: $t13 # refs: [] # - 23: if ($t10) goto 24 else goto 26 + 27: if ($t13) goto 28 else goto 30 # live vars: # refs: [] # - 24: label L5 + 28: label L5 # live vars: # refs: [] # - 25: goto 29 + 29: goto 33 # live vars: # refs: [] # - 26: label L6 + 30: label L6 # live vars: # refs: [] # - 27: $t12 := 0 - # live vars: $t12 + 31: $t16 := 0 + # live vars: $t16 # refs: [] # - 28: abort($t12) + 32: abort($t16) # live vars: # refs: [] # - 29: label L7 + 33: label L7 # live vars: # refs: [] # - 30: return () + 34: return () } ============ after AbortAnalysisProcessor: ================ @@ -427,13 +493,17 @@ fun m::test_for_each_mut() { var $t3: &vector var $t4: &mut vector var $t5: bool - var $t6: &mut u64 - var $t7: u64 - var $t8: u64 + var $t6: u64 + var $t7: &mut u64 + var $t8: &mut vector var $t9: u64 - var $t10: bool - var $t11: vector + var $t10: u64 + var $t11: u64 var $t12: u64 + var $t13: bool + var $t14: vector + var $t15: vector + var $t16: u64 # abort state: {returns,aborts} # live vars: # refs: [] @@ -480,7 +550,16 @@ fun m::test_for_each_mut() { # #root # => (mut) #4 via [local `v`] at line 9 # - 6: $t5 := <($t1, $t2) + 6: $t6 := infer($t1) + # abort state: {returns,aborts} + # live vars: $t0, $t1, $t2, $t4, $t6 + # refs: [$t4 => #4] + # #4 + # + # #root + # => (mut) #4 via [local `v`] at line 9 + # + 7: $t5 := <($t6, $t2) # abort state: {returns,aborts} # live vars: $t0, $t1, $t2, $t4, $t5 # refs: [$t4 => #4] @@ -489,7 +568,7 @@ fun m::test_for_each_mut() { # #root # => (mut) #4 via [local `v`] at line 9 # - 7: if ($t5) goto 8 else goto 16 + 8: if ($t5) goto 9 else goto 19 # abort state: {returns,aborts} # live vars: $t0, $t1, $t2, $t4 # refs: [$t4 => #4] @@ -498,7 +577,7 @@ fun m::test_for_each_mut() { # #root # => (mut) #4 via [local `v`] at line 9 # - 8: label L2 + 9: label L2 # abort state: {returns,aborts} # live vars: $t0, $t1, $t2, $t4 # refs: [$t4 => #4] @@ -507,29 +586,40 @@ fun m::test_for_each_mut() { # #root # => (mut) #4 via [local `v`] at line 9 # - 9: $t6 := vector::borrow_mut($t4, $t1) + 10: $t8 := infer($t4) # abort state: {returns,aborts} - # live vars: $t0, $t1, $t2, $t4, $t6 - # refs: [$t4 => #4, $t6 => #6] + # live vars: $t0, $t1, $t2, $t4, $t8 + # refs: [$t4 => #4, $t8 => #8] # #4 - # -> (mut) #6 via [] at line 11 - # #6 + # => (mut) #8 via [] at line 11 + # #8 # # #root # => (mut) #4 via [local `v`] at line 9 # - 10: $t7 := 2 + 11: $t7 := vector::borrow_mut($t8, $t1) # abort state: {returns,aborts} - # live vars: $t0, $t1, $t2, $t4, $t6, $t7 - # refs: [$t4 => #4, $t6 => #6] + # live vars: $t0, $t1, $t2, $t4, $t7 + # refs: [$t4 => #4, $t7 => #7] + # #4 + # -> (mut) #7 via [] at line 11 + # #7 + # + # #root + # => (mut) #4 via [local `v`] at line 9 + # + 12: $t9 := 2 + # abort state: {returns,aborts} + # live vars: $t0, $t1, $t2, $t4, $t7, $t9 + # refs: [$t4 => #4, $t7 => #7] # #4 - # -> (mut) #6 via [] at line 11 - # #6 + # -> (mut) #7 via [] at line 11 + # #7 # # #root # => (mut) #4 via [local `v`] at line 9 # - 11: write_ref($t6, $t7) + 13: write_ref($t7, $t9) # abort state: {returns,aborts} # live vars: $t0, $t1, $t2, $t4 # refs: [$t4 => #4] @@ -538,25 +628,34 @@ fun m::test_for_each_mut() { # #root # => (mut) #4 via [local `v`] at line 9 # - 12: $t9 := 1 + 14: $t11 := infer($t1) + # abort state: {returns,aborts} + # live vars: $t0, $t2, $t4, $t11 + # refs: [$t4 => #4] + # #4 + # + # #root + # => (mut) #4 via [local `v`] at line 9 + # + 15: $t12 := 1 # abort state: {returns,aborts} - # live vars: $t0, $t1, $t2, $t4, $t9 + # live vars: $t0, $t2, $t4, $t11, $t12 # refs: [$t4 => #4] # #4 # # #root # => (mut) #4 via [local `v`] at line 9 # - 13: $t8 := +($t1, $t9) + 16: $t10 := +($t11, $t12) # abort state: {returns,aborts} - # live vars: $t0, $t2, $t4, $t8 + # live vars: $t0, $t2, $t4, $t10 # refs: [$t4 => #4] # #4 # # #root # => (mut) #4 via [local `v`] at line 9 # - 14: $t1 := infer($t8) + 17: $t1 := infer($t10) # abort state: {returns,aborts} # live vars: $t0, $t1, $t2, $t4 # refs: [$t4 => #4] @@ -565,7 +664,7 @@ fun m::test_for_each_mut() { # #root # => (mut) #4 via [local `v`] at line 9 # - 15: goto 18 + 18: goto 21 # abort state: {returns,aborts} # live vars: $t0, $t1, $t2, $t4 # refs: [$t4 => #4] @@ -574,12 +673,12 @@ fun m::test_for_each_mut() { # #root # => (mut) #4 via [local `v`] at line 9 # - 16: label L3 + 19: label L3 # abort state: {returns,aborts} # live vars: $t0 # refs: [] # - 17: goto 20 + 20: goto 23 # abort state: {returns,aborts} # live vars: $t0, $t1, $t2, $t4 # refs: [$t4 => #4] @@ -588,7 +687,7 @@ fun m::test_for_each_mut() { # #root # => (mut) #4 via [local `v`] at line 9 # - 18: label L4 + 21: label L4 # abort state: {returns,aborts} # live vars: $t0, $t1, $t2, $t4 # refs: [$t4 => #4] @@ -597,62 +696,67 @@ fun m::test_for_each_mut() { # #root # => (mut) #4 via [local `v`] at line 9 # - 19: goto 5 + 22: goto 5 # abort state: {returns,aborts} # live vars: $t0 # refs: [] # - 20: label L1 + 23: label L1 # abort state: {returns,aborts} # live vars: $t0 # refs: [] # - 21: $t11 := ["2", "3", "4"] + 24: $t14 := infer($t0) + # abort state: {returns,aborts} + # live vars: $t14 + # refs: [] + # + 25: $t15 := ["2", "3", "4"] # abort state: {returns,aborts} - # live vars: $t0, $t11 + # live vars: $t14, $t15 # refs: [] # - 22: $t10 := ==($t0, $t11) + 26: $t13 := ==($t14, $t15) # abort state: {returns,aborts} - # live vars: $t10 + # live vars: $t13 # refs: [] # - 23: if ($t10) goto 24 else goto 26 + 27: if ($t13) goto 28 else goto 30 # abort state: {returns} # live vars: # refs: [] # - 24: label L5 + 28: label L5 # abort state: {returns} # live vars: # refs: [] # - 25: goto 29 + 29: goto 33 # abort state: {aborts} # live vars: # refs: [] # - 26: label L6 + 30: label L6 # abort state: {aborts} # live vars: # refs: [] # - 27: $t12 := 0 + 31: $t16 := 0 # abort state: {aborts} - # live vars: $t12 + # live vars: $t16 # refs: [] # - 28: abort($t12) + 32: abort($t16) # abort state: {returns} # live vars: # refs: [] # - 29: label L7 + 33: label L7 # abort state: {returns} # live vars: # refs: [] # - 30: return () + 34: return () } ============ after AbilityProcessor: ================ @@ -665,43 +769,439 @@ fun m::test_for_each_mut() { var $t3: &vector var $t4: &mut vector var $t5: bool - var $t6: &mut u64 - var $t7: u64 - var $t8: u64 + var $t6: u64 + var $t7: &mut u64 + var $t8: &mut vector var $t9: u64 - var $t10: bool - var $t11: vector + var $t10: u64 + var $t11: u64 var $t12: u64 + var $t13: bool + var $t14: vector + var $t15: vector + var $t16: u64 0: $t0 := ["1", "2", "3"] 1: $t1 := 0 2: $t3 := borrow_local($t0) 3: $t2 := vector::length($t3) 4: $t4 := borrow_local($t0) 5: label L0 - 6: $t5 := <($t1, $t2) - 7: if ($t5) goto 8 else goto 16 - 8: label L2 - 9: $t6 := vector::borrow_mut($t4, $t1) - 10: $t7 := 2 - 11: write_ref($t6, $t7) - 12: $t9 := 1 - 13: $t8 := +($t1, $t9) - 14: $t1 := move($t8) - 15: goto 19 - 16: label L3 - 17: drop($t4) - 18: goto 21 - 19: label L4 - 20: goto 5 - 21: label L1 - 22: $t11 := ["2", "3", "4"] - 23: $t10 := ==($t0, $t11) - 24: if ($t10) goto 25 else goto 27 + 6: $t6 := copy($t1) + 7: $t5 := <($t6, $t2) + 8: if ($t5) goto 9 else goto 19 + 9: label L2 + 10: $t8 := copy($t4) + 11: $t7 := vector::borrow_mut($t8, $t1) + 12: $t9 := 2 + 13: write_ref($t7, $t9) + 14: $t11 := move($t1) + 15: $t12 := 1 + 16: $t10 := +($t11, $t12) + 17: $t1 := move($t10) + 18: goto 22 + 19: label L3 + 20: drop($t4) + 21: goto 24 + 22: label L4 + 23: goto 5 + 24: label L1 + 25: $t14 := move($t0) + 26: $t15 := ["2", "3", "4"] + 27: $t13 := ==($t14, $t15) + 28: if ($t13) goto 29 else goto 31 + 29: label L5 + 30: goto 34 + 31: label L6 + 32: $t16 := 0 + 33: abort($t16) + 34: label L7 + 35: return () +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun m::test_for_each_mut() { + var $t0: vector + var $t1: u64 + var $t2: u64 + var $t3: &vector + var $t4: &mut vector + var $t5: bool + var $t6: u64 + var $t7: &mut u64 + var $t8: &mut vector + var $t9: u64 + var $t10: u64 + var $t11: u64 + var $t12: u64 + var $t13: bool + var $t14: vector + var $t15: vector + var $t16: u64 + # live vars: + 0: $t0 := ["1", "2", "3"] + # live vars: $t0 + 1: $t1 := 0 + # live vars: $t0, $t1 + 2: $t3 := borrow_local($t0) + # live vars: $t0, $t1, $t3 + 3: $t2 := vector::length($t3) + # live vars: $t0, $t1, $t2 + 4: $t4 := borrow_local($t0) + # live vars: $t0, $t1, $t2, $t4 + 5: label L0 + # live vars: $t0, $t1, $t2, $t4 + 6: $t6 := copy($t1) + # live vars: $t0, $t1, $t2, $t4, $t6 + 7: $t5 := <($t6, $t2) + # live vars: $t0, $t1, $t2, $t4, $t5 + 8: if ($t5) goto 9 else goto 19 + # live vars: $t0, $t1, $t2, $t4 + 9: label L2 + # live vars: $t0, $t1, $t2, $t4 + 10: $t8 := copy($t4) + # live vars: $t0, $t1, $t2, $t4, $t8 + 11: $t7 := vector::borrow_mut($t8, $t1) + # live vars: $t0, $t1, $t2, $t4, $t7 + 12: $t9 := 2 + # live vars: $t0, $t1, $t2, $t4, $t7, $t9 + 13: write_ref($t7, $t9) + # live vars: $t0, $t1, $t2, $t4 + 14: $t11 := move($t1) + # live vars: $t0, $t2, $t4, $t11 + 15: $t12 := 1 + # live vars: $t0, $t2, $t4, $t11, $t12 + 16: $t10 := +($t11, $t12) + # live vars: $t0, $t2, $t4, $t10 + 17: $t1 := move($t10) + # live vars: $t0, $t1, $t2, $t4 + 18: goto 5 + # live vars: $t0, $t1, $t2, $t4 + 19: label L3 + # live vars: $t0, $t4 + 20: drop($t4) + # live vars: $t0 + 21: $t14 := move($t0) + # live vars: $t14 + 22: $t15 := ["2", "3", "4"] + # live vars: $t14, $t15 + 23: $t13 := ==($t14, $t15) + # live vars: $t13 + 24: if ($t13) goto 25 else goto 27 + # live vars: + 25: label L5 + # live vars: + 26: return () + # live vars: + 27: label L6 + # live vars: + 28: $t16 := 0 + # live vars: $t16 + 29: abort($t16) +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun m::test_for_each_mut() { + var $t0: vector + var $t1: u64 + var $t2: u64 + var $t3: &vector + var $t4: &mut vector + var $t5: bool + var $t6: u64 + var $t7: &mut u64 + var $t8: &mut vector + var $t9: u64 + var $t10: u64 + var $t11: u64 + var $t12: u64 + var $t13: bool + var $t14: vector + var $t15: vector + var $t16: u64 + # live vars: + 0: $t0 := ["1", "2", "3"] + # live vars: $t0 + 1: $t1 := 0 + # live vars: $t0, $t1 + 2: $t3 := borrow_local($t0) + # live vars: $t0, $t1, $t3 + 3: $t2 := vector::length($t3) + # live vars: $t0, $t1, $t2 + 4: $t4 := borrow_local($t0) + # live vars: $t0, $t1, $t2, $t4 + 5: label L0 + # live vars: $t0, $t1, $t2, $t4 + 6: $t6 := copy($t1) + # live vars: $t0, $t1, $t2, $t4, $t6 + 7: $t5 := <($t6, $t2) + # live vars: $t0, $t1, $t2, $t4, $t5 + 8: if ($t5) goto 9 else goto 19 + # live vars: $t0, $t1, $t2, $t4 + 9: label L2 + # live vars: $t0, $t1, $t2, $t4 + 10: $t8 := copy($t4) + # live vars: $t0, $t1, $t2, $t4, $t8 + 11: $t7 := vector::borrow_mut($t8, $t1) + # live vars: $t0, $t1, $t2, $t4, $t7 + 12: $t9 := 2 + # live vars: $t0, $t1, $t2, $t4, $t7, $t9 + 13: write_ref($t7, $t9) + # live vars: $t0, $t1, $t2, $t4 + 14: $t11 := move($t1) + # live vars: $t0, $t2, $t4, $t11 + 15: $t12 := 1 + # live vars: $t0, $t2, $t4, $t11, $t12 + 16: $t10 := +($t11, $t12) + # live vars: $t0, $t2, $t4, $t10 + 17: $t1 := move($t10) + # live vars: $t0, $t1, $t2, $t4 + 18: goto 5 + # live vars: $t0, $t1, $t2, $t4 + 19: label L3 + # live vars: $t0, $t4 + 20: drop($t4) + # live vars: $t0 + 21: $t14 := move($t0) + # live vars: $t14 + 22: $t15 := ["2", "3", "4"] + # live vars: $t14, $t15 + 23: $t13 := ==($t14, $t15) + # live vars: $t13 + 24: if ($t13) goto 25 else goto 27 + # live vars: + 25: label L5 + # live vars: + 26: return () + # live vars: + 27: label L6 + # live vars: + 28: $t16 := 0 + # live vars: $t16 + 29: abort($t16) +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun m::test_for_each_mut() { + var $t0: vector + var $t1: u64 + var $t2: u64 + var $t3: &vector + var $t4: &mut vector + var $t5: bool + var $t6: u64 + var $t7: &mut u64 + var $t8: &mut vector + var $t9: u64 [unused] + var $t10: u64 [unused] + var $t11: u64 [unused] + var $t12: u64 + var $t13: bool [unused] + var $t14: vector + var $t15: vector + var $t16: u64 [unused] + # live vars: + 0: $t0 := ["1", "2", "3"] + # live vars: $t0 + 1: $t1 := 0 + # live vars: $t0, $t1 + 2: $t3 := borrow_local($t0) + # live vars: $t0, $t1, $t3 + 3: $t2 := vector::length($t3) + # live vars: $t0, $t1, $t2 + 4: $t4 := borrow_local($t0) + # live vars: $t0, $t1, $t2, $t4 + 5: label L0 + # live vars: $t0, $t1, $t2, $t4 + 6: $t6 := copy($t1) + # live vars: $t0, $t1, $t2, $t4, $t6 + 7: $t5 := <($t6, $t2) + # live vars: $t0, $t1, $t2, $t4, $t5 + 8: if ($t5) goto 9 else goto 19 + # live vars: $t0, $t1, $t2, $t4 + 9: label L2 + # live vars: $t0, $t1, $t2, $t4 + 10: $t8 := copy($t4) + # live vars: $t0, $t1, $t2, $t4, $t8 + 11: $t7 := vector::borrow_mut($t8, $t1) + # live vars: $t0, $t1, $t2, $t4, $t7 + 12: $t6 := 2 + # live vars: $t0, $t1, $t2, $t4, $t6, $t7 + 13: write_ref($t7, $t6) + # live vars: $t0, $t1, $t2, $t4 + 14: $t6 := move($t1) + # live vars: $t0, $t2, $t4, $t6 + 15: $t12 := 1 + # live vars: $t0, $t2, $t4, $t6, $t12 + 16: $t6 := +($t6, $t12) + # live vars: $t0, $t2, $t4, $t6 + 17: $t1 := move($t6) + # live vars: $t0, $t1, $t2, $t4 + 18: goto 5 + # live vars: $t0, $t1, $t2, $t4 + 19: label L3 + # live vars: $t0, $t4 + 20: drop($t4) + # live vars: $t0 + 21: $t14 := move($t0) + # live vars: $t14 + 22: $t15 := ["2", "3", "4"] + # live vars: $t14, $t15 + 23: $t5 := ==($t14, $t15) + # live vars: $t5 + 24: if ($t5) goto 25 else goto 27 + # live vars: 25: label L5 - 26: goto 30 + # live vars: + 26: return () + # live vars: 27: label L6 - 28: $t12 := 0 - 29: abort($t12) - 30: label L7 - 31: return () + # live vars: + 28: $t1 := 0 + # live vars: $t1 + 29: abort($t1) +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun m::test_for_each_mut() { + var $t0: vector + var $t1: u64 + var $t2: u64 + var $t3: &vector + var $t4: &mut vector + var $t5: bool + var $t6: u64 + var $t7: &mut u64 + var $t8: &mut vector + var $t9: u64 [unused] + var $t10: u64 [unused] + var $t11: u64 [unused] + var $t12: u64 + var $t13: bool [unused] + var $t14: vector + var $t15: vector + var $t16: u64 [unused] + # live vars: + 0: $t0 := ["1", "2", "3"] + # live vars: $t0 + 1: $t1 := 0 + # live vars: $t0, $t1 + 2: $t3 := borrow_local($t0) + # live vars: $t0, $t1, $t3 + 3: $t2 := vector::length($t3) + # live vars: $t0, $t1, $t2 + 4: $t4 := borrow_local($t0) + # live vars: $t0, $t1, $t2, $t4 + 5: label L0 + # live vars: $t0, $t1, $t2, $t4 + 6: $t6 := copy($t1) + # live vars: $t0, $t1, $t2, $t4, $t6 + 7: $t5 := <($t6, $t2) + # live vars: $t0, $t1, $t2, $t4, $t5 + 8: if ($t5) goto 9 else goto 19 + # live vars: $t0, $t1, $t2, $t4 + 9: label L2 + # live vars: $t0, $t1, $t2, $t4 + 10: $t8 := copy($t4) + # live vars: $t0, $t1, $t2, $t4, $t8 + 11: $t7 := vector::borrow_mut($t8, $t1) + # live vars: $t0, $t1, $t2, $t4, $t7 + 12: $t6 := 2 + # live vars: $t0, $t1, $t2, $t4, $t6, $t7 + 13: write_ref($t7, $t6) + # live vars: $t0, $t1, $t2, $t4 + 14: $t6 := move($t1) + # live vars: $t0, $t2, $t4, $t6 + 15: $t12 := 1 + # live vars: $t0, $t2, $t4, $t6, $t12 + 16: $t6 := +($t6, $t12) + # live vars: $t0, $t2, $t4, $t6 + 17: $t1 := move($t6) + # live vars: $t0, $t1, $t2, $t4 + 18: goto 5 + # live vars: $t0, $t1, $t2, $t4 + 19: label L3 + # live vars: $t0, $t4 + 20: drop($t4) + # live vars: $t0 + 21: $t14 := move($t0) + # live vars: $t14 + 22: $t15 := ["2", "3", "4"] + # live vars: $t14, $t15 + 23: $t5 := ==($t14, $t15) + # live vars: $t5 + 24: if ($t5) goto 25 else goto 27 + # live vars: + 25: label L5 + # live vars: + 26: return () + # live vars: + 27: label L6 + # live vars: + 28: $t1 := 0 + # live vars: $t1 + 29: abort($t1) +} + + +============ disassembled file-format ================== +// Move bytecode v7 +module 42.m { + + +test_for_each_mut() /* def_idx: 0 */ { +L0: loc0: vector +L1: loc1: u64 +L2: loc2: u64 +L3: loc3: &mut vector +L4: loc4: &mut u64 +B0: + 0: LdConst[0](Vector(U64): [3, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0]) + 1: StLoc[0](loc0: vector) + 2: LdU64(0) + 3: StLoc[1](loc1: u64) + 4: ImmBorrowLoc[0](loc0: vector) + 5: VecLen(1) + 6: StLoc[2](loc2: u64) + 7: MutBorrowLoc[0](loc0: vector) + 8: StLoc[3](loc3: &mut vector) +B1: + 9: CopyLoc[1](loc1: u64) + 10: CopyLoc[2](loc2: u64) + 11: Lt + 12: BrFalse(25) +B2: + 13: CopyLoc[3](loc3: &mut vector) + 14: CopyLoc[1](loc1: u64) + 15: VecMutBorrow(1) + 16: StLoc[4](loc4: &mut u64) + 17: LdU64(2) + 18: MoveLoc[4](loc4: &mut u64) + 19: WriteRef + 20: MoveLoc[1](loc1: u64) + 21: LdU64(1) + 22: Add + 23: StLoc[1](loc1: u64) + 24: Branch(9) +B3: + 25: MoveLoc[3](loc3: &mut vector) + 26: Pop + 27: MoveLoc[0](loc0: vector) + 28: LdConst[1](Vector(U64): [3, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0]) + 29: Eq + 30: BrFalse(32) +B4: + 31: Ret +B5: + 32: LdU64(0) + 33: Abort +} } +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/ability-transform/mutate_return.exp b/third_party/move/move-compiler-v2/tests/ability-transform/mutate_return.exp index 8598b7358c1ab..af7b55902c140 100644 --- a/third_party/move/move-compiler-v2/tests/ability-transform/mutate_return.exp +++ b/third_party/move/move-compiler-v2/tests/ability-transform/mutate_return.exp @@ -188,3 +188,141 @@ fun m::g<#0>($t0: &mut vector<#0>) { 0: drop($t0) 1: return () } + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +public fun m::singleton<#0>($t0: #0): vector<#0> { + var $t1: vector<#0> + var $t2: vector<#0> + var $t3: &mut vector<#0> + # live vars: $t0 + 0: $t2 := vector($t0) + # live vars: $t2 + 1: $t3 := borrow_local($t2) + # live vars: $t2, $t3 + 2: m::g<#0>($t3) + # live vars: $t2 + 3: $t1 := move($t2) + # live vars: $t1 + 4: return $t1 +} + + +[variant baseline] +fun m::g<#0>($t0: &mut vector<#0>) { + # live vars: $t0 + 0: drop($t0) + # live vars: + 1: return () +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +public fun m::singleton<#0>($t0: #0): vector<#0> { + var $t1: vector<#0> + var $t2: vector<#0> + var $t3: &mut vector<#0> + # live vars: $t0 + 0: $t2 := vector($t0) + # live vars: $t2 + 1: $t3 := borrow_local($t2) + # live vars: $t2, $t3 + 2: m::g<#0>($t3) + # live vars: $t2 + 3: $t1 := move($t2) + # live vars: $t1 + 4: return $t1 +} + + +[variant baseline] +fun m::g<#0>($t0: &mut vector<#0>) { + # live vars: $t0 + 0: drop($t0) + # live vars: + 1: return () +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +public fun m::singleton<#0>($t0: #0): vector<#0> { + var $t1: vector<#0> + var $t2: vector<#0> + var $t3: &mut vector<#0> + # live vars: $t0 + 0: $t2 := vector($t0) + # live vars: $t2 + 1: $t3 := borrow_local($t2) + # live vars: $t2, $t3 + 2: m::g<#0>($t3) + # live vars: $t2 + 3: $t1 := move($t2) + # live vars: $t1 + 4: return $t1 +} + + +[variant baseline] +fun m::g<#0>($t0: &mut vector<#0>) { + # live vars: $t0 + 0: drop($t0) + # live vars: + 1: return () +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +public fun m::singleton<#0>($t0: #0): vector<#0> { + var $t1: vector<#0> + var $t2: vector<#0> + var $t3: &mut vector<#0> + # live vars: $t0 + 0: $t2 := vector($t0) + # live vars: $t2 + 1: $t3 := borrow_local($t2) + # live vars: $t2, $t3 + 2: m::g<#0>($t3) + # live vars: $t2 + 3: $t1 := move($t2) + # live vars: $t1 + 4: return $t1 +} + + +[variant baseline] +fun m::g<#0>($t0: &mut vector<#0>) { + # live vars: $t0 + 0: drop($t0) + # live vars: + 1: return () +} + + +============ disassembled file-format ================== +// Move bytecode v7 +module c0ffee.m { + + +public singleton(Arg0: Ty0): vector /* def_idx: 0 */ { +L1: loc0: vector +B0: + 0: MoveLoc[0](Arg0: Ty0) + 1: VecPack(0, 1) + 2: StLoc[1](loc0: vector) + 3: MutBorrowLoc[1](loc0: vector) + 4: Call g(&mut vector) + 5: MoveLoc[1](loc0: vector) + 6: Ret +} +g(Arg0: &mut vector) /* def_idx: 1 */ { +B0: + 0: MoveLoc[0](Arg0: &mut vector) + 1: Pop + 2: Ret +} +} +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/ability-transform/mutate_vector.exp b/third_party/move/move-compiler-v2/tests/ability-transform/mutate_vector.exp index 7259af56e7847..9808a45e289f0 100644 --- a/third_party/move/move-compiler-v2/tests/ability-transform/mutate_vector.exp +++ b/third_party/move/move-compiler-v2/tests/ability-transform/mutate_vector.exp @@ -308,3 +308,201 @@ public fun m::scalar_zero(): 0x42::m::Scalar { 1: $t0 := pack 0x42::m::Scalar($t1) 2: return $t0 } + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +public fun m::new_scalar_from_u8($t0: u8): 0x42::m::Scalar { + var $t1: 0x42::m::Scalar + var $t2: 0x42::m::Scalar + var $t3: &mut u8 + var $t4: &mut vector + var $t5: &mut 0x42::m::Scalar + var $t6: u64 + # live vars: $t0 + 0: $t2 := m::scalar_zero() + # live vars: $t0, $t2 + 1: $t5 := borrow_local($t2) + # live vars: $t0, $t2, $t5 + 2: $t4 := borrow_field<0x42::m::Scalar>.data($t5) + # live vars: $t0, $t2, $t4 + 3: $t6 := 0 + # live vars: $t0, $t2, $t4, $t6 + 4: $t3 := vector::borrow_mut($t4, $t6) + # live vars: $t0, $t2, $t3 + 5: write_ref($t3, $t0) + # live vars: $t2 + 6: $t1 := move($t2) + # live vars: $t1 + 7: return $t1 +} + + +[variant baseline] +public fun m::scalar_zero(): 0x42::m::Scalar { + var $t0: 0x42::m::Scalar + var $t1: vector + # live vars: + 0: $t1 := [0] + # live vars: $t1 + 1: $t0 := pack 0x42::m::Scalar($t1) + # live vars: $t0 + 2: return $t0 +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +public fun m::new_scalar_from_u8($t0: u8): 0x42::m::Scalar { + var $t1: 0x42::m::Scalar + var $t2: 0x42::m::Scalar + var $t3: &mut u8 + var $t4: &mut vector + var $t5: &mut 0x42::m::Scalar + var $t6: u64 + # live vars: $t0 + 0: $t2 := m::scalar_zero() + # live vars: $t0, $t2 + 1: $t5 := borrow_local($t2) + # live vars: $t0, $t2, $t5 + 2: $t4 := borrow_field<0x42::m::Scalar>.data($t5) + # live vars: $t0, $t2, $t4 + 3: $t6 := 0 + # live vars: $t0, $t2, $t4, $t6 + 4: $t3 := vector::borrow_mut($t4, $t6) + # live vars: $t0, $t2, $t3 + 5: write_ref($t3, $t0) + # live vars: $t2 + 6: $t1 := move($t2) + # live vars: $t1 + 7: return $t1 +} + + +[variant baseline] +public fun m::scalar_zero(): 0x42::m::Scalar { + var $t0: 0x42::m::Scalar + var $t1: vector + # live vars: + 0: $t1 := [0] + # live vars: $t1 + 1: $t0 := pack 0x42::m::Scalar($t1) + # live vars: $t0 + 2: return $t0 +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +public fun m::new_scalar_from_u8($t0: u8): 0x42::m::Scalar { + var $t1: 0x42::m::Scalar + var $t2: 0x42::m::Scalar + var $t3: &mut u8 + var $t4: &mut vector + var $t5: &mut 0x42::m::Scalar + var $t6: u64 + # live vars: $t0 + 0: $t2 := m::scalar_zero() + # live vars: $t0, $t2 + 1: $t5 := borrow_local($t2) + # live vars: $t0, $t2, $t5 + 2: $t4 := borrow_field<0x42::m::Scalar>.data($t5) + # live vars: $t0, $t2, $t4 + 3: $t6 := 0 + # live vars: $t0, $t2, $t4, $t6 + 4: $t3 := vector::borrow_mut($t4, $t6) + # live vars: $t0, $t2, $t3 + 5: write_ref($t3, $t0) + # live vars: $t2 + 6: $t1 := move($t2) + # live vars: $t1 + 7: return $t1 +} + + +[variant baseline] +public fun m::scalar_zero(): 0x42::m::Scalar { + var $t0: 0x42::m::Scalar + var $t1: vector + # live vars: + 0: $t1 := [0] + # live vars: $t1 + 1: $t0 := pack 0x42::m::Scalar($t1) + # live vars: $t0 + 2: return $t0 +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +public fun m::new_scalar_from_u8($t0: u8): 0x42::m::Scalar { + var $t1: 0x42::m::Scalar + var $t2: 0x42::m::Scalar + var $t3: &mut u8 + var $t4: &mut vector + var $t5: &mut 0x42::m::Scalar + var $t6: u64 + # live vars: $t0 + 0: $t2 := m::scalar_zero() + # live vars: $t0, $t2 + 1: $t5 := borrow_local($t2) + # live vars: $t0, $t2, $t5 + 2: $t4 := borrow_field<0x42::m::Scalar>.data($t5) + # live vars: $t0, $t2, $t4 + 3: $t6 := 0 + # live vars: $t0, $t2, $t4, $t6 + 4: $t3 := vector::borrow_mut($t4, $t6) + # live vars: $t0, $t2, $t3 + 5: write_ref($t3, $t0) + # live vars: $t2 + 6: $t1 := move($t2) + # live vars: $t1 + 7: return $t1 +} + + +[variant baseline] +public fun m::scalar_zero(): 0x42::m::Scalar { + var $t0: 0x42::m::Scalar + var $t1: vector + # live vars: + 0: $t1 := [0] + # live vars: $t1 + 1: $t0 := pack 0x42::m::Scalar($t1) + # live vars: $t0 + 2: return $t0 +} + + +============ disassembled file-format ================== +// Move bytecode v7 +module 42.m { +struct Scalar has copy, drop, store { + data: vector +} + +public new_scalar_from_u8(Arg0: u8): Scalar /* def_idx: 0 */ { +L1: loc0: Scalar +L2: loc1: &mut u8 +B0: + 0: Call scalar_zero(): Scalar + 1: StLoc[1](loc0: Scalar) + 2: MutBorrowLoc[1](loc0: Scalar) + 3: MutBorrowField[0](Scalar.data: vector) + 4: LdU64(0) + 5: VecMutBorrow(0) + 6: StLoc[2](loc1: &mut u8) + 7: MoveLoc[0](Arg0: u8) + 8: MoveLoc[2](loc1: &mut u8) + 9: WriteRef + 10: MoveLoc[1](loc0: Scalar) + 11: Ret +} +public scalar_zero(): Scalar /* def_idx: 1 */ { +B0: + 0: LdConst[0](Vector(U8): [1, 0]) + 1: Pack[0](Scalar) + 2: Ret +} +} +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/assign.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/assign.exp index 19a38d4478a92..68478954e23e8 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/assign.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/assign.exp @@ -73,10 +73,12 @@ fun assign::assign_int($t0: &mut u64) { fun assign::assign_pattern($t0: 0x42::assign::S, $t1: u64, $t2: u64): u64 { var $t3: u64 var $t4: 0x42::assign::T + var $t5: u64 0: ($t1, $t4) := unpack 0x42::assign::S($t0) 1: $t2 := unpack 0x42::assign::T($t4) - 2: $t3 := +($t1, $t2) - 3: return $t3 + 2: $t5 := infer($t1) + 3: $t3 := +($t5, $t2) + 4: return $t3 } @@ -95,4 +97,52 @@ fun assign::assign_struct($t0: &mut 0x42::assign::S) { } +============ disassembled file-format ================== +// Move bytecode v7 +module 42.assign { +struct T has drop { + h: u64 +} +struct S has drop { + f: u64, + g: T +} + +assign_field(Arg0: &mut S, Arg1: u64) /* def_idx: 0 */ { +L2: loc0: &mut u64 +B0: + 0: MoveLoc[0](Arg0: &mut S) + 1: MutBorrowField[0](S.f: u64) + 2: StLoc[2](loc0: &mut u64) + 3: MoveLoc[1](Arg1: u64) + 4: MoveLoc[2](loc0: &mut u64) + 5: WriteRef + 6: Ret +} +assign_int(Arg0: &mut u64) /* def_idx: 1 */ { +B0: + 0: LdU64(42) + 1: MoveLoc[0](Arg0: &mut u64) + 2: WriteRef + 3: Ret +} +assign_pattern(Arg0: S, Arg1: u64, Arg2: u64): u64 /* def_idx: 2 */ { +B0: + 0: MoveLoc[0](Arg0: S) + 1: Unpack[1](S) + 2: Unpack[0](T) + 3: Add + 4: Ret +} +assign_struct(Arg0: &mut S) /* def_idx: 3 */ { +B0: + 0: LdU64(42) + 1: LdU64(42) + 2: Pack[0](T) + 3: Pack[1](S) + 4: MoveLoc[0](Arg0: &mut S) + 5: WriteRef + 6: Ret +} +} ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/assign_inline.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/assign_inline.exp index 4a09468c4d890..5cd8580b46bb1 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/assign_inline.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/assign_inline.exp @@ -30,4 +30,16 @@ public fun assign::main(): (u64, u64) { } +============ disassembled file-format ================== +// Move bytecode v7 +module 42.assign { + + +public main(): u64 * u64 /* def_idx: 0 */ { +B0: + 0: LdU64(1) + 1: LdU64(3) + 2: Ret +} +} ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/borrow.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/borrow.exp index 2ede6b56aa928..cd348d9e72963 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/borrow.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/borrow.exp @@ -171,4 +171,74 @@ fun borrow::mut_param($t0: u64): u64 { } +============ disassembled file-format ================== +// Move bytecode v7 +module 42.borrow { +struct S { + f: u64 +} + +field(Arg0: &S): u64 /* def_idx: 0 */ { +B0: + 0: MoveLoc[0](Arg0: &S) + 1: ImmBorrowField[0](S.f: u64) + 2: ReadRef + 3: Ret +} +local(Arg0: u64): u64 /* def_idx: 1 */ { +L1: loc0: u64 +B0: + 0: LdU64(33) + 1: StLoc[1](loc0: u64) + 2: ImmBorrowLoc[1](loc0: u64) + 3: ReadRef + 4: Ret +} +param(Arg0: u64): u64 /* def_idx: 2 */ { +B0: + 0: ImmBorrowLoc[0](Arg0: u64) + 1: ReadRef + 2: Ret +} +mut_field(Arg0: &mut S): u64 /* def_idx: 3 */ { +L1: loc0: &mut u64 +B0: + 0: MoveLoc[0](Arg0: &mut S) + 1: MutBorrowField[0](S.f: u64) + 2: StLoc[1](loc0: &mut u64) + 3: LdU64(22) + 4: CopyLoc[1](loc0: &mut u64) + 5: WriteRef + 6: MoveLoc[1](loc0: &mut u64) + 7: ReadRef + 8: Ret +} +mut_local(Arg0: u64): u64 /* def_idx: 4 */ { +L1: loc0: u64 +L2: loc1: &mut u64 +B0: + 0: LdU64(33) + 1: StLoc[1](loc0: u64) + 2: MutBorrowLoc[1](loc0: u64) + 3: StLoc[2](loc1: &mut u64) + 4: LdU64(22) + 5: CopyLoc[2](loc1: &mut u64) + 6: WriteRef + 7: MoveLoc[2](loc1: &mut u64) + 8: ReadRef + 9: Ret +} +mut_param(Arg0: u64): u64 /* def_idx: 5 */ { +L1: loc0: &mut u64 +B0: + 0: MutBorrowLoc[0](Arg0: u64) + 1: StLoc[1](loc0: &mut u64) + 2: LdU64(22) + 3: CopyLoc[1](loc0: &mut u64) + 4: WriteRef + 5: MoveLoc[1](loc0: &mut u64) + 6: ReadRef + 7: Ret +} +} ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/borrow_deref_optimize.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/borrow_deref_optimize.exp index bc23929966e0e..21034a034b38a 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/borrow_deref_optimize.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/borrow_deref_optimize.exp @@ -140,4 +140,64 @@ fun test::optimize_vector() { } +============ disassembled file-format ================== +// Move bytecode v7 +module 42.test { +struct X has copy, drop, key { + value: bool +} + +no_optimize_resource(): bool /* def_idx: 0 */ { +L0: loc0: X +B0: + 0: LdConst[0](Address: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]) + 1: ImmBorrowGlobal[0](X) + 2: ReadRef + 3: StLoc[0](loc0: X) + 4: MutBorrowLoc[0](loc0: X) + 5: ImmBorrowField[0](X.value: bool) + 6: ReadRef + 7: Ret +} +no_optimize_vector() /* def_idx: 1 */ { +L0: loc0: vector> +L1: loc1: vector +L2: loc2: &mut u64 +B0: + 0: LdConst[1](Vector(Vector(U64)): [1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0]) + 1: StLoc[0](loc0: vector>) + 2: ImmBorrowLoc[0](loc0: vector>) + 3: LdU64(0) + 4: VecImmBorrow(3) + 5: ReadRef + 6: StLoc[1](loc1: vector) + 7: MutBorrowLoc[1](loc1: vector) + 8: LdU64(1) + 9: VecMutBorrow(4) + 10: Pop + 11: Ret +} +optimize_resource(): bool /* def_idx: 2 */ { +B0: + 0: LdConst[0](Address: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]) + 1: ImmBorrowGlobal[0](X) + 2: ImmBorrowField[0](X.value: bool) + 3: ReadRef + 4: Ret +} +optimize_vector() /* def_idx: 3 */ { +L0: loc0: vector> +L1: loc1: &mut u64 +B0: + 0: LdConst[1](Vector(Vector(U64)): [1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0]) + 1: StLoc[0](loc0: vector>) + 2: MutBorrowLoc[0](loc0: vector>) + 3: LdU64(0) + 4: VecMutBorrow(3) + 5: LdU64(1) + 6: VecMutBorrow(4) + 7: Pop + 8: Ret +} +} ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/bug_14300_update_variant_select.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/bug_14300_update_variant_select.exp index e81fbf75afa73..19090c4f6c297 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/bug_14300_update_variant_select.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/bug_14300_update_variant_select.exp @@ -179,4 +179,125 @@ fun m::update_non_common_field(): u32 { } +============ disassembled file-format ================== +// Move bytecode v7 +module 815.m { +enum CommonFields has drop { + Foo{ + x: u64, + y: u8 + }, + Bar{ + x: u64, + y: u8, + z: u32 + }, + Baz{ + y: u8 + } +} + +update_common_field(): u64 /* def_idx: 0 */ { +L0: loc0: CommonFields +B0: + 0: LdU64(30) + 1: LdU8(40) + 2: LdU32(50) + 3: PackVariant[0](CommonFields/Bar) + 4: StLoc[0](loc0: CommonFields) + 5: LdU64(15) + 6: MutBorrowLoc[0](loc0: CommonFields) + 7: MutBorrowVariantField[0](Foo.x|Bar.x: u64) + 8: WriteRef + 9: ImmBorrowLoc[0](loc0: CommonFields) + 10: ImmBorrowVariantField[0](Foo.x|Bar.x: u64) + 11: ReadRef + 12: Ret +} +update_common_field_different_offset(): u8 /* def_idx: 1 */ { +L0: loc0: CommonFields +L1: loc1: u8 +L2: loc2: &mut CommonFields +L3: loc3: &mut u8 +L4: loc4: &CommonFields +L5: loc5: &u8 +B0: + 0: LdU64(30) + 1: LdU8(40) + 2: LdU32(50) + 3: PackVariant[0](CommonFields/Bar) + 4: StLoc[0](loc0: CommonFields) + 5: LdU8(15) + 6: StLoc[1](loc1: u8) + 7: MutBorrowLoc[0](loc0: CommonFields) + 8: StLoc[2](loc2: &mut CommonFields) + 9: CopyLoc[2](loc2: &mut CommonFields) + 10: TestVariant[1](CommonFields/Foo) + 11: BrFalse(39) +B1: + 12: Branch(13) +B2: + 13: MoveLoc[2](loc2: &mut CommonFields) + 14: MutBorrowVariantField[1](Foo.y|Bar.y: u8) + 15: StLoc[3](loc3: &mut u8) +B3: + 16: MoveLoc[1](loc1: u8) + 17: MoveLoc[3](loc3: &mut u8) + 18: WriteRef + 19: ImmBorrowLoc[0](loc0: CommonFields) + 20: StLoc[4](loc4: &CommonFields) + 21: CopyLoc[4](loc4: &CommonFields) + 22: TestVariant[1](CommonFields/Foo) + 23: BrFalse(31) +B4: + 24: Branch(25) +B5: + 25: MoveLoc[4](loc4: &CommonFields) + 26: ImmBorrowVariantField[1](Foo.y|Bar.y: u8) + 27: StLoc[5](loc5: &u8) +B6: + 28: MoveLoc[5](loc5: &u8) + 29: ReadRef + 30: Ret +B7: + 31: CopyLoc[4](loc4: &CommonFields) + 32: TestVariant[0](CommonFields/Bar) + 33: BrFalse(35) +B8: + 34: Branch(25) +B9: + 35: MoveLoc[4](loc4: &CommonFields) + 36: ImmBorrowVariantField[2](Baz.y: u8) + 37: StLoc[5](loc5: &u8) + 38: Branch(28) +B10: + 39: CopyLoc[2](loc2: &mut CommonFields) + 40: TestVariant[0](CommonFields/Bar) + 41: BrFalse(43) +B11: + 42: Branch(13) +B12: + 43: MoveLoc[2](loc2: &mut CommonFields) + 44: MutBorrowVariantField[2](Baz.y: u8) + 45: StLoc[3](loc3: &mut u8) + 46: Branch(16) +} +update_non_common_field(): u32 /* def_idx: 2 */ { +L0: loc0: CommonFields +B0: + 0: LdU64(30) + 1: LdU8(40) + 2: LdU32(50) + 3: PackVariant[0](CommonFields/Bar) + 4: StLoc[0](loc0: CommonFields) + 5: LdU32(15) + 6: MutBorrowLoc[0](loc0: CommonFields) + 7: MutBorrowVariantField[3](Bar.z: u32) + 8: WriteRef + 9: ImmBorrowLoc[0](loc0: CommonFields) + 10: ImmBorrowVariantField[3](Bar.z: u32) + 11: ReadRef + 12: Ret +} +} ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/bug_14300_variant_select_autoref.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/bug_14300_variant_select_autoref.exp index c26adc0db393d..fc0bec82c9031 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/bug_14300_variant_select_autoref.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/bug_14300_variant_select_autoref.exp @@ -55,4 +55,30 @@ fun m::test_common_access(): u8 { } +============ disassembled file-format ================== +// Move bytecode v7 +module 815.m { +enum Positional has drop { + A{ + _0: u8 + }, + B{ + _0: u8 + } +} + +test_common_access(): u8 /* def_idx: 0 */ { +L0: loc0: Positional +B0: + 0: LdU8(42) + 1: PackVariant[0](Positional/A) + 2: StLoc[0](loc0: Positional) + 3: LdU8(19) + 4: MutBorrowLoc[0](loc0: Positional) + 5: MutBorrowVariantField[0](A._0|B._0: u8) + 6: WriteRef + 7: LdU8(20) + 8: Ret +} +} ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/bug_14471_receiver_inference.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/bug_14471_receiver_inference.exp index 693daacb1ff71..12e828b0b7a36 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/bug_14471_receiver_inference.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/bug_14471_receiver_inference.exp @@ -87,21 +87,79 @@ public fun m::add_when_missing($t0: address, $t1: u64) { var $t6: &0x815::m::Table var $t7: 0x815::m::ValueWrap var $t8: &mut 0x815::m::Table + var $t9: address 0: $t3 := 0x815 1: $t2 := borrow_global<0x815::m::MyMap>($t3) 2: $t6 := borrow_field<0x815::m::MyMap>.table($t2) 3: $t5 := m::contains($t6, $t0) 4: $t4 := !($t5) - 5: if ($t4) goto 6 else goto 11 + 5: if ($t4) goto 6 else goto 12 6: label L0 7: $t7 := pack 0x815::m::ValueWrap($t1) 8: $t8 := borrow_field<0x815::m::MyMap>.table($t2) - 9: m::add($t8, $t0, $t7) - 10: goto 12 - 11: label L1 - 12: label L2 - 13: return () + 9: $t9 := infer($t0) + 10: m::add($t8, $t9, $t7) + 11: goto 13 + 12: label L1 + 13: label L2 + 14: return () } +============ disassembled file-format ================== +// Move bytecode v7 +module 815.m { +struct MyMap has key { + table: Table +} +struct Table has store { + x: Ty0, + y: Ty1 +} +struct ValueWrap has drop, store { + val: u64 +} + +contains(Arg0: &Table, Arg1: Ty0): bool /* def_idx: 0 */ { +B0: + 0: LdTrue + 1: MoveLoc[0](Arg0: &Table) + 2: Pop + 3: Ret +} +add(Arg0: &mut Table, Arg1: Ty0, Arg2: Ty1) /* def_idx: 1 */ { +B0: + 0: MoveLoc[0](Arg0: &mut Table) + 1: Pop + 2: Ret +} +public add_when_missing(Arg0: address, Arg1: u64) /* def_idx: 2 */ { +L2: loc0: &mut MyMap +L3: loc1: ValueWrap +B0: + 0: LdConst[0](Address: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 21]) + 1: MutBorrowGlobal[0](MyMap) + 2: StLoc[2](loc0: &mut MyMap) + 3: CopyLoc[2](loc0: &mut MyMap) + 4: ImmBorrowField[0](MyMap.table: Table) + 5: CopyLoc[0](Arg0: address) + 6: Call contains(&Table, address): bool + 7: BrTrue(17) +B1: + 8: MoveLoc[1](Arg1: u64) + 9: Pack[2](ValueWrap) + 10: StLoc[3](loc1: ValueWrap) + 11: MoveLoc[2](loc0: &mut MyMap) + 12: MutBorrowField[0](MyMap.table: Table) + 13: MoveLoc[0](Arg0: address) + 14: MoveLoc[3](loc1: ValueWrap) + 15: Call add(&mut Table, address, ValueWrap) +B2: + 16: Ret +B3: + 17: MoveLoc[2](loc0: &mut MyMap) + 18: Pop + 19: Branch(16) +} +} ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/bug_14629.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/bug_14629.exp index 74202644fcec6..8c840d334cfe2 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/bug_14629.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/bug_14629.exp @@ -74,4 +74,33 @@ fun M::t0_u128() { } +============ disassembled file-format ================== +// Move bytecode v7 +module 8675309.M { +struct R { + r: Ty0 +} +struct X has drop, key { + r: Ty0 +} + +t0() /* def_idx: 0 */ { +B0: + 0: LdU64(0) + 1: PackGeneric[0](X) + 2: PackGeneric[1](R>) + 3: UnpackGeneric[1](R>) + 4: Pop + 5: Ret +} +t0_u128() /* def_idx: 1 */ { +B0: + 0: LdU128(18446744073709551616) + 1: PackGeneric[2](X) + 2: PackGeneric[3](R>) + 3: UnpackGeneric[3](R>) + 4: Pop + 5: Ret +} +} ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/conditional_borrow.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/conditional_borrow.exp index 2e4693e518bd7..6d359a9b8806a 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/conditional_borrow.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/conditional_borrow.exp @@ -179,82 +179,86 @@ fun M::test1($t0: u64): u64 { var $t5: u64 var $t6: u64 var $t7: u64 - var $t8: &mut u64 - var $t9: u64 + var $t8: u64 + var $t9: &mut u64 var $t10: u64 var $t11: u64 var $t12: u64 - var $t13: &mut u64 - var $t14: u64 + var $t13: u64 + var $t14: &mut u64 var $t15: u64 var $t16: u64 var $t17: u64 var $t18: u64 var $t19: u64 - var $t20: &mut u64 + var $t20: u64 var $t21: u64 - var $t22: u64 + var $t22: &mut u64 var $t23: u64 var $t24: u64 - var $t25: &mut u64 + var $t25: u64 var $t26: u64 - var $t27: u64 + var $t27: &mut u64 var $t28: u64 var $t29: u64 - var $t30: &mut u64 + var $t30: u64 var $t31: u64 - var $t32: u64 + var $t32: &mut u64 var $t33: u64 var $t34: u64 var $t35: u64 - 0: $t5 := 4 - 1: $t4 := <($t0, $t5) - 2: if ($t4) goto 3 else goto 6 - 3: label L0 - 4: $t3 := infer($t0) - 5: goto 8 - 6: label L1 - 7: $t3 := 3 - 8: label L2 - 9: $t2 := borrow_local($t3) - 10: $t6 := 10 - 11: write_ref($t2, $t6) - 12: $t7 := infer($t0) - 13: $t8 := borrow_local($t7) - 14: $t10 := read_ref($t8) - 15: $t11 := 1 - 16: $t9 := +($t10, $t11) - 17: write_ref($t8, $t9) - 18: $t12 := infer($t7) - 19: $t15 := 0 - 20: $t14 := +($t12, $t15) - 21: $t13 := borrow_local($t14) - 22: $t17 := read_ref($t13) - 23: $t18 := 2 - 24: $t16 := +($t17, $t18) - 25: write_ref($t13, $t16) - 26: $t19 := infer($t12) - 27: $t21 := infer($t19) - 28: $t20 := borrow_local($t21) - 29: $t23 := read_ref($t20) - 30: $t24 := 4 - 31: $t22 := +($t23, $t24) - 32: write_ref($t20, $t22) - 33: $t26 := infer($t19) - 34: $t25 := borrow_local($t26) - 35: $t28 := read_ref($t25) - 36: $t29 := 8 - 37: $t27 := +($t28, $t29) - 38: write_ref($t25, $t27) - 39: $t32 := 3 - 40: $t31 := infer($t19) - 41: $t30 := borrow_local($t31) - 42: $t34 := read_ref($t30) - 43: $t35 := 16 - 44: $t33 := +($t34, $t35) - 45: write_ref($t30, $t33) - 46: $t1 := infer($t19) - 47: return $t1 + var $t36: u64 + var $t37: u64 + 0: $t5 := infer($t0) + 1: $t6 := 4 + 2: $t4 := <($t5, $t6) + 3: if ($t4) goto 4 else goto 7 + 4: label L0 + 5: $t3 := infer($t0) + 6: goto 9 + 7: label L1 + 8: $t3 := 3 + 9: label L2 + 10: $t2 := borrow_local($t3) + 11: $t7 := 10 + 12: write_ref($t2, $t7) + 13: $t8 := infer($t0) + 14: $t9 := borrow_local($t8) + 15: $t11 := read_ref($t9) + 16: $t12 := 1 + 17: $t10 := +($t11, $t12) + 18: write_ref($t9, $t10) + 19: $t13 := infer($t8) + 20: $t16 := infer($t13) + 21: $t17 := 0 + 22: $t15 := +($t16, $t17) + 23: $t14 := borrow_local($t15) + 24: $t19 := read_ref($t14) + 25: $t20 := 2 + 26: $t18 := +($t19, $t20) + 27: write_ref($t14, $t18) + 28: $t21 := infer($t13) + 29: $t23 := infer($t21) + 30: $t22 := borrow_local($t23) + 31: $t25 := read_ref($t22) + 32: $t26 := 4 + 33: $t24 := +($t25, $t26) + 34: write_ref($t22, $t24) + 35: $t28 := infer($t21) + 36: $t27 := borrow_local($t28) + 37: $t30 := read_ref($t27) + 38: $t31 := 8 + 39: $t29 := +($t30, $t31) + 40: write_ref($t27, $t29) + 41: $t34 := 3 + 42: $t33 := infer($t21) + 43: $t32 := borrow_local($t33) + 44: $t36 := read_ref($t32) + 45: $t37 := 16 + 46: $t35 := +($t36, $t37) + 47: write_ref($t32, $t35) + 48: $t1 := infer($t21) + 49: return $t1 } @@ -408,4 +412,229 @@ public fun M::testb(): u64 { } +============ disassembled file-format ================== +// Move bytecode v7 +module 8675.M { +struct S has copy, drop { + f: u64 +} + +public test(): u64 /* def_idx: 0 */ { +B0: + 0: LdU64(7) + 1: Call test1(u64): u64 + 2: LdU64(2) + 3: Call test1(u64): u64 + 4: Add + 5: Ret +} +test1(Arg0: u64): u64 /* def_idx: 1 */ { +L1: loc0: u64 +L2: loc1: &mut u64 +L3: loc2: u64 +L4: loc3: u64 +L5: loc4: u64 +L6: loc5: u64 +L7: loc6: u64 +L8: loc7: u64 +B0: + 0: CopyLoc[0](Arg0: u64) + 1: LdU64(4) + 2: Lt + 3: BrFalse(67) +B1: + 4: CopyLoc[0](Arg0: u64) + 5: StLoc[1](loc0: u64) +B2: + 6: MutBorrowLoc[1](loc0: u64) + 7: StLoc[2](loc1: &mut u64) + 8: LdU64(10) + 9: MoveLoc[2](loc1: &mut u64) + 10: WriteRef + 11: MoveLoc[0](Arg0: u64) + 12: StLoc[3](loc2: u64) + 13: MutBorrowLoc[3](loc2: u64) + 14: StLoc[2](loc1: &mut u64) + 15: CopyLoc[2](loc1: &mut u64) + 16: ReadRef + 17: LdU64(1) + 18: Add + 19: MoveLoc[2](loc1: &mut u64) + 20: WriteRef + 21: MoveLoc[3](loc2: u64) + 22: StLoc[4](loc3: u64) + 23: CopyLoc[4](loc3: u64) + 24: LdU64(0) + 25: Add + 26: StLoc[5](loc4: u64) + 27: MutBorrowLoc[5](loc4: u64) + 28: StLoc[2](loc1: &mut u64) + 29: CopyLoc[2](loc1: &mut u64) + 30: ReadRef + 31: LdU64(2) + 32: Add + 33: MoveLoc[2](loc1: &mut u64) + 34: WriteRef + 35: CopyLoc[4](loc3: u64) + 36: StLoc[6](loc5: u64) + 37: MutBorrowLoc[6](loc5: u64) + 38: StLoc[2](loc1: &mut u64) + 39: CopyLoc[2](loc1: &mut u64) + 40: ReadRef + 41: LdU64(4) + 42: Add + 43: MoveLoc[2](loc1: &mut u64) + 44: WriteRef + 45: CopyLoc[4](loc3: u64) + 46: StLoc[7](loc6: u64) + 47: MutBorrowLoc[7](loc6: u64) + 48: StLoc[2](loc1: &mut u64) + 49: CopyLoc[2](loc1: &mut u64) + 50: ReadRef + 51: LdU64(8) + 52: Add + 53: MoveLoc[2](loc1: &mut u64) + 54: WriteRef + 55: CopyLoc[4](loc3: u64) + 56: StLoc[8](loc7: u64) + 57: MutBorrowLoc[8](loc7: u64) + 58: StLoc[2](loc1: &mut u64) + 59: CopyLoc[2](loc1: &mut u64) + 60: ReadRef + 61: LdU64(16) + 62: Add + 63: MoveLoc[2](loc1: &mut u64) + 64: WriteRef + 65: MoveLoc[4](loc3: u64) + 66: Ret +B3: + 67: LdU64(3) + 68: StLoc[1](loc0: u64) + 69: Branch(6) +} +test1b(Arg0: S): u64 /* def_idx: 2 */ { +L1: loc0: S +L2: loc1: S +L3: loc2: &mut S +L4: loc3: S +L5: loc4: S +L6: loc5: S +L7: loc6: S +L8: loc7: S +L9: loc8: &mut u64 +L10: loc9: S +L11: loc10: u64 +L12: loc11: u64 +L13: loc12: u64 +B0: + 0: LdU64(3) + 1: Pack[0](S) + 2: StLoc[1](loc0: S) + 3: ImmBorrowLoc[0](Arg0: S) + 4: ImmBorrowField[0](S.f: u64) + 5: ReadRef + 6: LdU64(4) + 7: Lt + 8: BrFalse(91) +B1: + 9: CopyLoc[0](Arg0: S) + 10: StLoc[2](loc1: S) +B2: + 11: MutBorrowLoc[2](loc1: S) + 12: StLoc[3](loc2: &mut S) + 13: LdU64(10) + 14: MoveLoc[3](loc2: &mut S) + 15: ReadRef + 16: StLoc[4](loc3: S) + 17: MutBorrowLoc[4](loc3: S) + 18: MutBorrowField[0](S.f: u64) + 19: WriteRef + 20: MoveLoc[0](Arg0: S) + 21: StLoc[5](loc4: S) + 22: MutBorrowLoc[5](loc4: S) + 23: StLoc[3](loc2: &mut S) + 24: CopyLoc[3](loc2: &mut S) + 25: ReadRef + 26: StLoc[6](loc5: S) + 27: ImmBorrowLoc[6](loc5: S) + 28: ImmBorrowField[0](S.f: u64) + 29: ReadRef + 30: LdU64(1) + 31: Add + 32: MoveLoc[3](loc2: &mut S) + 33: ReadRef + 34: StLoc[7](loc6: S) + 35: MutBorrowLoc[7](loc6: S) + 36: MutBorrowField[0](S.f: u64) + 37: WriteRef + 38: MoveLoc[5](loc4: S) + 39: StLoc[8](loc7: S) + 40: MutBorrowLoc[8](loc7: S) + 41: MutBorrowField[0](S.f: u64) + 42: StLoc[9](loc8: &mut u64) + 43: CopyLoc[9](loc8: &mut u64) + 44: ReadRef + 45: LdU64(1) + 46: Add + 47: MoveLoc[9](loc8: &mut u64) + 48: WriteRef + 49: MoveLoc[8](loc7: S) + 50: StLoc[10](loc9: S) + 51: ImmBorrowLoc[10](loc9: S) + 52: ImmBorrowField[0](S.f: u64) + 53: ReadRef + 54: StLoc[11](loc10: u64) + 55: MutBorrowLoc[11](loc10: u64) + 56: StLoc[9](loc8: &mut u64) + 57: CopyLoc[9](loc8: &mut u64) + 58: ReadRef + 59: LdU64(1) + 60: Add + 61: MoveLoc[9](loc8: &mut u64) + 62: WriteRef + 63: ImmBorrowLoc[10](loc9: S) + 64: ImmBorrowField[0](S.f: u64) + 65: ReadRef + 66: StLoc[12](loc11: u64) + 67: MutBorrowLoc[12](loc11: u64) + 68: StLoc[9](loc8: &mut u64) + 69: CopyLoc[9](loc8: &mut u64) + 70: ReadRef + 71: LdU64(8) + 72: Add + 73: MoveLoc[9](loc8: &mut u64) + 74: WriteRef + 75: ImmBorrowLoc[10](loc9: S) + 76: ImmBorrowField[0](S.f: u64) + 77: ReadRef + 78: StLoc[13](loc12: u64) + 79: MutBorrowLoc[13](loc12: u64) + 80: StLoc[9](loc8: &mut u64) + 81: CopyLoc[9](loc8: &mut u64) + 82: ReadRef + 83: LdU64(16) + 84: Add + 85: MoveLoc[9](loc8: &mut u64) + 86: WriteRef + 87: ImmBorrowLoc[10](loc9: S) + 88: ImmBorrowField[0](S.f: u64) + 89: ReadRef + 90: Ret +B3: + 91: MoveLoc[1](loc0: S) + 92: StLoc[2](loc1: S) + 93: Branch(11) +} +public testb(): u64 /* def_idx: 3 */ { +B0: + 0: LdU64(7) + 1: Pack[0](S) + 2: Call test1b(S): u64 + 3: LdU64(2) + 4: Pack[0](S) + 5: Call test1b(S): u64 + 6: Add + 7: Ret +} +} ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/escape_autoref.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/escape_autoref.exp index aae0dcbebfe42..023d9b8e57d10 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/escape_autoref.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/escape_autoref.exp @@ -116,4 +116,50 @@ fun m::will_autoref(): address { } +============ disassembled file-format ================== +// Move bytecode v7 +module 42.m { +struct Object has copy, drop { + inner: address +} +struct ObjectCore has key { + owner: address +} + +make(): Object /* def_idx: 0 */ { +B0: + 0: LdU64(0) + 1: Abort +} +owner_correct(Arg0: Object): address /* def_idx: 1 */ { +B0: + 0: ImmBorrowLoc[0](Arg0: Object) + 1: ImmBorrowField[0](Object.inner: address) + 2: ReadRef + 3: ImmBorrowGlobal[1](ObjectCore) + 4: ImmBorrowField[1](ObjectCore.owner: address) + 5: ReadRef + 6: Ret +} +owner_read_ref_missing(Arg0: Object): address /* def_idx: 2 */ { +B0: + 0: ImmBorrowLoc[0](Arg0: Object) + 1: ImmBorrowField[0](Object.inner: address) + 2: ReadRef + 3: ImmBorrowGlobal[1](ObjectCore) + 4: ImmBorrowField[1](ObjectCore.owner: address) + 5: ReadRef + 6: Ret +} +will_autoref(): address /* def_idx: 3 */ { +L0: loc0: Object +B0: + 0: Call make(): Object + 1: StLoc[0](loc0: Object) + 2: ImmBorrowLoc[0](loc0: Object) + 3: ImmBorrowField[0](Object.inner: address) + 4: ReadRef + 5: Ret +} +} ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/fields.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/fields.exp index 72ad2c417ca09..8fee7cb9bb152 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/fields.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/fields.exp @@ -263,4 +263,126 @@ fun fields::write_val($t0: 0x42::fields::S): 0x42::fields::S { } +============ disassembled file-format ================== +// Move bytecode v7 +module 42.fields { +struct T has drop { + h: u64 +} +struct G has drop { + f: Ty0 +} +struct S has drop { + f: u64, + g: T +} + +read_generic_val(Arg0: G): u64 /* def_idx: 0 */ { +B0: + 0: ImmBorrowLoc[0](Arg0: G) + 1: ImmBorrowFieldGeneric[0](G.f: Ty0) + 2: ReadRef + 3: Ret +} +read_ref(Arg0: &S): u64 /* def_idx: 1 */ { +B0: + 0: MoveLoc[0](Arg0: &S) + 1: ImmBorrowField[1](S.g: T) + 2: ImmBorrowField[2](T.h: u64) + 3: ReadRef + 4: Ret +} +read_val(Arg0: S): u64 /* def_idx: 2 */ { +B0: + 0: ImmBorrowLoc[0](Arg0: S) + 1: ImmBorrowField[1](S.g: T) + 2: ImmBorrowField[2](T.h: u64) + 3: ReadRef + 4: Ret +} +write_generic_val(Arg0: &mut G, Arg1: u64) /* def_idx: 3 */ { +L2: loc0: &mut u64 +B0: + 0: MoveLoc[0](Arg0: &mut G) + 1: MutBorrowFieldGeneric[0](G.f: Ty0) + 2: StLoc[2](loc0: &mut u64) + 3: MoveLoc[1](Arg1: u64) + 4: MoveLoc[2](loc0: &mut u64) + 5: WriteRef + 6: Ret +} +write_local_direct(): S /* def_idx: 4 */ { +L0: loc0: S +B0: + 0: LdU64(0) + 1: LdU64(0) + 2: Pack[0](T) + 3: Pack[2](S) + 4: StLoc[0](loc0: S) + 5: LdU64(42) + 6: MutBorrowLoc[0](loc0: S) + 7: MutBorrowField[1](S.g: T) + 8: MutBorrowField[2](T.h: u64) + 9: WriteRef + 10: MoveLoc[0](loc0: S) + 11: Ret +} +write_local_via_ref(): S /* def_idx: 5 */ { +L0: loc0: S +L1: loc1: &mut S +B0: + 0: LdU64(0) + 1: LdU64(0) + 2: Pack[0](T) + 3: Pack[2](S) + 4: StLoc[0](loc0: S) + 5: MutBorrowLoc[0](loc0: S) + 6: StLoc[1](loc1: &mut S) + 7: LdU64(42) + 8: MoveLoc[1](loc1: &mut S) + 9: MutBorrowField[1](S.g: T) + 10: MutBorrowField[2](T.h: u64) + 11: WriteRef + 12: MoveLoc[0](loc0: S) + 13: Ret +} +write_local_via_ref_2(): S /* def_idx: 6 */ { +L0: loc0: S +L1: loc1: &mut u64 +B0: + 0: LdU64(0) + 1: LdU64(0) + 2: Pack[0](T) + 3: Pack[2](S) + 4: StLoc[0](loc0: S) + 5: MutBorrowLoc[0](loc0: S) + 6: MutBorrowField[1](S.g: T) + 7: MutBorrowField[2](T.h: u64) + 8: StLoc[1](loc1: &mut u64) + 9: LdU64(42) + 10: MoveLoc[1](loc1: &mut u64) + 11: WriteRef + 12: MoveLoc[0](loc0: S) + 13: Ret +} +write_param(Arg0: &mut S) /* def_idx: 7 */ { +B0: + 0: LdU64(42) + 1: MoveLoc[0](Arg0: &mut S) + 2: MutBorrowField[1](S.g: T) + 3: MutBorrowField[2](T.h: u64) + 4: WriteRef + 5: Ret +} +write_val(Arg0: S): S /* def_idx: 8 */ { +B0: + 0: LdU64(42) + 1: MutBorrowLoc[0](Arg0: S) + 2: MutBorrowField[1](S.g: T) + 3: MutBorrowField[2](T.h: u64) + 4: WriteRef + 5: MoveLoc[0](Arg0: S) + 6: Ret +} +} ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/freeze_mut_ref.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/freeze_mut_ref.exp index cf24cf3290946..c6e038e4bb34f 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/freeze_mut_ref.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/freeze_mut_ref.exp @@ -174,11 +174,13 @@ module 0x42::freeze_mut_ref { public fun freeze_mut_ref::borrow_mut<#0>($t0: &mut vector<#0>): � { var $t1: � var $t2: &mut #0 - var $t3: u64 - 0: $t3 := 0 - 1: $t2 := vector::borrow_mut<#0>($t0, $t3) - 2: $t1 := freeze_ref(implicit)($t2) - 3: return $t1 + var $t3: &mut vector<#0> + var $t4: u64 + 0: $t3 := infer($t0) + 1: $t4 := 0 + 2: $t2 := vector::borrow_mut<#0>($t3, $t4) + 3: $t1 := freeze_ref(implicit)($t2) + 4: return $t1 } @@ -276,38 +278,42 @@ public fun freeze_mut_ref::t5($t0: &mut 0x42::freeze_mut_ref::G) { var $t3: &mut 0x42::freeze_mut_ref::G var $t4: u64 var $t5: u64 - var $t6: &mut u64 - var $t7: &mut 0x42::freeze_mut_ref::G - var $t8: u64 + var $t6: u64 + var $t7: &mut u64 + var $t8: &mut 0x42::freeze_mut_ref::G var $t9: u64 - var $t10: &mut u64 + var $t10: u64 var $t11: u64 - var $t12: &u64 + var $t12: &mut u64 var $t13: u64 - var $t14: &mut u64 + var $t14: &u64 var $t15: u64 - var $t16: &u64 + var $t16: &mut u64 + var $t17: u64 + var $t18: &u64 0: $t1 := 0 - 1: $t5 := 1 - 2: $t4 := +($t1, $t5) - 3: $t1 := infer($t4) - 4: $t3 := infer($t0) - 5: $t2 := borrow_field<0x42::freeze_mut_ref::G>.f($t3) - 6: $t9 := 1 - 7: $t8 := +($t1, $t9) - 8: $t1 := infer($t8) - 9: $t7 := infer($t0) - 10: $t6 := borrow_field<0x42::freeze_mut_ref::G>.f($t7) - 11: $t11 := 2 - 12: $t10 := borrow_local($t11) + 1: $t5 := infer($t1) + 2: $t6 := 1 + 3: $t4 := +($t5, $t6) + 4: $t1 := infer($t4) + 5: $t3 := infer($t0) + 6: $t2 := borrow_field<0x42::freeze_mut_ref::G>.f($t3) + 7: $t10 := infer($t1) + 8: $t11 := 1 + 9: $t9 := +($t10, $t11) + 10: $t1 := infer($t9) + 11: $t8 := infer($t0) + 12: $t7 := borrow_field<0x42::freeze_mut_ref::G>.f($t8) 13: $t13 := 2 - 14: $t15 := 0 - 15: write_ref($t2, $t15) - 16: $t16 := freeze_ref(implicit)($t10) - 17: $t12 := infer($t16) - 18: $t14 := infer($t6) - 19: write_ref($t14, $t13) - 20: return () + 14: $t12 := borrow_local($t13) + 15: $t15 := 2 + 16: $t17 := 0 + 17: write_ref($t2, $t17) + 18: $t18 := freeze_ref(implicit)($t12) + 19: $t14 := infer($t18) + 20: $t16 := infer($t7) + 21: write_ref($t16, $t15) + 22: return () } @@ -397,4 +403,193 @@ warning: Unused assignment to `x`. Consider removing or prefixing with an unders │ ^^^^^^^^^ +============ disassembled file-format ================== +// Move bytecode v7 +module 42.freeze_mut_ref { +struct G { + f: u64 +} +struct S has drop { + dummy_field: bool +} + +public borrow_mut(Arg0: &mut vector): &Ty0 /* def_idx: 0 */ { +B0: + 0: MoveLoc[0](Arg0: &mut vector) + 1: LdU64(0) + 2: VecMutBorrow(2) + 3: FreezeRef + 4: Ret +} +public borrow_mut2(Arg0: &mut Ty0): &Ty0 /* def_idx: 1 */ { +B0: + 0: MoveLoc[0](Arg0: &mut Ty0) + 1: FreezeRef + 2: Ret +} +public borrow_mut3(Arg0: &mut Ty0, Arg1: &Ty0): &Ty0 /* def_idx: 2 */ { +L2: loc0: &Ty0 +B0: + 0: MoveLoc[1](Arg1: &Ty0) + 1: Pop + 2: MoveLoc[0](Arg0: &mut Ty0) + 3: FreezeRef + 4: StLoc[2](loc0: &Ty0) +B1: + 5: MoveLoc[2](loc0: &Ty0) + 6: Ret +B2: + 7: MoveLoc[0](Arg0: &mut Ty0) + 8: Pop + 9: MoveLoc[1](Arg1: &Ty0) + 10: StLoc[2](loc0: &Ty0) + 11: Branch(5) +} +public borrow_mut4(Arg0: &mut Ty0): &Ty0 /* def_idx: 3 */ { +B0: + 0: MoveLoc[0](Arg0: &mut Ty0) + 1: FreezeRef + 2: Ret +} +t0() /* def_idx: 4 */ { +L0: loc0: u64 +L1: loc1: &u64 +B0: + 0: LdU64(0) + 1: StLoc[0](loc0: u64) + 2: MutBorrowLoc[0](loc0: u64) + 3: FreezeRef + 4: Pop + 5: Ret +} +t1(Arg0: &mut S): &S /* def_idx: 5 */ { +B0: + 0: MoveLoc[0](Arg0: &mut S) + 1: FreezeRef + 2: Ret +} +t2(Arg0: &mut u64, Arg1: &mut u64): &u64 * &mut u64 /* def_idx: 6 */ { +B0: + 0: MoveLoc[0](Arg0: &mut u64) + 1: FreezeRef + 2: MoveLoc[1](Arg1: &mut u64) + 3: Ret +} +public t4() /* def_idx: 7 */ { +L0: loc0: u64 +L1: loc1: &u64 +L2: loc2: u64 +B0: + 0: LdU64(0) + 1: StLoc[0](loc0: u64) + 2: MutBorrowLoc[0](loc0: u64) + 3: FreezeRef + 4: Pop + 5: LdU64(0) + 6: StLoc[2](loc2: u64) + 7: MutBorrowLoc[2](loc2: u64) + 8: FreezeRef + 9: Pop + 10: Ret +} +public t5(Arg0: &mut G) /* def_idx: 8 */ { +L1: loc0: &mut u64 +L2: loc1: &mut u64 +L3: loc2: u64 +L4: loc3: &mut u64 +L5: loc4: &u64 +B0: + 0: LdU64(0) + 1: LdU64(1) + 2: Add + 3: CopyLoc[0](Arg0: &mut G) + 4: MutBorrowField[0](G.f: u64) + 5: StLoc[1](loc0: &mut u64) + 6: LdU64(1) + 7: Add + 8: Pop + 9: MoveLoc[0](Arg0: &mut G) + 10: MutBorrowField[0](G.f: u64) + 11: StLoc[2](loc1: &mut u64) + 12: LdU64(2) + 13: StLoc[3](loc2: u64) + 14: MutBorrowLoc[3](loc2: u64) + 15: StLoc[4](loc3: &mut u64) + 16: LdU64(2) + 17: LdU64(0) + 18: MoveLoc[1](loc0: &mut u64) + 19: WriteRef + 20: MoveLoc[4](loc3: &mut u64) + 21: FreezeRef + 22: Pop + 23: MoveLoc[2](loc1: &mut u64) + 24: WriteRef + 25: Ret +} +t6(Arg0: bool, Arg1: &mut S, Arg2: &S) /* def_idx: 9 */ { +L3: loc0: &S +B0: + 0: MoveLoc[0](Arg0: bool) + 1: BrFalse(10) +B1: + 2: MoveLoc[2](Arg2: &S) + 3: Pop + 4: CopyLoc[1](Arg1: &mut S) + 5: MoveLoc[1](Arg1: &mut S) + 6: Pop + 7: FreezeRef + 8: Pop +B2: + 9: Ret +B3: + 10: MoveLoc[1](Arg1: &mut S) + 11: Pop + 12: MoveLoc[2](Arg2: &S) + 13: Pop + 14: Branch(9) +} +t7(Arg0: bool, Arg1: &mut S, Arg2: &S) /* def_idx: 10 */ { +L3: loc0: &S +L4: loc1: &S +B0: + 0: MoveLoc[0](Arg0: bool) + 1: BrFalse(10) +B1: + 2: MoveLoc[2](Arg2: &S) + 3: Pop + 4: MoveLoc[1](Arg1: &mut S) + 5: FreezeRef + 6: StLoc[3](loc0: &S) +B2: + 7: MoveLoc[3](loc0: &S) + 8: Pop + 9: Ret +B3: + 10: MoveLoc[1](Arg1: &mut S) + 11: Pop + 12: MoveLoc[2](Arg2: &S) + 13: StLoc[3](loc0: &S) + 14: Branch(7) +} +t8(Arg0: bool, Arg1: &mut S, Arg2: &S) /* def_idx: 11 */ { +L3: loc0: &S +B0: + 0: MoveLoc[0](Arg0: bool) + 1: BrFalse(8) +B1: + 2: MoveLoc[2](Arg2: &S) + 3: Pop + 4: MoveLoc[1](Arg1: &mut S) + 5: FreezeRef + 6: Pop +B2: + 7: Ret +B3: + 8: MoveLoc[1](Arg1: &mut S) + 9: Pop + 10: MoveLoc[2](Arg2: &S) + 11: Pop + 12: Branch(7) +} +} ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/globals.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/globals.exp index 58f17e58316dc..ee19b08313cc7 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/globals.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/globals.exp @@ -75,12 +75,14 @@ fun globals::check($t0: address): bool { [variant baseline] fun globals::publish($t0: &signer) { - var $t1: 0x42::globals::R - var $t2: u64 - 0: $t2 := 1 - 1: $t1 := pack 0x42::globals::R($t2) - 2: move_to<0x42::globals::R>($t0, $t1) - 3: return () + var $t1: &signer + var $t2: 0x42::globals::R + var $t3: u64 + 0: $t1 := infer($t0) + 1: $t3 := 1 + 2: $t2 := pack 0x42::globals::R($t3) + 3: move_to<0x42::globals::R>($t1, $t2) + 4: return () } @@ -111,4 +113,47 @@ fun globals::write($t0: address, $t1: u64): u64 { } +============ disassembled file-format ================== +// Move bytecode v7 +module 42.globals { +struct R has store, key { + f: u64 +} + +check(Arg0: address): bool /* def_idx: 0 */ { +B0: + 0: MoveLoc[0](Arg0: address) + 1: Exists[0](R) + 2: Ret +} +publish(Arg0: &signer) /* def_idx: 1 */ { +B0: + 0: MoveLoc[0](Arg0: &signer) + 1: LdU64(1) + 2: Pack[0](R) + 3: MoveTo[0](R) + 4: Ret +} +read(Arg0: address): u64 /* def_idx: 2 */ { +B0: + 0: MoveLoc[0](Arg0: address) + 1: ImmBorrowGlobal[0](R) + 2: ImmBorrowField[0](R.f: u64) + 3: ReadRef + 4: Ret +} +write(Arg0: address, Arg1: u64): u64 /* def_idx: 3 */ { +L2: loc0: &mut R +B0: + 0: MoveLoc[0](Arg0: address) + 1: MutBorrowGlobal[0](R) + 2: StLoc[2](loc0: &mut R) + 3: LdU64(2) + 4: MoveLoc[2](loc0: &mut R) + 5: MutBorrowField[0](R.f: u64) + 6: WriteRef + 7: LdU64(9) + 8: Ret +} +} ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/if_else.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/if_else.exp index a8faa766b2a7a..357a4135d110f 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/if_else.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/if_else.exp @@ -37,16 +37,20 @@ fun if_else::if_else($t0: bool, $t1: u64): u64 { var $t2: u64 var $t3: u64 var $t4: u64 - 0: if ($t0) goto 1 else goto 5 + var $t5: u64 + var $t6: u64 + 0: if ($t0) goto 1 else goto 6 1: label L0 - 2: $t3 := 1 - 3: $t2 := +($t1, $t3) - 4: goto 8 - 5: label L1 - 6: $t4 := 1 - 7: $t2 := -($t1, $t4) - 8: label L2 - 9: return $t2 + 2: $t3 := infer($t1) + 3: $t4 := 1 + 4: $t2 := +($t3, $t4) + 5: goto 10 + 6: label L1 + 7: $t5 := infer($t1) + 8: $t6 := 1 + 9: $t2 := -($t5, $t6) + 10: label L2 + 11: return $t2 } @@ -60,28 +64,99 @@ fun if_else::if_else_nested($t0: bool, $t1: u64): u64 { var $t7: u64 var $t8: u64 var $t9: u64 - 0: if ($t0) goto 1 else goto 5 + var $t10: u64 + var $t11: u64 + var $t12: u64 + var $t13: u64 + 0: if ($t0) goto 1 else goto 6 1: label L0 - 2: $t5 := 1 - 3: $t4 := +($t1, $t5) - 4: goto 8 - 5: label L1 - 6: $t6 := 1 - 7: $t4 := -($t1, $t6) - 8: label L2 - 9: $t7 := 10 - 10: $t3 := >($t4, $t7) - 11: if ($t3) goto 12 else goto 16 - 12: label L3 - 13: $t8 := 2 - 14: $t2 := *($t1, $t8) - 15: goto 19 - 16: label L4 - 17: $t9 := 2 - 18: $t2 := /($t1, $t9) - 19: label L5 - 20: return $t2 + 2: $t5 := infer($t1) + 3: $t6 := 1 + 4: $t4 := +($t5, $t6) + 5: goto 10 + 6: label L1 + 7: $t7 := infer($t1) + 8: $t8 := 1 + 9: $t4 := -($t7, $t8) + 10: label L2 + 11: $t9 := 10 + 12: $t3 := >($t4, $t9) + 13: if ($t3) goto 14 else goto 19 + 14: label L3 + 15: $t10 := infer($t1) + 16: $t11 := 2 + 17: $t2 := *($t10, $t11) + 18: goto 23 + 19: label L4 + 20: $t12 := infer($t1) + 21: $t13 := 2 + 22: $t2 := /($t12, $t13) + 23: label L5 + 24: return $t2 } +============ disassembled file-format ================== +// Move bytecode v7 +module 42.if_else { + + +if_else(Arg0: bool, Arg1: u64): u64 /* def_idx: 0 */ { +L2: loc0: u64 +B0: + 0: MoveLoc[0](Arg0: bool) + 1: BrFalse(8) +B1: + 2: MoveLoc[1](Arg1: u64) + 3: LdU64(1) + 4: Add + 5: StLoc[2](loc0: u64) +B2: + 6: MoveLoc[2](loc0: u64) + 7: Ret +B3: + 8: MoveLoc[1](Arg1: u64) + 9: LdU64(1) + 10: Sub + 11: StLoc[2](loc0: u64) + 12: Branch(6) +} +if_else_nested(Arg0: bool, Arg1: u64): u64 /* def_idx: 1 */ { +L2: loc0: u64 +L3: loc1: u64 +B0: + 0: MoveLoc[0](Arg0: bool) + 1: BrFalse(21) +B1: + 2: CopyLoc[1](Arg1: u64) + 3: LdU64(1) + 4: Add + 5: StLoc[2](loc0: u64) +B2: + 6: MoveLoc[2](loc0: u64) + 7: LdU64(10) + 8: Gt + 9: BrFalse(16) +B3: + 10: MoveLoc[1](Arg1: u64) + 11: LdU64(2) + 12: Mul + 13: StLoc[3](loc1: u64) +B4: + 14: MoveLoc[3](loc1: u64) + 15: Ret +B5: + 16: MoveLoc[1](Arg1: u64) + 17: LdU64(2) + 18: Div + 19: StLoc[3](loc1: u64) + 20: Branch(14) +B6: + 21: CopyLoc[1](Arg1: u64) + 22: LdU64(1) + 23: Sub + 24: StLoc[2](loc0: u64) + 25: Branch(6) +} +} ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/inline_specs.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/inline_specs.exp index 2f77eb1351425..0901c91cacf7a 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/inline_specs.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/inline_specs.exp @@ -71,10 +71,38 @@ fun inline_specs::specs(): u64 { fun inline_specs::succ($t0: u64): u64 { var $t1: u64 var $t2: u64 - 0: $t2 := 1 - 1: $t1 := +($t0, $t2) - 2: return $t1 + var $t3: u64 + 0: $t2 := infer($t0) + 1: $t3 := 1 + 2: $t1 := +($t2, $t3) + 3: return $t1 } +============ disassembled file-format ================== +// Move bytecode v7 +module 42.inline_specs { + + +specs(): u64 /* def_idx: 0 */ { +L0: loc0: u64 +B0: + 0: LdU64(0) + 1: StLoc[0](loc0: u64) + 2: Nop + 3: MoveLoc[0](loc0: u64) + 4: Call succ(u64): u64 + 5: StLoc[0](loc0: u64) + 6: Nop + 7: MoveLoc[0](loc0: u64) + 8: Ret +} +succ(Arg0: u64): u64 /* def_idx: 1 */ { +B0: + 0: MoveLoc[0](Arg0: u64) + 1: LdU64(1) + 2: Add + 3: Ret +} +} ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/loop.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/loop.exp index 85bca4397bfc9..a203d708b09bd 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/loop.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/loop.exp @@ -91,44 +91,52 @@ fun loops::nested_loop($t0: u64): u64 { var $t1: u64 var $t2: bool var $t3: u64 - var $t4: bool - var $t5: u64 + var $t4: u64 + var $t5: bool var $t6: u64 var $t7: u64 var $t8: u64 var $t9: u64 + var $t10: u64 + var $t11: u64 + var $t12: u64 + var $t13: u64 0: label L0 - 1: $t3 := 0 - 2: $t2 := >($t0, $t3) - 3: if ($t2) goto 4 else goto 25 - 4: label L2 - 5: label L5 - 6: $t5 := 10 - 7: $t4 := >($t0, $t5) - 8: if ($t4) goto 9 else goto 15 - 9: label L7 - 10: $t7 := 1 - 11: $t6 := -($t0, $t7) - 12: $t0 := infer($t6) - 13: goto 19 - 14: goto 17 - 15: label L8 - 16: goto 19 - 17: label L9 - 18: goto 5 - 19: label L6 - 20: $t9 := 1 - 21: $t8 := -($t0, $t9) - 22: $t0 := infer($t8) - 23: goto 0 - 24: goto 27 - 25: label L3 - 26: goto 29 - 27: label L4 - 28: goto 0 - 29: label L1 - 30: $t1 := infer($t0) - 31: return $t1 + 1: $t3 := infer($t0) + 2: $t4 := 0 + 3: $t2 := >($t3, $t4) + 4: if ($t2) goto 5 else goto 29 + 5: label L2 + 6: label L5 + 7: $t6 := infer($t0) + 8: $t7 := 10 + 9: $t5 := >($t6, $t7) + 10: if ($t5) goto 11 else goto 18 + 11: label L7 + 12: $t9 := infer($t0) + 13: $t10 := 1 + 14: $t8 := -($t9, $t10) + 15: $t0 := infer($t8) + 16: goto 22 + 17: goto 20 + 18: label L8 + 19: goto 22 + 20: label L9 + 21: goto 6 + 22: label L6 + 23: $t12 := infer($t0) + 24: $t13 := 1 + 25: $t11 := -($t12, $t13) + 26: $t0 := infer($t11) + 27: goto 0 + 28: goto 31 + 29: label L3 + 30: goto 33 + 31: label L4 + 32: goto 0 + 33: label L1 + 34: $t1 := infer($t0) + 35: return $t1 } @@ -139,22 +147,26 @@ fun loops::while_loop($t0: u64): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 + var $t7: u64 0: label L0 - 1: $t3 := 0 - 2: $t2 := >($t0, $t3) - 3: if ($t2) goto 4 else goto 9 - 4: label L2 - 5: $t5 := 1 - 6: $t4 := -($t0, $t5) - 7: $t0 := infer($t4) - 8: goto 11 - 9: label L3 + 1: $t3 := infer($t0) + 2: $t4 := 0 + 3: $t2 := >($t3, $t4) + 4: if ($t2) goto 5 else goto 11 + 5: label L2 + 6: $t6 := infer($t0) + 7: $t7 := 1 + 8: $t5 := -($t6, $t7) + 9: $t0 := infer($t5) 10: goto 13 - 11: label L4 - 12: goto 0 - 13: label L1 - 14: $t1 := infer($t0) - 15: return $t1 + 11: label L3 + 12: goto 15 + 13: label L4 + 14: goto 0 + 15: label L1 + 16: $t1 := infer($t0) + 17: return $t1 } @@ -163,45 +175,135 @@ fun loops::while_loop_with_break_and_continue($t0: u64): u64 { var $t1: u64 var $t2: bool var $t3: u64 - var $t4: bool - var $t5: u64 - var $t6: bool + var $t4: u64 + var $t5: bool + var $t6: u64 var $t7: u64 - var $t8: u64 + var $t8: bool var $t9: u64 + var $t10: u64 + var $t11: u64 + var $t12: u64 + var $t13: u64 0: label L0 - 1: $t3 := 0 - 2: $t2 := >($t0, $t3) - 3: if ($t2) goto 4 else goto 25 - 4: label L2 - 5: $t5 := 42 - 6: $t4 := ==($t0, $t5) - 7: if ($t4) goto 8 else goto 11 - 8: label L5 - 9: goto 29 - 10: goto 12 - 11: label L6 - 12: label L7 - 13: $t7 := 21 - 14: $t6 := ==($t0, $t7) - 15: if ($t6) goto 16 else goto 19 - 16: label L8 - 17: goto 0 - 18: goto 20 - 19: label L9 - 20: label L10 - 21: $t9 := 1 - 22: $t8 := -($t0, $t9) - 23: $t0 := infer($t8) - 24: goto 27 - 25: label L3 - 26: goto 29 - 27: label L4 - 28: goto 0 - 29: label L1 - 30: $t1 := infer($t0) - 31: return $t1 + 1: $t3 := infer($t0) + 2: $t4 := 0 + 3: $t2 := >($t3, $t4) + 4: if ($t2) goto 5 else goto 29 + 5: label L2 + 6: $t6 := infer($t0) + 7: $t7 := 42 + 8: $t5 := ==($t6, $t7) + 9: if ($t5) goto 10 else goto 13 + 10: label L5 + 11: goto 33 + 12: goto 14 + 13: label L6 + 14: label L7 + 15: $t9 := infer($t0) + 16: $t10 := 21 + 17: $t8 := ==($t9, $t10) + 18: if ($t8) goto 19 else goto 22 + 19: label L8 + 20: goto 0 + 21: goto 23 + 22: label L9 + 23: label L10 + 24: $t12 := infer($t0) + 25: $t13 := 1 + 26: $t11 := -($t12, $t13) + 27: $t0 := infer($t11) + 28: goto 31 + 29: label L3 + 30: goto 33 + 31: label L4 + 32: goto 0 + 33: label L1 + 34: $t1 := infer($t0) + 35: return $t1 } +============ disassembled file-format ================== +// Move bytecode v7 +module 42.loops { + + +nested_loop(Arg0: u64): u64 /* def_idx: 0 */ { +B0: + 0: CopyLoc[0](Arg0: u64) + 1: LdU64(0) + 2: Gt + 3: BrFalse(18) +B1: + 4: CopyLoc[0](Arg0: u64) + 5: LdU64(10) + 6: Gt + 7: BrTrue(9) +B2: + 8: Branch(13) +B3: + 9: MoveLoc[0](Arg0: u64) + 10: LdU64(1) + 11: Sub + 12: StLoc[0](Arg0: u64) +B4: + 13: MoveLoc[0](Arg0: u64) + 14: LdU64(1) + 15: Sub + 16: StLoc[0](Arg0: u64) + 17: Branch(0) +B5: + 18: MoveLoc[0](Arg0: u64) + 19: Ret +} +while_loop(Arg0: u64): u64 /* def_idx: 1 */ { +B0: + 0: CopyLoc[0](Arg0: u64) + 1: LdU64(0) + 2: Gt + 3: BrFalse(9) +B1: + 4: MoveLoc[0](Arg0: u64) + 5: LdU64(1) + 6: Sub + 7: StLoc[0](Arg0: u64) + 8: Branch(0) +B2: + 9: MoveLoc[0](Arg0: u64) + 10: Ret +} +while_loop_with_break_and_continue(Arg0: u64): u64 /* def_idx: 2 */ { +B0: + 0: CopyLoc[0](Arg0: u64) + 1: LdU64(0) + 2: Gt + 3: BrTrue(5) +B1: + 4: Branch(10) +B2: + 5: CopyLoc[0](Arg0: u64) + 6: LdU64(42) + 7: Eq + 8: BrFalse(12) +B3: + 9: Branch(10) +B4: + 10: MoveLoc[0](Arg0: u64) + 11: Ret +B5: + 12: CopyLoc[0](Arg0: u64) + 13: LdU64(21) + 14: Eq + 15: BrFalse(17) +B6: + 16: Branch(0) +B7: + 17: MoveLoc[0](Arg0: u64) + 18: LdU64(1) + 19: Sub + 20: StLoc[0](Arg0: u64) + 21: Branch(0) +} +} ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/loop_labels.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/loop_labels.exp index 247f1e144dfdb..89bd08ec9c7b6 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/loop_labels.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/loop_labels.exp @@ -75,4 +75,18 @@ fun test::f1() { } +============ disassembled file-format ================== +// Move bytecode v7 +module 815.test { + + +f1() /* def_idx: 0 */ { +B0: + 0: Branch(2) +B1: + 1: Branch(0) +B2: + 2: Branch(0) +} +} ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/matching_ok.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/matching_ok.exp index 0e40ef6056174..a4fda769f9cbd 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/matching_ok.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/matching_ok.exp @@ -347,25 +347,27 @@ public fun m::inner_value($t0: 0xc0ffee::m::Inner): u64 { var $t5: u64 var $t6: u64 var $t7: u64 + var $t8: u64 0: $t2 := borrow_local($t0) 1: $t3 := test_variant 0xc0ffee::m::Inner::Inner1($t2) 2: if ($t3) goto 3 else goto 7 3: label L2 4: $t4 := unpack_variant 0xc0ffee::m::Inner::Inner1($t0) 5: $t1 := infer($t4) - 6: goto 17 + 6: goto 18 7: label L1 8: $t3 := test_variant 0xc0ffee::m::Inner::Inner2($t2) - 9: if ($t3) goto 10 else goto 14 + 9: if ($t3) goto 10 else goto 15 10: label L4 11: ($t5, $t6) := unpack_variant 0xc0ffee::m::Inner::Inner2($t0) - 12: $t1 := +($t5, $t6) - 13: goto 17 - 14: label L3 - 15: $t7 := 14566554180833181697 - 16: abort($t7) - 17: label L0 - 18: return $t1 + 12: $t7 := infer($t5) + 13: $t1 := +($t7, $t6) + 14: goto 18 + 15: label L3 + 16: $t8 := 14566554180833181697 + 17: abort($t8) + 18: label L0 + 19: return $t1 } diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/matching_refutable_err.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/matching_refutable_err.exp index c930a13a552b1..a8af7fd83d17a 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/matching_refutable_err.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/matching_refutable_err.exp @@ -40,4 +40,23 @@ fun m::t($t0: 0x815::m::E): u64 { } +============ disassembled file-format ================== +// Move bytecode v7 +module 815.m { +enum E { + None{ + + }, + Some{ + _0: u64 + } +} + +t(Arg0: E): u64 /* def_idx: 0 */ { +B0: + 0: MoveLoc[0](Arg0: E) + 1: UnpackVariant[0](E/Some) + 2: Ret +} +} ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/operators.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/operators.exp index 3260942440feb..958118005acac 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/operators.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/operators.exp @@ -51,12 +51,18 @@ fun operators::arithm($t0: u64, $t1: u64): u64 { var $t4: u64 var $t5: u64 var $t6: u64 - 0: $t6 := -($t0, $t1) - 1: $t5 := /($t1, $t6) - 2: $t4 := *($t5, $t1) - 3: $t3 := %($t4, $t0) - 4: $t2 := +($t0, $t3) - 5: return $t2 + var $t7: u64 + var $t8: u64 + var $t9: u64 + 0: $t3 := infer($t0) + 1: $t7 := infer($t1) + 2: $t9 := infer($t0) + 3: $t8 := -($t9, $t1) + 4: $t6 := /($t7, $t8) + 5: $t5 := *($t6, $t1) + 6: $t4 := %($t5, $t0) + 7: $t2 := +($t3, $t4) + 8: return $t2 } @@ -64,9 +70,11 @@ fun operators::arithm($t0: u64, $t1: u64): u64 { fun operators::bits($t0: u64, $t1: u8): u64 { var $t2: u64 var $t3: u64 - 0: $t3 := <<($t0, $t1) - 1: $t2 := &($t3, $t0) - 2: return $t2 + var $t4: u64 + 0: $t4 := infer($t0) + 1: $t3 := <<($t4, $t1) + 2: $t2 := &($t3, $t0) + 3: return $t2 } @@ -133,16 +141,20 @@ fun operators::bools($t0: bool, $t1: bool): bool { [variant baseline] fun operators::equality<#0>($t0: #0, $t1: #0): bool { var $t2: bool - 0: $t2 := ==($t0, $t1) - 1: return $t2 + var $t3: #0 + 0: $t3 := infer($t0) + 1: $t2 := ==($t3, $t1) + 2: return $t2 } [variant baseline] fun operators::inequality<#0>($t0: #0, $t1: #0): bool { var $t2: bool - 0: $t2 := !=($t0, $t1) - 1: return $t2 + var $t3: #0 + 0: $t3 := infer($t0) + 1: $t2 := !=($t3, $t1) + 2: return $t2 } @@ -152,34 +164,206 @@ fun operators::order($t0: u64, $t1: u64): bool { var $t3: bool var $t4: bool var $t5: bool - var $t6: bool - var $t7: bool - 0: $t5 := <($t0, $t1) - 1: if ($t5) goto 2 else goto 5 - 2: label L0 - 3: $t4 := <=($t0, $t1) - 4: goto 7 - 5: label L1 - 6: $t4 := false - 7: label L2 - 8: if ($t4) goto 9 else goto 13 - 9: label L3 - 10: $t6 := >($t0, $t1) - 11: $t3 := !($t6) - 12: goto 15 - 13: label L4 - 14: $t3 := false - 15: label L5 - 16: if ($t3) goto 17 else goto 21 - 17: label L6 - 18: $t7 := >=($t0, $t1) - 19: $t2 := !($t7) - 20: goto 23 - 21: label L7 - 22: $t2 := false - 23: label L8 - 24: return $t2 + var $t6: u64 + var $t7: u64 + var $t8: bool + var $t9: u64 + var $t10: bool + var $t11: u64 + 0: $t6 := infer($t0) + 1: $t5 := <($t6, $t1) + 2: if ($t5) goto 3 else goto 7 + 3: label L0 + 4: $t7 := infer($t0) + 5: $t4 := <=($t7, $t1) + 6: goto 9 + 7: label L1 + 8: $t4 := false + 9: label L2 + 10: if ($t4) goto 11 else goto 16 + 11: label L3 + 12: $t9 := infer($t0) + 13: $t8 := >($t9, $t1) + 14: $t3 := !($t8) + 15: goto 18 + 16: label L4 + 17: $t3 := false + 18: label L5 + 19: if ($t3) goto 20 else goto 25 + 20: label L6 + 21: $t11 := infer($t0) + 22: $t10 := >=($t11, $t1) + 23: $t2 := !($t10) + 24: goto 27 + 25: label L7 + 26: $t2 := false + 27: label L8 + 28: return $t2 } +============ disassembled file-format ================== +// Move bytecode v7 +module 42.operators { + + +arithm(Arg0: u64, Arg1: u64): u64 /* def_idx: 0 */ { +B0: + 0: CopyLoc[0](Arg0: u64) + 1: CopyLoc[1](Arg1: u64) + 2: CopyLoc[0](Arg0: u64) + 3: CopyLoc[1](Arg1: u64) + 4: Sub + 5: Div + 6: MoveLoc[1](Arg1: u64) + 7: Mul + 8: MoveLoc[0](Arg0: u64) + 9: Mod + 10: Add + 11: Ret +} +bits(Arg0: u64, Arg1: u8): u64 /* def_idx: 1 */ { +B0: + 0: CopyLoc[0](Arg0: u64) + 1: MoveLoc[1](Arg1: u8) + 2: Shl + 3: MoveLoc[0](Arg0: u64) + 4: BitAnd + 5: Ret +} +bools(Arg0: bool, Arg1: bool): bool /* def_idx: 2 */ { +L2: loc0: bool +L3: loc1: bool +L4: loc2: bool +L5: loc3: bool +B0: + 0: CopyLoc[0](Arg0: bool) + 1: BrFalse(44) +B1: + 2: CopyLoc[1](Arg1: bool) + 3: StLoc[2](loc0: bool) +B2: + 4: MoveLoc[2](loc0: bool) + 5: BrFalse(35) +B3: + 6: LdTrue + 7: StLoc[3](loc1: bool) +B4: + 8: MoveLoc[3](loc1: bool) + 9: BrFalse(27) +B5: + 10: LdTrue + 11: StLoc[4](loc2: bool) +B6: + 12: MoveLoc[4](loc2: bool) + 13: BrFalse(18) +B7: + 14: LdTrue + 15: StLoc[5](loc3: bool) +B8: + 16: MoveLoc[5](loc3: bool) + 17: Ret +B9: + 18: MoveLoc[0](Arg0: bool) + 19: BrTrue(24) +B10: + 20: MoveLoc[1](Arg1: bool) + 21: Not + 22: StLoc[5](loc3: bool) + 23: Branch(16) +B11: + 24: LdFalse + 25: StLoc[5](loc3: bool) + 26: Branch(16) +B12: + 27: CopyLoc[0](Arg0: bool) + 28: BrTrue(32) +B13: + 29: CopyLoc[1](Arg1: bool) + 30: StLoc[4](loc2: bool) + 31: Branch(12) +B14: + 32: LdFalse + 33: StLoc[4](loc2: bool) + 34: Branch(12) +B15: + 35: CopyLoc[0](Arg0: bool) + 36: BrFalse(41) +B16: + 37: CopyLoc[1](Arg1: bool) + 38: Not + 39: StLoc[3](loc1: bool) + 40: Branch(8) +B17: + 41: LdFalse + 42: StLoc[3](loc1: bool) + 43: Branch(8) +B18: + 44: LdFalse + 45: StLoc[2](loc0: bool) + 46: Branch(4) +} +equality(Arg0: Ty0, Arg1: Ty0): bool /* def_idx: 3 */ { +B0: + 0: MoveLoc[0](Arg0: Ty0) + 1: MoveLoc[1](Arg1: Ty0) + 2: Eq + 3: Ret +} +inequality(Arg0: Ty0, Arg1: Ty0): bool /* def_idx: 4 */ { +B0: + 0: MoveLoc[0](Arg0: Ty0) + 1: MoveLoc[1](Arg1: Ty0) + 2: Neq + 3: Ret +} +order(Arg0: u64, Arg1: u64): bool /* def_idx: 5 */ { +L2: loc0: bool +L3: loc1: bool +L4: loc2: bool +B0: + 0: CopyLoc[0](Arg0: u64) + 1: CopyLoc[1](Arg1: u64) + 2: Lt + 3: BrFalse(30) +B1: + 4: CopyLoc[0](Arg0: u64) + 5: CopyLoc[1](Arg1: u64) + 6: Le + 7: StLoc[2](loc0: bool) +B2: + 8: MoveLoc[2](loc0: bool) + 9: BrFalse(27) +B3: + 10: CopyLoc[0](Arg0: u64) + 11: CopyLoc[1](Arg1: u64) + 12: Gt + 13: Not + 14: StLoc[3](loc1: bool) +B4: + 15: MoveLoc[3](loc1: bool) + 16: BrFalse(24) +B5: + 17: MoveLoc[0](Arg0: u64) + 18: MoveLoc[1](Arg1: u64) + 19: Ge + 20: Not + 21: StLoc[4](loc2: bool) +B6: + 22: MoveLoc[4](loc2: bool) + 23: Ret +B7: + 24: LdFalse + 25: StLoc[4](loc2: bool) + 26: Branch(22) +B8: + 27: LdFalse + 28: StLoc[3](loc1: bool) + 29: Branch(15) +B9: + 30: LdFalse + 31: StLoc[2](loc0: bool) + 32: Branch(8) +} +} ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/pack_order.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/pack_order.exp index 52cea517af73a..d3d547a43fd85 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/pack_order.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/pack_order.exp @@ -89,8 +89,12 @@ module 0x42::pack_unpack { [variant baseline] fun pack_unpack::pack1($t0: u8, $t1: u8, $t2: u8): 0x42::pack_unpack::S { var $t3: 0x42::pack_unpack::S - 0: $t3 := pack 0x42::pack_unpack::S($t0, $t1, $t2) - 1: return $t3 + var $t4: u8 + var $t5: u8 + 0: $t4 := infer($t0) + 1: $t5 := infer($t1) + 2: $t3 := pack 0x42::pack_unpack::S($t4, $t5, $t2) + 3: return $t3 } @@ -99,10 +103,14 @@ fun pack_unpack::pack2($t0: u8, $t1: u8, $t2: u8): 0x42::pack_unpack::S { var $t3: 0x42::pack_unpack::S var $t4: u8 var $t5: u8 + var $t6: u8 + var $t7: u8 0: $t4 := infer($t0) 1: $t5 := infer($t1) - 2: $t3 := pack 0x42::pack_unpack::S($t4, $t2, $t5) - 3: return $t3 + 2: $t6 := infer($t4) + 3: $t7 := infer($t2) + 4: $t3 := pack 0x42::pack_unpack::S($t6, $t7, $t5) + 5: return $t3 } @@ -110,9 +118,13 @@ fun pack_unpack::pack2($t0: u8, $t1: u8, $t2: u8): 0x42::pack_unpack::S { fun pack_unpack::pack3($t0: u8, $t1: u8, $t2: u8): 0x42::pack_unpack::S { var $t3: 0x42::pack_unpack::S var $t4: u8 + var $t5: u8 + var $t6: u8 0: $t4 := infer($t0) - 1: $t3 := pack 0x42::pack_unpack::S($t1, $t4, $t2) - 2: return $t3 + 1: $t5 := infer($t1) + 2: $t6 := infer($t4) + 3: $t3 := pack 0x42::pack_unpack::S($t5, $t6, $t2) + 4: return $t3 } @@ -121,10 +133,14 @@ fun pack_unpack::pack4($t0: u8, $t1: u8, $t2: u8): 0x42::pack_unpack::S { var $t3: 0x42::pack_unpack::S var $t4: u8 var $t5: u8 + var $t6: u8 + var $t7: u8 0: $t4 := infer($t0) 1: $t5 := infer($t1) - 2: $t3 := pack 0x42::pack_unpack::S($t2, $t4, $t5) - 3: return $t3 + 2: $t6 := infer($t2) + 3: $t7 := infer($t4) + 4: $t3 := pack 0x42::pack_unpack::S($t6, $t7, $t5) + 5: return $t3 } @@ -132,9 +148,13 @@ fun pack_unpack::pack4($t0: u8, $t1: u8, $t2: u8): 0x42::pack_unpack::S { fun pack_unpack::pack5($t0: u8, $t1: u8, $t2: u8): 0x42::pack_unpack::S { var $t3: 0x42::pack_unpack::S var $t4: u8 + var $t5: u8 + var $t6: u8 0: $t4 := infer($t0) - 1: $t3 := pack 0x42::pack_unpack::S($t1, $t2, $t4) - 2: return $t3 + 1: $t5 := infer($t1) + 2: $t6 := infer($t2) + 3: $t3 := pack 0x42::pack_unpack::S($t5, $t6, $t4) + 4: return $t3 } @@ -143,11 +163,73 @@ fun pack_unpack::pack6($t0: u8, $t1: u8, $t2: u8): 0x42::pack_unpack::S { var $t3: 0x42::pack_unpack::S var $t4: u8 var $t5: u8 + var $t6: u8 + var $t7: u8 0: $t4 := infer($t0) 1: $t5 := infer($t1) - 2: $t3 := pack 0x42::pack_unpack::S($t2, $t5, $t4) - 3: return $t3 + 2: $t6 := infer($t2) + 3: $t7 := infer($t5) + 4: $t3 := pack 0x42::pack_unpack::S($t6, $t7, $t4) + 5: return $t3 } +============ disassembled file-format ================== +// Move bytecode v7 +module 42.pack_unpack { +struct S { + f1: u8, + f2: u8, + f3: u8 +} + +pack1(Arg0: u8, Arg1: u8, Arg2: u8): S /* def_idx: 0 */ { +B0: + 0: MoveLoc[0](Arg0: u8) + 1: MoveLoc[1](Arg1: u8) + 2: MoveLoc[2](Arg2: u8) + 3: Pack[0](S) + 4: Ret +} +pack2(Arg0: u8, Arg1: u8, Arg2: u8): S /* def_idx: 1 */ { +B0: + 0: MoveLoc[0](Arg0: u8) + 1: MoveLoc[2](Arg2: u8) + 2: MoveLoc[1](Arg1: u8) + 3: Pack[0](S) + 4: Ret +} +pack3(Arg0: u8, Arg1: u8, Arg2: u8): S /* def_idx: 2 */ { +B0: + 0: MoveLoc[1](Arg1: u8) + 1: MoveLoc[0](Arg0: u8) + 2: MoveLoc[2](Arg2: u8) + 3: Pack[0](S) + 4: Ret +} +pack4(Arg0: u8, Arg1: u8, Arg2: u8): S /* def_idx: 3 */ { +B0: + 0: MoveLoc[2](Arg2: u8) + 1: MoveLoc[0](Arg0: u8) + 2: MoveLoc[1](Arg1: u8) + 3: Pack[0](S) + 4: Ret +} +pack5(Arg0: u8, Arg1: u8, Arg2: u8): S /* def_idx: 4 */ { +B0: + 0: MoveLoc[1](Arg1: u8) + 1: MoveLoc[2](Arg2: u8) + 2: MoveLoc[0](Arg0: u8) + 3: Pack[0](S) + 4: Ret +} +pack6(Arg0: u8, Arg1: u8, Arg2: u8): S /* def_idx: 5 */ { +B0: + 0: MoveLoc[2](Arg2: u8) + 1: MoveLoc[1](Arg1: u8) + 2: MoveLoc[0](Arg0: u8) + 3: Pack[0](S) + 4: Ret +} +} ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/pack_unpack.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/pack_unpack.exp index 17e454f6177ee..1d424b9e884a1 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/pack_unpack.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/pack_unpack.exp @@ -41,10 +41,12 @@ module 0x42::pack_unpack { [variant baseline] fun pack_unpack::pack($t0: u64, $t1: u64): 0x42::pack_unpack::S { var $t2: 0x42::pack_unpack::S - var $t3: 0x42::pack_unpack::T - 0: $t3 := pack 0x42::pack_unpack::T($t1) - 1: $t2 := pack 0x42::pack_unpack::S($t0, $t3) - 2: return $t2 + var $t3: u64 + var $t4: 0x42::pack_unpack::T + 0: $t3 := infer($t0) + 1: $t4 := pack 0x42::pack_unpack::T($t1) + 2: $t2 := pack 0x42::pack_unpack::S($t3, $t4) + 3: return $t2 } @@ -63,4 +65,31 @@ fun pack_unpack::unpack($t0: 0x42::pack_unpack::S): (u64, u64) { } +============ disassembled file-format ================== +// Move bytecode v7 +module 42.pack_unpack { +struct T { + h: u64 +} +struct S { + f: u64, + g: T +} + +pack(Arg0: u64, Arg1: u64): S /* def_idx: 0 */ { +B0: + 0: MoveLoc[0](Arg0: u64) + 1: MoveLoc[1](Arg1: u64) + 2: Pack[0](T) + 3: Pack[1](S) + 4: Ret +} +unpack(Arg0: S): u64 * u64 /* def_idx: 1 */ { +B0: + 0: MoveLoc[0](Arg0: S) + 1: Unpack[1](S) + 2: Unpack[0](T) + 3: Ret +} +} ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/reference_conversion.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/reference_conversion.exp index 587b47b31883a..1a7186b1877b0 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/reference_conversion.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/reference_conversion.exp @@ -55,4 +55,32 @@ fun reference_conversion::use_it(): u64 { } +============ disassembled file-format ================== +// Move bytecode v7 +module 42.reference_conversion { + + +deref(Arg0: &u64): u64 /* def_idx: 0 */ { +B0: + 0: MoveLoc[0](Arg0: &u64) + 1: ReadRef + 2: Ret +} +use_it(): u64 /* def_idx: 1 */ { +L0: loc0: u64 +L1: loc1: &mut u64 +B0: + 0: LdU64(42) + 1: StLoc[0](loc0: u64) + 2: MutBorrowLoc[0](loc0: u64) + 3: StLoc[1](loc1: &mut u64) + 4: LdU64(43) + 5: CopyLoc[1](loc1: &mut u64) + 6: WriteRef + 7: MoveLoc[1](loc1: &mut u64) + 8: FreezeRef + 9: Call deref(&u64): u64 + 10: Ret +} +} ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/spec_construct.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/spec_construct.exp index 6108d5abdaa96..4a95c4483a3a9 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/spec_construct.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/spec_construct.exp @@ -43,4 +43,25 @@ public fun m::foo($t0: &0x42::m::S): u8 { } +============ disassembled file-format ================== +// Move bytecode v7 +module 42.m { +struct E { + k: u8 +} +struct S { + data: vector +} + +public foo(Arg0: &S): u8 /* def_idx: 0 */ { +B0: + 0: MoveLoc[0](Arg0: &S) + 1: ImmBorrowField[0](S.data: vector) + 2: LdU64(0) + 3: VecImmBorrow(2) + 4: ImmBorrowField[1](E.k: u8) + 5: ReadRef + 6: Ret +} +} ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/vector.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/vector.exp index 8843ffc5a4ac7..b3e3f13164e21 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/vector.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/vector.exp @@ -22,4 +22,15 @@ fun vector::create(): vector { } +============ disassembled file-format ================== +// Move bytecode v7 +module 42.vector { + + +create(): vector /* def_idx: 0 */ { +B0: + 0: LdConst[0](Vector(U64): [3, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0]) + 1: Ret +} +} ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/wildcard5.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/wildcard5.exp index 44dca347d8756..5eb3acb11c33c 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/wildcard5.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/wildcard5.exp @@ -44,4 +44,23 @@ public fun m::test() { } +============ disassembled file-format ================== +// Move bytecode v7 +module c0ffee.m { +struct S { + x: u64, + y: u64 +} + +public test() /* def_idx: 0 */ { +B0: + 0: LdU64(3) + 1: LdU64(4) + 2: Pack[0](S) + 3: Unpack[0](S) + 4: Pop + 5: Pop + 6: Ret +} +} ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/bytecode-verify-failure/equality.exp b/third_party/move/move-compiler-v2/tests/bytecode-verify-failure/equality.exp index 3c99d92a1d3b8..601110318e585 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-verify-failure/equality.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-verify-failure/equality.exp @@ -1,23 +1,7 @@ -============ disassembled file-format ================== -// Move bytecode v7 -module c0ffee.m { - - -equality(Arg0: Ty0, Arg1: Ty0): bool /* def_idx: 0 */ { -B0: - 0: MoveLoc[0](Arg0: Ty0) - 1: MoveLoc[1](Arg1: Ty0) - 2: Eq - 3: Ret -} -} -============ bytecode verification failed ======== - Diagnostics: -bug: bytecode verification failed with unexpected status code `EQUALITY_OP_TYPE_MISMATCH_ERROR`. This is a compiler bug, consider reporting it. -Error message: none - ┌─ tests/bytecode-verify-failure/equality.move:3:9 +bug: file format generator: Inferred and Store AssignKind should be not appear here. + ┌─ tests/bytecode-verify-failure/equality.move:2:7 │ -3 │ x == y - │ ^^^^^^ +2 │ fun equality(x: T, y: T): bool { + │ ^^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/control-flow-simplification/bug-10253.off.exp b/third_party/move/move-compiler-v2/tests/control-flow-simplification/bug-10253.off.exp index fcda55f1a11a3..d82b0f70c4794 100644 --- a/third_party/move/move-compiler-v2/tests/control-flow-simplification/bug-10253.off.exp +++ b/third_party/move/move-compiler-v2/tests/control-flow-simplification/bug-10253.off.exp @@ -7,7 +7,6 @@ module cafe.vectors { entry public guess_flips(Arg0: vector) /* def_idx: 0 */ { L1: loc0: &vector L2: loc1: u64 -L3: loc2: u64 B0: 0: ImmBorrowLoc[0](Arg0: vector) 1: StLoc[1](loc0: &vector) @@ -48,7 +47,6 @@ B7: } entry public guess_flips_directly(Arg0: vector) /* def_idx: 1 */ { L1: loc0: u64 -L2: loc1: u64 B0: 0: LdU64(0) 1: StLoc[1](loc0: u64) @@ -90,7 +88,6 @@ B0: entry public guess_without_break_with_inline(Arg0: vector) /* def_idx: 3 */ { L1: loc0: &vector L2: loc1: u64 -L3: loc2: u64 B0: 0: ImmBorrowLoc[0](Arg0: vector) 1: StLoc[1](loc0: &vector) @@ -134,7 +131,6 @@ B8: } loops_with_break_no_inline(Arg0: &vector) /* def_idx: 4 */ { L1: loc0: u64 -L2: loc1: u64 B0: 0: LdU64(0) 1: StLoc[1](loc0: u64) diff --git a/third_party/move/move-compiler-v2/tests/control-flow-simplification/bug-10253.on.exp b/third_party/move/move-compiler-v2/tests/control-flow-simplification/bug-10253.on.exp index 11a6f4028f8eb..9c62e420cdcaa 100644 --- a/third_party/move/move-compiler-v2/tests/control-flow-simplification/bug-10253.on.exp +++ b/third_party/move/move-compiler-v2/tests/control-flow-simplification/bug-10253.on.exp @@ -11,11 +11,13 @@ public fun vectors::guess_flips($t0: vector) { var $t7: bool var $t8: u8 var $t9: &u8 - var $t10: u8 - var $t11: u64 + var $t10: &vector + var $t11: u8 var $t12: u64 - var $t13: vector - var $t14: vector + var $t13: u64 + var $t14: u64 + var $t15: vector + var $t16: vector 0: $t2 := borrow_local($t0) 1: $t1 := move($t2) 2: $t3 := 0 @@ -23,27 +25,29 @@ public fun vectors::guess_flips($t0: vector) { 4: $t5 := copy($t3) 5: $t6 := vector::length($t1) 6: $t4 := <($t5, $t6) - 7: if ($t4) goto 8 else goto 25 + 7: if ($t4) goto 8 else goto 27 8: label L2 - 9: $t9 := vector::borrow($t1, $t3) - 10: $t8 := read_ref($t9) - 11: $t10 := 0 - 12: $t7 := !=($t8, $t10) - 13: if ($t7) goto 14 else goto 20 - 14: label L5 - 15: drop($t1) - 16: label L1 - 17: $t13 := copy($t0) - 18: $t14 := move($t0) - 19: return () - 20: label L7 - 21: $t12 := 1 - 22: $t11 := +($t3, $t12) - 23: $t3 := move($t11) - 24: goto 3 - 25: label L3 - 26: drop($t1) - 27: goto 16 + 9: $t10 := copy($t1) + 10: $t9 := vector::borrow($t10, $t3) + 11: $t8 := read_ref($t9) + 12: $t11 := 0 + 13: $t7 := !=($t8, $t11) + 14: if ($t7) goto 15 else goto 21 + 15: label L5 + 16: drop($t1) + 17: label L1 + 18: $t15 := copy($t0) + 19: $t16 := move($t0) + 20: return () + 21: label L7 + 22: $t13 := move($t3) + 23: $t14 := 1 + 24: $t12 := +($t13, $t14) + 25: $t3 := move($t12) + 26: goto 3 + 27: label L3 + 28: drop($t1) + 29: goto 17 } @@ -61,8 +65,9 @@ public fun vectors::guess_flips_directly($t0: vector) { var $t10: u8 var $t11: u64 var $t12: u64 - var $t13: vector + var $t13: u64 var $t14: vector + var $t15: vector 0: $t1 := 0 1: label L0 2: $t3 := copy($t1) @@ -78,14 +83,15 @@ public fun vectors::guess_flips_directly($t0: vector) { 12: $t6 := !=($t7, $t10) 13: if ($t6) goto 14 else goto 18 14: label L1 - 15: $t13 := copy($t0) - 16: $t14 := move($t0) + 15: $t14 := copy($t0) + 16: $t15 := move($t0) 17: return () 18: label L7 - 19: $t12 := 1 - 20: $t11 := +($t1, $t12) - 21: $t1 := move($t11) - 22: goto 1 + 19: $t12 := move($t1) + 20: $t13 := 1 + 21: $t11 := +($t12, $t13) + 22: $t1 := move($t11) + 23: goto 1 } @@ -113,12 +119,14 @@ public fun vectors::guess_without_break_with_inline($t0: vector) { var $t7: bool var $t8: u8 var $t9: &u8 - var $t10: u8 - var $t11: u64 + var $t10: &vector + var $t11: u8 var $t12: u64 var $t13: u64 - var $t14: vector - var $t15: vector + var $t14: u64 + var $t15: u64 + var $t16: vector + var $t17: vector 0: $t2 := borrow_local($t0) 1: $t1 := move($t2) 2: $t3 := 0 @@ -126,27 +134,29 @@ public fun vectors::guess_without_break_with_inline($t0: vector) { 4: $t5 := copy($t3) 5: $t6 := vector::length($t1) 6: $t4 := <($t5, $t6) - 7: if ($t4) goto 8 else goto 23 + 7: if ($t4) goto 8 else goto 25 8: label L2 - 9: $t9 := vector::borrow($t1, $t3) - 10: $t8 := read_ref($t9) - 11: $t10 := 0 - 12: $t7 := ==($t8, $t10) - 13: if ($t7) goto 14 else goto 19 - 14: label L5 - 15: $t13 := 1 - 16: $t12 := +($t3, $t13) - 17: $t3 := move($t12) - 18: goto 3 - 19: label L6 - 20: drop($t1) - 21: $t11 := 3 - 22: abort($t11) - 23: label L3 - 24: drop($t1) - 25: $t14 := copy($t0) - 26: $t15 := copy($t0) - 27: return () + 9: $t10 := copy($t1) + 10: $t9 := vector::borrow($t10, $t3) + 11: $t8 := read_ref($t9) + 12: $t11 := 0 + 13: $t7 := ==($t8, $t11) + 14: if ($t7) goto 15 else goto 21 + 15: label L5 + 16: $t14 := move($t3) + 17: $t15 := 1 + 18: $t13 := +($t14, $t15) + 19: $t3 := move($t13) + 20: goto 3 + 21: label L6 + 22: drop($t1) + 23: $t12 := 3 + 24: abort($t12) + 25: label L3 + 26: drop($t1) + 27: $t16 := copy($t0) + 28: $t17 := copy($t0) + 29: return () } @@ -159,33 +169,37 @@ fun vectors::loops_with_break_no_inline($t0: &vector) { var $t5: bool var $t6: u8 var $t7: &u8 - var $t8: u8 - var $t9: u64 + var $t8: &vector + var $t9: u8 var $t10: u64 + var $t11: u64 + var $t12: u64 0: $t1 := 0 1: label L0 2: $t3 := copy($t1) 3: $t4 := vector::length($t0) 4: $t2 := <($t3, $t4) - 5: if ($t2) goto 6 else goto 21 + 5: if ($t2) goto 6 else goto 23 6: label L2 - 7: $t7 := vector::borrow($t0, $t1) - 8: $t6 := read_ref($t7) - 9: $t8 := 0 - 10: $t5 := !=($t6, $t8) - 11: if ($t5) goto 12 else goto 16 - 12: label L5 - 13: drop($t0) - 14: label L1 - 15: return () - 16: label L7 - 17: $t10 := 1 - 18: $t9 := +($t1, $t10) - 19: $t1 := move($t9) - 20: goto 1 - 21: label L3 - 22: drop($t0) - 23: goto 14 + 7: $t8 := copy($t0) + 8: $t7 := vector::borrow($t8, $t1) + 9: $t6 := read_ref($t7) + 10: $t9 := 0 + 11: $t5 := !=($t6, $t9) + 12: if ($t5) goto 13 else goto 17 + 13: label L5 + 14: drop($t0) + 15: label L1 + 16: return () + 17: label L7 + 18: $t11 := move($t1) + 19: $t12 := 1 + 20: $t10 := +($t11, $t12) + 21: $t1 := move($t10) + 22: goto 1 + 23: label L3 + 24: drop($t0) + 25: goto 15 } @@ -233,7 +247,6 @@ module cafe.vectors { entry public guess_flips(Arg0: vector) /* def_idx: 0 */ { L1: loc0: &vector L2: loc1: u64 -L3: loc2: u64 B0: 0: ImmBorrowLoc[0](Arg0: vector) 1: StLoc[1](loc0: &vector) @@ -271,7 +284,6 @@ B6: } entry public guess_flips_directly(Arg0: vector) /* def_idx: 1 */ { L1: loc0: u64 -L2: loc1: u64 B0: 0: LdU64(0) 1: StLoc[1](loc0: u64) @@ -311,7 +323,6 @@ B0: entry public guess_without_break_with_inline(Arg0: vector) /* def_idx: 3 */ { L1: loc0: &vector L2: loc1: u64 -L3: loc2: u64 B0: 0: ImmBorrowLoc[0](Arg0: vector) 1: StLoc[1](loc0: &vector) @@ -349,7 +360,6 @@ B5: } loops_with_break_no_inline(Arg0: &vector) /* def_idx: 4 */ { L1: loc0: u64 -L2: loc1: u64 B0: 0: LdU64(0) 1: StLoc[1](loc0: u64) diff --git a/third_party/move/move-compiler-v2/tests/control-flow-simplification/jump-label.off.exp b/third_party/move/move-compiler-v2/tests/control-flow-simplification/jump-label.off.exp index af6586a3f5112..362c68f2794cb 100644 --- a/third_party/move/move-compiler-v2/tests/control-flow-simplification/jump-label.off.exp +++ b/third_party/move/move-compiler-v2/tests/control-flow-simplification/jump-label.off.exp @@ -9,7 +9,6 @@ use 0000000000000000000000000000000000000000000000000000000000000001::string; test(Arg0: vector): Ty0 /* def_idx: 0 */ { L1: loc0: String -L2: loc1: String B0: 0: Call foo(): String 1: StLoc[1](loc0: String) @@ -35,21 +34,19 @@ B3: 18: Call bar(bool): Ty0 19: Ret B4: - 20: LdConst[2](Vector(U8): [3, 117, 54, 52]) - 21: Call string::utf8(vector): String - 22: StLoc[2](loc1: String) - 23: MoveLoc[1](loc0: String) - 24: MoveLoc[2](loc1: String) - 25: Eq - 26: BrFalse(31) + 20: MoveLoc[1](loc0: String) + 21: LdConst[2](Vector(U8): [3, 117, 54, 52]) + 22: Call string::utf8(vector): String + 23: Eq + 24: BrFalse(29) B5: - 27: MoveLoc[0](Arg0: vector) - 28: Call baz(vector): bool - 29: Call bar(bool): Ty0 - 30: Ret + 25: MoveLoc[0](Arg0: vector) + 26: Call baz(vector): bool + 27: Call bar(bool): Ty0 + 28: Ret B6: - 31: LdU64(0) - 32: Abort + 29: LdU64(0) + 30: Abort } bar(Arg0: bool): Ty0 /* def_idx: 1 */ { B0: diff --git a/third_party/move/move-compiler-v2/tests/control-flow-simplification/jump-label.on.exp b/third_party/move/move-compiler-v2/tests/control-flow-simplification/jump-label.on.exp index 23438ea680516..e4ecc4bc0e0da 100644 --- a/third_party/move/move-compiler-v2/tests/control-flow-simplification/jump-label.on.exp +++ b/third_party/move/move-compiler-v2/tests/control-flow-simplification/jump-label.on.exp @@ -93,7 +93,6 @@ use 0000000000000000000000000000000000000000000000000000000000000001::string; test(Arg0: vector): Ty0 /* def_idx: 0 */ { L1: loc0: String -L2: loc1: String B0: 0: Call foo(): String 1: StLoc[1](loc0: String) @@ -119,21 +118,19 @@ B3: 18: Call bar(bool): Ty0 19: Ret B4: - 20: LdConst[2](Vector(U8): [3, 117, 54, 52]) - 21: Call string::utf8(vector): String - 22: StLoc[2](loc1: String) - 23: MoveLoc[1](loc0: String) - 24: MoveLoc[2](loc1: String) - 25: Eq - 26: BrFalse(31) + 20: MoveLoc[1](loc0: String) + 21: LdConst[2](Vector(U8): [3, 117, 54, 52]) + 22: Call string::utf8(vector): String + 23: Eq + 24: BrFalse(29) B5: - 27: MoveLoc[0](Arg0: vector) - 28: Call baz(vector): bool - 29: Call bar(bool): Ty0 - 30: Ret + 25: MoveLoc[0](Arg0: vector) + 26: Call baz(vector): bool + 27: Call bar(bool): Ty0 + 28: Ret B6: - 31: LdU64(0) - 32: Abort + 29: LdU64(0) + 30: Abort } bar(Arg0: bool): Ty0 /* def_idx: 1 */ { B0: diff --git a/third_party/move/move-compiler-v2/tests/copy-propagation/args_with_side_effects.exp b/third_party/move/move-compiler-v2/tests/copy-propagation/args_with_side_effects.exp index e607e6f3dc221..6c179173a5300 100644 --- a/third_party/move/move-compiler-v2/tests/copy-propagation/args_with_side_effects.exp +++ b/third_party/move/move-compiler-v2/tests/copy-propagation/args_with_side_effects.exp @@ -3,8 +3,10 @@ [variant baseline] fun m::add($t0: u64, $t1: u64): u64 { var $t2: u64 - 0: $t2 := +($t0, $t1) - 1: return $t2 + var $t3: u64 + 0: $t3 := infer($t0) + 1: $t2 := +($t3, $t1) + 2: return $t2 } @@ -15,13 +17,15 @@ public fun m::test($t0: u64): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 0: $t2 := infer($t0) - 1: $t5 := 1 - 2: $t4 := +($t0, $t5) - 3: $t0 := infer($t4) - 4: $t3 := infer($t0) - 5: $t1 := m::add($t2, $t3) - 6: return $t1 + 1: $t5 := infer($t0) + 2: $t6 := 1 + 3: $t4 := +($t5, $t6) + 4: $t0 := infer($t4) + 5: $t3 := infer($t0) + 6: $t1 := m::add($t2, $t3) + 7: return $t1 } ============ after DeadStoreElimination: ================ @@ -29,8 +33,10 @@ public fun m::test($t0: u64): u64 { [variant baseline] fun m::add($t0: u64, $t1: u64): u64 { var $t2: u64 - 0: $t2 := +($t0, $t1) - 1: return $t2 + var $t3: u64 + 0: $t3 := move($t0) + 1: $t2 := +($t3, $t1) + 2: return $t2 } @@ -41,11 +47,13 @@ public fun m::test($t0: u64): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 0: $t2 := copy($t0) - 1: $t5 := 1 - 2: $t4 := +($t0, $t5) - 3: $t0 := move($t4) - 4: $t3 := move($t0) - 5: $t1 := m::add($t2, $t3) - 6: return $t1 + 1: $t5 := move($t0) + 2: $t6 := 1 + 3: $t4 := +($t5, $t6) + 4: $t0 := move($t4) + 5: $t3 := move($t0) + 6: $t1 := m::add($t2, $t3) + 7: return $t1 } diff --git a/third_party/move/move-compiler-v2/tests/copy-propagation/branch_1.exp b/third_party/move/move-compiler-v2/tests/copy-propagation/branch_1.exp index 3a436a82d1143..5599015c76fe7 100644 --- a/third_party/move/move-compiler-v2/tests/copy-propagation/branch_1.exp +++ b/third_party/move/move-compiler-v2/tests/copy-propagation/branch_1.exp @@ -6,6 +6,7 @@ fun m::foo($t0: bool, $t1: u64): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 0: $t3 := infer($t1) 1: if ($t0) goto 2 else goto 6 2: label L0 @@ -14,9 +15,10 @@ fun m::foo($t0: bool, $t1: u64): u64 { 5: goto 7 6: label L1 7: label L2 - 8: $t5 := 1 - 9: $t2 := +($t3, $t5) - 10: return $t2 + 8: $t5 := infer($t3) + 9: $t6 := 1 + 10: $t2 := +($t5, $t6) + 11: return $t2 } ============ after DeadStoreElimination: ================ @@ -27,6 +29,7 @@ fun m::foo($t0: bool, $t1: u64): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 0: $t3 := move($t1) 1: if ($t0) goto 4 else goto 2 2: label L3 @@ -35,7 +38,8 @@ fun m::foo($t0: bool, $t1: u64): u64 { 5: $t4 := 0 6: $t3 := move($t4) 7: label L2 - 8: $t5 := 1 - 9: $t2 := +($t3, $t5) - 10: return $t2 + 8: $t5 := move($t3) + 9: $t6 := 1 + 10: $t2 := +($t5, $t6) + 11: return $t2 } diff --git a/third_party/move/move-compiler-v2/tests/copy-propagation/bug_12068.exp b/third_party/move/move-compiler-v2/tests/copy-propagation/bug_12068.exp index fe2ed828da30d..dd88a23a312d2 100644 --- a/third_party/move/move-compiler-v2/tests/copy-propagation/bug_12068.exp +++ b/third_party/move/move-compiler-v2/tests/copy-propagation/bug_12068.exp @@ -6,34 +6,38 @@ fun m::main() { var $t1: bool var $t2: u64 var $t3: u64 - var $t4: bool - var $t5: u64 + var $t4: u64 + var $t5: bool var $t6: u64 + var $t7: u64 + var $t8: u64 0: $t0 := 0 1: label L0 2: $t1 := true - 3: if ($t1) goto 4 else goto 10 + 3: if ($t1) goto 4 else goto 11 4: label L2 - 5: $t3 := 1 - 6: $t2 := +($t0, $t3) - 7: $t0 := infer($t2) - 8: goto 14 - 9: goto 12 - 10: label L3 - 11: goto 14 - 12: label L4 - 13: goto 1 - 14: label L1 - 15: $t5 := 1 - 16: $t4 := ==($t0, $t5) - 17: if ($t4) goto 18 else goto 20 - 18: label L5 - 19: goto 23 - 20: label L6 - 21: $t6 := 42 - 22: abort($t6) - 23: label L7 - 24: return () + 5: $t3 := infer($t0) + 6: $t4 := 1 + 7: $t2 := +($t3, $t4) + 8: $t0 := infer($t2) + 9: goto 15 + 10: goto 13 + 11: label L3 + 12: goto 15 + 13: label L4 + 14: goto 1 + 15: label L1 + 16: $t6 := infer($t0) + 17: $t7 := 1 + 18: $t5 := ==($t6, $t7) + 19: if ($t5) goto 20 else goto 22 + 20: label L5 + 21: goto 25 + 22: label L6 + 23: $t8 := 42 + 24: abort($t8) + 25: label L7 + 26: return () } ============ after DeadStoreElimination: ================ @@ -44,25 +48,29 @@ fun m::main() { var $t1: bool var $t2: u64 var $t3: u64 - var $t4: bool - var $t5: u64 + var $t4: u64 + var $t5: bool var $t6: u64 + var $t7: u64 + var $t8: u64 0: $t0 := 0 1: $t1 := true 2: if ($t1) goto 5 else goto 3 3: label L7 - 4: goto 9 + 4: goto 10 5: label L2 - 6: $t3 := 1 - 7: $t2 := +($t0, $t3) - 8: $t0 := move($t2) - 9: label L1 - 10: $t5 := 1 - 11: $t4 := ==($t0, $t5) - 12: if ($t4) goto 13 else goto 15 - 13: label L5 - 14: return () - 15: label L6 - 16: $t6 := 42 - 17: abort($t6) + 6: $t3 := move($t0) + 7: $t4 := 1 + 8: $t2 := +($t3, $t4) + 9: $t0 := move($t2) + 10: label L1 + 11: $t6 := move($t0) + 12: $t7 := 1 + 13: $t5 := ==($t6, $t7) + 14: if ($t5) goto 15 else goto 17 + 15: label L5 + 16: return () + 17: label L6 + 18: $t8 := 42 + 19: abort($t8) } diff --git a/third_party/move/move-compiler-v2/tests/copy-propagation/loop_1.exp b/third_party/move/move-compiler-v2/tests/copy-propagation/loop_1.exp index 8a148663185e4..1466154c7fd52 100644 --- a/third_party/move/move-compiler-v2/tests/copy-propagation/loop_1.exp +++ b/third_party/move/move-compiler-v2/tests/copy-propagation/loop_1.exp @@ -9,25 +9,29 @@ fun m::test($t0: u64): u64 { var $t5: u64 var $t6: u64 var $t7: u64 + var $t8: u64 + var $t9: u64 0: $t2 := 0 1: $t3 := 0 2: label L0 - 3: $t5 := 10 - 4: $t4 := <($t3, $t5) - 5: if ($t4) goto 6 else goto 12 - 6: label L2 - 7: $t2 := infer($t0) - 8: $t7 := 1 - 9: $t6 := +($t3, $t7) - 10: $t3 := infer($t6) - 11: goto 14 - 12: label L3 + 3: $t5 := infer($t3) + 4: $t6 := 10 + 5: $t4 := <($t5, $t6) + 6: if ($t4) goto 7 else goto 14 + 7: label L2 + 8: $t2 := infer($t0) + 9: $t8 := infer($t3) + 10: $t9 := 1 + 11: $t7 := +($t8, $t9) + 12: $t3 := infer($t7) 13: goto 16 - 14: label L4 - 15: goto 2 - 16: label L1 - 17: $t1 := infer($t2) - 18: return $t1 + 14: label L3 + 15: goto 18 + 16: label L4 + 17: goto 2 + 18: label L1 + 19: $t1 := infer($t2) + 20: return $t1 } ============ after DeadStoreElimination: ================ @@ -41,19 +45,23 @@ fun m::test($t0: u64): u64 { var $t5: u64 var $t6: u64 var $t7: u64 + var $t8: u64 + var $t9: u64 0: $t2 := 0 1: $t3 := 0 2: label L0 - 3: $t5 := 10 - 4: $t4 := <($t3, $t5) - 5: if ($t4) goto 6 else goto 12 - 6: label L2 - 7: $t2 := copy($t0) - 8: $t7 := 1 - 9: $t6 := +($t3, $t7) - 10: $t3 := move($t6) - 11: goto 2 - 12: label L3 - 13: $t1 := move($t2) - 14: return $t1 + 3: $t5 := copy($t3) + 4: $t6 := 10 + 5: $t4 := <($t5, $t6) + 6: if ($t4) goto 7 else goto 14 + 7: label L2 + 8: $t2 := copy($t0) + 9: $t8 := move($t3) + 10: $t9 := 1 + 11: $t7 := +($t8, $t9) + 12: $t3 := move($t7) + 13: goto 2 + 14: label L3 + 15: $t1 := move($t2) + 16: return $t1 } diff --git a/third_party/move/move-compiler-v2/tests/copy-propagation/loop_2.exp b/third_party/move/move-compiler-v2/tests/copy-propagation/loop_2.exp index 40ae16d3a9341..a1ba6207122a7 100644 --- a/third_party/move/move-compiler-v2/tests/copy-propagation/loop_2.exp +++ b/third_party/move/move-compiler-v2/tests/copy-propagation/loop_2.exp @@ -9,25 +9,29 @@ fun m::test($t0: u64): u64 { var $t5: u64 var $t6: u64 var $t7: u64 + var $t8: u64 + var $t9: u64 0: $t2 := infer($t0) 1: $t3 := 0 2: label L0 - 3: $t5 := 10 - 4: $t4 := <($t3, $t5) - 5: if ($t4) goto 6 else goto 12 - 6: label L2 - 7: $t2 := infer($t0) - 8: $t7 := 1 - 9: $t6 := +($t3, $t7) - 10: $t3 := infer($t6) - 11: goto 14 - 12: label L3 + 3: $t5 := infer($t3) + 4: $t6 := 10 + 5: $t4 := <($t5, $t6) + 6: if ($t4) goto 7 else goto 14 + 7: label L2 + 8: $t2 := infer($t0) + 9: $t8 := infer($t3) + 10: $t9 := 1 + 11: $t7 := +($t8, $t9) + 12: $t3 := infer($t7) 13: goto 16 - 14: label L4 - 15: goto 2 - 16: label L1 - 17: $t1 := infer($t2) - 18: return $t1 + 14: label L3 + 15: goto 18 + 16: label L4 + 17: goto 2 + 18: label L1 + 19: $t1 := infer($t2) + 20: return $t1 } ============ after DeadStoreElimination: ================ @@ -41,19 +45,23 @@ fun m::test($t0: u64): u64 { var $t5: u64 var $t6: u64 var $t7: u64 + var $t8: u64 + var $t9: u64 0: $t2 := copy($t0) 1: $t3 := 0 2: label L0 - 3: $t5 := 10 - 4: $t4 := <($t3, $t5) - 5: if ($t4) goto 6 else goto 12 - 6: label L2 - 7: $t2 := copy($t0) - 8: $t7 := 1 - 9: $t6 := +($t3, $t7) - 10: $t3 := move($t6) - 11: goto 2 - 12: label L3 - 13: $t1 := move($t2) - 14: return $t1 + 3: $t5 := copy($t3) + 4: $t6 := 10 + 5: $t4 := <($t5, $t6) + 6: if ($t4) goto 7 else goto 14 + 7: label L2 + 8: $t2 := copy($t0) + 9: $t8 := move($t3) + 10: $t9 := 1 + 11: $t7 := +($t8, $t9) + 12: $t3 := move($t7) + 13: goto 2 + 14: label L3 + 15: $t1 := move($t2) + 16: return $t1 } diff --git a/third_party/move/move-compiler-v2/tests/copy-propagation/seq_kills_1.exp b/third_party/move/move-compiler-v2/tests/copy-propagation/seq_kills_1.exp index 5cafa1aff0973..2daf35777c985 100644 --- a/third_party/move/move-compiler-v2/tests/copy-propagation/seq_kills_1.exp +++ b/third_party/move/move-compiler-v2/tests/copy-propagation/seq_kills_1.exp @@ -8,14 +8,18 @@ fun m::test($t0: u64): bool { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 0: $t2 := infer($t0) 1: $t3 := infer($t2) 2: $t4 := infer($t3) - 3: $t6 := 1 - 4: $t5 := +($t0, $t6) - 5: $t3 := infer($t5) - 6: $t1 := ==($t2, $t4) - 7: return $t1 + 3: $t6 := infer($t0) + 4: $t7 := 1 + 5: $t5 := +($t6, $t7) + 6: $t3 := infer($t5) + 7: $t8 := infer($t2) + 8: $t1 := ==($t8, $t4) + 9: return $t1 } @@ -36,11 +40,15 @@ fun m::test($t0: u64): bool { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 0: $t2 := copy($t0) 1: $t3 := copy($t2) 2: $t4 := move($t3) - 3: $t6 := 1 - 4: $t5 := +($t0, $t6) - 5: $t1 := ==($t2, $t4) - 6: return $t1 + 3: $t6 := move($t0) + 4: $t7 := 1 + 5: $t5 := +($t6, $t7) + 6: $t8 := move($t2) + 7: $t1 := ==($t8, $t4) + 8: return $t1 } diff --git a/third_party/move/move-compiler-v2/tests/copy-propagation/seq_kills_2.exp b/third_party/move/move-compiler-v2/tests/copy-propagation/seq_kills_2.exp index c4103b2556510..d7aac2eed7601 100644 --- a/third_party/move/move-compiler-v2/tests/copy-propagation/seq_kills_2.exp +++ b/third_party/move/move-compiler-v2/tests/copy-propagation/seq_kills_2.exp @@ -8,14 +8,18 @@ fun m::test($t0: u64): bool { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 0: $t2 := infer($t0) 1: $t3 := infer($t2) 2: $t4 := infer($t3) - 3: $t6 := 1 - 4: $t5 := +($t0, $t6) - 5: $t2 := infer($t5) - 6: $t1 := ==($t3, $t4) - 7: return $t1 + 3: $t6 := infer($t0) + 4: $t7 := 1 + 5: $t5 := +($t6, $t7) + 6: $t2 := infer($t5) + 7: $t8 := infer($t3) + 8: $t1 := ==($t8, $t4) + 9: return $t1 } @@ -36,11 +40,15 @@ fun m::test($t0: u64): bool { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 0: $t2 := copy($t0) 1: $t3 := move($t2) 2: $t4 := copy($t3) - 3: $t6 := 1 - 4: $t5 := +($t0, $t6) - 5: $t1 := ==($t3, $t4) - 6: return $t1 + 3: $t6 := move($t0) + 4: $t7 := 1 + 5: $t5 := +($t6, $t7) + 6: $t8 := move($t3) + 7: $t1 := ==($t8, $t4) + 8: return $t1 } diff --git a/third_party/move/move-compiler-v2/tests/copy-propagation/straight_line_kills.exp b/third_party/move/move-compiler-v2/tests/copy-propagation/straight_line_kills.exp index 5b0207d4fbdac..59402c27689e4 100644 --- a/third_party/move/move-compiler-v2/tests/copy-propagation/straight_line_kills.exp +++ b/third_party/move/move-compiler-v2/tests/copy-propagation/straight_line_kills.exp @@ -7,13 +7,17 @@ fun m::copy_kill($t0: u64): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 + var $t7: u64 0: $t2 := infer($t0) 1: $t3 := infer($t2) - 2: $t5 := 1 - 3: $t4 := +($t0, $t5) - 4: $t0 := infer($t4) - 5: $t1 := +($t3, $t2) - 6: return $t1 + 2: $t5 := infer($t0) + 3: $t6 := 1 + 4: $t4 := +($t5, $t6) + 5: $t0 := infer($t4) + 6: $t7 := infer($t3) + 7: $t1 := +($t7, $t2) + 8: return $t1 } @@ -33,10 +37,14 @@ fun m::copy_kill($t0: u64): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 + var $t7: u64 0: $t2 := copy($t0) 1: $t3 := copy($t2) - 2: $t5 := 1 - 3: $t4 := +($t0, $t5) - 4: $t1 := +($t3, $t2) - 5: return $t1 + 2: $t5 := move($t0) + 3: $t6 := 1 + 4: $t4 := +($t5, $t6) + 5: $t7 := move($t3) + 6: $t1 := +($t7, $t2) + 7: return $t1 } diff --git a/third_party/move/move-compiler-v2/tests/eager-pushes/eager_load_03.exp b/third_party/move/move-compiler-v2/tests/eager-pushes/eager_load_03.exp index bc43cd9fc3906..fc9d04860fc2b 100644 --- a/third_party/move/move-compiler-v2/tests/eager-pushes/eager_load_03.exp +++ b/third_party/move/move-compiler-v2/tests/eager-pushes/eager_load_03.exp @@ -16,11 +16,13 @@ fun m::baz($t0: u64, $t1: u64) { public fun m::foo($t0: u64) { var $t1: u64 var $t2: &mut u64 + var $t3: u64 0: $t1 := m::one() 1: $t2 := borrow_local($t0) 2: m::bar($t2) - 3: m::baz($t0, $t1) - 4: return () + 3: $t3 := infer($t0) + 4: m::baz($t3, $t1) + 5: return () } @@ -53,6 +55,7 @@ fun m::baz($t0: u64, $t1: u64) { public fun m::foo($t0: u64) { var $t1: u64 var $t2: &mut u64 + var $t3: u64 # live vars: $t0 0: $t1 := m::one() # live vars: $t0, $t1 @@ -60,9 +63,11 @@ public fun m::foo($t0: u64) { # live vars: $t0, $t1, $t2 2: m::bar($t2) # live vars: $t0, $t1 - 3: m::baz($t0, $t1) + 3: $t3 := move($t0) + # live vars: $t1, $t3 + 4: m::baz($t3, $t1) # live vars: - 4: return () + 5: return () } @@ -95,9 +100,9 @@ public foo(Arg0: u64) /* def_idx: 2 */ { L1: loc0: u64 B0: 0: Call one(): u64 - 1: MutBorrowLoc[0](Arg0: u64) - 2: Call bar(&mut u64) - 3: StLoc[1](loc0: u64) + 1: StLoc[1](loc0: u64) + 2: MutBorrowLoc[0](Arg0: u64) + 3: Call bar(&mut u64) 4: MoveLoc[0](Arg0: u64) 5: MoveLoc[1](loc0: u64) 6: Call baz(u64, u64) diff --git a/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_01.exp b/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_01.exp index 68d16c3fc8412..d0f01cb6ab0e2 100644 --- a/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_01.exp +++ b/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_01.exp @@ -72,25 +72,27 @@ public fun m::test($t0: u64) { # live vars: $t0 0: $t1 := m::two() # live vars: $t0, $t1 - 1: $t5 := m::one() + 1: $t0 := move($t0) + # live vars: $t0, $t1 + 2: $t5 := m::one() # live vars: $t0, $t1, $t5 - 2: $t0 := -($t0, $t5) + 3: $t0 := -($t0, $t5) # live vars: $t0, $t1 - 3: $t2 := >($t0, $t1) + 4: $t2 := >($t0, $t1) # live vars: $t2 - 4: if ($t2) goto 7 else goto 5 + 5: if ($t2) goto 8 else goto 6 # live vars: - 5: label L3 + 6: label L3 # live vars: - 6: goto 9 + 7: goto 10 # live vars: - 7: label L0 + 8: label L0 # live vars: - 8: m::foo() + 9: m::foo() # live vars: - 9: label L2 + 10: label L2 # live vars: - 10: return () + 11: return () } @@ -120,24 +122,21 @@ B0: } public test(Arg0: u64) /* def_idx: 2 */ { L1: loc0: u64 -L2: loc1: u64 B0: 0: Call two(): u64 1: StLoc[1](loc0: u64) - 2: Call one(): u64 - 3: StLoc[2](loc1: u64) - 4: MoveLoc[0](Arg0: u64) - 5: MoveLoc[2](loc1: u64) - 6: Sub - 7: MoveLoc[1](loc0: u64) - 8: Gt - 9: BrTrue(11) + 2: MoveLoc[0](Arg0: u64) + 3: Call one(): u64 + 4: Sub + 5: MoveLoc[1](loc0: u64) + 6: Gt + 7: BrTrue(9) B1: - 10: Branch(12) + 8: Branch(10) B2: - 11: Call foo() + 9: Call foo() B3: - 12: Ret + 10: Ret } two(): u64 /* def_idx: 3 */ { B0: diff --git a/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_02.exp b/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_02.exp index e2b68c2225ac0..c0e3b1ea99dca 100644 --- a/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_02.exp +++ b/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_02.exp @@ -4,11 +4,17 @@ public fun m::make($t0: u64, $t1: u64, $t2: u64, $t3: &0xc0ffee::m::S, $t4: u64): 0xc0ffee::m::Wrap { var $t5: 0xc0ffee::m::Wrap var $t6: u64 - var $t7: &u64 - 0: $t7 := borrow_field<0xc0ffee::m::S>.x($t3) - 1: $t6 := read_ref($t7) - 2: $t5 := pack 0xc0ffee::m::Wrap($t0, $t1, $t2, $t6, $t4) - 3: return $t5 + var $t7: u64 + var $t8: u64 + var $t9: u64 + var $t10: &u64 + 0: $t6 := infer($t0) + 1: $t7 := infer($t1) + 2: $t8 := infer($t2) + 3: $t10 := borrow_field<0xc0ffee::m::S>.x($t3) + 4: $t9 := read_ref($t10) + 5: $t5 := pack 0xc0ffee::m::Wrap($t6, $t7, $t8, $t9, $t4) + 6: return $t5 } ============ after LiveVarAnalysisProcessor: ================ @@ -16,16 +22,25 @@ public fun m::make($t0: u64, $t1: u64, $t2: u64, $t3: &0xc0ffee::m::S, $t4: u64) [variant baseline] public fun m::make($t0: u64, $t1: u64, $t2: u64, $t3: &0xc0ffee::m::S, $t4: u64): 0xc0ffee::m::Wrap { var $t5: 0xc0ffee::m::Wrap - var $t6: u64 - var $t7: &u64 + var $t6: u64 [unused] + var $t7: u64 [unused] + var $t8: u64 [unused] + var $t9: u64 + var $t10: &u64 + # live vars: $t0, $t1, $t2, $t3, $t4 + 0: $t0 := move($t0) + # live vars: $t0, $t1, $t2, $t3, $t4 + 1: $t1 := move($t1) + # live vars: $t0, $t1, $t2, $t3, $t4 + 2: $t2 := move($t2) # live vars: $t0, $t1, $t2, $t3, $t4 - 0: $t7 := borrow_field<0xc0ffee::m::S>.x($t3) - # live vars: $t0, $t1, $t2, $t4, $t7 - 1: $t6 := read_ref($t7) - # live vars: $t0, $t1, $t2, $t4, $t6 - 2: $t5 := pack 0xc0ffee::m::Wrap($t0, $t1, $t2, $t6, $t4) + 3: $t10 := borrow_field<0xc0ffee::m::S>.x($t3) + # live vars: $t0, $t1, $t2, $t4, $t10 + 4: $t9 := read_ref($t10) + # live vars: $t0, $t1, $t2, $t4, $t9 + 5: $t5 := pack 0xc0ffee::m::Wrap($t0, $t1, $t2, $t9, $t4) # live vars: $t5 - 3: return $t5 + 6: return $t5 } @@ -44,19 +59,16 @@ struct Wrap { } public make(Arg0: u64, Arg1: u64, Arg2: u64, Arg3: &S, Arg4: u64): Wrap /* def_idx: 0 */ { -L5: loc0: u64 B0: - 0: MoveLoc[3](Arg3: &S) - 1: ImmBorrowField[0](S.x: u64) - 2: ReadRef - 3: StLoc[5](loc0: u64) - 4: MoveLoc[0](Arg0: u64) - 5: MoveLoc[1](Arg1: u64) - 6: MoveLoc[2](Arg2: u64) - 7: MoveLoc[5](loc0: u64) - 8: MoveLoc[4](Arg4: u64) - 9: Pack[1](Wrap) - 10: Ret + 0: MoveLoc[0](Arg0: u64) + 1: MoveLoc[1](Arg1: u64) + 2: MoveLoc[2](Arg2: u64) + 3: MoveLoc[3](Arg3: &S) + 4: ImmBorrowField[0](S.x: u64) + 5: ReadRef + 6: MoveLoc[4](Arg4: u64) + 7: Pack[1](Wrap) + 8: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_03.exp b/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_03.exp index a203fca7796c0..9a2f3f7a3e223 100644 --- a/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_03.exp +++ b/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_03.exp @@ -5,16 +5,24 @@ public fun m::make($t0: u64, $t1: u64, $t2: u64, $t3: address, $t4: u64): 0xc0ff var $t5: 0xc0ffee::m::Wrap var $t6: &0xc0ffee::m::S var $t7: u64 - var $t8: &u64 + var $t8: u64 var $t9: u64 - var $t10: &u64 + var $t10: u64 + var $t11: &u64 + var $t12: u64 + var $t13: u64 + var $t14: &u64 0: $t6 := borrow_global<0xc0ffee::m::S>($t3) - 1: $t8 := borrow_field<0xc0ffee::m::S>.x($t6) - 2: $t7 := read_ref($t8) - 3: $t10 := borrow_field<0xc0ffee::m::S>.y($t6) - 4: $t9 := read_ref($t10) - 5: $t5 := pack 0xc0ffee::m::Wrap($t0, $t1, $t2, $t7, $t4, $t9) - 6: return $t5 + 1: $t7 := infer($t0) + 2: $t8 := infer($t1) + 3: $t9 := infer($t2) + 4: $t11 := borrow_field<0xc0ffee::m::S>.x($t6) + 5: $t10 := read_ref($t11) + 6: $t12 := infer($t4) + 7: $t14 := borrow_field<0xc0ffee::m::S>.y($t6) + 8: $t13 := read_ref($t14) + 9: $t5 := pack 0xc0ffee::m::Wrap($t7, $t8, $t9, $t10, $t12, $t13) + 10: return $t5 } ============ after LiveVarAnalysisProcessor: ================ @@ -23,24 +31,36 @@ public fun m::make($t0: u64, $t1: u64, $t2: u64, $t3: address, $t4: u64): 0xc0ff public fun m::make($t0: u64, $t1: u64, $t2: u64, $t3: address, $t4: u64): 0xc0ffee::m::Wrap { var $t5: 0xc0ffee::m::Wrap var $t6: &0xc0ffee::m::S - var $t7: u64 - var $t8: &u64 - var $t9: u64 - var $t10: &u64 [unused] + var $t7: u64 [unused] + var $t8: u64 [unused] + var $t9: u64 [unused] + var $t10: u64 + var $t11: &u64 + var $t12: u64 [unused] + var $t13: u64 + var $t14: &u64 [unused] # live vars: $t0, $t1, $t2, $t3, $t4 0: $t6 := borrow_global<0xc0ffee::m::S>($t3) # live vars: $t0, $t1, $t2, $t4, $t6 - 1: $t8 := borrow_field<0xc0ffee::m::S>.x($t6) - # live vars: $t0, $t1, $t2, $t4, $t6, $t8 - 2: $t7 := read_ref($t8) - # live vars: $t0, $t1, $t2, $t4, $t6, $t7 - 3: $t8 := borrow_field<0xc0ffee::m::S>.y($t6) - # live vars: $t0, $t1, $t2, $t4, $t7, $t8 - 4: $t9 := read_ref($t8) - # live vars: $t0, $t1, $t2, $t4, $t7, $t9 - 5: $t5 := pack 0xc0ffee::m::Wrap($t0, $t1, $t2, $t7, $t4, $t9) + 1: $t0 := move($t0) + # live vars: $t0, $t1, $t2, $t4, $t6 + 2: $t1 := move($t1) + # live vars: $t0, $t1, $t2, $t4, $t6 + 3: $t2 := move($t2) + # live vars: $t0, $t1, $t2, $t4, $t6 + 4: $t11 := borrow_field<0xc0ffee::m::S>.x($t6) + # live vars: $t0, $t1, $t2, $t4, $t6, $t11 + 5: $t10 := read_ref($t11) + # live vars: $t0, $t1, $t2, $t4, $t6, $t10 + 6: $t4 := move($t4) + # live vars: $t0, $t1, $t2, $t4, $t6, $t10 + 7: $t11 := borrow_field<0xc0ffee::m::S>.y($t6) + # live vars: $t0, $t1, $t2, $t4, $t10, $t11 + 8: $t13 := read_ref($t11) + # live vars: $t0, $t1, $t2, $t4, $t10, $t13 + 9: $t5 := pack 0xc0ffee::m::Wrap($t0, $t1, $t2, $t10, $t4, $t13) # live vars: $t5 - 6: return $t5 + 10: return $t5 } @@ -62,28 +82,22 @@ struct Wrap { public make(Arg0: u64, Arg1: u64, Arg2: u64, Arg3: address, Arg4: u64): Wrap /* def_idx: 0 */ { L5: loc0: &S -L6: loc1: u64 -L7: loc2: u64 B0: 0: MoveLoc[3](Arg3: address) 1: ImmBorrowGlobal[0](S) 2: StLoc[5](loc0: &S) - 3: CopyLoc[5](loc0: &S) - 4: ImmBorrowField[0](S.x: u64) - 5: ReadRef - 6: MoveLoc[5](loc0: &S) - 7: ImmBorrowField[1](S.y: u64) + 3: MoveLoc[0](Arg0: u64) + 4: MoveLoc[1](Arg1: u64) + 5: MoveLoc[2](Arg2: u64) + 6: CopyLoc[5](loc0: &S) + 7: ImmBorrowField[0](S.x: u64) 8: ReadRef - 9: StLoc[6](loc1: u64) - 10: StLoc[7](loc2: u64) - 11: MoveLoc[0](Arg0: u64) - 12: MoveLoc[1](Arg1: u64) - 13: MoveLoc[2](Arg2: u64) - 14: MoveLoc[7](loc2: u64) - 15: MoveLoc[4](Arg4: u64) - 16: MoveLoc[6](loc1: u64) - 17: Pack[1](Wrap) - 18: Ret + 9: MoveLoc[4](Arg4: u64) + 10: MoveLoc[5](loc0: &S) + 11: ImmBorrowField[1](S.y: u64) + 12: ReadRef + 13: Pack[1](Wrap) + 14: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_04.exp b/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_04.exp index 9aa46823a704c..d635928819623 100644 --- a/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_04.exp +++ b/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_04.exp @@ -116,29 +116,22 @@ B0: 4: Ret } public test(Arg0: signer, Arg1: address) /* def_idx: 1 */ { -L2: loc0: &signer -L3: loc1: &mut Wrap -L4: loc2: Wrap -L5: loc3: &mut u64 +L2: loc0: &mut Wrap B0: 0: MoveLoc[1](Arg1: address) 1: MutBorrowGlobal[0](Wrap) - 2: ImmBorrowLoc[0](Arg0: signer) - 3: StLoc[2](loc0: &signer) - 4: MutBorrowField[0](Wrap.a: u64) - 5: LdU64(0) + 2: StLoc[2](loc0: &mut Wrap) + 3: ImmBorrowLoc[0](Arg0: signer) + 4: MoveLoc[2](loc0: &mut Wrap) + 5: MutBorrowField[0](Wrap.a: u64) 6: LdU64(0) 7: LdU64(0) - 8: Call zero(u64): u64 - 9: LdU64(0) - 10: Pack[0](Wrap) - 11: StLoc[4](loc2: Wrap) - 12: StLoc[5](loc3: &mut u64) - 13: MoveLoc[2](loc0: &signer) - 14: MoveLoc[5](loc3: &mut u64) - 15: MoveLoc[4](loc2: Wrap) - 16: Call bar(&signer, &mut u64, Wrap) - 17: Ret + 8: LdU64(0) + 9: Call zero(u64): u64 + 10: LdU64(0) + 11: Pack[0](Wrap) + 12: Call bar(&signer, &mut u64, Wrap) + 13: Ret } zero(Arg0: u64): u64 /* def_idx: 2 */ { B0: diff --git a/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_05.exp b/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_05.exp index df80a414a62d7..c2ca65e0b72da 100644 --- a/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_05.exp +++ b/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_05.exp @@ -8,20 +8,22 @@ fun m::foo($t0: &signer, $t1: u64, $t2: u64) { [variant baseline] public fun m::test($t0: &signer, $t1: 0xc0ffee::m::S) { - var $t2: u64 - var $t3: &0xc0ffee::m::S - var $t4: &u64 - var $t5: u64 - var $t6: &0xc0ffee::m::S - var $t7: &u64 - 0: $t3 := borrow_local($t1) - 1: $t4 := borrow_field<0xc0ffee::m::S>.a($t3) - 2: $t2 := read_ref($t4) - 3: $t6 := borrow_local($t1) - 4: $t7 := borrow_field<0xc0ffee::m::S>.b($t6) - 5: $t5 := read_ref($t7) - 6: m::foo($t0, $t2, $t5) - 7: return () + var $t2: &signer + var $t3: u64 + var $t4: &0xc0ffee::m::S + var $t5: &u64 + var $t6: u64 + var $t7: &0xc0ffee::m::S + var $t8: &u64 + 0: $t2 := infer($t0) + 1: $t4 := borrow_local($t1) + 2: $t5 := borrow_field<0xc0ffee::m::S>.a($t4) + 3: $t3 := read_ref($t5) + 4: $t7 := borrow_local($t1) + 5: $t8 := borrow_field<0xc0ffee::m::S>.b($t7) + 6: $t6 := read_ref($t8) + 7: m::foo($t2, $t3, $t6) + 8: return () } ============ after LiveVarAnalysisProcessor: ================ @@ -37,28 +39,31 @@ fun m::foo($t0: &signer, $t1: u64, $t2: u64) { [variant baseline] public fun m::test($t0: &signer, $t1: 0xc0ffee::m::S) { - var $t2: u64 - var $t3: &0xc0ffee::m::S - var $t4: &u64 - var $t5: u64 - var $t6: &0xc0ffee::m::S [unused] - var $t7: &u64 [unused] + var $t2: &signer [unused] + var $t3: u64 + var $t4: &0xc0ffee::m::S + var $t5: &u64 + var $t6: u64 + var $t7: &0xc0ffee::m::S [unused] + var $t8: &u64 [unused] # live vars: $t0, $t1 - 0: $t3 := borrow_local($t1) - # live vars: $t0, $t1, $t3 - 1: $t4 := borrow_field<0xc0ffee::m::S>.a($t3) + 0: $t0 := move($t0) + # live vars: $t0, $t1 + 1: $t4 := borrow_local($t1) # live vars: $t0, $t1, $t4 - 2: $t2 := read_ref($t4) - # live vars: $t0, $t1, $t2 - 3: $t3 := borrow_local($t1) - # live vars: $t0, $t2, $t3 - 4: $t4 := borrow_field<0xc0ffee::m::S>.b($t3) - # live vars: $t0, $t2, $t4 - 5: $t5 := read_ref($t4) - # live vars: $t0, $t2, $t5 - 6: m::foo($t0, $t2, $t5) + 2: $t5 := borrow_field<0xc0ffee::m::S>.a($t4) + # live vars: $t0, $t1, $t5 + 3: $t3 := read_ref($t5) + # live vars: $t0, $t1, $t3 + 4: $t4 := borrow_local($t1) + # live vars: $t0, $t3, $t4 + 5: $t5 := borrow_field<0xc0ffee::m::S>.b($t4) + # live vars: $t0, $t3, $t5 + 6: $t6 := read_ref($t5) + # live vars: $t0, $t3, $t6 + 7: m::foo($t0, $t3, $t6) # live vars: - 7: return () + 8: return () } @@ -77,22 +82,16 @@ B0: 2: Ret } public test(Arg0: &signer, Arg1: S) /* def_idx: 1 */ { -L2: loc0: u64 -L3: loc1: u64 B0: - 0: ImmBorrowLoc[1](Arg1: S) - 1: ImmBorrowField[0](S.a: u64) - 2: ReadRef - 3: ImmBorrowLoc[1](Arg1: S) - 4: ImmBorrowField[1](S.b: u64) - 5: ReadRef - 6: StLoc[2](loc0: u64) - 7: StLoc[3](loc1: u64) - 8: MoveLoc[0](Arg0: &signer) - 9: MoveLoc[3](loc1: u64) - 10: MoveLoc[2](loc0: u64) - 11: Call foo(&signer, u64, u64) - 12: Ret + 0: MoveLoc[0](Arg0: &signer) + 1: ImmBorrowLoc[1](Arg1: S) + 2: ImmBorrowField[0](S.a: u64) + 3: ReadRef + 4: ImmBorrowLoc[1](Arg1: S) + 5: ImmBorrowField[1](S.b: u64) + 6: ReadRef + 7: Call foo(&signer, u64, u64) + 8: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_06.exp b/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_06.exp index 937040361d411..0f65187b98c3e 100644 --- a/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_06.exp +++ b/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_06.exp @@ -33,32 +33,36 @@ public fun m::test($t0: &mut 0xc0ffee::m::S, $t1: 0xc0ffee::m::S) { var $t2: u64 var $t3: bool var $t4: u64 - var $t5: &mut 0xc0ffee::m::S - var $t6: u64 - var $t7: &mut 0xc0ffee::m::S - var $t8: u64 + var $t5: u64 + var $t6: &mut 0xc0ffee::m::S + var $t7: u64 + var $t8: &mut 0xc0ffee::m::S var $t9: u64 + var $t10: u64 + var $t11: u64 0: $t2 := 0 1: label L0 - 2: $t4 := 42 - 3: $t3 := <($t2, $t4) - 4: if ($t3) goto 5 else goto 14 - 5: label L2 - 6: $t5 := infer($t0) - 7: $t7 := borrow_local($t1) - 8: $t6 := m::bar($t7, $t2) - 9: m::foo($t5, $t6) - 10: $t9 := 1 - 11: $t8 := +($t2, $t9) - 12: $t2 := infer($t8) - 13: goto 16 - 14: label L3 + 2: $t4 := infer($t2) + 3: $t5 := 42 + 4: $t3 := <($t4, $t5) + 5: if ($t3) goto 6 else goto 16 + 6: label L2 + 7: $t6 := infer($t0) + 8: $t8 := borrow_local($t1) + 9: $t7 := m::bar($t8, $t2) + 10: m::foo($t6, $t7) + 11: $t10 := infer($t2) + 12: $t11 := 1 + 13: $t9 := +($t10, $t11) + 14: $t2 := infer($t9) 15: goto 18 - 16: label L4 - 17: goto 1 - 18: label L1 - 19: m::destroy($t1) - 20: return () + 16: label L3 + 17: goto 20 + 18: label L4 + 19: goto 1 + 20: label L1 + 21: m::destroy($t1) + 22: return () } ============ after LiveVarAnalysisProcessor: ================ @@ -72,7 +76,9 @@ fun m::bar($t0: &mut 0xc0ffee::m::S, $t1: u64): u64 { # live vars: $t1, $t3 1: write_ref($t3, $t1) # live vars: $t1 - 2: return $t1 + 2: $t1 := move($t1) + # live vars: $t1 + 3: return $t1 } @@ -103,47 +109,53 @@ public fun m::test($t0: &mut 0xc0ffee::m::S, $t1: 0xc0ffee::m::S) { var $t2: u64 var $t3: bool var $t4: u64 - var $t5: &mut 0xc0ffee::m::S - var $t6: u64 [unused] - var $t7: &mut 0xc0ffee::m::S - var $t8: u64 [unused] + var $t5: u64 + var $t6: &mut 0xc0ffee::m::S + var $t7: u64 [unused] + var $t8: &mut 0xc0ffee::m::S var $t9: u64 [unused] + var $t10: u64 [unused] + var $t11: u64 [unused] # live vars: $t0, $t1 0: $t2 := 0 # live vars: $t0, $t1, $t2 1: label L0 # live vars: $t0, $t1, $t2 - 2: $t4 := 42 + 2: $t4 := copy($t2) # live vars: $t0, $t1, $t2, $t4 - 3: $t3 := <($t2, $t4) + 3: $t5 := 42 + # live vars: $t0, $t1, $t2, $t4, $t5 + 4: $t3 := <($t4, $t5) # live vars: $t0, $t1, $t2, $t3 - 4: if ($t3) goto 5 else goto 14 + 5: if ($t3) goto 6 else goto 16 # live vars: $t0, $t1, $t2 - 5: label L2 + 6: label L2 # live vars: $t0, $t1, $t2 - 6: $t5 := copy($t0) - # live vars: $t0, $t1, $t2, $t5 - 7: $t7 := borrow_local($t1) - # live vars: $t0, $t1, $t2, $t5, $t7 - 8: $t4 := m::bar($t7, $t2) - # live vars: $t0, $t1, $t2, $t4, $t5 - 9: m::foo($t5, $t4) + 7: $t6 := copy($t0) + # live vars: $t0, $t1, $t2, $t6 + 8: $t8 := borrow_local($t1) + # live vars: $t0, $t1, $t2, $t6, $t8 + 9: $t4 := m::bar($t8, $t2) + # live vars: $t0, $t1, $t2, $t4, $t6 + 10: m::foo($t6, $t4) # live vars: $t0, $t1, $t2 - 10: $t4 := 1 - # live vars: $t0, $t1, $t2, $t4 - 11: $t4 := +($t2, $t4) + 11: $t4 := move($t2) + # live vars: $t0, $t1, $t4 + 12: $t5 := 1 + # live vars: $t0, $t1, $t4, $t5 + 13: $t4 := +($t4, $t5) # live vars: $t0, $t1, $t4 - 12: $t2 := move($t4) + 14: $t2 := move($t4) # live vars: $t0, $t1, $t2 - 13: goto 1 + 15: goto 1 # live vars: $t0, $t1, $t2 - 14: label L3 + 16: label L3 # live vars: $t0, $t1 - 15: drop($t0) + 17: drop($t0) # live vars: $t1 - 16: m::destroy($t1) + 18: m::destroy($t1) # live vars: - 17: return () + 19: return () } @@ -186,7 +198,6 @@ B0: } public test(Arg0: &mut S, Arg1: S) /* def_idx: 3 */ { L2: loc0: u64 -L3: loc1: u64 B0: 0: LdU64(0) 1: StLoc[2](loc0: u64) diff --git a/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_07.exp b/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_07.exp index 2b2cd73ef54e5..e2018fce1b597 100644 --- a/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_07.exp +++ b/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_07.exp @@ -22,20 +22,24 @@ public fun m::test($t0: &mut 0xc0ffee::m::S, $t1: u64) { var $t3: &mut u64 var $t4: u64 var $t5: u64 - var $t6: &u64 - var $t7: u64 + var $t6: u64 + var $t7: &u64 var $t8: u64 - var $t9: &u64 + var $t9: u64 + var $t10: u64 + var $t11: &u64 0: $t3 := borrow_field<0xc0ffee::m::S>.x($t0) - 1: $t6 := borrow_field<0xc0ffee::m::S>.y($t0) - 2: $t5 := read_ref($t6) - 3: $t4 := /($t1, $t5) - 4: $t2 := m::foo($t3, $t4) - 5: $t9 := borrow_field<0xc0ffee::m::S>.y($t0) - 6: $t8 := read_ref($t9) - 7: $t7 := /($t1, $t8) - 8: m::bar($t2, $t7) - 9: return () + 1: $t5 := infer($t1) + 2: $t7 := borrow_field<0xc0ffee::m::S>.y($t0) + 3: $t6 := read_ref($t7) + 4: $t4 := /($t5, $t6) + 5: $t2 := m::foo($t3, $t4) + 6: $t9 := infer($t1) + 7: $t11 := borrow_field<0xc0ffee::m::S>.y($t0) + 8: $t10 := read_ref($t11) + 9: $t8 := /($t9, $t10) + 10: m::bar($t2, $t8) + 11: return () } ============ after LiveVarAnalysisProcessor: ================ @@ -55,7 +59,9 @@ fun m::foo($t0: &mut u64, $t1: u64): &mut u64 { # live vars: $t0, $t1 0: write_ref($t0, $t1) # live vars: $t0 - 1: return $t0 + 1: $t0 := move($t0) + # live vars: $t0 + 2: return $t0 } @@ -65,30 +71,36 @@ public fun m::test($t0: &mut 0xc0ffee::m::S, $t1: u64) { var $t3: &mut u64 var $t4: u64 [unused] var $t5: u64 - var $t6: &u64 - var $t7: u64 [unused] + var $t6: u64 + var $t7: &u64 var $t8: u64 [unused] - var $t9: &u64 [unused] + var $t9: u64 [unused] + var $t10: u64 [unused] + var $t11: &u64 [unused] # live vars: $t0, $t1 0: $t3 := borrow_field<0xc0ffee::m::S>.x($t0) # live vars: $t0, $t1, $t3 - 1: $t6 := borrow_field<0xc0ffee::m::S>.y($t0) - # live vars: $t0, $t1, $t3, $t6 - 2: $t5 := read_ref($t6) + 1: $t5 := copy($t1) # live vars: $t0, $t1, $t3, $t5 - 3: $t5 := /($t1, $t5) + 2: $t7 := borrow_field<0xc0ffee::m::S>.y($t0) + # live vars: $t0, $t1, $t3, $t5, $t7 + 3: $t6 := read_ref($t7) + # live vars: $t0, $t1, $t3, $t5, $t6 + 4: $t5 := /($t5, $t6) # live vars: $t0, $t1, $t3, $t5 - 4: $t3 := m::foo($t3, $t5) + 5: $t3 := m::foo($t3, $t5) + # live vars: $t0, $t1, $t3 + 6: $t1 := move($t1) # live vars: $t0, $t1, $t3 - 5: $t6 := borrow_field<0xc0ffee::m::S>.y($t0) - # live vars: $t1, $t3, $t6 - 6: $t5 := read_ref($t6) + 7: $t7 := borrow_field<0xc0ffee::m::S>.y($t0) + # live vars: $t1, $t3, $t7 + 8: $t5 := read_ref($t7) # live vars: $t1, $t3, $t5 - 7: $t1 := /($t1, $t5) + 9: $t1 := /($t1, $t5) # live vars: $t1, $t3 - 8: m::bar($t3, $t1) + 10: m::bar($t3, $t1) # live vars: - 9: return () + 11: return () } @@ -116,27 +128,22 @@ B0: 4: Ret } public test(Arg0: &mut S, Arg1: u64) /* def_idx: 2 */ { -L2: loc0: u64 B0: 0: CopyLoc[0](Arg0: &mut S) 1: MutBorrowField[0](S.x: u64) - 2: CopyLoc[0](Arg0: &mut S) - 3: ImmBorrowField[1](S.y: u64) - 4: ReadRef - 5: StLoc[2](loc0: u64) - 6: CopyLoc[1](Arg1: u64) - 7: MoveLoc[2](loc0: u64) - 8: Div - 9: Call foo(&mut u64, u64): &mut u64 - 10: MoveLoc[0](Arg0: &mut S) - 11: ImmBorrowField[1](S.y: u64) - 12: ReadRef - 13: StLoc[2](loc0: u64) - 14: MoveLoc[1](Arg1: u64) - 15: MoveLoc[2](loc0: u64) - 16: Div - 17: Call bar(&mut u64, u64) - 18: Ret + 2: CopyLoc[1](Arg1: u64) + 3: CopyLoc[0](Arg0: &mut S) + 4: ImmBorrowField[1](S.y: u64) + 5: ReadRef + 6: Div + 7: Call foo(&mut u64, u64): &mut u64 + 8: MoveLoc[1](Arg1: u64) + 9: MoveLoc[0](Arg0: &mut S) + 10: ImmBorrowField[1](S.y: u64) + 11: ReadRef + 12: Div + 13: Call bar(&mut u64, u64) + 14: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_08.exp b/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_08.exp index f8557d046d801..fec0212ea2814 100644 --- a/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_08.exp +++ b/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_08.exp @@ -20,20 +20,24 @@ public fun m::test($t0: &0xc0ffee::m::S, $t1: u64) { var $t3: &u64 var $t4: u64 var $t5: u64 - var $t6: &u64 - var $t7: u64 + var $t6: u64 + var $t7: &u64 var $t8: u64 - var $t9: &u64 + var $t9: u64 + var $t10: u64 + var $t11: &u64 0: $t3 := borrow_field<0xc0ffee::m::S>.x($t0) - 1: $t6 := borrow_field<0xc0ffee::m::S>.y($t0) - 2: $t5 := read_ref($t6) - 3: $t4 := /($t1, $t5) - 4: $t2 := m::foo($t3, $t4) - 5: $t9 := borrow_field<0xc0ffee::m::S>.y($t0) - 6: $t8 := read_ref($t9) - 7: $t7 := /($t1, $t8) - 8: m::bar($t2, $t7) - 9: return () + 1: $t5 := infer($t1) + 2: $t7 := borrow_field<0xc0ffee::m::S>.y($t0) + 3: $t6 := read_ref($t7) + 4: $t4 := /($t5, $t6) + 5: $t2 := m::foo($t3, $t4) + 6: $t9 := infer($t1) + 7: $t11 := borrow_field<0xc0ffee::m::S>.y($t0) + 8: $t10 := read_ref($t11) + 9: $t8 := /($t9, $t10) + 10: m::bar($t2, $t8) + 11: return () } ============ after LiveVarAnalysisProcessor: ================ @@ -51,7 +55,9 @@ fun m::bar($t0: &u64, $t1: u64) { fun m::foo($t0: &u64, $t1: u64): &u64 { var $t2: &u64 [unused] # live vars: $t0, $t1 - 0: return $t0 + 0: $t0 := move($t0) + # live vars: $t0 + 1: return $t0 } @@ -61,30 +67,36 @@ public fun m::test($t0: &0xc0ffee::m::S, $t1: u64) { var $t3: &u64 var $t4: u64 [unused] var $t5: u64 - var $t6: &u64 - var $t7: u64 [unused] + var $t6: u64 + var $t7: &u64 var $t8: u64 [unused] - var $t9: &u64 [unused] + var $t9: u64 [unused] + var $t10: u64 [unused] + var $t11: &u64 [unused] # live vars: $t0, $t1 0: $t3 := borrow_field<0xc0ffee::m::S>.x($t0) # live vars: $t0, $t1, $t3 - 1: $t6 := borrow_field<0xc0ffee::m::S>.y($t0) - # live vars: $t0, $t1, $t3, $t6 - 2: $t5 := read_ref($t6) + 1: $t5 := copy($t1) # live vars: $t0, $t1, $t3, $t5 - 3: $t5 := /($t1, $t5) + 2: $t7 := borrow_field<0xc0ffee::m::S>.y($t0) + # live vars: $t0, $t1, $t3, $t5, $t7 + 3: $t6 := read_ref($t7) + # live vars: $t0, $t1, $t3, $t5, $t6 + 4: $t5 := /($t5, $t6) # live vars: $t0, $t1, $t3, $t5 - 4: $t3 := m::foo($t3, $t5) + 5: $t3 := m::foo($t3, $t5) # live vars: $t0, $t1, $t3 - 5: $t6 := borrow_field<0xc0ffee::m::S>.y($t0) - # live vars: $t1, $t3, $t6 - 6: $t5 := read_ref($t6) + 6: $t1 := move($t1) + # live vars: $t0, $t1, $t3 + 7: $t7 := borrow_field<0xc0ffee::m::S>.y($t0) + # live vars: $t1, $t3, $t7 + 8: $t5 := read_ref($t7) # live vars: $t1, $t3, $t5 - 7: $t1 := /($t1, $t5) + 9: $t1 := /($t1, $t5) # live vars: $t1, $t3 - 8: m::bar($t3, $t1) + 10: m::bar($t3, $t1) # live vars: - 9: return () + 11: return () } @@ -108,27 +120,22 @@ B0: 1: Ret } public test(Arg0: &S, Arg1: u64) /* def_idx: 2 */ { -L2: loc0: u64 B0: 0: CopyLoc[0](Arg0: &S) 1: ImmBorrowField[0](S.x: u64) - 2: CopyLoc[0](Arg0: &S) - 3: ImmBorrowField[1](S.y: u64) - 4: ReadRef - 5: StLoc[2](loc0: u64) - 6: CopyLoc[1](Arg1: u64) - 7: MoveLoc[2](loc0: u64) - 8: Div - 9: Call foo(&u64, u64): &u64 - 10: MoveLoc[0](Arg0: &S) - 11: ImmBorrowField[1](S.y: u64) - 12: ReadRef - 13: StLoc[2](loc0: u64) - 14: MoveLoc[1](Arg1: u64) - 15: MoveLoc[2](loc0: u64) - 16: Div - 17: Call bar(&u64, u64) - 18: Ret + 2: CopyLoc[1](Arg1: u64) + 3: CopyLoc[0](Arg0: &S) + 4: ImmBorrowField[1](S.y: u64) + 5: ReadRef + 6: Div + 7: Call foo(&u64, u64): &u64 + 8: MoveLoc[1](Arg1: u64) + 9: MoveLoc[0](Arg0: &S) + 10: ImmBorrowField[1](S.y: u64) + 11: ReadRef + 12: Div + 13: Call bar(&u64, u64) + 14: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_09.exp b/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_09.exp index df94d0ba33f15..ecf2efc2599ef 100644 --- a/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_09.exp +++ b/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_09.exp @@ -33,26 +33,28 @@ public fun m::test($t0: &mut 0xc0ffee::m::S, $t1: u64) { var $t6: &u64 var $t7: u64 var $t8: u64 - var $t9: &u64 - var $t10: &mut u64 + var $t9: u64 + var $t10: &u64 var $t11: &mut u64 + var $t12: &mut u64 0: $t3 := borrow_field<0xc0ffee::m::S>.x($t0) 1: $t2 := m::foo($t3) 2: $t6 := borrow_field<0xc0ffee::m::S>.x($t0) 3: $t5 := read_ref($t6) - 4: $t9 := borrow_field<0xc0ffee::m::S>.y($t0) - 5: $t8 := read_ref($t9) - 6: $t7 := *($t2, $t8) - 7: $t4 := ==($t5, $t7) - 8: if ($t4) goto 9 else goto 14 - 9: label L0 - 10: $t11 := borrow_field<0xc0ffee::m::S>.x($t0) - 11: $t10 := m::bar($t11, $t2) - 12: m::baz($t10, $t1) - 13: goto 15 - 14: label L1 - 15: label L2 - 16: return () + 4: $t8 := infer($t2) + 5: $t10 := borrow_field<0xc0ffee::m::S>.y($t0) + 6: $t9 := read_ref($t10) + 7: $t7 := *($t8, $t9) + 8: $t4 := ==($t5, $t7) + 9: if ($t4) goto 10 else goto 15 + 10: label L0 + 11: $t12 := borrow_field<0xc0ffee::m::S>.x($t0) + 12: $t11 := m::bar($t12, $t2) + 13: m::baz($t11, $t1) + 14: goto 16 + 15: label L1 + 16: label L2 + 17: return () } ============ after LiveVarAnalysisProcessor: ================ @@ -63,7 +65,9 @@ fun m::bar($t0: &mut u64, $t1: u64): &mut u64 { # live vars: $t0, $t1 0: write_ref($t0, $t1) # live vars: $t0 - 1: return $t0 + 1: $t0 := move($t0) + # live vars: $t0 + 2: return $t0 } @@ -95,9 +99,10 @@ public fun m::test($t0: &mut 0xc0ffee::m::S, $t1: u64) { var $t6: &u64 [unused] var $t7: u64 [unused] var $t8: u64 - var $t9: &u64 [unused] - var $t10: &mut u64 [unused] - var $t11: &mut u64 + var $t9: u64 + var $t10: &u64 [unused] + var $t11: &mut u64 [unused] + var $t12: &mut u64 # live vars: $t0, $t1 0: $t3 := borrow_field<0xc0ffee::m::S>.x($t0) # live vars: $t0, $t1, $t3 @@ -107,33 +112,35 @@ public fun m::test($t0: &mut 0xc0ffee::m::S, $t1: u64) { # live vars: $t0, $t1, $t2, $t3 3: $t5 := read_ref($t3) # live vars: $t0, $t1, $t2, $t5 - 4: $t3 := borrow_field<0xc0ffee::m::S>.y($t0) - # live vars: $t0, $t1, $t2, $t3, $t5 - 5: $t8 := read_ref($t3) + 4: $t8 := copy($t2) # live vars: $t0, $t1, $t2, $t5, $t8 - 6: $t8 := *($t2, $t8) + 5: $t3 := borrow_field<0xc0ffee::m::S>.y($t0) + # live vars: $t0, $t1, $t2, $t3, $t5, $t8 + 6: $t9 := read_ref($t3) + # live vars: $t0, $t1, $t2, $t5, $t8, $t9 + 7: $t8 := *($t8, $t9) # live vars: $t0, $t1, $t2, $t5, $t8 - 7: $t4 := ==($t5, $t8) + 8: $t4 := ==($t5, $t8) # live vars: $t0, $t1, $t2, $t4 - 8: if ($t4) goto 9 else goto 15 + 9: if ($t4) goto 10 else goto 16 # live vars: $t0, $t1, $t2 - 9: label L0 + 10: label L0 # live vars: $t0, $t1, $t2 - 10: $t11 := borrow_field<0xc0ffee::m::S>.x($t0) - # live vars: $t1, $t2, $t11 - 11: $t11 := m::bar($t11, $t2) - # live vars: $t1, $t11 - 12: m::baz($t11, $t1) + 11: $t12 := borrow_field<0xc0ffee::m::S>.x($t0) + # live vars: $t1, $t2, $t12 + 12: $t12 := m::bar($t12, $t2) + # live vars: $t1, $t12 + 13: m::baz($t12, $t1) # live vars: - 13: label L2 + 14: label L2 # live vars: - 14: return () + 15: return () # live vars: $t0, $t1, $t2 - 15: label L1 + 16: label L1 # live vars: $t0 - 16: drop($t0) + 17: drop($t0) # live vars: - 17: goto 13 + 18: goto 14 } @@ -168,7 +175,6 @@ B0: } public test(Arg0: &mut S, Arg1: u64) /* def_idx: 3 */ { L2: loc0: u64 -L3: loc1: u64 B0: 0: CopyLoc[0](Arg0: &mut S) 1: ImmBorrowField[0](S.x: u64) @@ -177,28 +183,26 @@ B0: 4: CopyLoc[0](Arg0: &mut S) 5: ImmBorrowField[0](S.x: u64) 6: ReadRef - 7: CopyLoc[0](Arg0: &mut S) - 8: ImmBorrowField[1](S.y: u64) - 9: ReadRef - 10: StLoc[3](loc1: u64) - 11: CopyLoc[2](loc0: u64) - 12: MoveLoc[3](loc1: u64) - 13: Mul - 14: Eq - 15: BrFalse(23) + 7: CopyLoc[2](loc0: u64) + 8: CopyLoc[0](Arg0: &mut S) + 9: ImmBorrowField[1](S.y: u64) + 10: ReadRef + 11: Mul + 12: Eq + 13: BrFalse(21) B1: - 16: MoveLoc[0](Arg0: &mut S) - 17: MutBorrowField[0](S.x: u64) - 18: MoveLoc[2](loc0: u64) - 19: Call bar(&mut u64, u64): &mut u64 - 20: MoveLoc[1](Arg1: u64) - 21: Call baz(&mut u64, u64) + 14: MoveLoc[0](Arg0: &mut S) + 15: MutBorrowField[0](S.x: u64) + 16: MoveLoc[2](loc0: u64) + 17: Call bar(&mut u64, u64): &mut u64 + 18: MoveLoc[1](Arg1: u64) + 19: Call baz(&mut u64, u64) B2: - 22: Ret + 20: Ret B3: - 23: MoveLoc[0](Arg0: &mut S) - 24: Pop - 25: Branch(22) + 21: MoveLoc[0](Arg0: &mut S) + 22: Pop + 23: Branch(20) } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_10.exp b/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_10.exp index ff95289d51c83..f12e640934cca 100644 --- a/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_10.exp +++ b/third_party/move/move-compiler-v2/tests/eager-pushes/framework_reduced_10.exp @@ -19,38 +19,46 @@ fun m::foo($t0: &u64): u64 { public fun m::test($t0: &mut 0xc0ffee::m::S, $t1: u64) { var $t2: u64 var $t3: u64 - var $t4: &u64 - var $t5: u64 - var $t6: &u64 - var $t7: bool - var $t8: &mut u64 + var $t4: u64 + var $t5: &u64 + var $t6: u64 + var $t7: &u64 + var $t8: bool var $t9: u64 - var $t10: u64 + var $t10: &mut u64 var $t11: u64 var $t12: u64 - 0: $t4 := borrow_field<0xc0ffee::m::S>.x($t0) - 1: $t3 := read_ref($t4) - 2: $t2 := /($t1, $t3) - 3: $t6 := borrow_field<0xc0ffee::m::S>.y($t0) - 4: $t5 := m::foo($t6) - 5: label L0 - 6: $t7 := <($t2, $t5) - 7: if ($t7) goto 8 else goto 17 - 8: label L2 - 9: $t8 := borrow_field<0xc0ffee::m::S>.z($t0) - 10: $t10 := 1 - 11: $t9 := -($t2, $t10) - 12: m::bar($t8, $t9) - 13: $t12 := 1 - 14: $t11 := +($t2, $t12) - 15: $t2 := infer($t11) - 16: goto 19 - 17: label L3 - 18: goto 21 - 19: label L4 - 20: goto 5 - 21: label L1 - 22: return () + var $t13: u64 + var $t14: u64 + var $t15: u64 + var $t16: u64 + 0: $t3 := infer($t1) + 1: $t5 := borrow_field<0xc0ffee::m::S>.x($t0) + 2: $t4 := read_ref($t5) + 3: $t2 := /($t3, $t4) + 4: $t7 := borrow_field<0xc0ffee::m::S>.y($t0) + 5: $t6 := m::foo($t7) + 6: label L0 + 7: $t9 := infer($t2) + 8: $t8 := <($t9, $t6) + 9: if ($t8) goto 10 else goto 21 + 10: label L2 + 11: $t10 := borrow_field<0xc0ffee::m::S>.z($t0) + 12: $t12 := infer($t2) + 13: $t13 := 1 + 14: $t11 := -($t12, $t13) + 15: m::bar($t10, $t11) + 16: $t15 := infer($t2) + 17: $t16 := 1 + 18: $t14 := +($t15, $t16) + 19: $t2 := infer($t14) + 20: goto 23 + 21: label L3 + 22: goto 25 + 23: label L4 + 24: goto 6 + 25: label L1 + 26: return () } ============ after LiveVarAnalysisProcessor: ================ @@ -77,56 +85,68 @@ fun m::foo($t0: &u64): u64 { [variant baseline] public fun m::test($t0: &mut 0xc0ffee::m::S, $t1: u64) { var $t2: u64 [unused] - var $t3: u64 - var $t4: &u64 - var $t5: u64 [unused] - var $t6: &u64 [unused] - var $t7: bool - var $t8: &mut u64 - var $t9: u64 [unused] - var $t10: u64 + var $t3: u64 [unused] + var $t4: u64 + var $t5: &u64 + var $t6: u64 [unused] + var $t7: &u64 [unused] + var $t8: bool + var $t9: u64 + var $t10: &mut u64 var $t11: u64 [unused] var $t12: u64 [unused] + var $t13: u64 + var $t14: u64 [unused] + var $t15: u64 [unused] + var $t16: u64 [unused] + # live vars: $t0, $t1 + 0: $t1 := move($t1) # live vars: $t0, $t1 - 0: $t4 := borrow_field<0xc0ffee::m::S>.x($t0) + 1: $t5 := borrow_field<0xc0ffee::m::S>.x($t0) + # live vars: $t0, $t1, $t5 + 2: $t4 := read_ref($t5) # live vars: $t0, $t1, $t4 - 1: $t3 := read_ref($t4) - # live vars: $t0, $t1, $t3 - 2: $t1 := /($t1, $t3) + 3: $t1 := /($t1, $t4) # live vars: $t0, $t1 - 3: $t4 := borrow_field<0xc0ffee::m::S>.y($t0) + 4: $t5 := borrow_field<0xc0ffee::m::S>.y($t0) + # live vars: $t0, $t1, $t5 + 5: $t4 := m::foo($t5) + # live vars: $t0, $t1, $t4 + 6: label L0 + # live vars: $t0, $t1, $t4 + 7: $t9 := copy($t1) + # live vars: $t0, $t1, $t4, $t9 + 8: $t8 := <($t9, $t4) + # live vars: $t0, $t1, $t4, $t8 + 9: if ($t8) goto 10 else goto 21 # live vars: $t0, $t1, $t4 - 4: $t3 := m::foo($t4) - # live vars: $t0, $t1, $t3 - 5: label L0 - # live vars: $t0, $t1, $t3 - 6: $t7 := <($t1, $t3) - # live vars: $t0, $t1, $t3, $t7 - 7: if ($t7) goto 8 else goto 17 - # live vars: $t0, $t1, $t3 - 8: label L2 - # live vars: $t0, $t1, $t3 - 9: $t8 := borrow_field<0xc0ffee::m::S>.z($t0) - # live vars: $t0, $t1, $t3, $t8 - 10: $t10 := 1 - # live vars: $t0, $t1, $t3, $t8, $t10 - 11: $t10 := -($t1, $t10) - # live vars: $t0, $t1, $t3, $t8, $t10 - 12: m::bar($t8, $t10) - # live vars: $t0, $t1, $t3 - 13: $t10 := 1 - # live vars: $t0, $t1, $t3, $t10 - 14: $t10 := +($t1, $t10) - # live vars: $t0, $t3, $t10 - 15: $t1 := move($t10) - # live vars: $t0, $t1, $t3 - 16: goto 5 - # live vars: $t0, $t1, $t3 - 17: label L3 + 10: label L2 + # live vars: $t0, $t1, $t4 + 11: $t10 := borrow_field<0xc0ffee::m::S>.z($t0) + # live vars: $t0, $t1, $t4, $t10 + 12: $t9 := copy($t1) + # live vars: $t0, $t1, $t4, $t9, $t10 + 13: $t13 := 1 + # live vars: $t0, $t1, $t4, $t9, $t10, $t13 + 14: $t9 := -($t9, $t13) + # live vars: $t0, $t1, $t4, $t9, $t10 + 15: m::bar($t10, $t9) + # live vars: $t0, $t1, $t4 + 16: $t9 := move($t1) + # live vars: $t0, $t4, $t9 + 17: $t13 := 1 + # live vars: $t0, $t4, $t9, $t13 + 18: $t9 := +($t9, $t13) + # live vars: $t0, $t4, $t9 + 19: $t1 := move($t9) + # live vars: $t0, $t1, $t4 + 20: goto 6 + # live vars: $t0, $t1, $t4 + 21: label L3 # live vars: $t0 - 18: drop($t0) + 22: drop($t0) # live vars: - 19: return () + 23: return () } @@ -154,41 +174,38 @@ B0: } public test(Arg0: &mut S, Arg1: u64) /* def_idx: 2 */ { L2: loc0: u64 -L3: loc1: u64 B0: - 0: CopyLoc[0](Arg0: &mut S) - 1: ImmBorrowField[0](S.x: u64) - 2: ReadRef - 3: StLoc[2](loc0: u64) - 4: MoveLoc[1](Arg1: u64) - 5: MoveLoc[2](loc0: u64) - 6: Div - 7: StLoc[1](Arg1: u64) - 8: CopyLoc[0](Arg0: &mut S) - 9: ImmBorrowField[1](S.y: u64) - 10: Call foo(&u64): u64 - 11: StLoc[2](loc0: u64) + 0: MoveLoc[1](Arg1: u64) + 1: CopyLoc[0](Arg0: &mut S) + 2: ImmBorrowField[0](S.x: u64) + 3: ReadRef + 4: Div + 5: StLoc[1](Arg1: u64) + 6: CopyLoc[0](Arg0: &mut S) + 7: ImmBorrowField[1](S.y: u64) + 8: Call foo(&u64): u64 + 9: StLoc[2](loc0: u64) B1: - 12: CopyLoc[1](Arg1: u64) - 13: CopyLoc[2](loc0: u64) - 14: Lt - 15: BrFalse(27) + 10: CopyLoc[1](Arg1: u64) + 11: CopyLoc[2](loc0: u64) + 12: Lt + 13: BrFalse(25) B2: - 16: CopyLoc[0](Arg0: &mut S) - 17: MutBorrowField[2](S.z: u64) - 18: CopyLoc[1](Arg1: u64) - 19: LdU64(1) - 20: Sub - 21: Call bar(&mut u64, u64) - 22: MoveLoc[1](Arg1: u64) - 23: LdU64(1) - 24: Add - 25: StLoc[1](Arg1: u64) - 26: Branch(12) + 14: CopyLoc[0](Arg0: &mut S) + 15: MutBorrowField[2](S.z: u64) + 16: CopyLoc[1](Arg1: u64) + 17: LdU64(1) + 18: Sub + 19: Call bar(&mut u64, u64) + 20: MoveLoc[1](Arg1: u64) + 21: LdU64(1) + 22: Add + 23: StLoc[1](Arg1: u64) + 24: Branch(10) B3: - 27: MoveLoc[0](Arg0: &mut S) - 28: Pop - 29: Ret + 25: MoveLoc[0](Arg0: &mut S) + 26: Pop + 27: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/eager-pushes/move_stdlib_reduced.exp b/third_party/move/move-compiler-v2/tests/eager-pushes/move_stdlib_reduced.exp index 2ebaeb0bea084..d4df43193625b 100644 --- a/third_party/move/move-compiler-v2/tests/eager-pushes/move_stdlib_reduced.exp +++ b/third_party/move/move-compiler-v2/tests/eager-pushes/move_stdlib_reduced.exp @@ -11,28 +11,32 @@ fun m::bar($t0: &mut u64, $t1: u64) { public fun m::foo($t0: &mut u64, $t1: u64) { var $t2: bool var $t3: u64 - var $t4: &mut u64 - var $t5: u64 + var $t4: u64 + var $t5: &mut u64 var $t6: u64 var $t7: u64 + var $t8: u64 + var $t9: u64 0: label L0 - 1: $t3 := 0 - 2: $t2 := >($t1, $t3) - 3: if ($t2) goto 4 else goto 12 - 4: label L2 - 5: $t4 := infer($t0) - 6: $t5 := m::one() - 7: m::bar($t4, $t5) - 8: $t7 := 1 - 9: $t6 := -($t1, $t7) - 10: $t1 := infer($t6) - 11: goto 14 - 12: label L3 + 1: $t3 := infer($t1) + 2: $t4 := 0 + 3: $t2 := >($t3, $t4) + 4: if ($t2) goto 5 else goto 14 + 5: label L2 + 6: $t5 := infer($t0) + 7: $t6 := m::one() + 8: m::bar($t5, $t6) + 9: $t8 := infer($t1) + 10: $t9 := 1 + 11: $t7 := -($t8, $t9) + 12: $t1 := infer($t7) 13: goto 16 - 14: label L4 - 15: goto 0 - 16: label L1 - 17: return () + 14: label L3 + 15: goto 18 + 16: label L4 + 17: goto 0 + 18: label L1 + 19: return () } @@ -58,40 +62,46 @@ fun m::bar($t0: &mut u64, $t1: u64) { public fun m::foo($t0: &mut u64, $t1: u64) { var $t2: bool var $t3: u64 - var $t4: &mut u64 - var $t5: u64 [unused] + var $t4: u64 + var $t5: &mut u64 var $t6: u64 [unused] var $t7: u64 [unused] + var $t8: u64 [unused] + var $t9: u64 [unused] # live vars: $t0, $t1 0: label L0 # live vars: $t0, $t1 - 1: $t3 := 0 + 1: $t3 := copy($t1) # live vars: $t0, $t1, $t3 - 2: $t2 := >($t1, $t3) + 2: $t4 := 0 + # live vars: $t0, $t1, $t3, $t4 + 3: $t2 := >($t3, $t4) # live vars: $t0, $t1, $t2 - 3: if ($t2) goto 4 else goto 12 + 4: if ($t2) goto 5 else goto 14 # live vars: $t0, $t1 - 4: label L2 + 5: label L2 # live vars: $t0, $t1 - 5: $t4 := copy($t0) - # live vars: $t0, $t1, $t4 - 6: $t3 := m::one() - # live vars: $t0, $t1, $t3, $t4 - 7: m::bar($t4, $t3) + 6: $t5 := copy($t0) + # live vars: $t0, $t1, $t5 + 7: $t3 := m::one() + # live vars: $t0, $t1, $t3, $t5 + 8: m::bar($t5, $t3) # live vars: $t0, $t1 - 8: $t3 := 1 - # live vars: $t0, $t1, $t3 - 9: $t3 := -($t1, $t3) + 9: $t3 := move($t1) + # live vars: $t0, $t3 + 10: $t4 := 1 + # live vars: $t0, $t3, $t4 + 11: $t3 := -($t3, $t4) # live vars: $t0, $t3 - 10: $t1 := move($t3) + 12: $t1 := move($t3) # live vars: $t0, $t1 - 11: goto 0 + 13: goto 0 # live vars: $t0, $t1 - 12: label L3 + 14: label L3 # live vars: $t0 - 13: drop($t0) + 15: drop($t0) # live vars: - 14: return () + 16: return () } @@ -118,7 +128,6 @@ B0: 3: Ret } public foo(Arg0: &mut u64, Arg1: u64) /* def_idx: 1 */ { -L2: loc0: u64 B0: 0: CopyLoc[1](Arg1: u64) 1: LdU64(0) diff --git a/third_party/move/move-compiler-v2/tests/eager-pushes/txn_reduced_01.exp b/third_party/move/move-compiler-v2/tests/eager-pushes/txn_reduced_01.exp index a36517680038a..834258b42a956 100644 --- a/third_party/move/move-compiler-v2/tests/eager-pushes/txn_reduced_01.exp +++ b/third_party/move/move-compiler-v2/tests/eager-pushes/txn_reduced_01.exp @@ -12,38 +12,44 @@ public fun m::test($t0: &signer, $t1: vector
, $t2: vector) { var $t4: &vector
var $t5: u64 var $t6: bool - var $t7: &address - var $t8: &vector
- var $t9: &u64 - var $t10: &vector - var $t11: address - var $t12: u64 - var $t13: u64 + var $t7: u64 + var $t8: &address + var $t9: &vector
+ var $t10: &u64 + var $t11: &vector + var $t12: &signer + var $t13: address var $t14: u64 + var $t15: u64 + var $t16: u64 + var $t17: u64 0: $t4 := borrow_local($t1) 1: $t3 := vector::length
($t4) 2: $t5 := 0 3: label L0 - 4: $t6 := <($t5, $t3) - 5: if ($t6) goto 6 else goto 18 - 6: label L2 - 7: $t8 := borrow_local($t1) - 8: $t7 := vector::borrow
($t8, $t5) - 9: $t10 := borrow_local($t2) - 10: $t9 := vector::borrow($t10, $t5) - 11: $t11 := read_ref($t7) - 12: $t12 := read_ref($t9) - 13: m::call_other($t0, $t11, $t12) - 14: $t14 := 1 - 15: $t13 := +($t5, $t14) - 16: $t5 := infer($t13) - 17: goto 20 - 18: label L3 - 19: goto 22 - 20: label L4 - 21: goto 3 - 22: label L1 - 23: return () + 4: $t7 := infer($t5) + 5: $t6 := <($t7, $t3) + 6: if ($t6) goto 7 else goto 21 + 7: label L2 + 8: $t9 := borrow_local($t1) + 9: $t8 := vector::borrow
($t9, $t5) + 10: $t11 := borrow_local($t2) + 11: $t10 := vector::borrow($t11, $t5) + 12: $t12 := infer($t0) + 13: $t13 := read_ref($t8) + 14: $t14 := read_ref($t10) + 15: m::call_other($t12, $t13, $t14) + 16: $t16 := infer($t5) + 17: $t17 := 1 + 18: $t15 := +($t16, $t17) + 19: $t5 := infer($t15) + 20: goto 23 + 21: label L3 + 22: goto 25 + 23: label L4 + 24: goto 3 + 25: label L1 + 26: return () } ============ after LiveVarAnalysisProcessor: ================ @@ -63,14 +69,17 @@ public fun m::test($t0: &signer, $t1: vector
, $t2: vector) { var $t4: &vector
var $t5: u64 var $t6: bool - var $t7: &address - var $t8: &vector
[unused] - var $t9: &u64 - var $t10: &vector - var $t11: address - var $t12: u64 - var $t13: u64 [unused] + var $t7: u64 + var $t8: &address + var $t9: &vector
[unused] + var $t10: &u64 + var $t11: &vector + var $t12: &signer + var $t13: address var $t14: u64 [unused] + var $t15: u64 [unused] + var $t16: u64 [unused] + var $t17: u64 # live vars: $t0, $t1, $t2 0: $t4 := borrow_local($t1) # live vars: $t0, $t1, $t2, $t4 @@ -80,39 +89,45 @@ public fun m::test($t0: &signer, $t1: vector
, $t2: vector) { # live vars: $t0, $t1, $t2, $t3, $t5 3: label L0 # live vars: $t0, $t1, $t2, $t3, $t5 - 4: $t6 := <($t5, $t3) + 4: $t7 := copy($t5) + # live vars: $t0, $t1, $t2, $t3, $t5, $t7 + 5: $t6 := <($t7, $t3) # live vars: $t0, $t1, $t2, $t3, $t5, $t6 - 5: if ($t6) goto 6 else goto 18 + 6: if ($t6) goto 7 else goto 21 # live vars: $t0, $t1, $t2, $t3, $t5 - 6: label L2 + 7: label L2 # live vars: $t0, $t1, $t2, $t3, $t5 - 7: $t4 := borrow_local($t1) + 8: $t4 := borrow_local($t1) # live vars: $t0, $t1, $t2, $t3, $t4, $t5 - 8: $t7 := vector::borrow
($t4, $t5) - # live vars: $t0, $t1, $t2, $t3, $t5, $t7 - 9: $t10 := borrow_local($t2) - # live vars: $t0, $t1, $t2, $t3, $t5, $t7, $t10 - 10: $t9 := vector::borrow($t10, $t5) - # live vars: $t0, $t1, $t2, $t3, $t5, $t7, $t9 - 11: $t11 := read_ref($t7) - # live vars: $t0, $t1, $t2, $t3, $t5, $t9, $t11 - 12: $t12 := read_ref($t9) - # live vars: $t0, $t1, $t2, $t3, $t5, $t11, $t12 - 13: m::call_other($t0, $t11, $t12) + 9: $t8 := vector::borrow
($t4, $t5) + # live vars: $t0, $t1, $t2, $t3, $t5, $t8 + 10: $t11 := borrow_local($t2) + # live vars: $t0, $t1, $t2, $t3, $t5, $t8, $t11 + 11: $t10 := vector::borrow($t11, $t5) + # live vars: $t0, $t1, $t2, $t3, $t5, $t8, $t10 + 12: $t12 := copy($t0) + # live vars: $t0, $t1, $t2, $t3, $t5, $t8, $t10, $t12 + 13: $t13 := read_ref($t8) + # live vars: $t0, $t1, $t2, $t3, $t5, $t10, $t12, $t13 + 14: $t7 := read_ref($t10) + # live vars: $t0, $t1, $t2, $t3, $t5, $t7, $t12, $t13 + 15: m::call_other($t12, $t13, $t7) # live vars: $t0, $t1, $t2, $t3, $t5 - 14: $t12 := 1 - # live vars: $t0, $t1, $t2, $t3, $t5, $t12 - 15: $t12 := +($t5, $t12) - # live vars: $t0, $t1, $t2, $t3, $t12 - 16: $t5 := move($t12) + 16: $t7 := move($t5) + # live vars: $t0, $t1, $t2, $t3, $t7 + 17: $t17 := 1 + # live vars: $t0, $t1, $t2, $t3, $t7, $t17 + 18: $t7 := +($t7, $t17) + # live vars: $t0, $t1, $t2, $t3, $t7 + 19: $t5 := move($t7) # live vars: $t0, $t1, $t2, $t3, $t5 - 17: goto 3 + 20: goto 3 # live vars: $t0, $t1, $t2, $t3, $t5 - 18: label L3 + 21: label L3 # live vars: $t0 - 19: drop($t0) + 22: drop($t0) # live vars: - 20: return () + 23: return () } @@ -130,10 +145,8 @@ B0: public test(Arg0: &signer, Arg1: vector
, Arg2: vector) /* def_idx: 1 */ { L3: loc0: u64 L4: loc1: u64 -L5: loc2: &u64 -L6: loc3: &address -L7: loc4: u64 -L8: loc5: address +L5: loc2: &address +L6: loc3: &u64 B0: 0: ImmBorrowLoc[1](Arg1: vector
) 1: VecLen(3) @@ -144,33 +157,31 @@ B1: 5: CopyLoc[4](loc1: u64) 6: CopyLoc[3](loc0: u64) 7: Lt - 8: BrFalse(30) + 8: BrFalse(28) B2: 9: ImmBorrowLoc[1](Arg1: vector
) 10: CopyLoc[4](loc1: u64) 11: VecImmBorrow(3) - 12: ImmBorrowLoc[2](Arg2: vector) - 13: CopyLoc[4](loc1: u64) - 14: VecImmBorrow(4) - 15: StLoc[5](loc2: &u64) - 16: ReadRef - 17: MoveLoc[5](loc2: &u64) - 18: ReadRef - 19: StLoc[7](loc4: u64) - 20: StLoc[8](loc5: address) - 21: CopyLoc[0](Arg0: &signer) - 22: MoveLoc[8](loc5: address) - 23: MoveLoc[7](loc4: u64) - 24: Call call_other(&signer, address, u64) - 25: MoveLoc[4](loc1: u64) - 26: LdU64(1) - 27: Add - 28: StLoc[4](loc1: u64) - 29: Branch(5) + 12: StLoc[5](loc2: &address) + 13: ImmBorrowLoc[2](Arg2: vector) + 14: CopyLoc[4](loc1: u64) + 15: VecImmBorrow(4) + 16: StLoc[6](loc3: &u64) + 17: CopyLoc[0](Arg0: &signer) + 18: MoveLoc[5](loc2: &address) + 19: ReadRef + 20: MoveLoc[6](loc3: &u64) + 21: ReadRef + 22: Call call_other(&signer, address, u64) + 23: MoveLoc[4](loc1: u64) + 24: LdU64(1) + 25: Add + 26: StLoc[4](loc1: u64) + 27: Branch(5) B3: - 30: MoveLoc[0](Arg0: &signer) - 31: Pop - 32: Ret + 28: MoveLoc[0](Arg0: &signer) + 29: Pop + 30: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/bug_14762.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/bug_14762.opt.exp index d04e138c63dba..99ccbf85e8dfb 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/bug_14762.opt.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/bug_14762.opt.exp @@ -24,8 +24,7 @@ L4: loc2: u64 L5: loc3: u64 L6: loc4: u64 L7: loc5: u64 -L8: loc6: bool -L9: loc7: Option +L8: loc6: Option B0: 0: CopyLoc[0](Arg0: &mut S) 1: ImmBorrowField[0](S.entries: vector) @@ -54,7 +53,7 @@ B3: 21: ReadRef 22: CopyLoc[1](Arg1: vector) 23: Eq - 24: BrFalse(51) + 24: BrFalse(49) B4: 25: LdTrue 26: StLoc[3](loc1: bool) @@ -67,33 +66,29 @@ B5: 32: MoveLoc[3](loc1: bool) 33: MoveLoc[4](loc2: u64) 34: StLoc[7](loc5: u64) - 35: StLoc[8](loc6: bool) - 36: MoveLoc[8](loc6: bool) - 37: BrFalse(46) + 35: BrFalse(44) B6: - 38: MoveLoc[0](Arg0: &mut S) - 39: MutBorrowField[0](S.entries: vector) - 40: MoveLoc[7](loc5: u64) - 41: Call vector::remove(&mut vector, u64): T - 42: Call option::some(T): Option - 43: StLoc[9](loc7: Option) + 36: MoveLoc[0](Arg0: &mut S) + 37: MutBorrowField[0](S.entries: vector) + 38: MoveLoc[7](loc5: u64) + 39: Call vector::remove(&mut vector, u64): T + 40: Call option::some(T): Option + 41: StLoc[8](loc6: Option) B7: - 44: MoveLoc[9](loc7: Option) - 45: Ret + 42: MoveLoc[8](loc6: Option) + 43: Ret B8: - 46: MoveLoc[0](Arg0: &mut S) - 47: Pop - 48: Call option::none(): Option - 49: StLoc[9](loc7: Option) - 50: Branch(44) + 44: MoveLoc[0](Arg0: &mut S) + 45: Pop + 46: Call option::none(): Option + 47: StLoc[8](loc6: Option) + 48: Branch(42) B9: - 51: LdU64(1) - 52: StLoc[7](loc5: u64) - 53: MoveLoc[5](loc3: u64) - 54: MoveLoc[7](loc5: u64) - 55: Add - 56: StLoc[5](loc3: u64) - 57: Branch(12) + 49: MoveLoc[5](loc3: u64) + 50: LdU64(1) + 51: Add + 52: StLoc[5](loc3: u64) + 53: Branch(12) } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/eager_push_01.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/eager_push_01.exp new file mode 100644 index 0000000000000..24fc89cd866f2 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/eager_push_01.exp @@ -0,0 +1,46 @@ + +============ disassembled file-format ================== +// Move bytecode v7 +module c0ffee.m { + + +bar(Arg0: u64, Arg1: u64, Arg2: u64, Arg3: u64, Arg4: u64, Arg5: u64) /* def_idx: 0 */ { +B0: + 0: Ret +} +one(): u64 /* def_idx: 1 */ { +B0: + 0: LdU64(1) + 1: Ret +} +public test(Arg0: u64) /* def_idx: 2 */ { +L1: loc0: u64 +L2: loc1: u64 +L3: loc2: u64 +L4: loc3: u64 +L5: loc4: u64 +L6: loc5: u64 +B0: + 0: MoveLoc[0](Arg0: u64) + 1: StLoc[1](loc0: u64) + 2: Call one(): u64 + 3: Call one(): u64 + 4: Call one(): u64 + 5: Call one(): u64 + 6: Call one(): u64 + 7: StLoc[2](loc1: u64) + 8: StLoc[3](loc2: u64) + 9: StLoc[4](loc3: u64) + 10: StLoc[5](loc4: u64) + 11: StLoc[6](loc5: u64) + 12: MoveLoc[1](loc0: u64) + 13: MoveLoc[6](loc5: u64) + 14: MoveLoc[5](loc4: u64) + 15: MoveLoc[4](loc3: u64) + 16: MoveLoc[3](loc2: u64) + 17: MoveLoc[2](loc1: u64) + 18: Call bar(u64, u64, u64, u64, u64, u64) + 19: Ret +} +} +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/eager_push_01.move b/third_party/move/move-compiler-v2/tests/file-format-generator/eager_push_01.move new file mode 100644 index 0000000000000..bcff6578e1e07 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/eager_push_01.move @@ -0,0 +1,11 @@ +module 0xc0ffee::m { + fun one(): u64 { + 1 + } + + fun bar(_a: u64, _b: u64, _c: u64, _d: u64, _e: u64, _f: u64) {} + + public fun test(x: u64) { + bar(x, one(), one(), one(), one(), one()); + } +} diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/eager_push_01.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/eager_push_01.opt.exp new file mode 100644 index 0000000000000..677926f405b44 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/eager_push_01.opt.exp @@ -0,0 +1,28 @@ + +============ disassembled file-format ================== +// Move bytecode v7 +module c0ffee.m { + + +bar(Arg0: u64, Arg1: u64, Arg2: u64, Arg3: u64, Arg4: u64, Arg5: u64) /* def_idx: 0 */ { +B0: + 0: Ret +} +one(): u64 /* def_idx: 1 */ { +B0: + 0: LdU64(1) + 1: Ret +} +public test(Arg0: u64) /* def_idx: 2 */ { +B0: + 0: MoveLoc[0](Arg0: u64) + 1: Call one(): u64 + 2: Call one(): u64 + 3: Call one(): u64 + 4: Call one(): u64 + 5: Call one(): u64 + 6: Call bar(u64, u64, u64, u64, u64, u64) + 7: Ret +} +} +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/eager_push_02.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/eager_push_02.exp new file mode 100644 index 0000000000000..dd83ac44afdf0 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/eager_push_02.exp @@ -0,0 +1,20 @@ + +============ disassembled file-format ================== +// Move bytecode v7 +module c0ffee.m { + + +test(Arg0: u64, Arg1: u64): u64 /* def_idx: 0 */ { +L2: loc0: u64 +B0: + 0: MoveLoc[1](Arg1: u64) + 1: CopyLoc[0](Arg0: u64) + 2: Mul + 3: StLoc[2](loc0: u64) + 4: MoveLoc[0](Arg0: u64) + 5: MoveLoc[2](loc0: u64) + 6: Add + 7: Ret +} +} +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/eager_push_02.move b/third_party/move/move-compiler-v2/tests/file-format-generator/eager_push_02.move new file mode 100644 index 0000000000000..cd16357181f46 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/eager_push_02.move @@ -0,0 +1,5 @@ +module 0xc0ffee::m { + fun test(x: u64, y: u64): u64 { + x + (y * x) + } +} diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/eager_push_02.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/eager_push_02.opt.exp new file mode 100644 index 0000000000000..8f98258bd77db --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/eager_push_02.opt.exp @@ -0,0 +1,17 @@ + +============ disassembled file-format ================== +// Move bytecode v7 +module c0ffee.m { + + +test(Arg0: u64, Arg1: u64): u64 /* def_idx: 0 */ { +B0: + 0: CopyLoc[0](Arg0: u64) + 1: MoveLoc[1](Arg1: u64) + 2: MoveLoc[0](Arg0: u64) + 3: Mul + 4: Add + 5: Ret +} +} +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/fields.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/fields.opt.exp index bddcd323020fa..180ffa3a427e6 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/fields.opt.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/fields.opt.exp @@ -44,9 +44,7 @@ B0: } write_local_via_ref(): S /* def_idx: 3 */ { L0: loc0: S -L1: loc1: u64 -L2: loc2: &mut S -L3: loc3: &mut u64 +L1: loc1: &mut S B0: 0: LdU64(0) 1: LdU64(0) @@ -54,11 +52,11 @@ B0: 3: Pack[1](S) 4: StLoc[0](loc0: S) 5: MutBorrowLoc[0](loc0: S) - 6: MutBorrowField[0](S.g: T) - 7: MutBorrowField[1](T.h: u64) - 8: StLoc[3](loc3: &mut u64) - 9: LdU64(42) - 10: MoveLoc[3](loc3: &mut u64) + 6: StLoc[1](loc1: &mut S) + 7: LdU64(42) + 8: MoveLoc[1](loc1: &mut S) + 9: MutBorrowField[0](S.g: T) + 10: MutBorrowField[1](T.h: u64) 11: WriteRef 12: MoveLoc[0](loc0: S) 13: Ret diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/framework_reduced_06.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/framework_reduced_06.opt.exp index 5daf860469de1..41776e5da98bf 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/framework_reduced_06.opt.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/framework_reduced_06.opt.exp @@ -38,7 +38,9 @@ B0: } foo(Arg0: address, Arg1: &mut S, Arg2: &mut S): u64 /* def_idx: 4 */ { L3: loc0: u64 -L4: loc1: &u64 +L4: loc1: u64 +L5: loc2: &mut S +L6: loc3: address B0: 0: MoveLoc[1](Arg1: &mut S) 1: LdU64(1) @@ -49,15 +51,15 @@ B0: 6: StLoc[1](Arg1: &mut S) 7: CopyLoc[0](Arg0: address) 8: CopyLoc[1](Arg1: &mut S) - 9: MoveLoc[0](Arg0: address) - 10: CopyLoc[3](loc0: u64) - 11: MoveLoc[2](Arg2: &mut S) - 12: Call f2(address, &mut S, address, u64, &mut S) - 13: MoveLoc[1](Arg1: &mut S) - 14: ImmBorrowField[0](S.g: u64) - 15: StLoc[4](loc1: &u64) - 16: CopyLoc[3](loc0: u64) - 17: MoveLoc[4](loc1: &u64) + 9: CopyLoc[3](loc0: u64) + 10: StLoc[4](loc1: u64) + 11: MoveLoc[0](Arg0: address) + 12: MoveLoc[4](loc1: u64) + 13: MoveLoc[2](Arg2: &mut S) + 14: Call f2(address, &mut S, address, u64, &mut S) + 15: CopyLoc[3](loc0: u64) + 16: MoveLoc[1](Arg1: &mut S) + 17: ImmBorrowField[0](S.g: u64) 18: Call f3(u64, &u64) 19: MoveLoc[3](loc0: u64) 20: Ret diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/globals.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/globals.opt.exp index a923eb6daffcf..602dc61fed548 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/globals.opt.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/globals.opt.exp @@ -21,15 +21,12 @@ B0: 2: Ret } publish(Arg0: &signer) /* def_idx: 1 */ { -L1: loc0: R B0: - 0: LdU64(1) - 1: Pack[0](R) - 2: StLoc[1](loc0: R) - 3: MoveLoc[0](Arg0: &signer) - 4: MoveLoc[1](loc0: R) - 5: MoveTo[0](R) - 6: Ret + 0: MoveLoc[0](Arg0: &signer) + 1: LdU64(1) + 2: Pack[0](R) + 3: MoveTo[0](R) + 4: Ret } read(Arg0: address): u64 /* def_idx: 2 */ { B0: @@ -41,14 +38,13 @@ B0: } write(Arg0: address, Arg1: u64): u64 /* def_idx: 3 */ { L2: loc0: &mut R -L3: loc1: &mut u64 B0: 0: MoveLoc[0](Arg0: address) 1: MutBorrowGlobal[0](R) - 2: MutBorrowField[0](R.f: u64) - 3: StLoc[3](loc1: &mut u64) - 4: LdU64(2) - 5: MoveLoc[3](loc1: &mut u64) + 2: StLoc[2](loc0: &mut R) + 3: LdU64(2) + 4: MoveLoc[2](loc0: &mut R) + 5: MutBorrowField[0](R.f: u64) 6: WriteRef 7: LdU64(9) 8: Ret diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/if_else.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/if_else.opt.exp index 46d7ead1f3947..73a27449cd2ba 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/if_else.opt.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/if_else.opt.exp @@ -6,7 +6,6 @@ module 42.if_else { if_else(Arg0: bool, Arg1: u64): u64 /* def_idx: 0 */ { L2: loc0: u64 -L3: loc1: u64 B0: 0: MoveLoc[0](Arg0: bool) 1: BrFalse(8) @@ -28,7 +27,6 @@ B3: if_else_nested(Arg0: bool, Arg1: u64): u64 /* def_idx: 1 */ { L2: loc0: u64 L3: loc1: u64 -L4: loc2: u64 B0: 0: MoveLoc[0](Arg0: bool) 1: BrFalse(21) diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/loop.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/loop.opt.exp index c06febb790553..9c56b091164f6 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/loop.opt.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/loop.opt.exp @@ -5,7 +5,6 @@ module 42.loops { nested_loop(Arg0: u64): u64 /* def_idx: 0 */ { -L1: loc0: u64 B0: 0: CopyLoc[0](Arg0: u64) 1: LdU64(0) @@ -34,7 +33,6 @@ B5: 19: Ret } while_loop(Arg0: u64): u64 /* def_idx: 1 */ { -L1: loc0: u64 B0: 0: CopyLoc[0](Arg0: u64) 1: LdU64(0) @@ -51,7 +49,6 @@ B2: 10: Ret } while_loop_with_break_and_continue(Arg0: u64): u64 /* def_idx: 2 */ { -L1: loc0: u64 B0: 0: CopyLoc[0](Arg0: u64) 1: LdU64(0) diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/multi_use.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/multi_use.opt.exp index a75676beab4a8..dbad90fc3f4b2 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/multi_use.opt.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/multi_use.opt.exp @@ -9,7 +9,6 @@ B0: 0: Ret } public test(Arg0: u64) /* def_idx: 1 */ { -L1: loc0: u64 B0: 0: CopyLoc[0](Arg0: u64) 1: CopyLoc[0](Arg0: u64) diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/operators.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/operators.opt.exp index 3d429474d155e..94d263a3c0343 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/operators.opt.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/operators.opt.exp @@ -5,24 +5,19 @@ module 42.operators { arithm(Arg0: u64, Arg1: u64): u64 /* def_idx: 0 */ { -L2: loc0: u64 B0: 0: CopyLoc[0](Arg0: u64) 1: CopyLoc[1](Arg1: u64) - 2: Sub - 3: StLoc[2](loc0: u64) - 4: CopyLoc[1](Arg1: u64) - 5: MoveLoc[2](loc0: u64) - 6: Div - 7: MoveLoc[1](Arg1: u64) - 8: Mul - 9: CopyLoc[0](Arg0: u64) - 10: Mod - 11: StLoc[1](Arg1: u64) - 12: MoveLoc[0](Arg0: u64) - 13: MoveLoc[1](Arg1: u64) - 14: Add - 15: Ret + 2: CopyLoc[0](Arg0: u64) + 3: CopyLoc[1](Arg1: u64) + 4: Sub + 5: Div + 6: MoveLoc[1](Arg1: u64) + 7: Mul + 8: MoveLoc[0](Arg0: u64) + 9: Mod + 10: Add + 11: Ret } bits(Arg0: u64, Arg1: u8): u64 /* def_idx: 1 */ { B0: diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_01.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_01.opt.exp index 8503b6e5d38c3..2c32c62eca7a1 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_01.opt.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_01.opt.exp @@ -9,11 +9,6 @@ B0: 0: Ret } public test01(Arg0: u64) /* def_idx: 1 */ { -L1: loc0: u64 -L2: loc1: u64 -L3: loc2: u64 -L4: loc3: u64 -L5: loc4: u64 B0: 0: MoveLoc[0](Arg0: u64) 1: LdU64(1) @@ -25,10 +20,6 @@ B0: 7: Ret } public test02(Arg0: u64) /* def_idx: 2 */ { -L1: loc0: u64 -L2: loc1: u64 -L3: loc2: u64 -L4: loc3: u64 B0: 0: CopyLoc[0](Arg0: u64) 1: LdU64(1) @@ -40,11 +31,6 @@ B0: 7: Ret } public test03(Arg0: u64) /* def_idx: 3 */ { -L1: loc0: u64 -L2: loc1: u64 -L3: loc2: u64 -L4: loc3: u64 -L5: loc4: u64 B0: 0: CopyLoc[0](Arg0: u64) 1: LdU64(1) diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_02.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_02.opt.exp index 790b06577f4a9..ffe373d4103a1 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_02.opt.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_02.opt.exp @@ -29,11 +29,6 @@ B0: 4: Ret } public test01(Arg0: &S) /* def_idx: 3 */ { -L1: loc0: u64 -L2: loc1: u64 -L3: loc2: u64 -L4: loc3: u64 -L5: loc4: u64 B0: 0: MoveLoc[0](Arg0: &S) 1: LdU64(1) @@ -45,10 +40,6 @@ B0: 7: Ret } public test02(Arg0: &S) /* def_idx: 4 */ { -L1: loc0: u64 -L2: loc1: u64 -L3: loc2: u64 -L4: loc3: u64 B0: 0: CopyLoc[0](Arg0: &S) 1: LdU64(1) @@ -60,11 +51,6 @@ B0: 7: Ret } public test03(Arg0: &S) /* def_idx: 5 */ { -L1: loc0: u64 -L2: loc1: u64 -L3: loc2: u64 -L4: loc3: u64 -L5: loc4: u64 B0: 0: CopyLoc[0](Arg0: &S) 1: LdU64(1) @@ -83,47 +69,25 @@ B0: 14: Ret } public test04(Arg0: &S) /* def_idx: 6 */ { -L1: loc0: u64 -L2: loc1: &u64 -L3: loc2: u64 -L4: loc3: u64 -L5: loc4: u64 -L6: loc5: u64 B0: - 0: LdU64(1) - 1: LdU64(2) - 2: LdU64(3) - 3: CopyLoc[0](Arg0: &S) - 4: ImmBorrowField[0](S.x: u64) - 5: StLoc[2](loc1: &u64) - 6: StLoc[3](loc2: u64) - 7: StLoc[4](loc3: u64) - 8: StLoc[5](loc4: u64) - 9: CopyLoc[0](Arg0: &S) - 10: MoveLoc[5](loc4: u64) - 11: MoveLoc[4](loc3: u64) - 12: MoveLoc[3](loc2: u64) - 13: MoveLoc[2](loc1: &u64) - 14: LdU64(5) - 15: Call consume3(&S, u64, u64, u64, &u64, u64) - 16: LdU64(1) - 17: LdU64(2) - 18: LdU64(3) - 19: CopyLoc[0](Arg0: &S) - 20: ImmBorrowField[0](S.x: u64) - 21: ReadRef - 22: StLoc[1](loc0: u64) - 23: StLoc[3](loc2: u64) - 24: StLoc[4](loc3: u64) - 25: StLoc[5](loc4: u64) - 26: MoveLoc[0](Arg0: &S) - 27: MoveLoc[5](loc4: u64) - 28: MoveLoc[4](loc3: u64) - 29: MoveLoc[3](loc2: u64) - 30: MoveLoc[1](loc0: u64) - 31: LdU64(5) - 32: Call consume1(&S, u64, u64, u64, u64, u64) - 33: Ret + 0: CopyLoc[0](Arg0: &S) + 1: LdU64(1) + 2: LdU64(2) + 3: LdU64(3) + 4: CopyLoc[0](Arg0: &S) + 5: ImmBorrowField[0](S.x: u64) + 6: LdU64(5) + 7: Call consume3(&S, u64, u64, u64, &u64, u64) + 8: CopyLoc[0](Arg0: &S) + 9: LdU64(1) + 10: LdU64(2) + 11: LdU64(3) + 12: MoveLoc[0](Arg0: &S) + 13: ImmBorrowField[0](S.x: u64) + 14: ReadRef + 15: LdU64(5) + 16: Call consume1(&S, u64, u64, u64, u64, u64) + 17: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_04.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_04.opt.exp index 33b1f294dc099..8b175afa80b86 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_04.opt.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_04.opt.exp @@ -15,8 +15,6 @@ B0: 0: Ret } public foo(Arg0: u64) /* def_idx: 2 */ { -L1: loc0: u64 -L2: loc1: u64 B0: 0: MutBorrowLoc[0](Arg0: u64) 1: Call bar(&mut u64) diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_05.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_05.opt.exp index 56cc7a5deab9c..14e6070b12992 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_05.opt.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_05.opt.exp @@ -14,7 +14,6 @@ B0: 1: Ret } public test1(Arg0: u64) /* def_idx: 2 */ { -L1: loc0: u64 B0: 0: CopyLoc[0](Arg0: u64) 1: MoveLoc[0](Arg0: u64) @@ -23,8 +22,6 @@ B0: 4: Ret } public test2(Arg0: u64) /* def_idx: 3 */ { -L1: loc0: u64 -L2: loc1: u64 B0: 0: Call one(): u64 1: MoveLoc[0](Arg0: u64) @@ -37,9 +34,9 @@ L1: loc0: u64 L2: loc1: u64 B0: 0: Call one(): u64 - 1: StLoc[2](loc1: u64) + 1: StLoc[1](loc0: u64) 2: MoveLoc[0](Arg0: u64) - 3: MoveLoc[2](loc1: u64) + 3: MoveLoc[1](loc0: u64) 4: LdU64(3) 5: Call consume1(u64, u64, u64) 6: Ret diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/pack_unpack.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/pack_unpack.opt.exp index 814b21a7d843e..478176a41191f 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/pack_unpack.opt.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/pack_unpack.opt.exp @@ -11,15 +11,12 @@ struct S { } pack(Arg0: u64, Arg1: u64): S /* def_idx: 0 */ { -L2: loc0: T B0: - 0: MoveLoc[1](Arg1: u64) - 1: Pack[0](T) - 2: StLoc[2](loc0: T) - 3: MoveLoc[0](Arg0: u64) - 4: MoveLoc[2](loc0: T) - 5: Pack[1](S) - 6: Ret + 0: MoveLoc[0](Arg0: u64) + 1: MoveLoc[1](Arg1: u64) + 2: Pack[0](T) + 3: Pack[1](S) + 4: Ret } unpack(Arg0: S): u64 * u64 /* def_idx: 1 */ { B0: diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/pack_unpack_ref.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/pack_unpack_ref.opt.exp index 50897b5e6a239..ceb4c3c0a03a1 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/pack_unpack_ref.opt.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/pack_unpack_ref.opt.exp @@ -14,7 +14,6 @@ struct S { unpack_mut_ref(Arg0: &mut S): u64 * u64 /* def_idx: 0 */ { L1: loc0: &mut u64 -L2: loc1: &mut u64 B0: 0: CopyLoc[0](Arg0: &mut S) 1: MutBorrowField[0](S.f: u64) @@ -28,7 +27,6 @@ B0: } unpack_ref(Arg0: &S): u64 * u64 /* def_idx: 1 */ { L1: loc0: &u64 -L2: loc1: &u64 B0: 0: CopyLoc[0](Arg0: &S) 1: ImmBorrowField[0](S.f: u64) @@ -41,32 +39,31 @@ B0: 8: Ret } unpack_ref_G(Arg0: &G): u64 * u64 * u64 * u64 /* def_idx: 2 */ { -L1: loc0: &S -L2: loc1: &u64 +L1: loc0: &u64 +L2: loc1: &S L3: loc2: &u64 L4: loc3: &u64 -L5: loc4: &u64 B0: 0: CopyLoc[0](Arg0: &G) 1: ImmBorrowField[2](G.x1: u64) 2: CopyLoc[0](Arg0: &G) 3: ImmBorrowField[3](G.x2: u64) - 4: MoveLoc[0](Arg0: &G) - 5: ImmBorrowField[4](G.s: S) - 6: StLoc[1](loc0: &S) - 7: CopyLoc[1](loc0: &S) - 8: ImmBorrowField[0](S.f: u64) - 9: MoveLoc[1](loc0: &S) - 10: ImmBorrowField[1](S.g: u64) - 11: StLoc[2](loc1: &u64) - 12: StLoc[3](loc2: &u64) + 4: StLoc[1](loc0: &u64) + 5: MoveLoc[0](Arg0: &G) + 6: ImmBorrowField[4](G.s: S) + 7: StLoc[2](loc1: &S) + 8: CopyLoc[2](loc1: &S) + 9: ImmBorrowField[0](S.f: u64) + 10: StLoc[3](loc2: &u64) + 11: MoveLoc[2](loc1: &S) + 12: ImmBorrowField[1](S.g: u64) 13: StLoc[4](loc3: &u64) 14: ReadRef - 15: MoveLoc[4](loc3: &u64) + 15: MoveLoc[1](loc0: &u64) 16: ReadRef 17: MoveLoc[3](loc2: &u64) 18: ReadRef - 19: MoveLoc[2](loc1: &u64) + 19: MoveLoc[4](loc3: &u64) 20: ReadRef 21: Ret } diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/vector.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/vector.opt.exp index 59b0000ee2d3c..f334510d33d10 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/vector.opt.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/vector.opt.exp @@ -9,8 +9,6 @@ use 0000000000000000000000000000000000000000000000000000000000000001::vector as public remove(Arg0: &mut vector, Arg1: u64): Ty0 /* def_idx: 0 */ { L2: loc0: u64 -L3: loc1: u64 -L4: loc2: u64 B0: 0: CopyLoc[0](Arg0: &mut vector) 1: FreezeRef @@ -58,7 +56,6 @@ B0: test_fold() /* def_idx: 2 */ { L0: loc0: u64 L1: loc1: vector -L2: loc2: u64 B0: 0: LdU64(0) 1: StLoc[0](loc0: u64) @@ -72,7 +69,7 @@ B1: 8: BrTrue(15) B2: 9: MutBorrowLoc[1](loc1: vector) - 10: VecPopBack(5) + 10: VecPopBack(2) 11: Pop 12: LdU64(0) 13: StLoc[0](loc0: u64) diff --git a/third_party/move/move-compiler-v2/tests/flush-writes/def_use_01.on.exp b/third_party/move/move-compiler-v2/tests/flush-writes/def_use_01.on.exp index 0870224a85ec2..a98457b592311 100644 --- a/third_party/move/move-compiler-v2/tests/flush-writes/def_use_01.on.exp +++ b/third_party/move/move-compiler-v2/tests/flush-writes/def_use_01.on.exp @@ -31,6 +31,7 @@ fun m::take2($t0: u64, $t1: u64) { public fun m::test() { var $t0: u64 var $t1: u64 + var $t2: u64 [unused] # flush: $t1 # live vars: 0: ($t0, $t1) := m::one_one() diff --git a/third_party/move/move-compiler-v2/tests/flush-writes/def_use_02.on.exp b/third_party/move/move-compiler-v2/tests/flush-writes/def_use_02.on.exp index c2a870c8c44d0..cf1b28b1c904d 100644 --- a/third_party/move/move-compiler-v2/tests/flush-writes/def_use_02.on.exp +++ b/third_party/move/move-compiler-v2/tests/flush-writes/def_use_02.on.exp @@ -31,6 +31,7 @@ fun m::take2($t0: u64, $t1: u64) { public fun m::test() { var $t0: u64 var $t1: u64 + var $t2: u64 [unused] # flush: $t0, $t1 # live vars: 0: ($t0, $t1) := m::one_one() diff --git a/third_party/move/move-compiler-v2/tests/flush-writes/def_use_03.on.exp b/third_party/move/move-compiler-v2/tests/flush-writes/def_use_03.on.exp index 86d9781822945..f7d24cf2808cd 100644 --- a/third_party/move/move-compiler-v2/tests/flush-writes/def_use_03.on.exp +++ b/third_party/move/move-compiler-v2/tests/flush-writes/def_use_03.on.exp @@ -31,15 +31,18 @@ fun m::take2($t0: u64, $t1: u64) { public fun m::test() { var $t0: u64 var $t1: u64 + var $t2: u64 [unused] # flush: $t0 # live vars: 0: ($t0, $t1) := m::one_one() # live vars: $t0, $t1 1: m::take1($t1) # live vars: $t0 - 2: m::take2($t0, $t0) + 2: $t1 := copy($t0) + # live vars: $t0, $t1 + 3: m::take2($t1, $t0) # live vars: - 3: return () + 4: return () } diff --git a/third_party/move/move-compiler-v2/tests/flush-writes/def_use_04.on.exp b/third_party/move/move-compiler-v2/tests/flush-writes/def_use_04.on.exp index a13bdd44923af..ff806c7c0db02 100644 --- a/third_party/move/move-compiler-v2/tests/flush-writes/def_use_04.on.exp +++ b/third_party/move/move-compiler-v2/tests/flush-writes/def_use_04.on.exp @@ -31,15 +31,18 @@ fun m::take2($t0: u64, $t1: u64) { public fun m::test() { var $t0: u64 var $t1: u64 + var $t2: u64 [unused] # flush: $t1 # live vars: 0: ($t0, $t1) := m::one_one() # live vars: $t0, $t1 1: m::take1($t0) # live vars: $t1 - 2: m::take2($t1, $t1) + 2: $t0 := copy($t1) + # live vars: $t0, $t1 + 3: m::take2($t0, $t1) # live vars: - 3: return () + 4: return () } diff --git a/third_party/move/move-compiler-v2/tests/flush-writes/def_use_05.on.exp b/third_party/move/move-compiler-v2/tests/flush-writes/def_use_05.on.exp index 4410c4d801505..a31d5538a0d1f 100644 --- a/third_party/move/move-compiler-v2/tests/flush-writes/def_use_05.on.exp +++ b/third_party/move/move-compiler-v2/tests/flush-writes/def_use_05.on.exp @@ -31,6 +31,7 @@ fun m::take2($t0: u64, $t1: u64) { public fun m::test() { var $t0: u64 var $t1: u64 + # flush: $t0 # live vars: 0: ($t0, $t1) := m::one_one() # live vars: $t0, $t1 diff --git a/third_party/move/move-compiler-v2/tests/flush-writes/def_use_06.on.exp b/third_party/move/move-compiler-v2/tests/flush-writes/def_use_06.on.exp index 33a814454b8a5..96861d4e1c3bc 100644 --- a/third_party/move/move-compiler-v2/tests/flush-writes/def_use_06.on.exp +++ b/third_party/move/move-compiler-v2/tests/flush-writes/def_use_06.on.exp @@ -20,12 +20,16 @@ fun m::take2($t0: u64, $t1: u64) { [variant baseline] public fun m::test($t0: u64) { var $t1: u64 + var $t2: u64 [unused] + # flush: $t1 # live vars: $t0 0: $t1 := m::one() # live vars: $t0, $t1 - 1: m::take2($t0, $t1) + 1: $t0 := move($t0) + # live vars: $t0, $t1 + 2: m::take2($t0, $t1) # live vars: - 2: return () + 3: return () } diff --git a/third_party/move/move-compiler-v2/tests/flush-writes/def_use_07.off.exp b/third_party/move/move-compiler-v2/tests/flush-writes/def_use_07.off.exp index da91b1fbdbafc..9de43d650013d 100644 --- a/third_party/move/move-compiler-v2/tests/flush-writes/def_use_07.off.exp +++ b/third_party/move/move-compiler-v2/tests/flush-writes/def_use_07.off.exp @@ -5,7 +5,6 @@ module c0ffee.m { foo(Arg0: u64): u64 /* def_idx: 0 */ { -L1: loc0: u64 B0: 0: MoveLoc[0](Arg0: u64) 1: LdU64(1) diff --git a/third_party/move/move-compiler-v2/tests/flush-writes/def_use_07.on.exp b/third_party/move/move-compiler-v2/tests/flush-writes/def_use_07.on.exp index e30fa68798f35..e7ce2ad25d5c3 100644 --- a/third_party/move/move-compiler-v2/tests/flush-writes/def_use_07.on.exp +++ b/third_party/move/move-compiler-v2/tests/flush-writes/def_use_07.on.exp @@ -3,13 +3,16 @@ [variant baseline] fun m::foo($t0: u64): u64 { var $t1: u64 [unused] - var $t2: u64 + var $t2: u64 [unused] + var $t3: u64 + # live vars: $t0 + 0: $t0 := move($t0) # live vars: $t0 - 0: $t2 := 1 - # live vars: $t0, $t2 - 1: $t0 := +($t0, $t2) + 1: $t3 := 1 + # live vars: $t0, $t3 + 2: $t0 := +($t0, $t3) # live vars: $t0 - 2: return $t0 + 3: return $t0 } @@ -45,7 +48,6 @@ module c0ffee.m { foo(Arg0: u64): u64 /* def_idx: 0 */ { -L1: loc0: u64 B0: 0: MoveLoc[0](Arg0: u64) 1: LdU64(1) diff --git a/third_party/move/move-compiler-v2/tests/flush-writes/def_use_08.on.exp b/third_party/move/move-compiler-v2/tests/flush-writes/def_use_08.on.exp index 9bd6d2de130fc..4d2c4ea40228b 100644 --- a/third_party/move/move-compiler-v2/tests/flush-writes/def_use_08.on.exp +++ b/third_party/move/move-compiler-v2/tests/flush-writes/def_use_08.on.exp @@ -32,6 +32,9 @@ public fun m::test() { var $t1: u64 var $t2: u64 var $t3: u64 + var $t4: u64 [unused] + var $t5: u64 [unused] + var $t6: u64 [unused] # flush: $t0 # live vars: 0: ($t0, $t1, $t2, $t3) := m::foo() diff --git a/third_party/move/move-compiler-v2/tests/flush-writes/in_order_use_01.move b/third_party/move/move-compiler-v2/tests/flush-writes/in_order_use_01.move new file mode 100644 index 0000000000000..81da626809a08 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/flush-writes/in_order_use_01.move @@ -0,0 +1,26 @@ +module 0xc0ffee::m { + public fun one(): u64 { + 1 + } + + public fun consume( + _a: u64, + _b: u64, + _c: u64, + _d: u64, + _e: u64, + _f: u64, + _g: u64 + ) {} + + public fun test() { + let a = one(); + let b = one(); + let c = one(); + let d = one(); + let e = one(); + let f = one(); + let g = one(); + consume(a, b, c, d, e, f, g); + } +} diff --git a/third_party/move/move-compiler-v2/tests/flush-writes/in_order_use_01.off.exp b/third_party/move/move-compiler-v2/tests/flush-writes/in_order_use_01.off.exp new file mode 100644 index 0000000000000..83f331d38c8cd --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/flush-writes/in_order_use_01.off.exp @@ -0,0 +1,29 @@ + +============ disassembled file-format ================== +// Move bytecode v7 +module c0ffee.m { + + +public consume(Arg0: u64, Arg1: u64, Arg2: u64, Arg3: u64, Arg4: u64, Arg5: u64, Arg6: u64) /* def_idx: 0 */ { +B0: + 0: Ret +} +public one(): u64 /* def_idx: 1 */ { +B0: + 0: LdU64(1) + 1: Ret +} +public test() /* def_idx: 2 */ { +B0: + 0: Call one(): u64 + 1: Call one(): u64 + 2: Call one(): u64 + 3: Call one(): u64 + 4: Call one(): u64 + 5: Call one(): u64 + 6: Call one(): u64 + 7: Call consume(u64, u64, u64, u64, u64, u64, u64) + 8: Ret +} +} +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/flush-writes/in_order_use_01.on.exp b/third_party/move/move-compiler-v2/tests/flush-writes/in_order_use_01.on.exp new file mode 100644 index 0000000000000..aaa2e97210b77 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/flush-writes/in_order_use_01.on.exp @@ -0,0 +1,83 @@ +============ after FlushWritesProcessor: ================ + +[variant baseline] +public fun m::consume($t0: u64, $t1: u64, $t2: u64, $t3: u64, $t4: u64, $t5: u64, $t6: u64) { + # live vars: $t0, $t1, $t2, $t3, $t4, $t5, $t6 + 0: return () +} + + +[variant baseline] +public fun m::one(): u64 { + var $t0: u64 + # live vars: + 0: $t0 := 1 + # live vars: $t0 + 1: return $t0 +} + + +[variant baseline] +public fun m::test() { + var $t0: u64 + var $t1: u64 + var $t2: u64 + var $t3: u64 + var $t4: u64 + var $t5: u64 + var $t6: u64 + var $t7: u64 [unused] + var $t8: u64 [unused] + var $t9: u64 [unused] + var $t10: u64 [unused] + var $t11: u64 [unused] + var $t12: u64 [unused] + # live vars: + 0: $t0 := m::one() + # live vars: $t0 + 1: $t1 := m::one() + # live vars: $t0, $t1 + 2: $t2 := m::one() + # live vars: $t0, $t1, $t2 + 3: $t3 := m::one() + # live vars: $t0, $t1, $t2, $t3 + 4: $t4 := m::one() + # live vars: $t0, $t1, $t2, $t3, $t4 + 5: $t5 := m::one() + # live vars: $t0, $t1, $t2, $t3, $t4, $t5 + 6: $t6 := m::one() + # live vars: $t0, $t1, $t2, $t3, $t4, $t5, $t6 + 7: m::consume($t0, $t1, $t2, $t3, $t4, $t5, $t6) + # live vars: + 8: return () +} + + +============ disassembled file-format ================== +// Move bytecode v7 +module c0ffee.m { + + +public consume(Arg0: u64, Arg1: u64, Arg2: u64, Arg3: u64, Arg4: u64, Arg5: u64, Arg6: u64) /* def_idx: 0 */ { +B0: + 0: Ret +} +public one(): u64 /* def_idx: 1 */ { +B0: + 0: LdU64(1) + 1: Ret +} +public test() /* def_idx: 2 */ { +B0: + 0: Call one(): u64 + 1: Call one(): u64 + 2: Call one(): u64 + 3: Call one(): u64 + 4: Call one(): u64 + 5: Call one(): u64 + 6: Call one(): u64 + 7: Call consume(u64, u64, u64, u64, u64, u64, u64) + 8: Ret +} +} +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/flush-writes/loop_01.off.exp b/third_party/move/move-compiler-v2/tests/flush-writes/loop_01.off.exp index 9c907cf1b4e38..611c59a093878 100644 --- a/third_party/move/move-compiler-v2/tests/flush-writes/loop_01.off.exp +++ b/third_party/move/move-compiler-v2/tests/flush-writes/loop_01.off.exp @@ -5,7 +5,6 @@ module c0ffee.m { foo(Arg0: u64): u64 * u64 /* def_idx: 0 */ { -L1: loc0: u64 B0: 0: CopyLoc[0](Arg0: u64) 1: MoveLoc[0](Arg0: u64) diff --git a/third_party/move/move-compiler-v2/tests/flush-writes/loop_01.on.exp b/third_party/move/move-compiler-v2/tests/flush-writes/loop_01.on.exp index 4640def1c25d2..8a73dad251497 100644 --- a/third_party/move/move-compiler-v2/tests/flush-writes/loop_01.on.exp +++ b/third_party/move/move-compiler-v2/tests/flush-writes/loop_01.on.exp @@ -4,15 +4,18 @@ fun m::foo($t0: u64): (u64, u64) { var $t1: u64 var $t2: u64 [unused] - var $t3: u64 + var $t3: u64 [unused] + var $t4: u64 # live vars: $t0 0: $t1 := copy($t0) # live vars: $t0, $t1 - 1: $t3 := 1 - # live vars: $t0, $t1, $t3 - 2: $t0 := -($t0, $t3) + 1: $t0 := move($t0) # live vars: $t0, $t1 - 3: return ($t1, $t0) + 2: $t4 := 1 + # live vars: $t0, $t1, $t4 + 3: $t0 := -($t0, $t4) + # live vars: $t0, $t1 + 4: return ($t1, $t0) } @@ -20,16 +23,17 @@ fun m::foo($t0: u64): (u64, u64) { public fun m::test1($t0: u64) { var $t1: u64 var $t2: bool - var $t3: u64 + var $t3: u64 [unused] + var $t4: u64 # live vars: $t0 0: label L0 # flush: $t0 # live vars: $t0 1: ($t1, $t0) := m::foo($t0) # live vars: $t0, $t1 - 2: $t3 := 0 - # live vars: $t0, $t1, $t3 - 3: $t2 := ==($t1, $t3) + 2: $t4 := 0 + # live vars: $t0, $t1, $t4 + 3: $t2 := ==($t1, $t4) # live vars: $t0, $t2 4: if ($t2) goto 5 else goto 0 # live vars: $t0 @@ -43,16 +47,17 @@ public fun m::test1($t0: u64) { public fun m::test2($t0: u64) { var $t1: u64 var $t2: bool - var $t3: u64 + var $t3: u64 [unused] + var $t4: u64 # live vars: $t0 0: label L0 # flush: $t0 # live vars: $t0 1: ($t0, $t1) := m::foo($t0) # live vars: $t0, $t1 - 2: $t3 := 0 - # live vars: $t0, $t1, $t3 - 3: $t2 := ==($t1, $t3) + 2: $t4 := 0 + # live vars: $t0, $t1, $t4 + 3: $t2 := ==($t1, $t4) # live vars: $t0, $t2 4: if ($t2) goto 5 else goto 0 # live vars: $t0 @@ -68,7 +73,6 @@ module c0ffee.m { foo(Arg0: u64): u64 * u64 /* def_idx: 0 */ { -L1: loc0: u64 B0: 0: CopyLoc[0](Arg0: u64) 1: MoveLoc[0](Arg0: u64) diff --git a/third_party/move/move-compiler-v2/tests/flush-writes/loop_02.off.exp b/third_party/move/move-compiler-v2/tests/flush-writes/loop_02.off.exp index 690a6f78c649f..665c8ba795cbe 100644 --- a/third_party/move/move-compiler-v2/tests/flush-writes/loop_02.off.exp +++ b/third_party/move/move-compiler-v2/tests/flush-writes/loop_02.off.exp @@ -5,7 +5,6 @@ module c0ffee.m { inc(Arg0: u64): u64 /* def_idx: 0 */ { -L1: loc0: u64 B0: 0: MoveLoc[0](Arg0: u64) 1: LdU64(1) @@ -14,7 +13,6 @@ B0: } public test() /* def_idx: 1 */ { L0: loc0: u64 -L1: loc1: u64 B0: 0: LdU64(0) 1: StLoc[0](loc0: u64) diff --git a/third_party/move/move-compiler-v2/tests/flush-writes/loop_02.on.exp b/third_party/move/move-compiler-v2/tests/flush-writes/loop_02.on.exp index 55dca74a4e2ef..70a98721f5664 100644 --- a/third_party/move/move-compiler-v2/tests/flush-writes/loop_02.on.exp +++ b/third_party/move/move-compiler-v2/tests/flush-writes/loop_02.on.exp @@ -3,13 +3,16 @@ [variant baseline] fun m::inc($t0: u64): u64 { var $t1: u64 [unused] - var $t2: u64 + var $t2: u64 [unused] + var $t3: u64 # live vars: $t0 - 0: $t2 := 1 - # live vars: $t0, $t2 - 1: $t0 := +($t0, $t2) + 0: $t0 := move($t0) + # live vars: $t0 + 1: $t3 := 1 + # live vars: $t0, $t3 + 2: $t0 := +($t0, $t3) # live vars: $t0 - 2: return $t0 + 3: return $t0 } @@ -19,6 +22,7 @@ public fun m::test() { var $t1: u64 var $t2: bool var $t3: u64 [unused] + var $t4: u64 # flush: $t0 # live vars: 0: $t0 := 0 @@ -26,22 +30,25 @@ public fun m::test() { 1: label L0 # live vars: $t0 2: $t1 := m::inc($t0) + # flush: $t0 # live vars: $t1 3: $t0 := move($t1) # live vars: $t0 - 4: $t1 := 10 + 4: $t1 := copy($t0) # live vars: $t0, $t1 - 5: $t2 := >($t0, $t1) + 5: $t4 := 10 + # live vars: $t0, $t1, $t4 + 6: $t2 := >($t1, $t4) # live vars: $t0, $t2 - 6: if ($t2) goto 9 else goto 7 + 7: if ($t2) goto 10 else goto 8 # live vars: $t0 - 7: label L3 + 8: label L3 # live vars: $t0 - 8: goto 1 + 9: goto 1 # live vars: $t0 - 9: label L2 + 10: label L2 # live vars: - 10: return () + 11: return () } @@ -51,7 +58,6 @@ module c0ffee.m { inc(Arg0: u64): u64 /* def_idx: 0 */ { -L1: loc0: u64 B0: 0: MoveLoc[0](Arg0: u64) 1: LdU64(1) @@ -60,7 +66,6 @@ B0: } public test() /* def_idx: 1 */ { L0: loc0: u64 -L1: loc1: u64 B0: 0: LdU64(0) 1: StLoc[0](loc0: u64) diff --git a/third_party/move/move-compiler-v2/tests/flush-writes/out_of_order_use_01.on.exp b/third_party/move/move-compiler-v2/tests/flush-writes/out_of_order_use_01.on.exp index 7e0a55544f30a..8fabfb3efeb16 100644 --- a/third_party/move/move-compiler-v2/tests/flush-writes/out_of_order_use_01.on.exp +++ b/third_party/move/move-compiler-v2/tests/flush-writes/out_of_order_use_01.on.exp @@ -26,6 +26,12 @@ public fun m::test() { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 [unused] + var $t8: u64 [unused] + var $t9: u64 [unused] + var $t10: u64 [unused] + var $t11: u64 [unused] + var $t12: u64 [unused] # flush: $t0 # live vars: 0: $t0 := m::one() diff --git a/third_party/move/move-compiler-v2/tests/flush-writes/out_of_order_use_02.off.exp b/third_party/move/move-compiler-v2/tests/flush-writes/out_of_order_use_02.off.exp index 95adc98b1fb92..c0ceec5e952f7 100644 --- a/third_party/move/move-compiler-v2/tests/flush-writes/out_of_order_use_02.off.exp +++ b/third_party/move/move-compiler-v2/tests/flush-writes/out_of_order_use_02.off.exp @@ -16,16 +16,19 @@ B0: public test() /* def_idx: 2 */ { L0: loc0: u64 L1: loc1: u64 +L2: loc2: u64 B0: 0: Call one(): u64 1: Call one(): u64 2: StLoc[0](loc0: u64) 3: StLoc[1](loc1: u64) - 4: MoveLoc[0](loc0: u64) - 5: CopyLoc[1](loc1: u64) - 6: MoveLoc[1](loc1: u64) - 7: Call consume(u64, u64, u64) - 8: Ret + 4: CopyLoc[1](loc1: u64) + 5: StLoc[2](loc2: u64) + 6: MoveLoc[0](loc0: u64) + 7: MoveLoc[2](loc2: u64) + 8: MoveLoc[1](loc1: u64) + 9: Call consume(u64, u64, u64) + 10: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/flush-writes/out_of_order_use_02.on.exp b/third_party/move/move-compiler-v2/tests/flush-writes/out_of_order_use_02.on.exp index eeee9aeca8865..1c11b62be1e43 100644 --- a/third_party/move/move-compiler-v2/tests/flush-writes/out_of_order_use_02.on.exp +++ b/third_party/move/move-compiler-v2/tests/flush-writes/out_of_order_use_02.on.exp @@ -21,15 +21,19 @@ fun m::one(): u64 { public fun m::test() { var $t0: u64 var $t1: u64 + var $t2: u64 [unused] + var $t3: u64 # flush: $t0 # live vars: 0: $t0 := m::one() # live vars: $t0 1: $t1 := m::one() # live vars: $t0, $t1 - 2: m::consume($t1, $t0, $t0) + 2: $t3 := copy($t0) + # live vars: $t0, $t1, $t3 + 3: m::consume($t1, $t3, $t0) # live vars: - 3: return () + 4: return () } diff --git a/third_party/move/move-compiler-v2/tests/flush-writes/out_of_order_use_03.off.exp b/third_party/move/move-compiler-v2/tests/flush-writes/out_of_order_use_03.off.exp index 4b7e692da0d00..434e4c65aa790 100644 --- a/third_party/move/move-compiler-v2/tests/flush-writes/out_of_order_use_03.off.exp +++ b/third_party/move/move-compiler-v2/tests/flush-writes/out_of_order_use_03.off.exp @@ -17,15 +17,18 @@ B0: public test() /* def_idx: 2 */ { L0: loc0: u64 L1: loc1: u64 +L2: loc2: u64 B0: 0: Call one_one(): u64 * u64 1: StLoc[0](loc0: u64) 2: StLoc[1](loc1: u64) - 3: MoveLoc[0](loc0: u64) - 4: CopyLoc[1](loc1: u64) - 5: MoveLoc[1](loc1: u64) - 6: Call consume(u64, u64, u64) - 7: Ret + 3: CopyLoc[1](loc1: u64) + 4: StLoc[2](loc2: u64) + 5: MoveLoc[0](loc0: u64) + 6: MoveLoc[2](loc2: u64) + 7: MoveLoc[1](loc1: u64) + 8: Call consume(u64, u64, u64) + 9: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/flush-writes/out_of_order_use_03.on.exp b/third_party/move/move-compiler-v2/tests/flush-writes/out_of_order_use_03.on.exp index 788166f87ed53..857902c6a6fa5 100644 --- a/third_party/move/move-compiler-v2/tests/flush-writes/out_of_order_use_03.on.exp +++ b/third_party/move/move-compiler-v2/tests/flush-writes/out_of_order_use_03.on.exp @@ -24,13 +24,17 @@ fun m::one_one(): (u64, u64) { public fun m::test() { var $t0: u64 var $t1: u64 + var $t2: u64 [unused] + var $t3: u64 # flush: $t0 # live vars: 0: ($t0, $t1) := m::one_one() # live vars: $t0, $t1 - 1: m::consume($t1, $t0, $t0) + 1: $t3 := copy($t0) + # live vars: $t0, $t1, $t3 + 2: m::consume($t1, $t3, $t0) # live vars: - 2: return () + 3: return () } @@ -52,15 +56,18 @@ B0: public test() /* def_idx: 2 */ { L0: loc0: u64 L1: loc1: u64 +L2: loc2: u64 B0: 0: Call one_one(): u64 * u64 1: StLoc[0](loc0: u64) 2: StLoc[1](loc1: u64) - 3: MoveLoc[0](loc0: u64) - 4: CopyLoc[1](loc1: u64) - 5: MoveLoc[1](loc1: u64) - 6: Call consume(u64, u64, u64) - 7: Ret + 3: CopyLoc[1](loc1: u64) + 4: StLoc[2](loc2: u64) + 5: MoveLoc[0](loc0: u64) + 6: MoveLoc[2](loc2: u64) + 7: MoveLoc[1](loc1: u64) + 8: Call consume(u64, u64, u64) + 9: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/flush-writes/out_of_order_use_04.on.exp b/third_party/move/move-compiler-v2/tests/flush-writes/out_of_order_use_04.on.exp index e709922e98925..9d129dc3ef425 100644 --- a/third_party/move/move-compiler-v2/tests/flush-writes/out_of_order_use_04.on.exp +++ b/third_party/move/move-compiler-v2/tests/flush-writes/out_of_order_use_04.on.exp @@ -21,15 +21,20 @@ fun m::one(): u64 { public fun m::test() { var $t0: u64 var $t1: u64 + var $t2: u64 + var $t3: u64 [unused] # flush: $t0 # live vars: 0: $t0 := m::one() + # flush: $t1 # live vars: $t0 1: $t1 := m::one() # live vars: $t0, $t1 - 2: m::consume($t0, $t1, $t0) + 2: $t2 := copy($t0) + # live vars: $t0, $t1, $t2 + 3: m::consume($t2, $t1, $t0) # live vars: - 3: return () + 4: return () } diff --git a/third_party/move/move-compiler-v2/tests/flush-writes/unused_flush_early_02.on.exp b/third_party/move/move-compiler-v2/tests/flush-writes/unused_flush_early_02.on.exp index cd5b039374e09..df0b8aa411527 100644 --- a/third_party/move/move-compiler-v2/tests/flush-writes/unused_flush_early_02.on.exp +++ b/third_party/move/move-compiler-v2/tests/flush-writes/unused_flush_early_02.on.exp @@ -25,7 +25,8 @@ public fun m::test(): (u64, u64) { var $t3: u64 var $t4: u64 var $t5: bool - var $t6: u64 + var $t6: u64 [unused] + var $t7: u64 # flush: $t2 # live vars: 0: $t2 := m::one() @@ -35,9 +36,9 @@ public fun m::test(): (u64, u64) { # live vars: $t2, $t3 2: $t4 := m::one() # live vars: $t2, $t3, $t4 - 3: $t6 := 0 - # live vars: $t2, $t3, $t4, $t6 - 4: $t5 := ==($t3, $t6) + 3: $t7 := 0 + # live vars: $t2, $t3, $t4, $t7 + 4: $t5 := ==($t3, $t7) # live vars: $t2, $t4, $t5 5: if ($t5) goto 8 else goto 6 # live vars: $t2, $t4 @@ -51,7 +52,11 @@ public fun m::test(): (u64, u64) { # live vars: $t2, $t4 10: label L2 # live vars: $t2, $t4 - 11: return ($t2, $t4) + 11: $t2 := move($t2) + # live vars: $t2, $t4 + 12: $t4 := move($t4) + # live vars: $t2, $t4 + 13: return ($t2, $t4) } diff --git a/third_party/move/move-compiler-v2/tests/flush-writes/unused_flush_early_03.on.exp b/third_party/move/move-compiler-v2/tests/flush-writes/unused_flush_early_03.on.exp index 9af909489ad96..faae5c17d09e4 100644 --- a/third_party/move/move-compiler-v2/tests/flush-writes/unused_flush_early_03.on.exp +++ b/third_party/move/move-compiler-v2/tests/flush-writes/unused_flush_early_03.on.exp @@ -29,18 +29,21 @@ public fun m::test1() { var $t1: u64 var $t2: u64 var $t3: bool - var $t4: u64 - var $t5: bool [unused] - var $t6: u64 [unused] - var $t7: bool [unused] + var $t4: u64 [unused] + var $t5: u64 + var $t6: bool [unused] + var $t7: u64 [unused] var $t8: u64 [unused] + var $t9: bool [unused] + var $t10: u64 [unused] + var $t11: u64 [unused] # flush: $t1, $t2 # live vars: 0: ($t0, $t1, $t2) := m::foo() # live vars: $t0, $t1, $t2 - 1: $t4 := 0 - # live vars: $t0, $t1, $t2, $t4 - 2: $t3 := ==($t0, $t4) + 1: $t5 := 0 + # live vars: $t0, $t1, $t2, $t5 + 2: $t3 := ==($t0, $t5) # live vars: $t1, $t2, $t3 3: if ($t3) goto 6 else goto 4 # live vars: $t1, $t2 @@ -54,39 +57,43 @@ public fun m::test1() { # live vars: $t1, $t2 8: label L2 # live vars: $t1, $t2 - 9: $t0 := 0 + 9: $t1 := move($t1) + # live vars: $t1, $t2 + 10: $t0 := 0 # live vars: $t0, $t1, $t2 - 10: $t3 := ==($t1, $t0) + 11: $t3 := ==($t1, $t0) # live vars: $t2, $t3 - 11: if ($t3) goto 14 else goto 12 + 12: if ($t3) goto 15 else goto 13 + # live vars: $t2 + 13: label L10 # live vars: $t2 - 12: label L10 + 14: goto 17 # live vars: $t2 - 13: goto 16 + 15: label L3 # live vars: $t2 - 14: label L3 + 16: m::bar() # live vars: $t2 - 15: m::bar() + 17: label L5 # live vars: $t2 - 16: label L5 + 18: $t2 := move($t2) # live vars: $t2 - 17: $t0 := 0 + 19: $t0 := 0 # live vars: $t0, $t2 - 18: $t3 := ==($t2, $t0) + 20: $t3 := ==($t2, $t0) # live vars: $t3 - 19: if ($t3) goto 22 else goto 20 + 21: if ($t3) goto 24 else goto 22 # live vars: - 20: label L11 + 22: label L11 # live vars: - 21: goto 24 + 23: goto 26 # live vars: - 22: label L6 + 24: label L6 # live vars: - 23: m::bar() + 25: m::bar() # live vars: - 24: label L8 + 26: label L8 # live vars: - 25: return () + 27: return () } @@ -109,7 +116,6 @@ B0: public test1() /* def_idx: 2 */ { L0: loc0: u64 L1: loc1: u64 -L2: loc2: u64 B0: 0: Call foo(): u64 * u64 * u64 1: StLoc[0](loc0: u64) diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/non_lambda_arg.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/non_lambda_arg.lambda.exp index 2f733050cb6bd..afb55300b662d 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/non_lambda_arg.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/non_lambda_arg.lambda.exp @@ -354,16 +354,20 @@ module 0x42::sort { public fun sort::incorrect_sort<#0>($t0: &mut vector<#0>, $t1: |(#0, #0)|bool) { var $t2: u64 var $t3: &vector<#0> - var $t4: u64 + var $t4: &mut vector<#0> var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 0: $t3 := freeze_ref(implicit)($t0) 1: $t2 := vector::length<#0>($t3) - 2: $t4 := 0 - 3: $t6 := 1 - 4: $t5 := -($t2, $t6) - 5: sort::incorrect_sort_recursive<#0>($t0, $t4, $t5, $t1) - 6: return () + 2: $t4 := infer($t0) + 3: $t5 := 0 + 4: $t7 := infer($t2) + 5: $t8 := 1 + 6: $t6 := -($t7, $t8) + 7: sort::incorrect_sort_recursive<#0>($t4, $t5, $t6, $t1) + 8: return () } @@ -376,23 +380,41 @@ public fun sort::incorrect_sort_recursive<#0>($t0: &mut vector<#0>, $t1: u64, $t var $t8: u64 var $t9: u64 var $t10: u64 - var $t11: u64 - 0: $t4 := <($t1, $t2) - 1: if ($t4) goto 2 else goto 13 - 2: label L0 - 3: $t7 := 2 - 4: $t6 := /($t2, $t7) - 5: $t5 := +($t1, $t6) - 6: $t9 := 1 - 7: $t8 := -($t5, $t9) - 8: sort::incorrect_sort_recursive<#0>($t0, $t1, $t8, $t3) - 9: $t11 := 1 - 10: $t10 := +($t5, $t11) - 11: sort::incorrect_sort_recursive<#0>($t0, $t10, $t2, $t3) - 12: goto 14 - 13: label L1 - 14: label L2 - 15: return () + var $t11: &mut vector<#0> + var $t12: u64 + var $t13: u64 + var $t14: u64 + var $t15: u64 + var $t16: &mut vector<#0> + var $t17: u64 + var $t18: u64 + var $t19: u64 + var $t20: u64 + 0: $t5 := infer($t1) + 1: $t4 := <($t5, $t2) + 2: if ($t4) goto 3 else goto 22 + 3: label L0 + 4: $t7 := infer($t1) + 5: $t9 := infer($t2) + 6: $t10 := 2 + 7: $t8 := /($t9, $t10) + 8: $t6 := +($t7, $t8) + 9: $t11 := infer($t0) + 10: $t12 := infer($t1) + 11: $t14 := infer($t6) + 12: $t15 := 1 + 13: $t13 := -($t14, $t15) + 14: sort::incorrect_sort_recursive<#0>($t11, $t12, $t13, $t3) + 15: $t16 := infer($t0) + 16: $t18 := infer($t6) + 17: $t19 := 1 + 18: $t17 := +($t18, $t19) + 19: $t20 := infer($t2) + 20: sort::incorrect_sort_recursive<#0>($t16, $t17, $t20, $t3) + 21: goto 23 + 22: label L1 + 23: label L2 + 24: return () } diff --git a/third_party/move/move-compiler-v2/tests/lambda/non_lambda_arg.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/non_lambda_arg.lambda.exp index 8949035e6a9d3..5925804dec97c 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/non_lambda_arg.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/non_lambda_arg.lambda.exp @@ -354,16 +354,20 @@ module 0x42::sort { public fun sort::incorrect_sort<#0>($t0: &mut vector<#0>, $t1: |(#0, #0)|bool) { var $t2: u64 var $t3: &vector<#0> - var $t4: u64 + var $t4: &mut vector<#0> var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 0: $t3 := freeze_ref(implicit)($t0) 1: $t2 := vector::length<#0>($t3) - 2: $t4 := 0 - 3: $t6 := 1 - 4: $t5 := -($t2, $t6) - 5: sort::incorrect_sort_recursive<#0>($t0, $t4, $t5, $t1) - 6: return () + 2: $t4 := infer($t0) + 3: $t5 := 0 + 4: $t7 := infer($t2) + 5: $t8 := 1 + 6: $t6 := -($t7, $t8) + 7: sort::incorrect_sort_recursive<#0>($t4, $t5, $t6, $t1) + 8: return () } @@ -376,23 +380,41 @@ public fun sort::incorrect_sort_recursive<#0>($t0: &mut vector<#0>, $t1: u64, $t var $t8: u64 var $t9: u64 var $t10: u64 - var $t11: u64 - 0: $t4 := <($t1, $t2) - 1: if ($t4) goto 2 else goto 13 - 2: label L0 - 3: $t7 := 2 - 4: $t6 := /($t2, $t7) - 5: $t5 := +($t1, $t6) - 6: $t9 := 1 - 7: $t8 := -($t5, $t9) - 8: sort::incorrect_sort_recursive<#0>($t0, $t1, $t8, $t3) - 9: $t11 := 1 - 10: $t10 := +($t5, $t11) - 11: sort::incorrect_sort_recursive<#0>($t0, $t10, $t2, $t3) - 12: goto 14 - 13: label L1 - 14: label L2 - 15: return () + var $t11: &mut vector<#0> + var $t12: u64 + var $t13: u64 + var $t14: u64 + var $t15: u64 + var $t16: &mut vector<#0> + var $t17: u64 + var $t18: u64 + var $t19: u64 + var $t20: u64 + 0: $t5 := infer($t1) + 1: $t4 := <($t5, $t2) + 2: if ($t4) goto 3 else goto 22 + 3: label L0 + 4: $t7 := infer($t1) + 5: $t9 := infer($t2) + 6: $t10 := 2 + 7: $t8 := /($t9, $t10) + 8: $t6 := +($t7, $t8) + 9: $t11 := infer($t0) + 10: $t12 := infer($t1) + 11: $t14 := infer($t6) + 12: $t15 := 1 + 13: $t13 := -($t14, $t15) + 14: sort::incorrect_sort_recursive<#0>($t11, $t12, $t13, $t3) + 15: $t16 := infer($t0) + 16: $t18 := infer($t6) + 17: $t19 := 1 + 18: $t17 := +($t18, $t19) + 19: $t20 := infer($t2) + 20: sort::incorrect_sort_recursive<#0>($t16, $t17, $t20, $t3) + 21: goto 23 + 22: label L1 + 23: label L2 + 24: return () } diff --git a/third_party/move/move-compiler-v2/tests/live-var/bug_9717_looponly.exp b/third_party/move/move-compiler-v2/tests/live-var/bug_9717_looponly.exp index e7aa75eab4159..6e8dc21ffe57c 100644 --- a/third_party/move/move-compiler-v2/tests/live-var/bug_9717_looponly.exp +++ b/third_party/move/move-compiler-v2/tests/live-var/bug_9717_looponly.exp @@ -11,58 +11,64 @@ public fun vectors::guess_flips_break2($t0: vector): u64 { var $t7: bool var $t8: u8 var $t9: &u8 - var $t10: u8 - var $t11: u64 + var $t10: &vector + var $t11: u8 var $t12: u64 - var $t13: bool - var $t14: u8 - var $t15: &u8 + var $t13: u64 + var $t14: u64 + var $t15: bool var $t16: u8 - var $t17: vector - var $t18: vector - var $t19: &vector + var $t17: &u8 + var $t18: &vector + var $t19: u8 + var $t20: vector + var $t21: vector + var $t22: &vector 0: $t2 := 0 1: $t3 := borrow_local($t0) 2: label L0 3: $t5 := infer($t2) 4: $t6 := vector::length($t3) 5: $t4 := <($t5, $t6) - 6: if ($t4) goto 7 else goto 32 + 6: if ($t4) goto 7 else goto 35 7: label L2 - 8: $t9 := vector::borrow($t3, $t2) - 9: $t8 := read_ref($t9) - 10: $t10 := 0 - 11: $t7 := !=($t8, $t10) - 12: if ($t7) goto 13 else goto 16 - 13: label L5 - 14: goto 36 - 15: goto 17 - 16: label L6 - 17: label L7 - 18: $t12 := 1 - 19: $t11 := +($t2, $t12) - 20: $t2 := infer($t11) - 21: $t15 := vector::borrow($t3, $t2) - 22: $t14 := read_ref($t15) - 23: $t16 := 5 - 24: $t13 := ==($t14, $t16) - 25: if ($t13) goto 26 else goto 29 - 26: label L8 - 27: goto 36 - 28: goto 30 - 29: label L9 - 30: label L10 - 31: goto 34 - 32: label L3 - 33: goto 36 - 34: label L4 - 35: goto 2 - 36: label L1 - 37: $t17 := copy($t0) - 38: $t18 := infer($t0) - 39: $t19 := infer($t3) - 40: $t1 := vector::length($t19) - 41: return $t1 + 8: $t10 := infer($t3) + 9: $t9 := vector::borrow($t10, $t2) + 10: $t8 := read_ref($t9) + 11: $t11 := 0 + 12: $t7 := !=($t8, $t11) + 13: if ($t7) goto 14 else goto 17 + 14: label L5 + 15: goto 39 + 16: goto 18 + 17: label L6 + 18: label L7 + 19: $t13 := infer($t2) + 20: $t14 := 1 + 21: $t12 := +($t13, $t14) + 22: $t2 := infer($t12) + 23: $t18 := infer($t3) + 24: $t17 := vector::borrow($t18, $t2) + 25: $t16 := read_ref($t17) + 26: $t19 := 5 + 27: $t15 := ==($t16, $t19) + 28: if ($t15) goto 29 else goto 32 + 29: label L8 + 30: goto 39 + 31: goto 33 + 32: label L9 + 33: label L10 + 34: goto 37 + 35: label L3 + 36: goto 39 + 37: label L4 + 38: goto 2 + 39: label L1 + 40: $t20 := copy($t0) + 41: $t21 := infer($t0) + 42: $t22 := infer($t3) + 43: $t1 := vector::length($t22) + 44: return $t1 } ============ after LiveVarAnalysisProcessor: ================ @@ -78,16 +84,19 @@ public fun vectors::guess_flips_break2($t0: vector): u64 { var $t7: bool var $t8: u8 var $t9: &u8 - var $t10: u8 - var $t11: u64 + var $t10: &vector + var $t11: u8 var $t12: u64 - var $t13: bool - var $t14: u8 - var $t15: &u8 + var $t13: u64 + var $t14: u64 + var $t15: bool var $t16: u8 - var $t17: vector - var $t18: vector - var $t19: &vector + var $t17: &u8 + var $t18: &vector + var $t19: u8 + var $t20: vector + var $t21: vector + var $t22: &vector # live vars: $t0 0: $t2 := 0 # live vars: $t0, $t2 @@ -101,75 +110,667 @@ public fun vectors::guess_flips_break2($t0: vector): u64 { # live vars: $t0, $t2, $t3, $t5, $t6 5: $t4 := <($t5, $t6) # live vars: $t0, $t2, $t3, $t4 - 6: if ($t4) goto 7 else goto 32 + 6: if ($t4) goto 7 else goto 35 # live vars: $t0, $t2, $t3 7: label L2 # live vars: $t0, $t2, $t3 - 8: $t9 := vector::borrow($t3, $t2) + 8: $t10 := infer($t3) + # live vars: $t0, $t2, $t3, $t10 + 9: $t9 := vector::borrow($t10, $t2) # live vars: $t0, $t2, $t3, $t9 - 9: $t8 := read_ref($t9) + 10: $t8 := read_ref($t9) # live vars: $t0, $t2, $t3, $t8 - 10: $t10 := 0 - # live vars: $t0, $t2, $t3, $t8, $t10 - 11: $t7 := !=($t8, $t10) + 11: $t11 := 0 + # live vars: $t0, $t2, $t3, $t8, $t11 + 12: $t7 := !=($t8, $t11) # live vars: $t0, $t2, $t3, $t7 - 12: if ($t7) goto 13 else goto 16 + 13: if ($t7) goto 14 else goto 17 # live vars: $t0, $t2, $t3 - 13: label L5 + 14: label L5 # live vars: $t0, $t3 - 14: goto 36 + 15: goto 39 # live vars: $t0, $t2, $t3 - 15: goto 17 + 16: goto 18 # live vars: $t0, $t2, $t3 - 16: label L6 + 17: label L6 # live vars: $t0, $t2, $t3 - 17: label L7 + 18: label L7 # live vars: $t0, $t2, $t3 - 18: $t12 := 1 - # live vars: $t0, $t2, $t3, $t12 - 19: $t11 := +($t2, $t12) - # live vars: $t0, $t3, $t11 - 20: $t2 := infer($t11) + 19: $t13 := infer($t2) + # live vars: $t0, $t3, $t13 + 20: $t14 := 1 + # live vars: $t0, $t3, $t13, $t14 + 21: $t12 := +($t13, $t14) + # live vars: $t0, $t3, $t12 + 22: $t2 := infer($t12) # live vars: $t0, $t2, $t3 - 21: $t15 := vector::borrow($t3, $t2) + 23: $t18 := infer($t3) + # live vars: $t0, $t2, $t3, $t18 + 24: $t17 := vector::borrow($t18, $t2) + # live vars: $t0, $t2, $t3, $t17 + 25: $t16 := read_ref($t17) + # live vars: $t0, $t2, $t3, $t16 + 26: $t19 := 5 + # live vars: $t0, $t2, $t3, $t16, $t19 + 27: $t15 := ==($t16, $t19) # live vars: $t0, $t2, $t3, $t15 - 22: $t14 := read_ref($t15) - # live vars: $t0, $t2, $t3, $t14 - 23: $t16 := 5 - # live vars: $t0, $t2, $t3, $t14, $t16 - 24: $t13 := ==($t14, $t16) - # live vars: $t0, $t2, $t3, $t13 - 25: if ($t13) goto 26 else goto 29 + 28: if ($t15) goto 29 else goto 32 # live vars: $t0, $t2, $t3 - 26: label L8 + 29: label L8 # live vars: $t0, $t3 - 27: goto 36 + 30: goto 39 # live vars: $t0, $t2, $t3 - 28: goto 30 + 31: goto 33 # live vars: $t0, $t2, $t3 - 29: label L9 + 32: label L9 # live vars: $t0, $t2, $t3 - 30: label L10 + 33: label L10 # live vars: $t0, $t2, $t3 - 31: goto 34 + 34: goto 37 # live vars: $t0, $t2, $t3 - 32: label L3 + 35: label L3 # live vars: $t0, $t3 - 33: goto 36 + 36: goto 39 # live vars: $t0, $t2, $t3 - 34: label L4 + 37: label L4 # live vars: $t0, $t2, $t3 - 35: goto 2 + 38: goto 2 # live vars: $t0, $t3 - 36: label L1 + 39: label L1 # live vars: $t0, $t3 - 37: $t17 := copy($t0) + 40: $t20 := copy($t0) # live vars: $t0, $t3 - 38: $t18 := infer($t0) + 41: $t21 := infer($t0) # live vars: $t3 - 39: $t19 := infer($t3) - # live vars: $t19 - 40: $t1 := vector::length($t19) + 42: $t22 := infer($t3) + # live vars: $t22 + 43: $t1 := vector::length($t22) # live vars: $t1 - 41: return $t1 + 44: return $t1 } + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +public fun vectors::guess_flips_break2($t0: vector): u64 { + var $t1: u64 + var $t2: u64 + var $t3: &vector + var $t4: bool + var $t5: u64 + var $t6: u64 + var $t7: bool + var $t8: u8 + var $t9: &u8 + var $t10: &vector + var $t11: u8 + var $t12: u64 + var $t13: u64 + var $t14: u64 + var $t15: bool + var $t16: u8 + var $t17: &u8 + var $t18: &vector + var $t19: u8 + var $t20: vector + var $t21: vector + var $t22: &vector + # live vars: $t0 + 0: $t2 := 0 + # live vars: $t0, $t2 + 1: $t3 := borrow_local($t0) + # live vars: $t0, $t2, $t3 + 2: label L0 + # live vars: $t0, $t2, $t3 + 3: $t5 := infer($t2) + # live vars: $t0, $t2, $t3, $t5 + 4: $t6 := vector::length($t3) + # live vars: $t0, $t2, $t3, $t5, $t6 + 5: $t4 := <($t5, $t6) + # live vars: $t0, $t2, $t3, $t4 + 6: if ($t4) goto 7 else goto 35 + # live vars: $t0, $t2, $t3 + 7: label L2 + # live vars: $t0, $t2, $t3 + 8: $t10 := infer($t3) + # live vars: $t0, $t2, $t3, $t10 + 9: $t9 := vector::borrow($t10, $t2) + # live vars: $t0, $t2, $t3, $t9 + 10: $t8 := read_ref($t9) + # live vars: $t0, $t2, $t3, $t8 + 11: $t11 := 0 + # live vars: $t0, $t2, $t3, $t8, $t11 + 12: $t7 := !=($t8, $t11) + # live vars: $t0, $t2, $t3, $t7 + 13: if ($t7) goto 14 else goto 17 + # live vars: $t0, $t2, $t3 + 14: label L5 + # live vars: $t0, $t3 + 15: goto 39 + # live vars: $t0, $t2, $t3 + 16: goto 18 + # live vars: $t0, $t2, $t3 + 17: label L6 + # live vars: $t0, $t2, $t3 + 18: label L7 + # live vars: $t0, $t2, $t3 + 19: $t13 := infer($t2) + # live vars: $t0, $t3, $t13 + 20: $t14 := 1 + # live vars: $t0, $t3, $t13, $t14 + 21: $t12 := +($t13, $t14) + # live vars: $t0, $t3, $t12 + 22: $t2 := infer($t12) + # live vars: $t0, $t2, $t3 + 23: $t18 := infer($t3) + # live vars: $t0, $t2, $t3, $t18 + 24: $t17 := vector::borrow($t18, $t2) + # live vars: $t0, $t2, $t3, $t17 + 25: $t16 := read_ref($t17) + # live vars: $t0, $t2, $t3, $t16 + 26: $t19 := 5 + # live vars: $t0, $t2, $t3, $t16, $t19 + 27: $t15 := ==($t16, $t19) + # live vars: $t0, $t2, $t3, $t15 + 28: if ($t15) goto 29 else goto 32 + # live vars: $t0, $t2, $t3 + 29: label L8 + # live vars: $t0, $t3 + 30: goto 39 + # live vars: $t0, $t2, $t3 + 31: goto 33 + # live vars: $t0, $t2, $t3 + 32: label L9 + # live vars: $t0, $t2, $t3 + 33: label L10 + # live vars: $t0, $t2, $t3 + 34: goto 37 + # live vars: $t0, $t2, $t3 + 35: label L3 + # live vars: $t0, $t3 + 36: goto 39 + # live vars: $t0, $t2, $t3 + 37: label L4 + # live vars: $t0, $t2, $t3 + 38: goto 2 + # live vars: $t0, $t3 + 39: label L1 + # live vars: $t0, $t3 + 40: $t20 := copy($t0) + # live vars: $t0, $t3 + 41: $t21 := infer($t0) + # live vars: $t3 + 42: $t22 := infer($t3) + # live vars: $t22 + 43: $t1 := vector::length($t22) + # live vars: $t1 + 44: return $t1 +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +public fun vectors::guess_flips_break2($t0: vector): u64 { + var $t1: u64 + var $t2: u64 + var $t3: &vector + var $t4: bool + var $t5: u64 + var $t6: u64 + var $t7: bool + var $t8: u8 + var $t9: &u8 + var $t10: &vector + var $t11: u8 + var $t12: u64 + var $t13: u64 + var $t14: u64 + var $t15: bool + var $t16: u8 + var $t17: &u8 + var $t18: &vector + var $t19: u8 + var $t20: vector + var $t21: vector + var $t22: &vector + # live vars: $t0 + 0: $t2 := 0 + # live vars: $t0, $t2 + 1: $t3 := borrow_local($t0) + # live vars: $t0, $t2, $t3 + 2: label L0 + # live vars: $t0, $t2, $t3 + 3: $t5 := copy($t2) + # live vars: $t0, $t2, $t3, $t5 + 4: $t6 := vector::length($t3) + # live vars: $t0, $t2, $t3, $t5, $t6 + 5: $t4 := <($t5, $t6) + # live vars: $t0, $t2, $t3, $t4 + 6: if ($t4) goto 9 else goto 7 + # live vars: $t0, $t2, $t3 + 7: label L8 + # live vars: $t0, $t3 + 8: goto 18 + # live vars: $t0, $t2, $t3 + 9: label L2 + # live vars: $t0, $t2, $t3 + 10: $t10 := copy($t3) + # live vars: $t0, $t2, $t3, $t10 + 11: $t9 := vector::borrow($t10, $t2) + # live vars: $t0, $t2, $t3, $t9 + 12: $t8 := read_ref($t9) + # live vars: $t0, $t2, $t3, $t8 + 13: $t11 := 0 + # live vars: $t0, $t2, $t3, $t8, $t11 + 14: $t7 := !=($t8, $t11) + # live vars: $t0, $t2, $t3, $t7 + 15: if ($t7) goto 16 else goto 24 + # live vars: $t0, $t2, $t3 + 16: label L9 + # live vars: $t0, $t3 + 17: goto 18 + # live vars: $t0, $t3 + 18: label L1 + # live vars: $t0, $t3 + 19: $t20 := copy($t0) + # live vars: $t0, $t3 + 20: $t21 := copy($t0) + # live vars: $t3 + 21: $t22 := move($t3) + # live vars: $t22 + 22: $t1 := vector::length($t22) + # live vars: $t1 + 23: return $t1 + # live vars: $t0, $t2, $t3 + 24: label L7 + # live vars: $t0, $t2, $t3 + 25: $t13 := move($t2) + # live vars: $t0, $t3, $t13 + 26: $t14 := 1 + # live vars: $t0, $t3, $t13, $t14 + 27: $t12 := +($t13, $t14) + # live vars: $t0, $t3, $t12 + 28: $t2 := move($t12) + # live vars: $t0, $t2, $t3 + 29: $t18 := copy($t3) + # live vars: $t0, $t2, $t3, $t18 + 30: $t17 := vector::borrow($t18, $t2) + # live vars: $t0, $t2, $t3, $t17 + 31: $t16 := read_ref($t17) + # live vars: $t0, $t2, $t3, $t16 + 32: $t19 := 5 + # live vars: $t0, $t2, $t3, $t16, $t19 + 33: $t15 := ==($t16, $t19) + # live vars: $t0, $t2, $t3, $t15 + 34: if ($t15) goto 35 else goto 37 + # live vars: $t0, $t2, $t3 + 35: label L10 + # live vars: $t0, $t3 + 36: goto 18 + # live vars: $t0, $t2, $t3 + 37: label L11 + # live vars: $t0, $t2, $t3 + 38: goto 2 +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +public fun vectors::guess_flips_break2($t0: vector): u64 { + var $t1: u64 + var $t2: u64 + var $t3: &vector + var $t4: bool + var $t5: u64 + var $t6: u64 + var $t7: bool + var $t8: u8 + var $t9: &u8 + var $t10: &vector + var $t11: u8 + var $t12: u64 + var $t13: u64 + var $t14: u64 + var $t15: bool + var $t16: u8 + var $t17: &u8 + var $t18: &vector + var $t19: u8 + var $t20: vector [unused] + var $t21: vector [unused] + var $t22: &vector + # live vars: $t0 + 0: $t2 := 0 + # live vars: $t0, $t2 + 1: $t3 := borrow_local($t0) + # live vars: $t2, $t3 + 2: label L0 + # live vars: $t2, $t3 + 3: $t5 := copy($t2) + # live vars: $t2, $t3, $t5 + 4: $t6 := vector::length($t3) + # live vars: $t2, $t3, $t5, $t6 + 5: $t4 := <($t5, $t6) + # live vars: $t2, $t3, $t4 + 6: if ($t4) goto 9 else goto 7 + # live vars: $t2, $t3 + 7: label L8 + # live vars: $t3 + 8: goto 18 + # live vars: $t2, $t3 + 9: label L2 + # live vars: $t2, $t3 + 10: $t10 := copy($t3) + # live vars: $t2, $t3, $t10 + 11: $t9 := vector::borrow($t10, $t2) + # live vars: $t2, $t3, $t9 + 12: $t8 := read_ref($t9) + # live vars: $t2, $t3, $t8 + 13: $t11 := 0 + # live vars: $t2, $t3, $t8, $t11 + 14: $t7 := !=($t8, $t11) + # live vars: $t2, $t3, $t7 + 15: if ($t7) goto 16 else goto 22 + # live vars: $t2, $t3 + 16: label L9 + # live vars: $t3 + 17: goto 18 + # live vars: $t3 + 18: label L1 + # live vars: $t3 + 19: $t22 := move($t3) + # live vars: $t22 + 20: $t1 := vector::length($t22) + # live vars: $t1 + 21: return $t1 + # live vars: $t2, $t3 + 22: label L7 + # live vars: $t2, $t3 + 23: $t13 := move($t2) + # live vars: $t3, $t13 + 24: $t14 := 1 + # live vars: $t3, $t13, $t14 + 25: $t12 := +($t13, $t14) + # live vars: $t3, $t12 + 26: $t2 := move($t12) + # live vars: $t2, $t3 + 27: $t18 := copy($t3) + # live vars: $t2, $t3, $t18 + 28: $t17 := vector::borrow($t18, $t2) + # live vars: $t2, $t3, $t17 + 29: $t16 := read_ref($t17) + # live vars: $t2, $t3, $t16 + 30: $t19 := 5 + # live vars: $t2, $t3, $t16, $t19 + 31: $t15 := ==($t16, $t19) + # live vars: $t2, $t3, $t15 + 32: if ($t15) goto 33 else goto 35 + # live vars: $t2, $t3 + 33: label L10 + # live vars: $t3 + 34: goto 18 + # live vars: $t2, $t3 + 35: label L11 + # live vars: $t2, $t3 + 36: goto 2 +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +public fun vectors::guess_flips_break2($t0: vector): u64 { + var $t1: u64 [unused] + var $t2: u64 + var $t3: &vector + var $t4: bool + var $t5: u64 + var $t6: u64 + var $t7: bool [unused] + var $t8: u8 + var $t9: &u8 + var $t10: &vector + var $t11: u8 + var $t12: u64 [unused] + var $t13: u64 [unused] + var $t14: u64 [unused] + var $t15: bool [unused] + var $t16: u8 [unused] + var $t17: &u8 [unused] + var $t18: &vector [unused] + var $t19: u8 [unused] + var $t20: vector [unused] + var $t21: vector [unused] + var $t22: &vector [unused] + # live vars: $t0 + 0: $t2 := 0 + # live vars: $t0, $t2 + 1: $t3 := borrow_local($t0) + # live vars: $t2, $t3 + 2: label L0 + # live vars: $t2, $t3 + 3: $t5 := copy($t2) + # live vars: $t2, $t3, $t5 + 4: $t6 := vector::length($t3) + # live vars: $t2, $t3, $t5, $t6 + 5: $t4 := <($t5, $t6) + # live vars: $t2, $t3, $t4 + 6: if ($t4) goto 9 else goto 7 + # live vars: $t2, $t3 + 7: label L8 + # live vars: $t3 + 8: goto 18 + # live vars: $t2, $t3 + 9: label L2 + # live vars: $t2, $t3 + 10: $t10 := copy($t3) + # live vars: $t2, $t3, $t10 + 11: $t9 := vector::borrow($t10, $t2) + # live vars: $t2, $t3, $t9 + 12: $t8 := read_ref($t9) + # live vars: $t2, $t3, $t8 + 13: $t11 := 0 + # live vars: $t2, $t3, $t8, $t11 + 14: $t4 := !=($t8, $t11) + # live vars: $t2, $t3, $t4 + 15: if ($t4) goto 16 else goto 22 + # live vars: $t2, $t3 + 16: label L9 + # live vars: $t3 + 17: goto 18 + # live vars: $t3 + 18: label L1 + # live vars: $t3 + 19: $t10 := move($t3) + # live vars: $t10 + 20: $t5 := vector::length($t10) + # live vars: $t5 + 21: return $t5 + # live vars: $t2, $t3 + 22: label L7 + # live vars: $t2, $t3 + 23: $t5 := move($t2) + # live vars: $t3, $t5 + 24: $t6 := 1 + # live vars: $t3, $t5, $t6 + 25: $t5 := +($t5, $t6) + # live vars: $t3, $t5 + 26: $t2 := move($t5) + # live vars: $t2, $t3 + 27: $t10 := copy($t3) + # live vars: $t2, $t3, $t10 + 28: $t9 := vector::borrow($t10, $t2) + # live vars: $t2, $t3, $t9 + 29: $t8 := read_ref($t9) + # live vars: $t2, $t3, $t8 + 30: $t11 := 5 + # live vars: $t2, $t3, $t8, $t11 + 31: $t4 := ==($t8, $t11) + # live vars: $t2, $t3, $t4 + 32: if ($t4) goto 33 else goto 35 + # live vars: $t2, $t3 + 33: label L10 + # live vars: $t3 + 34: goto 18 + # live vars: $t2, $t3 + 35: label L11 + # live vars: $t2, $t3 + 36: goto 2 +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +public fun vectors::guess_flips_break2($t0: vector): u64 { + var $t1: u64 [unused] + var $t2: u64 + var $t3: &vector + var $t4: bool + var $t5: u64 + var $t6: u64 + var $t7: bool [unused] + var $t8: u8 + var $t9: &u8 + var $t10: &vector + var $t11: u8 + var $t12: u64 [unused] + var $t13: u64 [unused] + var $t14: u64 [unused] + var $t15: bool [unused] + var $t16: u8 [unused] + var $t17: &u8 [unused] + var $t18: &vector [unused] + var $t19: u8 [unused] + var $t20: vector [unused] + var $t21: vector [unused] + var $t22: &vector [unused] + # live vars: $t0 + 0: $t2 := 0 + # live vars: $t0, $t2 + 1: $t3 := borrow_local($t0) + # live vars: $t2, $t3 + 2: label L0 + # live vars: $t2, $t3 + 3: $t5 := copy($t2) + # live vars: $t2, $t3, $t5 + 4: $t6 := vector::length($t3) + # live vars: $t2, $t3, $t5, $t6 + 5: $t4 := <($t5, $t6) + # live vars: $t2, $t3, $t4 + 6: if ($t4) goto 9 else goto 7 + # live vars: $t2, $t3 + 7: label L8 + # live vars: $t3 + 8: goto 18 + # live vars: $t2, $t3 + 9: label L2 + # live vars: $t2, $t3 + 10: $t10 := copy($t3) + # live vars: $t2, $t3, $t10 + 11: $t9 := vector::borrow($t10, $t2) + # live vars: $t2, $t3, $t9 + 12: $t8 := read_ref($t9) + # live vars: $t2, $t3, $t8 + 13: $t11 := 0 + # live vars: $t2, $t3, $t8, $t11 + 14: $t4 := !=($t8, $t11) + # live vars: $t2, $t3, $t4 + 15: if ($t4) goto 16 else goto 22 + # live vars: $t2, $t3 + 16: label L9 + # live vars: $t3 + 17: goto 18 + # live vars: $t3 + 18: label L1 + # live vars: $t3 + 19: $t10 := move($t3) + # live vars: $t10 + 20: $t5 := vector::length($t10) + # live vars: $t5 + 21: return $t5 + # live vars: $t2, $t3 + 22: label L7 + # live vars: $t2, $t3 + 23: $t5 := move($t2) + # live vars: $t3, $t5 + 24: $t6 := 1 + # live vars: $t3, $t5, $t6 + 25: $t5 := +($t5, $t6) + # live vars: $t3, $t5 + 26: $t2 := move($t5) + # live vars: $t2, $t3 + 27: $t10 := copy($t3) + # live vars: $t2, $t3, $t10 + 28: $t9 := vector::borrow($t10, $t2) + # live vars: $t2, $t3, $t9 + 29: $t8 := read_ref($t9) + # live vars: $t2, $t3, $t8 + 30: $t11 := 5 + # live vars: $t2, $t3, $t8, $t11 + 31: $t4 := ==($t8, $t11) + # live vars: $t2, $t3, $t4 + 32: if ($t4) goto 33 else goto 35 + # live vars: $t2, $t3 + 33: label L10 + # live vars: $t3 + 34: goto 18 + # live vars: $t2, $t3 + 35: label L11 + # live vars: $t2, $t3 + 36: goto 2 +} + + +============ disassembled file-format ================== +// Move bytecode v7 +module cafe.vectors { + + +entry public guess_flips_break2(Arg0: vector): u64 /* def_idx: 0 */ { +L1: loc0: u64 +L2: loc1: &vector +B0: + 0: LdU64(0) + 1: StLoc[1](loc0: u64) + 2: ImmBorrowLoc[0](Arg0: vector) + 3: StLoc[2](loc1: &vector) +B1: + 4: CopyLoc[1](loc0: u64) + 5: CopyLoc[2](loc1: &vector) + 6: VecLen(2) + 7: Lt + 8: BrTrue(10) +B2: + 9: Branch(18) +B3: + 10: CopyLoc[2](loc1: &vector) + 11: CopyLoc[1](loc0: u64) + 12: VecImmBorrow(2) + 13: ReadRef + 14: LdU8(0) + 15: Neq + 16: BrFalse(21) +B4: + 17: Branch(18) +B5: + 18: MoveLoc[2](loc1: &vector) + 19: VecLen(2) + 20: Ret +B6: + 21: MoveLoc[1](loc0: u64) + 22: LdU64(1) + 23: Add + 24: StLoc[1](loc0: u64) + 25: CopyLoc[2](loc1: &vector) + 26: CopyLoc[1](loc0: u64) + 27: VecImmBorrow(2) + 28: ReadRef + 29: LdU8(5) + 30: Eq + 31: BrFalse(33) +B7: + 32: Branch(18) +B8: + 33: Branch(4) +} +} +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/live-var/mut_inline.exp b/third_party/move/move-compiler-v2/tests/live-var/mut_inline.exp index 294f89be7fbf0..e6e9ffce3b0ea 100644 --- a/third_party/move/move-compiler-v2/tests/live-var/mut_inline.exp +++ b/third_party/move/move-compiler-v2/tests/live-var/mut_inline.exp @@ -11,32 +11,40 @@ fun m::foo(): u64 { var $t6: u64 var $t7: &vector var $t8: bool - var $t9: bool + var $t9: u64 var $t10: bool - var $t11: &u64 + var $t11: bool var $t12: &u64 - var $t13: &vector - var $t14: u64 + var $t13: &u64 + var $t14: &vector var $t15: u64 var $t16: u64 var $t17: u64 var $t18: u64 var $t19: u64 var $t20: u64 - var $t21: bool - var $t22: bool - var $t23: &u64 - var $t24: &u64 - var $t25: &vector - var $t26: u64 - var $t27: u64 - var $t28: u64 - var $t29: u64 + var $t21: u64 + var $t22: u64 + var $t23: u64 + var $t24: bool + var $t25: u64 + var $t26: bool + var $t27: &u64 + var $t28: &u64 + var $t29: &vector var $t30: u64 var $t31: u64 - var $t32: &u64 - var $t33: &vector + var $t32: &mut vector + var $t33: u64 var $t34: u64 + var $t35: u64 + var $t36: u64 + var $t37: u64 + var $t38: u64 + var $t39: u64 + var $t40: &u64 + var $t41: &vector + var $t42: u64 0: $t1 := ["1", "2", "3"] 1: $t2 := borrow_local($t1) 2: $t4 := infer($t2) @@ -44,69 +52,77 @@ fun m::foo(): u64 { 4: $t7 := freeze_ref(implicit)($t4) 5: $t6 := vector::length($t7) 6: label L0 - 7: $t8 := <($t5, $t6) - 8: if ($t8) goto 9 else goto 27 - 9: label L2 - 10: $t13 := freeze_ref(implicit)($t4) - 11: $t12 := vector::borrow($t13, $t5) - 12: $t11 := infer($t12) - 13: $t14 := read_ref($t11) - 14: $t15 := 1 - 15: $t10 := >($t14, $t15) - 16: $t9 := !($t10) - 17: if ($t9) goto 18 else goto 21 - 18: label L5 - 19: goto 31 - 20: goto 22 - 21: label L6 - 22: label L7 - 23: $t17 := 1 - 24: $t16 := +($t5, $t17) - 25: $t5 := infer($t16) - 26: goto 29 - 27: label L3 + 7: $t9 := infer($t5) + 8: $t8 := <($t9, $t6) + 9: if ($t8) goto 10 else goto 29 + 10: label L2 + 11: $t14 := freeze_ref(implicit)($t4) + 12: $t13 := vector::borrow($t14, $t5) + 13: $t12 := infer($t13) + 14: $t15 := read_ref($t12) + 15: $t16 := 1 + 16: $t11 := >($t15, $t16) + 17: $t10 := !($t11) + 18: if ($t10) goto 19 else goto 22 + 19: label L5 + 20: goto 33 + 21: goto 23 + 22: label L6 + 23: label L7 + 24: $t18 := infer($t5) + 25: $t19 := 1 + 26: $t17 := +($t18, $t19) + 27: $t5 := infer($t17) 28: goto 31 - 29: label L4 - 30: goto 6 - 31: label L1 - 32: $t18 := infer($t5) - 33: $t20 := 1 - 34: $t19 := +($t5, $t20) - 35: $t5 := infer($t19) - 36: label L8 - 37: $t21 := <($t5, $t6) - 38: if ($t21) goto 39 else goto 59 - 39: label L10 - 40: $t25 := freeze_ref(implicit)($t4) - 41: $t24 := vector::borrow($t25, $t5) - 42: $t23 := infer($t24) - 43: $t26 := read_ref($t23) - 44: $t27 := 1 - 45: $t22 := >($t26, $t27) - 46: if ($t22) goto 47 else goto 53 - 47: label L13 - 48: vector::swap($t4, $t18, $t5) - 49: $t29 := 1 - 50: $t28 := +($t18, $t29) - 51: $t18 := infer($t28) - 52: goto 54 - 53: label L14 - 54: label L15 - 55: $t31 := 1 - 56: $t30 := +($t5, $t31) - 57: $t5 := infer($t30) - 58: goto 61 - 59: label L11 - 60: goto 63 - 61: label L12 - 62: goto 36 - 63: label L9 - 64: $t3 := infer($t18) - 65: $t33 := freeze_ref(implicit)($t2) - 66: $t34 := 0 - 67: $t32 := vector::borrow($t33, $t34) - 68: $t0 := read_ref($t32) - 69: return $t0 + 29: label L3 + 30: goto 33 + 31: label L4 + 32: goto 6 + 33: label L1 + 34: $t20 := infer($t5) + 35: $t22 := infer($t5) + 36: $t23 := 1 + 37: $t21 := +($t22, $t23) + 38: $t5 := infer($t21) + 39: label L8 + 40: $t25 := infer($t5) + 41: $t24 := <($t25, $t6) + 42: if ($t24) goto 43 else goto 67 + 43: label L10 + 44: $t29 := freeze_ref(implicit)($t4) + 45: $t28 := vector::borrow($t29, $t5) + 46: $t27 := infer($t28) + 47: $t30 := read_ref($t27) + 48: $t31 := 1 + 49: $t26 := >($t30, $t31) + 50: if ($t26) goto 51 else goto 60 + 51: label L13 + 52: $t32 := infer($t4) + 53: $t33 := infer($t20) + 54: vector::swap($t32, $t33, $t5) + 55: $t35 := infer($t20) + 56: $t36 := 1 + 57: $t34 := +($t35, $t36) + 58: $t20 := infer($t34) + 59: goto 61 + 60: label L14 + 61: label L15 + 62: $t38 := infer($t5) + 63: $t39 := 1 + 64: $t37 := +($t38, $t39) + 65: $t5 := infer($t37) + 66: goto 69 + 67: label L11 + 68: goto 71 + 69: label L12 + 70: goto 39 + 71: label L9 + 72: $t3 := infer($t20) + 73: $t41 := freeze_ref(implicit)($t2) + 74: $t42 := 0 + 75: $t40 := vector::borrow($t41, $t42) + 76: $t0 := read_ref($t40) + 77: return $t0 } ============ after LiveVarAnalysisProcessor: ================ @@ -122,32 +138,40 @@ fun m::foo(): u64 { var $t6: u64 var $t7: &vector var $t8: bool - var $t9: bool + var $t9: u64 var $t10: bool - var $t11: &u64 + var $t11: bool var $t12: &u64 - var $t13: &vector - var $t14: u64 + var $t13: &u64 + var $t14: &vector var $t15: u64 var $t16: u64 var $t17: u64 var $t18: u64 var $t19: u64 var $t20: u64 - var $t21: bool - var $t22: bool - var $t23: &u64 - var $t24: &u64 - var $t25: &vector - var $t26: u64 - var $t27: u64 - var $t28: u64 - var $t29: u64 + var $t21: u64 + var $t22: u64 + var $t23: u64 + var $t24: bool + var $t25: u64 + var $t26: bool + var $t27: &u64 + var $t28: &u64 + var $t29: &vector var $t30: u64 var $t31: u64 - var $t32: &u64 - var $t33: &vector + var $t32: &mut vector + var $t33: u64 var $t34: u64 + var $t35: u64 + var $t36: u64 + var $t37: u64 + var $t38: u64 + var $t39: u64 + var $t40: &u64 + var $t41: &vector + var $t42: u64 # live vars: 0: $t1 := ["1", "2", "3"] # live vars: $t1 @@ -163,129 +187,1205 @@ fun m::foo(): u64 { # live vars: $t2, $t4, $t5, $t6 6: label L0 # live vars: $t2, $t4, $t5, $t6 - 7: $t8 := <($t5, $t6) + 7: $t9 := infer($t5) + # live vars: $t2, $t4, $t5, $t6, $t9 + 8: $t8 := <($t9, $t6) # live vars: $t2, $t4, $t5, $t6, $t8 - 8: if ($t8) goto 9 else goto 27 + 9: if ($t8) goto 10 else goto 29 # live vars: $t2, $t4, $t5, $t6 - 9: label L2 + 10: label L2 # live vars: $t2, $t4, $t5, $t6 - 10: $t13 := freeze_ref(implicit)($t4) + 11: $t14 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t6, $t14 + 12: $t13 := vector::borrow($t14, $t5) # live vars: $t2, $t4, $t5, $t6, $t13 - 11: $t12 := vector::borrow($t13, $t5) + 13: $t12 := infer($t13) # live vars: $t2, $t4, $t5, $t6, $t12 - 12: $t11 := infer($t12) + 14: $t15 := read_ref($t12) + # live vars: $t2, $t4, $t5, $t6, $t15 + 15: $t16 := 1 + # live vars: $t2, $t4, $t5, $t6, $t15, $t16 + 16: $t11 := >($t15, $t16) # live vars: $t2, $t4, $t5, $t6, $t11 - 13: $t14 := read_ref($t11) - # live vars: $t2, $t4, $t5, $t6, $t14 - 14: $t15 := 1 - # live vars: $t2, $t4, $t5, $t6, $t14, $t15 - 15: $t10 := >($t14, $t15) + 17: $t10 := !($t11) # live vars: $t2, $t4, $t5, $t6, $t10 - 16: $t9 := !($t10) + 18: if ($t10) goto 19 else goto 22 + # live vars: $t2, $t4, $t5, $t6 + 19: label L5 + # live vars: $t2, $t4, $t5, $t6 + 20: goto 33 + # live vars: $t2, $t4, $t5, $t6 + 21: goto 23 + # live vars: $t2, $t4, $t5, $t6 + 22: label L6 + # live vars: $t2, $t4, $t5, $t6 + 23: label L7 + # live vars: $t2, $t4, $t5, $t6 + 24: $t18 := infer($t5) + # live vars: $t2, $t4, $t6, $t18 + 25: $t19 := 1 + # live vars: $t2, $t4, $t6, $t18, $t19 + 26: $t17 := +($t18, $t19) + # live vars: $t2, $t4, $t6, $t17 + 27: $t5 := infer($t17) + # live vars: $t2, $t4, $t5, $t6 + 28: goto 31 + # live vars: $t2, $t4, $t5, $t6 + 29: label L3 + # live vars: $t2, $t4, $t5, $t6 + 30: goto 33 + # live vars: $t2, $t4, $t5, $t6 + 31: label L4 + # live vars: $t2, $t4, $t5, $t6 + 32: goto 6 + # live vars: $t2, $t4, $t5, $t6 + 33: label L1 + # live vars: $t2, $t4, $t5, $t6 + 34: $t20 := infer($t5) + # live vars: $t2, $t4, $t5, $t6, $t20 + 35: $t22 := infer($t5) + # live vars: $t2, $t4, $t6, $t20, $t22 + 36: $t23 := 1 + # live vars: $t2, $t4, $t6, $t20, $t22, $t23 + 37: $t21 := +($t22, $t23) + # live vars: $t2, $t4, $t6, $t20, $t21 + 38: $t5 := infer($t21) + # live vars: $t2, $t4, $t5, $t6, $t20 + 39: label L8 + # live vars: $t2, $t4, $t5, $t6, $t20 + 40: $t25 := infer($t5) + # live vars: $t2, $t4, $t5, $t6, $t20, $t25 + 41: $t24 := <($t25, $t6) + # live vars: $t2, $t4, $t5, $t6, $t20, $t24 + 42: if ($t24) goto 43 else goto 67 + # live vars: $t2, $t4, $t5, $t6, $t20 + 43: label L10 + # live vars: $t2, $t4, $t5, $t6, $t20 + 44: $t29 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t6, $t20, $t29 + 45: $t28 := vector::borrow($t29, $t5) + # live vars: $t2, $t4, $t5, $t6, $t20, $t28 + 46: $t27 := infer($t28) + # live vars: $t2, $t4, $t5, $t6, $t20, $t27 + 47: $t30 := read_ref($t27) + # live vars: $t2, $t4, $t5, $t6, $t20, $t30 + 48: $t31 := 1 + # live vars: $t2, $t4, $t5, $t6, $t20, $t30, $t31 + 49: $t26 := >($t30, $t31) + # live vars: $t2, $t4, $t5, $t6, $t20, $t26 + 50: if ($t26) goto 51 else goto 60 + # live vars: $t2, $t4, $t5, $t6, $t20 + 51: label L13 + # live vars: $t2, $t4, $t5, $t6, $t20 + 52: $t32 := infer($t4) + # live vars: $t2, $t4, $t5, $t6, $t20, $t32 + 53: $t33 := infer($t20) + # live vars: $t2, $t4, $t5, $t6, $t20, $t32, $t33 + 54: vector::swap($t32, $t33, $t5) + # live vars: $t2, $t4, $t5, $t6, $t20 + 55: $t35 := infer($t20) + # live vars: $t2, $t4, $t5, $t6, $t35 + 56: $t36 := 1 + # live vars: $t2, $t4, $t5, $t6, $t35, $t36 + 57: $t34 := +($t35, $t36) + # live vars: $t2, $t4, $t5, $t6, $t34 + 58: $t20 := infer($t34) + # live vars: $t2, $t4, $t5, $t6, $t20 + 59: goto 61 + # live vars: $t2, $t4, $t5, $t6, $t20 + 60: label L14 + # live vars: $t2, $t4, $t5, $t6, $t20 + 61: label L15 + # live vars: $t2, $t4, $t5, $t6, $t20 + 62: $t38 := infer($t5) + # live vars: $t2, $t4, $t6, $t20, $t38 + 63: $t39 := 1 + # live vars: $t2, $t4, $t6, $t20, $t38, $t39 + 64: $t37 := +($t38, $t39) + # live vars: $t2, $t4, $t6, $t20, $t37 + 65: $t5 := infer($t37) + # live vars: $t2, $t4, $t5, $t6, $t20 + 66: goto 69 + # live vars: $t2, $t4, $t5, $t6, $t20 + 67: label L11 + # live vars: $t2, $t20 + 68: goto 71 + # live vars: $t2, $t4, $t5, $t6, $t20 + 69: label L12 + # live vars: $t2, $t4, $t5, $t6, $t20 + 70: goto 39 + # live vars: $t2, $t20 + 71: label L9 + # live vars: $t2, $t20 + 72: $t3 := infer($t20) + # live vars: $t2 + 73: $t41 := freeze_ref(implicit)($t2) + # live vars: $t41 + 74: $t42 := 0 + # live vars: $t41, $t42 + 75: $t40 := vector::borrow($t41, $t42) + # live vars: $t40 + 76: $t0 := read_ref($t40) + # live vars: $t0 + 77: return $t0 +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun m::foo(): u64 { + var $t0: u64 + var $t1: vector + var $t2: &mut vector + var $t3: u64 + var $t4: &mut vector + var $t5: u64 + var $t6: u64 + var $t7: &vector + var $t8: bool + var $t9: u64 + var $t10: bool + var $t11: bool + var $t12: &u64 + var $t13: &u64 + var $t14: &vector + var $t15: u64 + var $t16: u64 + var $t17: u64 + var $t18: u64 + var $t19: u64 + var $t20: u64 + var $t21: u64 + var $t22: u64 + var $t23: u64 + var $t24: bool + var $t25: u64 + var $t26: bool + var $t27: &u64 + var $t28: &u64 + var $t29: &vector + var $t30: u64 + var $t31: u64 + var $t32: &mut vector + var $t33: u64 + var $t34: u64 + var $t35: u64 + var $t36: u64 + var $t37: u64 + var $t38: u64 + var $t39: u64 + var $t40: &u64 + var $t41: &vector + var $t42: u64 + # live vars: + 0: $t1 := ["1", "2", "3"] + # live vars: $t1 + 1: $t2 := borrow_local($t1) + # live vars: $t2 + 2: $t4 := infer($t2) + # live vars: $t2, $t4 + 3: $t5 := 0 + # live vars: $t2, $t4, $t5 + 4: $t7 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t7 + 5: $t6 := vector::length($t7) + # live vars: $t2, $t4, $t5, $t6 + 6: label L0 + # live vars: $t2, $t4, $t5, $t6 + 7: $t9 := infer($t5) # live vars: $t2, $t4, $t5, $t6, $t9 - 17: if ($t9) goto 18 else goto 21 + 8: $t8 := <($t9, $t6) + # live vars: $t2, $t4, $t5, $t6, $t8 + 9: if ($t8) goto 10 else goto 29 # live vars: $t2, $t4, $t5, $t6 - 18: label L5 + 10: label L2 # live vars: $t2, $t4, $t5, $t6 - 19: goto 31 + 11: $t14 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t6, $t14 + 12: $t13 := vector::borrow($t14, $t5) + # live vars: $t2, $t4, $t5, $t6, $t13 + 13: $t12 := infer($t13) + # live vars: $t2, $t4, $t5, $t6, $t12 + 14: $t15 := read_ref($t12) + # live vars: $t2, $t4, $t5, $t6, $t15 + 15: $t16 := 1 + # live vars: $t2, $t4, $t5, $t6, $t15, $t16 + 16: $t11 := >($t15, $t16) + # live vars: $t2, $t4, $t5, $t6, $t11 + 17: $t10 := !($t11) + # live vars: $t2, $t4, $t5, $t6, $t10 + 18: if ($t10) goto 19 else goto 22 # live vars: $t2, $t4, $t5, $t6 - 20: goto 22 + 19: label L5 # live vars: $t2, $t4, $t5, $t6 - 21: label L6 + 20: goto 33 # live vars: $t2, $t4, $t5, $t6 - 22: label L7 + 21: goto 23 # live vars: $t2, $t4, $t5, $t6 - 23: $t17 := 1 - # live vars: $t2, $t4, $t5, $t6, $t17 - 24: $t16 := +($t5, $t17) - # live vars: $t2, $t4, $t6, $t16 - 25: $t5 := infer($t16) + 22: label L6 # live vars: $t2, $t4, $t5, $t6 - 26: goto 29 + 23: label L7 # live vars: $t2, $t4, $t5, $t6 - 27: label L3 + 24: $t18 := infer($t5) + # live vars: $t2, $t4, $t6, $t18 + 25: $t19 := 1 + # live vars: $t2, $t4, $t6, $t18, $t19 + 26: $t17 := +($t18, $t19) + # live vars: $t2, $t4, $t6, $t17 + 27: $t5 := infer($t17) # live vars: $t2, $t4, $t5, $t6 28: goto 31 # live vars: $t2, $t4, $t5, $t6 - 29: label L4 + 29: label L3 + # live vars: $t2, $t4, $t5, $t6 + 30: goto 33 + # live vars: $t2, $t4, $t5, $t6 + 31: label L4 + # live vars: $t2, $t4, $t5, $t6 + 32: goto 6 + # live vars: $t2, $t4, $t5, $t6 + 33: label L1 + # live vars: $t2, $t4, $t5, $t6 + 34: $t20 := infer($t5) + # live vars: $t2, $t4, $t5, $t6, $t20 + 35: $t22 := infer($t5) + # live vars: $t2, $t4, $t6, $t20, $t22 + 36: $t23 := 1 + # live vars: $t2, $t4, $t6, $t20, $t22, $t23 + 37: $t21 := +($t22, $t23) + # live vars: $t2, $t4, $t6, $t20, $t21 + 38: $t5 := infer($t21) + # live vars: $t2, $t4, $t5, $t6, $t20 + 39: label L8 + # live vars: $t2, $t4, $t5, $t6, $t20 + 40: $t25 := infer($t5) + # live vars: $t2, $t4, $t5, $t6, $t20, $t25 + 41: $t24 := <($t25, $t6) + # live vars: $t2, $t4, $t5, $t6, $t20, $t24 + 42: if ($t24) goto 43 else goto 67 + # live vars: $t2, $t4, $t5, $t6, $t20 + 43: label L10 + # live vars: $t2, $t4, $t5, $t6, $t20 + 44: $t29 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t6, $t20, $t29 + 45: $t28 := vector::borrow($t29, $t5) + # live vars: $t2, $t4, $t5, $t6, $t20, $t28 + 46: $t27 := infer($t28) + # live vars: $t2, $t4, $t5, $t6, $t20, $t27 + 47: $t30 := read_ref($t27) + # live vars: $t2, $t4, $t5, $t6, $t20, $t30 + 48: $t31 := 1 + # live vars: $t2, $t4, $t5, $t6, $t20, $t30, $t31 + 49: $t26 := >($t30, $t31) + # live vars: $t2, $t4, $t5, $t6, $t20, $t26 + 50: if ($t26) goto 51 else goto 60 + # live vars: $t2, $t4, $t5, $t6, $t20 + 51: label L13 + # live vars: $t2, $t4, $t5, $t6, $t20 + 52: $t32 := infer($t4) + # live vars: $t2, $t4, $t5, $t6, $t20, $t32 + 53: $t33 := infer($t20) + # live vars: $t2, $t4, $t5, $t6, $t20, $t32, $t33 + 54: vector::swap($t32, $t33, $t5) + # live vars: $t2, $t4, $t5, $t6, $t20 + 55: $t35 := infer($t20) + # live vars: $t2, $t4, $t5, $t6, $t35 + 56: $t36 := 1 + # live vars: $t2, $t4, $t5, $t6, $t35, $t36 + 57: $t34 := +($t35, $t36) + # live vars: $t2, $t4, $t5, $t6, $t34 + 58: $t20 := infer($t34) + # live vars: $t2, $t4, $t5, $t6, $t20 + 59: goto 61 + # live vars: $t2, $t4, $t5, $t6, $t20 + 60: label L14 + # live vars: $t2, $t4, $t5, $t6, $t20 + 61: label L15 + # live vars: $t2, $t4, $t5, $t6, $t20 + 62: $t38 := infer($t5) + # live vars: $t2, $t4, $t6, $t20, $t38 + 63: $t39 := 1 + # live vars: $t2, $t4, $t6, $t20, $t38, $t39 + 64: $t37 := +($t38, $t39) + # live vars: $t2, $t4, $t6, $t20, $t37 + 65: $t5 := infer($t37) + # live vars: $t2, $t4, $t5, $t6, $t20 + 66: goto 69 + # live vars: $t2, $t4, $t5, $t6, $t20 + 67: label L11 + # live vars: $t2, $t20 + 68: goto 71 + # live vars: $t2, $t4, $t5, $t6, $t20 + 69: label L12 + # live vars: $t2, $t4, $t5, $t6, $t20 + 70: goto 39 + # live vars: $t2, $t20 + 71: label L9 + # live vars: $t2, $t20 + 72: $t3 := infer($t20) + # live vars: $t2 + 73: $t41 := freeze_ref(implicit)($t2) + # live vars: $t41 + 74: $t42 := 0 + # live vars: $t41, $t42 + 75: $t40 := vector::borrow($t41, $t42) + # live vars: $t40 + 76: $t0 := read_ref($t40) + # live vars: $t0 + 77: return $t0 +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun m::foo(): u64 { + var $t0: u64 + var $t1: vector + var $t2: &mut vector + var $t3: u64 + var $t4: &mut vector + var $t5: u64 + var $t6: u64 + var $t7: &vector + var $t8: bool + var $t9: u64 + var $t10: bool + var $t11: bool + var $t12: &u64 + var $t13: &u64 + var $t14: &vector + var $t15: u64 + var $t16: u64 + var $t17: u64 + var $t18: u64 + var $t19: u64 + var $t20: u64 + var $t21: u64 + var $t22: u64 + var $t23: u64 + var $t24: bool + var $t25: u64 + var $t26: bool + var $t27: &u64 + var $t28: &u64 + var $t29: &vector + var $t30: u64 + var $t31: u64 + var $t32: &mut vector + var $t33: u64 + var $t34: u64 + var $t35: u64 + var $t36: u64 + var $t37: u64 + var $t38: u64 + var $t39: u64 + var $t40: &u64 + var $t41: &vector + var $t42: u64 + # live vars: + 0: $t1 := ["1", "2", "3"] + # live vars: $t1 + 1: $t2 := borrow_local($t1) + # live vars: $t2 + 2: $t4 := copy($t2) + # live vars: $t2, $t4 + 3: $t5 := 0 + # live vars: $t2, $t4, $t5 + 4: $t7 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t7 + 5: $t6 := vector::length($t7) + # live vars: $t2, $t4, $t5, $t6 + 6: label L0 + # live vars: $t2, $t4, $t5, $t6 + 7: $t9 := copy($t5) + # live vars: $t2, $t4, $t5, $t6, $t9 + 8: $t8 := <($t9, $t6) + # live vars: $t2, $t4, $t5, $t6, $t8 + 9: if ($t8) goto 12 else goto 10 + # live vars: $t2, $t4, $t5, $t6 + 10: label L16 + # live vars: $t2, $t4, $t5, $t6 + 11: goto 23 + # live vars: $t2, $t4, $t5, $t6 + 12: label L2 # live vars: $t2, $t4, $t5, $t6 - 30: goto 6 + 13: $t14 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t6, $t14 + 14: $t13 := vector::borrow($t14, $t5) + # live vars: $t2, $t4, $t5, $t6, $t13 + 15: $t12 := move($t13) + # live vars: $t2, $t4, $t5, $t6, $t12 + 16: $t15 := read_ref($t12) + # live vars: $t2, $t4, $t5, $t6, $t15 + 17: $t16 := 1 + # live vars: $t2, $t4, $t5, $t6, $t15, $t16 + 18: $t11 := >($t15, $t16) + # live vars: $t2, $t4, $t5, $t6, $t11 + 19: $t10 := !($t11) + # live vars: $t2, $t4, $t5, $t6, $t10 + 20: if ($t10) goto 21 else goto 65 + # live vars: $t2, $t4, $t5, $t6 + 21: label L17 + # live vars: $t2, $t4, $t5, $t6 + 22: goto 23 + # live vars: $t2, $t4, $t5, $t6 + 23: label L1 + # live vars: $t2, $t4, $t5, $t6 + 24: $t20 := copy($t5) + # live vars: $t2, $t4, $t5, $t6, $t20 + 25: $t22 := move($t5) + # live vars: $t2, $t4, $t6, $t20, $t22 + 26: $t23 := 1 + # live vars: $t2, $t4, $t6, $t20, $t22, $t23 + 27: $t21 := +($t22, $t23) + # live vars: $t2, $t4, $t6, $t20, $t21 + 28: $t5 := move($t21) + # live vars: $t2, $t4, $t5, $t6, $t20 + 29: label L8 + # live vars: $t2, $t4, $t5, $t6, $t20 + 30: $t25 := copy($t5) + # live vars: $t2, $t4, $t5, $t6, $t20, $t25 + 31: $t24 := <($t25, $t6) + # live vars: $t2, $t4, $t5, $t6, $t20, $t24 + 32: if ($t24) goto 33 else goto 57 + # live vars: $t2, $t4, $t5, $t6, $t20 + 33: label L10 + # live vars: $t2, $t4, $t5, $t6, $t20 + 34: $t29 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t6, $t20, $t29 + 35: $t28 := vector::borrow($t29, $t5) + # live vars: $t2, $t4, $t5, $t6, $t20, $t28 + 36: $t27 := move($t28) + # live vars: $t2, $t4, $t5, $t6, $t20, $t27 + 37: $t30 := read_ref($t27) + # live vars: $t2, $t4, $t5, $t6, $t20, $t30 + 38: $t31 := 1 + # live vars: $t2, $t4, $t5, $t6, $t20, $t30, $t31 + 39: $t26 := >($t30, $t31) + # live vars: $t2, $t4, $t5, $t6, $t20, $t26 + 40: if ($t26) goto 43 else goto 41 + # live vars: $t2, $t4, $t5, $t6, $t20 + 41: label L18 + # live vars: $t2, $t4, $t5, $t6, $t20 + 42: goto 51 + # live vars: $t2, $t4, $t5, $t6, $t20 + 43: label L13 + # live vars: $t2, $t4, $t5, $t6, $t20 + 44: $t32 := copy($t4) + # live vars: $t2, $t4, $t5, $t6, $t20, $t32 + 45: $t33 := copy($t20) + # live vars: $t2, $t4, $t5, $t6, $t20, $t32, $t33 + 46: vector::swap($t32, $t33, $t5) + # live vars: $t2, $t4, $t5, $t6, $t20 + 47: $t35 := move($t20) + # live vars: $t2, $t4, $t5, $t6, $t35 + 48: $t36 := 1 + # live vars: $t2, $t4, $t5, $t6, $t35, $t36 + 49: $t34 := +($t35, $t36) + # live vars: $t2, $t4, $t5, $t6, $t34 + 50: $t20 := move($t34) + # live vars: $t2, $t4, $t5, $t6, $t20 + 51: label L15 + # live vars: $t2, $t4, $t5, $t6, $t20 + 52: $t38 := move($t5) + # live vars: $t2, $t4, $t6, $t20, $t38 + 53: $t39 := 1 + # live vars: $t2, $t4, $t6, $t20, $t38, $t39 + 54: $t37 := +($t38, $t39) + # live vars: $t2, $t4, $t6, $t20, $t37 + 55: $t5 := move($t37) + # live vars: $t2, $t4, $t5, $t6, $t20 + 56: goto 29 + # live vars: $t2, $t4, $t5, $t6, $t20 + 57: label L11 + # live vars: $t2, $t4, $t20 + 58: drop($t4) + # live vars: $t2, $t20 + 59: $t3 := move($t20) + # live vars: $t2 + 60: $t41 := freeze_ref(implicit)($t2) + # live vars: $t41 + 61: $t42 := 0 + # live vars: $t41, $t42 + 62: $t40 := vector::borrow($t41, $t42) + # live vars: $t40 + 63: $t0 := read_ref($t40) + # live vars: $t0 + 64: return $t0 # live vars: $t2, $t4, $t5, $t6 - 31: label L1 + 65: label L7 # live vars: $t2, $t4, $t5, $t6 - 32: $t18 := infer($t5) - # live vars: $t2, $t4, $t5, $t6, $t18 - 33: $t20 := 1 - # live vars: $t2, $t4, $t5, $t6, $t18, $t20 - 34: $t19 := +($t5, $t20) + 66: $t18 := move($t5) + # live vars: $t2, $t4, $t6, $t18 + 67: $t19 := 1 # live vars: $t2, $t4, $t6, $t18, $t19 - 35: $t5 := infer($t19) - # live vars: $t2, $t4, $t5, $t6, $t18 - 36: label L8 - # live vars: $t2, $t4, $t5, $t6, $t18 - 37: $t21 := <($t5, $t6) - # live vars: $t2, $t4, $t5, $t6, $t18, $t21 - 38: if ($t21) goto 39 else goto 59 - # live vars: $t2, $t4, $t5, $t6, $t18 - 39: label L10 - # live vars: $t2, $t4, $t5, $t6, $t18 - 40: $t25 := freeze_ref(implicit)($t4) - # live vars: $t2, $t4, $t5, $t6, $t18, $t25 - 41: $t24 := vector::borrow($t25, $t5) - # live vars: $t2, $t4, $t5, $t6, $t18, $t24 - 42: $t23 := infer($t24) - # live vars: $t2, $t4, $t5, $t6, $t18, $t23 - 43: $t26 := read_ref($t23) - # live vars: $t2, $t4, $t5, $t6, $t18, $t26 - 44: $t27 := 1 - # live vars: $t2, $t4, $t5, $t6, $t18, $t26, $t27 - 45: $t22 := >($t26, $t27) - # live vars: $t2, $t4, $t5, $t6, $t18, $t22 - 46: if ($t22) goto 47 else goto 53 - # live vars: $t2, $t4, $t5, $t6, $t18 - 47: label L13 - # live vars: $t2, $t4, $t5, $t6, $t18 - 48: vector::swap($t4, $t18, $t5) - # live vars: $t2, $t4, $t5, $t6, $t18 - 49: $t29 := 1 - # live vars: $t2, $t4, $t5, $t6, $t18, $t29 - 50: $t28 := +($t18, $t29) - # live vars: $t2, $t4, $t5, $t6, $t28 - 51: $t18 := infer($t28) - # live vars: $t2, $t4, $t5, $t6, $t18 - 52: goto 54 - # live vars: $t2, $t4, $t5, $t6, $t18 - 53: label L14 - # live vars: $t2, $t4, $t5, $t6, $t18 - 54: label L15 - # live vars: $t2, $t4, $t5, $t6, $t18 - 55: $t31 := 1 - # live vars: $t2, $t4, $t5, $t6, $t18, $t31 - 56: $t30 := +($t5, $t31) - # live vars: $t2, $t4, $t6, $t18, $t30 - 57: $t5 := infer($t30) - # live vars: $t2, $t4, $t5, $t6, $t18 - 58: goto 61 - # live vars: $t2, $t4, $t5, $t6, $t18 - 59: label L11 - # live vars: $t2, $t18 - 60: goto 63 - # live vars: $t2, $t4, $t5, $t6, $t18 - 61: label L12 - # live vars: $t2, $t4, $t5, $t6, $t18 - 62: goto 36 - # live vars: $t2, $t18 - 63: label L9 - # live vars: $t2, $t18 - 64: $t3 := infer($t18) + 68: $t17 := +($t18, $t19) + # live vars: $t2, $t4, $t6, $t17 + 69: $t5 := move($t17) + # live vars: $t2, $t4, $t5, $t6 + 70: goto 6 +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun m::foo(): u64 { + var $t0: u64 + var $t1: vector + var $t2: &mut vector + var $t3: u64 [unused] + var $t4: &mut vector + var $t5: u64 + var $t6: u64 + var $t7: &vector + var $t8: bool + var $t9: u64 + var $t10: bool + var $t11: bool + var $t12: &u64 + var $t13: &u64 + var $t14: &vector + var $t15: u64 + var $t16: u64 + var $t17: u64 + var $t18: u64 + var $t19: u64 + var $t20: u64 + var $t21: u64 + var $t22: u64 + var $t23: u64 + var $t24: bool + var $t25: u64 + var $t26: bool + var $t27: &u64 + var $t28: &u64 + var $t29: &vector + var $t30: u64 + var $t31: u64 + var $t32: &mut vector + var $t33: u64 + var $t34: u64 + var $t35: u64 + var $t36: u64 + var $t37: u64 + var $t38: u64 + var $t39: u64 + var $t40: &u64 + var $t41: &vector + var $t42: u64 + # live vars: + 0: $t1 := ["1", "2", "3"] + # live vars: $t1 + 1: $t2 := borrow_local($t1) + # live vars: $t2 + 2: $t4 := copy($t2) + # live vars: $t2, $t4 + 3: $t5 := 0 + # live vars: $t2, $t4, $t5 + 4: $t7 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t7 + 5: $t6 := vector::length($t7) + # live vars: $t2, $t4, $t5, $t6 + 6: label L0 + # live vars: $t2, $t4, $t5, $t6 + 7: $t9 := copy($t5) + # live vars: $t2, $t4, $t5, $t6, $t9 + 8: $t8 := <($t9, $t6) + # live vars: $t2, $t4, $t5, $t6, $t8 + 9: if ($t8) goto 12 else goto 10 + # live vars: $t2, $t4, $t5, $t6 + 10: label L16 + # live vars: $t2, $t4, $t5, $t6 + 11: goto 23 + # live vars: $t2, $t4, $t5, $t6 + 12: label L2 + # live vars: $t2, $t4, $t5, $t6 + 13: $t14 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t6, $t14 + 14: $t13 := vector::borrow($t14, $t5) + # live vars: $t2, $t4, $t5, $t6, $t13 + 15: $t12 := move($t13) + # live vars: $t2, $t4, $t5, $t6, $t12 + 16: $t15 := read_ref($t12) + # live vars: $t2, $t4, $t5, $t6, $t15 + 17: $t16 := 1 + # live vars: $t2, $t4, $t5, $t6, $t15, $t16 + 18: $t11 := >($t15, $t16) + # live vars: $t2, $t4, $t5, $t6, $t11 + 19: $t10 := !($t11) + # live vars: $t2, $t4, $t5, $t6, $t10 + 20: if ($t10) goto 21 else goto 64 + # live vars: $t2, $t4, $t5, $t6 + 21: label L17 + # live vars: $t2, $t4, $t5, $t6 + 22: goto 23 + # live vars: $t2, $t4, $t5, $t6 + 23: label L1 + # live vars: $t2, $t4, $t5, $t6 + 24: $t20 := copy($t5) + # live vars: $t2, $t4, $t5, $t6, $t20 + 25: $t22 := move($t5) + # live vars: $t2, $t4, $t6, $t20, $t22 + 26: $t23 := 1 + # live vars: $t2, $t4, $t6, $t20, $t22, $t23 + 27: $t21 := +($t22, $t23) + # live vars: $t2, $t4, $t6, $t20, $t21 + 28: $t5 := move($t21) + # live vars: $t2, $t4, $t5, $t6, $t20 + 29: label L8 + # live vars: $t2, $t4, $t5, $t6, $t20 + 30: $t25 := copy($t5) + # live vars: $t2, $t4, $t5, $t6, $t20, $t25 + 31: $t24 := <($t25, $t6) + # live vars: $t2, $t4, $t5, $t6, $t20, $t24 + 32: if ($t24) goto 33 else goto 57 + # live vars: $t2, $t4, $t5, $t6, $t20 + 33: label L10 + # live vars: $t2, $t4, $t5, $t6, $t20 + 34: $t29 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t6, $t20, $t29 + 35: $t28 := vector::borrow($t29, $t5) + # live vars: $t2, $t4, $t5, $t6, $t20, $t28 + 36: $t27 := move($t28) + # live vars: $t2, $t4, $t5, $t6, $t20, $t27 + 37: $t30 := read_ref($t27) + # live vars: $t2, $t4, $t5, $t6, $t20, $t30 + 38: $t31 := 1 + # live vars: $t2, $t4, $t5, $t6, $t20, $t30, $t31 + 39: $t26 := >($t30, $t31) + # live vars: $t2, $t4, $t5, $t6, $t20, $t26 + 40: if ($t26) goto 43 else goto 41 + # live vars: $t2, $t4, $t5, $t6, $t20 + 41: label L18 + # live vars: $t2, $t4, $t5, $t6, $t20 + 42: goto 51 + # live vars: $t2, $t4, $t5, $t6, $t20 + 43: label L13 + # live vars: $t2, $t4, $t5, $t6, $t20 + 44: $t32 := copy($t4) + # live vars: $t2, $t4, $t5, $t6, $t20, $t32 + 45: $t33 := copy($t20) + # live vars: $t2, $t4, $t5, $t6, $t20, $t32, $t33 + 46: vector::swap($t32, $t33, $t5) + # live vars: $t2, $t4, $t5, $t6, $t20 + 47: $t35 := move($t20) + # live vars: $t2, $t4, $t5, $t6, $t35 + 48: $t36 := 1 + # live vars: $t2, $t4, $t5, $t6, $t35, $t36 + 49: $t34 := +($t35, $t36) + # live vars: $t2, $t4, $t5, $t6, $t34 + 50: $t20 := move($t34) + # live vars: $t2, $t4, $t5, $t6, $t20 + 51: label L15 + # live vars: $t2, $t4, $t5, $t6, $t20 + 52: $t38 := move($t5) + # live vars: $t2, $t4, $t6, $t20, $t38 + 53: $t39 := 1 + # live vars: $t2, $t4, $t6, $t20, $t38, $t39 + 54: $t37 := +($t38, $t39) + # live vars: $t2, $t4, $t6, $t20, $t37 + 55: $t5 := move($t37) + # live vars: $t2, $t4, $t5, $t6, $t20 + 56: goto 29 + # live vars: $t2, $t4, $t5, $t6, $t20 + 57: label L11 + # live vars: $t2, $t4 + 58: drop($t4) # live vars: $t2 - 65: $t33 := freeze_ref(implicit)($t2) - # live vars: $t33 - 66: $t34 := 0 - # live vars: $t33, $t34 - 67: $t32 := vector::borrow($t33, $t34) - # live vars: $t32 - 68: $t0 := read_ref($t32) + 59: $t41 := freeze_ref(implicit)($t2) + # live vars: $t41 + 60: $t42 := 0 + # live vars: $t41, $t42 + 61: $t40 := vector::borrow($t41, $t42) + # live vars: $t40 + 62: $t0 := read_ref($t40) # live vars: $t0 - 69: return $t0 + 63: return $t0 + # live vars: $t2, $t4, $t5, $t6 + 64: label L7 + # live vars: $t2, $t4, $t5, $t6 + 65: $t18 := move($t5) + # live vars: $t2, $t4, $t6, $t18 + 66: $t19 := 1 + # live vars: $t2, $t4, $t6, $t18, $t19 + 67: $t17 := +($t18, $t19) + # live vars: $t2, $t4, $t6, $t17 + 68: $t5 := move($t17) + # live vars: $t2, $t4, $t5, $t6 + 69: goto 6 +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun m::foo(): u64 { + var $t0: u64 [unused] + var $t1: vector + var $t2: &mut vector + var $t3: u64 [unused] + var $t4: &mut vector + var $t5: u64 + var $t6: u64 + var $t7: &vector + var $t8: bool + var $t9: u64 + var $t10: bool [unused] + var $t11: bool [unused] + var $t12: &u64 [unused] + var $t13: &u64 + var $t14: &vector [unused] + var $t15: u64 [unused] + var $t16: u64 + var $t17: u64 [unused] + var $t18: u64 [unused] + var $t19: u64 [unused] + var $t20: u64 [unused] + var $t21: u64 [unused] + var $t22: u64 [unused] + var $t23: u64 + var $t24: bool [unused] + var $t25: u64 [unused] + var $t26: bool [unused] + var $t27: &u64 [unused] + var $t28: &u64 [unused] + var $t29: &vector [unused] + var $t30: u64 [unused] + var $t31: u64 [unused] + var $t32: &mut vector + var $t33: u64 [unused] + var $t34: u64 [unused] + var $t35: u64 [unused] + var $t36: u64 [unused] + var $t37: u64 [unused] + var $t38: u64 [unused] + var $t39: u64 [unused] + var $t40: &u64 [unused] + var $t41: &vector [unused] + var $t42: u64 [unused] + # live vars: + 0: $t1 := ["1", "2", "3"] + # live vars: $t1 + 1: $t2 := borrow_local($t1) + # live vars: $t2 + 2: $t4 := copy($t2) + # live vars: $t2, $t4 + 3: $t5 := 0 + # live vars: $t2, $t4, $t5 + 4: $t7 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t7 + 5: $t6 := vector::length($t7) + # live vars: $t2, $t4, $t5, $t6 + 6: label L0 + # live vars: $t2, $t4, $t5, $t6 + 7: $t9 := copy($t5) + # live vars: $t2, $t4, $t5, $t6, $t9 + 8: $t8 := <($t9, $t6) + # live vars: $t2, $t4, $t5, $t6, $t8 + 9: if ($t8) goto 12 else goto 10 + # live vars: $t2, $t4, $t5, $t6 + 10: label L16 + # live vars: $t2, $t4, $t5, $t6 + 11: goto 23 + # live vars: $t2, $t4, $t5, $t6 + 12: label L2 + # live vars: $t2, $t4, $t5, $t6 + 13: $t7 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t6, $t7 + 14: $t13 := vector::borrow($t7, $t5) + # live vars: $t2, $t4, $t5, $t6, $t13 + 15: $t13 := move($t13) + # live vars: $t2, $t4, $t5, $t6, $t13 + 16: $t9 := read_ref($t13) + # live vars: $t2, $t4, $t5, $t6, $t9 + 17: $t16 := 1 + # live vars: $t2, $t4, $t5, $t6, $t9, $t16 + 18: $t8 := >($t9, $t16) + # live vars: $t2, $t4, $t5, $t6, $t8 + 19: $t8 := !($t8) + # live vars: $t2, $t4, $t5, $t6, $t8 + 20: if ($t8) goto 21 else goto 64 + # live vars: $t2, $t4, $t5, $t6 + 21: label L17 + # live vars: $t2, $t4, $t5, $t6 + 22: goto 23 + # live vars: $t2, $t4, $t5, $t6 + 23: label L1 + # live vars: $t2, $t4, $t5, $t6 + 24: $t9 := copy($t5) + # live vars: $t2, $t4, $t5, $t6, $t9 + 25: $t16 := move($t5) + # live vars: $t2, $t4, $t6, $t9, $t16 + 26: $t23 := 1 + # live vars: $t2, $t4, $t6, $t9, $t16, $t23 + 27: $t16 := +($t16, $t23) + # live vars: $t2, $t4, $t6, $t9, $t16 + 28: $t5 := move($t16) + # live vars: $t2, $t4, $t5, $t6, $t9 + 29: label L8 + # live vars: $t2, $t4, $t5, $t6, $t9 + 30: $t16 := copy($t5) + # live vars: $t2, $t4, $t5, $t6, $t9, $t16 + 31: $t8 := <($t16, $t6) + # live vars: $t2, $t4, $t5, $t6, $t8, $t9 + 32: if ($t8) goto 33 else goto 57 + # live vars: $t2, $t4, $t5, $t6, $t9 + 33: label L10 + # live vars: $t2, $t4, $t5, $t6, $t9 + 34: $t7 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t6, $t7, $t9 + 35: $t13 := vector::borrow($t7, $t5) + # live vars: $t2, $t4, $t5, $t6, $t9, $t13 + 36: $t13 := move($t13) + # live vars: $t2, $t4, $t5, $t6, $t9, $t13 + 37: $t16 := read_ref($t13) + # live vars: $t2, $t4, $t5, $t6, $t9, $t16 + 38: $t23 := 1 + # live vars: $t2, $t4, $t5, $t6, $t9, $t16, $t23 + 39: $t8 := >($t16, $t23) + # live vars: $t2, $t4, $t5, $t6, $t8, $t9 + 40: if ($t8) goto 43 else goto 41 + # live vars: $t2, $t4, $t5, $t6, $t9 + 41: label L18 + # live vars: $t2, $t4, $t5, $t6, $t9 + 42: goto 51 + # live vars: $t2, $t4, $t5, $t6, $t9 + 43: label L13 + # live vars: $t2, $t4, $t5, $t6, $t9 + 44: $t32 := copy($t4) + # live vars: $t2, $t4, $t5, $t6, $t9, $t32 + 45: $t16 := copy($t9) + # live vars: $t2, $t4, $t5, $t6, $t9, $t16, $t32 + 46: vector::swap($t32, $t16, $t5) + # live vars: $t2, $t4, $t5, $t6, $t9 + 47: $t16 := move($t9) + # live vars: $t2, $t4, $t5, $t6, $t16 + 48: $t23 := 1 + # live vars: $t2, $t4, $t5, $t6, $t16, $t23 + 49: $t16 := +($t16, $t23) + # live vars: $t2, $t4, $t5, $t6, $t16 + 50: $t9 := move($t16) + # live vars: $t2, $t4, $t5, $t6, $t9 + 51: label L15 + # live vars: $t2, $t4, $t5, $t6, $t9 + 52: $t16 := move($t5) + # live vars: $t2, $t4, $t6, $t9, $t16 + 53: $t23 := 1 + # live vars: $t2, $t4, $t6, $t9, $t16, $t23 + 54: $t16 := +($t16, $t23) + # live vars: $t2, $t4, $t6, $t9, $t16 + 55: $t5 := move($t16) + # live vars: $t2, $t4, $t5, $t6, $t9 + 56: goto 29 + # live vars: $t2, $t4, $t5, $t6, $t9 + 57: label L11 + # live vars: $t2, $t4 + 58: drop($t4) + # live vars: $t2 + 59: $t7 := freeze_ref(implicit)($t2) + # live vars: $t7 + 60: $t9 := 0 + # live vars: $t7, $t9 + 61: $t13 := vector::borrow($t7, $t9) + # live vars: $t13 + 62: $t9 := read_ref($t13) + # live vars: $t9 + 63: return $t9 + # live vars: $t2, $t4, $t5, $t6 + 64: label L7 + # live vars: $t2, $t4, $t5, $t6 + 65: $t9 := move($t5) + # live vars: $t2, $t4, $t6, $t9 + 66: $t16 := 1 + # live vars: $t2, $t4, $t6, $t9, $t16 + 67: $t9 := +($t9, $t16) + # live vars: $t2, $t4, $t6, $t9 + 68: $t5 := move($t9) + # live vars: $t2, $t4, $t5, $t6 + 69: goto 6 +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun m::foo(): u64 { + var $t0: u64 [unused] + var $t1: vector + var $t2: &mut vector + var $t3: u64 [unused] + var $t4: &mut vector + var $t5: u64 + var $t6: u64 + var $t7: &vector + var $t8: bool + var $t9: u64 + var $t10: bool [unused] + var $t11: bool [unused] + var $t12: &u64 [unused] + var $t13: &u64 + var $t14: &vector [unused] + var $t15: u64 [unused] + var $t16: u64 + var $t17: u64 [unused] + var $t18: u64 [unused] + var $t19: u64 [unused] + var $t20: u64 [unused] + var $t21: u64 [unused] + var $t22: u64 [unused] + var $t23: u64 + var $t24: bool [unused] + var $t25: u64 [unused] + var $t26: bool [unused] + var $t27: &u64 [unused] + var $t28: &u64 [unused] + var $t29: &vector [unused] + var $t30: u64 [unused] + var $t31: u64 [unused] + var $t32: &mut vector + var $t33: u64 [unused] + var $t34: u64 [unused] + var $t35: u64 [unused] + var $t36: u64 [unused] + var $t37: u64 [unused] + var $t38: u64 [unused] + var $t39: u64 [unused] + var $t40: &u64 [unused] + var $t41: &vector [unused] + var $t42: u64 [unused] + # live vars: + 0: $t1 := ["1", "2", "3"] + # live vars: $t1 + 1: $t2 := borrow_local($t1) + # live vars: $t2 + 2: $t4 := copy($t2) + # live vars: $t2, $t4 + 3: $t5 := 0 + # live vars: $t2, $t4, $t5 + 4: $t7 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t7 + 5: $t6 := vector::length($t7) + # live vars: $t2, $t4, $t5, $t6 + 6: label L0 + # live vars: $t2, $t4, $t5, $t6 + 7: $t9 := copy($t5) + # live vars: $t2, $t4, $t5, $t6, $t9 + 8: $t8 := <($t9, $t6) + # live vars: $t2, $t4, $t5, $t6, $t8 + 9: if ($t8) goto 12 else goto 10 + # live vars: $t2, $t4, $t5, $t6 + 10: label L16 + # live vars: $t2, $t4, $t5, $t6 + 11: goto 22 + # live vars: $t2, $t4, $t5, $t6 + 12: label L2 + # live vars: $t2, $t4, $t5, $t6 + 13: $t7 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t6, $t7 + 14: $t13 := vector::borrow($t7, $t5) + # live vars: $t2, $t4, $t5, $t6, $t13 + 15: $t9 := read_ref($t13) + # live vars: $t2, $t4, $t5, $t6, $t9 + 16: $t16 := 1 + # live vars: $t2, $t4, $t5, $t6, $t9, $t16 + 17: $t8 := >($t9, $t16) + # live vars: $t2, $t4, $t5, $t6, $t8 + 18: $t8 := !($t8) + # live vars: $t2, $t4, $t5, $t6, $t8 + 19: if ($t8) goto 20 else goto 62 + # live vars: $t2, $t4, $t5, $t6 + 20: label L17 + # live vars: $t2, $t4, $t5, $t6 + 21: goto 22 + # live vars: $t2, $t4, $t5, $t6 + 22: label L1 + # live vars: $t2, $t4, $t5, $t6 + 23: $t9 := copy($t5) + # live vars: $t2, $t4, $t5, $t6, $t9 + 24: $t16 := move($t5) + # live vars: $t2, $t4, $t6, $t9, $t16 + 25: $t23 := 1 + # live vars: $t2, $t4, $t6, $t9, $t16, $t23 + 26: $t16 := +($t16, $t23) + # live vars: $t2, $t4, $t6, $t9, $t16 + 27: $t5 := move($t16) + # live vars: $t2, $t4, $t5, $t6, $t9 + 28: label L8 + # live vars: $t2, $t4, $t5, $t6, $t9 + 29: $t16 := copy($t5) + # live vars: $t2, $t4, $t5, $t6, $t9, $t16 + 30: $t8 := <($t16, $t6) + # live vars: $t2, $t4, $t5, $t6, $t8, $t9 + 31: if ($t8) goto 32 else goto 55 + # live vars: $t2, $t4, $t5, $t6, $t9 + 32: label L10 + # live vars: $t2, $t4, $t5, $t6, $t9 + 33: $t7 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t6, $t7, $t9 + 34: $t13 := vector::borrow($t7, $t5) + # live vars: $t2, $t4, $t5, $t6, $t9, $t13 + 35: $t16 := read_ref($t13) + # live vars: $t2, $t4, $t5, $t6, $t9, $t16 + 36: $t23 := 1 + # live vars: $t2, $t4, $t5, $t6, $t9, $t16, $t23 + 37: $t8 := >($t16, $t23) + # live vars: $t2, $t4, $t5, $t6, $t8, $t9 + 38: if ($t8) goto 41 else goto 39 + # live vars: $t2, $t4, $t5, $t6, $t9 + 39: label L18 + # live vars: $t2, $t4, $t5, $t6, $t9 + 40: goto 49 + # live vars: $t2, $t4, $t5, $t6, $t9 + 41: label L13 + # live vars: $t2, $t4, $t5, $t6, $t9 + 42: $t32 := copy($t4) + # live vars: $t2, $t4, $t5, $t6, $t9, $t32 + 43: $t16 := copy($t9) + # live vars: $t2, $t4, $t5, $t6, $t9, $t16, $t32 + 44: vector::swap($t32, $t16, $t5) + # live vars: $t2, $t4, $t5, $t6, $t9 + 45: $t16 := move($t9) + # live vars: $t2, $t4, $t5, $t6, $t16 + 46: $t23 := 1 + # live vars: $t2, $t4, $t5, $t6, $t16, $t23 + 47: $t16 := +($t16, $t23) + # live vars: $t2, $t4, $t5, $t6, $t16 + 48: $t9 := move($t16) + # live vars: $t2, $t4, $t5, $t6, $t9 + 49: label L15 + # live vars: $t2, $t4, $t5, $t6, $t9 + 50: $t16 := move($t5) + # live vars: $t2, $t4, $t6, $t9, $t16 + 51: $t23 := 1 + # live vars: $t2, $t4, $t6, $t9, $t16, $t23 + 52: $t16 := +($t16, $t23) + # live vars: $t2, $t4, $t6, $t9, $t16 + 53: $t5 := move($t16) + # live vars: $t2, $t4, $t5, $t6, $t9 + 54: goto 28 + # live vars: $t2, $t4, $t5, $t6, $t9 + 55: label L11 + # live vars: $t2, $t4 + 56: drop($t4) + # live vars: $t2 + 57: $t7 := freeze_ref(implicit)($t2) + # live vars: $t7 + 58: $t9 := 0 + # live vars: $t7, $t9 + 59: $t13 := vector::borrow($t7, $t9) + # live vars: $t13 + 60: $t9 := read_ref($t13) + # live vars: $t9 + 61: return $t9 + # live vars: $t2, $t4, $t5, $t6 + 62: label L7 + # live vars: $t2, $t4, $t5, $t6 + 63: $t9 := move($t5) + # live vars: $t2, $t4, $t6, $t9 + 64: $t16 := 1 + # live vars: $t2, $t4, $t6, $t9, $t16 + 65: $t9 := +($t9, $t16) + # live vars: $t2, $t4, $t6, $t9 + 66: $t5 := move($t9) + # live vars: $t2, $t4, $t5, $t6 + 67: goto 6 +} + + +============ disassembled file-format ================== +// Move bytecode v7 +module 42.m { + + +foo(): u64 /* def_idx: 0 */ { +L0: loc0: vector +L1: loc1: &mut vector +L2: loc2: &mut vector +L3: loc3: u64 +L4: loc4: u64 +L5: loc5: u64 +B0: + 0: LdConst[0](Vector(U64): [3, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0]) + 1: StLoc[0](loc0: vector) + 2: MutBorrowLoc[0](loc0: vector) + 3: StLoc[1](loc1: &mut vector) + 4: CopyLoc[1](loc1: &mut vector) + 5: StLoc[2](loc2: &mut vector) + 6: LdU64(0) + 7: StLoc[3](loc3: u64) + 8: CopyLoc[2](loc2: &mut vector) + 9: FreezeRef + 10: VecLen(1) + 11: StLoc[4](loc4: u64) +B1: + 12: CopyLoc[3](loc3: u64) + 13: CopyLoc[4](loc4: u64) + 14: Lt + 15: BrTrue(17) +B2: + 16: Branch(26) +B3: + 17: CopyLoc[2](loc2: &mut vector) + 18: FreezeRef + 19: CopyLoc[3](loc3: u64) + 20: VecImmBorrow(1) + 21: ReadRef + 22: LdU64(1) + 23: Gt + 24: BrTrue(66) +B4: + 25: Branch(26) +B5: + 26: CopyLoc[3](loc3: u64) + 27: StLoc[5](loc5: u64) + 28: MoveLoc[3](loc3: u64) + 29: LdU64(1) + 30: Add + 31: StLoc[3](loc3: u64) +B6: + 32: CopyLoc[3](loc3: u64) + 33: CopyLoc[4](loc4: u64) + 34: Lt + 35: BrFalse(58) +B7: + 36: CopyLoc[2](loc2: &mut vector) + 37: FreezeRef + 38: CopyLoc[3](loc3: u64) + 39: VecImmBorrow(1) + 40: ReadRef + 41: LdU64(1) + 42: Gt + 43: BrTrue(45) +B8: + 44: Branch(53) +B9: + 45: CopyLoc[2](loc2: &mut vector) + 46: CopyLoc[5](loc5: u64) + 47: CopyLoc[3](loc3: u64) + 48: VecSwap(1) + 49: MoveLoc[5](loc5: u64) + 50: LdU64(1) + 51: Add + 52: StLoc[5](loc5: u64) +B10: + 53: MoveLoc[3](loc3: u64) + 54: LdU64(1) + 55: Add + 56: StLoc[3](loc3: u64) + 57: Branch(32) +B11: + 58: MoveLoc[2](loc2: &mut vector) + 59: Pop + 60: MoveLoc[1](loc1: &mut vector) + 61: FreezeRef + 62: LdU64(0) + 63: VecImmBorrow(1) + 64: ReadRef + 65: Ret +B12: + 66: MoveLoc[3](loc3: u64) + 67: LdU64(1) + 68: Add + 69: StLoc[3](loc3: u64) + 70: Branch(12) +} } +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/live-var/mut_inline_typed.exp b/third_party/move/move-compiler-v2/tests/live-var/mut_inline_typed.exp index 294f89be7fbf0..e6e9ffce3b0ea 100644 --- a/third_party/move/move-compiler-v2/tests/live-var/mut_inline_typed.exp +++ b/third_party/move/move-compiler-v2/tests/live-var/mut_inline_typed.exp @@ -11,32 +11,40 @@ fun m::foo(): u64 { var $t6: u64 var $t7: &vector var $t8: bool - var $t9: bool + var $t9: u64 var $t10: bool - var $t11: &u64 + var $t11: bool var $t12: &u64 - var $t13: &vector - var $t14: u64 + var $t13: &u64 + var $t14: &vector var $t15: u64 var $t16: u64 var $t17: u64 var $t18: u64 var $t19: u64 var $t20: u64 - var $t21: bool - var $t22: bool - var $t23: &u64 - var $t24: &u64 - var $t25: &vector - var $t26: u64 - var $t27: u64 - var $t28: u64 - var $t29: u64 + var $t21: u64 + var $t22: u64 + var $t23: u64 + var $t24: bool + var $t25: u64 + var $t26: bool + var $t27: &u64 + var $t28: &u64 + var $t29: &vector var $t30: u64 var $t31: u64 - var $t32: &u64 - var $t33: &vector + var $t32: &mut vector + var $t33: u64 var $t34: u64 + var $t35: u64 + var $t36: u64 + var $t37: u64 + var $t38: u64 + var $t39: u64 + var $t40: &u64 + var $t41: &vector + var $t42: u64 0: $t1 := ["1", "2", "3"] 1: $t2 := borrow_local($t1) 2: $t4 := infer($t2) @@ -44,69 +52,77 @@ fun m::foo(): u64 { 4: $t7 := freeze_ref(implicit)($t4) 5: $t6 := vector::length($t7) 6: label L0 - 7: $t8 := <($t5, $t6) - 8: if ($t8) goto 9 else goto 27 - 9: label L2 - 10: $t13 := freeze_ref(implicit)($t4) - 11: $t12 := vector::borrow($t13, $t5) - 12: $t11 := infer($t12) - 13: $t14 := read_ref($t11) - 14: $t15 := 1 - 15: $t10 := >($t14, $t15) - 16: $t9 := !($t10) - 17: if ($t9) goto 18 else goto 21 - 18: label L5 - 19: goto 31 - 20: goto 22 - 21: label L6 - 22: label L7 - 23: $t17 := 1 - 24: $t16 := +($t5, $t17) - 25: $t5 := infer($t16) - 26: goto 29 - 27: label L3 + 7: $t9 := infer($t5) + 8: $t8 := <($t9, $t6) + 9: if ($t8) goto 10 else goto 29 + 10: label L2 + 11: $t14 := freeze_ref(implicit)($t4) + 12: $t13 := vector::borrow($t14, $t5) + 13: $t12 := infer($t13) + 14: $t15 := read_ref($t12) + 15: $t16 := 1 + 16: $t11 := >($t15, $t16) + 17: $t10 := !($t11) + 18: if ($t10) goto 19 else goto 22 + 19: label L5 + 20: goto 33 + 21: goto 23 + 22: label L6 + 23: label L7 + 24: $t18 := infer($t5) + 25: $t19 := 1 + 26: $t17 := +($t18, $t19) + 27: $t5 := infer($t17) 28: goto 31 - 29: label L4 - 30: goto 6 - 31: label L1 - 32: $t18 := infer($t5) - 33: $t20 := 1 - 34: $t19 := +($t5, $t20) - 35: $t5 := infer($t19) - 36: label L8 - 37: $t21 := <($t5, $t6) - 38: if ($t21) goto 39 else goto 59 - 39: label L10 - 40: $t25 := freeze_ref(implicit)($t4) - 41: $t24 := vector::borrow($t25, $t5) - 42: $t23 := infer($t24) - 43: $t26 := read_ref($t23) - 44: $t27 := 1 - 45: $t22 := >($t26, $t27) - 46: if ($t22) goto 47 else goto 53 - 47: label L13 - 48: vector::swap($t4, $t18, $t5) - 49: $t29 := 1 - 50: $t28 := +($t18, $t29) - 51: $t18 := infer($t28) - 52: goto 54 - 53: label L14 - 54: label L15 - 55: $t31 := 1 - 56: $t30 := +($t5, $t31) - 57: $t5 := infer($t30) - 58: goto 61 - 59: label L11 - 60: goto 63 - 61: label L12 - 62: goto 36 - 63: label L9 - 64: $t3 := infer($t18) - 65: $t33 := freeze_ref(implicit)($t2) - 66: $t34 := 0 - 67: $t32 := vector::borrow($t33, $t34) - 68: $t0 := read_ref($t32) - 69: return $t0 + 29: label L3 + 30: goto 33 + 31: label L4 + 32: goto 6 + 33: label L1 + 34: $t20 := infer($t5) + 35: $t22 := infer($t5) + 36: $t23 := 1 + 37: $t21 := +($t22, $t23) + 38: $t5 := infer($t21) + 39: label L8 + 40: $t25 := infer($t5) + 41: $t24 := <($t25, $t6) + 42: if ($t24) goto 43 else goto 67 + 43: label L10 + 44: $t29 := freeze_ref(implicit)($t4) + 45: $t28 := vector::borrow($t29, $t5) + 46: $t27 := infer($t28) + 47: $t30 := read_ref($t27) + 48: $t31 := 1 + 49: $t26 := >($t30, $t31) + 50: if ($t26) goto 51 else goto 60 + 51: label L13 + 52: $t32 := infer($t4) + 53: $t33 := infer($t20) + 54: vector::swap($t32, $t33, $t5) + 55: $t35 := infer($t20) + 56: $t36 := 1 + 57: $t34 := +($t35, $t36) + 58: $t20 := infer($t34) + 59: goto 61 + 60: label L14 + 61: label L15 + 62: $t38 := infer($t5) + 63: $t39 := 1 + 64: $t37 := +($t38, $t39) + 65: $t5 := infer($t37) + 66: goto 69 + 67: label L11 + 68: goto 71 + 69: label L12 + 70: goto 39 + 71: label L9 + 72: $t3 := infer($t20) + 73: $t41 := freeze_ref(implicit)($t2) + 74: $t42 := 0 + 75: $t40 := vector::borrow($t41, $t42) + 76: $t0 := read_ref($t40) + 77: return $t0 } ============ after LiveVarAnalysisProcessor: ================ @@ -122,32 +138,40 @@ fun m::foo(): u64 { var $t6: u64 var $t7: &vector var $t8: bool - var $t9: bool + var $t9: u64 var $t10: bool - var $t11: &u64 + var $t11: bool var $t12: &u64 - var $t13: &vector - var $t14: u64 + var $t13: &u64 + var $t14: &vector var $t15: u64 var $t16: u64 var $t17: u64 var $t18: u64 var $t19: u64 var $t20: u64 - var $t21: bool - var $t22: bool - var $t23: &u64 - var $t24: &u64 - var $t25: &vector - var $t26: u64 - var $t27: u64 - var $t28: u64 - var $t29: u64 + var $t21: u64 + var $t22: u64 + var $t23: u64 + var $t24: bool + var $t25: u64 + var $t26: bool + var $t27: &u64 + var $t28: &u64 + var $t29: &vector var $t30: u64 var $t31: u64 - var $t32: &u64 - var $t33: &vector + var $t32: &mut vector + var $t33: u64 var $t34: u64 + var $t35: u64 + var $t36: u64 + var $t37: u64 + var $t38: u64 + var $t39: u64 + var $t40: &u64 + var $t41: &vector + var $t42: u64 # live vars: 0: $t1 := ["1", "2", "3"] # live vars: $t1 @@ -163,129 +187,1205 @@ fun m::foo(): u64 { # live vars: $t2, $t4, $t5, $t6 6: label L0 # live vars: $t2, $t4, $t5, $t6 - 7: $t8 := <($t5, $t6) + 7: $t9 := infer($t5) + # live vars: $t2, $t4, $t5, $t6, $t9 + 8: $t8 := <($t9, $t6) # live vars: $t2, $t4, $t5, $t6, $t8 - 8: if ($t8) goto 9 else goto 27 + 9: if ($t8) goto 10 else goto 29 # live vars: $t2, $t4, $t5, $t6 - 9: label L2 + 10: label L2 # live vars: $t2, $t4, $t5, $t6 - 10: $t13 := freeze_ref(implicit)($t4) + 11: $t14 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t6, $t14 + 12: $t13 := vector::borrow($t14, $t5) # live vars: $t2, $t4, $t5, $t6, $t13 - 11: $t12 := vector::borrow($t13, $t5) + 13: $t12 := infer($t13) # live vars: $t2, $t4, $t5, $t6, $t12 - 12: $t11 := infer($t12) + 14: $t15 := read_ref($t12) + # live vars: $t2, $t4, $t5, $t6, $t15 + 15: $t16 := 1 + # live vars: $t2, $t4, $t5, $t6, $t15, $t16 + 16: $t11 := >($t15, $t16) # live vars: $t2, $t4, $t5, $t6, $t11 - 13: $t14 := read_ref($t11) - # live vars: $t2, $t4, $t5, $t6, $t14 - 14: $t15 := 1 - # live vars: $t2, $t4, $t5, $t6, $t14, $t15 - 15: $t10 := >($t14, $t15) + 17: $t10 := !($t11) # live vars: $t2, $t4, $t5, $t6, $t10 - 16: $t9 := !($t10) + 18: if ($t10) goto 19 else goto 22 + # live vars: $t2, $t4, $t5, $t6 + 19: label L5 + # live vars: $t2, $t4, $t5, $t6 + 20: goto 33 + # live vars: $t2, $t4, $t5, $t6 + 21: goto 23 + # live vars: $t2, $t4, $t5, $t6 + 22: label L6 + # live vars: $t2, $t4, $t5, $t6 + 23: label L7 + # live vars: $t2, $t4, $t5, $t6 + 24: $t18 := infer($t5) + # live vars: $t2, $t4, $t6, $t18 + 25: $t19 := 1 + # live vars: $t2, $t4, $t6, $t18, $t19 + 26: $t17 := +($t18, $t19) + # live vars: $t2, $t4, $t6, $t17 + 27: $t5 := infer($t17) + # live vars: $t2, $t4, $t5, $t6 + 28: goto 31 + # live vars: $t2, $t4, $t5, $t6 + 29: label L3 + # live vars: $t2, $t4, $t5, $t6 + 30: goto 33 + # live vars: $t2, $t4, $t5, $t6 + 31: label L4 + # live vars: $t2, $t4, $t5, $t6 + 32: goto 6 + # live vars: $t2, $t4, $t5, $t6 + 33: label L1 + # live vars: $t2, $t4, $t5, $t6 + 34: $t20 := infer($t5) + # live vars: $t2, $t4, $t5, $t6, $t20 + 35: $t22 := infer($t5) + # live vars: $t2, $t4, $t6, $t20, $t22 + 36: $t23 := 1 + # live vars: $t2, $t4, $t6, $t20, $t22, $t23 + 37: $t21 := +($t22, $t23) + # live vars: $t2, $t4, $t6, $t20, $t21 + 38: $t5 := infer($t21) + # live vars: $t2, $t4, $t5, $t6, $t20 + 39: label L8 + # live vars: $t2, $t4, $t5, $t6, $t20 + 40: $t25 := infer($t5) + # live vars: $t2, $t4, $t5, $t6, $t20, $t25 + 41: $t24 := <($t25, $t6) + # live vars: $t2, $t4, $t5, $t6, $t20, $t24 + 42: if ($t24) goto 43 else goto 67 + # live vars: $t2, $t4, $t5, $t6, $t20 + 43: label L10 + # live vars: $t2, $t4, $t5, $t6, $t20 + 44: $t29 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t6, $t20, $t29 + 45: $t28 := vector::borrow($t29, $t5) + # live vars: $t2, $t4, $t5, $t6, $t20, $t28 + 46: $t27 := infer($t28) + # live vars: $t2, $t4, $t5, $t6, $t20, $t27 + 47: $t30 := read_ref($t27) + # live vars: $t2, $t4, $t5, $t6, $t20, $t30 + 48: $t31 := 1 + # live vars: $t2, $t4, $t5, $t6, $t20, $t30, $t31 + 49: $t26 := >($t30, $t31) + # live vars: $t2, $t4, $t5, $t6, $t20, $t26 + 50: if ($t26) goto 51 else goto 60 + # live vars: $t2, $t4, $t5, $t6, $t20 + 51: label L13 + # live vars: $t2, $t4, $t5, $t6, $t20 + 52: $t32 := infer($t4) + # live vars: $t2, $t4, $t5, $t6, $t20, $t32 + 53: $t33 := infer($t20) + # live vars: $t2, $t4, $t5, $t6, $t20, $t32, $t33 + 54: vector::swap($t32, $t33, $t5) + # live vars: $t2, $t4, $t5, $t6, $t20 + 55: $t35 := infer($t20) + # live vars: $t2, $t4, $t5, $t6, $t35 + 56: $t36 := 1 + # live vars: $t2, $t4, $t5, $t6, $t35, $t36 + 57: $t34 := +($t35, $t36) + # live vars: $t2, $t4, $t5, $t6, $t34 + 58: $t20 := infer($t34) + # live vars: $t2, $t4, $t5, $t6, $t20 + 59: goto 61 + # live vars: $t2, $t4, $t5, $t6, $t20 + 60: label L14 + # live vars: $t2, $t4, $t5, $t6, $t20 + 61: label L15 + # live vars: $t2, $t4, $t5, $t6, $t20 + 62: $t38 := infer($t5) + # live vars: $t2, $t4, $t6, $t20, $t38 + 63: $t39 := 1 + # live vars: $t2, $t4, $t6, $t20, $t38, $t39 + 64: $t37 := +($t38, $t39) + # live vars: $t2, $t4, $t6, $t20, $t37 + 65: $t5 := infer($t37) + # live vars: $t2, $t4, $t5, $t6, $t20 + 66: goto 69 + # live vars: $t2, $t4, $t5, $t6, $t20 + 67: label L11 + # live vars: $t2, $t20 + 68: goto 71 + # live vars: $t2, $t4, $t5, $t6, $t20 + 69: label L12 + # live vars: $t2, $t4, $t5, $t6, $t20 + 70: goto 39 + # live vars: $t2, $t20 + 71: label L9 + # live vars: $t2, $t20 + 72: $t3 := infer($t20) + # live vars: $t2 + 73: $t41 := freeze_ref(implicit)($t2) + # live vars: $t41 + 74: $t42 := 0 + # live vars: $t41, $t42 + 75: $t40 := vector::borrow($t41, $t42) + # live vars: $t40 + 76: $t0 := read_ref($t40) + # live vars: $t0 + 77: return $t0 +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun m::foo(): u64 { + var $t0: u64 + var $t1: vector + var $t2: &mut vector + var $t3: u64 + var $t4: &mut vector + var $t5: u64 + var $t6: u64 + var $t7: &vector + var $t8: bool + var $t9: u64 + var $t10: bool + var $t11: bool + var $t12: &u64 + var $t13: &u64 + var $t14: &vector + var $t15: u64 + var $t16: u64 + var $t17: u64 + var $t18: u64 + var $t19: u64 + var $t20: u64 + var $t21: u64 + var $t22: u64 + var $t23: u64 + var $t24: bool + var $t25: u64 + var $t26: bool + var $t27: &u64 + var $t28: &u64 + var $t29: &vector + var $t30: u64 + var $t31: u64 + var $t32: &mut vector + var $t33: u64 + var $t34: u64 + var $t35: u64 + var $t36: u64 + var $t37: u64 + var $t38: u64 + var $t39: u64 + var $t40: &u64 + var $t41: &vector + var $t42: u64 + # live vars: + 0: $t1 := ["1", "2", "3"] + # live vars: $t1 + 1: $t2 := borrow_local($t1) + # live vars: $t2 + 2: $t4 := infer($t2) + # live vars: $t2, $t4 + 3: $t5 := 0 + # live vars: $t2, $t4, $t5 + 4: $t7 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t7 + 5: $t6 := vector::length($t7) + # live vars: $t2, $t4, $t5, $t6 + 6: label L0 + # live vars: $t2, $t4, $t5, $t6 + 7: $t9 := infer($t5) # live vars: $t2, $t4, $t5, $t6, $t9 - 17: if ($t9) goto 18 else goto 21 + 8: $t8 := <($t9, $t6) + # live vars: $t2, $t4, $t5, $t6, $t8 + 9: if ($t8) goto 10 else goto 29 # live vars: $t2, $t4, $t5, $t6 - 18: label L5 + 10: label L2 # live vars: $t2, $t4, $t5, $t6 - 19: goto 31 + 11: $t14 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t6, $t14 + 12: $t13 := vector::borrow($t14, $t5) + # live vars: $t2, $t4, $t5, $t6, $t13 + 13: $t12 := infer($t13) + # live vars: $t2, $t4, $t5, $t6, $t12 + 14: $t15 := read_ref($t12) + # live vars: $t2, $t4, $t5, $t6, $t15 + 15: $t16 := 1 + # live vars: $t2, $t4, $t5, $t6, $t15, $t16 + 16: $t11 := >($t15, $t16) + # live vars: $t2, $t4, $t5, $t6, $t11 + 17: $t10 := !($t11) + # live vars: $t2, $t4, $t5, $t6, $t10 + 18: if ($t10) goto 19 else goto 22 # live vars: $t2, $t4, $t5, $t6 - 20: goto 22 + 19: label L5 # live vars: $t2, $t4, $t5, $t6 - 21: label L6 + 20: goto 33 # live vars: $t2, $t4, $t5, $t6 - 22: label L7 + 21: goto 23 # live vars: $t2, $t4, $t5, $t6 - 23: $t17 := 1 - # live vars: $t2, $t4, $t5, $t6, $t17 - 24: $t16 := +($t5, $t17) - # live vars: $t2, $t4, $t6, $t16 - 25: $t5 := infer($t16) + 22: label L6 # live vars: $t2, $t4, $t5, $t6 - 26: goto 29 + 23: label L7 # live vars: $t2, $t4, $t5, $t6 - 27: label L3 + 24: $t18 := infer($t5) + # live vars: $t2, $t4, $t6, $t18 + 25: $t19 := 1 + # live vars: $t2, $t4, $t6, $t18, $t19 + 26: $t17 := +($t18, $t19) + # live vars: $t2, $t4, $t6, $t17 + 27: $t5 := infer($t17) # live vars: $t2, $t4, $t5, $t6 28: goto 31 # live vars: $t2, $t4, $t5, $t6 - 29: label L4 + 29: label L3 + # live vars: $t2, $t4, $t5, $t6 + 30: goto 33 + # live vars: $t2, $t4, $t5, $t6 + 31: label L4 + # live vars: $t2, $t4, $t5, $t6 + 32: goto 6 + # live vars: $t2, $t4, $t5, $t6 + 33: label L1 + # live vars: $t2, $t4, $t5, $t6 + 34: $t20 := infer($t5) + # live vars: $t2, $t4, $t5, $t6, $t20 + 35: $t22 := infer($t5) + # live vars: $t2, $t4, $t6, $t20, $t22 + 36: $t23 := 1 + # live vars: $t2, $t4, $t6, $t20, $t22, $t23 + 37: $t21 := +($t22, $t23) + # live vars: $t2, $t4, $t6, $t20, $t21 + 38: $t5 := infer($t21) + # live vars: $t2, $t4, $t5, $t6, $t20 + 39: label L8 + # live vars: $t2, $t4, $t5, $t6, $t20 + 40: $t25 := infer($t5) + # live vars: $t2, $t4, $t5, $t6, $t20, $t25 + 41: $t24 := <($t25, $t6) + # live vars: $t2, $t4, $t5, $t6, $t20, $t24 + 42: if ($t24) goto 43 else goto 67 + # live vars: $t2, $t4, $t5, $t6, $t20 + 43: label L10 + # live vars: $t2, $t4, $t5, $t6, $t20 + 44: $t29 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t6, $t20, $t29 + 45: $t28 := vector::borrow($t29, $t5) + # live vars: $t2, $t4, $t5, $t6, $t20, $t28 + 46: $t27 := infer($t28) + # live vars: $t2, $t4, $t5, $t6, $t20, $t27 + 47: $t30 := read_ref($t27) + # live vars: $t2, $t4, $t5, $t6, $t20, $t30 + 48: $t31 := 1 + # live vars: $t2, $t4, $t5, $t6, $t20, $t30, $t31 + 49: $t26 := >($t30, $t31) + # live vars: $t2, $t4, $t5, $t6, $t20, $t26 + 50: if ($t26) goto 51 else goto 60 + # live vars: $t2, $t4, $t5, $t6, $t20 + 51: label L13 + # live vars: $t2, $t4, $t5, $t6, $t20 + 52: $t32 := infer($t4) + # live vars: $t2, $t4, $t5, $t6, $t20, $t32 + 53: $t33 := infer($t20) + # live vars: $t2, $t4, $t5, $t6, $t20, $t32, $t33 + 54: vector::swap($t32, $t33, $t5) + # live vars: $t2, $t4, $t5, $t6, $t20 + 55: $t35 := infer($t20) + # live vars: $t2, $t4, $t5, $t6, $t35 + 56: $t36 := 1 + # live vars: $t2, $t4, $t5, $t6, $t35, $t36 + 57: $t34 := +($t35, $t36) + # live vars: $t2, $t4, $t5, $t6, $t34 + 58: $t20 := infer($t34) + # live vars: $t2, $t4, $t5, $t6, $t20 + 59: goto 61 + # live vars: $t2, $t4, $t5, $t6, $t20 + 60: label L14 + # live vars: $t2, $t4, $t5, $t6, $t20 + 61: label L15 + # live vars: $t2, $t4, $t5, $t6, $t20 + 62: $t38 := infer($t5) + # live vars: $t2, $t4, $t6, $t20, $t38 + 63: $t39 := 1 + # live vars: $t2, $t4, $t6, $t20, $t38, $t39 + 64: $t37 := +($t38, $t39) + # live vars: $t2, $t4, $t6, $t20, $t37 + 65: $t5 := infer($t37) + # live vars: $t2, $t4, $t5, $t6, $t20 + 66: goto 69 + # live vars: $t2, $t4, $t5, $t6, $t20 + 67: label L11 + # live vars: $t2, $t20 + 68: goto 71 + # live vars: $t2, $t4, $t5, $t6, $t20 + 69: label L12 + # live vars: $t2, $t4, $t5, $t6, $t20 + 70: goto 39 + # live vars: $t2, $t20 + 71: label L9 + # live vars: $t2, $t20 + 72: $t3 := infer($t20) + # live vars: $t2 + 73: $t41 := freeze_ref(implicit)($t2) + # live vars: $t41 + 74: $t42 := 0 + # live vars: $t41, $t42 + 75: $t40 := vector::borrow($t41, $t42) + # live vars: $t40 + 76: $t0 := read_ref($t40) + # live vars: $t0 + 77: return $t0 +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun m::foo(): u64 { + var $t0: u64 + var $t1: vector + var $t2: &mut vector + var $t3: u64 + var $t4: &mut vector + var $t5: u64 + var $t6: u64 + var $t7: &vector + var $t8: bool + var $t9: u64 + var $t10: bool + var $t11: bool + var $t12: &u64 + var $t13: &u64 + var $t14: &vector + var $t15: u64 + var $t16: u64 + var $t17: u64 + var $t18: u64 + var $t19: u64 + var $t20: u64 + var $t21: u64 + var $t22: u64 + var $t23: u64 + var $t24: bool + var $t25: u64 + var $t26: bool + var $t27: &u64 + var $t28: &u64 + var $t29: &vector + var $t30: u64 + var $t31: u64 + var $t32: &mut vector + var $t33: u64 + var $t34: u64 + var $t35: u64 + var $t36: u64 + var $t37: u64 + var $t38: u64 + var $t39: u64 + var $t40: &u64 + var $t41: &vector + var $t42: u64 + # live vars: + 0: $t1 := ["1", "2", "3"] + # live vars: $t1 + 1: $t2 := borrow_local($t1) + # live vars: $t2 + 2: $t4 := copy($t2) + # live vars: $t2, $t4 + 3: $t5 := 0 + # live vars: $t2, $t4, $t5 + 4: $t7 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t7 + 5: $t6 := vector::length($t7) + # live vars: $t2, $t4, $t5, $t6 + 6: label L0 + # live vars: $t2, $t4, $t5, $t6 + 7: $t9 := copy($t5) + # live vars: $t2, $t4, $t5, $t6, $t9 + 8: $t8 := <($t9, $t6) + # live vars: $t2, $t4, $t5, $t6, $t8 + 9: if ($t8) goto 12 else goto 10 + # live vars: $t2, $t4, $t5, $t6 + 10: label L16 + # live vars: $t2, $t4, $t5, $t6 + 11: goto 23 + # live vars: $t2, $t4, $t5, $t6 + 12: label L2 # live vars: $t2, $t4, $t5, $t6 - 30: goto 6 + 13: $t14 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t6, $t14 + 14: $t13 := vector::borrow($t14, $t5) + # live vars: $t2, $t4, $t5, $t6, $t13 + 15: $t12 := move($t13) + # live vars: $t2, $t4, $t5, $t6, $t12 + 16: $t15 := read_ref($t12) + # live vars: $t2, $t4, $t5, $t6, $t15 + 17: $t16 := 1 + # live vars: $t2, $t4, $t5, $t6, $t15, $t16 + 18: $t11 := >($t15, $t16) + # live vars: $t2, $t4, $t5, $t6, $t11 + 19: $t10 := !($t11) + # live vars: $t2, $t4, $t5, $t6, $t10 + 20: if ($t10) goto 21 else goto 65 + # live vars: $t2, $t4, $t5, $t6 + 21: label L17 + # live vars: $t2, $t4, $t5, $t6 + 22: goto 23 + # live vars: $t2, $t4, $t5, $t6 + 23: label L1 + # live vars: $t2, $t4, $t5, $t6 + 24: $t20 := copy($t5) + # live vars: $t2, $t4, $t5, $t6, $t20 + 25: $t22 := move($t5) + # live vars: $t2, $t4, $t6, $t20, $t22 + 26: $t23 := 1 + # live vars: $t2, $t4, $t6, $t20, $t22, $t23 + 27: $t21 := +($t22, $t23) + # live vars: $t2, $t4, $t6, $t20, $t21 + 28: $t5 := move($t21) + # live vars: $t2, $t4, $t5, $t6, $t20 + 29: label L8 + # live vars: $t2, $t4, $t5, $t6, $t20 + 30: $t25 := copy($t5) + # live vars: $t2, $t4, $t5, $t6, $t20, $t25 + 31: $t24 := <($t25, $t6) + # live vars: $t2, $t4, $t5, $t6, $t20, $t24 + 32: if ($t24) goto 33 else goto 57 + # live vars: $t2, $t4, $t5, $t6, $t20 + 33: label L10 + # live vars: $t2, $t4, $t5, $t6, $t20 + 34: $t29 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t6, $t20, $t29 + 35: $t28 := vector::borrow($t29, $t5) + # live vars: $t2, $t4, $t5, $t6, $t20, $t28 + 36: $t27 := move($t28) + # live vars: $t2, $t4, $t5, $t6, $t20, $t27 + 37: $t30 := read_ref($t27) + # live vars: $t2, $t4, $t5, $t6, $t20, $t30 + 38: $t31 := 1 + # live vars: $t2, $t4, $t5, $t6, $t20, $t30, $t31 + 39: $t26 := >($t30, $t31) + # live vars: $t2, $t4, $t5, $t6, $t20, $t26 + 40: if ($t26) goto 43 else goto 41 + # live vars: $t2, $t4, $t5, $t6, $t20 + 41: label L18 + # live vars: $t2, $t4, $t5, $t6, $t20 + 42: goto 51 + # live vars: $t2, $t4, $t5, $t6, $t20 + 43: label L13 + # live vars: $t2, $t4, $t5, $t6, $t20 + 44: $t32 := copy($t4) + # live vars: $t2, $t4, $t5, $t6, $t20, $t32 + 45: $t33 := copy($t20) + # live vars: $t2, $t4, $t5, $t6, $t20, $t32, $t33 + 46: vector::swap($t32, $t33, $t5) + # live vars: $t2, $t4, $t5, $t6, $t20 + 47: $t35 := move($t20) + # live vars: $t2, $t4, $t5, $t6, $t35 + 48: $t36 := 1 + # live vars: $t2, $t4, $t5, $t6, $t35, $t36 + 49: $t34 := +($t35, $t36) + # live vars: $t2, $t4, $t5, $t6, $t34 + 50: $t20 := move($t34) + # live vars: $t2, $t4, $t5, $t6, $t20 + 51: label L15 + # live vars: $t2, $t4, $t5, $t6, $t20 + 52: $t38 := move($t5) + # live vars: $t2, $t4, $t6, $t20, $t38 + 53: $t39 := 1 + # live vars: $t2, $t4, $t6, $t20, $t38, $t39 + 54: $t37 := +($t38, $t39) + # live vars: $t2, $t4, $t6, $t20, $t37 + 55: $t5 := move($t37) + # live vars: $t2, $t4, $t5, $t6, $t20 + 56: goto 29 + # live vars: $t2, $t4, $t5, $t6, $t20 + 57: label L11 + # live vars: $t2, $t4, $t20 + 58: drop($t4) + # live vars: $t2, $t20 + 59: $t3 := move($t20) + # live vars: $t2 + 60: $t41 := freeze_ref(implicit)($t2) + # live vars: $t41 + 61: $t42 := 0 + # live vars: $t41, $t42 + 62: $t40 := vector::borrow($t41, $t42) + # live vars: $t40 + 63: $t0 := read_ref($t40) + # live vars: $t0 + 64: return $t0 # live vars: $t2, $t4, $t5, $t6 - 31: label L1 + 65: label L7 # live vars: $t2, $t4, $t5, $t6 - 32: $t18 := infer($t5) - # live vars: $t2, $t4, $t5, $t6, $t18 - 33: $t20 := 1 - # live vars: $t2, $t4, $t5, $t6, $t18, $t20 - 34: $t19 := +($t5, $t20) + 66: $t18 := move($t5) + # live vars: $t2, $t4, $t6, $t18 + 67: $t19 := 1 # live vars: $t2, $t4, $t6, $t18, $t19 - 35: $t5 := infer($t19) - # live vars: $t2, $t4, $t5, $t6, $t18 - 36: label L8 - # live vars: $t2, $t4, $t5, $t6, $t18 - 37: $t21 := <($t5, $t6) - # live vars: $t2, $t4, $t5, $t6, $t18, $t21 - 38: if ($t21) goto 39 else goto 59 - # live vars: $t2, $t4, $t5, $t6, $t18 - 39: label L10 - # live vars: $t2, $t4, $t5, $t6, $t18 - 40: $t25 := freeze_ref(implicit)($t4) - # live vars: $t2, $t4, $t5, $t6, $t18, $t25 - 41: $t24 := vector::borrow($t25, $t5) - # live vars: $t2, $t4, $t5, $t6, $t18, $t24 - 42: $t23 := infer($t24) - # live vars: $t2, $t4, $t5, $t6, $t18, $t23 - 43: $t26 := read_ref($t23) - # live vars: $t2, $t4, $t5, $t6, $t18, $t26 - 44: $t27 := 1 - # live vars: $t2, $t4, $t5, $t6, $t18, $t26, $t27 - 45: $t22 := >($t26, $t27) - # live vars: $t2, $t4, $t5, $t6, $t18, $t22 - 46: if ($t22) goto 47 else goto 53 - # live vars: $t2, $t4, $t5, $t6, $t18 - 47: label L13 - # live vars: $t2, $t4, $t5, $t6, $t18 - 48: vector::swap($t4, $t18, $t5) - # live vars: $t2, $t4, $t5, $t6, $t18 - 49: $t29 := 1 - # live vars: $t2, $t4, $t5, $t6, $t18, $t29 - 50: $t28 := +($t18, $t29) - # live vars: $t2, $t4, $t5, $t6, $t28 - 51: $t18 := infer($t28) - # live vars: $t2, $t4, $t5, $t6, $t18 - 52: goto 54 - # live vars: $t2, $t4, $t5, $t6, $t18 - 53: label L14 - # live vars: $t2, $t4, $t5, $t6, $t18 - 54: label L15 - # live vars: $t2, $t4, $t5, $t6, $t18 - 55: $t31 := 1 - # live vars: $t2, $t4, $t5, $t6, $t18, $t31 - 56: $t30 := +($t5, $t31) - # live vars: $t2, $t4, $t6, $t18, $t30 - 57: $t5 := infer($t30) - # live vars: $t2, $t4, $t5, $t6, $t18 - 58: goto 61 - # live vars: $t2, $t4, $t5, $t6, $t18 - 59: label L11 - # live vars: $t2, $t18 - 60: goto 63 - # live vars: $t2, $t4, $t5, $t6, $t18 - 61: label L12 - # live vars: $t2, $t4, $t5, $t6, $t18 - 62: goto 36 - # live vars: $t2, $t18 - 63: label L9 - # live vars: $t2, $t18 - 64: $t3 := infer($t18) + 68: $t17 := +($t18, $t19) + # live vars: $t2, $t4, $t6, $t17 + 69: $t5 := move($t17) + # live vars: $t2, $t4, $t5, $t6 + 70: goto 6 +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun m::foo(): u64 { + var $t0: u64 + var $t1: vector + var $t2: &mut vector + var $t3: u64 [unused] + var $t4: &mut vector + var $t5: u64 + var $t6: u64 + var $t7: &vector + var $t8: bool + var $t9: u64 + var $t10: bool + var $t11: bool + var $t12: &u64 + var $t13: &u64 + var $t14: &vector + var $t15: u64 + var $t16: u64 + var $t17: u64 + var $t18: u64 + var $t19: u64 + var $t20: u64 + var $t21: u64 + var $t22: u64 + var $t23: u64 + var $t24: bool + var $t25: u64 + var $t26: bool + var $t27: &u64 + var $t28: &u64 + var $t29: &vector + var $t30: u64 + var $t31: u64 + var $t32: &mut vector + var $t33: u64 + var $t34: u64 + var $t35: u64 + var $t36: u64 + var $t37: u64 + var $t38: u64 + var $t39: u64 + var $t40: &u64 + var $t41: &vector + var $t42: u64 + # live vars: + 0: $t1 := ["1", "2", "3"] + # live vars: $t1 + 1: $t2 := borrow_local($t1) + # live vars: $t2 + 2: $t4 := copy($t2) + # live vars: $t2, $t4 + 3: $t5 := 0 + # live vars: $t2, $t4, $t5 + 4: $t7 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t7 + 5: $t6 := vector::length($t7) + # live vars: $t2, $t4, $t5, $t6 + 6: label L0 + # live vars: $t2, $t4, $t5, $t6 + 7: $t9 := copy($t5) + # live vars: $t2, $t4, $t5, $t6, $t9 + 8: $t8 := <($t9, $t6) + # live vars: $t2, $t4, $t5, $t6, $t8 + 9: if ($t8) goto 12 else goto 10 + # live vars: $t2, $t4, $t5, $t6 + 10: label L16 + # live vars: $t2, $t4, $t5, $t6 + 11: goto 23 + # live vars: $t2, $t4, $t5, $t6 + 12: label L2 + # live vars: $t2, $t4, $t5, $t6 + 13: $t14 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t6, $t14 + 14: $t13 := vector::borrow($t14, $t5) + # live vars: $t2, $t4, $t5, $t6, $t13 + 15: $t12 := move($t13) + # live vars: $t2, $t4, $t5, $t6, $t12 + 16: $t15 := read_ref($t12) + # live vars: $t2, $t4, $t5, $t6, $t15 + 17: $t16 := 1 + # live vars: $t2, $t4, $t5, $t6, $t15, $t16 + 18: $t11 := >($t15, $t16) + # live vars: $t2, $t4, $t5, $t6, $t11 + 19: $t10 := !($t11) + # live vars: $t2, $t4, $t5, $t6, $t10 + 20: if ($t10) goto 21 else goto 64 + # live vars: $t2, $t4, $t5, $t6 + 21: label L17 + # live vars: $t2, $t4, $t5, $t6 + 22: goto 23 + # live vars: $t2, $t4, $t5, $t6 + 23: label L1 + # live vars: $t2, $t4, $t5, $t6 + 24: $t20 := copy($t5) + # live vars: $t2, $t4, $t5, $t6, $t20 + 25: $t22 := move($t5) + # live vars: $t2, $t4, $t6, $t20, $t22 + 26: $t23 := 1 + # live vars: $t2, $t4, $t6, $t20, $t22, $t23 + 27: $t21 := +($t22, $t23) + # live vars: $t2, $t4, $t6, $t20, $t21 + 28: $t5 := move($t21) + # live vars: $t2, $t4, $t5, $t6, $t20 + 29: label L8 + # live vars: $t2, $t4, $t5, $t6, $t20 + 30: $t25 := copy($t5) + # live vars: $t2, $t4, $t5, $t6, $t20, $t25 + 31: $t24 := <($t25, $t6) + # live vars: $t2, $t4, $t5, $t6, $t20, $t24 + 32: if ($t24) goto 33 else goto 57 + # live vars: $t2, $t4, $t5, $t6, $t20 + 33: label L10 + # live vars: $t2, $t4, $t5, $t6, $t20 + 34: $t29 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t6, $t20, $t29 + 35: $t28 := vector::borrow($t29, $t5) + # live vars: $t2, $t4, $t5, $t6, $t20, $t28 + 36: $t27 := move($t28) + # live vars: $t2, $t4, $t5, $t6, $t20, $t27 + 37: $t30 := read_ref($t27) + # live vars: $t2, $t4, $t5, $t6, $t20, $t30 + 38: $t31 := 1 + # live vars: $t2, $t4, $t5, $t6, $t20, $t30, $t31 + 39: $t26 := >($t30, $t31) + # live vars: $t2, $t4, $t5, $t6, $t20, $t26 + 40: if ($t26) goto 43 else goto 41 + # live vars: $t2, $t4, $t5, $t6, $t20 + 41: label L18 + # live vars: $t2, $t4, $t5, $t6, $t20 + 42: goto 51 + # live vars: $t2, $t4, $t5, $t6, $t20 + 43: label L13 + # live vars: $t2, $t4, $t5, $t6, $t20 + 44: $t32 := copy($t4) + # live vars: $t2, $t4, $t5, $t6, $t20, $t32 + 45: $t33 := copy($t20) + # live vars: $t2, $t4, $t5, $t6, $t20, $t32, $t33 + 46: vector::swap($t32, $t33, $t5) + # live vars: $t2, $t4, $t5, $t6, $t20 + 47: $t35 := move($t20) + # live vars: $t2, $t4, $t5, $t6, $t35 + 48: $t36 := 1 + # live vars: $t2, $t4, $t5, $t6, $t35, $t36 + 49: $t34 := +($t35, $t36) + # live vars: $t2, $t4, $t5, $t6, $t34 + 50: $t20 := move($t34) + # live vars: $t2, $t4, $t5, $t6, $t20 + 51: label L15 + # live vars: $t2, $t4, $t5, $t6, $t20 + 52: $t38 := move($t5) + # live vars: $t2, $t4, $t6, $t20, $t38 + 53: $t39 := 1 + # live vars: $t2, $t4, $t6, $t20, $t38, $t39 + 54: $t37 := +($t38, $t39) + # live vars: $t2, $t4, $t6, $t20, $t37 + 55: $t5 := move($t37) + # live vars: $t2, $t4, $t5, $t6, $t20 + 56: goto 29 + # live vars: $t2, $t4, $t5, $t6, $t20 + 57: label L11 + # live vars: $t2, $t4 + 58: drop($t4) # live vars: $t2 - 65: $t33 := freeze_ref(implicit)($t2) - # live vars: $t33 - 66: $t34 := 0 - # live vars: $t33, $t34 - 67: $t32 := vector::borrow($t33, $t34) - # live vars: $t32 - 68: $t0 := read_ref($t32) + 59: $t41 := freeze_ref(implicit)($t2) + # live vars: $t41 + 60: $t42 := 0 + # live vars: $t41, $t42 + 61: $t40 := vector::borrow($t41, $t42) + # live vars: $t40 + 62: $t0 := read_ref($t40) # live vars: $t0 - 69: return $t0 + 63: return $t0 + # live vars: $t2, $t4, $t5, $t6 + 64: label L7 + # live vars: $t2, $t4, $t5, $t6 + 65: $t18 := move($t5) + # live vars: $t2, $t4, $t6, $t18 + 66: $t19 := 1 + # live vars: $t2, $t4, $t6, $t18, $t19 + 67: $t17 := +($t18, $t19) + # live vars: $t2, $t4, $t6, $t17 + 68: $t5 := move($t17) + # live vars: $t2, $t4, $t5, $t6 + 69: goto 6 +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun m::foo(): u64 { + var $t0: u64 [unused] + var $t1: vector + var $t2: &mut vector + var $t3: u64 [unused] + var $t4: &mut vector + var $t5: u64 + var $t6: u64 + var $t7: &vector + var $t8: bool + var $t9: u64 + var $t10: bool [unused] + var $t11: bool [unused] + var $t12: &u64 [unused] + var $t13: &u64 + var $t14: &vector [unused] + var $t15: u64 [unused] + var $t16: u64 + var $t17: u64 [unused] + var $t18: u64 [unused] + var $t19: u64 [unused] + var $t20: u64 [unused] + var $t21: u64 [unused] + var $t22: u64 [unused] + var $t23: u64 + var $t24: bool [unused] + var $t25: u64 [unused] + var $t26: bool [unused] + var $t27: &u64 [unused] + var $t28: &u64 [unused] + var $t29: &vector [unused] + var $t30: u64 [unused] + var $t31: u64 [unused] + var $t32: &mut vector + var $t33: u64 [unused] + var $t34: u64 [unused] + var $t35: u64 [unused] + var $t36: u64 [unused] + var $t37: u64 [unused] + var $t38: u64 [unused] + var $t39: u64 [unused] + var $t40: &u64 [unused] + var $t41: &vector [unused] + var $t42: u64 [unused] + # live vars: + 0: $t1 := ["1", "2", "3"] + # live vars: $t1 + 1: $t2 := borrow_local($t1) + # live vars: $t2 + 2: $t4 := copy($t2) + # live vars: $t2, $t4 + 3: $t5 := 0 + # live vars: $t2, $t4, $t5 + 4: $t7 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t7 + 5: $t6 := vector::length($t7) + # live vars: $t2, $t4, $t5, $t6 + 6: label L0 + # live vars: $t2, $t4, $t5, $t6 + 7: $t9 := copy($t5) + # live vars: $t2, $t4, $t5, $t6, $t9 + 8: $t8 := <($t9, $t6) + # live vars: $t2, $t4, $t5, $t6, $t8 + 9: if ($t8) goto 12 else goto 10 + # live vars: $t2, $t4, $t5, $t6 + 10: label L16 + # live vars: $t2, $t4, $t5, $t6 + 11: goto 23 + # live vars: $t2, $t4, $t5, $t6 + 12: label L2 + # live vars: $t2, $t4, $t5, $t6 + 13: $t7 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t6, $t7 + 14: $t13 := vector::borrow($t7, $t5) + # live vars: $t2, $t4, $t5, $t6, $t13 + 15: $t13 := move($t13) + # live vars: $t2, $t4, $t5, $t6, $t13 + 16: $t9 := read_ref($t13) + # live vars: $t2, $t4, $t5, $t6, $t9 + 17: $t16 := 1 + # live vars: $t2, $t4, $t5, $t6, $t9, $t16 + 18: $t8 := >($t9, $t16) + # live vars: $t2, $t4, $t5, $t6, $t8 + 19: $t8 := !($t8) + # live vars: $t2, $t4, $t5, $t6, $t8 + 20: if ($t8) goto 21 else goto 64 + # live vars: $t2, $t4, $t5, $t6 + 21: label L17 + # live vars: $t2, $t4, $t5, $t6 + 22: goto 23 + # live vars: $t2, $t4, $t5, $t6 + 23: label L1 + # live vars: $t2, $t4, $t5, $t6 + 24: $t9 := copy($t5) + # live vars: $t2, $t4, $t5, $t6, $t9 + 25: $t16 := move($t5) + # live vars: $t2, $t4, $t6, $t9, $t16 + 26: $t23 := 1 + # live vars: $t2, $t4, $t6, $t9, $t16, $t23 + 27: $t16 := +($t16, $t23) + # live vars: $t2, $t4, $t6, $t9, $t16 + 28: $t5 := move($t16) + # live vars: $t2, $t4, $t5, $t6, $t9 + 29: label L8 + # live vars: $t2, $t4, $t5, $t6, $t9 + 30: $t16 := copy($t5) + # live vars: $t2, $t4, $t5, $t6, $t9, $t16 + 31: $t8 := <($t16, $t6) + # live vars: $t2, $t4, $t5, $t6, $t8, $t9 + 32: if ($t8) goto 33 else goto 57 + # live vars: $t2, $t4, $t5, $t6, $t9 + 33: label L10 + # live vars: $t2, $t4, $t5, $t6, $t9 + 34: $t7 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t6, $t7, $t9 + 35: $t13 := vector::borrow($t7, $t5) + # live vars: $t2, $t4, $t5, $t6, $t9, $t13 + 36: $t13 := move($t13) + # live vars: $t2, $t4, $t5, $t6, $t9, $t13 + 37: $t16 := read_ref($t13) + # live vars: $t2, $t4, $t5, $t6, $t9, $t16 + 38: $t23 := 1 + # live vars: $t2, $t4, $t5, $t6, $t9, $t16, $t23 + 39: $t8 := >($t16, $t23) + # live vars: $t2, $t4, $t5, $t6, $t8, $t9 + 40: if ($t8) goto 43 else goto 41 + # live vars: $t2, $t4, $t5, $t6, $t9 + 41: label L18 + # live vars: $t2, $t4, $t5, $t6, $t9 + 42: goto 51 + # live vars: $t2, $t4, $t5, $t6, $t9 + 43: label L13 + # live vars: $t2, $t4, $t5, $t6, $t9 + 44: $t32 := copy($t4) + # live vars: $t2, $t4, $t5, $t6, $t9, $t32 + 45: $t16 := copy($t9) + # live vars: $t2, $t4, $t5, $t6, $t9, $t16, $t32 + 46: vector::swap($t32, $t16, $t5) + # live vars: $t2, $t4, $t5, $t6, $t9 + 47: $t16 := move($t9) + # live vars: $t2, $t4, $t5, $t6, $t16 + 48: $t23 := 1 + # live vars: $t2, $t4, $t5, $t6, $t16, $t23 + 49: $t16 := +($t16, $t23) + # live vars: $t2, $t4, $t5, $t6, $t16 + 50: $t9 := move($t16) + # live vars: $t2, $t4, $t5, $t6, $t9 + 51: label L15 + # live vars: $t2, $t4, $t5, $t6, $t9 + 52: $t16 := move($t5) + # live vars: $t2, $t4, $t6, $t9, $t16 + 53: $t23 := 1 + # live vars: $t2, $t4, $t6, $t9, $t16, $t23 + 54: $t16 := +($t16, $t23) + # live vars: $t2, $t4, $t6, $t9, $t16 + 55: $t5 := move($t16) + # live vars: $t2, $t4, $t5, $t6, $t9 + 56: goto 29 + # live vars: $t2, $t4, $t5, $t6, $t9 + 57: label L11 + # live vars: $t2, $t4 + 58: drop($t4) + # live vars: $t2 + 59: $t7 := freeze_ref(implicit)($t2) + # live vars: $t7 + 60: $t9 := 0 + # live vars: $t7, $t9 + 61: $t13 := vector::borrow($t7, $t9) + # live vars: $t13 + 62: $t9 := read_ref($t13) + # live vars: $t9 + 63: return $t9 + # live vars: $t2, $t4, $t5, $t6 + 64: label L7 + # live vars: $t2, $t4, $t5, $t6 + 65: $t9 := move($t5) + # live vars: $t2, $t4, $t6, $t9 + 66: $t16 := 1 + # live vars: $t2, $t4, $t6, $t9, $t16 + 67: $t9 := +($t9, $t16) + # live vars: $t2, $t4, $t6, $t9 + 68: $t5 := move($t9) + # live vars: $t2, $t4, $t5, $t6 + 69: goto 6 +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun m::foo(): u64 { + var $t0: u64 [unused] + var $t1: vector + var $t2: &mut vector + var $t3: u64 [unused] + var $t4: &mut vector + var $t5: u64 + var $t6: u64 + var $t7: &vector + var $t8: bool + var $t9: u64 + var $t10: bool [unused] + var $t11: bool [unused] + var $t12: &u64 [unused] + var $t13: &u64 + var $t14: &vector [unused] + var $t15: u64 [unused] + var $t16: u64 + var $t17: u64 [unused] + var $t18: u64 [unused] + var $t19: u64 [unused] + var $t20: u64 [unused] + var $t21: u64 [unused] + var $t22: u64 [unused] + var $t23: u64 + var $t24: bool [unused] + var $t25: u64 [unused] + var $t26: bool [unused] + var $t27: &u64 [unused] + var $t28: &u64 [unused] + var $t29: &vector [unused] + var $t30: u64 [unused] + var $t31: u64 [unused] + var $t32: &mut vector + var $t33: u64 [unused] + var $t34: u64 [unused] + var $t35: u64 [unused] + var $t36: u64 [unused] + var $t37: u64 [unused] + var $t38: u64 [unused] + var $t39: u64 [unused] + var $t40: &u64 [unused] + var $t41: &vector [unused] + var $t42: u64 [unused] + # live vars: + 0: $t1 := ["1", "2", "3"] + # live vars: $t1 + 1: $t2 := borrow_local($t1) + # live vars: $t2 + 2: $t4 := copy($t2) + # live vars: $t2, $t4 + 3: $t5 := 0 + # live vars: $t2, $t4, $t5 + 4: $t7 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t7 + 5: $t6 := vector::length($t7) + # live vars: $t2, $t4, $t5, $t6 + 6: label L0 + # live vars: $t2, $t4, $t5, $t6 + 7: $t9 := copy($t5) + # live vars: $t2, $t4, $t5, $t6, $t9 + 8: $t8 := <($t9, $t6) + # live vars: $t2, $t4, $t5, $t6, $t8 + 9: if ($t8) goto 12 else goto 10 + # live vars: $t2, $t4, $t5, $t6 + 10: label L16 + # live vars: $t2, $t4, $t5, $t6 + 11: goto 22 + # live vars: $t2, $t4, $t5, $t6 + 12: label L2 + # live vars: $t2, $t4, $t5, $t6 + 13: $t7 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t6, $t7 + 14: $t13 := vector::borrow($t7, $t5) + # live vars: $t2, $t4, $t5, $t6, $t13 + 15: $t9 := read_ref($t13) + # live vars: $t2, $t4, $t5, $t6, $t9 + 16: $t16 := 1 + # live vars: $t2, $t4, $t5, $t6, $t9, $t16 + 17: $t8 := >($t9, $t16) + # live vars: $t2, $t4, $t5, $t6, $t8 + 18: $t8 := !($t8) + # live vars: $t2, $t4, $t5, $t6, $t8 + 19: if ($t8) goto 20 else goto 62 + # live vars: $t2, $t4, $t5, $t6 + 20: label L17 + # live vars: $t2, $t4, $t5, $t6 + 21: goto 22 + # live vars: $t2, $t4, $t5, $t6 + 22: label L1 + # live vars: $t2, $t4, $t5, $t6 + 23: $t9 := copy($t5) + # live vars: $t2, $t4, $t5, $t6, $t9 + 24: $t16 := move($t5) + # live vars: $t2, $t4, $t6, $t9, $t16 + 25: $t23 := 1 + # live vars: $t2, $t4, $t6, $t9, $t16, $t23 + 26: $t16 := +($t16, $t23) + # live vars: $t2, $t4, $t6, $t9, $t16 + 27: $t5 := move($t16) + # live vars: $t2, $t4, $t5, $t6, $t9 + 28: label L8 + # live vars: $t2, $t4, $t5, $t6, $t9 + 29: $t16 := copy($t5) + # live vars: $t2, $t4, $t5, $t6, $t9, $t16 + 30: $t8 := <($t16, $t6) + # live vars: $t2, $t4, $t5, $t6, $t8, $t9 + 31: if ($t8) goto 32 else goto 55 + # live vars: $t2, $t4, $t5, $t6, $t9 + 32: label L10 + # live vars: $t2, $t4, $t5, $t6, $t9 + 33: $t7 := freeze_ref(implicit)($t4) + # live vars: $t2, $t4, $t5, $t6, $t7, $t9 + 34: $t13 := vector::borrow($t7, $t5) + # live vars: $t2, $t4, $t5, $t6, $t9, $t13 + 35: $t16 := read_ref($t13) + # live vars: $t2, $t4, $t5, $t6, $t9, $t16 + 36: $t23 := 1 + # live vars: $t2, $t4, $t5, $t6, $t9, $t16, $t23 + 37: $t8 := >($t16, $t23) + # live vars: $t2, $t4, $t5, $t6, $t8, $t9 + 38: if ($t8) goto 41 else goto 39 + # live vars: $t2, $t4, $t5, $t6, $t9 + 39: label L18 + # live vars: $t2, $t4, $t5, $t6, $t9 + 40: goto 49 + # live vars: $t2, $t4, $t5, $t6, $t9 + 41: label L13 + # live vars: $t2, $t4, $t5, $t6, $t9 + 42: $t32 := copy($t4) + # live vars: $t2, $t4, $t5, $t6, $t9, $t32 + 43: $t16 := copy($t9) + # live vars: $t2, $t4, $t5, $t6, $t9, $t16, $t32 + 44: vector::swap($t32, $t16, $t5) + # live vars: $t2, $t4, $t5, $t6, $t9 + 45: $t16 := move($t9) + # live vars: $t2, $t4, $t5, $t6, $t16 + 46: $t23 := 1 + # live vars: $t2, $t4, $t5, $t6, $t16, $t23 + 47: $t16 := +($t16, $t23) + # live vars: $t2, $t4, $t5, $t6, $t16 + 48: $t9 := move($t16) + # live vars: $t2, $t4, $t5, $t6, $t9 + 49: label L15 + # live vars: $t2, $t4, $t5, $t6, $t9 + 50: $t16 := move($t5) + # live vars: $t2, $t4, $t6, $t9, $t16 + 51: $t23 := 1 + # live vars: $t2, $t4, $t6, $t9, $t16, $t23 + 52: $t16 := +($t16, $t23) + # live vars: $t2, $t4, $t6, $t9, $t16 + 53: $t5 := move($t16) + # live vars: $t2, $t4, $t5, $t6, $t9 + 54: goto 28 + # live vars: $t2, $t4, $t5, $t6, $t9 + 55: label L11 + # live vars: $t2, $t4 + 56: drop($t4) + # live vars: $t2 + 57: $t7 := freeze_ref(implicit)($t2) + # live vars: $t7 + 58: $t9 := 0 + # live vars: $t7, $t9 + 59: $t13 := vector::borrow($t7, $t9) + # live vars: $t13 + 60: $t9 := read_ref($t13) + # live vars: $t9 + 61: return $t9 + # live vars: $t2, $t4, $t5, $t6 + 62: label L7 + # live vars: $t2, $t4, $t5, $t6 + 63: $t9 := move($t5) + # live vars: $t2, $t4, $t6, $t9 + 64: $t16 := 1 + # live vars: $t2, $t4, $t6, $t9, $t16 + 65: $t9 := +($t9, $t16) + # live vars: $t2, $t4, $t6, $t9 + 66: $t5 := move($t9) + # live vars: $t2, $t4, $t5, $t6 + 67: goto 6 +} + + +============ disassembled file-format ================== +// Move bytecode v7 +module 42.m { + + +foo(): u64 /* def_idx: 0 */ { +L0: loc0: vector +L1: loc1: &mut vector +L2: loc2: &mut vector +L3: loc3: u64 +L4: loc4: u64 +L5: loc5: u64 +B0: + 0: LdConst[0](Vector(U64): [3, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0]) + 1: StLoc[0](loc0: vector) + 2: MutBorrowLoc[0](loc0: vector) + 3: StLoc[1](loc1: &mut vector) + 4: CopyLoc[1](loc1: &mut vector) + 5: StLoc[2](loc2: &mut vector) + 6: LdU64(0) + 7: StLoc[3](loc3: u64) + 8: CopyLoc[2](loc2: &mut vector) + 9: FreezeRef + 10: VecLen(1) + 11: StLoc[4](loc4: u64) +B1: + 12: CopyLoc[3](loc3: u64) + 13: CopyLoc[4](loc4: u64) + 14: Lt + 15: BrTrue(17) +B2: + 16: Branch(26) +B3: + 17: CopyLoc[2](loc2: &mut vector) + 18: FreezeRef + 19: CopyLoc[3](loc3: u64) + 20: VecImmBorrow(1) + 21: ReadRef + 22: LdU64(1) + 23: Gt + 24: BrTrue(66) +B4: + 25: Branch(26) +B5: + 26: CopyLoc[3](loc3: u64) + 27: StLoc[5](loc5: u64) + 28: MoveLoc[3](loc3: u64) + 29: LdU64(1) + 30: Add + 31: StLoc[3](loc3: u64) +B6: + 32: CopyLoc[3](loc3: u64) + 33: CopyLoc[4](loc4: u64) + 34: Lt + 35: BrFalse(58) +B7: + 36: CopyLoc[2](loc2: &mut vector) + 37: FreezeRef + 38: CopyLoc[3](loc3: u64) + 39: VecImmBorrow(1) + 40: ReadRef + 41: LdU64(1) + 42: Gt + 43: BrTrue(45) +B8: + 44: Branch(53) +B9: + 45: CopyLoc[2](loc2: &mut vector) + 46: CopyLoc[5](loc5: u64) + 47: CopyLoc[3](loc3: u64) + 48: VecSwap(1) + 49: MoveLoc[5](loc5: u64) + 50: LdU64(1) + 51: Add + 52: StLoc[5](loc5: u64) +B10: + 53: MoveLoc[3](loc3: u64) + 54: LdU64(1) + 55: Add + 56: StLoc[3](loc3: u64) + 57: Branch(32) +B11: + 58: MoveLoc[2](loc2: &mut vector) + 59: Pop + 60: MoveLoc[1](loc1: &mut vector) + 61: FreezeRef + 62: LdU64(0) + 63: VecImmBorrow(1) + 64: ReadRef + 65: Ret +B12: + 66: MoveLoc[3](loc3: u64) + 67: LdU64(1) + 68: Add + 69: StLoc[3](loc3: u64) + 70: Branch(12) +} } +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/live-var/mut_ref.exp b/third_party/move/move-compiler-v2/tests/live-var/mut_ref.exp index b2dabe6d743a4..e97e63f51a045 100644 --- a/third_party/move/move-compiler-v2/tests/live-var/mut_ref.exp +++ b/third_party/move/move-compiler-v2/tests/live-var/mut_ref.exp @@ -51,11 +51,177 @@ fun m::f2_fail() { var $t0: 0x42::m::R var $t1: u64 var $t2: &mut 0x42::m::R + var $t3: &mut 0x42::m::R + 0: $t1 := 0 + 1: $t0 := pack 0x42::m::R($t1) + 2: $t2 := borrow_local($t0) + 3: $t3 := infer($t2) + 4: m::some2($t3, $t2) + 5: return () +} + + +[variant baseline] +fun m::f3_ok() { + var $t0: 0x42::m::R + var $t1: u64 + var $t2: &mut 0x42::m::R + var $t3: &mut 0x42::m::R + 0: $t1 := 0 + 1: $t0 := pack 0x42::m::R($t1) + 2: $t2 := borrow_local($t0) + 3: m::some($t2) + 4: $t3 := borrow_local($t0) + 5: $t2 := infer($t3) + 6: m::some($t2) + 7: return () +} + + +[variant baseline] +fun m::f4_ok() { + var $t0: 0x42::m::R + var $t1: u64 + var $t2: &mut 0x42::m::R + var $t3: &mut 0x42::m::R + 0: $t1 := 0 + 1: $t0 := pack 0x42::m::R($t1) + 2: $t2 := borrow_local($t0) + 3: $t3 := m::id($t2) + 4: $t2 := infer($t3) + 5: m::some($t2) + 6: return () +} + + +[variant baseline] +fun m::f5_fail($t0: bool) { + var $t1: 0x42::m::R + var $t2: u64 + var $t3: &mut 0x42::m::R + var $t4: &mut 0x42::m::R + 0: $t2 := 0 + 1: $t1 := pack 0x42::m::R($t2) + 2: $t3 := borrow_local($t1) + 3: $t4 := infer($t3) + 4: if ($t0) goto 5 else goto 9 + 5: label L0 + 6: m::some($t3) + 7: m::some($t4) + 8: goto 12 + 9: label L1 + 10: m::some($t4) + 11: m::some($t3) + 12: label L2 + 13: return () +} + + +[variant baseline] +fun m::id($t0: &mut 0x42::m::R): &mut 0x42::m::R { + var $t1: &mut 0x42::m::R + 0: $t1 := infer($t0) + 1: return $t1 +} + + +[variant baseline] +fun m::some($t0: &mut 0x42::m::R) { + 0: return () +} + + +[variant baseline] +fun m::some2($t0: &mut 0x42::m::R, $t1: &mut 0x42::m::R) { + 0: return () +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun m::f1_ok() { + var $t0: 0x42::m::R + var $t1: u64 + var $t2: &mut 0x42::m::R + # live vars: + 0: $t1 := 0 + # live vars: $t1 + 1: $t0 := pack 0x42::m::R($t1) + # live vars: $t0 + 2: $t2 := borrow_local($t0) + # live vars: $t2 + 3: m::some($t2) + # live vars: $t2 + 4: m::some($t2) + # live vars: + 5: return () +} + + +[variant baseline] +fun m::f1a_ok() { + var $t0: 0x42::m::R + var $t1: u64 + var $t2: &mut 0x42::m::R + var $t3: 0x42::m::R + # live vars: + 0: $t1 := 0 + # live vars: $t1 + 1: $t0 := pack 0x42::m::R($t1) + # live vars: $t0 + 2: $t2 := borrow_local($t0) + # live vars: $t2 + 3: $t3 := read_ref($t2) + # live vars: $t2 + 4: m::some($t2) + # live vars: $t2 + 5: m::some($t2) + # live vars: + 6: return () +} + + +[variant baseline] +fun m::f1b_ok() { + var $t0: 0x42::m::R + var $t1: u64 + var $t2: &mut 0x42::m::R + var $t3: 0x42::m::R + # live vars: + 0: $t1 := 0 + # live vars: $t1 + 1: $t0 := pack 0x42::m::R($t1) + # live vars: $t0 + 2: $t2 := borrow_local($t0) + # live vars: $t2 + 3: m::some($t2) + # live vars: $t2 + 4: $t3 := read_ref($t2) + # live vars: $t2 + 5: m::some($t2) + # live vars: + 6: return () +} + + +[variant baseline] +fun m::f2_fail() { + var $t0: 0x42::m::R + var $t1: u64 + var $t2: &mut 0x42::m::R + var $t3: &mut 0x42::m::R + # live vars: 0: $t1 := 0 + # live vars: $t1 1: $t0 := pack 0x42::m::R($t1) + # live vars: $t0 2: $t2 := borrow_local($t0) - 3: m::some2($t2, $t2) - 4: return () + # live vars: $t2 + 3: $t3 := infer($t2) + # live vars: $t2, $t3 + 4: m::some2($t3, $t2) + # live vars: + 5: return () } @@ -65,13 +231,21 @@ fun m::f3_ok() { var $t1: u64 var $t2: &mut 0x42::m::R var $t3: &mut 0x42::m::R + # live vars: 0: $t1 := 0 + # live vars: $t1 1: $t0 := pack 0x42::m::R($t1) + # live vars: $t0 2: $t2 := borrow_local($t0) + # live vars: $t0, $t2 3: m::some($t2) + # live vars: $t0 4: $t3 := borrow_local($t0) + # live vars: $t3 5: $t2 := infer($t3) + # live vars: $t2 6: m::some($t2) + # live vars: 7: return () } @@ -82,12 +256,19 @@ fun m::f4_ok() { var $t1: u64 var $t2: &mut 0x42::m::R var $t3: &mut 0x42::m::R + # live vars: 0: $t1 := 0 + # live vars: $t1 1: $t0 := pack 0x42::m::R($t1) + # live vars: $t0 2: $t2 := borrow_local($t0) + # live vars: $t2 3: $t3 := m::id($t2) + # live vars: $t3 4: $t2 := infer($t3) + # live vars: $t2 5: m::some($t2) + # live vars: 6: return () } @@ -98,19 +279,33 @@ fun m::f5_fail($t0: bool) { var $t2: u64 var $t3: &mut 0x42::m::R var $t4: &mut 0x42::m::R + # live vars: $t0 0: $t2 := 0 + # live vars: $t0, $t2 1: $t1 := pack 0x42::m::R($t2) + # live vars: $t0, $t1 2: $t3 := borrow_local($t1) + # live vars: $t0, $t3 3: $t4 := infer($t3) + # live vars: $t0, $t3, $t4 4: if ($t0) goto 5 else goto 9 + # live vars: $t3, $t4 5: label L0 + # live vars: $t3, $t4 6: m::some($t3) + # live vars: $t4 7: m::some($t4) + # live vars: 8: goto 12 + # live vars: $t3, $t4 9: label L1 + # live vars: $t3, $t4 10: m::some($t4) + # live vars: $t3 11: m::some($t3) + # live vars: 12: label L2 + # live vars: 13: return () } @@ -118,19 +313,23 @@ fun m::f5_fail($t0: bool) { [variant baseline] fun m::id($t0: &mut 0x42::m::R): &mut 0x42::m::R { var $t1: &mut 0x42::m::R + # live vars: $t0 0: $t1 := infer($t0) + # live vars: $t1 1: return $t1 } [variant baseline] fun m::some($t0: &mut 0x42::m::R) { + # live vars: $t0 0: return () } [variant baseline] fun m::some2($t0: &mut 0x42::m::R, $t1: &mut 0x42::m::R) { + # live vars: $t0, $t1 0: return () } @@ -207,6 +406,7 @@ fun m::f2_fail() { var $t0: 0x42::m::R var $t1: u64 var $t2: &mut 0x42::m::R + var $t3: &mut 0x42::m::R # live vars: 0: $t1 := 0 # live vars: $t1 @@ -214,9 +414,11 @@ fun m::f2_fail() { # live vars: $t0 2: $t2 := borrow_local($t0) # live vars: $t2 - 3: m::some2($t2, $t2) + 3: $t3 := infer($t2) + # live vars: $t2, $t3 + 4: m::some2($t3, $t2) # live vars: - 4: return () + 5: return () } @@ -327,3 +529,25 @@ fun m::some2($t0: &mut 0x42::m::R, $t1: &mut 0x42::m::R) { # live vars: $t0, $t1 0: return () } + + +Diagnostics: +error: cannot transfer mutable local `x` since it is borrowed + ┌─ tests/live-var/mut_ref.move:41:9 + │ +41 │ some2(x, x); // expected error because multiple use + │ ^^^^^^^^^^^ + │ │ │ + │ │ previously mutably borrowed here + │ transfer attempted here + +error: cannot transfer mutable local `x` since it is borrowed + ┌─ tests/live-var/mut_ref.move:64:13 + │ +62 │ let y = x; // expected error because of implicit copy + │ - previously mutably borrowed here +63 │ if (cond) { +64 │ some(x); + │ ^^^^^^^ transfer attempted here +65 │ some(y) + │ ------- conflicting reference `y` used here diff --git a/third_party/move/move-compiler-v2/tests/more-v1/liveness/mut_ref.exp b/third_party/move/move-compiler-v2/tests/more-v1/liveness/mut_ref.exp index c4ecdd80bca73..56becb529d04b 100644 --- a/third_party/move/move-compiler-v2/tests/more-v1/liveness/mut_ref.exp +++ b/third_party/move/move-compiler-v2/tests/more-v1/liveness/mut_ref.exp @@ -5,9 +5,9 @@ error: cannot transfer mutable local `x` since it is borrowed │ 41 │ some2(x, x); // expected error because multiple use │ ^^^^^^^^^^^ - │ │ + │ │ │ + │ │ previously mutably borrowed here │ transfer attempted here - │ previously mutably borrowed here error: cannot transfer mutable local `x` since it is borrowed ┌─ tests/more-v1/liveness/mut_ref.move:64:13 diff --git a/third_party/move/move-compiler-v2/tests/more-v1/locals/use_after_move_if.exp b/third_party/move/move-compiler-v2/tests/more-v1/locals/use_after_move_if.exp index e99dac5a1a2b9..a98b47563fdad 100644 --- a/third_party/move/move-compiler-v2/tests/more-v1/locals/use_after_move_if.exp +++ b/third_party/move/move-compiler-v2/tests/more-v1/locals/use_after_move_if.exp @@ -14,7 +14,7 @@ error: cannot move local `x` since it is still in use 10 │ if (cond) { _ = move x }; │ ^^^^^^ attempted to move here 11 │ let _ = x + 1; - │ ----- used here + │ - used here error: cannot move local `x` since it is still in use ┌─ tests/more-v1/locals/use_after_move_if.move:16:25 diff --git a/third_party/move/move-compiler-v2/tests/more-v1/locals/use_after_move_if_else.exp b/third_party/move/move-compiler-v2/tests/more-v1/locals/use_after_move_if_else.exp index 6d3f341daa7d9..21d402916e2bd 100644 --- a/third_party/move/move-compiler-v2/tests/more-v1/locals/use_after_move_if_else.exp +++ b/third_party/move/move-compiler-v2/tests/more-v1/locals/use_after_move_if_else.exp @@ -30,7 +30,7 @@ error: cannot move local `x` since it is still in use 16 │ if (cond) { _ = move x } else { _ = move x }; │ ^^^^^^ attempted to move here 17 │ let _ = x + 1; - │ ----- used here + │ - used here error: cannot move local `x` since it is still in use ┌─ tests/more-v1/locals/use_after_move_if_else.move:16:45 @@ -38,7 +38,7 @@ error: cannot move local `x` since it is still in use 16 │ if (cond) { _ = move x } else { _ = move x }; │ ^^^^^^ attempted to move here 17 │ let _ = x + 1; - │ ----- used here + │ - used here error: cannot move local `x` since it is still in use ┌─ tests/more-v1/locals/use_after_move_if_else.move:23:25 @@ -46,7 +46,7 @@ error: cannot move local `x` since it is still in use 23 │ if (cond) { _ = move x } else { _ = x }; │ ^^^^^^ attempted to move here 24 │ let _ = x + 1; - │ ----- used here + │ - used here error: cannot move local `x` since it is still in use ┌─ tests/more-v1/locals/use_after_move_if_else.move:29:25 diff --git a/third_party/move/move-compiler-v2/tests/more-v1/locals/use_after_move_simple.exp b/third_party/move/move-compiler-v2/tests/more-v1/locals/use_after_move_simple.exp index 696c6dd3054de..47b693faaaa49 100644 --- a/third_party/move/move-compiler-v2/tests/more-v1/locals/use_after_move_simple.exp +++ b/third_party/move/move-compiler-v2/tests/more-v1/locals/use_after_move_simple.exp @@ -14,7 +14,7 @@ error: cannot move local `x` since it is still in use 16 │ move x; │ ^^^^^^ attempted to move here 17 │ let _ = x + 1; - │ ----- used here + │ - used here error: cannot move local `x` since it is still in use ┌─ tests/more-v1/locals/use_after_move_simple.move:26:9 diff --git a/third_party/move/move-compiler-v2/tests/more-v1/translated_ir_tests/move/commands/branch_assigns_then_moves.exp b/third_party/move/move-compiler-v2/tests/more-v1/translated_ir_tests/move/commands/branch_assigns_then_moves.exp index 4362ea3b66639..f0ef889fadf51 100644 --- a/third_party/move/move-compiler-v2/tests/more-v1/translated_ir_tests/move/commands/branch_assigns_then_moves.exp +++ b/third_party/move/move-compiler-v2/tests/more-v1/translated_ir_tests/move/commands/branch_assigns_then_moves.exp @@ -7,4 +7,4 @@ error: cannot move local `x` since it is still in use │ ^^^^^^ attempted to move here · 12 │ assert!(x == 5, 42); - │ ------ used here + │ - used here diff --git a/third_party/move/move-compiler-v2/tests/more-v1/translated_ir_tests/move/commands/else_moves_if_doesnt.exp b/third_party/move/move-compiler-v2/tests/more-v1/translated_ir_tests/move/commands/else_moves_if_doesnt.exp index c598f2de532cf..592859bd15e0e 100644 --- a/third_party/move/move-compiler-v2/tests/more-v1/translated_ir_tests/move/commands/else_moves_if_doesnt.exp +++ b/third_party/move/move-compiler-v2/tests/more-v1/translated_ir_tests/move/commands/else_moves_if_doesnt.exp @@ -6,4 +6,4 @@ error: cannot move local `x` since it is still in use 4 │ let y = if (true) 0 else move x; y; │ ^^^^^^ attempted to move here 5 │ assert!(x == 0, 42); - │ ------ used here + │ - used here diff --git a/third_party/move/move-compiler-v2/tests/more-v1/translated_ir_tests/move/commands/if_moves_else_doesnt.exp b/third_party/move/move-compiler-v2/tests/more-v1/translated_ir_tests/move/commands/if_moves_else_doesnt.exp index b2ffe2bcdfd57..c7a85d1a17fb2 100644 --- a/third_party/move/move-compiler-v2/tests/more-v1/translated_ir_tests/move/commands/if_moves_else_doesnt.exp +++ b/third_party/move/move-compiler-v2/tests/more-v1/translated_ir_tests/move/commands/if_moves_else_doesnt.exp @@ -7,4 +7,4 @@ error: cannot move local `x` since it is still in use │ ^^^^^^ attempted to move here 5 │ y; 6 │ assert!(x == 0, 42); - │ ------ used here + │ - used here diff --git a/third_party/move/move-compiler-v2/tests/more-v1/translated_ir_tests/move/commands/if_moves_no_else.exp b/third_party/move/move-compiler-v2/tests/more-v1/translated_ir_tests/move/commands/if_moves_no_else.exp index aacd970467d78..03059adfe2626 100644 --- a/third_party/move/move-compiler-v2/tests/more-v1/translated_ir_tests/move/commands/if_moves_no_else.exp +++ b/third_party/move/move-compiler-v2/tests/more-v1/translated_ir_tests/move/commands/if_moves_no_else.exp @@ -7,4 +7,4 @@ error: cannot move local `x` since it is still in use │ ^^^^^^ attempted to move here · 8 │ assert!(x == 0, 42); - │ ------ used here + │ - used here diff --git a/third_party/move/move-compiler-v2/tests/no-simplifier/moved_var_not_simplified.exp b/third_party/move/move-compiler-v2/tests/no-simplifier/moved_var_not_simplified.exp index 0ed31e88c7ef1..0114c974e14c4 100644 --- a/third_party/move/move-compiler-v2/tests/no-simplifier/moved_var_not_simplified.exp +++ b/third_party/move/move-compiler-v2/tests/no-simplifier/moved_var_not_simplified.exp @@ -28,4 +28,4 @@ error: cannot move local `x` since it is still in use 4 │ let y = move x; │ ^^^^^^ attempted to move here 5 │ x + y - │ ----- used here + │ - used here diff --git a/third_party/move/move-compiler-v2/tests/op-equal/eval_order.exp b/third_party/move/move-compiler-v2/tests/op-equal/eval_order.exp index 8d0574ecb6ed7..1710e30cb9de9 100644 --- a/third_party/move/move-compiler-v2/tests/op-equal/eval_order.exp +++ b/third_party/move/move-compiler-v2/tests/op-equal/eval_order.exp @@ -171,18 +171,24 @@ public fun m::test0(): u64 { var $t5: u64 var $t6: u64 var $t7: u64 + var $t8: u64 + var $t9: u64 + var $t10: u64 0: $t1 := 1 - 1: $t5 := 2 - 2: $t4 := +($t1, $t5) - 3: $t1 := infer($t4) - 4: $t3 := infer($t1) - 5: $t6 := +($t1, $t3) - 6: $t1 := infer($t6) - 7: $t2 := infer($t1) - 8: $t7 := +($t1, $t2) - 9: $t1 := infer($t7) - 10: $t0 := infer($t1) - 11: return $t0 + 1: $t5 := infer($t1) + 2: $t6 := 2 + 3: $t4 := +($t5, $t6) + 4: $t1 := infer($t4) + 5: $t3 := infer($t1) + 6: $t8 := infer($t1) + 7: $t7 := +($t8, $t3) + 8: $t1 := infer($t7) + 9: $t2 := infer($t1) + 10: $t10 := infer($t1) + 11: $t9 := +($t10, $t2) + 12: $t1 := infer($t9) + 13: $t0 := infer($t1) + 14: return $t0 } @@ -194,15 +200,19 @@ public fun m::test1(): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 + var $t7: u64 0: $t1 := 1 - 1: $t4 := 2 - 2: $t3 := +($t1, $t4) - 3: $t1 := infer($t3) - 4: $t2 := infer($t1) - 5: $t5 := +($t1, $t2) - 6: $t1 := infer($t5) - 7: $t0 := infer($t1) - 8: return $t0 + 1: $t4 := infer($t1) + 2: $t5 := 2 + 3: $t3 := +($t4, $t5) + 4: $t1 := infer($t3) + 5: $t2 := infer($t1) + 6: $t7 := infer($t1) + 7: $t6 := +($t7, $t2) + 8: $t1 := infer($t6) + 9: $t0 := infer($t1) + 10: return $t0 } @@ -213,14 +223,16 @@ public fun m::test2(): u64 { var $t2: u64 var $t3: &mut u64 var $t4: u64 + var $t5: u64 0: $t1 := 1 1: $t3 := borrow_local($t1) 2: m::mod1($t3) 3: $t2 := infer($t1) - 4: $t4 := +($t1, $t2) - 5: $t1 := infer($t4) - 6: $t0 := infer($t1) - 7: return $t0 + 4: $t5 := infer($t1) + 5: $t4 := +($t5, $t2) + 6: $t1 := infer($t4) + 7: $t0 := infer($t1) + 8: return $t0 } @@ -231,13 +243,15 @@ public fun m::test3(): u64 { var $t2: u64 var $t3: &mut u64 var $t4: u64 + var $t5: u64 0: $t1 := 1 1: $t3 := borrow_local($t1) 2: $t2 := m::mod2($t3) - 3: $t4 := +($t1, $t2) - 4: $t1 := infer($t4) - 5: $t0 := infer($t1) - 6: return $t0 + 3: $t5 := infer($t1) + 4: $t4 := +($t5, $t2) + 5: $t1 := infer($t4) + 6: $t0 := infer($t1) + 7: return $t0 } ============ after LiveVarAnalysisProcessor: ================ @@ -249,15 +263,17 @@ fun m::mod1($t0: &mut u64) { var $t3: u64 var $t4: u64 # live vars: $t0 - 0: $t3 := read_ref($t0) + 0: $t0 := move($t0) + # live vars: $t0 + 1: $t3 := read_ref($t0) # live vars: $t0, $t3 - 1: $t4 := 2 + 2: $t4 := 2 # live vars: $t0, $t3, $t4 - 2: $t3 := +($t3, $t4) + 3: $t3 := +($t3, $t4) # live vars: $t0, $t3 - 3: write_ref($t0, $t3) + 4: write_ref($t0, $t3) # live vars: - 4: return () + 5: return () } @@ -293,30 +309,39 @@ public fun m::test0(): u64 { var $t3: u64 [unused] var $t4: u64 [unused] var $t5: u64 - var $t6: u64 [unused] + var $t6: u64 var $t7: u64 [unused] + var $t8: u64 [unused] + var $t9: u64 [unused] + var $t10: u64 [unused] # live vars: 0: $t1 := 1 # live vars: $t1 - 1: $t5 := 2 - # live vars: $t1, $t5 - 2: $t5 := +($t1, $t5) + 1: $t5 := move($t1) + # live vars: $t5 + 2: $t6 := 2 + # live vars: $t5, $t6 + 3: $t5 := +($t5, $t6) # live vars: $t5 - 3: $t1 := move($t5) + 4: $t1 := move($t5) # live vars: $t1 - 4: $t5 := copy($t1) + 5: $t5 := copy($t1) # live vars: $t1, $t5 - 5: $t5 := +($t1, $t5) + 6: $t6 := move($t1) + # live vars: $t5, $t6 + 7: $t5 := +($t6, $t5) # live vars: $t5 - 6: $t1 := move($t5) + 8: $t1 := move($t5) # live vars: $t1 - 7: $t5 := copy($t1) + 9: $t5 := copy($t1) # live vars: $t1, $t5 - 8: $t5 := +($t1, $t5) + 10: $t6 := move($t1) + # live vars: $t5, $t6 + 11: $t5 := +($t6, $t5) # live vars: $t5 - 9: $t1 := move($t5) + 12: $t1 := move($t5) # live vars: $t1 - 10: return $t1 + 13: return $t1 } @@ -327,23 +352,29 @@ public fun m::test1(): u64 { var $t2: u64 [unused] var $t3: u64 [unused] var $t4: u64 - var $t5: u64 [unused] + var $t5: u64 + var $t6: u64 [unused] + var $t7: u64 [unused] # live vars: 0: $t1 := 1 # live vars: $t1 - 1: $t4 := 2 - # live vars: $t1, $t4 - 2: $t4 := +($t1, $t4) + 1: $t4 := move($t1) + # live vars: $t4 + 2: $t5 := 2 + # live vars: $t4, $t5 + 3: $t4 := +($t4, $t5) # live vars: $t4 - 3: $t1 := move($t4) + 4: $t1 := move($t4) # live vars: $t1 - 4: $t4 := copy($t1) + 5: $t4 := copy($t1) # live vars: $t1, $t4 - 5: $t4 := +($t1, $t4) + 6: $t5 := move($t1) + # live vars: $t4, $t5 + 7: $t4 := +($t5, $t4) # live vars: $t4 - 6: $t1 := move($t4) + 8: $t1 := move($t4) # live vars: $t1 - 7: return $t1 + 9: return $t1 } @@ -354,6 +385,7 @@ public fun m::test2(): u64 { var $t2: u64 var $t3: &mut u64 var $t4: u64 [unused] + var $t5: u64 # live vars: 0: $t1 := 1 # live vars: $t1 @@ -363,13 +395,15 @@ public fun m::test2(): u64 { # live vars: $t1 3: $t2 := copy($t1) # live vars: $t1, $t2 - 4: $t2 := +($t1, $t2) + 4: $t5 := move($t1) + # live vars: $t2, $t5 + 5: $t2 := +($t5, $t2) # live vars: $t2 - 5: $t1 := move($t2) + 6: $t1 := move($t2) # live vars: $t1 - 6: $t2 := move($t1) + 7: $t2 := move($t1) # live vars: $t2 - 7: return $t2 + 8: return $t2 } @@ -380,6 +414,7 @@ public fun m::test3(): u64 { var $t2: u64 var $t3: &mut u64 var $t4: u64 [unused] + var $t5: u64 # live vars: 0: $t1 := 1 # live vars: $t1 @@ -387,13 +422,15 @@ public fun m::test3(): u64 { # live vars: $t1, $t3 2: $t2 := m::mod2($t3) # live vars: $t1, $t2 - 3: $t2 := +($t1, $t2) + 3: $t5 := move($t1) + # live vars: $t2, $t5 + 4: $t2 := +($t5, $t2) # live vars: $t2 - 4: $t1 := move($t2) + 5: $t1 := move($t2) # live vars: $t1 - 5: $t2 := move($t1) + 6: $t2 := move($t1) # live vars: $t2 - 6: return $t2 + 7: return $t2 } diff --git a/third_party/move/move-compiler-v2/tests/op-equal/invalid1.exp b/third_party/move/move-compiler-v2/tests/op-equal/invalid1.exp index e615879b5173c..bd9894740abeb 100644 --- a/third_party/move/move-compiler-v2/tests/op-equal/invalid1.exp +++ b/third_party/move/move-compiler-v2/tests/op-equal/invalid1.exp @@ -39,23 +39,25 @@ fun test::test() { var $t1: &mut u64 var $t2: u64 var $t3: u64 - var $t4: &mut u64 - var $t5: u64 + var $t4: u64 + var $t5: &mut u64 var $t6: u64 var $t7: u64 var $t8: u64 + var $t9: u64 0: $t0 := 42 1: $t1 := borrow_local($t0) - 2: $t3 := 1 - 3: $t2 := +($t0, $t3) - 4: $t0 := infer($t2) - 5: $t4 := infer($t1) - 6: $t6 := read_ref($t4) - 7: $t7 := 1 - 8: $t5 := +($t6, $t7) - 9: write_ref($t4, $t5) - 10: $t8 := infer($t0) - 11: return () + 2: $t3 := infer($t0) + 3: $t4 := 1 + 4: $t2 := +($t3, $t4) + 5: $t0 := infer($t2) + 6: $t5 := infer($t1) + 7: $t7 := read_ref($t5) + 8: $t8 := 1 + 9: $t6 := +($t7, $t8) + 10: write_ref($t5, $t6) + 11: $t9 := infer($t0) + 12: return () } @@ -66,7 +68,7 @@ error: cannot copy local `x` which is still mutably borrowed 4 │ let p = &mut x; │ ------ local `x` previously mutably borrowed here 5 │ x += 1; - │ ^^^^^^ copy attempted here + │ ^ copy attempted here 6 │ *p += 1; │ - conflicting reference `p` used here diff --git a/third_party/move/move-compiler-v2/tests/op-equal/valid0.exp b/third_party/move/move-compiler-v2/tests/op-equal/valid0.exp index e3a00fa6e9edf..66ed1975916a0 100644 --- a/third_party/move/move-compiler-v2/tests/op-equal/valid0.exp +++ b/third_party/move/move-compiler-v2/tests/op-equal/valid0.exp @@ -204,11 +204,13 @@ fun test::add1_new($t0: u256): u256 { var $t1: u256 var $t2: u256 var $t3: u256 - 0: $t3 := 1 - 1: $t2 := +($t0, $t3) - 2: $t0 := infer($t2) - 3: $t1 := infer($t0) - 4: return $t1 + var $t4: u256 + 0: $t3 := infer($t0) + 1: $t4 := 1 + 2: $t2 := +($t3, $t4) + 3: $t0 := infer($t2) + 4: $t1 := infer($t0) + 5: return $t1 } @@ -217,11 +219,13 @@ fun test::add1_old($t0: u256): u256 { var $t1: u256 var $t2: u256 var $t3: u256 - 0: $t3 := 1 - 1: $t2 := +($t0, $t3) - 2: $t0 := infer($t2) - 3: $t1 := infer($t0) - 4: return $t1 + var $t4: u256 + 0: $t3 := infer($t0) + 1: $t4 := 1 + 2: $t2 := +($t3, $t4) + 3: $t0 := infer($t2) + 4: $t1 := infer($t0) + 5: return $t1 } @@ -379,15 +383,17 @@ fun test::inc_vec_coin_old($t0: vector<0x42::test::Coin>, $t1: u64) { [variant baseline] fun test::inc_vec_new($t0: &mut vector, $t1: u64) { var $t2: &mut u256 - var $t3: u256 + var $t3: &mut vector var $t4: u256 var $t5: u256 - 0: $t2 := vector::borrow_mut($t0, $t1) - 1: $t4 := read_ref($t2) - 2: $t5 := 1 - 3: $t3 := +($t4, $t5) - 4: write_ref($t2, $t3) - 5: return () + var $t6: u256 + 0: $t3 := infer($t0) + 1: $t2 := vector::borrow_mut($t3, $t1) + 2: $t5 := read_ref($t2) + 3: $t6 := 1 + 4: $t4 := +($t5, $t6) + 5: write_ref($t2, $t4) + 6: return () } @@ -506,14 +512,17 @@ fun test::add1_new($t0: u256): u256 { var $t1: u256 [unused] var $t2: u256 [unused] var $t3: u256 + var $t4: u256 # live vars: $t0 - 0: $t3 := 1 - # live vars: $t0, $t3 - 1: $t3 := +($t0, $t3) + 0: $t3 := move($t0) + # live vars: $t3 + 1: $t4 := 1 + # live vars: $t3, $t4 + 2: $t3 := +($t3, $t4) # live vars: $t3 - 2: $t0 := move($t3) + 3: $t0 := move($t3) # live vars: $t0 - 3: return $t0 + 4: return $t0 } @@ -522,14 +531,17 @@ fun test::add1_old($t0: u256): u256 { var $t1: u256 [unused] var $t2: u256 [unused] var $t3: u256 + var $t4: u256 # live vars: $t0 - 0: $t3 := 1 - # live vars: $t0, $t3 - 1: $t3 := +($t0, $t3) + 0: $t3 := move($t0) + # live vars: $t3 + 1: $t4 := 1 + # live vars: $t3, $t4 + 2: $t3 := +($t3, $t4) # live vars: $t3 - 2: $t0 := move($t3) + 3: $t0 := move($t3) # live vars: $t0 - 3: return $t0 + 4: return $t0 } @@ -651,15 +663,17 @@ fun test::inc_new($t0: &mut u256) { var $t3: u256 var $t4: u256 # live vars: $t0 - 0: $t3 := read_ref($t0) + 0: $t0 := move($t0) + # live vars: $t0 + 1: $t3 := read_ref($t0) # live vars: $t0, $t3 - 1: $t4 := 1 + 2: $t4 := 1 # live vars: $t0, $t3, $t4 - 2: $t3 := +($t3, $t4) + 3: $t3 := +($t3, $t4) # live vars: $t0, $t3 - 3: write_ref($t0, $t3) + 4: write_ref($t0, $t3) # live vars: - 4: return () + 5: return () } @@ -747,21 +761,24 @@ fun test::inc_vec_coin_old($t0: vector<0x42::test::Coin>, $t1: u64) { [variant baseline] fun test::inc_vec_new($t0: &mut vector, $t1: u64) { var $t2: &mut u256 - var $t3: u256 [unused] - var $t4: u256 + var $t3: &mut vector [unused] + var $t4: u256 [unused] var $t5: u256 + var $t6: u256 # live vars: $t0, $t1 - 0: $t2 := vector::borrow_mut($t0, $t1) + 0: $t0 := move($t0) + # live vars: $t0, $t1 + 1: $t2 := vector::borrow_mut($t0, $t1) # live vars: $t2 - 1: $t4 := read_ref($t2) - # live vars: $t2, $t4 - 2: $t5 := 1 - # live vars: $t2, $t4, $t5 - 3: $t4 := +($t4, $t5) - # live vars: $t2, $t4 - 4: write_ref($t2, $t4) + 2: $t5 := read_ref($t2) + # live vars: $t2, $t5 + 3: $t6 := 1 + # live vars: $t2, $t5, $t6 + 4: $t5 := +($t5, $t6) + # live vars: $t2, $t5 + 5: write_ref($t2, $t5) # live vars: - 5: return () + 6: return () } @@ -932,7 +949,6 @@ struct Wrapper has drop, key { } add1_new(Arg0: u256): u256 /* def_idx: 0 */ { -L1: loc0: u256 B0: 0: MoveLoc[0](Arg0: u256) 1: LdU256(1) @@ -940,7 +956,6 @@ B0: 3: Ret } add1_old(Arg0: u256): u256 /* def_idx: 1 */ { -L1: loc0: u256 B0: 0: MoveLoc[0](Arg0: u256) 1: LdU256(1) diff --git a/third_party/move/move-compiler-v2/tests/op-equal/valid1.exp b/third_party/move/move-compiler-v2/tests/op-equal/valid1.exp index d75c575a32c78..4687235280fae 100644 --- a/third_party/move/move-compiler-v2/tests/op-equal/valid1.exp +++ b/third_party/move/move-compiler-v2/tests/op-equal/valid1.exp @@ -167,15 +167,17 @@ fun test::bitand_vec_coin_new($t0: vector<0x42::test::Coin>, $t1: u64) { [variant baseline] fun test::bitor_vec_new($t0: &mut vector, $t1: u64) { var $t2: &mut u256 - var $t3: u256 + var $t3: &mut vector var $t4: u256 var $t5: u256 - 0: $t2 := vector::borrow_mut($t0, $t1) - 1: $t4 := read_ref($t2) - 2: $t5 := 42 - 3: $t3 := |($t4, $t5) - 4: write_ref($t2, $t3) - 5: return () + var $t6: u256 + 0: $t3 := infer($t0) + 1: $t2 := vector::borrow_mut($t3, $t1) + 2: $t5 := read_ref($t2) + 3: $t6 := 42 + 4: $t4 := |($t5, $t6) + 5: write_ref($t2, $t4) + 6: return () } @@ -331,21 +333,24 @@ fun test::bitand_vec_coin_new($t0: vector<0x42::test::Coin>, $t1: u64) { [variant baseline] fun test::bitor_vec_new($t0: &mut vector, $t1: u64) { var $t2: &mut u256 - var $t3: u256 [unused] - var $t4: u256 + var $t3: &mut vector [unused] + var $t4: u256 [unused] var $t5: u256 + var $t6: u256 + # live vars: $t0, $t1 + 0: $t0 := move($t0) # live vars: $t0, $t1 - 0: $t2 := vector::borrow_mut($t0, $t1) + 1: $t2 := vector::borrow_mut($t0, $t1) # live vars: $t2 - 1: $t4 := read_ref($t2) - # live vars: $t2, $t4 - 2: $t5 := 42 - # live vars: $t2, $t4, $t5 - 3: $t4 := |($t4, $t5) - # live vars: $t2, $t4 - 4: write_ref($t2, $t4) + 2: $t5 := read_ref($t2) + # live vars: $t2, $t5 + 3: $t6 := 42 + # live vars: $t2, $t5, $t6 + 4: $t5 := |($t5, $t6) + # live vars: $t2, $t5 + 5: write_ref($t2, $t5) # live vars: - 5: return () + 6: return () } @@ -476,15 +481,17 @@ fun test::sub1($t0: &mut u256) { var $t3: u256 var $t4: u256 # live vars: $t0 - 0: $t3 := read_ref($t0) + 0: $t0 := move($t0) + # live vars: $t0 + 1: $t3 := read_ref($t0) # live vars: $t0, $t3 - 1: $t4 := 1 + 2: $t4 := 1 # live vars: $t0, $t3, $t4 - 2: $t3 := -($t3, $t4) + 3: $t3 := -($t3, $t4) # live vars: $t0, $t3 - 3: write_ref($t0, $t3) + 4: write_ref($t0, $t3) # live vars: - 4: return () + 5: return () } diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/duplicate_use.exp b/third_party/move/move-compiler-v2/tests/reference-safety/duplicate_use.exp index f41849f78bc59..8410c0cfc90a9 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/duplicate_use.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/duplicate_use.exp @@ -5,6 +5,6 @@ error: cannot transfer mutable local `x` since it is borrowed │ 8 │ mut_ref(x, x) │ ^^^^^^^^^^^^^ - │ │ + │ │ │ + │ │ previously mutably borrowed here │ transfer attempted here - │ previously mutably borrowed here diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/duplicate_use.old.exp b/third_party/move/move-compiler-v2/tests/reference-safety/duplicate_use.old.exp index fca6dfb9b9abc..89a3a9cca1859 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/duplicate_use.old.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/duplicate_use.old.exp @@ -1,7 +1,9 @@ Diagnostics: -error: same mutable reference in local `x` is used again in argument list +error: same mutable reference in local `x` is also used in other value in argument list ┌─ tests/reference-safety/duplicate_use.move:8:9 │ +7 │ fun fail(x: &mut u64) { + │ - previous mutable local borrow 8 │ mut_ref(x, x) │ ^^^^^^^^^^^^^ requirement enforced here diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/freeze.exp b/third_party/move/move-compiler-v2/tests/reference-safety/freeze.exp index 773015d0f9c65..8167877ca429b 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/freeze.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/freeze.exp @@ -5,9 +5,9 @@ error: cannot transfer mutable local `r` since it is borrowed │ 18 │ ref_mut_mut(r, r); // error │ ^^^^^^^^^^^^^^^^^ - │ │ + │ │ │ + │ │ previously mutably borrowed here │ transfer attempted here - │ previously mutably borrowed here error: cannot transfer mutable local `r` since it is borrowed ┌─ tests/reference-safety/freeze.move:24:9 diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/freeze.old.exp b/third_party/move/move-compiler-v2/tests/reference-safety/freeze.old.exp index e56e055336711..62117e58091fc 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/freeze.old.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/freeze.old.exp @@ -1,8 +1,10 @@ Diagnostics: -error: same mutable reference in local `r` is used again in argument list +error: same mutable reference in local `r` is also used in other value in argument list ┌─ tests/reference-safety/freeze.move:18:9 │ +17 │ let r = &mut x; + │ ------ previous mutable local borrow 18 │ ref_mut_mut(r, r); // error │ ^^^^^^^^^^^^^^^^^ requirement enforced here diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/multiple_use_invalid.exp b/third_party/move/move-compiler-v2/tests/reference-safety/multiple_use_invalid.exp index 56d76e7207b0b..22155231434e2 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/multiple_use_invalid.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/multiple_use_invalid.exp @@ -9,7 +9,7 @@ error: cannot transfer mutable value since it is borrowed │ │ previously mutably borrowed here │ transfer attempted here -error: cannot transfer mutable local `r` since it is borrowed +error: cannot transfer mutable value since it is borrowed ┌─ tests/reference-safety/multiple_use_invalid.move:11:9 │ 10 │ let x = r; diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/multiple_use_invalid.old.exp b/third_party/move/move-compiler-v2/tests/reference-safety/multiple_use_invalid.old.exp index fcfc05f5dda14..bf55b27743b0a 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/multiple_use_invalid.old.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/multiple_use_invalid.old.exp @@ -10,7 +10,16 @@ error: same mutable reference in value is also used in other value in argument l │ │ previous mutable field borrow │ requirement enforced here -error: same mutable reference in local `r` is also used in other local `x` in argument list +error: mutable reference in local `r` requires exclusive access but is borrowed + ┌─ tests/reference-safety/multiple_use_invalid.move:11:11 + │ +11 │ s(r, x) + │ --^---- + │ │ │ + │ │ requirement enforced here + │ conflicting reference `x` used here + +error: same mutable reference in local `x` is also used in other value in argument list ┌─ tests/reference-safety/multiple_use_invalid.move:11:9 │ 9 │ let r = &mut s.x; @@ -19,7 +28,7 @@ error: same mutable reference in local `r` is also used in other local `x` in ar 11 │ s(r, x) │ ^^^^^^^ requirement enforced here -error: same mutable reference in local `r1` is also used in other local `r2` in argument list +error: same mutable reference in local `r2` is also used in other value in argument list ┌─ tests/reference-safety/multiple_use_invalid.move:20:9 │ 18 │ let r1 = &mut x; diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/v1-borrow-tests/factor_invalid_1.exp b/third_party/move/move-compiler-v2/tests/reference-safety/v1-borrow-tests/factor_invalid_1.exp index a37612c579b63..56f4e5f2d3b21 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/v1-borrow-tests/factor_invalid_1.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/v1-borrow-tests/factor_invalid_1.exp @@ -9,7 +9,7 @@ error: cannot transfer mutable local `f` since it is borrowed 12 │ foo(f_g, f); │ ^^^^^^^^^^^ transfer attempted here -error: cannot transfer mutable local `f` since it is borrowed +error: cannot transfer mutable value since it is borrowed ┌─ tests/reference-safety/v1-borrow-tests/factor_invalid_1.move:22:9 │ 19 │ let f_g = &mut f.g; diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/v1-borrow-tests/factor_invalid_1.old.exp b/third_party/move/move-compiler-v2/tests/reference-safety/v1-borrow-tests/factor_invalid_1.old.exp index 8a1e25a9340bd..b1846d1919b64 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/v1-borrow-tests/factor_invalid_1.old.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/v1-borrow-tests/factor_invalid_1.old.exp @@ -10,6 +10,18 @@ error: mutable reference in local `f` requires exclusive access but is borrowed │ ^^^^^^^^^^^ requirement enforced here error: mutable reference in local `f` requires exclusive access but is borrowed + ┌─ tests/reference-safety/v1-borrow-tests/factor_invalid_1.move:22:13 + │ +19 │ let f_g = &mut f.g; + │ -------- previous mutable field borrow + · +22 │ bar(f, f_g); + │ ----^------ + │ │ │ + │ │ requirement enforced here + │ conflicting reference `f_g` used here + +error: mutable reference in value requires exclusive access but is borrowed ┌─ tests/reference-safety/v1-borrow-tests/factor_invalid_1.move:22:9 │ 19 │ let f_g = &mut f.g; diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/v1-borrow-tests/imm_borrow_global_invalid.exp b/third_party/move/move-compiler-v2/tests/reference-safety/v1-borrow-tests/imm_borrow_global_invalid.exp index e9543d2bd3ac1..27c3fd7b6be3a 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/v1-borrow-tests/imm_borrow_global_invalid.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/v1-borrow-tests/imm_borrow_global_invalid.exp @@ -18,7 +18,7 @@ error: cannot mutably borrow `Tester::Pair` since it is already borrowed 36 │ let p2 = freeze(borrow_global_mut(addr2)); │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow attempted here 37 │ p1 == p2 - │ -------- conflicting reference `p1` used here + │ -- conflicting reference `p1` used here error: cannot mutably borrow `Tester::Pair` since it is already borrowed ┌─ tests/reference-safety/v1-borrow-tests/imm_borrow_global_invalid.move:42:19 @@ -28,4 +28,4 @@ error: cannot mutably borrow `Tester::Pair` since it is already borrowed 42 │ let c2 = &borrow_global_mut(addr2).x; │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow attempted here 43 │ c1 == c2 - │ -------- conflicting reference `c1` used here + │ -- conflicting reference `c1` used here diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/v1-borrow-tests/imm_borrow_loc.old.exp b/third_party/move/move-compiler-v2/tests/reference-safety/v1-borrow-tests/imm_borrow_loc.old.exp index ec38e8b177d8a..46735fe0e42ea 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/v1-borrow-tests/imm_borrow_loc.old.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/v1-borrow-tests/imm_borrow_loc.old.exp @@ -16,7 +16,7 @@ error: cannot immutably borrow since mutable references exist │ immutable borrow attempted here 28 │ assert!(b2.f != 0, 42); 29 │ assert!((returned_ref == &b1.f) != (returned_ref == &b2.f), 42); - │ ----------------------- conflicting reference `returned_ref` used here + │ ------------ conflicting reference `returned_ref` used here error: cannot immutably borrow since mutable references exist ┌─ tests/reference-safety/v1-borrow-tests/imm_borrow_loc.move:28:17 @@ -33,7 +33,7 @@ error: cannot immutably borrow since mutable references exist │ requirement enforced here │ immutable borrow attempted here 29 │ assert!((returned_ref == &b1.f) != (returned_ref == &b2.f), 42); - │ ----------------------- conflicting reference `returned_ref` used here + │ ------------ conflicting reference `returned_ref` used here error: cannot immutably borrow since mutable references exist ┌─ tests/reference-safety/v1-borrow-tests/imm_borrow_loc.move:29:35 @@ -45,7 +45,7 @@ error: cannot immutably borrow since mutable references exist │ used by call result · 29 │ assert!((returned_ref == &b1.f) != (returned_ref == &b2.f), 42); - │ ------------------^^--- ----------------------- conflicting reference `returned_ref` used here + │ ------------------^^--- ------------ conflicting reference `returned_ref` used here │ │ │ │ │ immutable borrow attempted here │ requirement enforced here diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/v1-borrow-tests/imm_borrow_loc_valid.old.exp b/third_party/move/move-compiler-v2/tests/reference-safety/v1-borrow-tests/imm_borrow_loc_valid.old.exp index 6709295ee1f47..b1d84511b940b 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/v1-borrow-tests/imm_borrow_loc_valid.old.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/v1-borrow-tests/imm_borrow_loc_valid.old.exp @@ -16,7 +16,7 @@ error: cannot immutably borrow since mutable references exist │ immutable borrow attempted here · 30 │ (returned_ref == &(&mut b1).f) != (returned_ref == &(&mut b2).f), - │ ------------------------------ conflicting reference `returned_ref` used here + │ ------------ conflicting reference `returned_ref` used here error: cannot immutably borrow since mutable references exist ┌─ tests/reference-safety/v1-borrow-tests/imm_borrow_loc_valid.move:28:17 @@ -34,4 +34,4 @@ error: cannot immutably borrow since mutable references exist │ immutable borrow attempted here 29 │ assert!( 30 │ (returned_ref == &(&mut b1).f) != (returned_ref == &(&mut b2).f), - │ ------------------------------ conflicting reference `returned_ref` used here + │ ------------ conflicting reference `returned_ref` used here diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_mutual_borrows_invalid.exp b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_mutual_borrows_invalid.exp index 3c2747e18e2d0..6cf64ef5cb91c 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_mutual_borrows_invalid.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_mutual_borrows_invalid.exp @@ -1,6 +1,6 @@ Diagnostics: -error: cannot transfer mutable local `s1` since it is borrowed +error: cannot transfer mutable value since it is borrowed ┌─ tests/reference-safety/v1-tests/call_mutual_borrows_invalid.move:15:9 │ 14 │ let f = freeze(s1); @@ -8,7 +8,7 @@ error: cannot transfer mutable local `s1` since it is borrowed 15 │ mut_imm(s1, f); │ ^^^^^^^^^^^^^^ transfer attempted here -error: cannot transfer mutable local `s1` since it is borrowed +error: cannot transfer mutable value since it is borrowed ┌─ tests/reference-safety/v1-tests/call_mutual_borrows_invalid.move:17:9 │ 16 │ let f = &s1.f; @@ -39,11 +39,11 @@ error: cannot transfer mutable local `s1` since it is borrowed │ 23 │ mut_mut(s1, s1); │ ^^^^^^^^^^^^^^^ - │ │ + │ │ │ + │ │ previously mutably borrowed here │ transfer attempted here - │ previously mutably borrowed here -error: cannot transfer mutable local `s1` since it is borrowed +error: cannot transfer mutable value since it is borrowed ┌─ tests/reference-safety/v1-tests/call_mutual_borrows_invalid.move:25:9 │ 24 │ let f = &mut s1.f; @@ -70,7 +70,7 @@ error: cannot transfer mutable local `s1` since it is borrowed 29 │ *s; │ -- conflicting reference `s` used here -error: cannot transfer mutable local `s1` since it is borrowed +error: cannot transfer mutable value since it is borrowed ┌─ tests/reference-safety/v1-tests/call_mutual_borrows_invalid.move:31:9 │ 30 │ let f = id_mut(&mut s1.f); diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_mutual_borrows_invalid.old.exp b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_mutual_borrows_invalid.old.exp index 36f592249a698..a1925cca1e95f 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_mutual_borrows_invalid.old.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_mutual_borrows_invalid.old.exp @@ -1,20 +1,46 @@ Diagnostics: error: mutable reference in local `s1` requires exclusive access but is borrowed + ┌─ tests/reference-safety/v1-tests/call_mutual_borrows_invalid.move:15:17 + │ +14 │ let f = freeze(s1); + │ ---------- previous freeze +15 │ mut_imm(s1, f); + │ --------^^---- + │ │ │ + │ │ requirement enforced here + │ conflicting reference `f` used here + +error: mutable reference in value requires exclusive access but is borrowed ┌─ tests/reference-safety/v1-tests/call_mutual_borrows_invalid.move:15:9 │ 14 │ let f = freeze(s1); │ ---------- previous freeze 15 │ mut_imm(s1, f); │ ^^^^^^^^^^^^^^ requirement enforced here +16 │ let f = &s1.f; + │ ----- conflicting reference `s1` used here error: mutable reference in local `s1` requires exclusive access but is borrowed + ┌─ tests/reference-safety/v1-tests/call_mutual_borrows_invalid.move:17:17 + │ +16 │ let f = &s1.f; + │ ----- previous field borrow +17 │ mut_imm(s1, f); + │ --------^^---- + │ │ │ + │ │ requirement enforced here + │ conflicting reference `f` used here + +error: mutable reference in value requires exclusive access but is borrowed ┌─ tests/reference-safety/v1-tests/call_mutual_borrows_invalid.move:17:9 │ 16 │ let f = &s1.f; │ ----- previous field borrow 17 │ mut_imm(s1, f); │ ^^^^^^^^^^^^^^ requirement enforced here +18 │ let f = &s1.f; + │ ----- conflicting reference `s1` used here error: cannot mutably borrow since immutable references exist ┌─ tests/reference-safety/v1-tests/call_mutual_borrows_invalid.move:19:17 @@ -43,19 +69,35 @@ error: cannot mutably borrow since immutable references exist │ │ mutable borrow attempted here │ requirement enforced here -error: same mutable reference in local `s1` is used again in argument list +error: same mutable reference in local `s1` is also used in other value in argument list ┌─ tests/reference-safety/v1-tests/call_mutual_borrows_invalid.move:23:9 │ +13 │ fun t0(s1: &mut S, _s2: &mut S) { + │ -- previous mutable local borrow + · 23 │ mut_mut(s1, s1); │ ^^^^^^^^^^^^^^^ requirement enforced here error: mutable reference in local `s1` requires exclusive access but is borrowed + ┌─ tests/reference-safety/v1-tests/call_mutual_borrows_invalid.move:25:17 + │ +24 │ let f = &mut s1.f; + │ --------- previous mutable field borrow +25 │ mut_mut(s1, f); + │ --------^^---- + │ │ │ + │ │ requirement enforced here + │ conflicting reference `f` used here + +error: mutable reference in value requires exclusive access but is borrowed ┌─ tests/reference-safety/v1-tests/call_mutual_borrows_invalid.move:25:9 │ 24 │ let f = &mut s1.f; │ --------- previous mutable field borrow 25 │ mut_mut(s1, f); │ ^^^^^^^^^^^^^^ requirement enforced here +26 │ mut_mut(&mut s1.f, s1); + │ --------- conflicting reference `s1` used here error: mutable reference in local `s1` requires exclusive access but is borrowed ┌─ tests/reference-safety/v1-tests/call_mutual_borrows_invalid.move:26:9 @@ -77,6 +119,20 @@ error: mutable reference in local `s1` requires exclusive access but is borrowed │ -- conflicting reference `s` used here error: mutable reference in local `s1` requires exclusive access but is borrowed + ┌─ tests/reference-safety/v1-tests/call_mutual_borrows_invalid.move:31:17 + │ +30 │ let f = id_mut(&mut s1.f); + │ ----------------- + │ │ │ + │ │ previous mutable field borrow + │ used by mutable call result +31 │ mut_mut(s1, f); + │ --------^^---- + │ │ │ + │ │ requirement enforced here + │ conflicting reference `f` used here + +error: mutable reference in value requires exclusive access but is borrowed ┌─ tests/reference-safety/v1-tests/call_mutual_borrows_invalid.move:31:9 │ 30 │ let f = id_mut(&mut s1.f); @@ -86,6 +142,8 @@ error: mutable reference in local `s1` requires exclusive access but is borrowed │ used by mutable call result 31 │ mut_mut(s1, f); │ ^^^^^^^^^^^^^^ requirement enforced here +32 │ mut_mut(id_mut(&mut s1.f), s1); + │ --------- conflicting reference `s1` used here error: mutable reference in local `s1` requires exclusive access but is borrowed ┌─ tests/reference-safety/v1-tests/call_mutual_borrows_invalid.move:32:9 diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/copy_full_invalid.exp b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/copy_full_invalid.exp index e5fbce1d21b8d..cce03ec82b236 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/copy_full_invalid.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/copy_full_invalid.exp @@ -6,7 +6,7 @@ error: cannot copy local `x` which is still mutably borrowed 12 │ let f = &mut x; │ ------ local `x` previously mutably borrowed here 13 │ x + 0; - │ ^^^^^ copy attempted here + │ ^ copy attempted here 14 │ *f; │ -- conflicting reference `f` used here @@ -16,6 +16,6 @@ error: cannot copy local `x` which is still mutably borrowed 18 │ let f = id_mut(&mut x); │ -------------- local `x` previously mutably borrowed here 19 │ x + 0; - │ ^^^^^ copy attempted here + │ ^ copy attempted here 20 │ *f; │ -- conflicting reference `f` used here diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/copy_full_invalid.old.exp b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/copy_full_invalid.old.exp index 8a5582cc2b73c..1c2c1073f3736 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/copy_full_invalid.old.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/copy_full_invalid.old.exp @@ -1,16 +1,16 @@ Diagnostics: -error: cannot pass local `x` which is still mutably borrowed as function argument +error: cannot copy local `x` which is still mutably borrowed ┌─ tests/reference-safety/v1-tests/copy_full_invalid.move:13:9 │ 12 │ let f = &mut x; │ ------ previous mutable local borrow 13 │ x + 0; - │ ^^^^^ passed here + │ ^ copied here 14 │ *f; │ -- conflicting reference `f` used here -error: cannot pass local `x` which is still mutably borrowed as function argument +error: cannot copy local `x` which is still mutably borrowed ┌─ tests/reference-safety/v1-tests/copy_full_invalid.move:19:9 │ 18 │ let f = id_mut(&mut x); @@ -19,6 +19,6 @@ error: cannot pass local `x` which is still mutably borrowed as function argumen │ │ previous mutable local borrow │ used by mutable call result 19 │ x + 0; - │ ^^^^^ passed here + │ ^ copied here 20 │ *f; │ -- conflicting reference `f` used here diff --git a/third_party/move/move-compiler-v2/tests/simplifier-elimination/else_assigns_if_doesnt.exp b/third_party/move/move-compiler-v2/tests/simplifier-elimination/else_assigns_if_doesnt.exp index dc7f6f24d283d..c8fb66932a341 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier-elimination/else_assigns_if_doesnt.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier-elimination/else_assigns_if_doesnt.exp @@ -45,4 +45,4 @@ error: use of possibly unassigned local `y` ┌─ tests/simplifier-elimination/else_assigns_if_doesnt.move:11:13 │ 11 │ assert!(y == 0, 42); - │ ^^^^^^ + │ ^ diff --git a/third_party/move/move-compiler-v2/tests/simplifier-elimination/if_assigns_else_doesnt.exp b/third_party/move/move-compiler-v2/tests/simplifier-elimination/if_assigns_else_doesnt.exp index 5c7d031f7cbe2..a1a6e7c1f0c7e 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier-elimination/if_assigns_else_doesnt.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier-elimination/if_assigns_else_doesnt.exp @@ -45,4 +45,4 @@ error: use of possibly unassigned local `x` ┌─ tests/simplifier-elimination/if_assigns_else_doesnt.move:11:13 │ 11 │ assert!(x == 42, 42); - │ ^^^^^^^ + │ ^ diff --git a/third_party/move/move-compiler-v2/tests/simplifier-elimination/moved_var_not_simplified.exp b/third_party/move/move-compiler-v2/tests/simplifier-elimination/moved_var_not_simplified.exp index 5993472addce0..e4bf54017e179 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier-elimination/moved_var_not_simplified.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier-elimination/moved_var_not_simplified.exp @@ -28,4 +28,4 @@ error: cannot move local `x` since it is still in use 4 │ let y = move x; │ ^^^^^^ attempted to move here 5 │ x + y - │ ----- used here + │ - used here diff --git a/third_party/move/move-compiler-v2/tests/simplifier-elimination/use_before_assign_loop.exp b/third_party/move/move-compiler-v2/tests/simplifier-elimination/use_before_assign_loop.exp index 549cc95c615c2..f61681833eb12 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier-elimination/use_before_assign_loop.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier-elimination/use_before_assign_loop.exp @@ -115,7 +115,7 @@ error: use of possibly unassigned local `x` ┌─ tests/simplifier-elimination/use_before_assign_loop.move:9:24 │ 9 │ loop { let y = x + 1; if (cond) { continue }; x = 0; y; } - │ ^^^^^ + │ ^ error: use of possibly unassigned local `x` ┌─ tests/simplifier-elimination/use_before_assign_loop.move:14:24 diff --git a/third_party/move/move-compiler-v2/tests/simplifier/moved_var_not_simplified.exp b/third_party/move/move-compiler-v2/tests/simplifier/moved_var_not_simplified.exp index bba70e2914393..d01240bac1cc4 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier/moved_var_not_simplified.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier/moved_var_not_simplified.exp @@ -28,4 +28,4 @@ error: cannot move local `x` since it is still in use 4 │ let y = move x; │ ^^^^^^ attempted to move here 5 │ x + y - │ ----- used here + │ - used here diff --git a/third_party/move/move-compiler-v2/tests/testsuite.rs b/third_party/move/move-compiler-v2/tests/testsuite.rs index eff9be3737cf6..a5e6ef2322d8d 100644 --- a/third_party/move/move-compiler-v2/tests/testsuite.rs +++ b/third_party/move/move-compiler-v2/tests/testsuite.rs @@ -265,7 +265,7 @@ const TEST_CONFIGS: Lazy> = Lazy::new(|| { stop_after: StopAfter::FileFormat, dump_ast: DumpLevel::EndStage, dump_bytecode: DumpLevel::EndStage, - dump_bytecode_filter: Some(vec![INITIAL_BYTECODE_STAGE]), + dump_bytecode_filter: Some(vec![INITIAL_BYTECODE_STAGE, FILE_FORMAT_STAGE]), }, // -- Tests for stages in the bytecode pipeline // Live-var tests @@ -276,10 +276,15 @@ const TEST_CONFIGS: Lazy> = Lazy::new(|| { exclude: vec![], exp_suffix: None, options: opts.clone(), - stop_after: StopAfter::BytecodePipeline(Some("LiveVarAnalysisProcessor")), + // Run the entire compiler pipeline to double-check the result + stop_after: StopAfter::FileFormat, dump_ast: DumpLevel::None, dump_bytecode: DumpLevel::AllStages, - dump_bytecode_filter: Some(vec![INITIAL_BYTECODE_STAGE, "LiveVarAnalysisProcessor"]), + dump_bytecode_filter: Some(vec![ + INITIAL_BYTECODE_STAGE, + "LiveVarAnalysisProcessor", + FILE_FORMAT_STAGE, + ]), }, // Reference safety tests, old version (with optimizations on) TestConfig { @@ -386,7 +391,8 @@ const TEST_CONFIGS: Lazy> = Lazy::new(|| { exclude: vec![], exp_suffix: None, options: opts.clone(), - stop_after: StopAfter::BytecodePipeline(Some("AbilityProcessor")), + // Run the entire compiler pipeline to double-check the result + stop_after: StopAfter::FileFormat, dump_ast: DumpLevel::None, dump_bytecode: DumpLevel::AllStages, dump_bytecode_filter: Some(vec![ @@ -395,6 +401,7 @@ const TEST_CONFIGS: Lazy> = Lazy::new(|| { "LiveVarAnalysisProcessor", "ReferenceSafetyProcessor", "AbilityProcessor", + FILE_FORMAT_STAGE, ]), }, TestConfig { @@ -541,6 +548,7 @@ const TEST_CONFIGS: Lazy> = Lazy::new(|| { INITIAL_BYTECODE_STAGE, "UnreachableCodeProcessor", "UnreachableCodeRemover", + FILE_FORMAT_STAGE, ]), }, // Uninitialized use checker @@ -553,10 +561,15 @@ const TEST_CONFIGS: Lazy> = Lazy::new(|| { options: opts .clone() .set_experiment(Experiment::KEEP_UNINIT_ANNOTATIONS, true), - stop_after: StopAfter::BytecodePipeline(Some("uninitialized_use_checker")), + // Run the entire compiler pipeline to double-check the result + stop_after: StopAfter::FileFormat, dump_ast: DumpLevel::None, dump_bytecode: DumpLevel::AllStages, - dump_bytecode_filter: Some(vec![INITIAL_BYTECODE_STAGE, "uninitialized_use_checker"]), + dump_bytecode_filter: Some(vec![ + INITIAL_BYTECODE_STAGE, + "uninitialized_use_checker", + FILE_FORMAT_STAGE, + ]), }, // -- File Format Generation // Test without bytecode optimizations enabled diff --git a/third_party/move/move-compiler-v2/tests/uninit-use-checker/assign_both_branch.exp b/third_party/move/move-compiler-v2/tests/uninit-use-checker/assign_both_branch.exp index fa135c53f0cc4..d8ee05d270a80 100644 --- a/third_party/move/move-compiler-v2/tests/uninit-use-checker/assign_both_branch.exp +++ b/third_party/move/move-compiler-v2/tests/uninit-use-checker/assign_both_branch.exp @@ -50,3 +50,28 @@ fun m::test($t0: bool): u64 { # before: { maybe: $t3, $t4 }, after: { maybe: $t3, $t4 } 10: return $t1 } + + +============ disassembled file-format ================== +// Move bytecode v7 +module c0ffee.m { + + +test(Arg0: bool): u64 /* def_idx: 0 */ { +L1: loc0: u64 +B0: + 0: MoveLoc[0](Arg0: bool) + 1: BrFalse(6) +B1: + 2: LdU64(1) + 3: StLoc[1](loc0: u64) +B2: + 4: MoveLoc[1](loc0: u64) + 5: Ret +B3: + 6: LdU64(2) + 7: StLoc[1](loc0: u64) + 8: Branch(4) +} +} +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/uninit-use-checker/assign_in_one_if_branch_unfoldable.exp b/third_party/move/move-compiler-v2/tests/uninit-use-checker/assign_in_one_if_branch_unfoldable.exp index acfac3d8089ec..f67534e1f57b6 100644 --- a/third_party/move/move-compiler-v2/tests/uninit-use-checker/assign_in_one_if_branch_unfoldable.exp +++ b/third_party/move/move-compiler-v2/tests/uninit-use-checker/assign_in_one_if_branch_unfoldable.exp @@ -7,6 +7,7 @@ fun _0::main($t0: bool, $t1: bool) { var $t4: u64 var $t5: u64 var $t6: bool + var $t7: u64 0: if ($t0) goto 1 else goto 5 1: label L0 2: $t4 := 5 @@ -21,8 +22,9 @@ fun _0::main($t0: bool, $t1: bool) { 11: goto 13 12: label L4 13: label L5 - 14: $t6 := ==($t2, $t3) - 15: return () + 14: $t7 := infer($t2) + 15: $t6 := ==($t7, $t3) + 16: return () } @@ -31,7 +33,7 @@ error: use of possibly unassigned local `x` ┌─ tests/uninit-use-checker/assign_in_one_if_branch_unfoldable.move:7:5 │ 7 │ x == y; - │ ^^^^^^ + │ ^ error: use of possibly unassigned local `y` ┌─ tests/uninit-use-checker/assign_in_one_if_branch_unfoldable.move:7:5 @@ -48,36 +50,39 @@ fun _0::main($t0: bool, $t1: bool) { var $t4: u64 var $t5: u64 var $t6: bool - # before: { no: $t2, $t3, $t4, $t5, $t6 }, after: { no: $t2, $t3, $t4, $t5, $t6 } + var $t7: u64 + # before: { no: $t2, $t3, $t4, $t5, $t6, $t7 }, after: { no: $t2, $t3, $t4, $t5, $t6, $t7 } 0: if ($t0) goto 1 else goto 5 - # before: { no: $t2, $t3, $t4, $t5, $t6 }, after: { no: $t2, $t3, $t4, $t5, $t6 } + # before: { no: $t2, $t3, $t4, $t5, $t6, $t7 }, after: { no: $t2, $t3, $t4, $t5, $t6, $t7 } 1: label L0 - # before: { no: $t2, $t3, $t4, $t5, $t6 }, after: { no: $t2, $t3, $t5, $t6 } + # before: { no: $t2, $t3, $t4, $t5, $t6, $t7 }, after: { no: $t2, $t3, $t5, $t6, $t7 } 2: $t4 := 5 - # before: { no: $t2, $t3, $t5, $t6 }, after: { no: $t3, $t5, $t6 } + # before: { no: $t2, $t3, $t5, $t6, $t7 }, after: { no: $t3, $t5, $t6, $t7 } 3: $t2 := infer($t4) - # before: { no: $t3, $t5, $t6 }, after: { no: $t3, $t5, $t6 } + # before: { no: $t3, $t5, $t6, $t7 }, after: { no: $t3, $t5, $t6, $t7 } 4: goto 6 - # before: { no: $t2, $t3, $t4, $t5, $t6 }, after: { no: $t2, $t3, $t4, $t5, $t6 } + # before: { no: $t2, $t3, $t4, $t5, $t6, $t7 }, after: { no: $t2, $t3, $t4, $t5, $t6, $t7 } 5: label L1 - # before: { no: $t3, $t5, $t6 }{ maybe: $t2, $t4 }, after: { no: $t3, $t5, $t6 }{ maybe: $t2, $t4 } + # before: { no: $t3, $t5, $t6, $t7 }{ maybe: $t2, $t4 }, after: { no: $t3, $t5, $t6, $t7 }{ maybe: $t2, $t4 } 6: label L2 - # before: { no: $t3, $t5, $t6 }{ maybe: $t2, $t4 }, after: { no: $t3, $t5, $t6 }{ maybe: $t2, $t4 } + # before: { no: $t3, $t5, $t6, $t7 }{ maybe: $t2, $t4 }, after: { no: $t3, $t5, $t6, $t7 }{ maybe: $t2, $t4 } 7: if ($t1) goto 8 else goto 12 - # before: { no: $t3, $t5, $t6 }{ maybe: $t2, $t4 }, after: { no: $t3, $t5, $t6 }{ maybe: $t2, $t4 } + # before: { no: $t3, $t5, $t6, $t7 }{ maybe: $t2, $t4 }, after: { no: $t3, $t5, $t6, $t7 }{ maybe: $t2, $t4 } 8: label L3 - # before: { no: $t3, $t5, $t6 }{ maybe: $t2, $t4 }, after: { no: $t3, $t6 }{ maybe: $t2, $t4 } + # before: { no: $t3, $t5, $t6, $t7 }{ maybe: $t2, $t4 }, after: { no: $t3, $t6, $t7 }{ maybe: $t2, $t4 } 9: $t5 := 5 - # before: { no: $t3, $t6 }{ maybe: $t2, $t4 }, after: { no: $t6 }{ maybe: $t2, $t4 } + # before: { no: $t3, $t6, $t7 }{ maybe: $t2, $t4 }, after: { no: $t6, $t7 }{ maybe: $t2, $t4 } 10: $t3 := infer($t5) - # before: { no: $t6 }{ maybe: $t2, $t4 }, after: { no: $t6 }{ maybe: $t2, $t4 } + # before: { no: $t6, $t7 }{ maybe: $t2, $t4 }, after: { no: $t6, $t7 }{ maybe: $t2, $t4 } 11: goto 13 - # before: { no: $t3, $t5, $t6 }{ maybe: $t2, $t4 }, after: { no: $t3, $t5, $t6 }{ maybe: $t2, $t4 } + # before: { no: $t3, $t5, $t6, $t7 }{ maybe: $t2, $t4 }, after: { no: $t3, $t5, $t6, $t7 }{ maybe: $t2, $t4 } 12: label L4 - # before: { no: $t6 }{ maybe: $t2, $t3, $t4, $t5 }, after: { no: $t6 }{ maybe: $t2, $t3, $t4, $t5 } + # before: { no: $t6, $t7 }{ maybe: $t2, $t3, $t4, $t5 }, after: { no: $t6, $t7 }{ maybe: $t2, $t3, $t4, $t5 } 13: label L5 + # before: { no: $t6, $t7 }{ maybe: $t2, $t3, $t4, $t5 }, after: { no: $t6 }{ maybe: $t2, $t3, $t4, $t5 } + 14: $t7 := infer($t2) # before: { no: $t6 }{ maybe: $t2, $t3, $t4, $t5 }, after: { maybe: $t2, $t3, $t4, $t5 } - 14: $t6 := ==($t2, $t3) + 15: $t6 := ==($t7, $t3) # before: { maybe: $t2, $t3, $t4, $t5 }, after: { maybe: $t2, $t3, $t4, $t5 } - 15: return () + 16: return () } diff --git a/third_party/move/move-compiler-v2/tests/uninit-use-checker/assign_wrong_if_branch_no_else_unfoldable.exp b/third_party/move/move-compiler-v2/tests/uninit-use-checker/assign_wrong_if_branch_no_else_unfoldable.exp index 8abdd013b22da..bf4b77e716272 100644 --- a/third_party/move/move-compiler-v2/tests/uninit-use-checker/assign_wrong_if_branch_no_else_unfoldable.exp +++ b/third_party/move/move-compiler-v2/tests/uninit-use-checker/assign_wrong_if_branch_no_else_unfoldable.exp @@ -7,6 +7,7 @@ fun _0::main($t0: bool) { var $t3: bool var $t4: u64 var $t5: u64 + var $t6: u64 0: if ($t0) goto 1 else goto 5 1: label L0 2: $t2 := 100 @@ -14,16 +15,17 @@ fun _0::main($t0: bool) { 4: goto 6 5: label L1 6: label L2 - 7: $t4 := 100 - 8: $t3 := ==($t1, $t4) - 9: if ($t3) goto 10 else goto 12 - 10: label L3 - 11: goto 15 - 12: label L4 - 13: $t5 := 42 - 14: abort($t5) - 15: label L5 - 16: return () + 7: $t4 := infer($t1) + 8: $t5 := 100 + 9: $t3 := ==($t4, $t5) + 10: if ($t3) goto 11 else goto 13 + 11: label L3 + 12: goto 16 + 13: label L4 + 14: $t6 := 42 + 15: abort($t6) + 16: label L5 + 17: return () } @@ -32,7 +34,7 @@ error: use of possibly unassigned local `x` ┌─ tests/uninit-use-checker/assign_wrong_if_branch_no_else_unfoldable.move:5:13 │ 5 │ assert!(x == 100, 42); - │ ^^^^^^^^ + │ ^ ============ after uninitialized_use_checker: ================ @@ -43,38 +45,41 @@ fun _0::main($t0: bool) { var $t3: bool var $t4: u64 var $t5: u64 - # before: { no: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t1, $t2, $t3, $t4, $t5 } + var $t6: u64 + # before: { no: $t1, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t1, $t2, $t3, $t4, $t5, $t6 } 0: if ($t0) goto 1 else goto 5 - # before: { no: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t1, $t2, $t3, $t4, $t5 } + # before: { no: $t1, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t1, $t2, $t3, $t4, $t5, $t6 } 1: label L0 - # before: { no: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t1, $t3, $t4, $t5 } + # before: { no: $t1, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t1, $t3, $t4, $t5, $t6 } 2: $t2 := 100 - # before: { no: $t1, $t3, $t4, $t5 }, after: { no: $t3, $t4, $t5 } + # before: { no: $t1, $t3, $t4, $t5, $t6 }, after: { no: $t3, $t4, $t5, $t6 } 3: $t1 := infer($t2) - # before: { no: $t3, $t4, $t5 }, after: { no: $t3, $t4, $t5 } + # before: { no: $t3, $t4, $t5, $t6 }, after: { no: $t3, $t4, $t5, $t6 } 4: goto 6 - # before: { no: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t1, $t2, $t3, $t4, $t5 } + # before: { no: $t1, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t1, $t2, $t3, $t4, $t5, $t6 } 5: label L1 - # before: { no: $t3, $t4, $t5 }{ maybe: $t1, $t2 }, after: { no: $t3, $t4, $t5 }{ maybe: $t1, $t2 } + # before: { no: $t3, $t4, $t5, $t6 }{ maybe: $t1, $t2 }, after: { no: $t3, $t4, $t5, $t6 }{ maybe: $t1, $t2 } 6: label L2 - # before: { no: $t3, $t4, $t5 }{ maybe: $t1, $t2 }, after: { no: $t3, $t5 }{ maybe: $t1, $t2 } - 7: $t4 := 100 - # before: { no: $t3, $t5 }{ maybe: $t1, $t2 }, after: { no: $t5 }{ maybe: $t1, $t2 } - 8: $t3 := ==($t1, $t4) - # before: { no: $t5 }{ maybe: $t1, $t2 }, after: { no: $t5 }{ maybe: $t1, $t2 } - 9: if ($t3) goto 10 else goto 12 - # before: { no: $t5 }{ maybe: $t1, $t2 }, after: { no: $t5 }{ maybe: $t1, $t2 } - 10: label L3 - # before: { no: $t5 }{ maybe: $t1, $t2 }, after: { no: $t5 }{ maybe: $t1, $t2 } - 11: goto 15 - # before: { no: $t5 }{ maybe: $t1, $t2 }, after: { no: $t5 }{ maybe: $t1, $t2 } - 12: label L4 - # before: { no: $t5 }{ maybe: $t1, $t2 }, after: { maybe: $t1, $t2 } - 13: $t5 := 42 + # before: { no: $t3, $t4, $t5, $t6 }{ maybe: $t1, $t2 }, after: { no: $t3, $t5, $t6 }{ maybe: $t1, $t2 } + 7: $t4 := infer($t1) + # before: { no: $t3, $t5, $t6 }{ maybe: $t1, $t2 }, after: { no: $t3, $t6 }{ maybe: $t1, $t2 } + 8: $t5 := 100 + # before: { no: $t3, $t6 }{ maybe: $t1, $t2 }, after: { no: $t6 }{ maybe: $t1, $t2 } + 9: $t3 := ==($t4, $t5) + # before: { no: $t6 }{ maybe: $t1, $t2 }, after: { no: $t6 }{ maybe: $t1, $t2 } + 10: if ($t3) goto 11 else goto 13 + # before: { no: $t6 }{ maybe: $t1, $t2 }, after: { no: $t6 }{ maybe: $t1, $t2 } + 11: label L3 + # before: { no: $t6 }{ maybe: $t1, $t2 }, after: { no: $t6 }{ maybe: $t1, $t2 } + 12: goto 16 + # before: { no: $t6 }{ maybe: $t1, $t2 }, after: { no: $t6 }{ maybe: $t1, $t2 } + 13: label L4 + # before: { no: $t6 }{ maybe: $t1, $t2 }, after: { maybe: $t1, $t2 } + 14: $t6 := 42 # before: { maybe: $t1, $t2 }, after: { maybe: $t1, $t2 } - 14: abort($t5) - # before: { no: $t5 }{ maybe: $t1, $t2 }, after: { no: $t5 }{ maybe: $t1, $t2 } - 15: label L5 - # before: { no: $t5 }{ maybe: $t1, $t2 }, after: { no: $t5 }{ maybe: $t1, $t2 } - 16: return () + 15: abort($t6) + # before: { no: $t6 }{ maybe: $t1, $t2 }, after: { no: $t6 }{ maybe: $t1, $t2 } + 16: label L5 + # before: { no: $t6 }{ maybe: $t1, $t2 }, after: { no: $t6 }{ maybe: $t1, $t2 } + 17: return () } diff --git a/third_party/move/move-compiler-v2/tests/uninit-use-checker/assign_wrong_if_branch_unfoldable.exp b/third_party/move/move-compiler-v2/tests/uninit-use-checker/assign_wrong_if_branch_unfoldable.exp index 4e388d37bbc54..4b5851bb39079 100644 --- a/third_party/move/move-compiler-v2/tests/uninit-use-checker/assign_wrong_if_branch_unfoldable.exp +++ b/third_party/move/move-compiler-v2/tests/uninit-use-checker/assign_wrong_if_branch_unfoldable.exp @@ -7,6 +7,7 @@ fun _0::main($t0: bool) { var $t3: bool var $t4: u64 var $t5: u64 + var $t6: u64 0: if ($t0) goto 1 else goto 3 1: label L0 2: goto 6 @@ -14,16 +15,17 @@ fun _0::main($t0: bool) { 4: $t2 := 100 5: $t1 := infer($t2) 6: label L2 - 7: $t4 := 100 - 8: $t3 := ==($t1, $t4) - 9: if ($t3) goto 10 else goto 12 - 10: label L3 - 11: goto 15 - 12: label L4 - 13: $t5 := 42 - 14: abort($t5) - 15: label L5 - 16: return () + 7: $t4 := infer($t1) + 8: $t5 := 100 + 9: $t3 := ==($t4, $t5) + 10: if ($t3) goto 11 else goto 13 + 11: label L3 + 12: goto 16 + 13: label L4 + 14: $t6 := 42 + 15: abort($t6) + 16: label L5 + 17: return () } @@ -32,7 +34,7 @@ error: use of possibly unassigned local `x` ┌─ tests/uninit-use-checker/assign_wrong_if_branch_unfoldable.move:5:13 │ 5 │ assert!(x == 100, 42); - │ ^^^^^^^^ + │ ^ ============ after uninitialized_use_checker: ================ @@ -43,38 +45,41 @@ fun _0::main($t0: bool) { var $t3: bool var $t4: u64 var $t5: u64 - # before: { no: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t1, $t2, $t3, $t4, $t5 } + var $t6: u64 + # before: { no: $t1, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t1, $t2, $t3, $t4, $t5, $t6 } 0: if ($t0) goto 1 else goto 3 - # before: { no: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t1, $t2, $t3, $t4, $t5 } + # before: { no: $t1, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t1, $t2, $t3, $t4, $t5, $t6 } 1: label L0 - # before: { no: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t1, $t2, $t3, $t4, $t5 } + # before: { no: $t1, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t1, $t2, $t3, $t4, $t5, $t6 } 2: goto 6 - # before: { no: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t1, $t2, $t3, $t4, $t5 } + # before: { no: $t1, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t1, $t2, $t3, $t4, $t5, $t6 } 3: label L1 - # before: { no: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t1, $t3, $t4, $t5 } + # before: { no: $t1, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t1, $t3, $t4, $t5, $t6 } 4: $t2 := 100 - # before: { no: $t1, $t3, $t4, $t5 }, after: { no: $t3, $t4, $t5 } + # before: { no: $t1, $t3, $t4, $t5, $t6 }, after: { no: $t3, $t4, $t5, $t6 } 5: $t1 := infer($t2) - # before: { no: $t3, $t4, $t5 }{ maybe: $t1, $t2 }, after: { no: $t3, $t4, $t5 }{ maybe: $t1, $t2 } + # before: { no: $t3, $t4, $t5, $t6 }{ maybe: $t1, $t2 }, after: { no: $t3, $t4, $t5, $t6 }{ maybe: $t1, $t2 } 6: label L2 - # before: { no: $t3, $t4, $t5 }{ maybe: $t1, $t2 }, after: { no: $t3, $t5 }{ maybe: $t1, $t2 } - 7: $t4 := 100 - # before: { no: $t3, $t5 }{ maybe: $t1, $t2 }, after: { no: $t5 }{ maybe: $t1, $t2 } - 8: $t3 := ==($t1, $t4) - # before: { no: $t5 }{ maybe: $t1, $t2 }, after: { no: $t5 }{ maybe: $t1, $t2 } - 9: if ($t3) goto 10 else goto 12 - # before: { no: $t5 }{ maybe: $t1, $t2 }, after: { no: $t5 }{ maybe: $t1, $t2 } - 10: label L3 - # before: { no: $t5 }{ maybe: $t1, $t2 }, after: { no: $t5 }{ maybe: $t1, $t2 } - 11: goto 15 - # before: { no: $t5 }{ maybe: $t1, $t2 }, after: { no: $t5 }{ maybe: $t1, $t2 } - 12: label L4 - # before: { no: $t5 }{ maybe: $t1, $t2 }, after: { maybe: $t1, $t2 } - 13: $t5 := 42 + # before: { no: $t3, $t4, $t5, $t6 }{ maybe: $t1, $t2 }, after: { no: $t3, $t5, $t6 }{ maybe: $t1, $t2 } + 7: $t4 := infer($t1) + # before: { no: $t3, $t5, $t6 }{ maybe: $t1, $t2 }, after: { no: $t3, $t6 }{ maybe: $t1, $t2 } + 8: $t5 := 100 + # before: { no: $t3, $t6 }{ maybe: $t1, $t2 }, after: { no: $t6 }{ maybe: $t1, $t2 } + 9: $t3 := ==($t4, $t5) + # before: { no: $t6 }{ maybe: $t1, $t2 }, after: { no: $t6 }{ maybe: $t1, $t2 } + 10: if ($t3) goto 11 else goto 13 + # before: { no: $t6 }{ maybe: $t1, $t2 }, after: { no: $t6 }{ maybe: $t1, $t2 } + 11: label L3 + # before: { no: $t6 }{ maybe: $t1, $t2 }, after: { no: $t6 }{ maybe: $t1, $t2 } + 12: goto 16 + # before: { no: $t6 }{ maybe: $t1, $t2 }, after: { no: $t6 }{ maybe: $t1, $t2 } + 13: label L4 + # before: { no: $t6 }{ maybe: $t1, $t2 }, after: { maybe: $t1, $t2 } + 14: $t6 := 42 # before: { maybe: $t1, $t2 }, after: { maybe: $t1, $t2 } - 14: abort($t5) - # before: { no: $t5 }{ maybe: $t1, $t2 }, after: { no: $t5 }{ maybe: $t1, $t2 } - 15: label L5 - # before: { no: $t5 }{ maybe: $t1, $t2 }, after: { no: $t5 }{ maybe: $t1, $t2 } - 16: return () + 15: abort($t6) + # before: { no: $t6 }{ maybe: $t1, $t2 }, after: { no: $t6 }{ maybe: $t1, $t2 } + 16: label L5 + # before: { no: $t6 }{ maybe: $t1, $t2 }, after: { no: $t6 }{ maybe: $t1, $t2 } + 17: return () } diff --git a/third_party/move/move-compiler-v2/tests/uninit-use-checker/else_assigns_if_doesnt_unfoldable.exp b/third_party/move/move-compiler-v2/tests/uninit-use-checker/else_assigns_if_doesnt_unfoldable.exp index e3361d8af67e3..e9001f34e133d 100644 --- a/third_party/move/move-compiler-v2/tests/uninit-use-checker/else_assigns_if_doesnt_unfoldable.exp +++ b/third_party/move/move-compiler-v2/tests/uninit-use-checker/else_assigns_if_doesnt_unfoldable.exp @@ -10,6 +10,7 @@ fun _0::main($t0: bool) { var $t6: bool var $t7: u64 var $t8: u64 + var $t9: u64 0: if ($t0) goto 1 else goto 5 1: label L0 2: $t3 := 0 @@ -20,16 +21,17 @@ fun _0::main($t0: bool) { 7: $t1 := infer($t4) 8: $t5 := infer($t1) 9: label L2 - 10: $t7 := 0 - 11: $t6 := ==($t2, $t7) - 12: if ($t6) goto 13 else goto 15 - 13: label L3 - 14: goto 18 - 15: label L4 - 16: $t8 := 42 - 17: abort($t8) - 18: label L5 - 19: return () + 10: $t7 := infer($t2) + 11: $t8 := 0 + 12: $t6 := ==($t7, $t8) + 13: if ($t6) goto 14 else goto 16 + 14: label L3 + 15: goto 19 + 16: label L4 + 17: $t9 := 42 + 18: abort($t9) + 19: label L5 + 20: return () } @@ -38,7 +40,7 @@ error: use of possibly unassigned local `y` ┌─ tests/uninit-use-checker/else_assigns_if_doesnt_unfoldable.move:11:13 │ 11 │ assert!(y == 0, 42); - │ ^^^^^^ + │ ^ ============ after uninitialized_use_checker: ================ @@ -52,44 +54,47 @@ fun _0::main($t0: bool) { var $t6: bool var $t7: u64 var $t8: u64 - # before: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8 } + var $t9: u64 + # before: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9 } 0: if ($t0) goto 1 else goto 5 - # before: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8 } + # before: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9 } 1: label L0 - # before: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t1, $t2, $t4, $t5, $t6, $t7, $t8 } + # before: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t1, $t2, $t4, $t5, $t6, $t7, $t8, $t9 } 2: $t3 := 0 - # before: { no: $t1, $t2, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t1, $t4, $t5, $t6, $t7, $t8 } + # before: { no: $t1, $t2, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t1, $t4, $t5, $t6, $t7, $t8, $t9 } 3: $t2 := infer($t3) - # before: { no: $t1, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t1, $t4, $t5, $t6, $t7, $t8 } + # before: { no: $t1, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t1, $t4, $t5, $t6, $t7, $t8, $t9 } 4: goto 9 - # before: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8 } + # before: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9 } 5: label L1 - # before: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t1, $t2, $t3, $t5, $t6, $t7, $t8 } + # before: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t1, $t2, $t3, $t5, $t6, $t7, $t8, $t9 } 6: $t4 := 42 - # before: { no: $t1, $t2, $t3, $t5, $t6, $t7, $t8 }, after: { no: $t2, $t3, $t5, $t6, $t7, $t8 } + # before: { no: $t1, $t2, $t3, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t2, $t3, $t5, $t6, $t7, $t8, $t9 } 7: $t1 := infer($t4) - # before: { no: $t2, $t3, $t5, $t6, $t7, $t8 }, after: { no: $t2, $t3, $t6, $t7, $t8 } + # before: { no: $t2, $t3, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t2, $t3, $t6, $t7, $t8, $t9 } 8: $t5 := infer($t1) - # before: { no: $t6, $t7, $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t6, $t7, $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 } + # before: { no: $t6, $t7, $t8, $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t6, $t7, $t8, $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 } 9: label L2 - # before: { no: $t6, $t7, $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t6, $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 } - 10: $t7 := 0 - # before: { no: $t6, $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 } - 11: $t6 := ==($t2, $t7) - # before: { no: $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 } - 12: if ($t6) goto 13 else goto 15 - # before: { no: $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 } - 13: label L3 - # before: { no: $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 } - 14: goto 18 - # before: { no: $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 } - 15: label L4 - # before: { no: $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { maybe: $t1, $t2, $t3, $t4, $t5 } - 16: $t8 := 42 + # before: { no: $t6, $t7, $t8, $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t6, $t8, $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 } + 10: $t7 := infer($t2) + # before: { no: $t6, $t8, $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t6, $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 } + 11: $t8 := 0 + # before: { no: $t6, $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 } + 12: $t6 := ==($t7, $t8) + # before: { no: $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 } + 13: if ($t6) goto 14 else goto 16 + # before: { no: $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 } + 14: label L3 + # before: { no: $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 } + 15: goto 19 + # before: { no: $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 } + 16: label L4 + # before: { no: $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { maybe: $t1, $t2, $t3, $t4, $t5 } + 17: $t9 := 42 # before: { maybe: $t1, $t2, $t3, $t4, $t5 }, after: { maybe: $t1, $t2, $t3, $t4, $t5 } - 17: abort($t8) - # before: { no: $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 } - 18: label L5 - # before: { no: $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 } - 19: return () + 18: abort($t9) + # before: { no: $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 } + 19: label L5 + # before: { no: $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 } + 20: return () } diff --git a/third_party/move/move-compiler-v2/tests/uninit-use-checker/if_assigns_else_doesnt_unfoldable.exp b/third_party/move/move-compiler-v2/tests/uninit-use-checker/if_assigns_else_doesnt_unfoldable.exp index b00b8cdb1eca5..e98a531fe81d2 100644 --- a/third_party/move/move-compiler-v2/tests/uninit-use-checker/if_assigns_else_doesnt_unfoldable.exp +++ b/third_party/move/move-compiler-v2/tests/uninit-use-checker/if_assigns_else_doesnt_unfoldable.exp @@ -10,6 +10,7 @@ fun _0::main($t0: bool) { var $t6: bool var $t7: u64 var $t8: u64 + var $t9: u64 0: if ($t0) goto 1 else goto 5 1: label L0 2: $t3 := 42 @@ -20,16 +21,17 @@ fun _0::main($t0: bool) { 7: $t2 := infer($t4) 8: $t5 := infer($t2) 9: label L2 - 10: $t7 := 42 - 11: $t6 := ==($t1, $t7) - 12: if ($t6) goto 13 else goto 15 - 13: label L3 - 14: goto 18 - 15: label L4 - 16: $t8 := 42 - 17: abort($t8) - 18: label L5 - 19: return () + 10: $t7 := infer($t1) + 11: $t8 := 42 + 12: $t6 := ==($t7, $t8) + 13: if ($t6) goto 14 else goto 16 + 14: label L3 + 15: goto 19 + 16: label L4 + 17: $t9 := 42 + 18: abort($t9) + 19: label L5 + 20: return () } @@ -38,7 +40,7 @@ error: use of possibly unassigned local `x` ┌─ tests/uninit-use-checker/if_assigns_else_doesnt_unfoldable.move:11:13 │ 11 │ assert!(x == 42, 42); - │ ^^^^^^^ + │ ^ ============ after uninitialized_use_checker: ================ @@ -52,44 +54,47 @@ fun _0::main($t0: bool) { var $t6: bool var $t7: u64 var $t8: u64 - # before: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8 } + var $t9: u64 + # before: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9 } 0: if ($t0) goto 1 else goto 5 - # before: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8 } + # before: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9 } 1: label L0 - # before: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t1, $t2, $t4, $t5, $t6, $t7, $t8 } + # before: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t1, $t2, $t4, $t5, $t6, $t7, $t8, $t9 } 2: $t3 := 42 - # before: { no: $t1, $t2, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t2, $t4, $t5, $t6, $t7, $t8 } + # before: { no: $t1, $t2, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t2, $t4, $t5, $t6, $t7, $t8, $t9 } 3: $t1 := infer($t3) - # before: { no: $t2, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t2, $t4, $t5, $t6, $t7, $t8 } + # before: { no: $t2, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t2, $t4, $t5, $t6, $t7, $t8, $t9 } 4: goto 9 - # before: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8 } + # before: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9 } 5: label L1 - # before: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t1, $t2, $t3, $t5, $t6, $t7, $t8 } + # before: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t1, $t2, $t3, $t5, $t6, $t7, $t8, $t9 } 6: $t4 := 0 - # before: { no: $t1, $t2, $t3, $t5, $t6, $t7, $t8 }, after: { no: $t1, $t3, $t5, $t6, $t7, $t8 } + # before: { no: $t1, $t2, $t3, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t1, $t3, $t5, $t6, $t7, $t8, $t9 } 7: $t2 := infer($t4) - # before: { no: $t1, $t3, $t5, $t6, $t7, $t8 }, after: { no: $t1, $t3, $t6, $t7, $t8 } + # before: { no: $t1, $t3, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t1, $t3, $t6, $t7, $t8, $t9 } 8: $t5 := infer($t2) - # before: { no: $t6, $t7, $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t6, $t7, $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 } + # before: { no: $t6, $t7, $t8, $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t6, $t7, $t8, $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 } 9: label L2 - # before: { no: $t6, $t7, $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t6, $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 } - 10: $t7 := 42 - # before: { no: $t6, $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 } - 11: $t6 := ==($t1, $t7) - # before: { no: $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 } - 12: if ($t6) goto 13 else goto 15 - # before: { no: $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 } - 13: label L3 - # before: { no: $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 } - 14: goto 18 - # before: { no: $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 } - 15: label L4 - # before: { no: $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { maybe: $t1, $t2, $t3, $t4, $t5 } - 16: $t8 := 42 + # before: { no: $t6, $t7, $t8, $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t6, $t8, $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 } + 10: $t7 := infer($t1) + # before: { no: $t6, $t8, $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t6, $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 } + 11: $t8 := 42 + # before: { no: $t6, $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 } + 12: $t6 := ==($t7, $t8) + # before: { no: $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 } + 13: if ($t6) goto 14 else goto 16 + # before: { no: $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 } + 14: label L3 + # before: { no: $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 } + 15: goto 19 + # before: { no: $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 } + 16: label L4 + # before: { no: $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { maybe: $t1, $t2, $t3, $t4, $t5 } + 17: $t9 := 42 # before: { maybe: $t1, $t2, $t3, $t4, $t5 }, after: { maybe: $t1, $t2, $t3, $t4, $t5 } - 17: abort($t8) - # before: { no: $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 } - 18: label L5 - # before: { no: $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t8 }{ maybe: $t1, $t2, $t3, $t4, $t5 } - 19: return () + 18: abort($t9) + # before: { no: $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 } + 19: label L5 + # before: { no: $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t9 }{ maybe: $t1, $t2, $t3, $t4, $t5 } + 20: return () } diff --git a/third_party/move/move-compiler-v2/tests/uninit-use-checker/if_assigns_no_else_unfoldable.exp b/third_party/move/move-compiler-v2/tests/uninit-use-checker/if_assigns_no_else_unfoldable.exp index f47080df23cb0..197cc81858eb9 100644 --- a/third_party/move/move-compiler-v2/tests/uninit-use-checker/if_assigns_no_else_unfoldable.exp +++ b/third_party/move/move-compiler-v2/tests/uninit-use-checker/if_assigns_no_else_unfoldable.exp @@ -7,6 +7,7 @@ fun _0::main($t0: bool) { var $t3: bool var $t4: u64 var $t5: u64 + var $t6: u64 0: if ($t0) goto 1 else goto 5 1: label L0 2: $t2 := 42 @@ -14,16 +15,17 @@ fun _0::main($t0: bool) { 4: goto 6 5: label L1 6: label L2 - 7: $t4 := 42 - 8: $t3 := ==($t1, $t4) - 9: if ($t3) goto 10 else goto 12 - 10: label L3 - 11: goto 15 - 12: label L4 - 13: $t5 := 42 - 14: abort($t5) - 15: label L5 - 16: return () + 7: $t4 := infer($t1) + 8: $t5 := 42 + 9: $t3 := ==($t4, $t5) + 10: if ($t3) goto 11 else goto 13 + 11: label L3 + 12: goto 16 + 13: label L4 + 14: $t6 := 42 + 15: abort($t6) + 16: label L5 + 17: return () } @@ -32,7 +34,7 @@ error: use of possibly unassigned local `x` ┌─ tests/uninit-use-checker/if_assigns_no_else_unfoldable.move:5:13 │ 5 │ assert!(x == 42, 42); - │ ^^^^^^^ + │ ^ ============ after uninitialized_use_checker: ================ @@ -43,38 +45,41 @@ fun _0::main($t0: bool) { var $t3: bool var $t4: u64 var $t5: u64 - # before: { no: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t1, $t2, $t3, $t4, $t5 } + var $t6: u64 + # before: { no: $t1, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t1, $t2, $t3, $t4, $t5, $t6 } 0: if ($t0) goto 1 else goto 5 - # before: { no: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t1, $t2, $t3, $t4, $t5 } + # before: { no: $t1, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t1, $t2, $t3, $t4, $t5, $t6 } 1: label L0 - # before: { no: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t1, $t3, $t4, $t5 } + # before: { no: $t1, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t1, $t3, $t4, $t5, $t6 } 2: $t2 := 42 - # before: { no: $t1, $t3, $t4, $t5 }, after: { no: $t3, $t4, $t5 } + # before: { no: $t1, $t3, $t4, $t5, $t6 }, after: { no: $t3, $t4, $t5, $t6 } 3: $t1 := infer($t2) - # before: { no: $t3, $t4, $t5 }, after: { no: $t3, $t4, $t5 } + # before: { no: $t3, $t4, $t5, $t6 }, after: { no: $t3, $t4, $t5, $t6 } 4: goto 6 - # before: { no: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t1, $t2, $t3, $t4, $t5 } + # before: { no: $t1, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t1, $t2, $t3, $t4, $t5, $t6 } 5: label L1 - # before: { no: $t3, $t4, $t5 }{ maybe: $t1, $t2 }, after: { no: $t3, $t4, $t5 }{ maybe: $t1, $t2 } + # before: { no: $t3, $t4, $t5, $t6 }{ maybe: $t1, $t2 }, after: { no: $t3, $t4, $t5, $t6 }{ maybe: $t1, $t2 } 6: label L2 - # before: { no: $t3, $t4, $t5 }{ maybe: $t1, $t2 }, after: { no: $t3, $t5 }{ maybe: $t1, $t2 } - 7: $t4 := 42 - # before: { no: $t3, $t5 }{ maybe: $t1, $t2 }, after: { no: $t5 }{ maybe: $t1, $t2 } - 8: $t3 := ==($t1, $t4) - # before: { no: $t5 }{ maybe: $t1, $t2 }, after: { no: $t5 }{ maybe: $t1, $t2 } - 9: if ($t3) goto 10 else goto 12 - # before: { no: $t5 }{ maybe: $t1, $t2 }, after: { no: $t5 }{ maybe: $t1, $t2 } - 10: label L3 - # before: { no: $t5 }{ maybe: $t1, $t2 }, after: { no: $t5 }{ maybe: $t1, $t2 } - 11: goto 15 - # before: { no: $t5 }{ maybe: $t1, $t2 }, after: { no: $t5 }{ maybe: $t1, $t2 } - 12: label L4 - # before: { no: $t5 }{ maybe: $t1, $t2 }, after: { maybe: $t1, $t2 } - 13: $t5 := 42 + # before: { no: $t3, $t4, $t5, $t6 }{ maybe: $t1, $t2 }, after: { no: $t3, $t5, $t6 }{ maybe: $t1, $t2 } + 7: $t4 := infer($t1) + # before: { no: $t3, $t5, $t6 }{ maybe: $t1, $t2 }, after: { no: $t3, $t6 }{ maybe: $t1, $t2 } + 8: $t5 := 42 + # before: { no: $t3, $t6 }{ maybe: $t1, $t2 }, after: { no: $t6 }{ maybe: $t1, $t2 } + 9: $t3 := ==($t4, $t5) + # before: { no: $t6 }{ maybe: $t1, $t2 }, after: { no: $t6 }{ maybe: $t1, $t2 } + 10: if ($t3) goto 11 else goto 13 + # before: { no: $t6 }{ maybe: $t1, $t2 }, after: { no: $t6 }{ maybe: $t1, $t2 } + 11: label L3 + # before: { no: $t6 }{ maybe: $t1, $t2 }, after: { no: $t6 }{ maybe: $t1, $t2 } + 12: goto 16 + # before: { no: $t6 }{ maybe: $t1, $t2 }, after: { no: $t6 }{ maybe: $t1, $t2 } + 13: label L4 + # before: { no: $t6 }{ maybe: $t1, $t2 }, after: { maybe: $t1, $t2 } + 14: $t6 := 42 # before: { maybe: $t1, $t2 }, after: { maybe: $t1, $t2 } - 14: abort($t5) - # before: { no: $t5 }{ maybe: $t1, $t2 }, after: { no: $t5 }{ maybe: $t1, $t2 } - 15: label L5 - # before: { no: $t5 }{ maybe: $t1, $t2 }, after: { no: $t5 }{ maybe: $t1, $t2 } - 16: return () + 15: abort($t6) + # before: { no: $t6 }{ maybe: $t1, $t2 }, after: { no: $t6 }{ maybe: $t1, $t2 } + 16: label L5 + # before: { no: $t6 }{ maybe: $t1, $t2 }, after: { no: $t6 }{ maybe: $t1, $t2 } + 17: return () } diff --git a/third_party/move/move-compiler-v2/tests/uninit-use-checker/no_error.exp b/third_party/move/move-compiler-v2/tests/uninit-use-checker/no_error.exp index 607fec561177c..72ecdcfd22bea 100644 --- a/third_party/move/move-compiler-v2/tests/uninit-use-checker/no_error.exp +++ b/third_party/move/move-compiler-v2/tests/uninit-use-checker/no_error.exp @@ -8,13 +8,19 @@ fun m::foo($t0: u64, $t1: u64): u64 { var $t5: u64 var $t6: u64 var $t7: u64 - 0: $t3 := +($t0, $t1) - 1: $t5 := 1 - 2: $t4 := +($t3, $t5) + var $t8: u64 + var $t9: u64 + var $t10: u64 + 0: $t4 := infer($t0) + 1: $t3 := +($t4, $t1) + 2: $t6 := infer($t3) 3: $t7 := 1 - 4: $t6 := +($t4, $t7) - 5: $t2 := infer($t6) - 6: return $t2 + 4: $t5 := +($t6, $t7) + 5: $t9 := infer($t5) + 6: $t10 := 1 + 7: $t8 := +($t9, $t10) + 8: $t2 := infer($t8) + 9: return $t2 } ============ after uninitialized_use_checker: ================ @@ -27,18 +33,47 @@ fun m::foo($t0: u64, $t1: u64): u64 { var $t5: u64 var $t6: u64 var $t7: u64 - # before: { no: $t2, $t3, $t4, $t5, $t6, $t7 }, after: { no: $t2, $t4, $t5, $t6, $t7 } - 0: $t3 := +($t0, $t1) - # before: { no: $t2, $t4, $t5, $t6, $t7 }, after: { no: $t2, $t4, $t6, $t7 } - 1: $t5 := 1 - # before: { no: $t2, $t4, $t6, $t7 }, after: { no: $t2, $t6, $t7 } - 2: $t4 := +($t3, $t5) - # before: { no: $t2, $t6, $t7 }, after: { no: $t2, $t6 } + var $t8: u64 + var $t9: u64 + var $t10: u64 + # before: { no: $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9, $t10 }, after: { no: $t2, $t3, $t5, $t6, $t7, $t8, $t9, $t10 } + 0: $t4 := infer($t0) + # before: { no: $t2, $t3, $t5, $t6, $t7, $t8, $t9, $t10 }, after: { no: $t2, $t5, $t6, $t7, $t8, $t9, $t10 } + 1: $t3 := +($t4, $t1) + # before: { no: $t2, $t5, $t6, $t7, $t8, $t9, $t10 }, after: { no: $t2, $t5, $t7, $t8, $t9, $t10 } + 2: $t6 := infer($t3) + # before: { no: $t2, $t5, $t7, $t8, $t9, $t10 }, after: { no: $t2, $t5, $t8, $t9, $t10 } 3: $t7 := 1 - # before: { no: $t2, $t6 }, after: { no: $t2 } - 4: $t6 := +($t4, $t7) + # before: { no: $t2, $t5, $t8, $t9, $t10 }, after: { no: $t2, $t8, $t9, $t10 } + 4: $t5 := +($t6, $t7) + # before: { no: $t2, $t8, $t9, $t10 }, after: { no: $t2, $t8, $t10 } + 5: $t9 := infer($t5) + # before: { no: $t2, $t8, $t10 }, after: { no: $t2, $t8 } + 6: $t10 := 1 + # before: { no: $t2, $t8 }, after: { no: $t2 } + 7: $t8 := +($t9, $t10) # before: { no: $t2 }, after: all initialized - 5: $t2 := infer($t6) + 8: $t2 := infer($t8) # before: all initialized, after: all initialized - 6: return $t2 + 9: return $t2 } + + +============ disassembled file-format ================== +// Move bytecode v7 +module c0.m { + + +foo(Arg0: u64, Arg1: u64): u64 /* def_idx: 0 */ { +B0: + 0: MoveLoc[0](Arg0: u64) + 1: MoveLoc[1](Arg1: u64) + 2: Add + 3: LdU64(1) + 4: Add + 5: LdU64(1) + 6: Add + 7: Ret +} +} +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/uninit-use-checker/use_twice_before_assign.exp b/third_party/move/move-compiler-v2/tests/uninit-use-checker/use_twice_before_assign.exp index c8037ab3914d8..ed183b0159ca1 100644 --- a/third_party/move/move-compiler-v2/tests/uninit-use-checker/use_twice_before_assign.exp +++ b/third_party/move/move-compiler-v2/tests/uninit-use-checker/use_twice_before_assign.exp @@ -12,12 +12,20 @@ warning: Unused local variable `y`. Consider removing or prefixing with an under fun _0::main() { var $t0: u64 var $t1: u64 - 0: $t1 := +($t0, $t0) - 1: return () + var $t2: u64 + 0: $t2 := infer($t0) + 1: $t1 := +($t2, $t0) + 2: return () } Diagnostics: +error: use of unassigned local `x` + ┌─ tests/uninit-use-checker/use_twice_before_assign.move:4:13 + │ +4 │ let y = x + x; + │ ^ + error: use of unassigned local `x` ┌─ tests/uninit-use-checker/use_twice_before_assign.move:4:13 │ @@ -30,8 +38,11 @@ error: use of unassigned local `x` fun _0::main() { var $t0: u64 var $t1: u64 + var $t2: u64 + # before: { no: $t0, $t1, $t2 }, after: { no: $t0, $t1 } + 0: $t2 := infer($t0) # before: { no: $t0, $t1 }, after: { no: $t0 } - 0: $t1 := +($t0, $t0) + 1: $t1 := +($t2, $t0) # before: { no: $t0 }, after: { no: $t0 } - 1: return () + 2: return () } diff --git a/third_party/move/move-compiler-v2/tests/uninit-use-checker/uses_before_assign.exp b/third_party/move/move-compiler-v2/tests/uninit-use-checker/uses_before_assign.exp index d3801de716820..a3d2e93a5c211 100644 --- a/third_party/move/move-compiler-v2/tests/uninit-use-checker/uses_before_assign.exp +++ b/third_party/move/move-compiler-v2/tests/uninit-use-checker/uses_before_assign.exp @@ -13,8 +13,10 @@ fun _0::main() { var $t0: u64 var $t1: u64 var $t2: u64 - 0: $t2 := +($t0, $t1) - 1: return () + var $t3: u64 + 0: $t3 := infer($t0) + 1: $t2 := +($t3, $t1) + 2: return () } @@ -23,7 +25,7 @@ error: use of unassigned local `x` ┌─ tests/uninit-use-checker/uses_before_assign.move:5:13 │ 5 │ let z = x + y; - │ ^^^^^ + │ ^ error: use of unassigned local `y` ┌─ tests/uninit-use-checker/uses_before_assign.move:5:13 @@ -38,8 +40,11 @@ fun _0::main() { var $t0: u64 var $t1: u64 var $t2: u64 + var $t3: u64 + # before: { no: $t0, $t1, $t2, $t3 }, after: { no: $t0, $t1, $t2 } + 0: $t3 := infer($t0) # before: { no: $t0, $t1, $t2 }, after: { no: $t0, $t1 } - 0: $t2 := +($t0, $t1) + 1: $t2 := +($t3, $t1) # before: { no: $t0, $t1 }, after: { no: $t0, $t1 } - 1: return () + 2: return () } diff --git a/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-borrows/eq_unassigned_local.exp b/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-borrows/eq_unassigned_local.exp index 20bf8e77052d9..12641727eb50c 100644 --- a/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-borrows/eq_unassigned_local.exp +++ b/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-borrows/eq_unassigned_local.exp @@ -5,11 +5,13 @@ fun _0::main() { var $t0: &u64 var $t1: bool var $t2: &u64 - var $t3: u64 - 0: $t3 := 5 - 1: $t2 := borrow_local($t3) - 2: $t1 := ==($t0, $t2) - 3: return () + var $t3: &u64 + var $t4: u64 + 0: $t2 := infer($t0) + 1: $t4 := 5 + 2: $t3 := borrow_local($t4) + 3: $t1 := ==($t2, $t3) + 4: return () } @@ -18,7 +20,7 @@ error: use of unassigned local `ref` ┌─ tests/uninit-use-checker/v1-borrows/eq_unassigned_local.move:5:9 │ 5 │ ref == &x; - │ ^^^^^^^^^ + │ ^^^ ============ after uninitialized_use_checker: ================ @@ -27,13 +29,16 @@ fun _0::main() { var $t0: &u64 var $t1: bool var $t2: &u64 - var $t3: u64 - # before: { no: $t0, $t1, $t2, $t3 }, after: { no: $t0, $t1, $t2 } - 0: $t3 := 5 - # before: { no: $t0, $t1, $t2 }, after: { no: $t0, $t1 } - 1: $t2 := borrow_local($t3) + var $t3: &u64 + var $t4: u64 + # before: { no: $t0, $t1, $t2, $t3, $t4 }, after: { no: $t0, $t1, $t3, $t4 } + 0: $t2 := infer($t0) + # before: { no: $t0, $t1, $t3, $t4 }, after: { no: $t0, $t1, $t3 } + 1: $t4 := 5 + # before: { no: $t0, $t1, $t3 }, after: { no: $t0, $t1 } + 2: $t3 := borrow_local($t4) # before: { no: $t0, $t1 }, after: { no: $t0 } - 2: $t1 := ==($t0, $t2) + 3: $t1 := ==($t2, $t3) # before: { no: $t0 }, after: { no: $t0 } - 3: return () + 4: return () } diff --git a/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-commands/assign_in_one_if_branch.exp b/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-commands/assign_in_one_if_branch.exp index a31e27277d3fd..cfd1b431a9941 100644 --- a/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-commands/assign_in_one_if_branch.exp +++ b/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-commands/assign_in_one_if_branch.exp @@ -9,6 +9,7 @@ fun _0::main() { var $t4: bool var $t5: u64 var $t6: bool + var $t7: u64 0: $t2 := true 1: if ($t2) goto 2 else goto 6 2: label L0 @@ -25,8 +26,9 @@ fun _0::main() { 13: goto 15 14: label L4 15: label L5 - 16: $t6 := ==($t0, $t1) - 17: return () + 16: $t7 := infer($t0) + 17: $t6 := ==($t7, $t1) + 18: return () } @@ -35,7 +37,7 @@ error: use of possibly unassigned local `x` ┌─ tests/uninit-use-checker/v1-commands/assign_in_one_if_branch.move:7:5 │ 7 │ x == y; - │ ^^^^^^ + │ ^ error: use of possibly unassigned local `y` ┌─ tests/uninit-use-checker/v1-commands/assign_in_one_if_branch.move:7:5 @@ -54,40 +56,43 @@ fun _0::main() { var $t4: bool var $t5: u64 var $t6: bool - # before: { no: $t0, $t1, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t0, $t1, $t3, $t4, $t5, $t6 } + var $t7: u64 + # before: { no: $t0, $t1, $t2, $t3, $t4, $t5, $t6, $t7 }, after: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7 } 0: $t2 := true - # before: { no: $t0, $t1, $t3, $t4, $t5, $t6 }, after: { no: $t0, $t1, $t3, $t4, $t5, $t6 } + # before: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7 }, after: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7 } 1: if ($t2) goto 2 else goto 6 - # before: { no: $t0, $t1, $t3, $t4, $t5, $t6 }, after: { no: $t0, $t1, $t3, $t4, $t5, $t6 } + # before: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7 }, after: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7 } 2: label L0 - # before: { no: $t0, $t1, $t3, $t4, $t5, $t6 }, after: { no: $t0, $t1, $t4, $t5, $t6 } + # before: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7 }, after: { no: $t0, $t1, $t4, $t5, $t6, $t7 } 3: $t3 := 5 - # before: { no: $t0, $t1, $t4, $t5, $t6 }, after: { no: $t1, $t4, $t5, $t6 } + # before: { no: $t0, $t1, $t4, $t5, $t6, $t7 }, after: { no: $t1, $t4, $t5, $t6, $t7 } 4: $t0 := infer($t3) - # before: { no: $t1, $t4, $t5, $t6 }, after: { no: $t1, $t4, $t5, $t6 } + # before: { no: $t1, $t4, $t5, $t6, $t7 }, after: { no: $t1, $t4, $t5, $t6, $t7 } 5: goto 7 - # before: { no: $t0, $t1, $t3, $t4, $t5, $t6 }, after: { no: $t0, $t1, $t3, $t4, $t5, $t6 } + # before: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7 }, after: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7 } 6: label L1 - # before: { no: $t1, $t4, $t5, $t6 }{ maybe: $t0, $t3 }, after: { no: $t1, $t4, $t5, $t6 }{ maybe: $t0, $t3 } + # before: { no: $t1, $t4, $t5, $t6, $t7 }{ maybe: $t0, $t3 }, after: { no: $t1, $t4, $t5, $t6, $t7 }{ maybe: $t0, $t3 } 7: label L2 - # before: { no: $t1, $t4, $t5, $t6 }{ maybe: $t0, $t3 }, after: { no: $t1, $t5, $t6 }{ maybe: $t0, $t3 } + # before: { no: $t1, $t4, $t5, $t6, $t7 }{ maybe: $t0, $t3 }, after: { no: $t1, $t5, $t6, $t7 }{ maybe: $t0, $t3 } 8: $t4 := true - # before: { no: $t1, $t5, $t6 }{ maybe: $t0, $t3 }, after: { no: $t1, $t5, $t6 }{ maybe: $t0, $t3 } + # before: { no: $t1, $t5, $t6, $t7 }{ maybe: $t0, $t3 }, after: { no: $t1, $t5, $t6, $t7 }{ maybe: $t0, $t3 } 9: if ($t4) goto 10 else goto 14 - # before: { no: $t1, $t5, $t6 }{ maybe: $t0, $t3 }, after: { no: $t1, $t5, $t6 }{ maybe: $t0, $t3 } + # before: { no: $t1, $t5, $t6, $t7 }{ maybe: $t0, $t3 }, after: { no: $t1, $t5, $t6, $t7 }{ maybe: $t0, $t3 } 10: label L3 - # before: { no: $t1, $t5, $t6 }{ maybe: $t0, $t3 }, after: { no: $t1, $t6 }{ maybe: $t0, $t3 } + # before: { no: $t1, $t5, $t6, $t7 }{ maybe: $t0, $t3 }, after: { no: $t1, $t6, $t7 }{ maybe: $t0, $t3 } 11: $t5 := 5 - # before: { no: $t1, $t6 }{ maybe: $t0, $t3 }, after: { no: $t6 }{ maybe: $t0, $t3 } + # before: { no: $t1, $t6, $t7 }{ maybe: $t0, $t3 }, after: { no: $t6, $t7 }{ maybe: $t0, $t3 } 12: $t1 := infer($t5) - # before: { no: $t6 }{ maybe: $t0, $t3 }, after: { no: $t6 }{ maybe: $t0, $t3 } + # before: { no: $t6, $t7 }{ maybe: $t0, $t3 }, after: { no: $t6, $t7 }{ maybe: $t0, $t3 } 13: goto 15 - # before: { no: $t1, $t5, $t6 }{ maybe: $t0, $t3 }, after: { no: $t1, $t5, $t6 }{ maybe: $t0, $t3 } + # before: { no: $t1, $t5, $t6, $t7 }{ maybe: $t0, $t3 }, after: { no: $t1, $t5, $t6, $t7 }{ maybe: $t0, $t3 } 14: label L4 - # before: { no: $t6 }{ maybe: $t0, $t1, $t3, $t5 }, after: { no: $t6 }{ maybe: $t0, $t1, $t3, $t5 } + # before: { no: $t6, $t7 }{ maybe: $t0, $t1, $t3, $t5 }, after: { no: $t6, $t7 }{ maybe: $t0, $t1, $t3, $t5 } 15: label L5 + # before: { no: $t6, $t7 }{ maybe: $t0, $t1, $t3, $t5 }, after: { no: $t6 }{ maybe: $t0, $t1, $t3, $t5 } + 16: $t7 := infer($t0) # before: { no: $t6 }{ maybe: $t0, $t1, $t3, $t5 }, after: { maybe: $t0, $t1, $t3, $t5 } - 16: $t6 := ==($t0, $t1) + 17: $t6 := ==($t7, $t1) # before: { maybe: $t0, $t1, $t3, $t5 }, after: { maybe: $t0, $t1, $t3, $t5 } - 17: return () + 18: return () } diff --git a/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-commands/assign_wrong_if_branch.exp b/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-commands/assign_wrong_if_branch.exp index 7598b364f73bd..c363492dc9e81 100644 --- a/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-commands/assign_wrong_if_branch.exp +++ b/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-commands/assign_wrong_if_branch.exp @@ -8,6 +8,7 @@ fun _0::main() { var $t3: bool var $t4: u64 var $t5: u64 + var $t6: u64 0: $t1 := true 1: if ($t1) goto 2 else goto 4 2: label L0 @@ -16,16 +17,17 @@ fun _0::main() { 5: $t2 := 100 6: $t0 := infer($t2) 7: label L2 - 8: $t4 := 100 - 9: $t3 := ==($t0, $t4) - 10: if ($t3) goto 11 else goto 13 - 11: label L3 - 12: goto 16 - 13: label L4 - 14: $t5 := 42 - 15: abort($t5) - 16: label L5 - 17: return () + 8: $t4 := infer($t0) + 9: $t5 := 100 + 10: $t3 := ==($t4, $t5) + 11: if ($t3) goto 12 else goto 14 + 12: label L3 + 13: goto 17 + 14: label L4 + 15: $t6 := 42 + 16: abort($t6) + 17: label L5 + 18: return () } @@ -34,7 +36,7 @@ error: use of possibly unassigned local `x` ┌─ tests/uninit-use-checker/v1-commands/assign_wrong_if_branch.move:5:13 │ 5 │ assert!(x == 100, 42); - │ ^^^^^^^^ + │ ^ ============ after uninitialized_use_checker: ================ @@ -46,40 +48,43 @@ fun _0::main() { var $t3: bool var $t4: u64 var $t5: u64 - # before: { no: $t0, $t1, $t2, $t3, $t4, $t5 }, after: { no: $t0, $t2, $t3, $t4, $t5 } + var $t6: u64 + # before: { no: $t0, $t1, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t0, $t2, $t3, $t4, $t5, $t6 } 0: $t1 := true - # before: { no: $t0, $t2, $t3, $t4, $t5 }, after: { no: $t0, $t2, $t3, $t4, $t5 } + # before: { no: $t0, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t0, $t2, $t3, $t4, $t5, $t6 } 1: if ($t1) goto 2 else goto 4 - # before: { no: $t0, $t2, $t3, $t4, $t5 }, after: { no: $t0, $t2, $t3, $t4, $t5 } + # before: { no: $t0, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t0, $t2, $t3, $t4, $t5, $t6 } 2: label L0 - # before: { no: $t0, $t2, $t3, $t4, $t5 }, after: { no: $t0, $t2, $t3, $t4, $t5 } + # before: { no: $t0, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t0, $t2, $t3, $t4, $t5, $t6 } 3: goto 7 - # before: { no: $t0, $t2, $t3, $t4, $t5 }, after: { no: $t0, $t2, $t3, $t4, $t5 } + # before: { no: $t0, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t0, $t2, $t3, $t4, $t5, $t6 } 4: label L1 - # before: { no: $t0, $t2, $t3, $t4, $t5 }, after: { no: $t0, $t3, $t4, $t5 } + # before: { no: $t0, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t0, $t3, $t4, $t5, $t6 } 5: $t2 := 100 - # before: { no: $t0, $t3, $t4, $t5 }, after: { no: $t3, $t4, $t5 } + # before: { no: $t0, $t3, $t4, $t5, $t6 }, after: { no: $t3, $t4, $t5, $t6 } 6: $t0 := infer($t2) - # before: { no: $t3, $t4, $t5 }{ maybe: $t0, $t2 }, after: { no: $t3, $t4, $t5 }{ maybe: $t0, $t2 } + # before: { no: $t3, $t4, $t5, $t6 }{ maybe: $t0, $t2 }, after: { no: $t3, $t4, $t5, $t6 }{ maybe: $t0, $t2 } 7: label L2 - # before: { no: $t3, $t4, $t5 }{ maybe: $t0, $t2 }, after: { no: $t3, $t5 }{ maybe: $t0, $t2 } - 8: $t4 := 100 - # before: { no: $t3, $t5 }{ maybe: $t0, $t2 }, after: { no: $t5 }{ maybe: $t0, $t2 } - 9: $t3 := ==($t0, $t4) - # before: { no: $t5 }{ maybe: $t0, $t2 }, after: { no: $t5 }{ maybe: $t0, $t2 } - 10: if ($t3) goto 11 else goto 13 - # before: { no: $t5 }{ maybe: $t0, $t2 }, after: { no: $t5 }{ maybe: $t0, $t2 } - 11: label L3 - # before: { no: $t5 }{ maybe: $t0, $t2 }, after: { no: $t5 }{ maybe: $t0, $t2 } - 12: goto 16 - # before: { no: $t5 }{ maybe: $t0, $t2 }, after: { no: $t5 }{ maybe: $t0, $t2 } - 13: label L4 - # before: { no: $t5 }{ maybe: $t0, $t2 }, after: { maybe: $t0, $t2 } - 14: $t5 := 42 + # before: { no: $t3, $t4, $t5, $t6 }{ maybe: $t0, $t2 }, after: { no: $t3, $t5, $t6 }{ maybe: $t0, $t2 } + 8: $t4 := infer($t0) + # before: { no: $t3, $t5, $t6 }{ maybe: $t0, $t2 }, after: { no: $t3, $t6 }{ maybe: $t0, $t2 } + 9: $t5 := 100 + # before: { no: $t3, $t6 }{ maybe: $t0, $t2 }, after: { no: $t6 }{ maybe: $t0, $t2 } + 10: $t3 := ==($t4, $t5) + # before: { no: $t6 }{ maybe: $t0, $t2 }, after: { no: $t6 }{ maybe: $t0, $t2 } + 11: if ($t3) goto 12 else goto 14 + # before: { no: $t6 }{ maybe: $t0, $t2 }, after: { no: $t6 }{ maybe: $t0, $t2 } + 12: label L3 + # before: { no: $t6 }{ maybe: $t0, $t2 }, after: { no: $t6 }{ maybe: $t0, $t2 } + 13: goto 17 + # before: { no: $t6 }{ maybe: $t0, $t2 }, after: { no: $t6 }{ maybe: $t0, $t2 } + 14: label L4 + # before: { no: $t6 }{ maybe: $t0, $t2 }, after: { maybe: $t0, $t2 } + 15: $t6 := 42 # before: { maybe: $t0, $t2 }, after: { maybe: $t0, $t2 } - 15: abort($t5) - # before: { no: $t5 }{ maybe: $t0, $t2 }, after: { no: $t5 }{ maybe: $t0, $t2 } - 16: label L5 - # before: { no: $t5 }{ maybe: $t0, $t2 }, after: { no: $t5 }{ maybe: $t0, $t2 } - 17: return () + 16: abort($t6) + # before: { no: $t6 }{ maybe: $t0, $t2 }, after: { no: $t6 }{ maybe: $t0, $t2 } + 17: label L5 + # before: { no: $t6 }{ maybe: $t0, $t2 }, after: { no: $t6 }{ maybe: $t0, $t2 } + 18: return () } diff --git a/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-commands/assign_wrong_if_branch_no_else.exp b/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-commands/assign_wrong_if_branch_no_else.exp index 9cf7420d46e5e..f68e7034cd275 100644 --- a/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-commands/assign_wrong_if_branch_no_else.exp +++ b/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-commands/assign_wrong_if_branch_no_else.exp @@ -8,6 +8,7 @@ fun _0::main() { var $t3: bool var $t4: u64 var $t5: u64 + var $t6: u64 0: $t1 := false 1: if ($t1) goto 2 else goto 6 2: label L0 @@ -16,16 +17,17 @@ fun _0::main() { 5: goto 7 6: label L1 7: label L2 - 8: $t4 := 100 - 9: $t3 := ==($t0, $t4) - 10: if ($t3) goto 11 else goto 13 - 11: label L3 - 12: goto 16 - 13: label L4 - 14: $t5 := 42 - 15: abort($t5) - 16: label L5 - 17: return () + 8: $t4 := infer($t0) + 9: $t5 := 100 + 10: $t3 := ==($t4, $t5) + 11: if ($t3) goto 12 else goto 14 + 12: label L3 + 13: goto 17 + 14: label L4 + 15: $t6 := 42 + 16: abort($t6) + 17: label L5 + 18: return () } @@ -34,7 +36,7 @@ error: use of possibly unassigned local `x` ┌─ tests/uninit-use-checker/v1-commands/assign_wrong_if_branch_no_else.move:5:13 │ 5 │ assert!(x == 100, 42); - │ ^^^^^^^^ + │ ^ ============ after uninitialized_use_checker: ================ @@ -46,40 +48,43 @@ fun _0::main() { var $t3: bool var $t4: u64 var $t5: u64 - # before: { no: $t0, $t1, $t2, $t3, $t4, $t5 }, after: { no: $t0, $t2, $t3, $t4, $t5 } + var $t6: u64 + # before: { no: $t0, $t1, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t0, $t2, $t3, $t4, $t5, $t6 } 0: $t1 := false - # before: { no: $t0, $t2, $t3, $t4, $t5 }, after: { no: $t0, $t2, $t3, $t4, $t5 } + # before: { no: $t0, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t0, $t2, $t3, $t4, $t5, $t6 } 1: if ($t1) goto 2 else goto 6 - # before: { no: $t0, $t2, $t3, $t4, $t5 }, after: { no: $t0, $t2, $t3, $t4, $t5 } + # before: { no: $t0, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t0, $t2, $t3, $t4, $t5, $t6 } 2: label L0 - # before: { no: $t0, $t2, $t3, $t4, $t5 }, after: { no: $t0, $t3, $t4, $t5 } + # before: { no: $t0, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t0, $t3, $t4, $t5, $t6 } 3: $t2 := 100 - # before: { no: $t0, $t3, $t4, $t5 }, after: { no: $t3, $t4, $t5 } + # before: { no: $t0, $t3, $t4, $t5, $t6 }, after: { no: $t3, $t4, $t5, $t6 } 4: $t0 := infer($t2) - # before: { no: $t3, $t4, $t5 }, after: { no: $t3, $t4, $t5 } + # before: { no: $t3, $t4, $t5, $t6 }, after: { no: $t3, $t4, $t5, $t6 } 5: goto 7 - # before: { no: $t0, $t2, $t3, $t4, $t5 }, after: { no: $t0, $t2, $t3, $t4, $t5 } + # before: { no: $t0, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t0, $t2, $t3, $t4, $t5, $t6 } 6: label L1 - # before: { no: $t3, $t4, $t5 }{ maybe: $t0, $t2 }, after: { no: $t3, $t4, $t5 }{ maybe: $t0, $t2 } + # before: { no: $t3, $t4, $t5, $t6 }{ maybe: $t0, $t2 }, after: { no: $t3, $t4, $t5, $t6 }{ maybe: $t0, $t2 } 7: label L2 - # before: { no: $t3, $t4, $t5 }{ maybe: $t0, $t2 }, after: { no: $t3, $t5 }{ maybe: $t0, $t2 } - 8: $t4 := 100 - # before: { no: $t3, $t5 }{ maybe: $t0, $t2 }, after: { no: $t5 }{ maybe: $t0, $t2 } - 9: $t3 := ==($t0, $t4) - # before: { no: $t5 }{ maybe: $t0, $t2 }, after: { no: $t5 }{ maybe: $t0, $t2 } - 10: if ($t3) goto 11 else goto 13 - # before: { no: $t5 }{ maybe: $t0, $t2 }, after: { no: $t5 }{ maybe: $t0, $t2 } - 11: label L3 - # before: { no: $t5 }{ maybe: $t0, $t2 }, after: { no: $t5 }{ maybe: $t0, $t2 } - 12: goto 16 - # before: { no: $t5 }{ maybe: $t0, $t2 }, after: { no: $t5 }{ maybe: $t0, $t2 } - 13: label L4 - # before: { no: $t5 }{ maybe: $t0, $t2 }, after: { maybe: $t0, $t2 } - 14: $t5 := 42 + # before: { no: $t3, $t4, $t5, $t6 }{ maybe: $t0, $t2 }, after: { no: $t3, $t5, $t6 }{ maybe: $t0, $t2 } + 8: $t4 := infer($t0) + # before: { no: $t3, $t5, $t6 }{ maybe: $t0, $t2 }, after: { no: $t3, $t6 }{ maybe: $t0, $t2 } + 9: $t5 := 100 + # before: { no: $t3, $t6 }{ maybe: $t0, $t2 }, after: { no: $t6 }{ maybe: $t0, $t2 } + 10: $t3 := ==($t4, $t5) + # before: { no: $t6 }{ maybe: $t0, $t2 }, after: { no: $t6 }{ maybe: $t0, $t2 } + 11: if ($t3) goto 12 else goto 14 + # before: { no: $t6 }{ maybe: $t0, $t2 }, after: { no: $t6 }{ maybe: $t0, $t2 } + 12: label L3 + # before: { no: $t6 }{ maybe: $t0, $t2 }, after: { no: $t6 }{ maybe: $t0, $t2 } + 13: goto 17 + # before: { no: $t6 }{ maybe: $t0, $t2 }, after: { no: $t6 }{ maybe: $t0, $t2 } + 14: label L4 + # before: { no: $t6 }{ maybe: $t0, $t2 }, after: { maybe: $t0, $t2 } + 15: $t6 := 42 # before: { maybe: $t0, $t2 }, after: { maybe: $t0, $t2 } - 15: abort($t5) - # before: { no: $t5 }{ maybe: $t0, $t2 }, after: { no: $t5 }{ maybe: $t0, $t2 } - 16: label L5 - # before: { no: $t5 }{ maybe: $t0, $t2 }, after: { no: $t5 }{ maybe: $t0, $t2 } - 17: return () + 16: abort($t6) + # before: { no: $t6 }{ maybe: $t0, $t2 }, after: { no: $t6 }{ maybe: $t0, $t2 } + 17: label L5 + # before: { no: $t6 }{ maybe: $t0, $t2 }, after: { no: $t6 }{ maybe: $t0, $t2 } + 18: return () } diff --git a/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-commands/else_assigns_if_doesnt.exp b/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-commands/else_assigns_if_doesnt.exp index b375052acabc4..fec11953f82aa 100644 --- a/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-commands/else_assigns_if_doesnt.exp +++ b/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-commands/else_assigns_if_doesnt.exp @@ -11,6 +11,7 @@ fun _0::main() { var $t6: bool var $t7: u64 var $t8: u64 + var $t9: u64 0: $t2 := true 1: if ($t2) goto 2 else goto 6 2: label L0 @@ -22,16 +23,17 @@ fun _0::main() { 8: $t0 := infer($t4) 9: $t5 := infer($t0) 10: label L2 - 11: $t7 := 0 - 12: $t6 := ==($t1, $t7) - 13: if ($t6) goto 14 else goto 16 - 14: label L3 - 15: goto 19 - 16: label L4 - 17: $t8 := 42 - 18: abort($t8) - 19: label L5 - 20: return () + 11: $t7 := infer($t1) + 12: $t8 := 0 + 13: $t6 := ==($t7, $t8) + 14: if ($t6) goto 15 else goto 17 + 15: label L3 + 16: goto 20 + 17: label L4 + 18: $t9 := 42 + 19: abort($t9) + 20: label L5 + 21: return () } @@ -40,7 +42,7 @@ error: use of possibly unassigned local `y` ┌─ tests/uninit-use-checker/v1-commands/else_assigns_if_doesnt.move:11:13 │ 11 │ assert!(y == 0, 42); - │ ^^^^^^ + │ ^ ============ after uninitialized_use_checker: ================ @@ -55,46 +57,49 @@ fun _0::main() { var $t6: bool var $t7: u64 var $t8: u64 - # before: { no: $t0, $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8 } + var $t9: u64 + # before: { no: $t0, $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8, $t9 } 0: $t2 := true - # before: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8 } + # before: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8, $t9 } 1: if ($t2) goto 2 else goto 6 - # before: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8 } + # before: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8, $t9 } 2: label L0 - # before: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t0, $t1, $t4, $t5, $t6, $t7, $t8 } + # before: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t0, $t1, $t4, $t5, $t6, $t7, $t8, $t9 } 3: $t3 := 0 - # before: { no: $t0, $t1, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t0, $t4, $t5, $t6, $t7, $t8 } + # before: { no: $t0, $t1, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t0, $t4, $t5, $t6, $t7, $t8, $t9 } 4: $t1 := infer($t3) - # before: { no: $t0, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t0, $t4, $t5, $t6, $t7, $t8 } + # before: { no: $t0, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t0, $t4, $t5, $t6, $t7, $t8, $t9 } 5: goto 10 - # before: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8 } + # before: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8, $t9 } 6: label L1 - # before: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t0, $t1, $t3, $t5, $t6, $t7, $t8 } + # before: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t0, $t1, $t3, $t5, $t6, $t7, $t8, $t9 } 7: $t4 := 42 - # before: { no: $t0, $t1, $t3, $t5, $t6, $t7, $t8 }, after: { no: $t1, $t3, $t5, $t6, $t7, $t8 } + # before: { no: $t0, $t1, $t3, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t1, $t3, $t5, $t6, $t7, $t8, $t9 } 8: $t0 := infer($t4) - # before: { no: $t1, $t3, $t5, $t6, $t7, $t8 }, after: { no: $t1, $t3, $t6, $t7, $t8 } + # before: { no: $t1, $t3, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t1, $t3, $t6, $t7, $t8, $t9 } 9: $t5 := infer($t0) - # before: { no: $t6, $t7, $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t6, $t7, $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 } + # before: { no: $t6, $t7, $t8, $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t6, $t7, $t8, $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 } 10: label L2 - # before: { no: $t6, $t7, $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t6, $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 } - 11: $t7 := 0 - # before: { no: $t6, $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 } - 12: $t6 := ==($t1, $t7) - # before: { no: $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 } - 13: if ($t6) goto 14 else goto 16 - # before: { no: $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 } - 14: label L3 - # before: { no: $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 } - 15: goto 19 - # before: { no: $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 } - 16: label L4 - # before: { no: $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { maybe: $t0, $t1, $t3, $t4, $t5 } - 17: $t8 := 42 + # before: { no: $t6, $t7, $t8, $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t6, $t8, $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 } + 11: $t7 := infer($t1) + # before: { no: $t6, $t8, $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t6, $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 } + 12: $t8 := 0 + # before: { no: $t6, $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 } + 13: $t6 := ==($t7, $t8) + # before: { no: $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 } + 14: if ($t6) goto 15 else goto 17 + # before: { no: $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 } + 15: label L3 + # before: { no: $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 } + 16: goto 20 + # before: { no: $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 } + 17: label L4 + # before: { no: $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { maybe: $t0, $t1, $t3, $t4, $t5 } + 18: $t9 := 42 # before: { maybe: $t0, $t1, $t3, $t4, $t5 }, after: { maybe: $t0, $t1, $t3, $t4, $t5 } - 18: abort($t8) - # before: { no: $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 } - 19: label L5 - # before: { no: $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 } - 20: return () + 19: abort($t9) + # before: { no: $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 } + 20: label L5 + # before: { no: $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 } + 21: return () } diff --git a/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-commands/if_assigns_else_doesnt.exp b/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-commands/if_assigns_else_doesnt.exp index 2d71e8e6d40b9..2188845b73cd3 100644 --- a/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-commands/if_assigns_else_doesnt.exp +++ b/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-commands/if_assigns_else_doesnt.exp @@ -11,6 +11,7 @@ fun _0::main() { var $t6: bool var $t7: u64 var $t8: u64 + var $t9: u64 0: $t2 := true 1: if ($t2) goto 2 else goto 6 2: label L0 @@ -22,16 +23,17 @@ fun _0::main() { 8: $t1 := infer($t4) 9: $t5 := infer($t1) 10: label L2 - 11: $t7 := 42 - 12: $t6 := ==($t0, $t7) - 13: if ($t6) goto 14 else goto 16 - 14: label L3 - 15: goto 19 - 16: label L4 - 17: $t8 := 42 - 18: abort($t8) - 19: label L5 - 20: return () + 11: $t7 := infer($t0) + 12: $t8 := 42 + 13: $t6 := ==($t7, $t8) + 14: if ($t6) goto 15 else goto 17 + 15: label L3 + 16: goto 20 + 17: label L4 + 18: $t9 := 42 + 19: abort($t9) + 20: label L5 + 21: return () } @@ -40,7 +42,7 @@ error: use of possibly unassigned local `x` ┌─ tests/uninit-use-checker/v1-commands/if_assigns_else_doesnt.move:11:13 │ 11 │ assert!(x == 42, 42); - │ ^^^^^^^ + │ ^ ============ after uninitialized_use_checker: ================ @@ -55,46 +57,49 @@ fun _0::main() { var $t6: bool var $t7: u64 var $t8: u64 - # before: { no: $t0, $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8 } + var $t9: u64 + # before: { no: $t0, $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8, $t9 } 0: $t2 := true - # before: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8 } + # before: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8, $t9 } 1: if ($t2) goto 2 else goto 6 - # before: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8 } + # before: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8, $t9 } 2: label L0 - # before: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t0, $t1, $t4, $t5, $t6, $t7, $t8 } + # before: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t0, $t1, $t4, $t5, $t6, $t7, $t8, $t9 } 3: $t3 := 42 - # before: { no: $t0, $t1, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t1, $t4, $t5, $t6, $t7, $t8 } + # before: { no: $t0, $t1, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t1, $t4, $t5, $t6, $t7, $t8, $t9 } 4: $t0 := infer($t3) - # before: { no: $t1, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t1, $t4, $t5, $t6, $t7, $t8 } + # before: { no: $t1, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t1, $t4, $t5, $t6, $t7, $t8, $t9 } 5: goto 10 - # before: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8 } + # before: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8, $t9 } 6: label L1 - # before: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t0, $t1, $t3, $t5, $t6, $t7, $t8 } + # before: { no: $t0, $t1, $t3, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t0, $t1, $t3, $t5, $t6, $t7, $t8, $t9 } 7: $t4 := 0 - # before: { no: $t0, $t1, $t3, $t5, $t6, $t7, $t8 }, after: { no: $t0, $t3, $t5, $t6, $t7, $t8 } + # before: { no: $t0, $t1, $t3, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t0, $t3, $t5, $t6, $t7, $t8, $t9 } 8: $t1 := infer($t4) - # before: { no: $t0, $t3, $t5, $t6, $t7, $t8 }, after: { no: $t0, $t3, $t6, $t7, $t8 } + # before: { no: $t0, $t3, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t0, $t3, $t6, $t7, $t8, $t9 } 9: $t5 := infer($t1) - # before: { no: $t6, $t7, $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t6, $t7, $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 } + # before: { no: $t6, $t7, $t8, $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t6, $t7, $t8, $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 } 10: label L2 - # before: { no: $t6, $t7, $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t6, $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 } - 11: $t7 := 42 - # before: { no: $t6, $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 } - 12: $t6 := ==($t0, $t7) - # before: { no: $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 } - 13: if ($t6) goto 14 else goto 16 - # before: { no: $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 } - 14: label L3 - # before: { no: $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 } - 15: goto 19 - # before: { no: $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 } - 16: label L4 - # before: { no: $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { maybe: $t0, $t1, $t3, $t4, $t5 } - 17: $t8 := 42 + # before: { no: $t6, $t7, $t8, $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t6, $t8, $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 } + 11: $t7 := infer($t0) + # before: { no: $t6, $t8, $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t6, $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 } + 12: $t8 := 42 + # before: { no: $t6, $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 } + 13: $t6 := ==($t7, $t8) + # before: { no: $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 } + 14: if ($t6) goto 15 else goto 17 + # before: { no: $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 } + 15: label L3 + # before: { no: $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 } + 16: goto 20 + # before: { no: $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 } + 17: label L4 + # before: { no: $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { maybe: $t0, $t1, $t3, $t4, $t5 } + 18: $t9 := 42 # before: { maybe: $t0, $t1, $t3, $t4, $t5 }, after: { maybe: $t0, $t1, $t3, $t4, $t5 } - 18: abort($t8) - # before: { no: $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 } - 19: label L5 - # before: { no: $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t8 }{ maybe: $t0, $t1, $t3, $t4, $t5 } - 20: return () + 19: abort($t9) + # before: { no: $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 } + 20: label L5 + # before: { no: $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t9 }{ maybe: $t0, $t1, $t3, $t4, $t5 } + 21: return () } diff --git a/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-commands/if_assigns_no_else.exp b/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-commands/if_assigns_no_else.exp index c5764f1e874d2..070230c7b04e9 100644 --- a/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-commands/if_assigns_no_else.exp +++ b/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-commands/if_assigns_no_else.exp @@ -8,6 +8,7 @@ fun _0::main() { var $t3: bool var $t4: u64 var $t5: u64 + var $t6: u64 0: $t1 := true 1: if ($t1) goto 2 else goto 6 2: label L0 @@ -16,16 +17,17 @@ fun _0::main() { 5: goto 7 6: label L1 7: label L2 - 8: $t4 := 42 - 9: $t3 := ==($t0, $t4) - 10: if ($t3) goto 11 else goto 13 - 11: label L3 - 12: goto 16 - 13: label L4 - 14: $t5 := 42 - 15: abort($t5) - 16: label L5 - 17: return () + 8: $t4 := infer($t0) + 9: $t5 := 42 + 10: $t3 := ==($t4, $t5) + 11: if ($t3) goto 12 else goto 14 + 12: label L3 + 13: goto 17 + 14: label L4 + 15: $t6 := 42 + 16: abort($t6) + 17: label L5 + 18: return () } @@ -34,7 +36,7 @@ error: use of possibly unassigned local `x` ┌─ tests/uninit-use-checker/v1-commands/if_assigns_no_else.move:5:13 │ 5 │ assert!(x == 42, 42); - │ ^^^^^^^ + │ ^ ============ after uninitialized_use_checker: ================ @@ -46,40 +48,43 @@ fun _0::main() { var $t3: bool var $t4: u64 var $t5: u64 - # before: { no: $t0, $t1, $t2, $t3, $t4, $t5 }, after: { no: $t0, $t2, $t3, $t4, $t5 } + var $t6: u64 + # before: { no: $t0, $t1, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t0, $t2, $t3, $t4, $t5, $t6 } 0: $t1 := true - # before: { no: $t0, $t2, $t3, $t4, $t5 }, after: { no: $t0, $t2, $t3, $t4, $t5 } + # before: { no: $t0, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t0, $t2, $t3, $t4, $t5, $t6 } 1: if ($t1) goto 2 else goto 6 - # before: { no: $t0, $t2, $t3, $t4, $t5 }, after: { no: $t0, $t2, $t3, $t4, $t5 } + # before: { no: $t0, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t0, $t2, $t3, $t4, $t5, $t6 } 2: label L0 - # before: { no: $t0, $t2, $t3, $t4, $t5 }, after: { no: $t0, $t3, $t4, $t5 } + # before: { no: $t0, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t0, $t3, $t4, $t5, $t6 } 3: $t2 := 42 - # before: { no: $t0, $t3, $t4, $t5 }, after: { no: $t3, $t4, $t5 } + # before: { no: $t0, $t3, $t4, $t5, $t6 }, after: { no: $t3, $t4, $t5, $t6 } 4: $t0 := infer($t2) - # before: { no: $t3, $t4, $t5 }, after: { no: $t3, $t4, $t5 } + # before: { no: $t3, $t4, $t5, $t6 }, after: { no: $t3, $t4, $t5, $t6 } 5: goto 7 - # before: { no: $t0, $t2, $t3, $t4, $t5 }, after: { no: $t0, $t2, $t3, $t4, $t5 } + # before: { no: $t0, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t0, $t2, $t3, $t4, $t5, $t6 } 6: label L1 - # before: { no: $t3, $t4, $t5 }{ maybe: $t0, $t2 }, after: { no: $t3, $t4, $t5 }{ maybe: $t0, $t2 } + # before: { no: $t3, $t4, $t5, $t6 }{ maybe: $t0, $t2 }, after: { no: $t3, $t4, $t5, $t6 }{ maybe: $t0, $t2 } 7: label L2 - # before: { no: $t3, $t4, $t5 }{ maybe: $t0, $t2 }, after: { no: $t3, $t5 }{ maybe: $t0, $t2 } - 8: $t4 := 42 - # before: { no: $t3, $t5 }{ maybe: $t0, $t2 }, after: { no: $t5 }{ maybe: $t0, $t2 } - 9: $t3 := ==($t0, $t4) - # before: { no: $t5 }{ maybe: $t0, $t2 }, after: { no: $t5 }{ maybe: $t0, $t2 } - 10: if ($t3) goto 11 else goto 13 - # before: { no: $t5 }{ maybe: $t0, $t2 }, after: { no: $t5 }{ maybe: $t0, $t2 } - 11: label L3 - # before: { no: $t5 }{ maybe: $t0, $t2 }, after: { no: $t5 }{ maybe: $t0, $t2 } - 12: goto 16 - # before: { no: $t5 }{ maybe: $t0, $t2 }, after: { no: $t5 }{ maybe: $t0, $t2 } - 13: label L4 - # before: { no: $t5 }{ maybe: $t0, $t2 }, after: { maybe: $t0, $t2 } - 14: $t5 := 42 + # before: { no: $t3, $t4, $t5, $t6 }{ maybe: $t0, $t2 }, after: { no: $t3, $t5, $t6 }{ maybe: $t0, $t2 } + 8: $t4 := infer($t0) + # before: { no: $t3, $t5, $t6 }{ maybe: $t0, $t2 }, after: { no: $t3, $t6 }{ maybe: $t0, $t2 } + 9: $t5 := 42 + # before: { no: $t3, $t6 }{ maybe: $t0, $t2 }, after: { no: $t6 }{ maybe: $t0, $t2 } + 10: $t3 := ==($t4, $t5) + # before: { no: $t6 }{ maybe: $t0, $t2 }, after: { no: $t6 }{ maybe: $t0, $t2 } + 11: if ($t3) goto 12 else goto 14 + # before: { no: $t6 }{ maybe: $t0, $t2 }, after: { no: $t6 }{ maybe: $t0, $t2 } + 12: label L3 + # before: { no: $t6 }{ maybe: $t0, $t2 }, after: { no: $t6 }{ maybe: $t0, $t2 } + 13: goto 17 + # before: { no: $t6 }{ maybe: $t0, $t2 }, after: { no: $t6 }{ maybe: $t0, $t2 } + 14: label L4 + # before: { no: $t6 }{ maybe: $t0, $t2 }, after: { maybe: $t0, $t2 } + 15: $t6 := 42 # before: { maybe: $t0, $t2 }, after: { maybe: $t0, $t2 } - 15: abort($t5) - # before: { no: $t5 }{ maybe: $t0, $t2 }, after: { no: $t5 }{ maybe: $t0, $t2 } - 16: label L5 - # before: { no: $t5 }{ maybe: $t0, $t2 }, after: { no: $t5 }{ maybe: $t0, $t2 } - 17: return () + 16: abort($t6) + # before: { no: $t6 }{ maybe: $t0, $t2 }, after: { no: $t6 }{ maybe: $t0, $t2 } + 17: label L5 + # before: { no: $t6 }{ maybe: $t0, $t2 }, after: { no: $t6 }{ maybe: $t0, $t2 } + 18: return () } diff --git a/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-locals/use_before_assign_if.exp b/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-locals/use_before_assign_if.exp index f6fb5c095e8a0..82e094bc6ca5a 100644 --- a/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-locals/use_before_assign_if.exp +++ b/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-locals/use_before_assign_if.exp @@ -26,6 +26,7 @@ fun M::tcopy($t0: bool) { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 0: if ($t0) goto 1 else goto 5 1: label L0 2: $t2 := 0 @@ -33,10 +34,11 @@ fun M::tcopy($t0: bool) { 4: goto 6 5: label L1 6: label L2 - 7: $t4 := 1 - 8: $t3 := +($t1, $t4) - 9: $t5 := infer($t3) - 10: return () + 7: $t4 := infer($t1) + 8: $t5 := 1 + 9: $t3 := +($t4, $t5) + 10: $t6 := infer($t3) + 11: return () } @@ -74,7 +76,7 @@ error: use of possibly unassigned local `x` ┌─ tests/uninit-use-checker/v1-locals/use_before_assign_if.move:11:17 │ 11 │ let _ = x + 1; - │ ^^^^^ + │ ^ error: use of possibly unassigned local `x` ┌─ tests/uninit-use-checker/v1-locals/use_before_assign_if.move:17:17 @@ -120,28 +122,31 @@ fun M::tcopy($t0: bool) { var $t3: u64 var $t4: u64 var $t5: u64 - # before: { no: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t1, $t2, $t3, $t4, $t5 } + var $t6: u64 + # before: { no: $t1, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t1, $t2, $t3, $t4, $t5, $t6 } 0: if ($t0) goto 1 else goto 5 - # before: { no: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t1, $t2, $t3, $t4, $t5 } + # before: { no: $t1, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t1, $t2, $t3, $t4, $t5, $t6 } 1: label L0 - # before: { no: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t1, $t3, $t4, $t5 } + # before: { no: $t1, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t1, $t3, $t4, $t5, $t6 } 2: $t2 := 0 - # before: { no: $t1, $t3, $t4, $t5 }, after: { no: $t3, $t4, $t5 } + # before: { no: $t1, $t3, $t4, $t5, $t6 }, after: { no: $t3, $t4, $t5, $t6 } 3: $t1 := infer($t2) - # before: { no: $t3, $t4, $t5 }, after: { no: $t3, $t4, $t5 } + # before: { no: $t3, $t4, $t5, $t6 }, after: { no: $t3, $t4, $t5, $t6 } 4: goto 6 - # before: { no: $t1, $t2, $t3, $t4, $t5 }, after: { no: $t1, $t2, $t3, $t4, $t5 } + # before: { no: $t1, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t1, $t2, $t3, $t4, $t5, $t6 } 5: label L1 - # before: { no: $t3, $t4, $t5 }{ maybe: $t1, $t2 }, after: { no: $t3, $t4, $t5 }{ maybe: $t1, $t2 } + # before: { no: $t3, $t4, $t5, $t6 }{ maybe: $t1, $t2 }, after: { no: $t3, $t4, $t5, $t6 }{ maybe: $t1, $t2 } 6: label L2 - # before: { no: $t3, $t4, $t5 }{ maybe: $t1, $t2 }, after: { no: $t3, $t5 }{ maybe: $t1, $t2 } - 7: $t4 := 1 - # before: { no: $t3, $t5 }{ maybe: $t1, $t2 }, after: { no: $t5 }{ maybe: $t1, $t2 } - 8: $t3 := +($t1, $t4) - # before: { no: $t5 }{ maybe: $t1, $t2 }, after: { maybe: $t1, $t2 } - 9: $t5 := infer($t3) + # before: { no: $t3, $t4, $t5, $t6 }{ maybe: $t1, $t2 }, after: { no: $t3, $t5, $t6 }{ maybe: $t1, $t2 } + 7: $t4 := infer($t1) + # before: { no: $t3, $t5, $t6 }{ maybe: $t1, $t2 }, after: { no: $t3, $t6 }{ maybe: $t1, $t2 } + 8: $t5 := 1 + # before: { no: $t3, $t6 }{ maybe: $t1, $t2 }, after: { no: $t6 }{ maybe: $t1, $t2 } + 9: $t3 := +($t4, $t5) + # before: { no: $t6 }{ maybe: $t1, $t2 }, after: { maybe: $t1, $t2 } + 10: $t6 := infer($t3) # before: { maybe: $t1, $t2 }, after: { maybe: $t1, $t2 } - 10: return () + 11: return () } diff --git a/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-locals/use_before_assign_loop.exp b/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-locals/use_before_assign_loop.exp index 175d7515003fb..0e1218f0287c9 100644 --- a/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-locals/use_before_assign_loop.exp +++ b/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-locals/use_before_assign_loop.exp @@ -53,21 +53,23 @@ fun M::tcopy($t0: bool) { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 0: label L0 - 1: $t3 := 1 - 2: $t2 := +($t1, $t3) - 3: if ($t0) goto 4 else goto 7 - 4: label L2 - 5: goto 0 - 6: goto 8 - 7: label L3 - 8: label L4 - 9: $t4 := 0 - 10: $t1 := infer($t4) - 11: $t5 := infer($t2) - 12: goto 0 - 13: label L1 - 14: return () + 1: $t3 := infer($t1) + 2: $t4 := 1 + 3: $t2 := +($t3, $t4) + 4: if ($t0) goto 5 else goto 8 + 5: label L2 + 6: goto 0 + 7: goto 9 + 8: label L3 + 9: label L4 + 10: $t5 := 0 + 11: $t1 := infer($t5) + 12: $t6 := infer($t2) + 13: goto 0 + 14: label L1 + 15: return () } @@ -103,7 +105,7 @@ error: use of possibly unassigned local `x` ┌─ tests/uninit-use-checker/v1-locals/use_before_assign_loop.move:9:24 │ 9 │ loop { let y = x + 1; if (cond) { continue }; x = 0; y; } - │ ^^^^^ + │ ^ error: use of possibly unassigned local `x` ┌─ tests/uninit-use-checker/v1-locals/use_before_assign_loop.move:14:24 @@ -200,33 +202,36 @@ fun M::tcopy($t0: bool) { var $t3: u64 var $t4: u64 var $t5: u64 - # before: { maybe: $t1, $t2, $t3, $t4, $t5 }, after: { maybe: $t1, $t2, $t3, $t4, $t5 } + var $t6: u64 + # before: { maybe: $t1, $t2, $t3, $t4, $t5, $t6 }, after: { maybe: $t1, $t2, $t3, $t4, $t5, $t6 } 0: label L0 - # before: { maybe: $t1, $t2, $t3, $t4, $t5 }, after: { maybe: $t1, $t2, $t4, $t5 } - 1: $t3 := 1 - # before: { maybe: $t1, $t2, $t4, $t5 }, after: { maybe: $t1, $t4, $t5 } - 2: $t2 := +($t1, $t3) - # before: { maybe: $t1, $t4, $t5 }, after: { maybe: $t1, $t4, $t5 } - 3: if ($t0) goto 4 else goto 7 - # before: { maybe: $t1, $t4, $t5 }, after: { maybe: $t1, $t4, $t5 } - 4: label L2 - # before: { maybe: $t1, $t4, $t5 }, after: { maybe: $t1, $t4, $t5 } - 5: goto 0 - 6: goto 8 - # before: { maybe: $t1, $t4, $t5 }, after: { maybe: $t1, $t4, $t5 } - 7: label L3 - # before: { maybe: $t1, $t4, $t5 }, after: { maybe: $t1, $t4, $t5 } - 8: label L4 - # before: { maybe: $t1, $t4, $t5 }, after: { maybe: $t1, $t5 } - 9: $t4 := 0 - # before: { maybe: $t1, $t5 }, after: { maybe: $t5 } - 10: $t1 := infer($t4) - # before: { maybe: $t5 }, after: all initialized - 11: $t5 := infer($t2) + # before: { maybe: $t1, $t2, $t3, $t4, $t5, $t6 }, after: { maybe: $t1, $t2, $t4, $t5, $t6 } + 1: $t3 := infer($t1) + # before: { maybe: $t1, $t2, $t4, $t5, $t6 }, after: { maybe: $t1, $t2, $t5, $t6 } + 2: $t4 := 1 + # before: { maybe: $t1, $t2, $t5, $t6 }, after: { maybe: $t1, $t5, $t6 } + 3: $t2 := +($t3, $t4) + # before: { maybe: $t1, $t5, $t6 }, after: { maybe: $t1, $t5, $t6 } + 4: if ($t0) goto 5 else goto 8 + # before: { maybe: $t1, $t5, $t6 }, after: { maybe: $t1, $t5, $t6 } + 5: label L2 + # before: { maybe: $t1, $t5, $t6 }, after: { maybe: $t1, $t5, $t6 } + 6: goto 0 + 7: goto 9 + # before: { maybe: $t1, $t5, $t6 }, after: { maybe: $t1, $t5, $t6 } + 8: label L3 + # before: { maybe: $t1, $t5, $t6 }, after: { maybe: $t1, $t5, $t6 } + 9: label L4 + # before: { maybe: $t1, $t5, $t6 }, after: { maybe: $t1, $t6 } + 10: $t5 := 0 + # before: { maybe: $t1, $t6 }, after: { maybe: $t6 } + 11: $t1 := infer($t5) + # before: { maybe: $t6 }, after: all initialized + 12: $t6 := infer($t2) # before: all initialized, after: all initialized - 12: goto 0 - 13: label L1 - 14: return () + 13: goto 0 + 14: label L1 + 15: return () } diff --git a/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-locals/use_before_assign_simple.exp b/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-locals/use_before_assign_simple.exp index 46ecf613deaa7..8292b77e67716 100644 --- a/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-locals/use_before_assign_simple.exp +++ b/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-locals/use_before_assign_simple.exp @@ -20,13 +20,15 @@ fun M::tcopy() { var $t1: u64 var $t2: u64 var $t3: u64 - var $t4: 0x8675309::M::S + var $t4: u64 var $t5: 0x8675309::M::S - 0: $t2 := 1 - 1: $t1 := +($t0, $t2) - 2: $t3 := infer($t1) - 3: $t5 := copy($t4) - 4: return () + var $t6: 0x8675309::M::S + 0: $t2 := infer($t0) + 1: $t3 := 1 + 2: $t1 := +($t2, $t3) + 3: $t4 := infer($t1) + 4: $t6 := copy($t5) + 5: return () } @@ -65,7 +67,7 @@ error: use of unassigned local `x` ┌─ tests/uninit-use-checker/v1-locals/use_before_assign_simple.move:14:17 │ 14 │ let _ = x + 1; - │ ^^^^^ + │ ^ error: use of unassigned local `s` ┌─ tests/uninit-use-checker/v1-locals/use_before_assign_simple.move:17:19 @@ -111,18 +113,21 @@ fun M::tcopy() { var $t1: u64 var $t2: u64 var $t3: u64 - var $t4: 0x8675309::M::S + var $t4: u64 var $t5: 0x8675309::M::S - # before: { no: $t0, $t1, $t2, $t3, $t4, $t5 }, after: { no: $t0, $t1, $t3, $t4, $t5 } - 0: $t2 := 1 - # before: { no: $t0, $t1, $t3, $t4, $t5 }, after: { no: $t0, $t3, $t4, $t5 } - 1: $t1 := +($t0, $t2) - # before: { no: $t0, $t3, $t4, $t5 }, after: { no: $t0, $t4, $t5 } - 2: $t3 := infer($t1) - # before: { no: $t0, $t4, $t5 }, after: { no: $t0, $t4 } - 3: $t5 := copy($t4) - # before: { no: $t0, $t4 }, after: { no: $t0, $t4 } - 4: return () + var $t6: 0x8675309::M::S + # before: { no: $t0, $t1, $t2, $t3, $t4, $t5, $t6 }, after: { no: $t0, $t1, $t3, $t4, $t5, $t6 } + 0: $t2 := infer($t0) + # before: { no: $t0, $t1, $t3, $t4, $t5, $t6 }, after: { no: $t0, $t1, $t4, $t5, $t6 } + 1: $t3 := 1 + # before: { no: $t0, $t1, $t4, $t5, $t6 }, after: { no: $t0, $t4, $t5, $t6 } + 2: $t1 := +($t2, $t3) + # before: { no: $t0, $t4, $t5, $t6 }, after: { no: $t0, $t5, $t6 } + 3: $t4 := infer($t1) + # before: { no: $t0, $t5, $t6 }, after: { no: $t0, $t5 } + 4: $t6 := copy($t5) + # before: { no: $t0, $t5 }, after: { no: $t0, $t5 } + 5: return () } diff --git a/third_party/move/move-compiler-v2/tests/unreachable-code-remover/abort_only.exp b/third_party/move/move-compiler-v2/tests/unreachable-code-remover/abort_only.exp index e4b4fd0c62559..323a655777f9e 100644 --- a/third_party/move/move-compiler-v2/tests/unreachable-code-remover/abort_only.exp +++ b/third_party/move/move-compiler-v2/tests/unreachable-code-remover/abort_only.exp @@ -29,4 +29,15 @@ fun m::test() { } +============ disassembled file-format ================== +// Move bytecode v7 +module c0ffee.m { + + +test() /* def_idx: 0 */ { +B0: + 0: LdU64(0) + 1: Abort +} +} ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unreachable-code-remover/abort_or_return_always.exp b/third_party/move/move-compiler-v2/tests/unreachable-code-remover/abort_or_return_always.exp index 6d7f7215ad4f4..2fe6829f1dd67 100644 --- a/third_party/move/move-compiler-v2/tests/unreachable-code-remover/abort_or_return_always.exp +++ b/third_party/move/move-compiler-v2/tests/unreachable-code-remover/abort_or_return_always.exp @@ -55,4 +55,21 @@ fun m::test($t0: bool): u64 { } +============ disassembled file-format ================== +// Move bytecode v7 +module c0ffee.m { + + +test(Arg0: bool): u64 /* def_idx: 0 */ { +B0: + 0: MoveLoc[0](Arg0: bool) + 1: BrFalse(4) +B1: + 2: LdU64(0) + 3: Abort +B2: + 4: LdU64(1) + 5: Ret +} +} ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unreachable-code-remover/always_false_branch.exp b/third_party/move/move-compiler-v2/tests/unreachable-code-remover/always_false_branch.exp index 99e0aca193630..287eed0c9630d 100644 --- a/third_party/move/move-compiler-v2/tests/unreachable-code-remover/always_false_branch.exp +++ b/third_party/move/move-compiler-v2/tests/unreachable-code-remover/always_false_branch.exp @@ -7,20 +7,22 @@ fun m::test(): u64 { var $t2: u64 var $t3: u64 var $t4: u64 + var $t5: u64 0: $t1 := false - 1: if ($t1) goto 2 else goto 10 + 1: if ($t1) goto 2 else goto 11 2: label L0 3: $t2 := 0 - 4: $t4 := 1 - 5: $t3 := +($t2, $t4) - 6: $t2 := infer($t3) - 7: $t0 := infer($t2) - 8: return $t0 - 9: goto 11 - 10: label L1 - 11: label L2 - 12: $t0 := 0 - 13: return $t0 + 4: $t4 := infer($t2) + 5: $t5 := 1 + 6: $t3 := +($t4, $t5) + 7: $t2 := infer($t3) + 8: $t0 := infer($t2) + 9: return $t0 + 10: goto 12 + 11: label L1 + 12: label L2 + 13: $t0 := 0 + 14: return $t0 } ============ after UnreachableCodeProcessor: ================ @@ -32,30 +34,33 @@ fun m::test(): u64 { var $t2: u64 var $t3: u64 var $t4: u64 + var $t5: u64 # maybe 0: $t1 := false # maybe - 1: if ($t1) goto 2 else goto 9 + 1: if ($t1) goto 2 else goto 10 # maybe 2: label L0 # maybe 3: $t2 := 0 # maybe - 4: $t4 := 1 + 4: $t4 := move($t2) # maybe - 5: $t3 := +($t2, $t4) + 5: $t5 := 1 # maybe - 6: $t2 := move($t3) + 6: $t3 := +($t4, $t5) # maybe - 7: $t0 := move($t2) + 7: $t2 := move($t3) # maybe - 8: return $t0 + 8: $t0 := move($t2) # maybe - 9: label L2 + 9: return $t0 # maybe - 10: $t0 := 0 + 10: label L2 # maybe - 11: return $t0 + 11: $t0 := 0 + # maybe + 12: return $t0 } ============ after UnreachableCodeRemover: ================ @@ -67,19 +72,39 @@ fun m::test(): u64 { var $t2: u64 var $t3: u64 var $t4: u64 + var $t5: u64 0: $t1 := false - 1: if ($t1) goto 2 else goto 9 + 1: if ($t1) goto 2 else goto 10 2: label L0 3: $t2 := 0 - 4: $t4 := 1 - 5: $t3 := +($t2, $t4) - 6: $t2 := move($t3) - 7: $t0 := move($t2) - 8: return $t0 - 9: label L2 - 10: $t0 := 0 - 11: return $t0 + 4: $t4 := move($t2) + 5: $t5 := 1 + 6: $t3 := +($t4, $t5) + 7: $t2 := move($t3) + 8: $t0 := move($t2) + 9: return $t0 + 10: label L2 + 11: $t0 := 0 + 12: return $t0 } +============ disassembled file-format ================== +// Move bytecode v7 +module c0ffee.m { + + +test(): u64 /* def_idx: 0 */ { +B0: + 0: Branch(5) +B1: + 1: LdU64(0) + 2: LdU64(1) + 3: Add + 4: Ret +B2: + 5: LdU64(0) + 6: Ret +} +} ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unreachable-code-remover/break_unreachable.exp b/third_party/move/move-compiler-v2/tests/unreachable-code-remover/break_unreachable.exp index ca5f7519139aa..44e712f41be8b 100644 --- a/third_party/move/move-compiler-v2/tests/unreachable-code-remover/break_unreachable.exp +++ b/third_party/move/move-compiler-v2/tests/unreachable-code-remover/break_unreachable.exp @@ -5,40 +5,50 @@ fun m::test() { var $t0: u64 var $t1: u64 var $t2: u64 - var $t3: bool - var $t4: u64 + var $t3: u64 + var $t4: bool var $t5: u64 var $t6: u64 var $t7: u64 var $t8: u64 var $t9: u64 var $t10: u64 + var $t11: u64 + var $t12: u64 + var $t13: u64 + var $t14: u64 + var $t15: u64 0: $t0 := 0 1: label L0 - 2: $t2 := 1 - 3: $t1 := +($t0, $t2) - 4: $t0 := infer($t1) - 5: $t4 := 10 - 6: $t3 := ==($t0, $t4) - 7: if ($t3) goto 8 else goto 14 - 8: label L2 - 9: goto 24 - 10: $t6 := 1 - 11: $t5 := +($t0, $t6) - 12: $t0 := infer($t5) - 13: goto 19 - 14: label L3 - 15: goto 1 - 16: $t8 := 1 - 17: $t7 := +($t0, $t8) - 18: $t0 := infer($t7) - 19: label L4 - 20: $t10 := 1 - 21: $t9 := +($t0, $t10) - 22: $t0 := infer($t9) - 23: goto 1 - 24: label L1 - 25: return () + 2: $t2 := infer($t0) + 3: $t3 := 1 + 4: $t1 := +($t2, $t3) + 5: $t0 := infer($t1) + 6: $t5 := infer($t0) + 7: $t6 := 10 + 8: $t4 := ==($t5, $t6) + 9: if ($t4) goto 10 else goto 17 + 10: label L2 + 11: goto 29 + 12: $t8 := infer($t0) + 13: $t9 := 1 + 14: $t7 := +($t8, $t9) + 15: $t0 := infer($t7) + 16: goto 23 + 17: label L3 + 18: goto 1 + 19: $t11 := infer($t0) + 20: $t12 := 1 + 21: $t10 := +($t11, $t12) + 22: $t0 := infer($t10) + 23: label L4 + 24: $t14 := infer($t0) + 25: $t15 := 1 + 26: $t13 := +($t14, $t15) + 27: $t0 := infer($t13) + 28: goto 1 + 29: label L1 + 30: return () } ============ after UnreachableCodeProcessor: ================ @@ -48,38 +58,47 @@ fun m::test() { var $t0: u64 var $t1: u64 var $t2: u64 - var $t3: bool - var $t4: u64 - var $t5: u64 [unused] - var $t6: u64 [unused] + var $t3: u64 + var $t4: bool + var $t5: u64 + var $t6: u64 var $t7: u64 [unused] var $t8: u64 [unused] var $t9: u64 [unused] var $t10: u64 [unused] + var $t11: u64 [unused] + var $t12: u64 [unused] + var $t13: u64 [unused] + var $t14: u64 [unused] + var $t15: u64 [unused] # maybe 0: $t0 := 0 # maybe 1: label L0 # maybe - 2: $t2 := 1 + 2: $t2 := move($t0) # maybe - 3: $t1 := +($t0, $t2) + 3: $t3 := 1 # maybe - 4: $t0 := move($t1) + 4: $t1 := +($t2, $t3) # maybe - 5: $t4 := 10 + 5: $t0 := move($t1) # maybe - 6: $t3 := ==($t0, $t4) + 6: $t5 := copy($t0) # maybe - 7: if ($t3) goto 10 else goto 8 + 7: $t6 := 10 # maybe - 8: label L3 + 8: $t4 := ==($t5, $t6) # maybe - 9: goto 1 + 9: if ($t4) goto 12 else goto 10 # maybe - 10: label L2 + 10: label L3 # maybe - 11: return () + 11: goto 1 + # maybe + 12: label L2 + # maybe + 13: return () } ============ after UnreachableCodeRemover: ================ @@ -89,27 +108,59 @@ fun m::test() { var $t0: u64 var $t1: u64 var $t2: u64 - var $t3: bool - var $t4: u64 - var $t5: u64 [unused] - var $t6: u64 [unused] + var $t3: u64 + var $t4: bool + var $t5: u64 + var $t6: u64 var $t7: u64 [unused] var $t8: u64 [unused] var $t9: u64 [unused] var $t10: u64 [unused] + var $t11: u64 [unused] + var $t12: u64 [unused] + var $t13: u64 [unused] + var $t14: u64 [unused] + var $t15: u64 [unused] 0: $t0 := 0 1: label L0 - 2: $t2 := 1 - 3: $t1 := +($t0, $t2) - 4: $t0 := move($t1) - 5: $t4 := 10 - 6: $t3 := ==($t0, $t4) - 7: if ($t3) goto 10 else goto 8 - 8: label L3 - 9: goto 1 - 10: label L2 - 11: return () + 2: $t2 := move($t0) + 3: $t3 := 1 + 4: $t1 := +($t2, $t3) + 5: $t0 := move($t1) + 6: $t5 := copy($t0) + 7: $t6 := 10 + 8: $t4 := ==($t5, $t6) + 9: if ($t4) goto 12 else goto 10 + 10: label L3 + 11: goto 1 + 12: label L2 + 13: return () } +============ disassembled file-format ================== +// Move bytecode v7 +module c0ffee.m { + + +test() /* def_idx: 0 */ { +L0: loc0: u64 +B0: + 0: LdU64(0) + 1: StLoc[0](loc0: u64) +B1: + 2: MoveLoc[0](loc0: u64) + 3: LdU64(1) + 4: Add + 5: StLoc[0](loc0: u64) + 6: CopyLoc[0](loc0: u64) + 7: LdU64(10) + 8: Eq + 9: BrTrue(11) +B2: + 10: Branch(2) +B3: + 11: Ret +} +} ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unreachable-code-remover/conditional_loop_unreachable.exp b/third_party/move/move-compiler-v2/tests/unreachable-code-remover/conditional_loop_unreachable.exp index 39b915dd1b386..2a1a4be89f909 100644 --- a/third_party/move/move-compiler-v2/tests/unreachable-code-remover/conditional_loop_unreachable.exp +++ b/third_party/move/move-compiler-v2/tests/unreachable-code-remover/conditional_loop_unreachable.exp @@ -8,33 +8,37 @@ fun m::test($t0: bool, $t1: bool) { var $t5: u64 var $t6: u64 var $t7: u64 + var $t8: u64 + var $t9: u64 0: label L0 - 1: if ($t0) goto 2 else goto 21 + 1: if ($t0) goto 2 else goto 23 2: label L2 - 3: if ($t1) goto 4 else goto 13 + 3: if ($t1) goto 4 else goto 14 4: label L5 5: label L8 6: goto 5 7: label L9 8: $t2 := 0 - 9: $t4 := 1 - 10: $t3 := +($t2, $t4) - 11: $t2 := infer($t3) - 12: goto 15 - 13: label L6 - 14: goto 25 - 15: label L7 - 16: $t5 := 0 - 17: $t7 := 1 - 18: $t6 := +($t5, $t7) - 19: $t5 := infer($t6) - 20: goto 23 - 21: label L3 + 9: $t4 := infer($t2) + 10: $t5 := 1 + 11: $t3 := +($t4, $t5) + 12: $t2 := infer($t3) + 13: goto 16 + 14: label L6 + 15: goto 27 + 16: label L7 + 17: $t6 := 0 + 18: $t8 := infer($t6) + 19: $t9 := 1 + 20: $t7 := +($t8, $t9) + 21: $t6 := infer($t7) 22: goto 25 - 23: label L4 - 24: goto 0 - 25: label L1 - 26: return () + 23: label L3 + 24: goto 27 + 25: label L4 + 26: goto 0 + 27: label L1 + 28: return () } @@ -61,6 +65,8 @@ fun m::test($t0: bool, $t1: bool) { var $t5: u64 [unused] var $t6: u64 [unused] var $t7: u64 [unused] + var $t8: u64 [unused] + var $t9: u64 [unused] # maybe 0: if ($t0) goto 3 else goto 1 # maybe @@ -99,6 +105,8 @@ fun m::test($t0: bool, $t1: bool) { var $t5: u64 [unused] var $t6: u64 [unused] var $t7: u64 [unused] + var $t8: u64 [unused] + var $t9: u64 [unused] 0: if ($t0) goto 3 else goto 1 1: label L9 2: goto 11 @@ -115,4 +123,28 @@ fun m::test($t0: bool, $t1: bool) { } +============ disassembled file-format ================== +// Move bytecode v7 +module c0ffee.m { + + +test(Arg0: bool, Arg1: bool) /* def_idx: 0 */ { +B0: + 0: MoveLoc[0](Arg0: bool) + 1: BrTrue(3) +B1: + 2: Branch(8) +B2: + 3: MoveLoc[1](Arg1: bool) + 4: BrFalse(6) +B3: + 5: Branch(7) +B4: + 6: Branch(8) +B5: + 7: Branch(7) +B6: + 8: Ret +} +} ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unreachable-code-remover/inter_procedural_abort.exp b/third_party/move/move-compiler-v2/tests/unreachable-code-remover/inter_procedural_abort.exp index 1eebd76b31354..c9682f28384ef 100644 --- a/third_party/move/move-compiler-v2/tests/unreachable-code-remover/inter_procedural_abort.exp +++ b/third_party/move/move-compiler-v2/tests/unreachable-code-remover/inter_procedural_abort.exp @@ -15,13 +15,15 @@ fun m::test(): u64 { var $t1: u64 var $t2: u64 var $t3: u64 + var $t4: u64 0: m::always_abort() 1: $t1 := 0 - 2: $t3 := 1 - 3: $t2 := +($t1, $t3) - 4: $t1 := infer($t2) - 5: $t0 := infer($t1) - 6: return $t0 + 2: $t3 := infer($t1) + 3: $t4 := 1 + 4: $t2 := +($t3, $t4) + 5: $t1 := infer($t2) + 6: $t0 := infer($t1) + 7: return $t0 } ============ after UnreachableCodeProcessor: ================ @@ -42,20 +44,23 @@ fun m::test(): u64 { var $t1: u64 var $t2: u64 var $t3: u64 + var $t4: u64 # maybe 0: m::always_abort() # maybe 1: $t1 := 0 # maybe - 2: $t3 := 1 + 2: $t3 := move($t1) # maybe - 3: $t2 := +($t1, $t3) + 3: $t4 := 1 # maybe - 4: $t1 := move($t2) + 4: $t2 := +($t3, $t4) # maybe - 5: $t0 := move($t1) + 5: $t1 := move($t2) # maybe - 6: return $t0 + 6: $t0 := move($t1) + # maybe + 7: return $t0 } ============ after UnreachableCodeRemover: ================ @@ -74,14 +79,35 @@ fun m::test(): u64 { var $t1: u64 var $t2: u64 var $t3: u64 + var $t4: u64 0: m::always_abort() 1: $t1 := 0 - 2: $t3 := 1 - 3: $t2 := +($t1, $t3) - 4: $t1 := move($t2) - 5: $t0 := move($t1) - 6: return $t0 + 2: $t3 := move($t1) + 3: $t4 := 1 + 4: $t2 := +($t3, $t4) + 5: $t1 := move($t2) + 6: $t0 := move($t1) + 7: return $t0 } +============ disassembled file-format ================== +// Move bytecode v7 +module c0ffee.m { + + +always_abort() /* def_idx: 0 */ { +B0: + 0: LdU64(0) + 1: Abort +} +test(): u64 /* def_idx: 1 */ { +B0: + 0: Call always_abort() + 1: LdU64(0) + 2: LdU64(1) + 3: Add + 4: Ret +} +} ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unreachable-code-remover/loop_unreachable.exp b/third_party/move/move-compiler-v2/tests/unreachable-code-remover/loop_unreachable.exp index 1c8c37a0a5415..249ad2a47c0ba 100644 --- a/third_party/move/move-compiler-v2/tests/unreachable-code-remover/loop_unreachable.exp +++ b/third_party/move/move-compiler-v2/tests/unreachable-code-remover/loop_unreachable.exp @@ -31,4 +31,14 @@ fun m::test(): u64 { } +============ disassembled file-format ================== +// Move bytecode v7 +module c0ffee.m { + + +test(): u64 /* def_idx: 0 */ { +B0: + 0: Branch(0) +} +} ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unreachable-code-remover/return_after_abort.exp b/third_party/move/move-compiler-v2/tests/unreachable-code-remover/return_after_abort.exp index 0b5d7dce0681e..487fe2041cf79 100644 --- a/third_party/move/move-compiler-v2/tests/unreachable-code-remover/return_after_abort.exp +++ b/third_party/move/move-compiler-v2/tests/unreachable-code-remover/return_after_abort.exp @@ -33,4 +33,15 @@ fun m::test(): u32 { } +============ disassembled file-format ================== +// Move bytecode v7 +module c0ffee.m { + + +test(): u32 /* def_idx: 0 */ { +B0: + 0: LdU64(0) + 1: Abort +} +} ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/args_with_side_effects.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/args_with_side_effects.exp index a58b76fe10539..1c8ed4cb68489 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/args_with_side_effects.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/args_with_side_effects.exp @@ -3,8 +3,10 @@ [variant baseline] fun m::add($t0: u64, $t1: u64): u64 { var $t2: u64 - 0: $t2 := +($t0, $t1) - 1: return $t2 + var $t3: u64 + 0: $t3 := infer($t0) + 1: $t2 := +($t3, $t1) + 2: return $t2 } @@ -15,13 +17,15 @@ public fun m::test($t0: u64): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 0: $t2 := infer($t0) - 1: $t5 := 1 - 2: $t4 := +($t0, $t5) - 3: $t0 := infer($t4) - 4: $t3 := infer($t0) - 5: $t1 := m::add($t2, $t3) - 6: return $t1 + 1: $t5 := infer($t0) + 2: $t6 := 1 + 3: $t4 := +($t5, $t6) + 4: $t0 := infer($t4) + 5: $t3 := infer($t0) + 6: $t1 := m::add($t2, $t3) + 7: return $t1 } ============ after DeadStoreElimination: ================ @@ -29,8 +33,10 @@ public fun m::test($t0: u64): u64 { [variant baseline] fun m::add($t0: u64, $t1: u64): u64 { var $t2: u64 - 0: $t2 := +($t0, $t1) - 1: return $t2 + var $t3: u64 + 0: $t3 := move($t0) + 1: $t2 := +($t3, $t1) + 2: return $t2 } @@ -41,13 +47,15 @@ public fun m::test($t0: u64): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 0: $t2 := copy($t0) - 1: $t5 := 1 - 2: $t4 := +($t0, $t5) - 3: $t0 := move($t4) - 4: $t3 := move($t0) - 5: $t1 := m::add($t2, $t3) - 6: return $t1 + 1: $t5 := move($t0) + 2: $t6 := 1 + 3: $t4 := +($t5, $t6) + 4: $t0 := move($t4) + 5: $t3 := move($t0) + 6: $t1 := m::add($t2, $t3) + 7: return $t1 } ============ after VariableCoalescingAnnotator: ================ @@ -55,12 +63,16 @@ public fun m::test($t0: u64): u64 { [variant baseline] fun m::add($t0: u64, $t1: u64): u64 { var $t2: u64 + var $t3: u64 # live vars: $t0, $t1 - # events: b:$t0, b:$t1, e:$t0, e:$t1, b:$t2 - 0: $t2 := +($t0, $t1) + # events: b:$t0, b:$t1, e:$t0, b:$t3 + 0: $t3 := move($t0) + # live vars: $t1, $t3 + # events: e:$t1, e:$t3, b:$t2 + 1: $t2 := +($t3, $t1) # live vars: $t2 # events: e:$t2 - 1: return $t2 + 2: return $t2 } @@ -71,27 +83,31 @@ public fun m::test($t0: u64): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 # live vars: $t0 # events: b:$t0, b:$t2 0: $t2 := copy($t0) # live vars: $t0, $t2 # events: b:$t5 - 1: $t5 := 1 - # live vars: $t0, $t2, $t5 - # events: e:$t5, b:$t4 - 2: $t4 := +($t0, $t5) + 1: $t5 := move($t0) + # live vars: $t2, $t5 + # events: b:$t6 + 2: $t6 := 1 + # live vars: $t2, $t5, $t6 + # events: e:$t5, e:$t6, b:$t4 + 3: $t4 := +($t5, $t6) # live vars: $t2, $t4 # events: e:$t4 - 3: $t0 := move($t4) + 4: $t0 := move($t4) # live vars: $t0, $t2 # events: e:$t0, b:$t3 - 4: $t3 := move($t0) + 5: $t3 := move($t0) # live vars: $t2, $t3 # events: e:$t2, e:$t3, b:$t1 - 5: $t1 := m::add($t2, $t3) + 6: $t1 := m::add($t2, $t3) # live vars: $t1 # events: e:$t1 - 6: return $t1 + 7: return $t1 } ============ after VariableCoalescingTransformer: ================ @@ -99,8 +115,10 @@ public fun m::test($t0: u64): u64 { [variant baseline] fun m::add($t0: u64, $t1: u64): u64 { var $t2: u64 [unused] - 0: $t0 := +($t0, $t1) - 1: return $t0 + var $t3: u64 [unused] + 0: $t0 := move($t0) + 1: $t0 := +($t0, $t1) + 2: return $t0 } @@ -111,13 +129,15 @@ public fun m::test($t0: u64): u64 { var $t3: u64 [unused] var $t4: u64 [unused] var $t5: u64 + var $t6: u64 0: $t2 := copy($t0) - 1: $t5 := 1 - 2: $t5 := +($t0, $t5) - 3: $t0 := move($t5) - 4: $t0 := move($t0) - 5: $t0 := m::add($t2, $t0) - 6: return $t0 + 1: $t5 := move($t0) + 2: $t6 := 1 + 3: $t5 := +($t5, $t6) + 4: $t0 := move($t5) + 5: $t0 := move($t0) + 6: $t0 := m::add($t2, $t0) + 7: return $t0 } ============ after DeadStoreElimination: ================ @@ -125,8 +145,10 @@ public fun m::test($t0: u64): u64 { [variant baseline] fun m::add($t0: u64, $t1: u64): u64 { var $t2: u64 [unused] - 0: $t0 := +($t0, $t1) - 1: return $t0 + var $t3: u64 [unused] + 0: $t0 := move($t0) + 1: $t0 := +($t0, $t1) + 2: return $t0 } @@ -137,12 +159,14 @@ public fun m::test($t0: u64): u64 { var $t3: u64 [unused] var $t4: u64 [unused] var $t5: u64 + var $t6: u64 0: $t2 := copy($t0) - 1: $t5 := 1 - 2: $t5 := +($t0, $t5) - 3: $t0 := move($t5) - 4: $t0 := m::add($t2, $t0) - 5: return $t0 + 1: $t5 := move($t0) + 2: $t6 := 1 + 3: $t5 := +($t5, $t6) + 4: $t0 := move($t5) + 5: $t0 := m::add($t2, $t0) + 6: return $t0 } @@ -159,7 +183,6 @@ B0: 3: Ret } public test(Arg0: u64): u64 /* def_idx: 1 */ { -L1: loc0: u64 B0: 0: CopyLoc[0](Arg0: u64) 1: MoveLoc[0](Arg0: u64) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/args_with_side_effects.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/args_with_side_effects.opt.exp index a58b76fe10539..1c8ed4cb68489 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/args_with_side_effects.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/args_with_side_effects.opt.exp @@ -3,8 +3,10 @@ [variant baseline] fun m::add($t0: u64, $t1: u64): u64 { var $t2: u64 - 0: $t2 := +($t0, $t1) - 1: return $t2 + var $t3: u64 + 0: $t3 := infer($t0) + 1: $t2 := +($t3, $t1) + 2: return $t2 } @@ -15,13 +17,15 @@ public fun m::test($t0: u64): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 0: $t2 := infer($t0) - 1: $t5 := 1 - 2: $t4 := +($t0, $t5) - 3: $t0 := infer($t4) - 4: $t3 := infer($t0) - 5: $t1 := m::add($t2, $t3) - 6: return $t1 + 1: $t5 := infer($t0) + 2: $t6 := 1 + 3: $t4 := +($t5, $t6) + 4: $t0 := infer($t4) + 5: $t3 := infer($t0) + 6: $t1 := m::add($t2, $t3) + 7: return $t1 } ============ after DeadStoreElimination: ================ @@ -29,8 +33,10 @@ public fun m::test($t0: u64): u64 { [variant baseline] fun m::add($t0: u64, $t1: u64): u64 { var $t2: u64 - 0: $t2 := +($t0, $t1) - 1: return $t2 + var $t3: u64 + 0: $t3 := move($t0) + 1: $t2 := +($t3, $t1) + 2: return $t2 } @@ -41,13 +47,15 @@ public fun m::test($t0: u64): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 0: $t2 := copy($t0) - 1: $t5 := 1 - 2: $t4 := +($t0, $t5) - 3: $t0 := move($t4) - 4: $t3 := move($t0) - 5: $t1 := m::add($t2, $t3) - 6: return $t1 + 1: $t5 := move($t0) + 2: $t6 := 1 + 3: $t4 := +($t5, $t6) + 4: $t0 := move($t4) + 5: $t3 := move($t0) + 6: $t1 := m::add($t2, $t3) + 7: return $t1 } ============ after VariableCoalescingAnnotator: ================ @@ -55,12 +63,16 @@ public fun m::test($t0: u64): u64 { [variant baseline] fun m::add($t0: u64, $t1: u64): u64 { var $t2: u64 + var $t3: u64 # live vars: $t0, $t1 - # events: b:$t0, b:$t1, e:$t0, e:$t1, b:$t2 - 0: $t2 := +($t0, $t1) + # events: b:$t0, b:$t1, e:$t0, b:$t3 + 0: $t3 := move($t0) + # live vars: $t1, $t3 + # events: e:$t1, e:$t3, b:$t2 + 1: $t2 := +($t3, $t1) # live vars: $t2 # events: e:$t2 - 1: return $t2 + 2: return $t2 } @@ -71,27 +83,31 @@ public fun m::test($t0: u64): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 # live vars: $t0 # events: b:$t0, b:$t2 0: $t2 := copy($t0) # live vars: $t0, $t2 # events: b:$t5 - 1: $t5 := 1 - # live vars: $t0, $t2, $t5 - # events: e:$t5, b:$t4 - 2: $t4 := +($t0, $t5) + 1: $t5 := move($t0) + # live vars: $t2, $t5 + # events: b:$t6 + 2: $t6 := 1 + # live vars: $t2, $t5, $t6 + # events: e:$t5, e:$t6, b:$t4 + 3: $t4 := +($t5, $t6) # live vars: $t2, $t4 # events: e:$t4 - 3: $t0 := move($t4) + 4: $t0 := move($t4) # live vars: $t0, $t2 # events: e:$t0, b:$t3 - 4: $t3 := move($t0) + 5: $t3 := move($t0) # live vars: $t2, $t3 # events: e:$t2, e:$t3, b:$t1 - 5: $t1 := m::add($t2, $t3) + 6: $t1 := m::add($t2, $t3) # live vars: $t1 # events: e:$t1 - 6: return $t1 + 7: return $t1 } ============ after VariableCoalescingTransformer: ================ @@ -99,8 +115,10 @@ public fun m::test($t0: u64): u64 { [variant baseline] fun m::add($t0: u64, $t1: u64): u64 { var $t2: u64 [unused] - 0: $t0 := +($t0, $t1) - 1: return $t0 + var $t3: u64 [unused] + 0: $t0 := move($t0) + 1: $t0 := +($t0, $t1) + 2: return $t0 } @@ -111,13 +129,15 @@ public fun m::test($t0: u64): u64 { var $t3: u64 [unused] var $t4: u64 [unused] var $t5: u64 + var $t6: u64 0: $t2 := copy($t0) - 1: $t5 := 1 - 2: $t5 := +($t0, $t5) - 3: $t0 := move($t5) - 4: $t0 := move($t0) - 5: $t0 := m::add($t2, $t0) - 6: return $t0 + 1: $t5 := move($t0) + 2: $t6 := 1 + 3: $t5 := +($t5, $t6) + 4: $t0 := move($t5) + 5: $t0 := move($t0) + 6: $t0 := m::add($t2, $t0) + 7: return $t0 } ============ after DeadStoreElimination: ================ @@ -125,8 +145,10 @@ public fun m::test($t0: u64): u64 { [variant baseline] fun m::add($t0: u64, $t1: u64): u64 { var $t2: u64 [unused] - 0: $t0 := +($t0, $t1) - 1: return $t0 + var $t3: u64 [unused] + 0: $t0 := move($t0) + 1: $t0 := +($t0, $t1) + 2: return $t0 } @@ -137,12 +159,14 @@ public fun m::test($t0: u64): u64 { var $t3: u64 [unused] var $t4: u64 [unused] var $t5: u64 + var $t6: u64 0: $t2 := copy($t0) - 1: $t5 := 1 - 2: $t5 := +($t0, $t5) - 3: $t0 := move($t5) - 4: $t0 := m::add($t2, $t0) - 5: return $t0 + 1: $t5 := move($t0) + 2: $t6 := 1 + 3: $t5 := +($t5, $t6) + 4: $t0 := move($t5) + 5: $t0 := m::add($t2, $t0) + 6: return $t0 } @@ -159,7 +183,6 @@ B0: 3: Ret } public test(Arg0: u64): u64 /* def_idx: 1 */ { -L1: loc0: u64 B0: 0: CopyLoc[0](Arg0: u64) 1: MoveLoc[0](Arg0: u64) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_1.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_1.exp index 79aa80de12745..d916e03530cdb 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_1.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_1.exp @@ -6,6 +6,7 @@ fun m::foo($t0: bool, $t1: u64): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 0: $t3 := infer($t1) 1: if ($t0) goto 2 else goto 6 2: label L0 @@ -14,9 +15,10 @@ fun m::foo($t0: bool, $t1: u64): u64 { 5: goto 7 6: label L1 7: label L2 - 8: $t5 := 1 - 9: $t2 := +($t3, $t5) - 10: return $t2 + 8: $t5 := infer($t3) + 9: $t6 := 1 + 10: $t2 := +($t5, $t6) + 11: return $t2 } ============ after DeadStoreElimination: ================ @@ -27,6 +29,7 @@ fun m::foo($t0: bool, $t1: u64): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 0: $t3 := move($t1) 1: if ($t0) goto 4 else goto 2 2: label L3 @@ -35,9 +38,10 @@ fun m::foo($t0: bool, $t1: u64): u64 { 5: $t4 := 0 6: $t3 := move($t4) 7: label L2 - 8: $t5 := 1 - 9: $t2 := +($t3, $t5) - 10: return $t2 + 8: $t5 := move($t3) + 9: $t6 := 1 + 10: $t2 := +($t5, $t6) + 11: return $t2 } ============ after VariableCoalescingAnnotator: ================ @@ -48,6 +52,7 @@ fun m::foo($t0: bool, $t1: u64): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 # live vars: $t0, $t1 # events: b:$t0, b:$t1, e:$t1, b:$t3 0: $t3 := move($t1) @@ -69,14 +74,17 @@ fun m::foo($t0: bool, $t1: u64): u64 { # live vars: $t3 7: label L2 # live vars: $t3 - # events: b:$t5 - 8: $t5 := 1 - # live vars: $t3, $t5 - # events: e:$t3, e:$t5, b:$t2 - 9: $t2 := +($t3, $t5) + # events: e:$t3, b:$t5 + 8: $t5 := move($t3) + # live vars: $t5 + # events: b:$t6 + 9: $t6 := 1 + # live vars: $t5, $t6 + # events: e:$t5, e:$t6, b:$t2 + 10: $t2 := +($t5, $t6) # live vars: $t2 # events: e:$t2 - 10: return $t2 + 11: return $t2 } ============ after VariableCoalescingTransformer: ================ @@ -87,6 +95,7 @@ fun m::foo($t0: bool, $t1: u64): u64 { var $t3: u64 [unused] var $t4: u64 var $t5: u64 [unused] + var $t6: u64 [unused] 0: $t1 := move($t1) 1: if ($t0) goto 4 else goto 2 2: label L3 @@ -95,9 +104,10 @@ fun m::foo($t0: bool, $t1: u64): u64 { 5: $t4 := 0 6: $t1 := move($t4) 7: label L2 - 8: $t4 := 1 - 9: $t1 := +($t1, $t4) - 10: return $t1 + 8: $t1 := move($t1) + 9: $t4 := 1 + 10: $t1 := +($t1, $t4) + 11: return $t1 } ============ after DeadStoreElimination: ================ @@ -108,16 +118,19 @@ fun m::foo($t0: bool, $t1: u64): u64 { var $t3: u64 [unused] var $t4: u64 var $t5: u64 [unused] - 0: if ($t0) goto 3 else goto 1 - 1: label L3 - 2: goto 6 - 3: label L0 - 4: $t4 := 0 - 5: $t1 := move($t4) - 6: label L2 - 7: $t4 := 1 - 8: $t1 := +($t1, $t4) - 9: return $t1 + var $t6: u64 [unused] + 0: $t1 := move($t1) + 1: if ($t0) goto 4 else goto 2 + 2: label L3 + 3: goto 7 + 4: label L0 + 5: $t4 := 0 + 6: $t1 := move($t4) + 7: label L2 + 8: $t1 := move($t1) + 9: $t4 := 1 + 10: $t1 := +($t1, $t4) + 11: return $t1 } @@ -127,7 +140,6 @@ module c0ffee.m { foo(Arg0: bool, Arg1: u64): u64 /* def_idx: 0 */ { -L2: loc0: u64 B0: 0: MoveLoc[0](Arg0: bool) 1: BrTrue(3) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_1.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_1.opt.exp index 79aa80de12745..d916e03530cdb 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_1.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_1.opt.exp @@ -6,6 +6,7 @@ fun m::foo($t0: bool, $t1: u64): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 0: $t3 := infer($t1) 1: if ($t0) goto 2 else goto 6 2: label L0 @@ -14,9 +15,10 @@ fun m::foo($t0: bool, $t1: u64): u64 { 5: goto 7 6: label L1 7: label L2 - 8: $t5 := 1 - 9: $t2 := +($t3, $t5) - 10: return $t2 + 8: $t5 := infer($t3) + 9: $t6 := 1 + 10: $t2 := +($t5, $t6) + 11: return $t2 } ============ after DeadStoreElimination: ================ @@ -27,6 +29,7 @@ fun m::foo($t0: bool, $t1: u64): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 0: $t3 := move($t1) 1: if ($t0) goto 4 else goto 2 2: label L3 @@ -35,9 +38,10 @@ fun m::foo($t0: bool, $t1: u64): u64 { 5: $t4 := 0 6: $t3 := move($t4) 7: label L2 - 8: $t5 := 1 - 9: $t2 := +($t3, $t5) - 10: return $t2 + 8: $t5 := move($t3) + 9: $t6 := 1 + 10: $t2 := +($t5, $t6) + 11: return $t2 } ============ after VariableCoalescingAnnotator: ================ @@ -48,6 +52,7 @@ fun m::foo($t0: bool, $t1: u64): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 # live vars: $t0, $t1 # events: b:$t0, b:$t1, e:$t1, b:$t3 0: $t3 := move($t1) @@ -69,14 +74,17 @@ fun m::foo($t0: bool, $t1: u64): u64 { # live vars: $t3 7: label L2 # live vars: $t3 - # events: b:$t5 - 8: $t5 := 1 - # live vars: $t3, $t5 - # events: e:$t3, e:$t5, b:$t2 - 9: $t2 := +($t3, $t5) + # events: e:$t3, b:$t5 + 8: $t5 := move($t3) + # live vars: $t5 + # events: b:$t6 + 9: $t6 := 1 + # live vars: $t5, $t6 + # events: e:$t5, e:$t6, b:$t2 + 10: $t2 := +($t5, $t6) # live vars: $t2 # events: e:$t2 - 10: return $t2 + 11: return $t2 } ============ after VariableCoalescingTransformer: ================ @@ -87,6 +95,7 @@ fun m::foo($t0: bool, $t1: u64): u64 { var $t3: u64 [unused] var $t4: u64 var $t5: u64 [unused] + var $t6: u64 [unused] 0: $t1 := move($t1) 1: if ($t0) goto 4 else goto 2 2: label L3 @@ -95,9 +104,10 @@ fun m::foo($t0: bool, $t1: u64): u64 { 5: $t4 := 0 6: $t1 := move($t4) 7: label L2 - 8: $t4 := 1 - 9: $t1 := +($t1, $t4) - 10: return $t1 + 8: $t1 := move($t1) + 9: $t4 := 1 + 10: $t1 := +($t1, $t4) + 11: return $t1 } ============ after DeadStoreElimination: ================ @@ -108,16 +118,19 @@ fun m::foo($t0: bool, $t1: u64): u64 { var $t3: u64 [unused] var $t4: u64 var $t5: u64 [unused] - 0: if ($t0) goto 3 else goto 1 - 1: label L3 - 2: goto 6 - 3: label L0 - 4: $t4 := 0 - 5: $t1 := move($t4) - 6: label L2 - 7: $t4 := 1 - 8: $t1 := +($t1, $t4) - 9: return $t1 + var $t6: u64 [unused] + 0: $t1 := move($t1) + 1: if ($t0) goto 4 else goto 2 + 2: label L3 + 3: goto 7 + 4: label L0 + 5: $t4 := 0 + 6: $t1 := move($t4) + 7: label L2 + 8: $t1 := move($t1) + 9: $t4 := 1 + 10: $t1 := +($t1, $t4) + 11: return $t1 } @@ -127,7 +140,6 @@ module c0ffee.m { foo(Arg0: bool, Arg1: u64): u64 /* def_idx: 0 */ { -L2: loc0: u64 B0: 0: MoveLoc[0](Arg0: bool) 1: BrTrue(3) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/bug_12068.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/bug_12068.exp index 3d253d06f0147..9330b8cd46a7c 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/bug_12068.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/bug_12068.exp @@ -6,34 +6,38 @@ fun m::main() { var $t1: bool var $t2: u64 var $t3: u64 - var $t4: bool - var $t5: u64 + var $t4: u64 + var $t5: bool var $t6: u64 + var $t7: u64 + var $t8: u64 0: $t0 := 0 1: label L0 2: $t1 := true - 3: if ($t1) goto 4 else goto 10 + 3: if ($t1) goto 4 else goto 11 4: label L2 - 5: $t3 := 1 - 6: $t2 := +($t0, $t3) - 7: $t0 := infer($t2) - 8: goto 14 - 9: goto 12 - 10: label L3 - 11: goto 14 - 12: label L4 - 13: goto 1 - 14: label L1 - 15: $t5 := 1 - 16: $t4 := ==($t0, $t5) - 17: if ($t4) goto 18 else goto 20 - 18: label L5 - 19: goto 23 - 20: label L6 - 21: $t6 := 42 - 22: abort($t6) - 23: label L7 - 24: return () + 5: $t3 := infer($t0) + 6: $t4 := 1 + 7: $t2 := +($t3, $t4) + 8: $t0 := infer($t2) + 9: goto 15 + 10: goto 13 + 11: label L3 + 12: goto 15 + 13: label L4 + 14: goto 1 + 15: label L1 + 16: $t6 := infer($t0) + 17: $t7 := 1 + 18: $t5 := ==($t6, $t7) + 19: if ($t5) goto 20 else goto 22 + 20: label L5 + 21: goto 25 + 22: label L6 + 23: $t8 := 42 + 24: abort($t8) + 25: label L7 + 26: return () } ============ after DeadStoreElimination: ================ @@ -44,27 +48,31 @@ fun m::main() { var $t1: bool var $t2: u64 var $t3: u64 - var $t4: bool - var $t5: u64 + var $t4: u64 + var $t5: bool var $t6: u64 + var $t7: u64 + var $t8: u64 0: $t0 := 0 1: $t1 := true 2: if ($t1) goto 5 else goto 3 3: label L7 - 4: goto 9 + 4: goto 10 5: label L2 - 6: $t3 := 1 - 7: $t2 := +($t0, $t3) - 8: $t0 := move($t2) - 9: label L1 - 10: $t5 := 1 - 11: $t4 := ==($t0, $t5) - 12: if ($t4) goto 13 else goto 15 - 13: label L5 - 14: return () - 15: label L6 - 16: $t6 := 42 - 17: abort($t6) + 6: $t3 := move($t0) + 7: $t4 := 1 + 8: $t2 := +($t3, $t4) + 9: $t0 := move($t2) + 10: label L1 + 11: $t6 := move($t0) + 12: $t7 := 1 + 13: $t5 := ==($t6, $t7) + 14: if ($t5) goto 15 else goto 17 + 15: label L5 + 16: return () + 17: label L6 + 18: $t8 := 42 + 19: abort($t8) } ============ after VariableCoalescingAnnotator: ================ @@ -75,9 +83,11 @@ fun m::main() { var $t1: bool var $t2: u64 var $t3: u64 - var $t4: bool - var $t5: u64 + var $t4: u64 + var $t5: bool var $t6: u64 + var $t7: u64 + var $t8: u64 # live vars: # events: b:$t0 0: $t0 := 0 @@ -90,41 +100,47 @@ fun m::main() { # live vars: $t0 3: label L7 # live vars: $t0 - 4: goto 9 + 4: goto 10 # live vars: $t0 5: label L2 # live vars: $t0 # events: b:$t3 - 6: $t3 := 1 - # live vars: $t0, $t3 - # events: e:$t3, b:$t2 - 7: $t2 := +($t0, $t3) + 6: $t3 := move($t0) + # live vars: $t3 + # events: b:$t4 + 7: $t4 := 1 + # live vars: $t3, $t4 + # events: e:$t3, e:$t4, b:$t2 + 8: $t2 := +($t3, $t4) # live vars: $t2 # events: e:$t2 - 8: $t0 := move($t2) + 9: $t0 := move($t2) # live vars: $t0 - 9: label L1 + 10: label L1 # live vars: $t0 - # events: b:$t5 - 10: $t5 := 1 - # live vars: $t0, $t5 - # events: e:$t0, e:$t5, b:$t4 - 11: $t4 := ==($t0, $t5) - # live vars: $t4 - # events: e:$t4 - 12: if ($t4) goto 13 else goto 15 + # events: e:$t0, b:$t6 + 11: $t6 := move($t0) + # live vars: $t6 + # events: b:$t7 + 12: $t7 := 1 + # live vars: $t6, $t7 + # events: e:$t6, e:$t7, b:$t5 + 13: $t5 := ==($t6, $t7) + # live vars: $t5 + # events: e:$t5 + 14: if ($t5) goto 15 else goto 17 # live vars: - 13: label L5 + 15: label L5 # live vars: - 14: return () + 16: return () # live vars: - 15: label L6 + 17: label L6 # live vars: - # events: b:$t6 - 16: $t6 := 42 - # live vars: $t6 - # events: e:$t6 - 17: abort($t6) + # events: b:$t8 + 18: $t8 := 42 + # live vars: $t8 + # events: e:$t8 + 19: abort($t8) } ============ after VariableCoalescingTransformer: ================ @@ -135,27 +151,31 @@ fun m::main() { var $t1: bool var $t2: u64 [unused] var $t3: u64 - var $t4: bool [unused] - var $t5: u64 [unused] + var $t4: u64 + var $t5: bool [unused] var $t6: u64 [unused] + var $t7: u64 [unused] + var $t8: u64 [unused] 0: $t0 := 0 1: $t1 := true 2: if ($t1) goto 5 else goto 3 3: label L7 - 4: goto 9 + 4: goto 10 5: label L2 - 6: $t3 := 1 - 7: $t3 := +($t0, $t3) - 8: $t0 := move($t3) - 9: label L1 - 10: $t3 := 1 - 11: $t1 := ==($t0, $t3) - 12: if ($t1) goto 13 else goto 15 - 13: label L5 - 14: return () - 15: label L6 - 16: $t0 := 42 - 17: abort($t0) + 6: $t3 := move($t0) + 7: $t4 := 1 + 8: $t3 := +($t3, $t4) + 9: $t0 := move($t3) + 10: label L1 + 11: $t0 := move($t0) + 12: $t3 := 1 + 13: $t1 := ==($t0, $t3) + 14: if ($t1) goto 15 else goto 17 + 15: label L5 + 16: return () + 17: label L6 + 18: $t0 := 42 + 19: abort($t0) } ============ after DeadStoreElimination: ================ @@ -166,27 +186,31 @@ fun m::main() { var $t1: bool var $t2: u64 [unused] var $t3: u64 - var $t4: bool [unused] - var $t5: u64 [unused] + var $t4: u64 + var $t5: bool [unused] var $t6: u64 [unused] + var $t7: u64 [unused] + var $t8: u64 [unused] 0: $t0 := 0 1: $t1 := true 2: if ($t1) goto 5 else goto 3 3: label L7 - 4: goto 9 + 4: goto 10 5: label L2 - 6: $t3 := 1 - 7: $t3 := +($t0, $t3) - 8: $t0 := move($t3) - 9: label L1 - 10: $t3 := 1 - 11: $t1 := ==($t0, $t3) - 12: if ($t1) goto 13 else goto 15 - 13: label L5 - 14: return () - 15: label L6 - 16: $t0 := 42 - 17: abort($t0) + 6: $t3 := move($t0) + 7: $t4 := 1 + 8: $t3 := +($t3, $t4) + 9: $t0 := move($t3) + 10: label L1 + 11: $t0 := move($t0) + 12: $t3 := 1 + 13: $t1 := ==($t0, $t3) + 14: if ($t1) goto 15 else goto 17 + 15: label L5 + 16: return () + 17: label L6 + 18: $t0 := 42 + 19: abort($t0) } @@ -197,7 +221,6 @@ module 32.m { main() /* def_idx: 0 */ { L0: loc0: u64 -L1: loc1: u64 B0: 0: LdU64(0) 1: StLoc[0](loc0: u64) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/bug_12068.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/bug_12068.opt.exp index 3d253d06f0147..9330b8cd46a7c 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/bug_12068.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/bug_12068.opt.exp @@ -6,34 +6,38 @@ fun m::main() { var $t1: bool var $t2: u64 var $t3: u64 - var $t4: bool - var $t5: u64 + var $t4: u64 + var $t5: bool var $t6: u64 + var $t7: u64 + var $t8: u64 0: $t0 := 0 1: label L0 2: $t1 := true - 3: if ($t1) goto 4 else goto 10 + 3: if ($t1) goto 4 else goto 11 4: label L2 - 5: $t3 := 1 - 6: $t2 := +($t0, $t3) - 7: $t0 := infer($t2) - 8: goto 14 - 9: goto 12 - 10: label L3 - 11: goto 14 - 12: label L4 - 13: goto 1 - 14: label L1 - 15: $t5 := 1 - 16: $t4 := ==($t0, $t5) - 17: if ($t4) goto 18 else goto 20 - 18: label L5 - 19: goto 23 - 20: label L6 - 21: $t6 := 42 - 22: abort($t6) - 23: label L7 - 24: return () + 5: $t3 := infer($t0) + 6: $t4 := 1 + 7: $t2 := +($t3, $t4) + 8: $t0 := infer($t2) + 9: goto 15 + 10: goto 13 + 11: label L3 + 12: goto 15 + 13: label L4 + 14: goto 1 + 15: label L1 + 16: $t6 := infer($t0) + 17: $t7 := 1 + 18: $t5 := ==($t6, $t7) + 19: if ($t5) goto 20 else goto 22 + 20: label L5 + 21: goto 25 + 22: label L6 + 23: $t8 := 42 + 24: abort($t8) + 25: label L7 + 26: return () } ============ after DeadStoreElimination: ================ @@ -44,27 +48,31 @@ fun m::main() { var $t1: bool var $t2: u64 var $t3: u64 - var $t4: bool - var $t5: u64 + var $t4: u64 + var $t5: bool var $t6: u64 + var $t7: u64 + var $t8: u64 0: $t0 := 0 1: $t1 := true 2: if ($t1) goto 5 else goto 3 3: label L7 - 4: goto 9 + 4: goto 10 5: label L2 - 6: $t3 := 1 - 7: $t2 := +($t0, $t3) - 8: $t0 := move($t2) - 9: label L1 - 10: $t5 := 1 - 11: $t4 := ==($t0, $t5) - 12: if ($t4) goto 13 else goto 15 - 13: label L5 - 14: return () - 15: label L6 - 16: $t6 := 42 - 17: abort($t6) + 6: $t3 := move($t0) + 7: $t4 := 1 + 8: $t2 := +($t3, $t4) + 9: $t0 := move($t2) + 10: label L1 + 11: $t6 := move($t0) + 12: $t7 := 1 + 13: $t5 := ==($t6, $t7) + 14: if ($t5) goto 15 else goto 17 + 15: label L5 + 16: return () + 17: label L6 + 18: $t8 := 42 + 19: abort($t8) } ============ after VariableCoalescingAnnotator: ================ @@ -75,9 +83,11 @@ fun m::main() { var $t1: bool var $t2: u64 var $t3: u64 - var $t4: bool - var $t5: u64 + var $t4: u64 + var $t5: bool var $t6: u64 + var $t7: u64 + var $t8: u64 # live vars: # events: b:$t0 0: $t0 := 0 @@ -90,41 +100,47 @@ fun m::main() { # live vars: $t0 3: label L7 # live vars: $t0 - 4: goto 9 + 4: goto 10 # live vars: $t0 5: label L2 # live vars: $t0 # events: b:$t3 - 6: $t3 := 1 - # live vars: $t0, $t3 - # events: e:$t3, b:$t2 - 7: $t2 := +($t0, $t3) + 6: $t3 := move($t0) + # live vars: $t3 + # events: b:$t4 + 7: $t4 := 1 + # live vars: $t3, $t4 + # events: e:$t3, e:$t4, b:$t2 + 8: $t2 := +($t3, $t4) # live vars: $t2 # events: e:$t2 - 8: $t0 := move($t2) + 9: $t0 := move($t2) # live vars: $t0 - 9: label L1 + 10: label L1 # live vars: $t0 - # events: b:$t5 - 10: $t5 := 1 - # live vars: $t0, $t5 - # events: e:$t0, e:$t5, b:$t4 - 11: $t4 := ==($t0, $t5) - # live vars: $t4 - # events: e:$t4 - 12: if ($t4) goto 13 else goto 15 + # events: e:$t0, b:$t6 + 11: $t6 := move($t0) + # live vars: $t6 + # events: b:$t7 + 12: $t7 := 1 + # live vars: $t6, $t7 + # events: e:$t6, e:$t7, b:$t5 + 13: $t5 := ==($t6, $t7) + # live vars: $t5 + # events: e:$t5 + 14: if ($t5) goto 15 else goto 17 # live vars: - 13: label L5 + 15: label L5 # live vars: - 14: return () + 16: return () # live vars: - 15: label L6 + 17: label L6 # live vars: - # events: b:$t6 - 16: $t6 := 42 - # live vars: $t6 - # events: e:$t6 - 17: abort($t6) + # events: b:$t8 + 18: $t8 := 42 + # live vars: $t8 + # events: e:$t8 + 19: abort($t8) } ============ after VariableCoalescingTransformer: ================ @@ -135,27 +151,31 @@ fun m::main() { var $t1: bool var $t2: u64 [unused] var $t3: u64 - var $t4: bool [unused] - var $t5: u64 [unused] + var $t4: u64 + var $t5: bool [unused] var $t6: u64 [unused] + var $t7: u64 [unused] + var $t8: u64 [unused] 0: $t0 := 0 1: $t1 := true 2: if ($t1) goto 5 else goto 3 3: label L7 - 4: goto 9 + 4: goto 10 5: label L2 - 6: $t3 := 1 - 7: $t3 := +($t0, $t3) - 8: $t0 := move($t3) - 9: label L1 - 10: $t3 := 1 - 11: $t1 := ==($t0, $t3) - 12: if ($t1) goto 13 else goto 15 - 13: label L5 - 14: return () - 15: label L6 - 16: $t0 := 42 - 17: abort($t0) + 6: $t3 := move($t0) + 7: $t4 := 1 + 8: $t3 := +($t3, $t4) + 9: $t0 := move($t3) + 10: label L1 + 11: $t0 := move($t0) + 12: $t3 := 1 + 13: $t1 := ==($t0, $t3) + 14: if ($t1) goto 15 else goto 17 + 15: label L5 + 16: return () + 17: label L6 + 18: $t0 := 42 + 19: abort($t0) } ============ after DeadStoreElimination: ================ @@ -166,27 +186,31 @@ fun m::main() { var $t1: bool var $t2: u64 [unused] var $t3: u64 - var $t4: bool [unused] - var $t5: u64 [unused] + var $t4: u64 + var $t5: bool [unused] var $t6: u64 [unused] + var $t7: u64 [unused] + var $t8: u64 [unused] 0: $t0 := 0 1: $t1 := true 2: if ($t1) goto 5 else goto 3 3: label L7 - 4: goto 9 + 4: goto 10 5: label L2 - 6: $t3 := 1 - 7: $t3 := +($t0, $t3) - 8: $t0 := move($t3) - 9: label L1 - 10: $t3 := 1 - 11: $t1 := ==($t0, $t3) - 12: if ($t1) goto 13 else goto 15 - 13: label L5 - 14: return () - 15: label L6 - 16: $t0 := 42 - 17: abort($t0) + 6: $t3 := move($t0) + 7: $t4 := 1 + 8: $t3 := +($t3, $t4) + 9: $t0 := move($t3) + 10: label L1 + 11: $t0 := move($t0) + 12: $t3 := 1 + 13: $t1 := ==($t0, $t3) + 14: if ($t1) goto 15 else goto 17 + 15: label L5 + 16: return () + 17: label L6 + 18: $t0 := 42 + 19: abort($t0) } @@ -197,7 +221,6 @@ module 32.m { main() /* def_idx: 0 */ { L0: loc0: u64 -L1: loc1: u64 B0: 0: LdU64(0) 1: StLoc[0](loc0: u64) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/call_1.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/call_1.exp index 3f4ff64c3e1c9..e7f5b6b27d6c2 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/call_1.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/call_1.exp @@ -140,7 +140,8 @@ fun m::test($t0: u64): u64 { [variant baseline] fun m::id($t0: u64): u64 { var $t1: u64 [unused] - 0: return $t0 + 0: $t0 := move($t0) + 1: return $t0 } @@ -152,10 +153,11 @@ fun m::test($t0: u64): u64 { var $t4: u64 [unused] var $t5: u64 [unused] var $t6: u64 [unused] - 0: $t0 := m::id($t0) + 0: $t0 := move($t0) 1: $t0 := m::id($t0) 2: $t0 := m::id($t0) - 3: return $t0 + 3: $t0 := m::id($t0) + 4: return $t0 } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/call_1.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/call_1.opt.exp index 3f4ff64c3e1c9..e7f5b6b27d6c2 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/call_1.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/call_1.opt.exp @@ -140,7 +140,8 @@ fun m::test($t0: u64): u64 { [variant baseline] fun m::id($t0: u64): u64 { var $t1: u64 [unused] - 0: return $t0 + 0: $t0 := move($t0) + 1: return $t0 } @@ -152,10 +153,11 @@ fun m::test($t0: u64): u64 { var $t4: u64 [unused] var $t5: u64 [unused] var $t6: u64 [unused] - 0: $t0 := m::id($t0) + 0: $t0 := move($t0) 1: $t0 := m::id($t0) 2: $t0 := m::id($t0) - 3: return $t0 + 3: $t0 := m::id($t0) + 4: return $t0 } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/call_2.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/call_2.exp index d51e981ce065e..49b17686bb69a 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/call_2.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/call_2.exp @@ -144,9 +144,10 @@ fun m::test($t0: u64): u64 { var $t4: u64 [unused] var $t5: &mut u64 0: $t2 := copy($t0) - 1: $t5 := borrow_local($t2) - 2: m::update($t5) - 3: return $t0 + 1: $t0 := move($t0) + 2: $t5 := borrow_local($t2) + 3: m::update($t5) + 4: return $t0 } @@ -167,9 +168,9 @@ L1: loc0: u64 B0: 0: CopyLoc[0](Arg0: u64) 1: StLoc[1](loc0: u64) - 2: MutBorrowLoc[1](loc0: u64) - 3: Call update(&mut u64) - 4: MoveLoc[0](Arg0: u64) + 2: MoveLoc[0](Arg0: u64) + 3: MutBorrowLoc[1](loc0: u64) + 4: Call update(&mut u64) 5: Ret } } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/call_2.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/call_2.opt.exp index d51e981ce065e..49b17686bb69a 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/call_2.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/call_2.opt.exp @@ -144,9 +144,10 @@ fun m::test($t0: u64): u64 { var $t4: u64 [unused] var $t5: &mut u64 0: $t2 := copy($t0) - 1: $t5 := borrow_local($t2) - 2: m::update($t5) - 3: return $t0 + 1: $t0 := move($t0) + 2: $t5 := borrow_local($t2) + 3: m::update($t5) + 4: return $t0 } @@ -167,9 +168,9 @@ L1: loc0: u64 B0: 0: CopyLoc[0](Arg0: u64) 1: StLoc[1](loc0: u64) - 2: MutBorrowLoc[1](loc0: u64) - 3: Call update(&mut u64) - 4: MoveLoc[0](Arg0: u64) + 2: MoveLoc[0](Arg0: u64) + 3: MutBorrowLoc[1](loc0: u64) + 4: Call update(&mut u64) 5: Ret } } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/cant_coalesce_1.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/cant_coalesce_1.exp index 4006c3f61f920..e00c0bf60093f 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/cant_coalesce_1.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/cant_coalesce_1.exp @@ -13,10 +13,12 @@ public fun m::test($t0: u64): u64 { var $t1: u64 var $t2: u64 var $t3: u64 - 0: $t2 := +($t0, $t0) - 1: $t3 := 2 - 2: $t1 := infer($t3) - 3: return $t1 + var $t4: u64 + 0: $t3 := infer($t0) + 1: $t2 := +($t3, $t0) + 2: $t4 := 2 + 3: $t1 := infer($t4) + 4: return $t1 } @@ -34,10 +36,12 @@ public fun m::test($t0: u64): u64 { var $t1: u64 var $t2: u64 var $t3: u64 - 0: $t2 := +($t0, $t0) - 1: $t3 := 2 - 2: $t1 := move($t3) - 3: return $t1 + var $t4: u64 + 0: $t3 := copy($t0) + 1: $t2 := +($t3, $t0) + 2: $t4 := 2 + 3: $t1 := move($t4) + 4: return $t1 } ============ after VariableCoalescingAnnotator: ================ @@ -47,18 +51,22 @@ public fun m::test($t0: u64): u64 { var $t1: u64 var $t2: u64 var $t3: u64 + var $t4: u64 # live vars: $t0 - # events: b:$t0, e:$t0, e:$t2, b:$t2 - 0: $t2 := +($t0, $t0) + # events: b:$t0, b:$t3 + 0: $t3 := copy($t0) + # live vars: $t0, $t3 + # events: e:$t0, e:$t2, e:$t3, b:$t2 + 1: $t2 := +($t3, $t0) # live vars: - # events: b:$t3 - 1: $t3 := 2 - # live vars: $t3 - # events: e:$t3, b:$t1 - 2: $t1 := move($t3) + # events: b:$t4 + 2: $t4 := 2 + # live vars: $t4 + # events: e:$t4, b:$t1 + 3: $t1 := move($t4) # live vars: $t1 # events: e:$t1 - 3: return $t1 + 4: return $t1 } ============ after VariableCoalescingTransformer: ================ @@ -67,11 +75,13 @@ public fun m::test($t0: u64): u64 { public fun m::test($t0: u64): u64 { var $t1: u64 [unused] var $t2: u64 - var $t3: u64 [unused] - 0: $t0 := +($t0, $t0) - 1: $t2 := 2 - 2: $t2 := move($t2) - 3: return $t2 + var $t3: u64 + var $t4: u64 [unused] + 0: $t3 := copy($t0) + 1: $t0 := +($t3, $t0) + 2: $t2 := 2 + 3: $t2 := move($t2) + 4: return $t2 } ============ after DeadStoreElimination: ================ @@ -80,10 +90,12 @@ public fun m::test($t0: u64): u64 { public fun m::test($t0: u64): u64 { var $t1: u64 [unused] var $t2: u64 - var $t3: u64 [unused] - 0: $t0 := +($t0, $t0) - 1: $t2 := 2 - 2: return $t2 + var $t3: u64 + var $t4: u64 [unused] + 0: $t3 := copy($t0) + 1: $t0 := +($t3, $t0) + 2: $t2 := 2 + 3: return $t2 } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/cant_coalesce_1.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/cant_coalesce_1.opt.exp index 398c9816847c6..3c13338dc2ac1 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/cant_coalesce_1.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/cant_coalesce_1.opt.exp @@ -12,9 +12,11 @@ warning: Unused local variable `x`. Consider removing or prefixing with an under public fun m::test($t0: u64): u64 { var $t1: u64 var $t2: u64 - 0: $t2 := +($t0, $t0) - 1: $t1 := 2 - 2: return $t1 + var $t3: u64 + 0: $t3 := infer($t0) + 1: $t2 := +($t3, $t0) + 2: $t1 := 2 + 3: return $t1 } @@ -31,9 +33,11 @@ warning: Unused assignment to `x`. Consider removing or prefixing with an unders public fun m::test($t0: u64): u64 { var $t1: u64 var $t2: u64 - 0: $t2 := +($t0, $t0) - 1: $t1 := 2 - 2: return $t1 + var $t3: u64 + 0: $t3 := copy($t0) + 1: $t2 := +($t3, $t0) + 2: $t1 := 2 + 3: return $t1 } ============ after VariableCoalescingAnnotator: ================ @@ -42,15 +46,19 @@ public fun m::test($t0: u64): u64 { public fun m::test($t0: u64): u64 { var $t1: u64 var $t2: u64 + var $t3: u64 # live vars: $t0 - # events: b:$t0, e:$t0, e:$t2, b:$t2 - 0: $t2 := +($t0, $t0) + # events: b:$t0, b:$t3 + 0: $t3 := copy($t0) + # live vars: $t0, $t3 + # events: e:$t0, e:$t2, e:$t3, b:$t2 + 1: $t2 := +($t3, $t0) # live vars: # events: b:$t1 - 1: $t1 := 2 + 2: $t1 := 2 # live vars: $t1 # events: e:$t1 - 2: return $t1 + 3: return $t1 } ============ after VariableCoalescingTransformer: ================ @@ -59,9 +67,11 @@ public fun m::test($t0: u64): u64 { public fun m::test($t0: u64): u64 { var $t1: u64 [unused] var $t2: u64 - 0: $t0 := +($t0, $t0) - 1: $t2 := 2 - 2: return $t2 + var $t3: u64 + 0: $t3 := copy($t0) + 1: $t0 := +($t3, $t0) + 2: $t2 := 2 + 3: return $t2 } ============ after DeadStoreElimination: ================ @@ -70,9 +80,11 @@ public fun m::test($t0: u64): u64 { public fun m::test($t0: u64): u64 { var $t1: u64 [unused] var $t2: u64 - 0: $t0 := +($t0, $t0) - 1: $t2 := 2 - 2: return $t2 + var $t3: u64 + 0: $t3 := copy($t0) + 1: $t0 := +($t3, $t0) + 2: $t2 := 2 + 3: return $t2 } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/cant_copy_propagate.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/cant_copy_propagate.exp index 7204294002594..da6e6748d8cc2 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/cant_copy_propagate.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/cant_copy_propagate.exp @@ -15,20 +15,22 @@ fun m::test($t0: u64, $t1: bool) { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 0: $t2 := move($t0) 1: if ($t1) goto 2 else goto 5 2: label L0 3: m::consume($t2) - 4: goto 12 + 4: goto 13 5: label L1 6: $t3 := 99 7: $t0 := infer($t3) 8: $t4 := infer($t2) - 9: $t6 := 1 - 10: $t5 := +($t4, $t6) - 11: $t4 := infer($t5) - 12: label L2 - 13: return () + 9: $t6 := infer($t4) + 10: $t7 := 1 + 11: $t5 := +($t6, $t7) + 12: $t4 := infer($t5) + 13: label L2 + 14: return () } @@ -61,6 +63,7 @@ fun m::test($t0: u64, $t1: bool) { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 0: $t2 := move($t0) 1: if ($t1) goto 2 else goto 6 2: label L0 @@ -69,9 +72,10 @@ fun m::test($t0: u64, $t1: bool) { 5: return () 6: label L1 7: $t4 := move($t2) - 8: $t6 := 1 - 9: $t5 := +($t4, $t6) - 10: goto 4 + 8: $t6 := move($t4) + 9: $t7 := 1 + 10: $t5 := +($t6, $t7) + 11: goto 4 } ============ after VariableCoalescingAnnotator: ================ @@ -92,6 +96,7 @@ fun m::test($t0: u64, $t1: bool) { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 # live vars: $t0, $t1 # events: b:$t0, b:$t1, e:$t0, b:$t2 0: $t2 := move($t0) @@ -112,13 +117,16 @@ fun m::test($t0: u64, $t1: bool) { # events: e:$t2, b:$t4 7: $t4 := move($t2) # live vars: $t4 - # events: b:$t6 - 8: $t6 := 1 - # live vars: $t4, $t6 - # events: e:$t4, e:$t5, e:$t6, b:$t5 - 9: $t5 := +($t4, $t6) + # events: e:$t4, b:$t6 + 8: $t6 := move($t4) + # live vars: $t6 + # events: b:$t7 + 9: $t7 := 1 + # live vars: $t6, $t7 + # events: e:$t5, e:$t6, e:$t7, b:$t5 + 10: $t5 := +($t6, $t7) # live vars: - 10: goto 4 + 11: goto 4 } ============ after VariableCoalescingTransformer: ================ @@ -136,7 +144,8 @@ fun m::test($t0: u64, $t1: bool) { var $t3: u64 [unused] var $t4: u64 [unused] var $t5: u64 [unused] - var $t6: u64 + var $t6: u64 [unused] + var $t7: u64 0: $t0 := move($t0) 1: if ($t1) goto 2 else goto 6 2: label L0 @@ -145,9 +154,10 @@ fun m::test($t0: u64, $t1: bool) { 5: return () 6: label L1 7: $t0 := move($t0) - 8: $t6 := 1 - 9: $t0 := +($t0, $t6) - 10: goto 4 + 8: $t0 := move($t0) + 9: $t7 := 1 + 10: $t0 := +($t0, $t7) + 11: goto 4 } ============ after DeadStoreElimination: ================ @@ -165,16 +175,19 @@ fun m::test($t0: u64, $t1: bool) { var $t3: u64 [unused] var $t4: u64 [unused] var $t5: u64 [unused] - var $t6: u64 - 0: if ($t1) goto 1 else goto 5 - 1: label L0 - 2: m::consume($t0) - 3: label L2 - 4: return () - 5: label L1 - 6: $t6 := 1 - 7: $t0 := +($t0, $t6) - 8: goto 3 + var $t6: u64 [unused] + var $t7: u64 + 0: $t0 := move($t0) + 1: if ($t1) goto 2 else goto 6 + 2: label L0 + 3: m::consume($t0) + 4: label L2 + 5: return () + 6: label L1 + 7: $t0 := move($t0) + 8: $t7 := 1 + 9: $t0 := +($t0, $t7) + 10: goto 4 } @@ -188,7 +201,6 @@ B0: 0: Ret } test(Arg0: u64, Arg1: bool) /* def_idx: 1 */ { -L2: loc0: u64 B0: 0: MoveLoc[1](Arg1: bool) 1: BrFalse(5) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/cant_copy_propagate.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/cant_copy_propagate.opt.exp index 7204294002594..da6e6748d8cc2 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/cant_copy_propagate.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/cant_copy_propagate.opt.exp @@ -15,20 +15,22 @@ fun m::test($t0: u64, $t1: bool) { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 0: $t2 := move($t0) 1: if ($t1) goto 2 else goto 5 2: label L0 3: m::consume($t2) - 4: goto 12 + 4: goto 13 5: label L1 6: $t3 := 99 7: $t0 := infer($t3) 8: $t4 := infer($t2) - 9: $t6 := 1 - 10: $t5 := +($t4, $t6) - 11: $t4 := infer($t5) - 12: label L2 - 13: return () + 9: $t6 := infer($t4) + 10: $t7 := 1 + 11: $t5 := +($t6, $t7) + 12: $t4 := infer($t5) + 13: label L2 + 14: return () } @@ -61,6 +63,7 @@ fun m::test($t0: u64, $t1: bool) { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 0: $t2 := move($t0) 1: if ($t1) goto 2 else goto 6 2: label L0 @@ -69,9 +72,10 @@ fun m::test($t0: u64, $t1: bool) { 5: return () 6: label L1 7: $t4 := move($t2) - 8: $t6 := 1 - 9: $t5 := +($t4, $t6) - 10: goto 4 + 8: $t6 := move($t4) + 9: $t7 := 1 + 10: $t5 := +($t6, $t7) + 11: goto 4 } ============ after VariableCoalescingAnnotator: ================ @@ -92,6 +96,7 @@ fun m::test($t0: u64, $t1: bool) { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 # live vars: $t0, $t1 # events: b:$t0, b:$t1, e:$t0, b:$t2 0: $t2 := move($t0) @@ -112,13 +117,16 @@ fun m::test($t0: u64, $t1: bool) { # events: e:$t2, b:$t4 7: $t4 := move($t2) # live vars: $t4 - # events: b:$t6 - 8: $t6 := 1 - # live vars: $t4, $t6 - # events: e:$t4, e:$t5, e:$t6, b:$t5 - 9: $t5 := +($t4, $t6) + # events: e:$t4, b:$t6 + 8: $t6 := move($t4) + # live vars: $t6 + # events: b:$t7 + 9: $t7 := 1 + # live vars: $t6, $t7 + # events: e:$t5, e:$t6, e:$t7, b:$t5 + 10: $t5 := +($t6, $t7) # live vars: - 10: goto 4 + 11: goto 4 } ============ after VariableCoalescingTransformer: ================ @@ -136,7 +144,8 @@ fun m::test($t0: u64, $t1: bool) { var $t3: u64 [unused] var $t4: u64 [unused] var $t5: u64 [unused] - var $t6: u64 + var $t6: u64 [unused] + var $t7: u64 0: $t0 := move($t0) 1: if ($t1) goto 2 else goto 6 2: label L0 @@ -145,9 +154,10 @@ fun m::test($t0: u64, $t1: bool) { 5: return () 6: label L1 7: $t0 := move($t0) - 8: $t6 := 1 - 9: $t0 := +($t0, $t6) - 10: goto 4 + 8: $t0 := move($t0) + 9: $t7 := 1 + 10: $t0 := +($t0, $t7) + 11: goto 4 } ============ after DeadStoreElimination: ================ @@ -165,16 +175,19 @@ fun m::test($t0: u64, $t1: bool) { var $t3: u64 [unused] var $t4: u64 [unused] var $t5: u64 [unused] - var $t6: u64 - 0: if ($t1) goto 1 else goto 5 - 1: label L0 - 2: m::consume($t0) - 3: label L2 - 4: return () - 5: label L1 - 6: $t6 := 1 - 7: $t0 := +($t0, $t6) - 8: goto 3 + var $t6: u64 [unused] + var $t7: u64 + 0: $t0 := move($t0) + 1: if ($t1) goto 2 else goto 6 + 2: label L0 + 3: m::consume($t0) + 4: label L2 + 5: return () + 6: label L1 + 7: $t0 := move($t0) + 8: $t7 := 1 + 9: $t0 := +($t0, $t7) + 10: goto 4 } @@ -188,7 +201,6 @@ B0: 0: Ret } test(Arg0: u64, Arg1: bool) /* def_idx: 1 */ { -L2: loc0: u64 B0: 0: MoveLoc[1](Arg1: bool) 1: BrFalse(5) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/conditional.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/conditional.exp index 4259871b96bbb..faacecd9a425d 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/conditional.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/conditional.exp @@ -7,18 +7,20 @@ fun m::test($t0: bool): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 0: $t2 := 2 1: if ($t0) goto 2 else goto 6 2: label L0 3: $t3 := 3 4: $t1 := infer($t3) - 5: goto 10 + 5: goto 11 6: label L1 - 7: $t5 := 1 - 8: $t4 := +($t2, $t5) - 9: $t1 := infer($t4) - 10: label L2 - 11: return $t1 + 7: $t5 := infer($t2) + 8: $t6 := 1 + 9: $t4 := +($t5, $t6) + 10: $t1 := infer($t4) + 11: label L2 + 12: return $t1 } ============ after DeadStoreElimination: ================ @@ -30,6 +32,7 @@ fun m::test($t0: bool): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 0: $t2 := 2 1: if ($t0) goto 2 else goto 7 2: label L0 @@ -38,10 +41,11 @@ fun m::test($t0: bool): u64 { 5: label L2 6: return $t1 7: label L1 - 8: $t5 := 1 - 9: $t4 := +($t2, $t5) - 10: $t1 := move($t4) - 11: goto 5 + 8: $t5 := move($t2) + 9: $t6 := 1 + 10: $t4 := +($t5, $t6) + 11: $t1 := move($t4) + 12: goto 5 } ============ after VariableCoalescingAnnotator: ================ @@ -53,6 +57,7 @@ fun m::test($t0: bool): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 # live vars: $t0 # events: b:$t0, b:$t2 0: $t2 := 2 @@ -74,17 +79,20 @@ fun m::test($t0: bool): u64 { # live vars: $t2 7: label L1 # live vars: $t2 - # events: b:$t5 - 8: $t5 := 1 - # live vars: $t2, $t5 - # events: e:$t2, e:$t5, b:$t4 - 9: $t4 := +($t2, $t5) + # events: e:$t2, b:$t5 + 8: $t5 := move($t2) + # live vars: $t5 + # events: b:$t6 + 9: $t6 := 1 + # live vars: $t5, $t6 + # events: e:$t5, e:$t6, b:$t4 + 10: $t4 := +($t5, $t6) # live vars: $t4 # events: e:$t4 - 10: $t1 := move($t4) + 11: $t1 := move($t4) # live vars: $t1 # events: e:$t1 - 11: goto 5 + 12: goto 5 } ============ after VariableCoalescingTransformer: ================ @@ -95,7 +103,8 @@ fun m::test($t0: bool): u64 { var $t2: u64 var $t3: u64 var $t4: u64 [unused] - var $t5: u64 + var $t5: u64 [unused] + var $t6: u64 0: $t2 := 2 1: if ($t0) goto 2 else goto 7 2: label L0 @@ -104,10 +113,11 @@ fun m::test($t0: bool): u64 { 5: label L2 6: return $t3 7: label L1 - 8: $t5 := 1 - 9: $t2 := +($t2, $t5) - 10: $t3 := move($t2) - 11: goto 5 + 8: $t2 := move($t2) + 9: $t6 := 1 + 10: $t2 := +($t2, $t6) + 11: $t3 := move($t2) + 12: goto 5 } ============ after DeadStoreElimination: ================ @@ -118,7 +128,8 @@ fun m::test($t0: bool): u64 { var $t2: u64 var $t3: u64 var $t4: u64 [unused] - var $t5: u64 + var $t5: u64 [unused] + var $t6: u64 0: $t2 := 2 1: if ($t0) goto 2 else goto 6 2: label L0 @@ -126,10 +137,11 @@ fun m::test($t0: bool): u64 { 4: label L2 5: return $t3 6: label L1 - 7: $t5 := 1 - 8: $t2 := +($t2, $t5) - 9: $t3 := move($t2) - 10: goto 4 + 7: $t2 := move($t2) + 8: $t6 := 1 + 9: $t2 := +($t2, $t6) + 10: $t3 := move($t2) + 11: goto 4 } @@ -141,7 +153,6 @@ module c0ffee.m { test(Arg0: bool): u64 /* def_idx: 0 */ { L1: loc0: u64 L2: loc1: u64 -L3: loc2: u64 B0: 0: LdU64(2) 1: StLoc[1](loc0: u64) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_2.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_2.exp index 9467564dc9e2c..70c9af2424c4c 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_2.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_2.exp @@ -163,18 +163,20 @@ fun m::consume_($t0: 0xc0ffee::m::W) { [variant baseline] public fun m::test1($t0: u64) { var $t1: u64 [unused] - 0: m::consume($t0) + 0: $t0 := move($t0) 1: m::consume($t0) - 2: return () + 2: m::consume($t0) + 3: return () } [variant baseline] public fun m::test2($t0: 0xc0ffee::m::W) { var $t1: 0xc0ffee::m::W [unused] - 0: m::consume_($t0) + 0: $t0 := move($t0) 1: m::consume_($t0) - 2: return () + 2: m::consume_($t0) + 3: return () } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_2.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_2.opt.exp index 9467564dc9e2c..70c9af2424c4c 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_2.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_2.opt.exp @@ -163,18 +163,20 @@ fun m::consume_($t0: 0xc0ffee::m::W) { [variant baseline] public fun m::test1($t0: u64) { var $t1: u64 [unused] - 0: m::consume($t0) + 0: $t0 := move($t0) 1: m::consume($t0) - 2: return () + 2: m::consume($t0) + 3: return () } [variant baseline] public fun m::test2($t0: 0xc0ffee::m::W) { var $t1: 0xc0ffee::m::W [unused] - 0: m::consume_($t0) + 0: $t0 := move($t0) 1: m::consume_($t0) - 2: return () + 2: m::consume_($t0) + 3: return () } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_dead_store.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_dead_store.exp index 532b75388a4fb..eb2737329ba18 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_dead_store.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_dead_store.exp @@ -6,23 +6,27 @@ public fun m::test1($t0: u64, $t1: u64, $t2: u64) { var $t4: bool var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 0: $t3 := 0 1: label L0 - 2: $t4 := <($t3, $t0) - 3: if ($t4) goto 4 else goto 11 - 4: label L2 - 5: $t1 := infer($t2) - 6: $t2 := infer($t1) - 7: $t6 := 1 - 8: $t5 := +($t3, $t6) - 9: $t3 := infer($t5) - 10: goto 13 - 11: label L3 + 2: $t5 := infer($t3) + 3: $t4 := <($t5, $t0) + 4: if ($t4) goto 5 else goto 13 + 5: label L2 + 6: $t1 := infer($t2) + 7: $t2 := infer($t1) + 8: $t7 := infer($t3) + 9: $t8 := 1 + 10: $t6 := +($t7, $t8) + 11: $t3 := infer($t6) 12: goto 15 - 13: label L4 - 14: goto 1 - 15: label L1 - 16: return () + 13: label L3 + 14: goto 17 + 15: label L4 + 16: goto 1 + 17: label L1 + 18: return () } @@ -32,22 +36,26 @@ public fun m::test2($t0: u64, $t1: u64) { var $t3: bool var $t4: u64 var $t5: u64 + var $t6: u64 + var $t7: u64 0: $t2 := 0 1: label L0 - 2: $t3 := <($t2, $t0) - 3: if ($t3) goto 4 else goto 10 - 4: label L2 - 5: $t1 := infer($t1) - 6: $t5 := 1 - 7: $t4 := +($t2, $t5) - 8: $t2 := infer($t4) - 9: goto 12 - 10: label L3 + 2: $t4 := infer($t2) + 3: $t3 := <($t4, $t0) + 4: if ($t3) goto 5 else goto 12 + 5: label L2 + 6: $t1 := infer($t1) + 7: $t6 := infer($t2) + 8: $t7 := 1 + 9: $t5 := +($t6, $t7) + 10: $t2 := infer($t5) 11: goto 14 - 12: label L4 - 13: goto 1 - 14: label L1 - 15: return () + 12: label L3 + 13: goto 16 + 14: label L4 + 15: goto 1 + 16: label L1 + 17: return () } ============ after DeadStoreElimination: ================ @@ -58,19 +66,23 @@ public fun m::test1($t0: u64, $t1: u64, $t2: u64) { var $t4: bool var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 0: $t3 := 0 1: label L0 - 2: $t4 := <($t3, $t0) - 3: if ($t4) goto 4 else goto 11 - 4: label L2 - 5: $t1 := move($t2) - 6: $t2 := move($t1) - 7: $t6 := 1 - 8: $t5 := +($t3, $t6) - 9: $t3 := move($t5) - 10: goto 1 - 11: label L3 - 12: return () + 2: $t5 := copy($t3) + 3: $t4 := <($t5, $t0) + 4: if ($t4) goto 5 else goto 13 + 5: label L2 + 6: $t1 := move($t2) + 7: $t2 := move($t1) + 8: $t7 := move($t3) + 9: $t8 := 1 + 10: $t6 := +($t7, $t8) + 11: $t3 := move($t6) + 12: goto 1 + 13: label L3 + 14: return () } @@ -80,17 +92,21 @@ public fun m::test2($t0: u64, $t1: u64) { var $t3: bool var $t4: u64 var $t5: u64 + var $t6: u64 + var $t7: u64 0: $t2 := 0 1: label L0 - 2: $t3 := <($t2, $t0) - 3: if ($t3) goto 4 else goto 9 - 4: label L2 - 5: $t5 := 1 - 6: $t4 := +($t2, $t5) - 7: $t2 := move($t4) - 8: goto 1 - 9: label L3 - 10: return () + 2: $t4 := copy($t2) + 3: $t3 := <($t4, $t0) + 4: if ($t3) goto 5 else goto 11 + 5: label L2 + 6: $t6 := move($t2) + 7: $t7 := 1 + 8: $t5 := +($t6, $t7) + 9: $t2 := move($t5) + 10: goto 1 + 11: label L3 + 12: return () } ============ after VariableCoalescingAnnotator: ================ @@ -101,40 +117,48 @@ public fun m::test1($t0: u64, $t1: u64, $t2: u64) { var $t4: bool var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 # live vars: $t0, $t1, $t2 # events: b:$t0, b:$t1, b:$t2, b:$t3 0: $t3 := 0 # live vars: $t0, $t2, $t3 1: label L0 # live vars: $t0, $t2, $t3 - # events: b:$t4 - 2: $t4 := <($t3, $t0) + # events: b:$t5 + 2: $t5 := copy($t3) + # live vars: $t0, $t2, $t3, $t5 + # events: e:$t5, b:$t4 + 3: $t4 := <($t5, $t0) # live vars: $t0, $t2, $t3, $t4 # events: e:$t4 - 3: if ($t4) goto 4 else goto 11 + 4: if ($t4) goto 5 else goto 13 # live vars: $t0, $t2, $t3 - 4: label L2 + 5: label L2 # live vars: $t0, $t2, $t3 - 5: $t1 := move($t2) + 6: $t1 := move($t2) # live vars: $t0, $t1, $t3 # events: e:$t1 - 6: $t2 := move($t1) + 7: $t2 := move($t1) # live vars: $t0, $t2, $t3 - # events: b:$t6 - 7: $t6 := 1 - # live vars: $t0, $t2, $t3, $t6 - # events: e:$t6, b:$t5 - 8: $t5 := +($t3, $t6) - # live vars: $t0, $t2, $t5 - # events: e:$t5 - 9: $t3 := move($t5) + # events: b:$t7 + 8: $t7 := move($t3) + # live vars: $t0, $t2, $t7 + # events: b:$t8 + 9: $t8 := 1 + # live vars: $t0, $t2, $t7, $t8 + # events: e:$t7, e:$t8, b:$t6 + 10: $t6 := +($t7, $t8) + # live vars: $t0, $t2, $t6 + # events: e:$t6 + 11: $t3 := move($t6) # live vars: $t0, $t2, $t3 - 10: goto 1 + 12: goto 1 # live vars: $t0, $t2, $t3 # events: e:$t0, e:$t2, e:$t3 - 11: label L3 + 13: label L3 # live vars: - 12: return () + 14: return () } @@ -144,35 +168,43 @@ public fun m::test2($t0: u64, $t1: u64) { var $t3: bool var $t4: u64 var $t5: u64 + var $t6: u64 + var $t7: u64 # live vars: $t0, $t1 # events: b:$t0, b:$t1, e:$t1, b:$t2 0: $t2 := 0 # live vars: $t0, $t2 1: label L0 # live vars: $t0, $t2 - # events: b:$t3 - 2: $t3 := <($t2, $t0) + # events: b:$t4 + 2: $t4 := copy($t2) + # live vars: $t0, $t2, $t4 + # events: e:$t4, b:$t3 + 3: $t3 := <($t4, $t0) # live vars: $t0, $t2, $t3 # events: e:$t3 - 3: if ($t3) goto 4 else goto 9 + 4: if ($t3) goto 5 else goto 11 # live vars: $t0, $t2 - 4: label L2 + 5: label L2 # live vars: $t0, $t2 - # events: b:$t5 - 5: $t5 := 1 - # live vars: $t0, $t2, $t5 - # events: e:$t5, b:$t4 - 6: $t4 := +($t2, $t5) - # live vars: $t0, $t4 - # events: e:$t4 - 7: $t2 := move($t4) + # events: b:$t6 + 6: $t6 := move($t2) + # live vars: $t0, $t6 + # events: b:$t7 + 7: $t7 := 1 + # live vars: $t0, $t6, $t7 + # events: e:$t6, e:$t7, b:$t5 + 8: $t5 := +($t6, $t7) + # live vars: $t0, $t5 + # events: e:$t5 + 9: $t2 := move($t5) # live vars: $t0, $t2 - 8: goto 1 + 10: goto 1 # live vars: $t0, $t2 # events: e:$t0, e:$t2 - 9: label L3 + 11: label L3 # live vars: - 10: return () + 12: return () } ============ after VariableCoalescingTransformer: ================ @@ -181,21 +213,25 @@ public fun m::test2($t0: u64, $t1: u64) { public fun m::test1($t0: u64, $t1: u64, $t2: u64) { var $t3: u64 var $t4: bool - var $t5: u64 [unused] + var $t5: u64 var $t6: u64 [unused] + var $t7: u64 [unused] + var $t8: u64 [unused] 0: $t3 := 0 1: label L0 - 2: $t4 := <($t3, $t0) - 3: if ($t4) goto 4 else goto 11 - 4: label L2 - 5: $t1 := move($t2) - 6: $t2 := move($t1) - 7: $t1 := 1 - 8: $t1 := +($t3, $t1) - 9: $t3 := move($t1) - 10: goto 1 - 11: label L3 - 12: return () + 2: $t5 := copy($t3) + 3: $t4 := <($t5, $t0) + 4: if ($t4) goto 5 else goto 13 + 5: label L2 + 6: $t1 := move($t2) + 7: $t2 := move($t1) + 8: $t1 := move($t3) + 9: $t5 := 1 + 10: $t1 := +($t1, $t5) + 11: $t3 := move($t1) + 12: goto 1 + 13: label L3 + 14: return () } @@ -203,19 +239,23 @@ public fun m::test1($t0: u64, $t1: u64, $t2: u64) { public fun m::test2($t0: u64, $t1: u64) { var $t2: u64 [unused] var $t3: bool - var $t4: u64 [unused] - var $t5: u64 + var $t4: u64 + var $t5: u64 [unused] + var $t6: u64 [unused] + var $t7: u64 0: $t1 := 0 1: label L0 - 2: $t3 := <($t1, $t0) - 3: if ($t3) goto 4 else goto 9 - 4: label L2 - 5: $t5 := 1 - 6: $t5 := +($t1, $t5) - 7: $t1 := move($t5) - 8: goto 1 - 9: label L3 - 10: return () + 2: $t4 := copy($t1) + 3: $t3 := <($t4, $t0) + 4: if ($t3) goto 5 else goto 11 + 5: label L2 + 6: $t4 := move($t1) + 7: $t7 := 1 + 8: $t4 := +($t4, $t7) + 9: $t1 := move($t4) + 10: goto 1 + 11: label L3 + 12: return () } ============ after DeadStoreElimination: ================ @@ -224,21 +264,25 @@ public fun m::test2($t0: u64, $t1: u64) { public fun m::test1($t0: u64, $t1: u64, $t2: u64) { var $t3: u64 var $t4: bool - var $t5: u64 [unused] + var $t5: u64 var $t6: u64 [unused] + var $t7: u64 [unused] + var $t8: u64 [unused] 0: $t3 := 0 1: label L0 - 2: $t4 := <($t3, $t0) - 3: if ($t4) goto 4 else goto 11 - 4: label L2 - 5: $t1 := move($t2) - 6: $t2 := move($t1) - 7: $t1 := 1 - 8: $t1 := +($t3, $t1) - 9: $t3 := move($t1) - 10: goto 1 - 11: label L3 - 12: return () + 2: $t5 := copy($t3) + 3: $t4 := <($t5, $t0) + 4: if ($t4) goto 5 else goto 13 + 5: label L2 + 6: $t1 := move($t2) + 7: $t2 := move($t1) + 8: $t1 := move($t3) + 9: $t5 := 1 + 10: $t1 := +($t1, $t5) + 11: $t3 := move($t1) + 12: goto 1 + 13: label L3 + 14: return () } @@ -246,19 +290,23 @@ public fun m::test1($t0: u64, $t1: u64, $t2: u64) { public fun m::test2($t0: u64, $t1: u64) { var $t2: u64 [unused] var $t3: bool - var $t4: u64 [unused] - var $t5: u64 + var $t4: u64 + var $t5: u64 [unused] + var $t6: u64 [unused] + var $t7: u64 0: $t1 := 0 1: label L0 - 2: $t3 := <($t1, $t0) - 3: if ($t3) goto 4 else goto 9 - 4: label L2 - 5: $t5 := 1 - 6: $t5 := +($t1, $t5) - 7: $t1 := move($t5) - 8: goto 1 - 9: label L3 - 10: return () + 2: $t4 := copy($t1) + 3: $t3 := <($t4, $t0) + 4: if ($t3) goto 5 else goto 11 + 5: label L2 + 6: $t4 := move($t1) + 7: $t7 := 1 + 8: $t4 := +($t4, $t7) + 9: $t1 := move($t4) + 10: goto 1 + 11: label L3 + 12: return () } @@ -276,20 +324,17 @@ B1: 2: CopyLoc[3](loc0: u64) 3: CopyLoc[0](Arg0: u64) 4: Lt - 5: BrFalse(13) + 5: BrFalse(11) B2: - 6: MoveLoc[2](Arg2: u64) - 7: MoveLoc[3](loc0: u64) - 8: LdU64(1) - 9: Add - 10: StLoc[3](loc0: u64) - 11: StLoc[2](Arg2: u64) - 12: Branch(2) + 6: MoveLoc[3](loc0: u64) + 7: LdU64(1) + 8: Add + 9: StLoc[3](loc0: u64) + 10: Branch(2) B3: - 13: Ret + 11: Ret } public test2(Arg0: u64, Arg1: u64) /* def_idx: 1 */ { -L2: loc0: u64 B0: 0: LdU64(0) 1: StLoc[1](Arg1: u64) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_dead_store.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_dead_store.opt.exp index 532b75388a4fb..eb2737329ba18 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_dead_store.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_dead_store.opt.exp @@ -6,23 +6,27 @@ public fun m::test1($t0: u64, $t1: u64, $t2: u64) { var $t4: bool var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 0: $t3 := 0 1: label L0 - 2: $t4 := <($t3, $t0) - 3: if ($t4) goto 4 else goto 11 - 4: label L2 - 5: $t1 := infer($t2) - 6: $t2 := infer($t1) - 7: $t6 := 1 - 8: $t5 := +($t3, $t6) - 9: $t3 := infer($t5) - 10: goto 13 - 11: label L3 + 2: $t5 := infer($t3) + 3: $t4 := <($t5, $t0) + 4: if ($t4) goto 5 else goto 13 + 5: label L2 + 6: $t1 := infer($t2) + 7: $t2 := infer($t1) + 8: $t7 := infer($t3) + 9: $t8 := 1 + 10: $t6 := +($t7, $t8) + 11: $t3 := infer($t6) 12: goto 15 - 13: label L4 - 14: goto 1 - 15: label L1 - 16: return () + 13: label L3 + 14: goto 17 + 15: label L4 + 16: goto 1 + 17: label L1 + 18: return () } @@ -32,22 +36,26 @@ public fun m::test2($t0: u64, $t1: u64) { var $t3: bool var $t4: u64 var $t5: u64 + var $t6: u64 + var $t7: u64 0: $t2 := 0 1: label L0 - 2: $t3 := <($t2, $t0) - 3: if ($t3) goto 4 else goto 10 - 4: label L2 - 5: $t1 := infer($t1) - 6: $t5 := 1 - 7: $t4 := +($t2, $t5) - 8: $t2 := infer($t4) - 9: goto 12 - 10: label L3 + 2: $t4 := infer($t2) + 3: $t3 := <($t4, $t0) + 4: if ($t3) goto 5 else goto 12 + 5: label L2 + 6: $t1 := infer($t1) + 7: $t6 := infer($t2) + 8: $t7 := 1 + 9: $t5 := +($t6, $t7) + 10: $t2 := infer($t5) 11: goto 14 - 12: label L4 - 13: goto 1 - 14: label L1 - 15: return () + 12: label L3 + 13: goto 16 + 14: label L4 + 15: goto 1 + 16: label L1 + 17: return () } ============ after DeadStoreElimination: ================ @@ -58,19 +66,23 @@ public fun m::test1($t0: u64, $t1: u64, $t2: u64) { var $t4: bool var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 0: $t3 := 0 1: label L0 - 2: $t4 := <($t3, $t0) - 3: if ($t4) goto 4 else goto 11 - 4: label L2 - 5: $t1 := move($t2) - 6: $t2 := move($t1) - 7: $t6 := 1 - 8: $t5 := +($t3, $t6) - 9: $t3 := move($t5) - 10: goto 1 - 11: label L3 - 12: return () + 2: $t5 := copy($t3) + 3: $t4 := <($t5, $t0) + 4: if ($t4) goto 5 else goto 13 + 5: label L2 + 6: $t1 := move($t2) + 7: $t2 := move($t1) + 8: $t7 := move($t3) + 9: $t8 := 1 + 10: $t6 := +($t7, $t8) + 11: $t3 := move($t6) + 12: goto 1 + 13: label L3 + 14: return () } @@ -80,17 +92,21 @@ public fun m::test2($t0: u64, $t1: u64) { var $t3: bool var $t4: u64 var $t5: u64 + var $t6: u64 + var $t7: u64 0: $t2 := 0 1: label L0 - 2: $t3 := <($t2, $t0) - 3: if ($t3) goto 4 else goto 9 - 4: label L2 - 5: $t5 := 1 - 6: $t4 := +($t2, $t5) - 7: $t2 := move($t4) - 8: goto 1 - 9: label L3 - 10: return () + 2: $t4 := copy($t2) + 3: $t3 := <($t4, $t0) + 4: if ($t3) goto 5 else goto 11 + 5: label L2 + 6: $t6 := move($t2) + 7: $t7 := 1 + 8: $t5 := +($t6, $t7) + 9: $t2 := move($t5) + 10: goto 1 + 11: label L3 + 12: return () } ============ after VariableCoalescingAnnotator: ================ @@ -101,40 +117,48 @@ public fun m::test1($t0: u64, $t1: u64, $t2: u64) { var $t4: bool var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 # live vars: $t0, $t1, $t2 # events: b:$t0, b:$t1, b:$t2, b:$t3 0: $t3 := 0 # live vars: $t0, $t2, $t3 1: label L0 # live vars: $t0, $t2, $t3 - # events: b:$t4 - 2: $t4 := <($t3, $t0) + # events: b:$t5 + 2: $t5 := copy($t3) + # live vars: $t0, $t2, $t3, $t5 + # events: e:$t5, b:$t4 + 3: $t4 := <($t5, $t0) # live vars: $t0, $t2, $t3, $t4 # events: e:$t4 - 3: if ($t4) goto 4 else goto 11 + 4: if ($t4) goto 5 else goto 13 # live vars: $t0, $t2, $t3 - 4: label L2 + 5: label L2 # live vars: $t0, $t2, $t3 - 5: $t1 := move($t2) + 6: $t1 := move($t2) # live vars: $t0, $t1, $t3 # events: e:$t1 - 6: $t2 := move($t1) + 7: $t2 := move($t1) # live vars: $t0, $t2, $t3 - # events: b:$t6 - 7: $t6 := 1 - # live vars: $t0, $t2, $t3, $t6 - # events: e:$t6, b:$t5 - 8: $t5 := +($t3, $t6) - # live vars: $t0, $t2, $t5 - # events: e:$t5 - 9: $t3 := move($t5) + # events: b:$t7 + 8: $t7 := move($t3) + # live vars: $t0, $t2, $t7 + # events: b:$t8 + 9: $t8 := 1 + # live vars: $t0, $t2, $t7, $t8 + # events: e:$t7, e:$t8, b:$t6 + 10: $t6 := +($t7, $t8) + # live vars: $t0, $t2, $t6 + # events: e:$t6 + 11: $t3 := move($t6) # live vars: $t0, $t2, $t3 - 10: goto 1 + 12: goto 1 # live vars: $t0, $t2, $t3 # events: e:$t0, e:$t2, e:$t3 - 11: label L3 + 13: label L3 # live vars: - 12: return () + 14: return () } @@ -144,35 +168,43 @@ public fun m::test2($t0: u64, $t1: u64) { var $t3: bool var $t4: u64 var $t5: u64 + var $t6: u64 + var $t7: u64 # live vars: $t0, $t1 # events: b:$t0, b:$t1, e:$t1, b:$t2 0: $t2 := 0 # live vars: $t0, $t2 1: label L0 # live vars: $t0, $t2 - # events: b:$t3 - 2: $t3 := <($t2, $t0) + # events: b:$t4 + 2: $t4 := copy($t2) + # live vars: $t0, $t2, $t4 + # events: e:$t4, b:$t3 + 3: $t3 := <($t4, $t0) # live vars: $t0, $t2, $t3 # events: e:$t3 - 3: if ($t3) goto 4 else goto 9 + 4: if ($t3) goto 5 else goto 11 # live vars: $t0, $t2 - 4: label L2 + 5: label L2 # live vars: $t0, $t2 - # events: b:$t5 - 5: $t5 := 1 - # live vars: $t0, $t2, $t5 - # events: e:$t5, b:$t4 - 6: $t4 := +($t2, $t5) - # live vars: $t0, $t4 - # events: e:$t4 - 7: $t2 := move($t4) + # events: b:$t6 + 6: $t6 := move($t2) + # live vars: $t0, $t6 + # events: b:$t7 + 7: $t7 := 1 + # live vars: $t0, $t6, $t7 + # events: e:$t6, e:$t7, b:$t5 + 8: $t5 := +($t6, $t7) + # live vars: $t0, $t5 + # events: e:$t5 + 9: $t2 := move($t5) # live vars: $t0, $t2 - 8: goto 1 + 10: goto 1 # live vars: $t0, $t2 # events: e:$t0, e:$t2 - 9: label L3 + 11: label L3 # live vars: - 10: return () + 12: return () } ============ after VariableCoalescingTransformer: ================ @@ -181,21 +213,25 @@ public fun m::test2($t0: u64, $t1: u64) { public fun m::test1($t0: u64, $t1: u64, $t2: u64) { var $t3: u64 var $t4: bool - var $t5: u64 [unused] + var $t5: u64 var $t6: u64 [unused] + var $t7: u64 [unused] + var $t8: u64 [unused] 0: $t3 := 0 1: label L0 - 2: $t4 := <($t3, $t0) - 3: if ($t4) goto 4 else goto 11 - 4: label L2 - 5: $t1 := move($t2) - 6: $t2 := move($t1) - 7: $t1 := 1 - 8: $t1 := +($t3, $t1) - 9: $t3 := move($t1) - 10: goto 1 - 11: label L3 - 12: return () + 2: $t5 := copy($t3) + 3: $t4 := <($t5, $t0) + 4: if ($t4) goto 5 else goto 13 + 5: label L2 + 6: $t1 := move($t2) + 7: $t2 := move($t1) + 8: $t1 := move($t3) + 9: $t5 := 1 + 10: $t1 := +($t1, $t5) + 11: $t3 := move($t1) + 12: goto 1 + 13: label L3 + 14: return () } @@ -203,19 +239,23 @@ public fun m::test1($t0: u64, $t1: u64, $t2: u64) { public fun m::test2($t0: u64, $t1: u64) { var $t2: u64 [unused] var $t3: bool - var $t4: u64 [unused] - var $t5: u64 + var $t4: u64 + var $t5: u64 [unused] + var $t6: u64 [unused] + var $t7: u64 0: $t1 := 0 1: label L0 - 2: $t3 := <($t1, $t0) - 3: if ($t3) goto 4 else goto 9 - 4: label L2 - 5: $t5 := 1 - 6: $t5 := +($t1, $t5) - 7: $t1 := move($t5) - 8: goto 1 - 9: label L3 - 10: return () + 2: $t4 := copy($t1) + 3: $t3 := <($t4, $t0) + 4: if ($t3) goto 5 else goto 11 + 5: label L2 + 6: $t4 := move($t1) + 7: $t7 := 1 + 8: $t4 := +($t4, $t7) + 9: $t1 := move($t4) + 10: goto 1 + 11: label L3 + 12: return () } ============ after DeadStoreElimination: ================ @@ -224,21 +264,25 @@ public fun m::test2($t0: u64, $t1: u64) { public fun m::test1($t0: u64, $t1: u64, $t2: u64) { var $t3: u64 var $t4: bool - var $t5: u64 [unused] + var $t5: u64 var $t6: u64 [unused] + var $t7: u64 [unused] + var $t8: u64 [unused] 0: $t3 := 0 1: label L0 - 2: $t4 := <($t3, $t0) - 3: if ($t4) goto 4 else goto 11 - 4: label L2 - 5: $t1 := move($t2) - 6: $t2 := move($t1) - 7: $t1 := 1 - 8: $t1 := +($t3, $t1) - 9: $t3 := move($t1) - 10: goto 1 - 11: label L3 - 12: return () + 2: $t5 := copy($t3) + 3: $t4 := <($t5, $t0) + 4: if ($t4) goto 5 else goto 13 + 5: label L2 + 6: $t1 := move($t2) + 7: $t2 := move($t1) + 8: $t1 := move($t3) + 9: $t5 := 1 + 10: $t1 := +($t1, $t5) + 11: $t3 := move($t1) + 12: goto 1 + 13: label L3 + 14: return () } @@ -246,19 +290,23 @@ public fun m::test1($t0: u64, $t1: u64, $t2: u64) { public fun m::test2($t0: u64, $t1: u64) { var $t2: u64 [unused] var $t3: bool - var $t4: u64 [unused] - var $t5: u64 + var $t4: u64 + var $t5: u64 [unused] + var $t6: u64 [unused] + var $t7: u64 0: $t1 := 0 1: label L0 - 2: $t3 := <($t1, $t0) - 3: if ($t3) goto 4 else goto 9 - 4: label L2 - 5: $t5 := 1 - 6: $t5 := +($t1, $t5) - 7: $t1 := move($t5) - 8: goto 1 - 9: label L3 - 10: return () + 2: $t4 := copy($t1) + 3: $t3 := <($t4, $t0) + 4: if ($t3) goto 5 else goto 11 + 5: label L2 + 6: $t4 := move($t1) + 7: $t7 := 1 + 8: $t4 := +($t4, $t7) + 9: $t1 := move($t4) + 10: goto 1 + 11: label L3 + 12: return () } @@ -276,20 +324,17 @@ B1: 2: CopyLoc[3](loc0: u64) 3: CopyLoc[0](Arg0: u64) 4: Lt - 5: BrFalse(13) + 5: BrFalse(11) B2: - 6: MoveLoc[2](Arg2: u64) - 7: MoveLoc[3](loc0: u64) - 8: LdU64(1) - 9: Add - 10: StLoc[3](loc0: u64) - 11: StLoc[2](Arg2: u64) - 12: Branch(2) + 6: MoveLoc[3](loc0: u64) + 7: LdU64(1) + 8: Add + 9: StLoc[3](loc0: u64) + 10: Branch(2) B3: - 13: Ret + 11: Ret } public test2(Arg0: u64, Arg1: u64) /* def_idx: 1 */ { -L2: loc0: u64 B0: 0: LdU64(0) 1: StLoc[1](Arg1: u64) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_1.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_1.exp index 2cc99f49b4eab..7dd05bb58a5b3 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_1.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_1.exp @@ -65,7 +65,8 @@ fun m::dead($t0: u64): u64 { var $t1: u64 [unused] var $t2: u64 [unused] var $t3: u64 [unused] - 0: return $t0 + 0: $t0 := move($t0) + 1: return $t0 } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_1.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_1.opt.exp index 2cc99f49b4eab..7dd05bb58a5b3 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_1.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_1.opt.exp @@ -65,7 +65,8 @@ fun m::dead($t0: u64): u64 { var $t1: u64 [unused] var $t2: u64 [unused] var $t3: u64 [unused] - 0: return $t0 + 0: $t0 := move($t0) + 1: return $t0 } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_2.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_2.exp index ff4216c1abb91..351ca18eaaa97 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_2.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_2.exp @@ -44,7 +44,8 @@ fun m::dead($t0: u64): u64 { [variant baseline] fun m::dead($t0: u64): u64 { var $t1: u64 [unused] - 0: return $t0 + 0: $t0 := move($t0) + 1: return $t0 } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_2.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_2.opt.exp index ff4216c1abb91..351ca18eaaa97 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_2.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_2.opt.exp @@ -44,7 +44,8 @@ fun m::dead($t0: u64): u64 { [variant baseline] fun m::dead($t0: u64): u64 { var $t1: u64 [unused] - 0: return $t0 + 0: $t0 := move($t0) + 1: return $t0 } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_4.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_4.exp index 970a6b84ab094..e5d53fcb4a3b2 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_4.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_4.exp @@ -243,7 +243,8 @@ public fun m::test1(): u64 { public fun m::test2($t0: u64): u64 { var $t1: u64 [unused] var $t2: u64 [unused] - 0: return $t0 + 0: $t0 := move($t0) + 1: return $t0 } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_4.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_4.opt.exp index c4b4326890f8a..28520f67195bc 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_4.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_4.opt.exp @@ -210,7 +210,8 @@ public fun m::test1(): u64 { public fun m::test2($t0: u64): u64 { var $t1: u64 [unused] var $t2: u64 [unused] - 0: return $t0 + 0: $t0 := move($t0) + 1: return $t0 } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_1.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_1.exp index 6d8197b4a1bcd..ab6be61985f7f 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_1.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_1.exp @@ -7,13 +7,17 @@ fun m::test(): u64 { var $t2: u64 var $t3: u64 var $t4: u64 + var $t5: u64 + var $t6: u64 0: $t1 := 1 1: $t2 := 2 - 2: $t3 := +($t1, $t2) - 3: $t1 := infer($t3) - 4: $t4 := infer($t2) - 5: $t0 := +($t4, $t2) - 6: return $t0 + 2: $t4 := infer($t1) + 3: $t3 := +($t4, $t2) + 4: $t1 := infer($t3) + 5: $t5 := infer($t2) + 6: $t6 := infer($t5) + 7: $t0 := +($t6, $t2) + 8: return $t0 } @@ -33,12 +37,16 @@ fun m::test(): u64 { var $t2: u64 var $t3: u64 var $t4: u64 + var $t5: u64 + var $t6: u64 0: $t1 := 1 1: $t2 := 2 - 2: $t3 := +($t1, $t2) - 3: $t4 := copy($t2) - 4: $t0 := +($t4, $t2) - 5: return $t0 + 2: $t4 := move($t1) + 3: $t3 := +($t4, $t2) + 4: $t5 := copy($t2) + 5: $t6 := move($t5) + 6: $t0 := +($t6, $t2) + 7: return $t0 } ============ after VariableCoalescingAnnotator: ================ @@ -50,6 +58,8 @@ fun m::test(): u64 { var $t2: u64 var $t3: u64 var $t4: u64 + var $t5: u64 + var $t6: u64 # live vars: # events: b:$t1 0: $t1 := 1 @@ -57,17 +67,23 @@ fun m::test(): u64 { # events: b:$t2 1: $t2 := 2 # live vars: $t1, $t2 - # events: e:$t1, e:$t3, b:$t3 - 2: $t3 := +($t1, $t2) - # live vars: $t2 - # events: b:$t4 - 3: $t4 := copy($t2) + # events: e:$t1, b:$t4 + 2: $t4 := move($t1) # live vars: $t2, $t4 - # events: e:$t2, e:$t4, b:$t0 - 4: $t0 := +($t4, $t2) + # events: e:$t3, e:$t4, b:$t3 + 3: $t3 := +($t4, $t2) + # live vars: $t2 + # events: b:$t5 + 4: $t5 := copy($t2) + # live vars: $t2, $t5 + # events: e:$t5, b:$t6 + 5: $t6 := move($t5) + # live vars: $t2, $t6 + # events: e:$t2, e:$t6, b:$t0 + 6: $t0 := +($t6, $t2) # live vars: $t0 # events: e:$t0 - 5: return $t0 + 7: return $t0 } ============ after VariableCoalescingTransformer: ================ @@ -79,12 +95,16 @@ fun m::test(): u64 { var $t2: u64 var $t3: u64 var $t4: u64 [unused] + var $t5: u64 [unused] + var $t6: u64 [unused] 0: $t1 := 1 1: $t2 := 2 - 2: $t1 := +($t1, $t2) - 3: $t3 := copy($t2) - 4: $t2 := +($t3, $t2) - 5: return $t2 + 2: $t1 := move($t1) + 3: $t1 := +($t1, $t2) + 4: $t3 := copy($t2) + 5: $t3 := move($t3) + 6: $t2 := +($t3, $t2) + 7: return $t2 } ============ after DeadStoreElimination: ================ @@ -96,6 +116,8 @@ fun m::test(): u64 { var $t2: u64 var $t3: u64 var $t4: u64 [unused] + var $t5: u64 [unused] + var $t6: u64 [unused] 0: $t1 := 1 1: $t2 := 2 2: $t1 := +($t1, $t2) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_1.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_1.opt.exp index 1dc1eb6f44cd7..c510bcdf05fe1 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_1.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_1.opt.exp @@ -6,12 +6,14 @@ fun m::test(): u64 { var $t1: u64 var $t2: u64 var $t3: u64 + var $t4: u64 0: $t1 := 1 - 1: $t3 := 2 - 2: $t2 := +($t1, $t3) - 3: $t1 := infer($t2) - 4: $t0 := 4 - 5: return $t0 + 1: $t3 := infer($t1) + 2: $t4 := 2 + 3: $t2 := +($t3, $t4) + 4: $t1 := infer($t2) + 5: $t0 := 4 + 6: return $t0 } @@ -30,11 +32,13 @@ fun m::test(): u64 { var $t1: u64 var $t2: u64 var $t3: u64 + var $t4: u64 0: $t1 := 1 - 1: $t3 := 2 - 2: $t2 := +($t1, $t3) - 3: $t0 := 4 - 4: return $t0 + 1: $t3 := move($t1) + 2: $t4 := 2 + 3: $t2 := +($t3, $t4) + 4: $t0 := 4 + 5: return $t0 } ============ after VariableCoalescingAnnotator: ================ @@ -45,21 +49,25 @@ fun m::test(): u64 { var $t1: u64 var $t2: u64 var $t3: u64 + var $t4: u64 # live vars: # events: b:$t1 0: $t1 := 1 # live vars: $t1 - # events: b:$t3 - 1: $t3 := 2 - # live vars: $t1, $t3 - # events: e:$t1, e:$t2, e:$t3, b:$t2 - 2: $t2 := +($t1, $t3) + # events: e:$t1, b:$t3 + 1: $t3 := move($t1) + # live vars: $t3 + # events: b:$t4 + 2: $t4 := 2 + # live vars: $t3, $t4 + # events: e:$t2, e:$t3, e:$t4, b:$t2 + 3: $t2 := +($t3, $t4) # live vars: # events: b:$t0 - 3: $t0 := 4 + 4: $t0 := 4 # live vars: $t0 # events: e:$t0 - 4: return $t0 + 5: return $t0 } ============ after VariableCoalescingTransformer: ================ @@ -69,12 +77,14 @@ fun m::test(): u64 { var $t0: u64 [unused] var $t1: u64 var $t2: u64 - var $t3: u64 + var $t3: u64 [unused] + var $t4: u64 0: $t1 := 1 - 1: $t3 := 2 - 2: $t1 := +($t1, $t3) - 3: $t2 := 4 - 4: return $t2 + 1: $t1 := move($t1) + 2: $t4 := 2 + 3: $t1 := +($t1, $t4) + 4: $t2 := 4 + 5: return $t2 } ============ after DeadStoreElimination: ================ @@ -84,10 +94,11 @@ fun m::test(): u64 { var $t0: u64 [unused] var $t1: u64 var $t2: u64 - var $t3: u64 + var $t3: u64 [unused] + var $t4: u64 0: $t1 := 1 - 1: $t3 := 2 - 2: $t1 := +($t1, $t3) + 1: $t4 := 2 + 2: $t1 := +($t1, $t4) 3: $t2 := 4 4: return $t2 } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_2.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_2.exp index c1d0ebf04aff7..f64720867bb98 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_2.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_2.exp @@ -8,14 +8,18 @@ fun m::test(): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 + var $t7: u64 0: $t1 := 1 1: $t2 := 2 - 2: $t4 := 1 - 3: $t3 := +($t1, $t4) - 4: $t1 := infer($t3) - 5: $t5 := infer($t2) - 6: $t0 := +($t5, $t1) - 7: return $t0 + 2: $t4 := infer($t1) + 3: $t5 := 1 + 4: $t3 := +($t4, $t5) + 5: $t1 := infer($t3) + 6: $t6 := infer($t2) + 7: $t7 := infer($t6) + 8: $t0 := +($t7, $t1) + 9: return $t0 } ============ after DeadStoreElimination: ================ @@ -28,14 +32,18 @@ fun m::test(): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 + var $t7: u64 0: $t1 := 1 1: $t2 := 2 - 2: $t4 := 1 - 3: $t3 := +($t1, $t4) - 4: $t1 := move($t3) - 5: $t5 := move($t2) - 6: $t0 := +($t5, $t1) - 7: return $t0 + 2: $t4 := move($t1) + 3: $t5 := 1 + 4: $t3 := +($t4, $t5) + 5: $t1 := move($t3) + 6: $t6 := move($t2) + 7: $t7 := move($t6) + 8: $t0 := +($t7, $t1) + 9: return $t0 } ============ after VariableCoalescingAnnotator: ================ @@ -48,6 +56,8 @@ fun m::test(): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 + var $t7: u64 # live vars: # events: b:$t1 0: $t1 := 1 @@ -56,22 +66,28 @@ fun m::test(): u64 { 1: $t2 := 2 # live vars: $t1, $t2 # events: b:$t4 - 2: $t4 := 1 - # live vars: $t1, $t2, $t4 - # events: e:$t4, b:$t3 - 3: $t3 := +($t1, $t4) + 2: $t4 := move($t1) + # live vars: $t2, $t4 + # events: b:$t5 + 3: $t5 := 1 + # live vars: $t2, $t4, $t5 + # events: e:$t4, e:$t5, b:$t3 + 4: $t3 := +($t4, $t5) # live vars: $t2, $t3 # events: e:$t3 - 4: $t1 := move($t3) + 5: $t1 := move($t3) # live vars: $t1, $t2 - # events: e:$t2, b:$t5 - 5: $t5 := move($t2) - # live vars: $t1, $t5 - # events: e:$t1, e:$t5, b:$t0 - 6: $t0 := +($t5, $t1) + # events: e:$t2, b:$t6 + 6: $t6 := move($t2) + # live vars: $t1, $t6 + # events: e:$t6, b:$t7 + 7: $t7 := move($t6) + # live vars: $t1, $t7 + # events: e:$t1, e:$t7, b:$t0 + 8: $t0 := +($t7, $t1) # live vars: $t0 # events: e:$t0 - 7: return $t0 + 9: return $t0 } ============ after VariableCoalescingTransformer: ================ @@ -83,15 +99,19 @@ fun m::test(): u64 { var $t2: u64 var $t3: u64 [unused] var $t4: u64 - var $t5: u64 [unused] + var $t5: u64 + var $t6: u64 [unused] + var $t7: u64 [unused] 0: $t1 := 1 1: $t2 := 2 - 2: $t4 := 1 - 3: $t4 := +($t1, $t4) - 4: $t1 := move($t4) - 5: $t2 := move($t2) - 6: $t1 := +($t2, $t1) - 7: return $t1 + 2: $t4 := move($t1) + 3: $t5 := 1 + 4: $t4 := +($t4, $t5) + 5: $t1 := move($t4) + 6: $t2 := move($t2) + 7: $t2 := move($t2) + 8: $t1 := +($t2, $t1) + 9: return $t1 } ============ after DeadStoreElimination: ================ @@ -103,14 +123,17 @@ fun m::test(): u64 { var $t2: u64 var $t3: u64 [unused] var $t4: u64 - var $t5: u64 [unused] + var $t5: u64 + var $t6: u64 [unused] + var $t7: u64 [unused] 0: $t1 := 1 1: $t2 := 2 - 2: $t4 := 1 - 3: $t4 := +($t1, $t4) - 4: $t1 := move($t4) - 5: $t1 := +($t2, $t1) - 6: return $t1 + 2: $t4 := move($t1) + 3: $t5 := 1 + 4: $t4 := +($t4, $t5) + 5: $t1 := move($t4) + 6: $t1 := +($t2, $t1) + 7: return $t1 } @@ -121,17 +144,13 @@ module c0ffee.m { test(): u64 /* def_idx: 0 */ { L0: loc0: u64 -L1: loc1: u64 -L2: loc2: u64 B0: - 0: LdU64(1) + 0: LdU64(2) 1: LdU64(1) - 2: Add - 3: StLoc[2](loc2: u64) - 4: LdU64(2) - 5: MoveLoc[2](loc2: u64) - 6: Add - 7: Ret + 2: LdU64(1) + 3: Add + 4: Add + 5: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_2.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_2.opt.exp index 6eb72ab89b2c0..bc0c54da967d8 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_2.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_2.opt.exp @@ -7,13 +7,15 @@ fun m::test(): u64 { var $t2: u64 var $t3: u64 var $t4: u64 + var $t5: u64 0: $t1 := 1 - 1: $t3 := 1 - 2: $t2 := +($t1, $t3) - 3: $t1 := infer($t2) - 4: $t4 := 2 - 5: $t0 := +($t4, $t1) - 6: return $t0 + 1: $t3 := infer($t1) + 2: $t4 := 1 + 3: $t2 := +($t3, $t4) + 4: $t1 := infer($t2) + 5: $t5 := 2 + 6: $t0 := +($t5, $t1) + 7: return $t0 } ============ after DeadStoreElimination: ================ @@ -25,13 +27,15 @@ fun m::test(): u64 { var $t2: u64 var $t3: u64 var $t4: u64 + var $t5: u64 0: $t1 := 1 - 1: $t3 := 1 - 2: $t2 := +($t1, $t3) - 3: $t1 := move($t2) - 4: $t4 := 2 - 5: $t0 := +($t4, $t1) - 6: return $t0 + 1: $t3 := move($t1) + 2: $t4 := 1 + 3: $t2 := +($t3, $t4) + 4: $t1 := move($t2) + 5: $t5 := 2 + 6: $t0 := +($t5, $t1) + 7: return $t0 } ============ after VariableCoalescingAnnotator: ================ @@ -43,27 +47,31 @@ fun m::test(): u64 { var $t2: u64 var $t3: u64 var $t4: u64 + var $t5: u64 # live vars: # events: b:$t1 0: $t1 := 1 # live vars: $t1 # events: b:$t3 - 1: $t3 := 1 - # live vars: $t1, $t3 - # events: e:$t3, b:$t2 - 2: $t2 := +($t1, $t3) + 1: $t3 := move($t1) + # live vars: $t3 + # events: b:$t4 + 2: $t4 := 1 + # live vars: $t3, $t4 + # events: e:$t3, e:$t4, b:$t2 + 3: $t2 := +($t3, $t4) # live vars: $t2 # events: e:$t2 - 3: $t1 := move($t2) + 4: $t1 := move($t2) # live vars: $t1 - # events: b:$t4 - 4: $t4 := 2 - # live vars: $t1, $t4 - # events: e:$t1, e:$t4, b:$t0 - 5: $t0 := +($t4, $t1) + # events: b:$t5 + 5: $t5 := 2 + # live vars: $t1, $t5 + # events: e:$t1, e:$t5, b:$t0 + 6: $t0 := +($t5, $t1) # live vars: $t0 # events: e:$t0 - 6: return $t0 + 7: return $t0 } ============ after VariableCoalescingTransformer: ================ @@ -74,14 +82,16 @@ fun m::test(): u64 { var $t1: u64 var $t2: u64 [unused] var $t3: u64 - var $t4: u64 [unused] + var $t4: u64 + var $t5: u64 [unused] 0: $t1 := 1 - 1: $t3 := 1 - 2: $t3 := +($t1, $t3) - 3: $t1 := move($t3) - 4: $t3 := 2 - 5: $t1 := +($t3, $t1) - 6: return $t1 + 1: $t3 := move($t1) + 2: $t4 := 1 + 3: $t3 := +($t3, $t4) + 4: $t1 := move($t3) + 5: $t3 := 2 + 6: $t1 := +($t3, $t1) + 7: return $t1 } ============ after DeadStoreElimination: ================ @@ -92,14 +102,16 @@ fun m::test(): u64 { var $t1: u64 var $t2: u64 [unused] var $t3: u64 - var $t4: u64 [unused] + var $t4: u64 + var $t5: u64 [unused] 0: $t1 := 1 - 1: $t3 := 1 - 2: $t3 := +($t1, $t3) - 3: $t1 := move($t3) - 4: $t3 := 2 - 5: $t1 := +($t3, $t1) - 6: return $t1 + 1: $t3 := move($t1) + 2: $t4 := 1 + 3: $t3 := +($t3, $t4) + 4: $t1 := move($t3) + 5: $t3 := 2 + 6: $t1 := +($t3, $t1) + 7: return $t1 } @@ -110,14 +122,13 @@ module c0ffee.m { test(): u64 /* def_idx: 0 */ { L0: loc0: u64 -L1: loc1: u64 B0: 0: LdU64(1) 1: LdU64(1) 2: Add - 3: StLoc[1](loc1: u64) + 3: StLoc[0](loc0: u64) 4: LdU64(2) - 5: MoveLoc[1](loc1: u64) + 5: MoveLoc[0](loc0: u64) 6: Add 7: Ret } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_3.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_3.exp index bdbed18eca8eb..50896e93a95a3 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_3.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_3.exp @@ -8,14 +8,16 @@ fun m::test(): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 0: $t1 := 1 1: $t2 := 2 - 2: $t4 := 1 - 3: $t3 := +($t1, $t4) - 4: $t1 := infer($t3) - 5: $t5 := infer($t2) - 6: $t0 := infer($t5) - 7: return $t0 + 2: $t4 := infer($t1) + 3: $t5 := 1 + 4: $t3 := +($t4, $t5) + 5: $t1 := infer($t3) + 6: $t6 := infer($t2) + 7: $t0 := infer($t6) + 8: return $t0 } @@ -36,13 +38,15 @@ fun m::test(): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 0: $t1 := 1 1: $t2 := 2 - 2: $t4 := 1 - 3: $t3 := +($t1, $t4) - 4: $t5 := move($t2) - 5: $t0 := move($t5) - 6: return $t0 + 2: $t4 := move($t1) + 3: $t5 := 1 + 4: $t3 := +($t4, $t5) + 5: $t6 := move($t2) + 6: $t0 := move($t6) + 7: return $t0 } ============ after VariableCoalescingAnnotator: ================ @@ -55,6 +59,7 @@ fun m::test(): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 # live vars: # events: b:$t1 0: $t1 := 1 @@ -62,20 +67,23 @@ fun m::test(): u64 { # events: b:$t2 1: $t2 := 2 # live vars: $t1, $t2 - # events: b:$t4 - 2: $t4 := 1 - # live vars: $t1, $t2, $t4 - # events: e:$t1, e:$t3, e:$t4, b:$t3 - 3: $t3 := +($t1, $t4) + # events: e:$t1, b:$t4 + 2: $t4 := move($t1) + # live vars: $t2, $t4 + # events: b:$t5 + 3: $t5 := 1 + # live vars: $t2, $t4, $t5 + # events: e:$t3, e:$t4, e:$t5, b:$t3 + 4: $t3 := +($t4, $t5) # live vars: $t2 - # events: e:$t2, b:$t5 - 4: $t5 := move($t2) - # live vars: $t5 - # events: e:$t5, b:$t0 - 5: $t0 := move($t5) + # events: e:$t2, b:$t6 + 5: $t6 := move($t2) + # live vars: $t6 + # events: e:$t6, b:$t0 + 6: $t0 := move($t6) # live vars: $t0 # events: e:$t0 - 6: return $t0 + 7: return $t0 } ============ after VariableCoalescingTransformer: ================ @@ -86,15 +94,17 @@ fun m::test(): u64 { var $t1: u64 var $t2: u64 var $t3: u64 [unused] - var $t4: u64 - var $t5: u64 [unused] + var $t4: u64 [unused] + var $t5: u64 + var $t6: u64 [unused] 0: $t1 := 1 1: $t2 := 2 - 2: $t4 := 1 - 3: $t1 := +($t1, $t4) - 4: $t2 := move($t2) + 2: $t1 := move($t1) + 3: $t5 := 1 + 4: $t1 := +($t1, $t5) 5: $t2 := move($t2) - 6: return $t2 + 6: $t2 := move($t2) + 7: return $t2 } ============ after DeadStoreElimination: ================ @@ -105,12 +115,13 @@ fun m::test(): u64 { var $t1: u64 var $t2: u64 var $t3: u64 [unused] - var $t4: u64 - var $t5: u64 [unused] + var $t4: u64 [unused] + var $t5: u64 + var $t6: u64 [unused] 0: $t1 := 1 1: $t2 := 2 - 2: $t4 := 1 - 3: $t1 := +($t1, $t4) + 2: $t5 := 1 + 3: $t1 := +($t1, $t5) 4: return $t2 } @@ -123,13 +134,12 @@ module c0ffee.m { test(): u64 /* def_idx: 0 */ { L0: loc0: u64 L1: loc1: u64 -L2: loc2: u64 B0: - 0: LdU64(1) + 0: LdU64(2) 1: LdU64(1) - 2: Add - 3: Pop - 4: LdU64(2) + 2: LdU64(1) + 3: Add + 4: Pop 5: Ret } } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_3.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_3.opt.exp index 5bdf9150dff2d..18270e0d1f323 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_3.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_3.opt.exp @@ -6,12 +6,14 @@ fun m::test(): u64 { var $t1: u64 var $t2: u64 var $t3: u64 + var $t4: u64 0: $t1 := 1 - 1: $t3 := 1 - 2: $t2 := +($t1, $t3) - 3: $t1 := infer($t2) - 4: $t0 := 2 - 5: return $t0 + 1: $t3 := infer($t1) + 2: $t4 := 1 + 3: $t2 := +($t3, $t4) + 4: $t1 := infer($t2) + 5: $t0 := 2 + 6: return $t0 } @@ -30,11 +32,13 @@ fun m::test(): u64 { var $t1: u64 var $t2: u64 var $t3: u64 + var $t4: u64 0: $t1 := 1 - 1: $t3 := 1 - 2: $t2 := +($t1, $t3) - 3: $t0 := 2 - 4: return $t0 + 1: $t3 := move($t1) + 2: $t4 := 1 + 3: $t2 := +($t3, $t4) + 4: $t0 := 2 + 5: return $t0 } ============ after VariableCoalescingAnnotator: ================ @@ -45,21 +49,25 @@ fun m::test(): u64 { var $t1: u64 var $t2: u64 var $t3: u64 + var $t4: u64 # live vars: # events: b:$t1 0: $t1 := 1 # live vars: $t1 - # events: b:$t3 - 1: $t3 := 1 - # live vars: $t1, $t3 - # events: e:$t1, e:$t2, e:$t3, b:$t2 - 2: $t2 := +($t1, $t3) + # events: e:$t1, b:$t3 + 1: $t3 := move($t1) + # live vars: $t3 + # events: b:$t4 + 2: $t4 := 1 + # live vars: $t3, $t4 + # events: e:$t2, e:$t3, e:$t4, b:$t2 + 3: $t2 := +($t3, $t4) # live vars: # events: b:$t0 - 3: $t0 := 2 + 4: $t0 := 2 # live vars: $t0 # events: e:$t0 - 4: return $t0 + 5: return $t0 } ============ after VariableCoalescingTransformer: ================ @@ -69,12 +77,14 @@ fun m::test(): u64 { var $t0: u64 [unused] var $t1: u64 var $t2: u64 - var $t3: u64 + var $t3: u64 [unused] + var $t4: u64 0: $t1 := 1 - 1: $t3 := 1 - 2: $t1 := +($t1, $t3) - 3: $t2 := 2 - 4: return $t2 + 1: $t1 := move($t1) + 2: $t4 := 1 + 3: $t1 := +($t1, $t4) + 4: $t2 := 2 + 5: return $t2 } ============ after DeadStoreElimination: ================ @@ -84,10 +94,11 @@ fun m::test(): u64 { var $t0: u64 [unused] var $t1: u64 var $t2: u64 - var $t3: u64 + var $t3: u64 [unused] + var $t4: u64 0: $t1 := 1 - 1: $t3 := 1 - 2: $t1 := +($t1, $t3) + 1: $t4 := 1 + 2: $t1 := +($t1, $t4) 3: $t2 := 2 4: return $t2 } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_1.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_1.exp index b8c4d57d833a0..41fb4d41dddfe 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_1.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_1.exp @@ -9,25 +9,29 @@ fun m::test($t0: u64): u64 { var $t5: u64 var $t6: u64 var $t7: u64 + var $t8: u64 + var $t9: u64 0: $t2 := 0 1: $t3 := 0 2: label L0 - 3: $t5 := 10 - 4: $t4 := <($t3, $t5) - 5: if ($t4) goto 6 else goto 12 - 6: label L2 - 7: $t2 := infer($t0) - 8: $t7 := 1 - 9: $t6 := +($t3, $t7) - 10: $t3 := infer($t6) - 11: goto 14 - 12: label L3 + 3: $t5 := infer($t3) + 4: $t6 := 10 + 5: $t4 := <($t5, $t6) + 6: if ($t4) goto 7 else goto 14 + 7: label L2 + 8: $t2 := infer($t0) + 9: $t8 := infer($t3) + 10: $t9 := 1 + 11: $t7 := +($t8, $t9) + 12: $t3 := infer($t7) 13: goto 16 - 14: label L4 - 15: goto 2 - 16: label L1 - 17: $t1 := infer($t2) - 18: return $t1 + 14: label L3 + 15: goto 18 + 16: label L4 + 17: goto 2 + 18: label L1 + 19: $t1 := infer($t2) + 20: return $t1 } ============ after DeadStoreElimination: ================ @@ -41,21 +45,25 @@ fun m::test($t0: u64): u64 { var $t5: u64 var $t6: u64 var $t7: u64 + var $t8: u64 + var $t9: u64 0: $t2 := 0 1: $t3 := 0 2: label L0 - 3: $t5 := 10 - 4: $t4 := <($t3, $t5) - 5: if ($t4) goto 6 else goto 12 - 6: label L2 - 7: $t2 := copy($t0) - 8: $t7 := 1 - 9: $t6 := +($t3, $t7) - 10: $t3 := move($t6) - 11: goto 2 - 12: label L3 - 13: $t1 := move($t2) - 14: return $t1 + 3: $t5 := copy($t3) + 4: $t6 := 10 + 5: $t4 := <($t5, $t6) + 6: if ($t4) goto 7 else goto 14 + 7: label L2 + 8: $t2 := copy($t0) + 9: $t8 := move($t3) + 10: $t9 := 1 + 11: $t7 := +($t8, $t9) + 12: $t3 := move($t7) + 13: goto 2 + 14: label L3 + 15: $t1 := move($t2) + 16: return $t1 } ============ after VariableCoalescingAnnotator: ================ @@ -69,6 +77,8 @@ fun m::test($t0: u64): u64 { var $t5: u64 var $t6: u64 var $t7: u64 + var $t8: u64 + var $t9: u64 # live vars: $t0 # events: b:$t0, b:$t2 0: $t2 := 0 @@ -79,37 +89,43 @@ fun m::test($t0: u64): u64 { 2: label L0 # live vars: $t0, $t2, $t3 # events: b:$t5 - 3: $t5 := 10 + 3: $t5 := copy($t3) # live vars: $t0, $t2, $t3, $t5 - # events: e:$t5, b:$t4 - 4: $t4 := <($t3, $t5) + # events: b:$t6 + 4: $t6 := 10 + # live vars: $t0, $t2, $t3, $t5, $t6 + # events: e:$t5, e:$t6, b:$t4 + 5: $t4 := <($t5, $t6) # live vars: $t0, $t2, $t3, $t4 # events: e:$t4 - 5: if ($t4) goto 6 else goto 12 + 6: if ($t4) goto 7 else goto 14 # live vars: $t0, $t2, $t3 - 6: label L2 + 7: label L2 # live vars: $t0, $t3 - 7: $t2 := copy($t0) + 8: $t2 := copy($t0) # live vars: $t0, $t2, $t3 - # events: b:$t7 - 8: $t7 := 1 - # live vars: $t0, $t2, $t3, $t7 - # events: e:$t7, b:$t6 - 9: $t6 := +($t3, $t7) - # live vars: $t0, $t2, $t6 - # events: e:$t6 - 10: $t3 := move($t6) + # events: b:$t8 + 9: $t8 := move($t3) + # live vars: $t0, $t2, $t8 + # events: b:$t9 + 10: $t9 := 1 + # live vars: $t0, $t2, $t8, $t9 + # events: e:$t8, e:$t9, b:$t7 + 11: $t7 := +($t8, $t9) + # live vars: $t0, $t2, $t7 + # events: e:$t7 + 12: $t3 := move($t7) # live vars: $t0, $t2, $t3 - 11: goto 2 + 13: goto 2 # live vars: $t0, $t2, $t3 # events: e:$t0, e:$t3 - 12: label L3 + 14: label L3 # live vars: $t2 # events: e:$t2, b:$t1 - 13: $t1 := move($t2) + 15: $t1 := move($t2) # live vars: $t1 # events: e:$t1 - 14: return $t1 + 16: return $t1 } ============ after VariableCoalescingTransformer: ================ @@ -121,23 +137,27 @@ fun m::test($t0: u64): u64 { var $t3: u64 var $t4: bool var $t5: u64 - var $t6: u64 [unused] + var $t6: u64 var $t7: u64 [unused] + var $t8: u64 [unused] + var $t9: u64 [unused] 0: $t2 := 0 1: $t3 := 0 2: label L0 - 3: $t5 := 10 - 4: $t4 := <($t3, $t5) - 5: if ($t4) goto 6 else goto 12 - 6: label L2 - 7: $t2 := copy($t0) - 8: $t5 := 1 - 9: $t5 := +($t3, $t5) - 10: $t3 := move($t5) - 11: goto 2 - 12: label L3 - 13: $t2 := move($t2) - 14: return $t2 + 3: $t5 := copy($t3) + 4: $t6 := 10 + 5: $t4 := <($t5, $t6) + 6: if ($t4) goto 7 else goto 14 + 7: label L2 + 8: $t2 := copy($t0) + 9: $t5 := move($t3) + 10: $t6 := 1 + 11: $t5 := +($t5, $t6) + 12: $t3 := move($t5) + 13: goto 2 + 14: label L3 + 15: $t2 := move($t2) + 16: return $t2 } ============ after DeadStoreElimination: ================ @@ -149,22 +169,27 @@ fun m::test($t0: u64): u64 { var $t3: u64 var $t4: bool var $t5: u64 - var $t6: u64 [unused] + var $t6: u64 var $t7: u64 [unused] + var $t8: u64 [unused] + var $t9: u64 [unused] 0: $t2 := 0 1: $t3 := 0 2: label L0 - 3: $t5 := 10 - 4: $t4 := <($t3, $t5) - 5: if ($t4) goto 6 else goto 12 - 6: label L2 - 7: $t2 := copy($t0) - 8: $t5 := 1 - 9: $t5 := +($t3, $t5) - 10: $t3 := move($t5) - 11: goto 2 - 12: label L3 - 13: return $t2 + 3: $t5 := copy($t3) + 4: $t6 := 10 + 5: $t4 := <($t5, $t6) + 6: if ($t4) goto 7 else goto 14 + 7: label L2 + 8: $t2 := copy($t0) + 9: $t5 := move($t3) + 10: $t6 := 1 + 11: $t5 := +($t5, $t6) + 12: $t3 := move($t5) + 13: goto 2 + 14: label L3 + 15: $t2 := move($t2) + 16: return $t2 } @@ -176,7 +201,6 @@ module c0ffee.m { test(Arg0: u64): u64 /* def_idx: 0 */ { L1: loc0: u64 L2: loc1: u64 -L3: loc2: u64 B0: 0: LdU64(0) 1: StLoc[1](loc0: u64) @@ -189,11 +213,11 @@ B1: 7: BrFalse(15) B2: 8: CopyLoc[0](Arg0: u64) - 9: MoveLoc[2](loc1: u64) - 10: LdU64(1) - 11: Add - 12: StLoc[2](loc1: u64) - 13: StLoc[1](loc0: u64) + 9: StLoc[1](loc0: u64) + 10: MoveLoc[2](loc1: u64) + 11: LdU64(1) + 12: Add + 13: StLoc[2](loc1: u64) 14: Branch(4) B3: 15: MoveLoc[1](loc0: u64) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_1.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_1.opt.exp index b8c4d57d833a0..41fb4d41dddfe 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_1.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_1.opt.exp @@ -9,25 +9,29 @@ fun m::test($t0: u64): u64 { var $t5: u64 var $t6: u64 var $t7: u64 + var $t8: u64 + var $t9: u64 0: $t2 := 0 1: $t3 := 0 2: label L0 - 3: $t5 := 10 - 4: $t4 := <($t3, $t5) - 5: if ($t4) goto 6 else goto 12 - 6: label L2 - 7: $t2 := infer($t0) - 8: $t7 := 1 - 9: $t6 := +($t3, $t7) - 10: $t3 := infer($t6) - 11: goto 14 - 12: label L3 + 3: $t5 := infer($t3) + 4: $t6 := 10 + 5: $t4 := <($t5, $t6) + 6: if ($t4) goto 7 else goto 14 + 7: label L2 + 8: $t2 := infer($t0) + 9: $t8 := infer($t3) + 10: $t9 := 1 + 11: $t7 := +($t8, $t9) + 12: $t3 := infer($t7) 13: goto 16 - 14: label L4 - 15: goto 2 - 16: label L1 - 17: $t1 := infer($t2) - 18: return $t1 + 14: label L3 + 15: goto 18 + 16: label L4 + 17: goto 2 + 18: label L1 + 19: $t1 := infer($t2) + 20: return $t1 } ============ after DeadStoreElimination: ================ @@ -41,21 +45,25 @@ fun m::test($t0: u64): u64 { var $t5: u64 var $t6: u64 var $t7: u64 + var $t8: u64 + var $t9: u64 0: $t2 := 0 1: $t3 := 0 2: label L0 - 3: $t5 := 10 - 4: $t4 := <($t3, $t5) - 5: if ($t4) goto 6 else goto 12 - 6: label L2 - 7: $t2 := copy($t0) - 8: $t7 := 1 - 9: $t6 := +($t3, $t7) - 10: $t3 := move($t6) - 11: goto 2 - 12: label L3 - 13: $t1 := move($t2) - 14: return $t1 + 3: $t5 := copy($t3) + 4: $t6 := 10 + 5: $t4 := <($t5, $t6) + 6: if ($t4) goto 7 else goto 14 + 7: label L2 + 8: $t2 := copy($t0) + 9: $t8 := move($t3) + 10: $t9 := 1 + 11: $t7 := +($t8, $t9) + 12: $t3 := move($t7) + 13: goto 2 + 14: label L3 + 15: $t1 := move($t2) + 16: return $t1 } ============ after VariableCoalescingAnnotator: ================ @@ -69,6 +77,8 @@ fun m::test($t0: u64): u64 { var $t5: u64 var $t6: u64 var $t7: u64 + var $t8: u64 + var $t9: u64 # live vars: $t0 # events: b:$t0, b:$t2 0: $t2 := 0 @@ -79,37 +89,43 @@ fun m::test($t0: u64): u64 { 2: label L0 # live vars: $t0, $t2, $t3 # events: b:$t5 - 3: $t5 := 10 + 3: $t5 := copy($t3) # live vars: $t0, $t2, $t3, $t5 - # events: e:$t5, b:$t4 - 4: $t4 := <($t3, $t5) + # events: b:$t6 + 4: $t6 := 10 + # live vars: $t0, $t2, $t3, $t5, $t6 + # events: e:$t5, e:$t6, b:$t4 + 5: $t4 := <($t5, $t6) # live vars: $t0, $t2, $t3, $t4 # events: e:$t4 - 5: if ($t4) goto 6 else goto 12 + 6: if ($t4) goto 7 else goto 14 # live vars: $t0, $t2, $t3 - 6: label L2 + 7: label L2 # live vars: $t0, $t3 - 7: $t2 := copy($t0) + 8: $t2 := copy($t0) # live vars: $t0, $t2, $t3 - # events: b:$t7 - 8: $t7 := 1 - # live vars: $t0, $t2, $t3, $t7 - # events: e:$t7, b:$t6 - 9: $t6 := +($t3, $t7) - # live vars: $t0, $t2, $t6 - # events: e:$t6 - 10: $t3 := move($t6) + # events: b:$t8 + 9: $t8 := move($t3) + # live vars: $t0, $t2, $t8 + # events: b:$t9 + 10: $t9 := 1 + # live vars: $t0, $t2, $t8, $t9 + # events: e:$t8, e:$t9, b:$t7 + 11: $t7 := +($t8, $t9) + # live vars: $t0, $t2, $t7 + # events: e:$t7 + 12: $t3 := move($t7) # live vars: $t0, $t2, $t3 - 11: goto 2 + 13: goto 2 # live vars: $t0, $t2, $t3 # events: e:$t0, e:$t3 - 12: label L3 + 14: label L3 # live vars: $t2 # events: e:$t2, b:$t1 - 13: $t1 := move($t2) + 15: $t1 := move($t2) # live vars: $t1 # events: e:$t1 - 14: return $t1 + 16: return $t1 } ============ after VariableCoalescingTransformer: ================ @@ -121,23 +137,27 @@ fun m::test($t0: u64): u64 { var $t3: u64 var $t4: bool var $t5: u64 - var $t6: u64 [unused] + var $t6: u64 var $t7: u64 [unused] + var $t8: u64 [unused] + var $t9: u64 [unused] 0: $t2 := 0 1: $t3 := 0 2: label L0 - 3: $t5 := 10 - 4: $t4 := <($t3, $t5) - 5: if ($t4) goto 6 else goto 12 - 6: label L2 - 7: $t2 := copy($t0) - 8: $t5 := 1 - 9: $t5 := +($t3, $t5) - 10: $t3 := move($t5) - 11: goto 2 - 12: label L3 - 13: $t2 := move($t2) - 14: return $t2 + 3: $t5 := copy($t3) + 4: $t6 := 10 + 5: $t4 := <($t5, $t6) + 6: if ($t4) goto 7 else goto 14 + 7: label L2 + 8: $t2 := copy($t0) + 9: $t5 := move($t3) + 10: $t6 := 1 + 11: $t5 := +($t5, $t6) + 12: $t3 := move($t5) + 13: goto 2 + 14: label L3 + 15: $t2 := move($t2) + 16: return $t2 } ============ after DeadStoreElimination: ================ @@ -149,22 +169,27 @@ fun m::test($t0: u64): u64 { var $t3: u64 var $t4: bool var $t5: u64 - var $t6: u64 [unused] + var $t6: u64 var $t7: u64 [unused] + var $t8: u64 [unused] + var $t9: u64 [unused] 0: $t2 := 0 1: $t3 := 0 2: label L0 - 3: $t5 := 10 - 4: $t4 := <($t3, $t5) - 5: if ($t4) goto 6 else goto 12 - 6: label L2 - 7: $t2 := copy($t0) - 8: $t5 := 1 - 9: $t5 := +($t3, $t5) - 10: $t3 := move($t5) - 11: goto 2 - 12: label L3 - 13: return $t2 + 3: $t5 := copy($t3) + 4: $t6 := 10 + 5: $t4 := <($t5, $t6) + 6: if ($t4) goto 7 else goto 14 + 7: label L2 + 8: $t2 := copy($t0) + 9: $t5 := move($t3) + 10: $t6 := 1 + 11: $t5 := +($t5, $t6) + 12: $t3 := move($t5) + 13: goto 2 + 14: label L3 + 15: $t2 := move($t2) + 16: return $t2 } @@ -176,7 +201,6 @@ module c0ffee.m { test(Arg0: u64): u64 /* def_idx: 0 */ { L1: loc0: u64 L2: loc1: u64 -L3: loc2: u64 B0: 0: LdU64(0) 1: StLoc[1](loc0: u64) @@ -189,11 +213,11 @@ B1: 7: BrFalse(15) B2: 8: CopyLoc[0](Arg0: u64) - 9: MoveLoc[2](loc1: u64) - 10: LdU64(1) - 11: Add - 12: StLoc[2](loc1: u64) - 13: StLoc[1](loc0: u64) + 9: StLoc[1](loc0: u64) + 10: MoveLoc[2](loc1: u64) + 11: LdU64(1) + 12: Add + 13: StLoc[2](loc1: u64) 14: Branch(4) B3: 15: MoveLoc[1](loc0: u64) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_2.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_2.exp index 3334689dfa167..07402b30cdb90 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_2.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_2.exp @@ -9,25 +9,29 @@ fun m::test($t0: u64): u64 { var $t5: u64 var $t6: u64 var $t7: u64 + var $t8: u64 + var $t9: u64 0: $t2 := infer($t0) 1: $t3 := 0 2: label L0 - 3: $t5 := 10 - 4: $t4 := <($t3, $t5) - 5: if ($t4) goto 6 else goto 12 - 6: label L2 - 7: $t2 := infer($t0) - 8: $t7 := 1 - 9: $t6 := +($t3, $t7) - 10: $t3 := infer($t6) - 11: goto 14 - 12: label L3 + 3: $t5 := infer($t3) + 4: $t6 := 10 + 5: $t4 := <($t5, $t6) + 6: if ($t4) goto 7 else goto 14 + 7: label L2 + 8: $t2 := infer($t0) + 9: $t8 := infer($t3) + 10: $t9 := 1 + 11: $t7 := +($t8, $t9) + 12: $t3 := infer($t7) 13: goto 16 - 14: label L4 - 15: goto 2 - 16: label L1 - 17: $t1 := infer($t2) - 18: return $t1 + 14: label L3 + 15: goto 18 + 16: label L4 + 17: goto 2 + 18: label L1 + 19: $t1 := infer($t2) + 20: return $t1 } ============ after DeadStoreElimination: ================ @@ -41,21 +45,25 @@ fun m::test($t0: u64): u64 { var $t5: u64 var $t6: u64 var $t7: u64 + var $t8: u64 + var $t9: u64 0: $t2 := copy($t0) 1: $t3 := 0 2: label L0 - 3: $t5 := 10 - 4: $t4 := <($t3, $t5) - 5: if ($t4) goto 6 else goto 12 - 6: label L2 - 7: $t2 := copy($t0) - 8: $t7 := 1 - 9: $t6 := +($t3, $t7) - 10: $t3 := move($t6) - 11: goto 2 - 12: label L3 - 13: $t1 := move($t2) - 14: return $t1 + 3: $t5 := copy($t3) + 4: $t6 := 10 + 5: $t4 := <($t5, $t6) + 6: if ($t4) goto 7 else goto 14 + 7: label L2 + 8: $t2 := copy($t0) + 9: $t8 := move($t3) + 10: $t9 := 1 + 11: $t7 := +($t8, $t9) + 12: $t3 := move($t7) + 13: goto 2 + 14: label L3 + 15: $t1 := move($t2) + 16: return $t1 } ============ after VariableCoalescingAnnotator: ================ @@ -69,6 +77,8 @@ fun m::test($t0: u64): u64 { var $t5: u64 var $t6: u64 var $t7: u64 + var $t8: u64 + var $t9: u64 # live vars: $t0 # events: b:$t0, b:$t2 0: $t2 := copy($t0) @@ -79,37 +89,43 @@ fun m::test($t0: u64): u64 { 2: label L0 # live vars: $t0, $t2, $t3 # events: b:$t5 - 3: $t5 := 10 + 3: $t5 := copy($t3) # live vars: $t0, $t2, $t3, $t5 - # events: e:$t5, b:$t4 - 4: $t4 := <($t3, $t5) + # events: b:$t6 + 4: $t6 := 10 + # live vars: $t0, $t2, $t3, $t5, $t6 + # events: e:$t5, e:$t6, b:$t4 + 5: $t4 := <($t5, $t6) # live vars: $t0, $t2, $t3, $t4 # events: e:$t4 - 5: if ($t4) goto 6 else goto 12 + 6: if ($t4) goto 7 else goto 14 # live vars: $t0, $t2, $t3 - 6: label L2 + 7: label L2 # live vars: $t0, $t3 - 7: $t2 := copy($t0) + 8: $t2 := copy($t0) # live vars: $t0, $t2, $t3 - # events: b:$t7 - 8: $t7 := 1 - # live vars: $t0, $t2, $t3, $t7 - # events: e:$t7, b:$t6 - 9: $t6 := +($t3, $t7) - # live vars: $t0, $t2, $t6 - # events: e:$t6 - 10: $t3 := move($t6) + # events: b:$t8 + 9: $t8 := move($t3) + # live vars: $t0, $t2, $t8 + # events: b:$t9 + 10: $t9 := 1 + # live vars: $t0, $t2, $t8, $t9 + # events: e:$t8, e:$t9, b:$t7 + 11: $t7 := +($t8, $t9) + # live vars: $t0, $t2, $t7 + # events: e:$t7 + 12: $t3 := move($t7) # live vars: $t0, $t2, $t3 - 11: goto 2 + 13: goto 2 # live vars: $t0, $t2, $t3 # events: e:$t0, e:$t3 - 12: label L3 + 14: label L3 # live vars: $t2 # events: e:$t2, b:$t1 - 13: $t1 := move($t2) + 15: $t1 := move($t2) # live vars: $t1 # events: e:$t1 - 14: return $t1 + 16: return $t1 } ============ after VariableCoalescingTransformer: ================ @@ -121,23 +137,27 @@ fun m::test($t0: u64): u64 { var $t3: u64 var $t4: bool var $t5: u64 - var $t6: u64 [unused] + var $t6: u64 var $t7: u64 [unused] + var $t8: u64 [unused] + var $t9: u64 [unused] 0: $t2 := copy($t0) 1: $t3 := 0 2: label L0 - 3: $t5 := 10 - 4: $t4 := <($t3, $t5) - 5: if ($t4) goto 6 else goto 12 - 6: label L2 - 7: $t2 := copy($t0) - 8: $t5 := 1 - 9: $t5 := +($t3, $t5) - 10: $t3 := move($t5) - 11: goto 2 - 12: label L3 - 13: $t2 := move($t2) - 14: return $t2 + 3: $t5 := copy($t3) + 4: $t6 := 10 + 5: $t4 := <($t5, $t6) + 6: if ($t4) goto 7 else goto 14 + 7: label L2 + 8: $t2 := copy($t0) + 9: $t5 := move($t3) + 10: $t6 := 1 + 11: $t5 := +($t5, $t6) + 12: $t3 := move($t5) + 13: goto 2 + 14: label L3 + 15: $t2 := move($t2) + 16: return $t2 } ============ after DeadStoreElimination: ================ @@ -149,22 +169,27 @@ fun m::test($t0: u64): u64 { var $t3: u64 var $t4: bool var $t5: u64 - var $t6: u64 [unused] + var $t6: u64 var $t7: u64 [unused] + var $t8: u64 [unused] + var $t9: u64 [unused] 0: $t2 := copy($t0) 1: $t3 := 0 2: label L0 - 3: $t5 := 10 - 4: $t4 := <($t3, $t5) - 5: if ($t4) goto 6 else goto 12 - 6: label L2 - 7: $t2 := copy($t0) - 8: $t5 := 1 - 9: $t5 := +($t3, $t5) - 10: $t3 := move($t5) - 11: goto 2 - 12: label L3 - 13: return $t2 + 3: $t5 := copy($t3) + 4: $t6 := 10 + 5: $t4 := <($t5, $t6) + 6: if ($t4) goto 7 else goto 14 + 7: label L2 + 8: $t2 := copy($t0) + 9: $t5 := move($t3) + 10: $t6 := 1 + 11: $t5 := +($t5, $t6) + 12: $t3 := move($t5) + 13: goto 2 + 14: label L3 + 15: $t2 := move($t2) + 16: return $t2 } @@ -176,27 +201,26 @@ module c0ffee.m { test(Arg0: u64): u64 /* def_idx: 0 */ { L1: loc0: u64 L2: loc1: u64 -L3: loc2: u64 B0: 0: CopyLoc[0](Arg0: u64) - 1: LdU64(0) - 2: StLoc[1](loc0: u64) + 1: StLoc[1](loc0: u64) + 2: LdU64(0) 3: StLoc[2](loc1: u64) B1: - 4: CopyLoc[1](loc0: u64) + 4: CopyLoc[2](loc1: u64) 5: LdU64(10) 6: Lt 7: BrFalse(15) B2: 8: CopyLoc[0](Arg0: u64) - 9: MoveLoc[1](loc0: u64) - 10: LdU64(1) - 11: Add - 12: StLoc[1](loc0: u64) + 9: StLoc[1](loc0: u64) + 10: MoveLoc[2](loc1: u64) + 11: LdU64(1) + 12: Add 13: StLoc[2](loc1: u64) 14: Branch(4) B3: - 15: MoveLoc[2](loc1: u64) + 15: MoveLoc[1](loc0: u64) 16: Ret } } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_2.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_2.opt.exp index 3334689dfa167..07402b30cdb90 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_2.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_2.opt.exp @@ -9,25 +9,29 @@ fun m::test($t0: u64): u64 { var $t5: u64 var $t6: u64 var $t7: u64 + var $t8: u64 + var $t9: u64 0: $t2 := infer($t0) 1: $t3 := 0 2: label L0 - 3: $t5 := 10 - 4: $t4 := <($t3, $t5) - 5: if ($t4) goto 6 else goto 12 - 6: label L2 - 7: $t2 := infer($t0) - 8: $t7 := 1 - 9: $t6 := +($t3, $t7) - 10: $t3 := infer($t6) - 11: goto 14 - 12: label L3 + 3: $t5 := infer($t3) + 4: $t6 := 10 + 5: $t4 := <($t5, $t6) + 6: if ($t4) goto 7 else goto 14 + 7: label L2 + 8: $t2 := infer($t0) + 9: $t8 := infer($t3) + 10: $t9 := 1 + 11: $t7 := +($t8, $t9) + 12: $t3 := infer($t7) 13: goto 16 - 14: label L4 - 15: goto 2 - 16: label L1 - 17: $t1 := infer($t2) - 18: return $t1 + 14: label L3 + 15: goto 18 + 16: label L4 + 17: goto 2 + 18: label L1 + 19: $t1 := infer($t2) + 20: return $t1 } ============ after DeadStoreElimination: ================ @@ -41,21 +45,25 @@ fun m::test($t0: u64): u64 { var $t5: u64 var $t6: u64 var $t7: u64 + var $t8: u64 + var $t9: u64 0: $t2 := copy($t0) 1: $t3 := 0 2: label L0 - 3: $t5 := 10 - 4: $t4 := <($t3, $t5) - 5: if ($t4) goto 6 else goto 12 - 6: label L2 - 7: $t2 := copy($t0) - 8: $t7 := 1 - 9: $t6 := +($t3, $t7) - 10: $t3 := move($t6) - 11: goto 2 - 12: label L3 - 13: $t1 := move($t2) - 14: return $t1 + 3: $t5 := copy($t3) + 4: $t6 := 10 + 5: $t4 := <($t5, $t6) + 6: if ($t4) goto 7 else goto 14 + 7: label L2 + 8: $t2 := copy($t0) + 9: $t8 := move($t3) + 10: $t9 := 1 + 11: $t7 := +($t8, $t9) + 12: $t3 := move($t7) + 13: goto 2 + 14: label L3 + 15: $t1 := move($t2) + 16: return $t1 } ============ after VariableCoalescingAnnotator: ================ @@ -69,6 +77,8 @@ fun m::test($t0: u64): u64 { var $t5: u64 var $t6: u64 var $t7: u64 + var $t8: u64 + var $t9: u64 # live vars: $t0 # events: b:$t0, b:$t2 0: $t2 := copy($t0) @@ -79,37 +89,43 @@ fun m::test($t0: u64): u64 { 2: label L0 # live vars: $t0, $t2, $t3 # events: b:$t5 - 3: $t5 := 10 + 3: $t5 := copy($t3) # live vars: $t0, $t2, $t3, $t5 - # events: e:$t5, b:$t4 - 4: $t4 := <($t3, $t5) + # events: b:$t6 + 4: $t6 := 10 + # live vars: $t0, $t2, $t3, $t5, $t6 + # events: e:$t5, e:$t6, b:$t4 + 5: $t4 := <($t5, $t6) # live vars: $t0, $t2, $t3, $t4 # events: e:$t4 - 5: if ($t4) goto 6 else goto 12 + 6: if ($t4) goto 7 else goto 14 # live vars: $t0, $t2, $t3 - 6: label L2 + 7: label L2 # live vars: $t0, $t3 - 7: $t2 := copy($t0) + 8: $t2 := copy($t0) # live vars: $t0, $t2, $t3 - # events: b:$t7 - 8: $t7 := 1 - # live vars: $t0, $t2, $t3, $t7 - # events: e:$t7, b:$t6 - 9: $t6 := +($t3, $t7) - # live vars: $t0, $t2, $t6 - # events: e:$t6 - 10: $t3 := move($t6) + # events: b:$t8 + 9: $t8 := move($t3) + # live vars: $t0, $t2, $t8 + # events: b:$t9 + 10: $t9 := 1 + # live vars: $t0, $t2, $t8, $t9 + # events: e:$t8, e:$t9, b:$t7 + 11: $t7 := +($t8, $t9) + # live vars: $t0, $t2, $t7 + # events: e:$t7 + 12: $t3 := move($t7) # live vars: $t0, $t2, $t3 - 11: goto 2 + 13: goto 2 # live vars: $t0, $t2, $t3 # events: e:$t0, e:$t3 - 12: label L3 + 14: label L3 # live vars: $t2 # events: e:$t2, b:$t1 - 13: $t1 := move($t2) + 15: $t1 := move($t2) # live vars: $t1 # events: e:$t1 - 14: return $t1 + 16: return $t1 } ============ after VariableCoalescingTransformer: ================ @@ -121,23 +137,27 @@ fun m::test($t0: u64): u64 { var $t3: u64 var $t4: bool var $t5: u64 - var $t6: u64 [unused] + var $t6: u64 var $t7: u64 [unused] + var $t8: u64 [unused] + var $t9: u64 [unused] 0: $t2 := copy($t0) 1: $t3 := 0 2: label L0 - 3: $t5 := 10 - 4: $t4 := <($t3, $t5) - 5: if ($t4) goto 6 else goto 12 - 6: label L2 - 7: $t2 := copy($t0) - 8: $t5 := 1 - 9: $t5 := +($t3, $t5) - 10: $t3 := move($t5) - 11: goto 2 - 12: label L3 - 13: $t2 := move($t2) - 14: return $t2 + 3: $t5 := copy($t3) + 4: $t6 := 10 + 5: $t4 := <($t5, $t6) + 6: if ($t4) goto 7 else goto 14 + 7: label L2 + 8: $t2 := copy($t0) + 9: $t5 := move($t3) + 10: $t6 := 1 + 11: $t5 := +($t5, $t6) + 12: $t3 := move($t5) + 13: goto 2 + 14: label L3 + 15: $t2 := move($t2) + 16: return $t2 } ============ after DeadStoreElimination: ================ @@ -149,22 +169,27 @@ fun m::test($t0: u64): u64 { var $t3: u64 var $t4: bool var $t5: u64 - var $t6: u64 [unused] + var $t6: u64 var $t7: u64 [unused] + var $t8: u64 [unused] + var $t9: u64 [unused] 0: $t2 := copy($t0) 1: $t3 := 0 2: label L0 - 3: $t5 := 10 - 4: $t4 := <($t3, $t5) - 5: if ($t4) goto 6 else goto 12 - 6: label L2 - 7: $t2 := copy($t0) - 8: $t5 := 1 - 9: $t5 := +($t3, $t5) - 10: $t3 := move($t5) - 11: goto 2 - 12: label L3 - 13: return $t2 + 3: $t5 := copy($t3) + 4: $t6 := 10 + 5: $t4 := <($t5, $t6) + 6: if ($t4) goto 7 else goto 14 + 7: label L2 + 8: $t2 := copy($t0) + 9: $t5 := move($t3) + 10: $t6 := 1 + 11: $t5 := +($t5, $t6) + 12: $t3 := move($t5) + 13: goto 2 + 14: label L3 + 15: $t2 := move($t2) + 16: return $t2 } @@ -176,27 +201,26 @@ module c0ffee.m { test(Arg0: u64): u64 /* def_idx: 0 */ { L1: loc0: u64 L2: loc1: u64 -L3: loc2: u64 B0: 0: CopyLoc[0](Arg0: u64) - 1: LdU64(0) - 2: StLoc[1](loc0: u64) + 1: StLoc[1](loc0: u64) + 2: LdU64(0) 3: StLoc[2](loc1: u64) B1: - 4: CopyLoc[1](loc0: u64) + 4: CopyLoc[2](loc1: u64) 5: LdU64(10) 6: Lt 7: BrFalse(15) B2: 8: CopyLoc[0](Arg0: u64) - 9: MoveLoc[1](loc0: u64) - 10: LdU64(1) - 11: Add - 12: StLoc[1](loc0: u64) + 9: StLoc[1](loc0: u64) + 10: MoveLoc[2](loc1: u64) + 11: LdU64(1) + 12: Add 13: StLoc[2](loc1: u64) 14: Branch(4) B3: - 15: MoveLoc[2](loc1: u64) + 15: MoveLoc[1](loc0: u64) 16: Ret } } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/non_overlapping_vars1.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/non_overlapping_vars1.exp index 0790b3db1cd47..02df37a49f25d 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/non_overlapping_vars1.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/non_overlapping_vars1.exp @@ -8,15 +8,19 @@ fun m::test() { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 + var $t7: u64 0: $t0 := 1 - 1: $t2 := 1 - 2: $t1 := +($t0, $t2) - 3: $t0 := infer($t1) - 4: $t3 := 2 - 5: $t5 := 1 - 6: $t4 := +($t3, $t5) - 7: $t3 := infer($t4) - 8: return () + 1: $t2 := infer($t0) + 2: $t3 := 1 + 3: $t1 := +($t2, $t3) + 4: $t0 := infer($t1) + 5: $t4 := 2 + 6: $t6 := infer($t4) + 7: $t7 := 1 + 8: $t5 := +($t6, $t7) + 9: $t4 := infer($t5) + 10: return () } @@ -43,13 +47,17 @@ fun m::test() { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 + var $t7: u64 0: $t0 := 1 - 1: $t2 := 1 - 2: $t1 := +($t0, $t2) - 3: $t3 := 2 - 4: $t5 := 1 - 5: $t4 := +($t3, $t5) - 6: return () + 1: $t2 := move($t0) + 2: $t3 := 1 + 3: $t1 := +($t2, $t3) + 4: $t4 := 2 + 5: $t6 := move($t4) + 6: $t7 := 1 + 7: $t5 := +($t6, $t7) + 8: return () } ============ after VariableCoalescingAnnotator: ================ @@ -62,26 +70,34 @@ fun m::test() { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 + var $t7: u64 # live vars: # events: b:$t0 0: $t0 := 1 # live vars: $t0 - # events: b:$t2 - 1: $t2 := 1 - # live vars: $t0, $t2 - # events: e:$t0, e:$t1, e:$t2, b:$t1 - 2: $t1 := +($t0, $t2) - # live vars: + # events: e:$t0, b:$t2 + 1: $t2 := move($t0) + # live vars: $t2 # events: b:$t3 - 3: $t3 := 2 - # live vars: $t3 - # events: b:$t5 - 4: $t5 := 1 - # live vars: $t3, $t5 - # events: e:$t3, e:$t4, e:$t5, b:$t4 - 5: $t4 := +($t3, $t5) + 2: $t3 := 1 + # live vars: $t2, $t3 + # events: e:$t1, e:$t2, e:$t3, b:$t1 + 3: $t1 := +($t2, $t3) # live vars: - 6: return () + # events: b:$t4 + 4: $t4 := 2 + # live vars: $t4 + # events: e:$t4, b:$t6 + 5: $t6 := move($t4) + # live vars: $t6 + # events: b:$t7 + 6: $t7 := 1 + # live vars: $t6, $t7 + # events: e:$t5, e:$t6, e:$t7, b:$t5 + 7: $t5 := +($t6, $t7) + # live vars: + 8: return () } ============ after VariableCoalescingTransformer: ================ @@ -90,17 +106,21 @@ fun m::test() { fun m::test() { var $t0: u64 var $t1: u64 - var $t2: u64 - var $t3: u64 [unused] + var $t2: u64 [unused] + var $t3: u64 var $t4: u64 [unused] var $t5: u64 [unused] + var $t6: u64 [unused] + var $t7: u64 [unused] 0: $t0 := 1 - 1: $t2 := 1 - 2: $t0 := +($t0, $t2) - 3: $t1 := 2 - 4: $t2 := 1 - 5: $t1 := +($t1, $t2) - 6: return () + 1: $t0 := move($t0) + 2: $t3 := 1 + 3: $t0 := +($t0, $t3) + 4: $t1 := 2 + 5: $t1 := move($t1) + 6: $t3 := 1 + 7: $t1 := +($t1, $t3) + 8: return () } ============ after DeadStoreElimination: ================ @@ -109,16 +129,18 @@ fun m::test() { fun m::test() { var $t0: u64 var $t1: u64 - var $t2: u64 - var $t3: u64 [unused] + var $t2: u64 [unused] + var $t3: u64 var $t4: u64 [unused] var $t5: u64 [unused] + var $t6: u64 [unused] + var $t7: u64 [unused] 0: $t0 := 1 - 1: $t2 := 1 - 2: $t0 := +($t0, $t2) + 1: $t3 := 1 + 2: $t0 := +($t0, $t3) 3: $t1 := 2 - 4: $t2 := 1 - 5: $t1 := +($t1, $t2) + 4: $t3 := 1 + 5: $t1 := +($t1, $t3) 6: return () } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/non_overlapping_vars1.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/non_overlapping_vars1.opt.exp index 0790b3db1cd47..02df37a49f25d 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/non_overlapping_vars1.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/non_overlapping_vars1.opt.exp @@ -8,15 +8,19 @@ fun m::test() { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 + var $t7: u64 0: $t0 := 1 - 1: $t2 := 1 - 2: $t1 := +($t0, $t2) - 3: $t0 := infer($t1) - 4: $t3 := 2 - 5: $t5 := 1 - 6: $t4 := +($t3, $t5) - 7: $t3 := infer($t4) - 8: return () + 1: $t2 := infer($t0) + 2: $t3 := 1 + 3: $t1 := +($t2, $t3) + 4: $t0 := infer($t1) + 5: $t4 := 2 + 6: $t6 := infer($t4) + 7: $t7 := 1 + 8: $t5 := +($t6, $t7) + 9: $t4 := infer($t5) + 10: return () } @@ -43,13 +47,17 @@ fun m::test() { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 + var $t7: u64 0: $t0 := 1 - 1: $t2 := 1 - 2: $t1 := +($t0, $t2) - 3: $t3 := 2 - 4: $t5 := 1 - 5: $t4 := +($t3, $t5) - 6: return () + 1: $t2 := move($t0) + 2: $t3 := 1 + 3: $t1 := +($t2, $t3) + 4: $t4 := 2 + 5: $t6 := move($t4) + 6: $t7 := 1 + 7: $t5 := +($t6, $t7) + 8: return () } ============ after VariableCoalescingAnnotator: ================ @@ -62,26 +70,34 @@ fun m::test() { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 + var $t7: u64 # live vars: # events: b:$t0 0: $t0 := 1 # live vars: $t0 - # events: b:$t2 - 1: $t2 := 1 - # live vars: $t0, $t2 - # events: e:$t0, e:$t1, e:$t2, b:$t1 - 2: $t1 := +($t0, $t2) - # live vars: + # events: e:$t0, b:$t2 + 1: $t2 := move($t0) + # live vars: $t2 # events: b:$t3 - 3: $t3 := 2 - # live vars: $t3 - # events: b:$t5 - 4: $t5 := 1 - # live vars: $t3, $t5 - # events: e:$t3, e:$t4, e:$t5, b:$t4 - 5: $t4 := +($t3, $t5) + 2: $t3 := 1 + # live vars: $t2, $t3 + # events: e:$t1, e:$t2, e:$t3, b:$t1 + 3: $t1 := +($t2, $t3) # live vars: - 6: return () + # events: b:$t4 + 4: $t4 := 2 + # live vars: $t4 + # events: e:$t4, b:$t6 + 5: $t6 := move($t4) + # live vars: $t6 + # events: b:$t7 + 6: $t7 := 1 + # live vars: $t6, $t7 + # events: e:$t5, e:$t6, e:$t7, b:$t5 + 7: $t5 := +($t6, $t7) + # live vars: + 8: return () } ============ after VariableCoalescingTransformer: ================ @@ -90,17 +106,21 @@ fun m::test() { fun m::test() { var $t0: u64 var $t1: u64 - var $t2: u64 - var $t3: u64 [unused] + var $t2: u64 [unused] + var $t3: u64 var $t4: u64 [unused] var $t5: u64 [unused] + var $t6: u64 [unused] + var $t7: u64 [unused] 0: $t0 := 1 - 1: $t2 := 1 - 2: $t0 := +($t0, $t2) - 3: $t1 := 2 - 4: $t2 := 1 - 5: $t1 := +($t1, $t2) - 6: return () + 1: $t0 := move($t0) + 2: $t3 := 1 + 3: $t0 := +($t0, $t3) + 4: $t1 := 2 + 5: $t1 := move($t1) + 6: $t3 := 1 + 7: $t1 := +($t1, $t3) + 8: return () } ============ after DeadStoreElimination: ================ @@ -109,16 +129,18 @@ fun m::test() { fun m::test() { var $t0: u64 var $t1: u64 - var $t2: u64 - var $t3: u64 [unused] + var $t2: u64 [unused] + var $t3: u64 var $t4: u64 [unused] var $t5: u64 [unused] + var $t6: u64 [unused] + var $t7: u64 [unused] 0: $t0 := 1 - 1: $t2 := 1 - 2: $t0 := +($t0, $t2) + 1: $t3 := 1 + 2: $t0 := +($t0, $t3) 3: $t1 := 2 - 4: $t2 := 1 - 5: $t1 := +($t1, $t2) + 4: $t3 := 1 + 5: $t1 := +($t1, $t3) 6: return () } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/non_overlapping_vars_diff_type.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/non_overlapping_vars_diff_type.exp index 631c697bc491e..84ab65613679c 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/non_overlapping_vars_diff_type.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/non_overlapping_vars_diff_type.exp @@ -5,18 +5,22 @@ fun m::test() { var $t0: u32 var $t1: u32 var $t2: u32 - var $t3: u64 + var $t3: u32 var $t4: u64 var $t5: u64 + var $t6: u64 + var $t7: u64 0: $t0 := 1 - 1: $t2 := 1 - 2: $t1 := +($t0, $t2) - 3: $t0 := infer($t1) - 4: $t3 := 2 - 5: $t5 := 1 - 6: $t4 := +($t3, $t5) - 7: $t3 := infer($t4) - 8: return () + 1: $t2 := infer($t0) + 2: $t3 := 1 + 3: $t1 := +($t2, $t3) + 4: $t0 := infer($t1) + 5: $t4 := 2 + 6: $t6 := infer($t4) + 7: $t7 := 1 + 8: $t5 := +($t6, $t7) + 9: $t4 := infer($t5) + 10: return () } @@ -40,16 +44,20 @@ fun m::test() { var $t0: u32 var $t1: u32 var $t2: u32 - var $t3: u64 + var $t3: u32 var $t4: u64 var $t5: u64 + var $t6: u64 + var $t7: u64 0: $t0 := 1 - 1: $t2 := 1 - 2: $t1 := +($t0, $t2) - 3: $t3 := 2 - 4: $t5 := 1 - 5: $t4 := +($t3, $t5) - 6: return () + 1: $t2 := move($t0) + 2: $t3 := 1 + 3: $t1 := +($t2, $t3) + 4: $t4 := 2 + 5: $t6 := move($t4) + 6: $t7 := 1 + 7: $t5 := +($t6, $t7) + 8: return () } ============ after VariableCoalescingAnnotator: ================ @@ -59,29 +67,37 @@ fun m::test() { var $t0: u32 var $t1: u32 var $t2: u32 - var $t3: u64 + var $t3: u32 var $t4: u64 var $t5: u64 + var $t6: u64 + var $t7: u64 # live vars: # events: b:$t0 0: $t0 := 1 # live vars: $t0 - # events: b:$t2 - 1: $t2 := 1 - # live vars: $t0, $t2 - # events: e:$t0, e:$t1, e:$t2, b:$t1 - 2: $t1 := +($t0, $t2) - # live vars: + # events: e:$t0, b:$t2 + 1: $t2 := move($t0) + # live vars: $t2 # events: b:$t3 - 3: $t3 := 2 - # live vars: $t3 - # events: b:$t5 - 4: $t5 := 1 - # live vars: $t3, $t5 - # events: e:$t3, e:$t4, e:$t5, b:$t4 - 5: $t4 := +($t3, $t5) + 2: $t3 := 1 + # live vars: $t2, $t3 + # events: e:$t1, e:$t2, e:$t3, b:$t1 + 3: $t1 := +($t2, $t3) # live vars: - 6: return () + # events: b:$t4 + 4: $t4 := 2 + # live vars: $t4 + # events: e:$t4, b:$t6 + 5: $t6 := move($t4) + # live vars: $t6 + # events: b:$t7 + 6: $t7 := 1 + # live vars: $t6, $t7 + # events: e:$t5, e:$t6, e:$t7, b:$t5 + 7: $t5 := +($t6, $t7) + # live vars: + 8: return () } ============ after VariableCoalescingTransformer: ================ @@ -90,17 +106,21 @@ fun m::test() { fun m::test() { var $t0: u32 var $t1: u32 [unused] - var $t2: u32 - var $t3: u64 - var $t4: u64 [unused] - var $t5: u64 + var $t2: u32 [unused] + var $t3: u32 + var $t4: u64 + var $t5: u64 [unused] + var $t6: u64 [unused] + var $t7: u64 0: $t0 := 1 - 1: $t2 := 1 - 2: $t0 := +($t0, $t2) - 3: $t3 := 2 - 4: $t5 := 1 - 5: $t3 := +($t3, $t5) - 6: return () + 1: $t0 := move($t0) + 2: $t3 := 1 + 3: $t0 := +($t0, $t3) + 4: $t4 := 2 + 5: $t4 := move($t4) + 6: $t7 := 1 + 7: $t4 := +($t4, $t7) + 8: return () } ============ after DeadStoreElimination: ================ @@ -109,16 +129,18 @@ fun m::test() { fun m::test() { var $t0: u32 var $t1: u32 [unused] - var $t2: u32 - var $t3: u64 - var $t4: u64 [unused] - var $t5: u64 + var $t2: u32 [unused] + var $t3: u32 + var $t4: u64 + var $t5: u64 [unused] + var $t6: u64 [unused] + var $t7: u64 0: $t0 := 1 - 1: $t2 := 1 - 2: $t0 := +($t0, $t2) - 3: $t3 := 2 - 4: $t5 := 1 - 5: $t3 := +($t3, $t5) + 1: $t3 := 1 + 2: $t0 := +($t0, $t3) + 3: $t4 := 2 + 4: $t7 := 1 + 5: $t4 := +($t4, $t7) 6: return () } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/non_overlapping_vars_diff_type.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/non_overlapping_vars_diff_type.opt.exp index 631c697bc491e..84ab65613679c 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/non_overlapping_vars_diff_type.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/non_overlapping_vars_diff_type.opt.exp @@ -5,18 +5,22 @@ fun m::test() { var $t0: u32 var $t1: u32 var $t2: u32 - var $t3: u64 + var $t3: u32 var $t4: u64 var $t5: u64 + var $t6: u64 + var $t7: u64 0: $t0 := 1 - 1: $t2 := 1 - 2: $t1 := +($t0, $t2) - 3: $t0 := infer($t1) - 4: $t3 := 2 - 5: $t5 := 1 - 6: $t4 := +($t3, $t5) - 7: $t3 := infer($t4) - 8: return () + 1: $t2 := infer($t0) + 2: $t3 := 1 + 3: $t1 := +($t2, $t3) + 4: $t0 := infer($t1) + 5: $t4 := 2 + 6: $t6 := infer($t4) + 7: $t7 := 1 + 8: $t5 := +($t6, $t7) + 9: $t4 := infer($t5) + 10: return () } @@ -40,16 +44,20 @@ fun m::test() { var $t0: u32 var $t1: u32 var $t2: u32 - var $t3: u64 + var $t3: u32 var $t4: u64 var $t5: u64 + var $t6: u64 + var $t7: u64 0: $t0 := 1 - 1: $t2 := 1 - 2: $t1 := +($t0, $t2) - 3: $t3 := 2 - 4: $t5 := 1 - 5: $t4 := +($t3, $t5) - 6: return () + 1: $t2 := move($t0) + 2: $t3 := 1 + 3: $t1 := +($t2, $t3) + 4: $t4 := 2 + 5: $t6 := move($t4) + 6: $t7 := 1 + 7: $t5 := +($t6, $t7) + 8: return () } ============ after VariableCoalescingAnnotator: ================ @@ -59,29 +67,37 @@ fun m::test() { var $t0: u32 var $t1: u32 var $t2: u32 - var $t3: u64 + var $t3: u32 var $t4: u64 var $t5: u64 + var $t6: u64 + var $t7: u64 # live vars: # events: b:$t0 0: $t0 := 1 # live vars: $t0 - # events: b:$t2 - 1: $t2 := 1 - # live vars: $t0, $t2 - # events: e:$t0, e:$t1, e:$t2, b:$t1 - 2: $t1 := +($t0, $t2) - # live vars: + # events: e:$t0, b:$t2 + 1: $t2 := move($t0) + # live vars: $t2 # events: b:$t3 - 3: $t3 := 2 - # live vars: $t3 - # events: b:$t5 - 4: $t5 := 1 - # live vars: $t3, $t5 - # events: e:$t3, e:$t4, e:$t5, b:$t4 - 5: $t4 := +($t3, $t5) + 2: $t3 := 1 + # live vars: $t2, $t3 + # events: e:$t1, e:$t2, e:$t3, b:$t1 + 3: $t1 := +($t2, $t3) # live vars: - 6: return () + # events: b:$t4 + 4: $t4 := 2 + # live vars: $t4 + # events: e:$t4, b:$t6 + 5: $t6 := move($t4) + # live vars: $t6 + # events: b:$t7 + 6: $t7 := 1 + # live vars: $t6, $t7 + # events: e:$t5, e:$t6, e:$t7, b:$t5 + 7: $t5 := +($t6, $t7) + # live vars: + 8: return () } ============ after VariableCoalescingTransformer: ================ @@ -90,17 +106,21 @@ fun m::test() { fun m::test() { var $t0: u32 var $t1: u32 [unused] - var $t2: u32 - var $t3: u64 - var $t4: u64 [unused] - var $t5: u64 + var $t2: u32 [unused] + var $t3: u32 + var $t4: u64 + var $t5: u64 [unused] + var $t6: u64 [unused] + var $t7: u64 0: $t0 := 1 - 1: $t2 := 1 - 2: $t0 := +($t0, $t2) - 3: $t3 := 2 - 4: $t5 := 1 - 5: $t3 := +($t3, $t5) - 6: return () + 1: $t0 := move($t0) + 2: $t3 := 1 + 3: $t0 := +($t0, $t3) + 4: $t4 := 2 + 5: $t4 := move($t4) + 6: $t7 := 1 + 7: $t4 := +($t4, $t7) + 8: return () } ============ after DeadStoreElimination: ================ @@ -109,16 +129,18 @@ fun m::test() { fun m::test() { var $t0: u32 var $t1: u32 [unused] - var $t2: u32 - var $t3: u64 - var $t4: u64 [unused] - var $t5: u64 + var $t2: u32 [unused] + var $t3: u32 + var $t4: u64 + var $t5: u64 [unused] + var $t6: u64 [unused] + var $t7: u64 0: $t0 := 1 - 1: $t2 := 1 - 2: $t0 := +($t0, $t2) - 3: $t3 := 2 - 4: $t5 := 1 - 5: $t3 := +($t3, $t5) + 1: $t3 := 1 + 2: $t0 := +($t0, $t3) + 3: $t4 := 2 + 4: $t7 := 1 + 5: $t4 := +($t4, $t7) 6: return () } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/overlapping_vars.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/overlapping_vars.exp index 6a7fe387fea8d..100bf7dc94e2b 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/overlapping_vars.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/overlapping_vars.exp @@ -7,12 +7,14 @@ fun m::test(): u64 { var $t2: u64 var $t3: u64 var $t4: u64 + var $t5: u64 0: $t1 := 1 1: $t2 := 2 2: $t3 := 3 - 3: $t4 := +($t1, $t2) - 4: $t0 := +($t4, $t3) - 5: return $t0 + 3: $t5 := infer($t1) + 4: $t4 := +($t5, $t2) + 5: $t0 := +($t4, $t3) + 6: return $t0 } ============ after DeadStoreElimination: ================ @@ -24,12 +26,14 @@ fun m::test(): u64 { var $t2: u64 var $t3: u64 var $t4: u64 + var $t5: u64 0: $t1 := 1 1: $t2 := 2 2: $t3 := 3 - 3: $t4 := +($t1, $t2) - 4: $t0 := +($t4, $t3) - 5: return $t0 + 3: $t5 := move($t1) + 4: $t4 := +($t5, $t2) + 5: $t0 := +($t4, $t3) + 6: return $t0 } ============ after VariableCoalescingAnnotator: ================ @@ -41,6 +45,7 @@ fun m::test(): u64 { var $t2: u64 var $t3: u64 var $t4: u64 + var $t5: u64 # live vars: # events: b:$t1 0: $t1 := 1 @@ -51,14 +56,17 @@ fun m::test(): u64 { # events: b:$t3 2: $t3 := 3 # live vars: $t1, $t2, $t3 - # events: e:$t1, e:$t2, b:$t4 - 3: $t4 := +($t1, $t2) + # events: e:$t1, b:$t5 + 3: $t5 := move($t1) + # live vars: $t2, $t3, $t5 + # events: e:$t2, e:$t5, b:$t4 + 4: $t4 := +($t5, $t2) # live vars: $t3, $t4 # events: e:$t3, e:$t4, b:$t0 - 4: $t0 := +($t4, $t3) + 5: $t0 := +($t4, $t3) # live vars: $t0 # events: e:$t0 - 5: return $t0 + 6: return $t0 } ============ after VariableCoalescingTransformer: ================ @@ -70,12 +78,14 @@ fun m::test(): u64 { var $t2: u64 var $t3: u64 var $t4: u64 [unused] + var $t5: u64 [unused] 0: $t1 := 1 1: $t2 := 2 2: $t3 := 3 - 3: $t1 := +($t1, $t2) - 4: $t1 := +($t1, $t3) - 5: return $t1 + 3: $t1 := move($t1) + 4: $t1 := +($t1, $t2) + 5: $t1 := +($t1, $t3) + 6: return $t1 } ============ after DeadStoreElimination: ================ @@ -87,6 +97,7 @@ fun m::test(): u64 { var $t2: u64 var $t3: u64 var $t4: u64 [unused] + var $t5: u64 [unused] 0: $t1 := 1 1: $t2 := 2 2: $t3 := 3 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/reassigned_var.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/reassigned_var.exp index 1910043c0413b..c562039b5f8e4 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/reassigned_var.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/reassigned_var.exp @@ -6,12 +6,14 @@ fun m::test(): u64 { var $t1: u64 var $t2: u64 var $t3: u64 + var $t4: u64 0: $t1 := 1 1: $t2 := 2 2: $t3 := 9 3: $t1 := infer($t3) - 4: $t0 := +($t1, $t2) - 5: return $t0 + 4: $t4 := infer($t1) + 5: $t0 := +($t4, $t2) + 6: return $t0 } @@ -30,11 +32,13 @@ fun m::test(): u64 { var $t1: u64 var $t2: u64 var $t3: u64 + var $t4: u64 0: $t2 := 2 1: $t3 := 9 2: $t1 := move($t3) - 3: $t0 := +($t1, $t2) - 4: return $t0 + 3: $t4 := move($t1) + 4: $t0 := +($t4, $t2) + 5: return $t0 } ============ after VariableCoalescingAnnotator: ================ @@ -45,6 +49,7 @@ fun m::test(): u64 { var $t1: u64 var $t2: u64 var $t3: u64 + var $t4: u64 # live vars: # events: b:$t2 0: $t2 := 2 @@ -55,11 +60,14 @@ fun m::test(): u64 { # events: e:$t3, b:$t1 2: $t1 := move($t3) # live vars: $t1, $t2 - # events: e:$t1, e:$t2, b:$t0 - 3: $t0 := +($t1, $t2) + # events: e:$t1, b:$t4 + 3: $t4 := move($t1) + # live vars: $t2, $t4 + # events: e:$t2, e:$t4, b:$t0 + 4: $t0 := +($t4, $t2) # live vars: $t0 # events: e:$t0 - 4: return $t0 + 5: return $t0 } ============ after VariableCoalescingTransformer: ================ @@ -70,11 +78,13 @@ fun m::test(): u64 { var $t1: u64 [unused] var $t2: u64 var $t3: u64 + var $t4: u64 [unused] 0: $t2 := 2 1: $t3 := 9 2: $t3 := move($t3) - 3: $t2 := +($t3, $t2) - 4: return $t2 + 3: $t3 := move($t3) + 4: $t2 := +($t3, $t2) + 5: return $t2 } ============ after DeadStoreElimination: ================ @@ -85,6 +95,7 @@ fun m::test(): u64 { var $t1: u64 [unused] var $t2: u64 var $t3: u64 + var $t4: u64 [unused] 0: $t2 := 2 1: $t3 := 9 2: $t2 := +($t3, $t2) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/reassigned_var.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/reassigned_var.opt.exp index 0bff15a1e37e6..de6e03454830c 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/reassigned_var.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/reassigned_var.opt.exp @@ -6,12 +6,14 @@ fun m::test(): u64 { var $t1: u64 var $t2: u64 var $t3: u64 + var $t4: u64 0: $t1 := 1 1: $t2 := 9 2: $t1 := infer($t2) - 3: $t3 := 2 - 4: $t0 := +($t1, $t3) - 5: return $t0 + 3: $t3 := infer($t1) + 4: $t4 := 2 + 5: $t0 := +($t3, $t4) + 6: return $t0 } @@ -30,11 +32,13 @@ fun m::test(): u64 { var $t1: u64 var $t2: u64 var $t3: u64 + var $t4: u64 0: $t2 := 9 1: $t1 := move($t2) - 2: $t3 := 2 - 3: $t0 := +($t1, $t3) - 4: return $t0 + 2: $t3 := move($t1) + 3: $t4 := 2 + 4: $t0 := +($t3, $t4) + 5: return $t0 } ============ after VariableCoalescingAnnotator: ================ @@ -45,6 +49,7 @@ fun m::test(): u64 { var $t1: u64 var $t2: u64 var $t3: u64 + var $t4: u64 # live vars: # events: b:$t2 0: $t2 := 9 @@ -52,14 +57,17 @@ fun m::test(): u64 { # events: e:$t2, b:$t1 1: $t1 := move($t2) # live vars: $t1 - # events: b:$t3 - 2: $t3 := 2 - # live vars: $t1, $t3 - # events: e:$t1, e:$t3, b:$t0 - 3: $t0 := +($t1, $t3) + # events: e:$t1, b:$t3 + 2: $t3 := move($t1) + # live vars: $t3 + # events: b:$t4 + 3: $t4 := 2 + # live vars: $t3, $t4 + # events: e:$t3, e:$t4, b:$t0 + 4: $t0 := +($t3, $t4) # live vars: $t0 # events: e:$t0 - 4: return $t0 + 5: return $t0 } ============ after VariableCoalescingTransformer: ================ @@ -69,12 +77,14 @@ fun m::test(): u64 { var $t0: u64 [unused] var $t1: u64 [unused] var $t2: u64 - var $t3: u64 + var $t3: u64 [unused] + var $t4: u64 0: $t2 := 9 1: $t2 := move($t2) - 2: $t3 := 2 - 3: $t2 := +($t2, $t3) - 4: return $t2 + 2: $t2 := move($t2) + 3: $t4 := 2 + 4: $t2 := +($t2, $t4) + 5: return $t2 } ============ after DeadStoreElimination: ================ @@ -84,10 +94,11 @@ fun m::test(): u64 { var $t0: u64 [unused] var $t1: u64 [unused] var $t2: u64 - var $t3: u64 + var $t3: u64 [unused] + var $t4: u64 0: $t2 := 9 - 1: $t3 := 2 - 2: $t2 := +($t2, $t3) + 1: $t4 := 2 + 2: $t2 := +($t2, $t4) 3: return $t2 } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/self_assigns.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/self_assigns.exp index bceab3ecdb634..58ba325ed068c 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/self_assigns.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/self_assigns.exp @@ -25,25 +25,29 @@ public fun m::test3(): u64 { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 0: $t1 := 0 1: $t2 := 1 2: label L0 - 3: $t4 := 42 - 4: $t3 := <($t1, $t4) - 5: if ($t3) goto 6 else goto 12 - 6: label L2 - 7: $t2 := infer($t2) - 8: $t6 := 1 - 9: $t5 := +($t1, $t6) - 10: $t1 := infer($t5) - 11: goto 14 - 12: label L3 + 3: $t4 := infer($t1) + 4: $t5 := 42 + 5: $t3 := <($t4, $t5) + 6: if ($t3) goto 7 else goto 14 + 7: label L2 + 8: $t2 := infer($t2) + 9: $t7 := infer($t1) + 10: $t8 := 1 + 11: $t6 := +($t7, $t8) + 12: $t1 := infer($t6) 13: goto 16 - 14: label L4 - 15: goto 2 - 16: label L1 - 17: $t0 := infer($t2) - 18: return $t0 + 14: label L3 + 15: goto 18 + 16: label L4 + 17: goto 2 + 18: label L1 + 19: $t0 := infer($t2) + 20: return $t0 } @@ -55,24 +59,28 @@ public fun m::test4($t0: u64): u64 { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 0: $t2 := 0 1: label L0 - 2: $t4 := 42 - 3: $t3 := <($t2, $t4) - 4: if ($t3) goto 5 else goto 11 - 5: label L2 - 6: $t0 := infer($t0) - 7: $t6 := 1 - 8: $t5 := +($t2, $t6) - 9: $t2 := infer($t5) - 10: goto 13 - 11: label L3 + 2: $t4 := infer($t2) + 3: $t5 := 42 + 4: $t3 := <($t4, $t5) + 5: if ($t3) goto 6 else goto 13 + 6: label L2 + 7: $t0 := infer($t0) + 8: $t7 := infer($t2) + 9: $t8 := 1 + 10: $t6 := +($t7, $t8) + 11: $t2 := infer($t6) 12: goto 15 - 13: label L4 - 14: goto 1 - 15: label L1 - 16: $t1 := infer($t0) - 17: return $t1 + 13: label L3 + 14: goto 17 + 15: label L4 + 16: goto 1 + 17: label L1 + 18: $t1 := infer($t0) + 19: return $t1 } @@ -108,20 +116,24 @@ public fun m::test3(): u64 { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 0: $t1 := 0 1: $t2 := 1 2: label L0 - 3: $t4 := 42 - 4: $t3 := <($t1, $t4) - 5: if ($t3) goto 6 else goto 11 - 6: label L2 - 7: $t6 := 1 - 8: $t5 := +($t1, $t6) - 9: $t1 := move($t5) - 10: goto 2 - 11: label L3 - 12: $t0 := move($t2) - 13: return $t0 + 3: $t4 := copy($t1) + 4: $t5 := 42 + 5: $t3 := <($t4, $t5) + 6: if ($t3) goto 7 else goto 13 + 7: label L2 + 8: $t7 := move($t1) + 9: $t8 := 1 + 10: $t6 := +($t7, $t8) + 11: $t1 := move($t6) + 12: goto 2 + 13: label L3 + 14: $t0 := move($t2) + 15: return $t0 } @@ -133,19 +145,23 @@ public fun m::test4($t0: u64): u64 { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 0: $t2 := 0 1: label L0 - 2: $t4 := 42 - 3: $t3 := <($t2, $t4) - 4: if ($t3) goto 5 else goto 10 - 5: label L2 - 6: $t6 := 1 - 7: $t5 := +($t2, $t6) - 8: $t2 := move($t5) - 9: goto 1 - 10: label L3 - 11: $t1 := move($t0) - 12: return $t1 + 2: $t4 := copy($t2) + 3: $t5 := 42 + 4: $t3 := <($t4, $t5) + 5: if ($t3) goto 6 else goto 12 + 6: label L2 + 7: $t7 := move($t2) + 8: $t8 := 1 + 9: $t6 := +($t7, $t8) + 10: $t2 := move($t6) + 11: goto 1 + 12: label L3 + 13: $t1 := move($t0) + 14: return $t1 } ============ after VariableCoalescingAnnotator: ================ @@ -179,6 +195,8 @@ public fun m::test3(): u64 { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 # live vars: # events: b:$t1 0: $t1 := 0 @@ -189,35 +207,41 @@ public fun m::test3(): u64 { 2: label L0 # live vars: $t1, $t2 # events: b:$t4 - 3: $t4 := 42 + 3: $t4 := copy($t1) # live vars: $t1, $t2, $t4 - # events: e:$t4, b:$t3 - 4: $t3 := <($t1, $t4) + # events: b:$t5 + 4: $t5 := 42 + # live vars: $t1, $t2, $t4, $t5 + # events: e:$t4, e:$t5, b:$t3 + 5: $t3 := <($t4, $t5) # live vars: $t1, $t2, $t3 # events: e:$t3 - 5: if ($t3) goto 6 else goto 11 + 6: if ($t3) goto 7 else goto 13 # live vars: $t1, $t2 - 6: label L2 + 7: label L2 # live vars: $t1, $t2 - # events: b:$t6 - 7: $t6 := 1 - # live vars: $t1, $t2, $t6 - # events: e:$t6, b:$t5 - 8: $t5 := +($t1, $t6) - # live vars: $t2, $t5 - # events: e:$t5 - 9: $t1 := move($t5) + # events: b:$t7 + 8: $t7 := move($t1) + # live vars: $t2, $t7 + # events: b:$t8 + 9: $t8 := 1 + # live vars: $t2, $t7, $t8 + # events: e:$t7, e:$t8, b:$t6 + 10: $t6 := +($t7, $t8) + # live vars: $t2, $t6 + # events: e:$t6 + 11: $t1 := move($t6) # live vars: $t1, $t2 - 10: goto 2 + 12: goto 2 # live vars: $t1, $t2 # events: e:$t1 - 11: label L3 + 13: label L3 # live vars: $t2 # events: e:$t2, b:$t0 - 12: $t0 := move($t2) + 14: $t0 := move($t2) # live vars: $t0 # events: e:$t0 - 13: return $t0 + 15: return $t0 } @@ -229,6 +253,8 @@ public fun m::test4($t0: u64): u64 { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 # live vars: $t0 # events: b:$t0, b:$t2 0: $t2 := 0 @@ -236,35 +262,41 @@ public fun m::test4($t0: u64): u64 { 1: label L0 # live vars: $t0, $t2 # events: b:$t4 - 2: $t4 := 42 + 2: $t4 := copy($t2) # live vars: $t0, $t2, $t4 - # events: e:$t4, b:$t3 - 3: $t3 := <($t2, $t4) + # events: b:$t5 + 3: $t5 := 42 + # live vars: $t0, $t2, $t4, $t5 + # events: e:$t4, e:$t5, b:$t3 + 4: $t3 := <($t4, $t5) # live vars: $t0, $t2, $t3 # events: e:$t3 - 4: if ($t3) goto 5 else goto 10 + 5: if ($t3) goto 6 else goto 12 # live vars: $t0, $t2 - 5: label L2 + 6: label L2 # live vars: $t0, $t2 - # events: b:$t6 - 6: $t6 := 1 - # live vars: $t0, $t2, $t6 - # events: e:$t6, b:$t5 - 7: $t5 := +($t2, $t6) - # live vars: $t0, $t5 - # events: e:$t5 - 8: $t2 := move($t5) + # events: b:$t7 + 7: $t7 := move($t2) + # live vars: $t0, $t7 + # events: b:$t8 + 8: $t8 := 1 + # live vars: $t0, $t7, $t8 + # events: e:$t7, e:$t8, b:$t6 + 9: $t6 := +($t7, $t8) + # live vars: $t0, $t6 + # events: e:$t6 + 10: $t2 := move($t6) # live vars: $t0, $t2 - 9: goto 1 + 11: goto 1 # live vars: $t0, $t2 # events: e:$t2 - 10: label L3 + 12: label L3 # live vars: $t0 # events: e:$t0, b:$t1 - 11: $t1 := move($t0) + 13: $t1 := move($t0) # live vars: $t1 # events: e:$t1 - 12: return $t1 + 14: return $t1 } ============ after VariableCoalescingTransformer: ================ @@ -290,22 +322,26 @@ public fun m::test3(): u64 { var $t2: u64 var $t3: bool var $t4: u64 - var $t5: u64 [unused] + var $t5: u64 var $t6: u64 [unused] + var $t7: u64 [unused] + var $t8: u64 [unused] 0: $t1 := 0 1: $t2 := 1 2: label L0 - 3: $t4 := 42 - 4: $t3 := <($t1, $t4) - 5: if ($t3) goto 6 else goto 11 - 6: label L2 - 7: $t4 := 1 - 8: $t4 := +($t1, $t4) - 9: $t1 := move($t4) - 10: goto 2 - 11: label L3 - 12: $t2 := move($t2) - 13: return $t2 + 3: $t4 := copy($t1) + 4: $t5 := 42 + 5: $t3 := <($t4, $t5) + 6: if ($t3) goto 7 else goto 13 + 7: label L2 + 8: $t4 := move($t1) + 9: $t5 := 1 + 10: $t4 := +($t4, $t5) + 11: $t1 := move($t4) + 12: goto 2 + 13: label L3 + 14: $t2 := move($t2) + 15: return $t2 } @@ -315,21 +351,25 @@ public fun m::test4($t0: u64): u64 { var $t2: u64 var $t3: bool var $t4: u64 - var $t5: u64 [unused] + var $t5: u64 var $t6: u64 [unused] + var $t7: u64 [unused] + var $t8: u64 [unused] 0: $t2 := 0 1: label L0 - 2: $t4 := 42 - 3: $t3 := <($t2, $t4) - 4: if ($t3) goto 5 else goto 10 - 5: label L2 - 6: $t4 := 1 - 7: $t4 := +($t2, $t4) - 8: $t2 := move($t4) - 9: goto 1 - 10: label L3 - 11: $t0 := move($t0) - 12: return $t0 + 2: $t4 := copy($t2) + 3: $t5 := 42 + 4: $t3 := <($t4, $t5) + 5: if ($t3) goto 6 else goto 12 + 6: label L2 + 7: $t4 := move($t2) + 8: $t5 := 1 + 9: $t4 := +($t4, $t5) + 10: $t2 := move($t4) + 11: goto 1 + 12: label L3 + 13: $t0 := move($t0) + 14: return $t0 } ============ after DeadStoreElimination: ================ @@ -343,7 +383,8 @@ public fun m::test1($t0: u64) { [variant baseline] public fun m::test2($t0: u64): u64 { var $t1: u64 [unused] - 0: return $t0 + 0: $t0 := move($t0) + 1: return $t0 } @@ -354,21 +395,26 @@ public fun m::test3(): u64 { var $t2: u64 var $t3: bool var $t4: u64 - var $t5: u64 [unused] + var $t5: u64 var $t6: u64 [unused] + var $t7: u64 [unused] + var $t8: u64 [unused] 0: $t1 := 0 1: $t2 := 1 2: label L0 - 3: $t4 := 42 - 4: $t3 := <($t1, $t4) - 5: if ($t3) goto 6 else goto 11 - 6: label L2 - 7: $t4 := 1 - 8: $t4 := +($t1, $t4) - 9: $t1 := move($t4) - 10: goto 2 - 11: label L3 - 12: return $t2 + 3: $t4 := copy($t1) + 4: $t5 := 42 + 5: $t3 := <($t4, $t5) + 6: if ($t3) goto 7 else goto 13 + 7: label L2 + 8: $t4 := move($t1) + 9: $t5 := 1 + 10: $t4 := +($t4, $t5) + 11: $t1 := move($t4) + 12: goto 2 + 13: label L3 + 14: $t2 := move($t2) + 15: return $t2 } @@ -378,20 +424,25 @@ public fun m::test4($t0: u64): u64 { var $t2: u64 var $t3: bool var $t4: u64 - var $t5: u64 [unused] + var $t5: u64 var $t6: u64 [unused] + var $t7: u64 [unused] + var $t8: u64 [unused] 0: $t2 := 0 1: label L0 - 2: $t4 := 42 - 3: $t3 := <($t2, $t4) - 4: if ($t3) goto 5 else goto 10 - 5: label L2 - 6: $t4 := 1 - 7: $t4 := +($t2, $t4) - 8: $t2 := move($t4) - 9: goto 1 - 10: label L3 - 11: return $t0 + 2: $t4 := copy($t2) + 3: $t5 := 42 + 4: $t3 := <($t4, $t5) + 5: if ($t3) goto 6 else goto 12 + 6: label L2 + 7: $t4 := move($t2) + 8: $t5 := 1 + 9: $t4 := +($t4, $t5) + 10: $t2 := move($t4) + 11: goto 1 + 12: label L3 + 13: $t0 := move($t0) + 14: return $t0 } @@ -412,7 +463,6 @@ B0: public test3(): u64 /* def_idx: 2 */ { L0: loc0: u64 L1: loc1: u64 -L2: loc2: u64 B0: 0: LdU64(0) 1: StLoc[0](loc0: u64) @@ -435,7 +485,6 @@ B3: } public test4(Arg0: u64): u64 /* def_idx: 3 */ { L1: loc0: u64 -L2: loc1: u64 B0: 0: LdU64(0) 1: StLoc[1](loc0: u64) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/self_assigns.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/self_assigns.opt.exp index bceab3ecdb634..58ba325ed068c 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/self_assigns.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/self_assigns.opt.exp @@ -25,25 +25,29 @@ public fun m::test3(): u64 { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 0: $t1 := 0 1: $t2 := 1 2: label L0 - 3: $t4 := 42 - 4: $t3 := <($t1, $t4) - 5: if ($t3) goto 6 else goto 12 - 6: label L2 - 7: $t2 := infer($t2) - 8: $t6 := 1 - 9: $t5 := +($t1, $t6) - 10: $t1 := infer($t5) - 11: goto 14 - 12: label L3 + 3: $t4 := infer($t1) + 4: $t5 := 42 + 5: $t3 := <($t4, $t5) + 6: if ($t3) goto 7 else goto 14 + 7: label L2 + 8: $t2 := infer($t2) + 9: $t7 := infer($t1) + 10: $t8 := 1 + 11: $t6 := +($t7, $t8) + 12: $t1 := infer($t6) 13: goto 16 - 14: label L4 - 15: goto 2 - 16: label L1 - 17: $t0 := infer($t2) - 18: return $t0 + 14: label L3 + 15: goto 18 + 16: label L4 + 17: goto 2 + 18: label L1 + 19: $t0 := infer($t2) + 20: return $t0 } @@ -55,24 +59,28 @@ public fun m::test4($t0: u64): u64 { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 0: $t2 := 0 1: label L0 - 2: $t4 := 42 - 3: $t3 := <($t2, $t4) - 4: if ($t3) goto 5 else goto 11 - 5: label L2 - 6: $t0 := infer($t0) - 7: $t6 := 1 - 8: $t5 := +($t2, $t6) - 9: $t2 := infer($t5) - 10: goto 13 - 11: label L3 + 2: $t4 := infer($t2) + 3: $t5 := 42 + 4: $t3 := <($t4, $t5) + 5: if ($t3) goto 6 else goto 13 + 6: label L2 + 7: $t0 := infer($t0) + 8: $t7 := infer($t2) + 9: $t8 := 1 + 10: $t6 := +($t7, $t8) + 11: $t2 := infer($t6) 12: goto 15 - 13: label L4 - 14: goto 1 - 15: label L1 - 16: $t1 := infer($t0) - 17: return $t1 + 13: label L3 + 14: goto 17 + 15: label L4 + 16: goto 1 + 17: label L1 + 18: $t1 := infer($t0) + 19: return $t1 } @@ -108,20 +116,24 @@ public fun m::test3(): u64 { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 0: $t1 := 0 1: $t2 := 1 2: label L0 - 3: $t4 := 42 - 4: $t3 := <($t1, $t4) - 5: if ($t3) goto 6 else goto 11 - 6: label L2 - 7: $t6 := 1 - 8: $t5 := +($t1, $t6) - 9: $t1 := move($t5) - 10: goto 2 - 11: label L3 - 12: $t0 := move($t2) - 13: return $t0 + 3: $t4 := copy($t1) + 4: $t5 := 42 + 5: $t3 := <($t4, $t5) + 6: if ($t3) goto 7 else goto 13 + 7: label L2 + 8: $t7 := move($t1) + 9: $t8 := 1 + 10: $t6 := +($t7, $t8) + 11: $t1 := move($t6) + 12: goto 2 + 13: label L3 + 14: $t0 := move($t2) + 15: return $t0 } @@ -133,19 +145,23 @@ public fun m::test4($t0: u64): u64 { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 0: $t2 := 0 1: label L0 - 2: $t4 := 42 - 3: $t3 := <($t2, $t4) - 4: if ($t3) goto 5 else goto 10 - 5: label L2 - 6: $t6 := 1 - 7: $t5 := +($t2, $t6) - 8: $t2 := move($t5) - 9: goto 1 - 10: label L3 - 11: $t1 := move($t0) - 12: return $t1 + 2: $t4 := copy($t2) + 3: $t5 := 42 + 4: $t3 := <($t4, $t5) + 5: if ($t3) goto 6 else goto 12 + 6: label L2 + 7: $t7 := move($t2) + 8: $t8 := 1 + 9: $t6 := +($t7, $t8) + 10: $t2 := move($t6) + 11: goto 1 + 12: label L3 + 13: $t1 := move($t0) + 14: return $t1 } ============ after VariableCoalescingAnnotator: ================ @@ -179,6 +195,8 @@ public fun m::test3(): u64 { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 # live vars: # events: b:$t1 0: $t1 := 0 @@ -189,35 +207,41 @@ public fun m::test3(): u64 { 2: label L0 # live vars: $t1, $t2 # events: b:$t4 - 3: $t4 := 42 + 3: $t4 := copy($t1) # live vars: $t1, $t2, $t4 - # events: e:$t4, b:$t3 - 4: $t3 := <($t1, $t4) + # events: b:$t5 + 4: $t5 := 42 + # live vars: $t1, $t2, $t4, $t5 + # events: e:$t4, e:$t5, b:$t3 + 5: $t3 := <($t4, $t5) # live vars: $t1, $t2, $t3 # events: e:$t3 - 5: if ($t3) goto 6 else goto 11 + 6: if ($t3) goto 7 else goto 13 # live vars: $t1, $t2 - 6: label L2 + 7: label L2 # live vars: $t1, $t2 - # events: b:$t6 - 7: $t6 := 1 - # live vars: $t1, $t2, $t6 - # events: e:$t6, b:$t5 - 8: $t5 := +($t1, $t6) - # live vars: $t2, $t5 - # events: e:$t5 - 9: $t1 := move($t5) + # events: b:$t7 + 8: $t7 := move($t1) + # live vars: $t2, $t7 + # events: b:$t8 + 9: $t8 := 1 + # live vars: $t2, $t7, $t8 + # events: e:$t7, e:$t8, b:$t6 + 10: $t6 := +($t7, $t8) + # live vars: $t2, $t6 + # events: e:$t6 + 11: $t1 := move($t6) # live vars: $t1, $t2 - 10: goto 2 + 12: goto 2 # live vars: $t1, $t2 # events: e:$t1 - 11: label L3 + 13: label L3 # live vars: $t2 # events: e:$t2, b:$t0 - 12: $t0 := move($t2) + 14: $t0 := move($t2) # live vars: $t0 # events: e:$t0 - 13: return $t0 + 15: return $t0 } @@ -229,6 +253,8 @@ public fun m::test4($t0: u64): u64 { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 # live vars: $t0 # events: b:$t0, b:$t2 0: $t2 := 0 @@ -236,35 +262,41 @@ public fun m::test4($t0: u64): u64 { 1: label L0 # live vars: $t0, $t2 # events: b:$t4 - 2: $t4 := 42 + 2: $t4 := copy($t2) # live vars: $t0, $t2, $t4 - # events: e:$t4, b:$t3 - 3: $t3 := <($t2, $t4) + # events: b:$t5 + 3: $t5 := 42 + # live vars: $t0, $t2, $t4, $t5 + # events: e:$t4, e:$t5, b:$t3 + 4: $t3 := <($t4, $t5) # live vars: $t0, $t2, $t3 # events: e:$t3 - 4: if ($t3) goto 5 else goto 10 + 5: if ($t3) goto 6 else goto 12 # live vars: $t0, $t2 - 5: label L2 + 6: label L2 # live vars: $t0, $t2 - # events: b:$t6 - 6: $t6 := 1 - # live vars: $t0, $t2, $t6 - # events: e:$t6, b:$t5 - 7: $t5 := +($t2, $t6) - # live vars: $t0, $t5 - # events: e:$t5 - 8: $t2 := move($t5) + # events: b:$t7 + 7: $t7 := move($t2) + # live vars: $t0, $t7 + # events: b:$t8 + 8: $t8 := 1 + # live vars: $t0, $t7, $t8 + # events: e:$t7, e:$t8, b:$t6 + 9: $t6 := +($t7, $t8) + # live vars: $t0, $t6 + # events: e:$t6 + 10: $t2 := move($t6) # live vars: $t0, $t2 - 9: goto 1 + 11: goto 1 # live vars: $t0, $t2 # events: e:$t2 - 10: label L3 + 12: label L3 # live vars: $t0 # events: e:$t0, b:$t1 - 11: $t1 := move($t0) + 13: $t1 := move($t0) # live vars: $t1 # events: e:$t1 - 12: return $t1 + 14: return $t1 } ============ after VariableCoalescingTransformer: ================ @@ -290,22 +322,26 @@ public fun m::test3(): u64 { var $t2: u64 var $t3: bool var $t4: u64 - var $t5: u64 [unused] + var $t5: u64 var $t6: u64 [unused] + var $t7: u64 [unused] + var $t8: u64 [unused] 0: $t1 := 0 1: $t2 := 1 2: label L0 - 3: $t4 := 42 - 4: $t3 := <($t1, $t4) - 5: if ($t3) goto 6 else goto 11 - 6: label L2 - 7: $t4 := 1 - 8: $t4 := +($t1, $t4) - 9: $t1 := move($t4) - 10: goto 2 - 11: label L3 - 12: $t2 := move($t2) - 13: return $t2 + 3: $t4 := copy($t1) + 4: $t5 := 42 + 5: $t3 := <($t4, $t5) + 6: if ($t3) goto 7 else goto 13 + 7: label L2 + 8: $t4 := move($t1) + 9: $t5 := 1 + 10: $t4 := +($t4, $t5) + 11: $t1 := move($t4) + 12: goto 2 + 13: label L3 + 14: $t2 := move($t2) + 15: return $t2 } @@ -315,21 +351,25 @@ public fun m::test4($t0: u64): u64 { var $t2: u64 var $t3: bool var $t4: u64 - var $t5: u64 [unused] + var $t5: u64 var $t6: u64 [unused] + var $t7: u64 [unused] + var $t8: u64 [unused] 0: $t2 := 0 1: label L0 - 2: $t4 := 42 - 3: $t3 := <($t2, $t4) - 4: if ($t3) goto 5 else goto 10 - 5: label L2 - 6: $t4 := 1 - 7: $t4 := +($t2, $t4) - 8: $t2 := move($t4) - 9: goto 1 - 10: label L3 - 11: $t0 := move($t0) - 12: return $t0 + 2: $t4 := copy($t2) + 3: $t5 := 42 + 4: $t3 := <($t4, $t5) + 5: if ($t3) goto 6 else goto 12 + 6: label L2 + 7: $t4 := move($t2) + 8: $t5 := 1 + 9: $t4 := +($t4, $t5) + 10: $t2 := move($t4) + 11: goto 1 + 12: label L3 + 13: $t0 := move($t0) + 14: return $t0 } ============ after DeadStoreElimination: ================ @@ -343,7 +383,8 @@ public fun m::test1($t0: u64) { [variant baseline] public fun m::test2($t0: u64): u64 { var $t1: u64 [unused] - 0: return $t0 + 0: $t0 := move($t0) + 1: return $t0 } @@ -354,21 +395,26 @@ public fun m::test3(): u64 { var $t2: u64 var $t3: bool var $t4: u64 - var $t5: u64 [unused] + var $t5: u64 var $t6: u64 [unused] + var $t7: u64 [unused] + var $t8: u64 [unused] 0: $t1 := 0 1: $t2 := 1 2: label L0 - 3: $t4 := 42 - 4: $t3 := <($t1, $t4) - 5: if ($t3) goto 6 else goto 11 - 6: label L2 - 7: $t4 := 1 - 8: $t4 := +($t1, $t4) - 9: $t1 := move($t4) - 10: goto 2 - 11: label L3 - 12: return $t2 + 3: $t4 := copy($t1) + 4: $t5 := 42 + 5: $t3 := <($t4, $t5) + 6: if ($t3) goto 7 else goto 13 + 7: label L2 + 8: $t4 := move($t1) + 9: $t5 := 1 + 10: $t4 := +($t4, $t5) + 11: $t1 := move($t4) + 12: goto 2 + 13: label L3 + 14: $t2 := move($t2) + 15: return $t2 } @@ -378,20 +424,25 @@ public fun m::test4($t0: u64): u64 { var $t2: u64 var $t3: bool var $t4: u64 - var $t5: u64 [unused] + var $t5: u64 var $t6: u64 [unused] + var $t7: u64 [unused] + var $t8: u64 [unused] 0: $t2 := 0 1: label L0 - 2: $t4 := 42 - 3: $t3 := <($t2, $t4) - 4: if ($t3) goto 5 else goto 10 - 5: label L2 - 6: $t4 := 1 - 7: $t4 := +($t2, $t4) - 8: $t2 := move($t4) - 9: goto 1 - 10: label L3 - 11: return $t0 + 2: $t4 := copy($t2) + 3: $t5 := 42 + 4: $t3 := <($t4, $t5) + 5: if ($t3) goto 6 else goto 12 + 6: label L2 + 7: $t4 := move($t2) + 8: $t5 := 1 + 9: $t4 := +($t4, $t5) + 10: $t2 := move($t4) + 11: goto 1 + 12: label L3 + 13: $t0 := move($t0) + 14: return $t0 } @@ -412,7 +463,6 @@ B0: public test3(): u64 /* def_idx: 2 */ { L0: loc0: u64 L1: loc1: u64 -L2: loc2: u64 B0: 0: LdU64(0) 1: StLoc[0](loc0: u64) @@ -435,7 +485,6 @@ B3: } public test4(Arg0: u64): u64 /* def_idx: 3 */ { L1: loc0: u64 -L2: loc1: u64 B0: 0: LdU64(0) 1: StLoc[1](loc0: u64) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_1.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_1.exp index 86b5890cae6d7..5356fad8a5f8e 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_1.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_1.exp @@ -8,14 +8,18 @@ fun m::test($t0: u64): bool { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 0: $t2 := infer($t0) 1: $t3 := infer($t2) 2: $t4 := infer($t3) - 3: $t6 := 1 - 4: $t5 := +($t0, $t6) - 5: $t3 := infer($t5) - 6: $t1 := ==($t2, $t4) - 7: return $t1 + 3: $t6 := infer($t0) + 4: $t7 := 1 + 5: $t5 := +($t6, $t7) + 6: $t3 := infer($t5) + 7: $t8 := infer($t2) + 8: $t1 := ==($t8, $t4) + 9: return $t1 } @@ -36,13 +40,17 @@ fun m::test($t0: u64): bool { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 0: $t2 := copy($t0) 1: $t3 := copy($t2) 2: $t4 := move($t3) - 3: $t6 := 1 - 4: $t5 := +($t0, $t6) - 5: $t1 := ==($t2, $t4) - 6: return $t1 + 3: $t6 := move($t0) + 4: $t7 := 1 + 5: $t5 := +($t6, $t7) + 6: $t8 := move($t2) + 7: $t1 := ==($t8, $t4) + 8: return $t1 } ============ after VariableCoalescingAnnotator: ================ @@ -55,6 +63,8 @@ fun m::test($t0: u64): bool { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 # live vars: $t0 # events: b:$t0, b:$t2 0: $t2 := copy($t0) @@ -65,17 +75,23 @@ fun m::test($t0: u64): bool { # events: e:$t3, b:$t4 2: $t4 := move($t3) # live vars: $t0, $t2, $t4 - # events: b:$t6 - 3: $t6 := 1 - # live vars: $t0, $t2, $t4, $t6 - # events: e:$t0, e:$t5, e:$t6, b:$t5 - 4: $t5 := +($t0, $t6) + # events: e:$t0, b:$t6 + 3: $t6 := move($t0) + # live vars: $t2, $t4, $t6 + # events: b:$t7 + 4: $t7 := 1 + # live vars: $t2, $t4, $t6, $t7 + # events: e:$t5, e:$t6, e:$t7, b:$t5 + 5: $t5 := +($t6, $t7) # live vars: $t2, $t4 - # events: e:$t2, e:$t4, b:$t1 - 5: $t1 := ==($t2, $t4) + # events: e:$t2, b:$t8 + 6: $t8 := move($t2) + # live vars: $t4, $t8 + # events: e:$t4, e:$t8, b:$t1 + 7: $t1 := ==($t8, $t4) # live vars: $t1 # events: e:$t1 - 6: return $t1 + 8: return $t1 } ============ after VariableCoalescingTransformer: ================ @@ -87,14 +103,18 @@ fun m::test($t0: u64): bool { var $t3: u64 var $t4: u64 [unused] var $t5: u64 [unused] - var $t6: u64 + var $t6: u64 [unused] + var $t7: u64 + var $t8: u64 [unused] 0: $t2 := copy($t0) 1: $t3 := copy($t2) 2: $t3 := move($t3) - 3: $t6 := 1 - 4: $t0 := +($t0, $t6) - 5: $t1 := ==($t2, $t3) - 6: return $t1 + 3: $t0 := move($t0) + 4: $t7 := 1 + 5: $t0 := +($t0, $t7) + 6: $t2 := move($t2) + 7: $t1 := ==($t2, $t3) + 8: return $t1 } ============ after DeadStoreElimination: ================ @@ -106,13 +126,16 @@ fun m::test($t0: u64): bool { var $t3: u64 var $t4: u64 [unused] var $t5: u64 [unused] - var $t6: u64 + var $t6: u64 [unused] + var $t7: u64 + var $t8: u64 [unused] 0: $t2 := copy($t0) 1: $t3 := copy($t2) - 2: $t6 := 1 - 3: $t0 := +($t0, $t6) - 4: $t1 := ==($t2, $t3) - 5: return $t1 + 2: $t0 := move($t0) + 3: $t7 := 1 + 4: $t0 := +($t0, $t7) + 5: $t1 := ==($t2, $t3) + 6: return $t1 } @@ -124,7 +147,6 @@ module c0ffee.m { test(Arg0: u64): bool /* def_idx: 0 */ { L1: loc0: u64 L2: loc1: u64 -L3: loc2: u64 B0: 0: CopyLoc[0](Arg0: u64) 1: StLoc[1](loc0: u64) @@ -133,9 +155,9 @@ B0: 4: LdU64(1) 5: Add 6: Pop - 7: StLoc[3](loc2: u64) + 7: StLoc[2](loc1: u64) 8: MoveLoc[1](loc0: u64) - 9: MoveLoc[3](loc2: u64) + 9: MoveLoc[2](loc1: u64) 10: Eq 11: Ret } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_1.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_1.opt.exp index 86b5890cae6d7..5356fad8a5f8e 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_1.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_1.opt.exp @@ -8,14 +8,18 @@ fun m::test($t0: u64): bool { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 0: $t2 := infer($t0) 1: $t3 := infer($t2) 2: $t4 := infer($t3) - 3: $t6 := 1 - 4: $t5 := +($t0, $t6) - 5: $t3 := infer($t5) - 6: $t1 := ==($t2, $t4) - 7: return $t1 + 3: $t6 := infer($t0) + 4: $t7 := 1 + 5: $t5 := +($t6, $t7) + 6: $t3 := infer($t5) + 7: $t8 := infer($t2) + 8: $t1 := ==($t8, $t4) + 9: return $t1 } @@ -36,13 +40,17 @@ fun m::test($t0: u64): bool { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 0: $t2 := copy($t0) 1: $t3 := copy($t2) 2: $t4 := move($t3) - 3: $t6 := 1 - 4: $t5 := +($t0, $t6) - 5: $t1 := ==($t2, $t4) - 6: return $t1 + 3: $t6 := move($t0) + 4: $t7 := 1 + 5: $t5 := +($t6, $t7) + 6: $t8 := move($t2) + 7: $t1 := ==($t8, $t4) + 8: return $t1 } ============ after VariableCoalescingAnnotator: ================ @@ -55,6 +63,8 @@ fun m::test($t0: u64): bool { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 # live vars: $t0 # events: b:$t0, b:$t2 0: $t2 := copy($t0) @@ -65,17 +75,23 @@ fun m::test($t0: u64): bool { # events: e:$t3, b:$t4 2: $t4 := move($t3) # live vars: $t0, $t2, $t4 - # events: b:$t6 - 3: $t6 := 1 - # live vars: $t0, $t2, $t4, $t6 - # events: e:$t0, e:$t5, e:$t6, b:$t5 - 4: $t5 := +($t0, $t6) + # events: e:$t0, b:$t6 + 3: $t6 := move($t0) + # live vars: $t2, $t4, $t6 + # events: b:$t7 + 4: $t7 := 1 + # live vars: $t2, $t4, $t6, $t7 + # events: e:$t5, e:$t6, e:$t7, b:$t5 + 5: $t5 := +($t6, $t7) # live vars: $t2, $t4 - # events: e:$t2, e:$t4, b:$t1 - 5: $t1 := ==($t2, $t4) + # events: e:$t2, b:$t8 + 6: $t8 := move($t2) + # live vars: $t4, $t8 + # events: e:$t4, e:$t8, b:$t1 + 7: $t1 := ==($t8, $t4) # live vars: $t1 # events: e:$t1 - 6: return $t1 + 8: return $t1 } ============ after VariableCoalescingTransformer: ================ @@ -87,14 +103,18 @@ fun m::test($t0: u64): bool { var $t3: u64 var $t4: u64 [unused] var $t5: u64 [unused] - var $t6: u64 + var $t6: u64 [unused] + var $t7: u64 + var $t8: u64 [unused] 0: $t2 := copy($t0) 1: $t3 := copy($t2) 2: $t3 := move($t3) - 3: $t6 := 1 - 4: $t0 := +($t0, $t6) - 5: $t1 := ==($t2, $t3) - 6: return $t1 + 3: $t0 := move($t0) + 4: $t7 := 1 + 5: $t0 := +($t0, $t7) + 6: $t2 := move($t2) + 7: $t1 := ==($t2, $t3) + 8: return $t1 } ============ after DeadStoreElimination: ================ @@ -106,13 +126,16 @@ fun m::test($t0: u64): bool { var $t3: u64 var $t4: u64 [unused] var $t5: u64 [unused] - var $t6: u64 + var $t6: u64 [unused] + var $t7: u64 + var $t8: u64 [unused] 0: $t2 := copy($t0) 1: $t3 := copy($t2) - 2: $t6 := 1 - 3: $t0 := +($t0, $t6) - 4: $t1 := ==($t2, $t3) - 5: return $t1 + 2: $t0 := move($t0) + 3: $t7 := 1 + 4: $t0 := +($t0, $t7) + 5: $t1 := ==($t2, $t3) + 6: return $t1 } @@ -124,7 +147,6 @@ module c0ffee.m { test(Arg0: u64): bool /* def_idx: 0 */ { L1: loc0: u64 L2: loc1: u64 -L3: loc2: u64 B0: 0: CopyLoc[0](Arg0: u64) 1: StLoc[1](loc0: u64) @@ -133,9 +155,9 @@ B0: 4: LdU64(1) 5: Add 6: Pop - 7: StLoc[3](loc2: u64) + 7: StLoc[2](loc1: u64) 8: MoveLoc[1](loc0: u64) - 9: MoveLoc[3](loc2: u64) + 9: MoveLoc[2](loc1: u64) 10: Eq 11: Ret } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_2.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_2.exp index eb034ba9ffbaf..3276987a3f816 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_2.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_2.exp @@ -8,14 +8,18 @@ fun m::test($t0: u64): bool { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 0: $t2 := infer($t0) 1: $t3 := infer($t2) 2: $t4 := infer($t3) - 3: $t6 := 1 - 4: $t5 := +($t0, $t6) - 5: $t2 := infer($t5) - 6: $t1 := ==($t3, $t4) - 7: return $t1 + 3: $t6 := infer($t0) + 4: $t7 := 1 + 5: $t5 := +($t6, $t7) + 6: $t2 := infer($t5) + 7: $t8 := infer($t3) + 8: $t1 := ==($t8, $t4) + 9: return $t1 } @@ -36,13 +40,17 @@ fun m::test($t0: u64): bool { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 0: $t2 := copy($t0) 1: $t3 := move($t2) 2: $t4 := copy($t3) - 3: $t6 := 1 - 4: $t5 := +($t0, $t6) - 5: $t1 := ==($t3, $t4) - 6: return $t1 + 3: $t6 := move($t0) + 4: $t7 := 1 + 5: $t5 := +($t6, $t7) + 6: $t8 := move($t3) + 7: $t1 := ==($t8, $t4) + 8: return $t1 } ============ after VariableCoalescingAnnotator: ================ @@ -55,6 +63,8 @@ fun m::test($t0: u64): bool { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 # live vars: $t0 # events: b:$t0, b:$t2 0: $t2 := copy($t0) @@ -65,17 +75,23 @@ fun m::test($t0: u64): bool { # events: b:$t4 2: $t4 := copy($t3) # live vars: $t0, $t3, $t4 - # events: b:$t6 - 3: $t6 := 1 - # live vars: $t0, $t3, $t4, $t6 - # events: e:$t0, e:$t5, e:$t6, b:$t5 - 4: $t5 := +($t0, $t6) + # events: e:$t0, b:$t6 + 3: $t6 := move($t0) + # live vars: $t3, $t4, $t6 + # events: b:$t7 + 4: $t7 := 1 + # live vars: $t3, $t4, $t6, $t7 + # events: e:$t5, e:$t6, e:$t7, b:$t5 + 5: $t5 := +($t6, $t7) # live vars: $t3, $t4 - # events: e:$t3, e:$t4, b:$t1 - 5: $t1 := ==($t3, $t4) + # events: e:$t3, b:$t8 + 6: $t8 := move($t3) + # live vars: $t4, $t8 + # events: e:$t4, e:$t8, b:$t1 + 7: $t1 := ==($t8, $t4) # live vars: $t1 # events: e:$t1 - 6: return $t1 + 8: return $t1 } ============ after VariableCoalescingTransformer: ================ @@ -87,14 +103,18 @@ fun m::test($t0: u64): bool { var $t3: u64 [unused] var $t4: u64 var $t5: u64 [unused] - var $t6: u64 + var $t6: u64 [unused] + var $t7: u64 + var $t8: u64 [unused] 0: $t2 := copy($t0) 1: $t2 := move($t2) 2: $t4 := copy($t2) - 3: $t6 := 1 - 4: $t0 := +($t0, $t6) - 5: $t1 := ==($t2, $t4) - 6: return $t1 + 3: $t0 := move($t0) + 4: $t7 := 1 + 5: $t0 := +($t0, $t7) + 6: $t2 := move($t2) + 7: $t1 := ==($t2, $t4) + 8: return $t1 } ============ after DeadStoreElimination: ================ @@ -106,13 +126,16 @@ fun m::test($t0: u64): bool { var $t3: u64 [unused] var $t4: u64 var $t5: u64 [unused] - var $t6: u64 + var $t6: u64 [unused] + var $t7: u64 + var $t8: u64 [unused] 0: $t2 := copy($t0) 1: $t4 := copy($t2) - 2: $t6 := 1 - 3: $t0 := +($t0, $t6) - 4: $t1 := ==($t2, $t4) - 5: return $t1 + 2: $t0 := move($t0) + 3: $t7 := 1 + 4: $t0 := +($t0, $t7) + 5: $t1 := ==($t2, $t4) + 6: return $t1 } @@ -124,7 +147,6 @@ module c0ffee.m { test(Arg0: u64): bool /* def_idx: 0 */ { L1: loc0: u64 L2: loc1: u64 -L3: loc2: u64 B0: 0: CopyLoc[0](Arg0: u64) 1: StLoc[1](loc0: u64) @@ -133,9 +155,9 @@ B0: 4: LdU64(1) 5: Add 6: Pop - 7: StLoc[3](loc2: u64) + 7: StLoc[2](loc1: u64) 8: MoveLoc[1](loc0: u64) - 9: MoveLoc[3](loc2: u64) + 9: MoveLoc[2](loc1: u64) 10: Eq 11: Ret } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_2.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_2.opt.exp index eb034ba9ffbaf..3276987a3f816 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_2.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_2.opt.exp @@ -8,14 +8,18 @@ fun m::test($t0: u64): bool { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 0: $t2 := infer($t0) 1: $t3 := infer($t2) 2: $t4 := infer($t3) - 3: $t6 := 1 - 4: $t5 := +($t0, $t6) - 5: $t2 := infer($t5) - 6: $t1 := ==($t3, $t4) - 7: return $t1 + 3: $t6 := infer($t0) + 4: $t7 := 1 + 5: $t5 := +($t6, $t7) + 6: $t2 := infer($t5) + 7: $t8 := infer($t3) + 8: $t1 := ==($t8, $t4) + 9: return $t1 } @@ -36,13 +40,17 @@ fun m::test($t0: u64): bool { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 0: $t2 := copy($t0) 1: $t3 := move($t2) 2: $t4 := copy($t3) - 3: $t6 := 1 - 4: $t5 := +($t0, $t6) - 5: $t1 := ==($t3, $t4) - 6: return $t1 + 3: $t6 := move($t0) + 4: $t7 := 1 + 5: $t5 := +($t6, $t7) + 6: $t8 := move($t3) + 7: $t1 := ==($t8, $t4) + 8: return $t1 } ============ after VariableCoalescingAnnotator: ================ @@ -55,6 +63,8 @@ fun m::test($t0: u64): bool { var $t4: u64 var $t5: u64 var $t6: u64 + var $t7: u64 + var $t8: u64 # live vars: $t0 # events: b:$t0, b:$t2 0: $t2 := copy($t0) @@ -65,17 +75,23 @@ fun m::test($t0: u64): bool { # events: b:$t4 2: $t4 := copy($t3) # live vars: $t0, $t3, $t4 - # events: b:$t6 - 3: $t6 := 1 - # live vars: $t0, $t3, $t4, $t6 - # events: e:$t0, e:$t5, e:$t6, b:$t5 - 4: $t5 := +($t0, $t6) + # events: e:$t0, b:$t6 + 3: $t6 := move($t0) + # live vars: $t3, $t4, $t6 + # events: b:$t7 + 4: $t7 := 1 + # live vars: $t3, $t4, $t6, $t7 + # events: e:$t5, e:$t6, e:$t7, b:$t5 + 5: $t5 := +($t6, $t7) # live vars: $t3, $t4 - # events: e:$t3, e:$t4, b:$t1 - 5: $t1 := ==($t3, $t4) + # events: e:$t3, b:$t8 + 6: $t8 := move($t3) + # live vars: $t4, $t8 + # events: e:$t4, e:$t8, b:$t1 + 7: $t1 := ==($t8, $t4) # live vars: $t1 # events: e:$t1 - 6: return $t1 + 8: return $t1 } ============ after VariableCoalescingTransformer: ================ @@ -87,14 +103,18 @@ fun m::test($t0: u64): bool { var $t3: u64 [unused] var $t4: u64 var $t5: u64 [unused] - var $t6: u64 + var $t6: u64 [unused] + var $t7: u64 + var $t8: u64 [unused] 0: $t2 := copy($t0) 1: $t2 := move($t2) 2: $t4 := copy($t2) - 3: $t6 := 1 - 4: $t0 := +($t0, $t6) - 5: $t1 := ==($t2, $t4) - 6: return $t1 + 3: $t0 := move($t0) + 4: $t7 := 1 + 5: $t0 := +($t0, $t7) + 6: $t2 := move($t2) + 7: $t1 := ==($t2, $t4) + 8: return $t1 } ============ after DeadStoreElimination: ================ @@ -106,13 +126,16 @@ fun m::test($t0: u64): bool { var $t3: u64 [unused] var $t4: u64 var $t5: u64 [unused] - var $t6: u64 + var $t6: u64 [unused] + var $t7: u64 + var $t8: u64 [unused] 0: $t2 := copy($t0) 1: $t4 := copy($t2) - 2: $t6 := 1 - 3: $t0 := +($t0, $t6) - 4: $t1 := ==($t2, $t4) - 5: return $t1 + 2: $t0 := move($t0) + 3: $t7 := 1 + 4: $t0 := +($t0, $t7) + 5: $t1 := ==($t2, $t4) + 6: return $t1 } @@ -124,7 +147,6 @@ module c0ffee.m { test(Arg0: u64): bool /* def_idx: 0 */ { L1: loc0: u64 L2: loc1: u64 -L3: loc2: u64 B0: 0: CopyLoc[0](Arg0: u64) 1: StLoc[1](loc0: u64) @@ -133,9 +155,9 @@ B0: 4: LdU64(1) 5: Add 6: Pop - 7: StLoc[3](loc2: u64) + 7: StLoc[2](loc1: u64) 8: MoveLoc[1](loc0: u64) - 9: MoveLoc[3](loc2: u64) + 9: MoveLoc[2](loc1: u64) 10: Eq 11: Ret } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/sequential_assign_struct.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/sequential_assign_struct.exp index d07e8b35bdcd3..14b304721a80a 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/sequential_assign_struct.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/sequential_assign_struct.exp @@ -98,7 +98,8 @@ fun m::sequential($t0: 0xc0ffee::m::Foo): 0xc0ffee::m::Foo { var $t4: 0xc0ffee::m::Foo [unused] var $t5: 0xc0ffee::m::Foo [unused] var $t6: 0xc0ffee::m::Foo [unused] - 0: return $t0 + 0: $t0 := move($t0) + 1: return $t0 } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/sequential_assign_struct.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/sequential_assign_struct.opt.exp index d07e8b35bdcd3..14b304721a80a 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/sequential_assign_struct.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/sequential_assign_struct.opt.exp @@ -98,7 +98,8 @@ fun m::sequential($t0: 0xc0ffee::m::Foo): 0xc0ffee::m::Foo { var $t4: 0xc0ffee::m::Foo [unused] var $t5: 0xc0ffee::m::Foo [unused] var $t6: 0xc0ffee::m::Foo [unused] - 0: return $t0 + 0: $t0 := move($t0) + 1: return $t0 } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/simple_sequential_assign.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/simple_sequential_assign.exp index f8f714d03bae3..212171e0178cf 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/simple_sequential_assign.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/simple_sequential_assign.exp @@ -98,7 +98,8 @@ fun m::sequential($t0: u64): u64 { var $t4: u64 [unused] var $t5: u64 [unused] var $t6: u64 [unused] - 0: return $t0 + 0: $t0 := move($t0) + 1: return $t0 } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/simple_sequential_assign.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/simple_sequential_assign.opt.exp index f8f714d03bae3..212171e0178cf 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/simple_sequential_assign.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/simple_sequential_assign.opt.exp @@ -98,7 +98,8 @@ fun m::sequential($t0: u64): u64 { var $t4: u64 [unused] var $t5: u64 [unused] var $t6: u64 [unused] - 0: return $t0 + 0: $t0 := move($t0) + 1: return $t0 } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/straight_line_kills.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/straight_line_kills.exp index 822f245566624..ebc4a657f613c 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/straight_line_kills.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/straight_line_kills.exp @@ -7,13 +7,17 @@ fun m::copy_kill($t0: u64): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 + var $t7: u64 0: $t2 := infer($t0) 1: $t3 := infer($t2) - 2: $t5 := 1 - 3: $t4 := +($t0, $t5) - 4: $t0 := infer($t4) - 5: $t1 := +($t3, $t2) - 6: return $t1 + 2: $t5 := infer($t0) + 3: $t6 := 1 + 4: $t4 := +($t5, $t6) + 5: $t0 := infer($t4) + 6: $t7 := infer($t3) + 7: $t1 := +($t7, $t2) + 8: return $t1 } @@ -33,12 +37,16 @@ fun m::copy_kill($t0: u64): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 + var $t7: u64 0: $t2 := copy($t0) 1: $t3 := copy($t2) - 2: $t5 := 1 - 3: $t4 := +($t0, $t5) - 4: $t1 := +($t3, $t2) - 5: return $t1 + 2: $t5 := move($t0) + 3: $t6 := 1 + 4: $t4 := +($t5, $t6) + 5: $t7 := move($t3) + 6: $t1 := +($t7, $t2) + 7: return $t1 } ============ after VariableCoalescingAnnotator: ================ @@ -50,6 +58,8 @@ fun m::copy_kill($t0: u64): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 + var $t7: u64 # live vars: $t0 # events: b:$t0, b:$t2 0: $t2 := copy($t0) @@ -57,17 +67,23 @@ fun m::copy_kill($t0: u64): u64 { # events: b:$t3 1: $t3 := copy($t2) # live vars: $t0, $t2, $t3 - # events: b:$t5 - 2: $t5 := 1 - # live vars: $t0, $t2, $t3, $t5 - # events: e:$t0, e:$t4, e:$t5, b:$t4 - 3: $t4 := +($t0, $t5) + # events: e:$t0, b:$t5 + 2: $t5 := move($t0) + # live vars: $t2, $t3, $t5 + # events: b:$t6 + 3: $t6 := 1 + # live vars: $t2, $t3, $t5, $t6 + # events: e:$t4, e:$t5, e:$t6, b:$t4 + 4: $t4 := +($t5, $t6) # live vars: $t2, $t3 - # events: e:$t2, e:$t3, b:$t1 - 4: $t1 := +($t3, $t2) + # events: e:$t3, b:$t7 + 5: $t7 := move($t3) + # live vars: $t2, $t7 + # events: e:$t2, e:$t7, b:$t1 + 6: $t1 := +($t7, $t2) # live vars: $t1 # events: e:$t1 - 5: return $t1 + 7: return $t1 } ============ after VariableCoalescingTransformer: ================ @@ -78,13 +94,17 @@ fun m::copy_kill($t0: u64): u64 { var $t2: u64 var $t3: u64 var $t4: u64 [unused] - var $t5: u64 + var $t5: u64 [unused] + var $t6: u64 + var $t7: u64 [unused] 0: $t2 := copy($t0) 1: $t3 := copy($t2) - 2: $t5 := 1 - 3: $t0 := +($t0, $t5) - 4: $t2 := +($t3, $t2) - 5: return $t2 + 2: $t0 := move($t0) + 3: $t6 := 1 + 4: $t0 := +($t0, $t6) + 5: $t3 := move($t3) + 6: $t2 := +($t3, $t2) + 7: return $t2 } ============ after DeadStoreElimination: ================ @@ -95,13 +115,16 @@ fun m::copy_kill($t0: u64): u64 { var $t2: u64 var $t3: u64 var $t4: u64 [unused] - var $t5: u64 + var $t5: u64 [unused] + var $t6: u64 + var $t7: u64 [unused] 0: $t2 := copy($t0) 1: $t3 := copy($t2) - 2: $t5 := 1 - 3: $t0 := +($t0, $t5) - 4: $t2 := +($t3, $t2) - 5: return $t2 + 2: $t0 := move($t0) + 3: $t6 := 1 + 4: $t0 := +($t0, $t6) + 5: $t2 := +($t3, $t2) + 6: return $t2 } @@ -112,7 +135,6 @@ module c0ffee.m { copy_kill(Arg0: u64): u64 /* def_idx: 0 */ { L1: loc0: u64 -L2: loc1: u64 B0: 0: CopyLoc[0](Arg0: u64) 1: StLoc[1](loc0: u64) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/straight_line_kills.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/straight_line_kills.opt.exp index 822f245566624..ebc4a657f613c 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/straight_line_kills.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/straight_line_kills.opt.exp @@ -7,13 +7,17 @@ fun m::copy_kill($t0: u64): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 + var $t7: u64 0: $t2 := infer($t0) 1: $t3 := infer($t2) - 2: $t5 := 1 - 3: $t4 := +($t0, $t5) - 4: $t0 := infer($t4) - 5: $t1 := +($t3, $t2) - 6: return $t1 + 2: $t5 := infer($t0) + 3: $t6 := 1 + 4: $t4 := +($t5, $t6) + 5: $t0 := infer($t4) + 6: $t7 := infer($t3) + 7: $t1 := +($t7, $t2) + 8: return $t1 } @@ -33,12 +37,16 @@ fun m::copy_kill($t0: u64): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 + var $t7: u64 0: $t2 := copy($t0) 1: $t3 := copy($t2) - 2: $t5 := 1 - 3: $t4 := +($t0, $t5) - 4: $t1 := +($t3, $t2) - 5: return $t1 + 2: $t5 := move($t0) + 3: $t6 := 1 + 4: $t4 := +($t5, $t6) + 5: $t7 := move($t3) + 6: $t1 := +($t7, $t2) + 7: return $t1 } ============ after VariableCoalescingAnnotator: ================ @@ -50,6 +58,8 @@ fun m::copy_kill($t0: u64): u64 { var $t3: u64 var $t4: u64 var $t5: u64 + var $t6: u64 + var $t7: u64 # live vars: $t0 # events: b:$t0, b:$t2 0: $t2 := copy($t0) @@ -57,17 +67,23 @@ fun m::copy_kill($t0: u64): u64 { # events: b:$t3 1: $t3 := copy($t2) # live vars: $t0, $t2, $t3 - # events: b:$t5 - 2: $t5 := 1 - # live vars: $t0, $t2, $t3, $t5 - # events: e:$t0, e:$t4, e:$t5, b:$t4 - 3: $t4 := +($t0, $t5) + # events: e:$t0, b:$t5 + 2: $t5 := move($t0) + # live vars: $t2, $t3, $t5 + # events: b:$t6 + 3: $t6 := 1 + # live vars: $t2, $t3, $t5, $t6 + # events: e:$t4, e:$t5, e:$t6, b:$t4 + 4: $t4 := +($t5, $t6) # live vars: $t2, $t3 - # events: e:$t2, e:$t3, b:$t1 - 4: $t1 := +($t3, $t2) + # events: e:$t3, b:$t7 + 5: $t7 := move($t3) + # live vars: $t2, $t7 + # events: e:$t2, e:$t7, b:$t1 + 6: $t1 := +($t7, $t2) # live vars: $t1 # events: e:$t1 - 5: return $t1 + 7: return $t1 } ============ after VariableCoalescingTransformer: ================ @@ -78,13 +94,17 @@ fun m::copy_kill($t0: u64): u64 { var $t2: u64 var $t3: u64 var $t4: u64 [unused] - var $t5: u64 + var $t5: u64 [unused] + var $t6: u64 + var $t7: u64 [unused] 0: $t2 := copy($t0) 1: $t3 := copy($t2) - 2: $t5 := 1 - 3: $t0 := +($t0, $t5) - 4: $t2 := +($t3, $t2) - 5: return $t2 + 2: $t0 := move($t0) + 3: $t6 := 1 + 4: $t0 := +($t0, $t6) + 5: $t3 := move($t3) + 6: $t2 := +($t3, $t2) + 7: return $t2 } ============ after DeadStoreElimination: ================ @@ -95,13 +115,16 @@ fun m::copy_kill($t0: u64): u64 { var $t2: u64 var $t3: u64 var $t4: u64 [unused] - var $t5: u64 + var $t5: u64 [unused] + var $t6: u64 + var $t7: u64 [unused] 0: $t2 := copy($t0) 1: $t3 := copy($t2) - 2: $t5 := 1 - 3: $t0 := +($t0, $t5) - 4: $t2 := +($t3, $t2) - 5: return $t2 + 2: $t0 := move($t0) + 3: $t6 := 1 + 4: $t0 := +($t0, $t6) + 5: $t2 := +($t3, $t2) + 6: return $t2 } @@ -112,7 +135,6 @@ module c0ffee.m { copy_kill(Arg0: u64): u64 /* def_idx: 0 */ { L1: loc0: u64 -L2: loc1: u64 B0: 0: CopyLoc[0](Arg0: u64) 1: StLoc[1](loc0: u64) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/swap.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/swap.exp index 08533b6b6dd91..bcdd09b79ebc9 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/swap.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/swap.exp @@ -92,12 +92,10 @@ public test(Arg0: u64, Arg1: u64): u64 * u64 /* def_idx: 0 */ { L2: loc0: u64 B0: 0: MoveLoc[0](Arg0: u64) - 1: MoveLoc[1](Arg1: u64) - 2: StLoc[0](Arg0: u64) - 3: StLoc[1](Arg1: u64) - 4: MoveLoc[0](Arg0: u64) - 5: MoveLoc[1](Arg1: u64) - 6: Ret + 1: StLoc[2](loc0: u64) + 2: MoveLoc[1](Arg1: u64) + 3: MoveLoc[2](loc0: u64) + 4: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/swap.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/swap.opt.exp index 08533b6b6dd91..bcdd09b79ebc9 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/swap.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/swap.opt.exp @@ -92,12 +92,10 @@ public test(Arg0: u64, Arg1: u64): u64 * u64 /* def_idx: 0 */ { L2: loc0: u64 B0: 0: MoveLoc[0](Arg0: u64) - 1: MoveLoc[1](Arg1: u64) - 2: StLoc[0](Arg0: u64) - 3: StLoc[1](Arg1: u64) - 4: MoveLoc[0](Arg0: u64) - 5: MoveLoc[1](Arg1: u64) - 6: Ret + 1: StLoc[2](loc0: u64) + 2: MoveLoc[1](Arg1: u64) + 3: MoveLoc[2](loc0: u64) + 4: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/swap_in_a_loop.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/swap_in_a_loop.exp index 4b4283ceb66ac..b25d39a45b007 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/swap_in_a_loop.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/swap_in_a_loop.exp @@ -10,27 +10,31 @@ public fun m::test($t0: u64, $t1: u64): (u64, u64) { var $t7: u64 var $t8: u64 var $t9: u64 + var $t10: u64 + var $t11: u64 0: $t4 := infer($t0) 1: label L0 - 2: $t7 := 0 - 3: $t6 := >($t4, $t7) - 4: if ($t6) goto 5 else goto 13 - 5: label L2 - 6: $t5 := infer($t0) - 7: $t0 := infer($t1) - 8: $t1 := infer($t5) - 9: $t9 := 1 - 10: $t8 := -($t4, $t9) - 11: $t4 := infer($t8) - 12: goto 15 - 13: label L3 + 2: $t7 := infer($t4) + 3: $t8 := 0 + 4: $t6 := >($t7, $t8) + 5: if ($t6) goto 6 else goto 15 + 6: label L2 + 7: $t5 := infer($t0) + 8: $t0 := infer($t1) + 9: $t1 := infer($t5) + 10: $t10 := infer($t4) + 11: $t11 := 1 + 12: $t9 := -($t10, $t11) + 13: $t4 := infer($t9) 14: goto 17 - 15: label L4 - 16: goto 1 - 17: label L1 - 18: $t2 := infer($t0) - 19: $t3 := infer($t1) - 20: return ($t2, $t3) + 15: label L3 + 16: goto 19 + 17: label L4 + 18: goto 1 + 19: label L1 + 20: $t2 := infer($t0) + 21: $t3 := infer($t1) + 22: return ($t2, $t3) } ============ after DeadStoreElimination: ================ @@ -45,23 +49,27 @@ public fun m::test($t0: u64, $t1: u64): (u64, u64) { var $t7: u64 var $t8: u64 var $t9: u64 + var $t10: u64 + var $t11: u64 0: $t4 := copy($t0) 1: label L0 - 2: $t7 := 0 - 3: $t6 := >($t4, $t7) - 4: if ($t6) goto 5 else goto 13 - 5: label L2 - 6: $t5 := move($t0) - 7: $t0 := move($t1) - 8: $t1 := move($t5) - 9: $t9 := 1 - 10: $t8 := -($t4, $t9) - 11: $t4 := move($t8) - 12: goto 1 - 13: label L3 - 14: $t2 := move($t0) - 15: $t3 := move($t1) - 16: return ($t2, $t3) + 2: $t7 := copy($t4) + 3: $t8 := 0 + 4: $t6 := >($t7, $t8) + 5: if ($t6) goto 6 else goto 15 + 6: label L2 + 7: $t5 := move($t0) + 8: $t0 := move($t1) + 9: $t1 := move($t5) + 10: $t10 := move($t4) + 11: $t11 := 1 + 12: $t9 := -($t10, $t11) + 13: $t4 := move($t9) + 14: goto 1 + 15: label L3 + 16: $t2 := move($t0) + 17: $t3 := move($t1) + 18: return ($t2, $t3) } ============ after VariableCoalescingAnnotator: ================ @@ -76,6 +84,8 @@ public fun m::test($t0: u64, $t1: u64): (u64, u64) { var $t7: u64 var $t8: u64 var $t9: u64 + var $t10: u64 + var $t11: u64 # live vars: $t0, $t1 # events: b:$t0, b:$t1, b:$t4 0: $t4 := copy($t0) @@ -83,46 +93,52 @@ public fun m::test($t0: u64, $t1: u64): (u64, u64) { 1: label L0 # live vars: $t0, $t1, $t4 # events: b:$t7 - 2: $t7 := 0 + 2: $t7 := copy($t4) # live vars: $t0, $t1, $t4, $t7 - # events: e:$t7, b:$t6 - 3: $t6 := >($t4, $t7) + # events: b:$t8 + 3: $t8 := 0 + # live vars: $t0, $t1, $t4, $t7, $t8 + # events: e:$t7, e:$t8, b:$t6 + 4: $t6 := >($t7, $t8) # live vars: $t0, $t1, $t4, $t6 # events: e:$t6 - 4: if ($t6) goto 5 else goto 13 + 5: if ($t6) goto 6 else goto 15 # live vars: $t0, $t1, $t4 - 5: label L2 + 6: label L2 # live vars: $t0, $t1, $t4 # events: b:$t5 - 6: $t5 := move($t0) + 7: $t5 := move($t0) # live vars: $t1, $t4, $t5 - 7: $t0 := move($t1) + 8: $t0 := move($t1) # live vars: $t0, $t4, $t5 # events: e:$t5 - 8: $t1 := move($t5) + 9: $t1 := move($t5) # live vars: $t0, $t1, $t4 - # events: b:$t9 - 9: $t9 := 1 - # live vars: $t0, $t1, $t4, $t9 - # events: e:$t9, b:$t8 - 10: $t8 := -($t4, $t9) - # live vars: $t0, $t1, $t8 - # events: e:$t8 - 11: $t4 := move($t8) + # events: b:$t10 + 10: $t10 := move($t4) + # live vars: $t0, $t1, $t10 + # events: b:$t11 + 11: $t11 := 1 + # live vars: $t0, $t1, $t10, $t11 + # events: e:$t10, e:$t11, b:$t9 + 12: $t9 := -($t10, $t11) + # live vars: $t0, $t1, $t9 + # events: e:$t9 + 13: $t4 := move($t9) # live vars: $t0, $t1, $t4 - 12: goto 1 + 14: goto 1 # live vars: $t0, $t1, $t4 # events: e:$t4 - 13: label L3 + 15: label L3 # live vars: $t0, $t1 # events: e:$t0, b:$t2 - 14: $t2 := move($t0) + 16: $t2 := move($t0) # live vars: $t1, $t2 # events: e:$t1, b:$t3 - 15: $t3 := move($t1) + 17: $t3 := move($t1) # live vars: $t2, $t3 # events: e:$t2, e:$t3 - 16: return ($t2, $t3) + 18: return ($t2, $t3) } ============ after VariableCoalescingTransformer: ================ @@ -135,25 +151,29 @@ public fun m::test($t0: u64, $t1: u64): (u64, u64) { var $t5: u64 [unused] var $t6: bool var $t7: u64 - var $t8: u64 [unused] + var $t8: u64 var $t9: u64 [unused] + var $t10: u64 [unused] + var $t11: u64 [unused] 0: $t4 := copy($t0) 1: label L0 - 2: $t7 := 0 - 3: $t6 := >($t4, $t7) - 4: if ($t6) goto 5 else goto 13 - 5: label L2 - 6: $t7 := move($t0) - 7: $t0 := move($t1) - 8: $t1 := move($t7) - 9: $t7 := 1 - 10: $t7 := -($t4, $t7) - 11: $t4 := move($t7) - 12: goto 1 - 13: label L3 - 14: $t0 := move($t0) - 15: $t1 := move($t1) - 16: return ($t0, $t1) + 2: $t7 := copy($t4) + 3: $t8 := 0 + 4: $t6 := >($t7, $t8) + 5: if ($t6) goto 6 else goto 15 + 6: label L2 + 7: $t7 := move($t0) + 8: $t0 := move($t1) + 9: $t1 := move($t7) + 10: $t7 := move($t4) + 11: $t8 := 1 + 12: $t7 := -($t7, $t8) + 13: $t4 := move($t7) + 14: goto 1 + 15: label L3 + 16: $t0 := move($t0) + 17: $t1 := move($t1) + 18: return ($t0, $t1) } ============ after DeadStoreElimination: ================ @@ -166,23 +186,29 @@ public fun m::test($t0: u64, $t1: u64): (u64, u64) { var $t5: u64 [unused] var $t6: bool var $t7: u64 - var $t8: u64 [unused] + var $t8: u64 var $t9: u64 [unused] + var $t10: u64 [unused] + var $t11: u64 [unused] 0: $t4 := copy($t0) 1: label L0 - 2: $t7 := 0 - 3: $t6 := >($t4, $t7) - 4: if ($t6) goto 5 else goto 13 - 5: label L2 - 6: $t7 := move($t0) - 7: $t0 := move($t1) - 8: $t1 := move($t7) - 9: $t7 := 1 - 10: $t7 := -($t4, $t7) - 11: $t4 := move($t7) - 12: goto 1 - 13: label L3 - 14: return ($t0, $t1) + 2: $t7 := copy($t4) + 3: $t8 := 0 + 4: $t6 := >($t7, $t8) + 5: if ($t6) goto 6 else goto 15 + 6: label L2 + 7: $t7 := move($t0) + 8: $t0 := move($t1) + 9: $t1 := move($t7) + 10: $t7 := move($t4) + 11: $t8 := 1 + 12: $t7 := -($t7, $t8) + 13: $t4 := move($t7) + 14: goto 1 + 15: label L3 + 16: $t0 := move($t0) + 17: $t1 := move($t1) + 18: return ($t0, $t1) } @@ -193,7 +219,6 @@ module c0ffee.m { public test(Arg0: u64, Arg1: u64): u64 * u64 /* def_idx: 0 */ { L2: loc0: u64 -L3: loc1: u64 B0: 0: CopyLoc[0](Arg0: u64) 1: StLoc[2](loc0: u64) @@ -206,11 +231,11 @@ B2: 6: MoveLoc[0](Arg0: u64) 7: MoveLoc[1](Arg1: u64) 8: StLoc[0](Arg0: u64) - 9: MoveLoc[2](loc0: u64) - 10: LdU64(1) - 11: Sub - 12: StLoc[2](loc0: u64) - 13: StLoc[1](Arg1: u64) + 9: StLoc[1](Arg1: u64) + 10: MoveLoc[2](loc0: u64) + 11: LdU64(1) + 12: Sub + 13: StLoc[2](loc0: u64) 14: Branch(2) B3: 15: MoveLoc[0](Arg0: u64) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/swap_in_a_loop.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/swap_in_a_loop.opt.exp index 4b4283ceb66ac..b25d39a45b007 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/swap_in_a_loop.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/swap_in_a_loop.opt.exp @@ -10,27 +10,31 @@ public fun m::test($t0: u64, $t1: u64): (u64, u64) { var $t7: u64 var $t8: u64 var $t9: u64 + var $t10: u64 + var $t11: u64 0: $t4 := infer($t0) 1: label L0 - 2: $t7 := 0 - 3: $t6 := >($t4, $t7) - 4: if ($t6) goto 5 else goto 13 - 5: label L2 - 6: $t5 := infer($t0) - 7: $t0 := infer($t1) - 8: $t1 := infer($t5) - 9: $t9 := 1 - 10: $t8 := -($t4, $t9) - 11: $t4 := infer($t8) - 12: goto 15 - 13: label L3 + 2: $t7 := infer($t4) + 3: $t8 := 0 + 4: $t6 := >($t7, $t8) + 5: if ($t6) goto 6 else goto 15 + 6: label L2 + 7: $t5 := infer($t0) + 8: $t0 := infer($t1) + 9: $t1 := infer($t5) + 10: $t10 := infer($t4) + 11: $t11 := 1 + 12: $t9 := -($t10, $t11) + 13: $t4 := infer($t9) 14: goto 17 - 15: label L4 - 16: goto 1 - 17: label L1 - 18: $t2 := infer($t0) - 19: $t3 := infer($t1) - 20: return ($t2, $t3) + 15: label L3 + 16: goto 19 + 17: label L4 + 18: goto 1 + 19: label L1 + 20: $t2 := infer($t0) + 21: $t3 := infer($t1) + 22: return ($t2, $t3) } ============ after DeadStoreElimination: ================ @@ -45,23 +49,27 @@ public fun m::test($t0: u64, $t1: u64): (u64, u64) { var $t7: u64 var $t8: u64 var $t9: u64 + var $t10: u64 + var $t11: u64 0: $t4 := copy($t0) 1: label L0 - 2: $t7 := 0 - 3: $t6 := >($t4, $t7) - 4: if ($t6) goto 5 else goto 13 - 5: label L2 - 6: $t5 := move($t0) - 7: $t0 := move($t1) - 8: $t1 := move($t5) - 9: $t9 := 1 - 10: $t8 := -($t4, $t9) - 11: $t4 := move($t8) - 12: goto 1 - 13: label L3 - 14: $t2 := move($t0) - 15: $t3 := move($t1) - 16: return ($t2, $t3) + 2: $t7 := copy($t4) + 3: $t8 := 0 + 4: $t6 := >($t7, $t8) + 5: if ($t6) goto 6 else goto 15 + 6: label L2 + 7: $t5 := move($t0) + 8: $t0 := move($t1) + 9: $t1 := move($t5) + 10: $t10 := move($t4) + 11: $t11 := 1 + 12: $t9 := -($t10, $t11) + 13: $t4 := move($t9) + 14: goto 1 + 15: label L3 + 16: $t2 := move($t0) + 17: $t3 := move($t1) + 18: return ($t2, $t3) } ============ after VariableCoalescingAnnotator: ================ @@ -76,6 +84,8 @@ public fun m::test($t0: u64, $t1: u64): (u64, u64) { var $t7: u64 var $t8: u64 var $t9: u64 + var $t10: u64 + var $t11: u64 # live vars: $t0, $t1 # events: b:$t0, b:$t1, b:$t4 0: $t4 := copy($t0) @@ -83,46 +93,52 @@ public fun m::test($t0: u64, $t1: u64): (u64, u64) { 1: label L0 # live vars: $t0, $t1, $t4 # events: b:$t7 - 2: $t7 := 0 + 2: $t7 := copy($t4) # live vars: $t0, $t1, $t4, $t7 - # events: e:$t7, b:$t6 - 3: $t6 := >($t4, $t7) + # events: b:$t8 + 3: $t8 := 0 + # live vars: $t0, $t1, $t4, $t7, $t8 + # events: e:$t7, e:$t8, b:$t6 + 4: $t6 := >($t7, $t8) # live vars: $t0, $t1, $t4, $t6 # events: e:$t6 - 4: if ($t6) goto 5 else goto 13 + 5: if ($t6) goto 6 else goto 15 # live vars: $t0, $t1, $t4 - 5: label L2 + 6: label L2 # live vars: $t0, $t1, $t4 # events: b:$t5 - 6: $t5 := move($t0) + 7: $t5 := move($t0) # live vars: $t1, $t4, $t5 - 7: $t0 := move($t1) + 8: $t0 := move($t1) # live vars: $t0, $t4, $t5 # events: e:$t5 - 8: $t1 := move($t5) + 9: $t1 := move($t5) # live vars: $t0, $t1, $t4 - # events: b:$t9 - 9: $t9 := 1 - # live vars: $t0, $t1, $t4, $t9 - # events: e:$t9, b:$t8 - 10: $t8 := -($t4, $t9) - # live vars: $t0, $t1, $t8 - # events: e:$t8 - 11: $t4 := move($t8) + # events: b:$t10 + 10: $t10 := move($t4) + # live vars: $t0, $t1, $t10 + # events: b:$t11 + 11: $t11 := 1 + # live vars: $t0, $t1, $t10, $t11 + # events: e:$t10, e:$t11, b:$t9 + 12: $t9 := -($t10, $t11) + # live vars: $t0, $t1, $t9 + # events: e:$t9 + 13: $t4 := move($t9) # live vars: $t0, $t1, $t4 - 12: goto 1 + 14: goto 1 # live vars: $t0, $t1, $t4 # events: e:$t4 - 13: label L3 + 15: label L3 # live vars: $t0, $t1 # events: e:$t0, b:$t2 - 14: $t2 := move($t0) + 16: $t2 := move($t0) # live vars: $t1, $t2 # events: e:$t1, b:$t3 - 15: $t3 := move($t1) + 17: $t3 := move($t1) # live vars: $t2, $t3 # events: e:$t2, e:$t3 - 16: return ($t2, $t3) + 18: return ($t2, $t3) } ============ after VariableCoalescingTransformer: ================ @@ -135,25 +151,29 @@ public fun m::test($t0: u64, $t1: u64): (u64, u64) { var $t5: u64 [unused] var $t6: bool var $t7: u64 - var $t8: u64 [unused] + var $t8: u64 var $t9: u64 [unused] + var $t10: u64 [unused] + var $t11: u64 [unused] 0: $t4 := copy($t0) 1: label L0 - 2: $t7 := 0 - 3: $t6 := >($t4, $t7) - 4: if ($t6) goto 5 else goto 13 - 5: label L2 - 6: $t7 := move($t0) - 7: $t0 := move($t1) - 8: $t1 := move($t7) - 9: $t7 := 1 - 10: $t7 := -($t4, $t7) - 11: $t4 := move($t7) - 12: goto 1 - 13: label L3 - 14: $t0 := move($t0) - 15: $t1 := move($t1) - 16: return ($t0, $t1) + 2: $t7 := copy($t4) + 3: $t8 := 0 + 4: $t6 := >($t7, $t8) + 5: if ($t6) goto 6 else goto 15 + 6: label L2 + 7: $t7 := move($t0) + 8: $t0 := move($t1) + 9: $t1 := move($t7) + 10: $t7 := move($t4) + 11: $t8 := 1 + 12: $t7 := -($t7, $t8) + 13: $t4 := move($t7) + 14: goto 1 + 15: label L3 + 16: $t0 := move($t0) + 17: $t1 := move($t1) + 18: return ($t0, $t1) } ============ after DeadStoreElimination: ================ @@ -166,23 +186,29 @@ public fun m::test($t0: u64, $t1: u64): (u64, u64) { var $t5: u64 [unused] var $t6: bool var $t7: u64 - var $t8: u64 [unused] + var $t8: u64 var $t9: u64 [unused] + var $t10: u64 [unused] + var $t11: u64 [unused] 0: $t4 := copy($t0) 1: label L0 - 2: $t7 := 0 - 3: $t6 := >($t4, $t7) - 4: if ($t6) goto 5 else goto 13 - 5: label L2 - 6: $t7 := move($t0) - 7: $t0 := move($t1) - 8: $t1 := move($t7) - 9: $t7 := 1 - 10: $t7 := -($t4, $t7) - 11: $t4 := move($t7) - 12: goto 1 - 13: label L3 - 14: return ($t0, $t1) + 2: $t7 := copy($t4) + 3: $t8 := 0 + 4: $t6 := >($t7, $t8) + 5: if ($t6) goto 6 else goto 15 + 6: label L2 + 7: $t7 := move($t0) + 8: $t0 := move($t1) + 9: $t1 := move($t7) + 10: $t7 := move($t4) + 11: $t8 := 1 + 12: $t7 := -($t7, $t8) + 13: $t4 := move($t7) + 14: goto 1 + 15: label L3 + 16: $t0 := move($t0) + 17: $t1 := move($t1) + 18: return ($t0, $t1) } @@ -193,7 +219,6 @@ module c0ffee.m { public test(Arg0: u64, Arg1: u64): u64 * u64 /* def_idx: 0 */ { L2: loc0: u64 -L3: loc1: u64 B0: 0: CopyLoc[0](Arg0: u64) 1: StLoc[2](loc0: u64) @@ -206,11 +231,11 @@ B2: 6: MoveLoc[0](Arg0: u64) 7: MoveLoc[1](Arg1: u64) 8: StLoc[0](Arg0: u64) - 9: MoveLoc[2](loc0: u64) - 10: LdU64(1) - 11: Sub - 12: StLoc[2](loc0: u64) - 13: StLoc[1](Arg1: u64) + 9: StLoc[1](Arg1: u64) + 10: MoveLoc[2](loc0: u64) + 11: LdU64(1) + 12: Sub + 13: StLoc[2](loc0: u64) 14: Branch(2) B3: 15: MoveLoc[0](Arg0: u64) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/unused_add.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/unused_add.exp index 850ba7d9bb591..e408f58495292 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/unused_add.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/unused_add.exp @@ -13,10 +13,12 @@ public fun m::test() { var $t0: u64 var $t1: u64 var $t2: u64 + var $t3: u64 0: $t0 := 1 1: $t1 := 2 - 2: $t2 := +($t0, $t1) - 3: return () + 2: $t3 := infer($t0) + 3: $t2 := +($t3, $t1) + 4: return () } @@ -34,10 +36,12 @@ public fun m::test() { var $t0: u64 var $t1: u64 var $t2: u64 + var $t3: u64 0: $t0 := 1 1: $t1 := 2 - 2: $t2 := +($t0, $t1) - 3: return () + 2: $t3 := move($t0) + 3: $t2 := +($t3, $t1) + 4: return () } ============ after VariableCoalescingAnnotator: ================ @@ -47,6 +51,7 @@ public fun m::test() { var $t0: u64 var $t1: u64 var $t2: u64 + var $t3: u64 # live vars: # events: b:$t0 0: $t0 := 1 @@ -54,10 +59,13 @@ public fun m::test() { # events: b:$t1 1: $t1 := 2 # live vars: $t0, $t1 - # events: e:$t0, e:$t1, e:$t2, b:$t2 - 2: $t2 := +($t0, $t1) + # events: e:$t0, b:$t3 + 2: $t3 := move($t0) + # live vars: $t1, $t3 + # events: e:$t1, e:$t2, e:$t3, b:$t2 + 3: $t2 := +($t3, $t1) # live vars: - 3: return () + 4: return () } ============ after VariableCoalescingTransformer: ================ @@ -67,10 +75,12 @@ public fun m::test() { var $t0: u64 var $t1: u64 var $t2: u64 [unused] + var $t3: u64 [unused] 0: $t0 := 1 1: $t1 := 2 - 2: $t0 := +($t0, $t1) - 3: return () + 2: $t0 := move($t0) + 3: $t0 := +($t0, $t1) + 4: return () } ============ after DeadStoreElimination: ================ @@ -80,6 +90,7 @@ public fun m::test() { var $t0: u64 var $t1: u64 var $t2: u64 [unused] + var $t3: u64 [unused] 0: $t0 := 1 1: $t1 := 2 2: $t0 := +($t0, $t1) diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/misc/vector_popback.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/misc/vector_popback.exp new file mode 100644 index 0000000000000..15b4a3261910f --- /dev/null +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/misc/vector_popback.exp @@ -0,0 +1,3 @@ +processed 3 tasks + +==> Compiler v2 delivered same results! diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/misc/vector_popback.move b/third_party/move/move-compiler-v2/transactional-tests/tests/misc/vector_popback.move new file mode 100644 index 0000000000000..c37a6ba8deb27 --- /dev/null +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/misc/vector_popback.move @@ -0,0 +1,37 @@ +//# publish +module 0x42::vector { + fun create(): vector { + vector[1, 2, 3] + } + + public fun test_fold() { + use std::vector; + let v = vector[1]; + let accu = vector::fold(v, 0, |_, _| 0 ); + assert!(accu == 0 , 0) + } + + public fun test_remove() { + use std::vector; + let v = create(); + let e = remove(&mut v, 1); + assert!(e == 2, 0); + assert!(vector::length(&v) == 2, 0); + assert!(*vector::borrow(&v, 0) == 1, 0); + assert!(*vector::borrow(&v, 1) == 3, 0); + } + + public fun remove(v: &mut vector, i: u64): Element { + use std::vector; + let len = vector::length(v); + if (i >= len) abort 1; + + len = len - 1; + while (i < len) vector::swap(v, i, { i = i + 1; i }); + vector::pop_back(v) + } +} + +//# run 0x42::vector::test_fold + +//# run 0x42::vector::test_remove From 1c4f6ede1a396dbedab9d9ec1b85dba0192e015f Mon Sep 17 00:00:00 2001 From: marco ilardi Date: Fri, 13 Dec 2024 19:40:31 +0100 Subject: [PATCH 52/78] ensure ObjectCore exists before short-circuit --- aptos-move/framework/aptos-framework/doc/object.md | 7 ++++--- aptos-move/framework/aptos-framework/sources/object.move | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/aptos-move/framework/aptos-framework/doc/object.md b/aptos-move/framework/aptos-framework/doc/object.md index cb633a173bf6c..7ae33a425ee25 100644 --- a/aptos-move/framework/aptos-framework/doc/object.md +++ b/aptos-move/framework/aptos-framework/doc/object.md @@ -2301,15 +2301,16 @@ Return true if the provided address has indirect or direct ownership of the prov
public fun owns<T: key>(object: Object<T>, owner: address): bool acquires ObjectCore {
     let current_address = object_address(&object);
-    if (current_address == owner) {
-        return true
-    };
 
     assert!(
         exists<ObjectCore>(current_address),
         error::not_found(EOBJECT_DOES_NOT_EXIST),
     );
 
+    if (current_address == owner) {
+        return true
+    };
+
     let object = borrow_global<ObjectCore>(current_address);
     let current_address = object.owner;
 
diff --git a/aptos-move/framework/aptos-framework/sources/object.move b/aptos-move/framework/aptos-framework/sources/object.move
index abca67bb2451a..bb6684ff6f430 100644
--- a/aptos-move/framework/aptos-framework/sources/object.move
+++ b/aptos-move/framework/aptos-framework/sources/object.move
@@ -662,15 +662,16 @@ module aptos_framework::object {
     /// Return true if the provided address has indirect or direct ownership of the provided object.
     public fun owns(object: Object, owner: address): bool acquires ObjectCore {
         let current_address = object_address(&object);
-        if (current_address == owner) {
-            return true
-        };
 
         assert!(
             exists(current_address),
             error::not_found(EOBJECT_DOES_NOT_EXIST),
         );
 
+        if (current_address == owner) {
+            return true
+        };
+
         let object = borrow_global(current_address);
         let current_address = object.owner;
 

From 3497c86a7172f0209773c71258bba6a6b2d5f488 Mon Sep 17 00:00:00 2001
From: Vineeth Kashyap 
Date: Sat, 14 Dec 2024 22:24:16 -0500
Subject: [PATCH 53/78] [compiler-v2] Enable recent stack-optimizations by
 default (#15595)

---
 .../aptos_test_harness/diamond_clicker.v2_exp |  68 +-
 .../tests/compiler-v2-doc/aptos_governance.md |   3 +
 .../tests/compiler-v2-doc/coin.md             | 166 +--
 .../tests/compiler-v2-doc/genesis.md          |   2 +-
 .../tests/compiler-v2-doc/staking_config.md   |  15 +
 .../tests/compiler-v2-doc/features.md         |  68 ++
 .../tests/compiler-v2-doc/vector.md           | 131 ++-
 .../src/bytecode_generator.rs                 |  16 +-
 .../move/move-compiler-v2/src/experiments.rs  |  15 -
 .../function_generator.rs                     |  18 +-
 third_party/move/move-compiler-v2/src/lib.rs  |   6 +-
 .../src/pipeline/flush_writes_processor.rs    |  36 +-
 .../tests/file-format-generator/assign.exp    |   8 +-
 .../tests/file-format-generator/bug_14762.exp | 100 +-
 .../tests/file-format-generator/const.exp     |   5 +-
 .../file-format-generator/eager_push_01.exp   |  24 +-
 .../file-format-generator/eager_push_02.exp   |  15 +-
 .../tests/file-format-generator/fields.exp    |  15 +-
 .../framework_reduced_06.exp                  |  70 +-
 .../file-format-generator/generic_call.exp    |   5 +-
 .../tests/file-format-generator/globals.exp   |  13 +-
 .../tests/file-format-generator/if_else.exp   |  96 +-
 .../tests/file-format-generator/loop.exp      | 167 ++-
 .../tests/file-format-generator/multi_use.exp |  15 +-
 .../tests/file-format-generator/operators.exp |  26 +-
 .../file-format-generator/opt_load_01.exp     | 119 +--
 .../file-format-generator/opt_load_02.exp     | 185 +---
 .../file-format-generator/opt_load_04.exp     |  16 +-
 .../file-format-generator/opt_load_05.exp     |  45 +-
 .../file-format-generator/pack_order.exp      |  86 +-
 .../file-format-generator/pack_unpack.exp     |  23 +-
 .../file-format-generator/struct_variants.exp | 118 ++-
 .../unpack_generic_struct.exp                 |  30 +-
 .../unpack_generic_struct_typed.exp           |  30 +-
 .../tests/file-format-generator/vector.exp    | 106 +-
 .../reference-safety/duplicate_use.no-opt.exp |   4 +-
 .../tests/reference-safety/freeze.no-opt.exp  |   4 +-
 .../multiple_use_invalid.no-opt.exp           |   2 +-
 .../factor_invalid_1.no-opt.exp               |   2 +-
 .../imm_borrow_global_invalid.no-opt.exp      |   4 +-
 .../call_mutual_borrows_invalid.no-opt.exp    |  12 +-
 .../v1-tests/copy_full_invalid.no-opt.exp     |   4 +-
 .../tests/inlining/deep_exp.no-optimize.exp   |  29 +-
 .../tests/misc/bitwise_features.exp           |   3 +
 .../tests/misc/bitwise_features.move          |  58 +
 .../misc/bug_14243_stack_size.no-optimize.exp |   6 +-
 .../assert_one.no-optimize.exp                |   2 +-
 .../tests/abort_example.exp                   | 111 +-
 .../tests/bit_vector_loop_example.exp         | 988 ++++++++----------
 .../tests/conditionals.exp                    | 130 ++-
 .../ast-generator-tests/tests/loops.exp       | 379 ++++---
 .../functional/ModifiesErrorTest.v2_exp       |   1 -
 .../functional/ModifiesSchemaTest.v2_exp      |   2 +-
 .../sources/functional/address_quant.v2_exp   |   1 -
 .../functional/bitwise_features.v2_exp        |  12 +
 .../tests/sources/functional/choice.v2_exp    |   3 -
 .../data_invariant_for_mut_ref_arg.v2_exp     |   2 -
 .../functional/data_invariant_in_map.v2_exp   |   2 +-
 .../tests/sources/functional/emits.v2_exp     |  19 -
 .../functional/fixed_point_arithm.v2_exp      |   8 -
 .../functional/global_invariants.v2_exp       |   1 -
 .../sources/functional/global_vars.v2_exp     |   1 -
 .../sources/functional/loop_unroll.v2_exp     |  12 -
 .../tests/sources/functional/loops.v2_exp     |   8 -
 .../functional/loops_with_memory_ops.v2_exp   |   3 -
 .../functional/macro_verification.v2_exp      |   8 -
 .../functional/module_level_spec.v2_exp       |   1 -
 .../tests/sources/functional/mut_ref.v2_exp   |   1 -
 .../functional/nested_invariants.v2_exp       |   4 +-
 .../functional/script_incorrect.v2_exp        |   2 -
 .../sources/functional/specs_in_fun.v2_exp    |   1 -
 .../sources/functional/strong_edges.v2_exp    |   2 +-
 .../tests/sources/functional/trace.v2_exp     |   6 +-
 .../tests/sources/regression/Escape.v2_exp    |   2 -
 .../mono_after_global_invariant.v2_exp        |   2 -
 .../regression/type_param_bug_121721.v2_exp   |   1 -
 .../vector_theory_boogie_array.v2_exp         |   2 +-
 .../move-decompiler/tests/bit_vector.exp      |  72 +-
 .../move-decompiler/tests/fixed_point32.exp   |   6 +-
 .../move-decompiler/tests/simple_map.exp      |  24 +-
 .../tools/move-decompiler/tests/string.exp    |  14 +-
 .../tools/move-decompiler/tests/vector.exp    |  22 +-
 82 files changed, 1764 insertions(+), 2080 deletions(-)
 create mode 100644 third_party/move/move-compiler-v2/transactional-tests/tests/misc/bitwise_features.exp
 create mode 100644 third_party/move/move-compiler-v2/transactional-tests/tests/misc/bitwise_features.move
 create mode 100644 third_party/move/move-prover/tests/sources/functional/bitwise_features.v2_exp

diff --git a/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/diamond_clicker.v2_exp b/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/diamond_clicker.v2_exp
index 0a49bf4ec95ce..6da8712401946 100644
--- a/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/diamond_clicker.v2_exp
+++ b/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/diamond_clicker.v2_exp
@@ -15,49 +15,45 @@ struct OuterStruct has key {
 }
 
 entry public test_upgrade(Arg0: &signer) /* def_idx: 0 */ {
-L1:	loc0: OuterStruct
-L2:	loc1: &mut vector
+L1:	loc0: &mut vector
+L2:	loc1: u64
 L3:	loc2: u64
-L4:	loc3: u64
-L5:	loc4: u64
 B0:
 	0: CopyLoc[0](Arg0: &signer)
 	1: Call signer::address_of(&signer): address
-	2: VecPack(3, 0)
-	3: Pack[1](OuterStruct)
-	4: StLoc[1](loc0: OuterStruct)
-	5: MoveLoc[0](Arg0: &signer)
-	6: MoveLoc[1](loc0: OuterStruct)
-	7: MoveTo[1](OuterStruct)
-	8: MutBorrowGlobal[1](OuterStruct)
-	9: MutBorrowField[0](OuterStruct.any_field: vector)
-	10: StLoc[2](loc1: &mut vector)
-	11: LdU64(0)
-	12: StLoc[3](loc2: u64)
-	13: CopyLoc[2](loc1: &mut vector)
-	14: FreezeRef
-	15: VecLen(3)
-	16: StLoc[4](loc3: u64)
+	2: MoveLoc[0](Arg0: &signer)
+	3: VecPack(3, 0)
+	4: Pack[1](OuterStruct)
+	5: MoveTo[1](OuterStruct)
+	6: MutBorrowGlobal[1](OuterStruct)
+	7: MutBorrowField[0](OuterStruct.any_field: vector)
+	8: StLoc[1](loc0: &mut vector)
+	9: LdU64(0)
+	10: StLoc[2](loc1: u64)
+	11: CopyLoc[1](loc0: &mut vector)
+	12: FreezeRef
+	13: VecLen(3)
+	14: StLoc[3](loc2: u64)
 B1:
-	17: CopyLoc[3](loc2: u64)
-	18: CopyLoc[4](loc3: u64)
-	19: Lt
-	20: BrFalse(31)
+	15: CopyLoc[2](loc1: u64)
+	16: CopyLoc[3](loc2: u64)
+	17: Lt
+	18: BrFalse(29)
 B2:
-	21: CopyLoc[2](loc1: &mut vector)
-	22: CopyLoc[3](loc2: u64)
-	23: VecMutBorrow(3)
-	24: FreezeRef
-	25: Call debug::print(&InnerStruct)
-	26: MoveLoc[3](loc2: u64)
-	27: LdU64(1)
-	28: Add
-	29: StLoc[3](loc2: u64)
-	30: Branch(17)
+	19: CopyLoc[1](loc0: &mut vector)
+	20: CopyLoc[2](loc1: u64)
+	21: VecMutBorrow(3)
+	22: FreezeRef
+	23: Call debug::print(&InnerStruct)
+	24: MoveLoc[2](loc1: u64)
+	25: LdU64(1)
+	26: Add
+	27: StLoc[2](loc1: u64)
+	28: Branch(15)
 B3:
-	31: MoveLoc[2](loc1: &mut vector)
-	32: Pop
-	33: Ret
+	29: MoveLoc[1](loc0: &mut vector)
+	30: Pop
+	31: Ret
 }
 }
 
diff --git a/aptos-move/framework/aptos-framework/tests/compiler-v2-doc/aptos_governance.md b/aptos-move/framework/aptos-framework/tests/compiler-v2-doc/aptos_governance.md
index 64445190ff092..05b579a9fc508 100644
--- a/aptos-move/framework/aptos-framework/tests/compiler-v2-doc/aptos_governance.md
+++ b/aptos-move/framework/aptos-framework/tests/compiler-v2-doc/aptos_governance.md
@@ -883,6 +883,7 @@ This function is private because it's called directly from the vm.
     system_addresses::assert_aptos_framework(aptos_framework);
 
     voting::register<GovernanceProposal>(aptos_framework);
+    initialize_partial_voting(aptos_framework);
     move_to(aptos_framework, GovernanceConfig {
         voting_duration_secs,
         min_voting_threshold,
@@ -2132,6 +2133,7 @@ Limit addition overflow.
 ensures exists<GovernanceEvents>(addr);
 ensures exists<VotingRecords>(addr);
 ensures exists<ApprovedExecutionHashes>(addr);
+ensures exists<VotingRecordsV2>(addr);
 
@@ -2204,6 +2206,7 @@ Abort if structs have already been created. aborts_if exists<VotingRecords>(addr); aborts_if exists<ApprovedExecutionHashes>(addr); aborts_if !exists<account::Account>(addr); + aborts_if exists<VotingRecordsV2>(addr); } diff --git a/aptos-move/framework/aptos-framework/tests/compiler-v2-doc/coin.md b/aptos-move/framework/aptos-framework/tests/compiler-v2-doc/coin.md index 2a7bff1d84289..363acc14af2c3 100644 --- a/aptos-move/framework/aptos-framework/tests/compiler-v2-doc/coin.md +++ b/aptos-move/framework/aptos-framework/tests/compiler-v2-doc/coin.md @@ -19,7 +19,6 @@ This module provides the foundation for typesafe Coins. - [Struct `WithdrawEvent`](#0x1_coin_WithdrawEvent) - [Struct `CoinEventHandleDeletion`](#0x1_coin_CoinEventHandleDeletion) - [Struct `PairCreation`](#0x1_coin_PairCreation) -- [Resource `MigrationFlag`](#0x1_coin_MigrationFlag) - [Struct `MintCapability`](#0x1_coin_MintCapability) - [Struct `FreezeCapability`](#0x1_coin_FreezeCapability) - [Struct `BurnCapability`](#0x1_coin_BurnCapability) @@ -29,6 +28,7 @@ This module provides the foundation for typesafe Coins. - [Struct `MintRefReceipt`](#0x1_coin_MintRefReceipt) - [Struct `TransferRefReceipt`](#0x1_coin_TransferRefReceipt) - [Struct `BurnRefReceipt`](#0x1_coin_BurnRefReceipt) +- [Resource `MigrationFlag`](#0x1_coin_MigrationFlag) - [Resource `Ghost$supply`](#0x1_coin_Ghost$supply) - [Resource `Ghost$aggregate_supply`](#0x1_coin_Ghost$aggregate_supply) - [Constants](#@Constants_0) @@ -57,6 +57,7 @@ This module provides the foundation for typesafe Coins. - [Function `calculate_amount_to_withdraw`](#0x1_coin_calculate_amount_to_withdraw) - [Function `maybe_convert_to_fungible_store`](#0x1_coin_maybe_convert_to_fungible_store) - [Function `migrate_to_fungible_store`](#0x1_coin_migrate_to_fungible_store) +- [Function `migrate_coin_store_to_fungible_store`](#0x1_coin_migrate_coin_store_to_fungible_store) - [Function `coin_address`](#0x1_coin_coin_address) - [Function `balance`](#0x1_coin_balance) - [Function `is_balance_at_least`](#0x1_coin_is_balance_at_least) @@ -72,7 +73,7 @@ This module provides the foundation for typesafe Coins. - [Function `burn`](#0x1_coin_burn) - [Function `burn_from`](#0x1_coin_burn_from) - [Function `deposit`](#0x1_coin_deposit) -- [Function `migrated_primary_fungible_store_exists`](#0x1_coin_migrated_primary_fungible_store_exists) +- [Function `can_receive_paired_fungible_asset`](#0x1_coin_can_receive_paired_fungible_asset) - [Function `force_deposit`](#0x1_coin_force_deposit) - [Function `destroy_zero`](#0x1_coin_destroy_zero) - [Function `extract`](#0x1_coin_extract) @@ -151,6 +152,7 @@ This module provides the foundation for typesafe Coins. use 0x1::system_addresses; use 0x1::table; use 0x1::type_info; +use 0x1::vector; @@ -621,35 +623,6 @@ Module event emitted when a new pair of coin and fungible asset is created. - - - - -## Resource `MigrationFlag` - -The flag the existence of which indicates the primary fungible store is created by the migration from CoinStore. - - -
#[resource_group_member(#[group = 0x1::object::ObjectGroup])]
-struct MigrationFlag has key
-
- - - -
-Fields - - -
-
-dummy_field: bool -
-
- -
-
- -
@@ -916,6 +889,36 @@ The hot potato receipt for flash borrowing BurnRef. + + + + +## Resource `MigrationFlag` + +The flag the existence of which indicates the primary fungible store is created by the migration from CoinStore. + + +
#[resource_group_member(#[group = 0x1::object::ObjectGroup])]
+#[deprecated]
+struct MigrationFlag has key
+
+ + + +
+Fields + + +
+
+dummy_field: bool +
+
+ +
+
+ +
@@ -2038,7 +2041,6 @@ or disallow upgradability of total supply. let metadata = ensure_paired_metadata<CoinType>(); let store = primary_fungible_store::ensure_primary_store_exists(account, metadata); - let store_address = object::object_address(&store); if (exists<CoinStore<CoinType>>(account)) { let CoinStore<CoinType> { coin, frozen, deposit_events, withdraw_events } = move_from<CoinStore<CoinType>>( account @@ -2052,13 +2054,21 @@ or disallow upgradability of total supply. deleted_withdraw_event_handle_creation_number: guid::creation_num(event::guid(&withdraw_events)) } ); - event::destroy_handle(deposit_events); - event::destroy_handle(withdraw_events); if (coin.value == 0) { destroy_zero(coin); } else { - fungible_asset::deposit(store, coin_to_fungible_asset(coin)); + if (std::features::module_event_migration_enabled()) { + event::emit(CoinWithdraw { coin_type: type_name<CoinType>(), account, amount: coin.value }); + } else { + event::emit_event<WithdrawEvent>( + &mut withdraw_events, + WithdrawEvent { amount: coin.value }, + ); + }; + fungible_asset::deposit_internal(object_address(&store), coin_to_fungible_asset(coin)); }; + event::destroy_handle(deposit_events); + event::destroy_handle(withdraw_events); // Note: // It is possible the primary fungible store may already exist before this function call. // In this case, if the account owns a frozen CoinStore and an unfrozen primary fungible store, this @@ -2068,9 +2078,6 @@ or disallow upgradability of total supply. fungible_asset::set_frozen_flag_internal(store, frozen); } }; - if (!exists<MigrationFlag>(store_address)) { - move_to(&create_signer::create_signer(store_address), MigrationFlag {}); - } } @@ -2103,6 +2110,37 @@ Voluntarily migrate to fungible store for CoinType if not yet. + + + + +## Function `migrate_coin_store_to_fungible_store` + +Migrate to fungible store for CoinType if not yet. + + +
public entry fun migrate_coin_store_to_fungible_store<CoinType>(accounts: vector<address>)
+
+ + + +
+Implementation + + +
public entry fun migrate_coin_store_to_fungible_store<CoinType>(
+    accounts: vector<address>
+) acquires CoinStore, CoinConversionMap, CoinInfo {
+    if (features::new_accounts_default_to_fa_apt_store_enabled()) {
+        std::vector::for_each(accounts, |account| {
+            maybe_convert_to_fungible_store<CoinType>(account);
+        });
+    }
+}
+
+ + +
@@ -2314,7 +2352,7 @@ Returns true if account_addr is registered to r let paired_metadata_opt = paired_metadata<CoinType>(); (option::is_some( &paired_metadata_opt - ) && migrated_primary_fungible_store_exists(account_addr, option::destroy_some(paired_metadata_opt))) + ) && can_receive_paired_fungible_asset(account_addr, option::destroy_some(paired_metadata_opt))) } } @@ -2590,7 +2628,7 @@ Deposit the coin balance into the recipient's account and emit an event. merge(&mut coin_store.coin, coin); } else { let metadata = paired_metadata<CoinType>(); - if (option::is_some(&metadata) && migrated_primary_fungible_store_exists( + if (option::is_some(&metadata) && can_receive_paired_fungible_asset( account_addr, option::destroy_some(metadata) )) { @@ -2606,13 +2644,13 @@ Deposit the coin balance into the recipient's account and emit an event. - + -## Function `migrated_primary_fungible_store_exists` +## Function `can_receive_paired_fungible_asset` -
fun migrated_primary_fungible_store_exists(account_address: address, metadata: object::Object<fungible_asset::Metadata>): bool
+
fun can_receive_paired_fungible_asset(account_address: address, metadata: object::Object<fungible_asset::Metadata>): bool
 
@@ -2621,15 +2659,17 @@ Deposit the coin balance into the recipient's account and emit an event. Implementation -
inline fun migrated_primary_fungible_store_exists(
+
inline fun can_receive_paired_fungible_asset(
     account_address: address,
     metadata: Object<Metadata>
 ): bool {
-    let primary_store_address = primary_fungible_store::primary_store_address<Metadata>(account_address, metadata);
-    fungible_asset::store_exists(primary_store_address) && (
-        // migration flag is needed, until we start defaulting new accounts to APT PFS
-        features::new_accounts_default_to_fa_apt_store_enabled() || exists<MigrationFlag>(primary_store_address)
-    )
+    (features::new_accounts_default_to_fa_apt_store_enabled() && object::object_address(&metadata) == @0xa) || {
+        let primary_store_address = primary_fungible_store::primary_store_address<Metadata>(
+            account_address,
+            metadata
+        );
+        fungible_asset::store_exists(primary_store_address)
+    }
 }
 
@@ -2663,13 +2703,13 @@ This is for internal use only and doesn't emit an DepositEvent. merge(&mut coin_store.coin, coin); } else { let metadata = paired_metadata<CoinType>(); - if (option::is_some(&metadata) && migrated_primary_fungible_store_exists( + if (option::is_some(&metadata) && can_receive_paired_fungible_asset( account_addr, option::destroy_some(metadata) )) { let fa = coin_to_fungible_asset(coin); let metadata = fungible_asset::asset_metadata(&fa); - let store = primary_fungible_store::primary_store(account_addr, metadata); + let store = primary_fungible_store::ensure_primary_store_exists(account_addr, metadata); fungible_asset::deposit_internal(object::object_address(&store), fa); } else { abort error::not_found(ECOIN_STORE_NOT_PUBLISHED) @@ -3782,7 +3822,8 @@ Get address by reflection.
fun spec_is_account_registered<CoinType>(account_addr: address): bool {
    let paired_metadata_opt = spec_paired_metadata<CoinType>();
-   exists<CoinStore<CoinType>>(account_addr) || (option::spec_is_some(
+   exists<CoinStore<CoinType>>(account_addr) || features::spec_new_accounts_default_to_fa_apt_store_enabled(
+   ) || (option::spec_is_some(
        paired_metadata_opt
    ) && primary_fungible_store::spec_primary_store_exists(account_addr, option::spec_borrow(paired_metadata_opt)))
 }
@@ -4195,27 +4236,6 @@ The creator of CoinType must be @aptos_framework.
 
-Make sure name and symbol are legal length. -Only the creator of CoinType can initialize. - - - - - -
schema InitializeInternalSchema<CoinType> {
-    account: signer;
-    name: vector<u8>;
-    symbol: vector<u8>;
-    let account_addr = signer::address_of(account);
-    let coin_address = type_info::type_of<CoinType>().account_address;
-    aborts_if coin_address != account_addr;
-    aborts_if exists<CoinInfo<CoinType>>(account_addr);
-    aborts_if len(name) > MAX_COIN_NAME_LENGTH;
-    aborts_if len(symbol) > MAX_COIN_SYMBOL_LENGTH;
-}
-
- - diff --git a/aptos-move/framework/aptos-framework/tests/compiler-v2-doc/genesis.md b/aptos-move/framework/aptos-framework/tests/compiler-v2-doc/genesis.md index b9895b4393743..ff4866aad7c8f 100644 --- a/aptos-move/framework/aptos-framework/tests/compiler-v2-doc/genesis.md +++ b/aptos-move/framework/aptos-framework/tests/compiler-v2-doc/genesis.md @@ -340,6 +340,7 @@ Genesis step 1: Initialize aptos framework account and core modules on chain. execution_config::set(&aptos_framework_account, execution_config); version::initialize(&aptos_framework_account, initial_version); stake::initialize(&aptos_framework_account); + timestamp::set_time_has_started(&aptos_framework_account); staking_config::initialize( &aptos_framework_account, minimum_stake, @@ -360,7 +361,6 @@ Genesis step 1: Initialize aptos framework account and core modules on chain. reconfiguration::initialize(&aptos_framework_account); block::initialize(&aptos_framework_account, epoch_interval_microsecs); state_storage::initialize(&aptos_framework_account); - timestamp::set_time_has_started(&aptos_framework_account); }
diff --git a/aptos-move/framework/aptos-framework/tests/compiler-v2-doc/staking_config.md b/aptos-move/framework/aptos-framework/tests/compiler-v2-doc/staking_config.md index f053716b0e392..b4d2a86a61a27 100644 --- a/aptos-move/framework/aptos-framework/tests/compiler-v2-doc/staking_config.md +++ b/aptos-move/framework/aptos-framework/tests/compiler-v2-doc/staking_config.md @@ -386,6 +386,17 @@ Only called during genesis. rewards_rate_denominator, voting_power_increase_limit, }); + + // Initialize StakingRewardsConfig with the given rewards_rate and rewards_rate_denominator, + // while setting min_rewards_rate and rewards_rate_decrease_rate to 0. + initialize_rewards( + aptos_framework, + fixed_point64::create_from_rational((rewards_rate as u128), (rewards_rate_denominator as u128)), + fixed_point64::create_from_rational(0, 1000), + ONE_YEAR_IN_SECS, + 0, + fixed_point64::create_from_rational(0, 1000), + ); }
@@ -1072,6 +1083,7 @@ Can only be called as part of the Aptos governance proposal process established
invariant [suspendable] chain_status::is_operating() ==> exists<StakingConfig>(@aptos_framework);
+invariant [suspendable] chain_status::is_operating() ==> exists<StakingRewardsConfig>(@aptos_framework);
 pragma verify = true;
 pragma aborts_if_is_strict;
 
@@ -1223,6 +1235,7 @@ StakingConfig does not exist under the aptos_framework before creating it.
let addr = signer::address_of(aptos_framework);
+requires exists<timestamp::CurrentTimeMicroseconds>(@aptos_framework);
 // This enforces high-level requirement 1:
 aborts_if addr != @aptos_framework;
 aborts_if minimum_stake > maximum_stake || maximum_stake == 0;
@@ -1234,7 +1247,9 @@ StakingConfig does not exist under the aptos_framework before creating it.
 aborts_if rewards_rate > MAX_REWARDS_RATE;
 aborts_if rewards_rate > rewards_rate_denominator;
 aborts_if exists<StakingConfig>(addr);
+aborts_if exists<StakingRewardsConfig>(addr);
 ensures exists<StakingConfig>(addr);
+ensures exists<StakingRewardsConfig>(addr);
 
diff --git a/aptos-move/framework/move-stdlib/tests/compiler-v2-doc/features.md b/aptos-move/framework/move-stdlib/tests/compiler-v2-doc/features.md index 6bfd2a4d4554a..ba2122e8a9788 100644 --- a/aptos-move/framework/move-stdlib/tests/compiler-v2-doc/features.md +++ b/aptos-move/framework/move-stdlib/tests/compiler-v2-doc/features.md @@ -133,6 +133,8 @@ return true. - [Function `transaction_simulation_enhancement_enabled`](#0x1_features_transaction_simulation_enhancement_enabled) - [Function `get_collection_owner_feature`](#0x1_features_get_collection_owner_feature) - [Function `is_collection_owner_enabled`](#0x1_features_is_collection_owner_enabled) +- [Function `get_native_memory_operations_feature`](#0x1_features_get_native_memory_operations_feature) +- [Function `is_native_memory_operations_enabled`](#0x1_features_is_native_memory_operations_enabled) - [Function `change_feature_flags`](#0x1_features_change_feature_flags) - [Function `change_feature_flags_internal`](#0x1_features_change_feature_flags_internal) - [Function `change_feature_flags_for_next_epoch`](#0x1_features_change_feature_flags_for_next_epoch) @@ -670,6 +672,15 @@ Lifetime: transient + + + + +
const NATIVE_MEMORY_OPERATIONS: u64 = 80;
+
+ + + Lifetime: transient @@ -3273,6 +3284,52 @@ Deprecated feature + + + + +## Function `get_native_memory_operations_feature` + + + +
public fun get_native_memory_operations_feature(): u64
+
+ + + +
+Implementation + + +
public fun get_native_memory_operations_feature(): u64 { NATIVE_MEMORY_OPERATIONS }
+
+ + + +
+ + + +## Function `is_native_memory_operations_enabled` + + + +
public fun is_native_memory_operations_enabled(): bool
+
+ + + +
+Implementation + + +
public fun is_native_memory_operations_enabled(): bool acquires Features {
+    is_enabled(NATIVE_MEMORY_OPERATIONS)
+}
+
+ + +
@@ -3697,6 +3754,17 @@ Helper to check whether a feature flag is enabled. + + + +
fun spec_new_accounts_default_to_fa_apt_store_enabled(): bool {
+   spec_is_enabled(NEW_ACCOUNTS_DEFAULT_TO_FA_APT_STORE)
+}
+
+ + + + diff --git a/aptos-move/framework/move-stdlib/tests/compiler-v2-doc/vector.md b/aptos-move/framework/move-stdlib/tests/compiler-v2-doc/vector.md index b56160dbaf27e..9e837c9c1cfae 100644 --- a/aptos-move/framework/move-stdlib/tests/compiler-v2-doc/vector.md +++ b/aptos-move/framework/move-stdlib/tests/compiler-v2-doc/vector.md @@ -40,6 +40,7 @@ the return on investment didn't seem worth it for these simple functions. - [Function `remove`](#0x1_vector_remove) - [Function `remove_value`](#0x1_vector_remove_value) - [Function `swap_remove`](#0x1_vector_swap_remove) +- [Function `replace`](#0x1_vector_replace) - [Function `for_each`](#0x1_vector_for_each) - [Function `for_each_reverse`](#0x1_vector_for_each_reverse) - [Function `for_each_ref`](#0x1_vector_for_each_ref) @@ -146,6 +147,18 @@ The length of the vectors are not equal. + + +Whether to utilize native vector::move_range +Vector module cannot call features module, due to cyclic dependency, +so this is a constant. + + +
const USE_MOVE_RANGE: bool = true;
+
+ + + ## Function `empty` @@ -482,8 +495,15 @@ Pushes all of the elements of the other vector into the self<
public fun append<Element>(self: &mut vector<Element>, other: vector<Element>) {
-    reverse(&mut other);
-    reverse_append(self, other);
+    if (USE_MOVE_RANGE) {
+        let self_length = length(self);
+        let other_length = length(&other);
+        move_range(&mut other, 0, other_length, self, self_length);
+        destroy_empty(other);
+    } else {
+        reverse(&mut other);
+        reverse_append(self, other);
+    }
 }
 
@@ -525,7 +545,11 @@ Pushes all of the elements of the other vector into the self< ## Function `trim` -Trim a vector to a smaller size, returning the evicted elements in order +Splits (trims) the collection into two at the given index. +Returns a newly allocated vector containing the elements in the range [new_len, len). +After the call, the original vector will be left containing the elements [0, new_len) +with its previous capacity unchanged. +In many languages this is also called split_off.
public fun trim<Element>(self: &mut vector<Element>, new_len: u64): vector<Element>
@@ -538,9 +562,21 @@ Trim a vector to a smaller size, returning the evicted elements in order
 
 
 
public fun trim<Element>(self: &mut vector<Element>, new_len: u64): vector<Element> {
-    let res = trim_reverse(self, new_len);
-    reverse(&mut res);
-    res
+    let len = length(self);
+    assert!(new_len <= len, EINDEX_OUT_OF_BOUNDS);
+
+    let other = empty();
+    if (USE_MOVE_RANGE) {
+        move_range(self, new_len, len - new_len, &mut other, 0);
+    } else {
+        while (len > new_len) {
+            push_back(&mut other, pop_back(self));
+            len = len - 1;
+        };
+        reverse(&mut other);
+    };
+
+    other
 }
 
@@ -728,10 +764,27 @@ Aborts if out of bounds.
public fun insert<Element>(self: &mut vector<Element>, i: u64, e: Element) {
     let len = length(self);
     assert!(i <= len, EINDEX_OUT_OF_BOUNDS);
-    push_back(self, e);
-    while (i < len) {
-        swap(self, i, len);
-        i = i + 1;
+
+    if (USE_MOVE_RANGE) {
+        if (i + 2 >= len) {
+            // When we are close to the end, it is cheaper to not create
+            // a temporary vector, and swap directly
+            push_back(self, e);
+            while (i < len) {
+                swap(self, i, len);
+                i = i + 1;
+            };
+        } else {
+            let other = singleton(e);
+            move_range(&mut other, 0, 1, self, i);
+            destroy_empty(other);
+        }
+    } else {
+        push_back(self, e);
+        while (i < len) {
+            swap(self, i, len);
+            i = i + 1;
+        };
     };
 }
 
@@ -763,9 +816,25 @@ Aborts if i is out of bounds. // i out of bounds; abort if (i >= len) abort EINDEX_OUT_OF_BOUNDS; - len = len - 1; - while (i < len) swap(self, i, { i = i + 1; i }); - pop_back(self) + if (USE_MOVE_RANGE) { + // When we are close to the end, it is cheaper to not create + // a temporary vector, and swap directly + if (i + 3 >= len) { + len = len - 1; + while (i < len) swap(self, i, { i = i + 1; i }); + pop_back(self) + } else { + let other = empty(); + move_range(self, i, 1, &mut other, 0); + let result = pop_back(&mut other); + destroy_empty(other); + result + } + } else { + len = len - 1; + while (i < len) swap(self, i, { i = i + 1; i }); + pop_back(self) + } }
@@ -838,6 +907,42 @@ Aborts if i is out of bounds. + + + + +## Function `replace` + +Replace the ith element of the vector self with the given value, and return +to the caller the value that was there before. +Aborts if i is out of bounds. + + +
public fun replace<Element>(self: &mut vector<Element>, i: u64, val: Element): Element
+
+ + + +
+Implementation + + +
public fun replace<Element>(self: &mut vector<Element>, i: u64, val: Element): Element {
+    let last_idx = length(self);
+    assert!(i < last_idx, EINDEX_OUT_OF_BOUNDS);
+    // TODO: Enable after tests are fixed.
+    // if (USE_MOVE_RANGE) {
+    //     mem::replace(borrow_mut(self, i), val)
+    // } else {
+    push_back(self, val);
+    swap(self, i, last_idx);
+    pop_back(self)
+    // }
+}
+
+ + +
diff --git a/third_party/move/move-compiler-v2/src/bytecode_generator.rs b/third_party/move/move-compiler-v2/src/bytecode_generator.rs index 3e6b05bd88d5b..cebd84c748329 100644 --- a/third_party/move/move-compiler-v2/src/bytecode_generator.rs +++ b/third_party/move/move-compiler-v2/src/bytecode_generator.rs @@ -1108,22 +1108,12 @@ impl<'env> Generator<'env> { /// Generate the code for a list of arguments. /// Note that the arguments are evaluated in left-to-right order. fn gen_arg_list(&mut self, exps: &[Exp]) -> Vec { - // If all args are side-effect free, we don't need to force temporary generation - // to get left-to-right evaluation. - // TODO: after comparison testing, remove depending on the experiment and always - // have `with_forced_temp` be true. - let options = self - .env() - .get_extension::() - .expect("Options is available"); - let with_forced_temp = options.experiment_on(Experiment::RETAIN_TEMPS_FOR_ARGS) - || !exps.iter().all(is_definitely_pure); let len = exps.len(); - // Generate code with (potentially) forced creation of temporaries for all except last arg. + // Generate code with forced creation of temporaries for all except last arg. let mut args = exps .iter() .take(if len == 0 { 0 } else { len - 1 }) - .map(|exp| self.gen_escape_auto_ref_arg(exp, with_forced_temp)) + .map(|exp| self.gen_escape_auto_ref_arg(exp, true)) .collect::>(); // If there is a last arg, we don't need to force create a temporary for it. if let Some(last_arg) = exps @@ -2445,6 +2435,7 @@ impl<'a> fmt::Display for ValueShapeDisplay<'a> { // Helpers /// Is this a leaf expression which cannot contain another expression? +#[allow(dead_code)] fn is_leaf_exp(exp: &Exp) -> bool { matches!( exp.as_ref(), @@ -2453,6 +2444,7 @@ fn is_leaf_exp(exp: &Exp) -> bool { } /// Can we be certain that this expression is side-effect free? +#[allow(dead_code)] fn is_definitely_pure(exp: &Exp) -> bool { is_leaf_exp(exp) // A leaf expression is pure. || match exp.as_ref() { diff --git a/third_party/move/move-compiler-v2/src/experiments.rs b/third_party/move/move-compiler-v2/src/experiments.rs index c0e7d5178ca60..a519049690013 100644 --- a/third_party/move/move-compiler-v2/src/experiments.rs +++ b/third_party/move/move-compiler-v2/src/experiments.rs @@ -271,19 +271,6 @@ pub static EXPERIMENTS: Lazy> = Lazy::new(|| { .to_string(), default: Given(false), }, - Experiment { - name: Experiment::AVOID_STORE_IN_ASSIGNS.to_string(), - description: "Avoid storing to a local during assigns".to_string(), - default: Inherited(Experiment::OPTIMIZE_WAITING_FOR_COMPARE_TESTS.to_string()), - }, - Experiment { - name: Experiment::RETAIN_TEMPS_FOR_ARGS.to_string(), - description: - "Create temps for each argument of a function call during stackless bytecode \ - generation and retain them until file format bytecode generation" - .to_string(), - default: Inherited(Experiment::OPTIMIZE_WAITING_FOR_COMPARE_TESTS.to_string()), - }, ]; experiments .into_iter() @@ -299,7 +286,6 @@ impl Experiment { pub const AST_SIMPLIFY: &'static str = "ast-simplify"; pub const AST_SIMPLIFY_FULL: &'static str = "ast-simplify-full"; pub const ATTACH_COMPILED_MODULE: &'static str = "attach-compiled-module"; - pub const AVOID_STORE_IN_ASSIGNS: &'static str = "avoid-store-in-assigns"; pub const CFG_SIMPLIFICATION: &'static str = "cfg-simplification"; pub const CHECKS: &'static str = "checks"; pub const COPY_PROPAGATION: &'static str = "copy-propagation"; @@ -324,7 +310,6 @@ impl Experiment { pub const RECURSIVE_TYPE_CHECK: &'static str = "recursive-type-check"; pub const REFERENCE_SAFETY: &'static str = "reference-safety"; pub const REFERENCE_SAFETY_V3: &'static str = "reference-safety-v3"; - pub const RETAIN_TEMPS_FOR_ARGS: &'static str = "retain-temps-for-args"; pub const SEQS_IN_BINOPS_CHECK: &'static str = "seqs-in-binops-check"; pub const SPEC_CHECK: &'static str = "spec-check"; pub const SPEC_REWRITE: &'static str = "spec-rewrite"; diff --git a/third_party/move/move-compiler-v2/src/file_format_generator/function_generator.rs b/third_party/move/move-compiler-v2/src/file_format_generator/function_generator.rs index 85e5e9402fc54..ea383d6298e2f 100644 --- a/third_party/move/move-compiler-v2/src/file_format_generator/function_generator.rs +++ b/third_party/move/move-compiler-v2/src/file_format_generator/function_generator.rs @@ -285,22 +285,8 @@ impl<'a> FunctionGenerator<'a> { std::slice::from_ref(source), ); self.abstract_push_args(ctx, vec![*source], Some(mode)); - // TODO: the below conditional check is temporary, the plan is to get rid of the `else` - // case if comparison testing is successful. - let options = ctx - .fun_ctx - .module - .env - .get_extension::() - .expect("Options is available"); - if options.experiment_on(Experiment::AVOID_STORE_IN_ASSIGNS) { - self.abstract_pop(ctx); - self.abstract_push_result(ctx, std::slice::from_ref(dest)); - } else { - let local = self.temp_to_local(ctx.fun_ctx, Some(ctx.attr_id), *dest); - self.emit(FF::Bytecode::StLoc(local)); - self.abstract_pop(ctx); - } + self.abstract_pop(ctx); + self.abstract_push_result(ctx, std::slice::from_ref(dest)); }, Bytecode::Ret(_, result) => { self.balance_stack_end_of_block(ctx, result); diff --git a/third_party/move/move-compiler-v2/src/lib.rs b/third_party/move/move-compiler-v2/src/lib.rs index ecfcfc75dc5c1..2b7e6d18b8c25 100644 --- a/third_party/move/move-compiler-v2/src/lib.rs +++ b/third_party/move/move-compiler-v2/src/lib.rs @@ -484,11 +484,7 @@ pub fn bytecode_pipeline(env: &GlobalEnv) -> FunctionTargetPipeline { if options.experiment_on(Experiment::DEAD_CODE_ELIMINATION) { pipeline.add_processor(Box::new(LiveVarAnalysisProcessor::new(true))); - // TODO: after comparison testing passes, always call with `eliminate_all_self_assigns` set - // to `false` when instantiating `DeadStoreElimination`. - pipeline.add_processor(Box::new(DeadStoreElimination::new( - !options.experiment_on(Experiment::RETAIN_TEMPS_FOR_ARGS), - ))); + pipeline.add_processor(Box::new(DeadStoreElimination::new(false))); } // Run live var analysis again because it could be invalidated by previous pipeline steps, diff --git a/third_party/move/move-compiler-v2/src/pipeline/flush_writes_processor.rs b/third_party/move/move-compiler-v2/src/pipeline/flush_writes_processor.rs index d15db4139ac3e..23c748713d8be 100644 --- a/third_party/move/move-compiler-v2/src/pipeline/flush_writes_processor.rs +++ b/third_party/move/move-compiler-v2/src/pipeline/flush_writes_processor.rs @@ -42,11 +42,7 @@ //! In all these cases, the file format generator can avoid extra stack operations due //! to eager flushing. -use crate::{ - experiments::Experiment, - pipeline::livevar_analysis_processor::{LiveVarAnnotation, LiveVarInfoAtCodeOffset}, - Options, -}; +use crate::pipeline::livevar_analysis_processor::{LiveVarAnnotation, LiveVarInfoAtCodeOffset}; use itertools::Itertools; use move_binary_format::file_format::CodeOffset; use move_model::{ast::TempIndex, model::FunctionEnv}; @@ -180,15 +176,6 @@ impl FunctionTargetProcessor for FlushWritesProcessor { let use_def_links = UseDefLinks::new(code, live_vars); let cfg = StacklessControlFlowGraph::new_forward(code); let mut flush_writes: BTreeMap> = BTreeMap::new(); - // TODO: After comparison testing, remove the `assign_optimize` flag and always - // perform the optimization. It currently is passed around so that existing behavior - // is retained when the flag is off. - let assign_optimize = func_env - .module_env - .env - .get_extension::() - .expect("Options is available") - .experiment_on(Experiment::RETAIN_TEMPS_FOR_ARGS); for block_id in cfg.blocks() { if let Some((lower, upper)) = cfg.instr_offset_bounds(block_id) { Self::extract_flush_writes_in_block( @@ -196,7 +183,6 @@ impl FunctionTargetProcessor for FlushWritesProcessor { code, &use_def_links, &mut flush_writes, - assign_optimize, ); } } @@ -219,7 +205,6 @@ impl FlushWritesProcessor { code: &[Bytecode], use_def_links: &UseDefLinks, flush_writes: &mut BTreeMap>, - assign_optimize: bool, ) { let upper = *block_range.end(); // Traverse the block in reverse order: for each definition starting from the @@ -231,23 +216,12 @@ impl FlushWritesProcessor { // Only `Assign`, `Call`, and `Load` instructions push temps to the stack. // We need to find if any of these temps are better flushed right away. if matches!(instr, Assign(..) | Call(..) | Load(..)) { - if !assign_optimize && matches!(instr, Assign(..)) { - // Retain previous behavior. - continue; - } for (dest_index, dest) in instr.dests().into_iter().enumerate().rev() { let def = DefOrUsePoint { offset, index: dest_index, }; - if Self::could_flush_right_away( - def, - upper, - code, - use_def_links, - flush_writes, - assign_optimize, - ) { + if Self::could_flush_right_away(def, upper, code, use_def_links, flush_writes) { flush_writes.entry(offset).or_default().insert(dest); } } @@ -263,7 +237,6 @@ impl FlushWritesProcessor { code: &[Bytecode], use_def_links: &UseDefLinks, flush_writes: &BTreeMap>, - assign_optimize: bool, ) -> bool { use_def_links.def_to_use.get(&def).map_or(true, |uses| { let exactly_one_use = uses.len() == 1; @@ -287,7 +260,6 @@ impl FlushWritesProcessor { code, use_def_links, flush_writes, - assign_optimize, ) }) } @@ -328,11 +300,7 @@ impl FlushWritesProcessor { code: &[Bytecode], use_def_links: &UseDefLinks, flush_writes: &BTreeMap>, - assign_optimize: bool, ) -> bool { - if !assign_optimize { - return false; - } // For each definition in between `def` and `use_`, is there at least one that is: // 1. not marked to be flushed right away? // 2. not consumed before `use_`? diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/assign.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/assign.exp index 0140492ccc133..1400c660aa9f9 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/assign.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/assign.exp @@ -33,8 +33,12 @@ B0: 0: MoveLoc[0](Arg0: S) 1: Unpack[1](S) 2: Unpack[0](T) - 3: Add - 4: Ret + 3: StLoc[2](Arg2: u64) + 4: StLoc[1](Arg1: u64) + 5: MoveLoc[1](Arg1: u64) + 6: MoveLoc[2](Arg2: u64) + 7: Add + 8: Ret } assign_struct(Arg0: &mut S) /* def_idx: 3 */ { B0: diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/bug_14762.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/bug_14762.exp index 9d0f6f655fbc9..8289c4d42afd3 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/bug_14762.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/bug_14762.exp @@ -23,13 +23,9 @@ L3: loc1: bool L4: loc2: u64 L5: loc3: u64 L6: loc4: u64 -L7: loc5: &T -L8: loc6: &T -L9: loc7: u64 -L10: loc8: bool -L11: loc9: u64 -L12: loc10: Option -L13: loc11: Option +L7: loc5: u64 +L8: loc6: bool +L9: loc7: Option B0: 0: CopyLoc[0](Arg0: &mut S) 1: ImmBorrowField[0](S.entries: vector) @@ -47,68 +43,60 @@ B1: 12: CopyLoc[6](loc4: u64) 13: CopyLoc[5](loc3: u64) 14: Lt - 15: BrFalse(41) + 15: BrFalse(35) B2: 16: CopyLoc[2](loc0: &vector) 17: CopyLoc[6](loc4: u64) 18: VecImmBorrow(2) - 19: StLoc[7](loc5: &T) - 20: MoveLoc[7](loc5: &T) - 21: StLoc[8](loc6: &T) - 22: MoveLoc[8](loc6: &T) - 23: ImmBorrowField[1](T.issuer: vector) - 24: ReadRef - 25: CopyLoc[1](Arg1: vector) - 26: Eq - 27: BrFalse(34) + 19: ImmBorrowField[1](T.issuer: vector) + 20: ReadRef + 21: CopyLoc[1](Arg1: vector) + 22: Eq + 23: BrFalse(30) B3: - 28: LdTrue - 29: StLoc[3](loc1: bool) - 30: MoveLoc[6](loc4: u64) - 31: StLoc[4](loc2: u64) - 32: Branch(43) + 24: LdTrue + 25: StLoc[3](loc1: bool) + 26: MoveLoc[6](loc4: u64) + 27: StLoc[4](loc2: u64) + 28: Branch(37) B4: - 33: Branch(34) + 29: Branch(30) B5: - 34: LdU64(1) - 35: StLoc[9](loc7: u64) - 36: MoveLoc[6](loc4: u64) - 37: MoveLoc[9](loc7: u64) - 38: Add - 39: StLoc[6](loc4: u64) - 40: Branch(42) + 30: MoveLoc[6](loc4: u64) + 31: LdU64(1) + 32: Add + 33: StLoc[6](loc4: u64) + 34: Branch(36) B6: - 41: Branch(43) + 35: Branch(37) B7: - 42: Branch(12) + 36: Branch(12) B8: - 43: Nop - 44: MoveLoc[2](loc0: &vector) - 45: Pop - 46: MoveLoc[3](loc1: bool) - 47: StLoc[10](loc8: bool) - 48: MoveLoc[4](loc2: u64) - 49: StLoc[11](loc9: u64) - 50: MoveLoc[10](loc8: bool) - 51: BrFalse(59) + 37: Nop + 38: MoveLoc[2](loc0: &vector) + 39: Pop + 40: MoveLoc[3](loc1: bool) + 41: MoveLoc[4](loc2: u64) + 42: StLoc[7](loc5: u64) + 43: StLoc[8](loc6: bool) + 44: MoveLoc[8](loc6: bool) + 45: BrFalse(53) B9: - 52: MoveLoc[0](Arg0: &mut S) - 53: MutBorrowField[0](S.entries: vector) - 54: MoveLoc[11](loc9: u64) - 55: Call vector::remove(&mut vector, u64): T - 56: Call option::some(T): Option - 57: StLoc[12](loc10: Option) - 58: Branch(63) + 46: MoveLoc[0](Arg0: &mut S) + 47: MutBorrowField[0](S.entries: vector) + 48: MoveLoc[7](loc5: u64) + 49: Call vector::remove(&mut vector, u64): T + 50: Call option::some(T): Option + 51: StLoc[9](loc7: Option) + 52: Branch(57) B10: - 59: MoveLoc[0](Arg0: &mut S) - 60: Pop - 61: Call option::none(): Option - 62: StLoc[12](loc10: Option) + 53: MoveLoc[0](Arg0: &mut S) + 54: Pop + 55: Call option::none(): Option + 56: StLoc[9](loc7: Option) B11: - 63: MoveLoc[12](loc10: Option) - 64: StLoc[13](loc11: Option) - 65: MoveLoc[13](loc11: Option) - 66: Ret + 57: MoveLoc[9](loc7: Option) + 58: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/const.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/const.exp index e3c70827b11a7..8c6bd9d68e95d 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/const.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/const.exp @@ -178,12 +178,9 @@ B0: 33: Ret } u(Arg0: Ty0): Ty0 /* def_idx: 1 */ { -L1: loc0: Ty0 B0: 0: MoveLoc[0](Arg0: Ty0) - 1: StLoc[1](loc0: Ty0) - 2: MoveLoc[1](loc0: Ty0) - 3: Ret + 1: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/eager_push_01.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/eager_push_01.exp index 24fc89cd866f2..677926f405b44 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/eager_push_01.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/eager_push_01.exp @@ -14,33 +14,15 @@ B0: 1: Ret } public test(Arg0: u64) /* def_idx: 2 */ { -L1: loc0: u64 -L2: loc1: u64 -L3: loc2: u64 -L4: loc3: u64 -L5: loc4: u64 -L6: loc5: u64 B0: 0: MoveLoc[0](Arg0: u64) - 1: StLoc[1](loc0: u64) + 1: Call one(): u64 2: Call one(): u64 3: Call one(): u64 4: Call one(): u64 5: Call one(): u64 - 6: Call one(): u64 - 7: StLoc[2](loc1: u64) - 8: StLoc[3](loc2: u64) - 9: StLoc[4](loc3: u64) - 10: StLoc[5](loc4: u64) - 11: StLoc[6](loc5: u64) - 12: MoveLoc[1](loc0: u64) - 13: MoveLoc[6](loc5: u64) - 14: MoveLoc[5](loc4: u64) - 15: MoveLoc[4](loc3: u64) - 16: MoveLoc[3](loc2: u64) - 17: MoveLoc[2](loc1: u64) - 18: Call bar(u64, u64, u64, u64, u64, u64) - 19: Ret + 6: Call bar(u64, u64, u64, u64, u64, u64) + 7: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/eager_push_02.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/eager_push_02.exp index dd83ac44afdf0..8f98258bd77db 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/eager_push_02.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/eager_push_02.exp @@ -5,16 +5,13 @@ module c0ffee.m { test(Arg0: u64, Arg1: u64): u64 /* def_idx: 0 */ { -L2: loc0: u64 B0: - 0: MoveLoc[1](Arg1: u64) - 1: CopyLoc[0](Arg0: u64) - 2: Mul - 3: StLoc[2](loc0: u64) - 4: MoveLoc[0](Arg0: u64) - 5: MoveLoc[2](loc0: u64) - 6: Add - 7: Ret + 0: CopyLoc[0](Arg0: u64) + 1: MoveLoc[1](Arg1: u64) + 2: MoveLoc[0](Arg0: u64) + 3: Mul + 4: Add + 5: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/fields.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/fields.exp index 70d71108d70db..3337fb03ac051 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/fields.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/fields.exp @@ -28,7 +28,6 @@ B0: } write_local_direct(): S /* def_idx: 2 */ { L0: loc0: S -L1: loc1: S B0: 0: LdU64(0) 1: LdU64(0) @@ -41,16 +40,13 @@ B0: 8: MutBorrowField[1](T.h: u64) 9: WriteRef 10: MoveLoc[0](loc0: S) - 11: StLoc[1](loc1: S) - 12: MoveLoc[1](loc1: S) - 13: Ret + 11: Ret } write_local_via_ref(): S /* def_idx: 3 */ { L0: loc0: S L1: loc1: u64 L2: loc2: &mut S L3: loc3: &mut u64 -L4: loc4: S B0: 0: LdU64(0) 1: LdU64(0) @@ -69,9 +65,7 @@ B0: 14: MoveLoc[3](loc3: &mut u64) 15: WriteRef 16: MoveLoc[0](loc0: S) - 17: StLoc[4](loc4: S) - 18: MoveLoc[4](loc4: S) - 19: Ret + 17: Ret } write_param(Arg0: &mut S) /* def_idx: 4 */ { B0: @@ -83,7 +77,6 @@ B0: 5: Ret } write_val(Arg0: S): S /* def_idx: 5 */ { -L1: loc0: S B0: 0: LdU64(42) 1: MutBorrowLoc[0](Arg0: S) @@ -91,9 +84,7 @@ B0: 3: MutBorrowField[1](T.h: u64) 4: WriteRef 5: MoveLoc[0](Arg0: S) - 6: StLoc[1](loc0: S) - 7: MoveLoc[1](loc0: S) - 8: Ret + 6: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/framework_reduced_06.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/framework_reduced_06.exp index 92d40d16fd075..d3f45765c6ccf 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/framework_reduced_06.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/framework_reduced_06.exp @@ -16,20 +16,11 @@ B0: 4: Ret } f1(Arg0: &mut S, Arg1: u64, Arg2: address): &mut S * address * u64 /* def_idx: 1 */ { -L3: loc0: &mut S -L4: loc1: address -L5: loc2: u64 B0: 0: MoveLoc[0](Arg0: &mut S) - 1: StLoc[3](loc0: &mut S) - 2: MoveLoc[2](Arg2: address) - 3: StLoc[4](loc1: address) - 4: MoveLoc[1](Arg1: u64) - 5: StLoc[5](loc2: u64) - 6: MoveLoc[3](loc0: &mut S) - 7: MoveLoc[4](loc1: address) - 8: MoveLoc[5](loc2: u64) - 9: Ret + 1: MoveLoc[2](Arg2: address) + 2: MoveLoc[1](Arg1: u64) + 3: Ret } f2(Arg0: address, Arg1: &mut S, Arg2: address, Arg3: u64, Arg4: &mut S) /* def_idx: 2 */ { B0: @@ -47,37 +38,40 @@ B0: } foo(Arg0: address, Arg1: &mut S, Arg2: &mut S): u64 /* def_idx: 4 */ { L3: loc0: u64 -L4: loc1: u64 +L4: loc1: address L5: loc2: address L6: loc3: &mut S -L7: loc4: &u64 -L8: loc5: u64 +L7: loc4: u64 +L8: loc5: address +L9: loc6: &mut S B0: - 0: LdU64(1) - 1: StLoc[3](loc0: u64) - 2: MoveLoc[1](Arg1: &mut S) - 3: MoveLoc[3](loc0: u64) - 4: MoveLoc[0](Arg0: address) - 5: Call f1(&mut S, u64, address): &mut S * address * u64 - 6: StLoc[4](loc1: u64) + 0: MoveLoc[1](Arg1: &mut S) + 1: LdU64(1) + 2: MoveLoc[0](Arg0: address) + 3: Call f1(&mut S, u64, address): &mut S * address * u64 + 4: StLoc[3](loc0: u64) + 5: StLoc[4](loc1: address) + 6: CopyLoc[4](loc1: address) 7: StLoc[5](loc2: address) 8: StLoc[6](loc3: &mut S) - 9: CopyLoc[5](loc2: address) - 10: CopyLoc[6](loc3: &mut S) - 11: MoveLoc[5](loc2: address) - 12: CopyLoc[4](loc1: u64) - 13: MoveLoc[2](Arg2: &mut S) - 14: Call f2(address, &mut S, address, u64, &mut S) - 15: MoveLoc[6](loc3: &mut S) - 16: ImmBorrowField[0](S.g: u64) - 17: StLoc[7](loc4: &u64) - 18: CopyLoc[4](loc1: u64) - 19: MoveLoc[7](loc4: &u64) - 20: Call f3(u64, &u64) - 21: MoveLoc[4](loc1: u64) - 22: StLoc[8](loc5: u64) - 23: MoveLoc[8](loc5: u64) - 24: Ret + 9: CopyLoc[6](loc3: &mut S) + 10: MoveLoc[4](loc1: address) + 11: CopyLoc[3](loc0: u64) + 12: StLoc[7](loc4: u64) + 13: StLoc[8](loc5: address) + 14: StLoc[9](loc6: &mut S) + 15: MoveLoc[5](loc2: address) + 16: MoveLoc[9](loc6: &mut S) + 17: MoveLoc[8](loc5: address) + 18: MoveLoc[7](loc4: u64) + 19: MoveLoc[2](Arg2: &mut S) + 20: Call f2(address, &mut S, address, u64, &mut S) + 21: CopyLoc[3](loc0: u64) + 22: MoveLoc[6](loc3: &mut S) + 23: ImmBorrowField[0](S.g: u64) + 24: Call f3(u64, &u64) + 25: MoveLoc[3](loc0: u64) + 26: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/generic_call.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/generic_call.exp index fc2e7c3271071..953ed238d97bb 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/generic_call.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/generic_call.exp @@ -11,12 +11,9 @@ B0: 2: Ret } identity(Arg0: Ty0): Ty0 /* def_idx: 1 */ { -L1: loc0: Ty0 B0: 0: MoveLoc[0](Arg0: Ty0) - 1: StLoc[1](loc0: Ty0) - 2: MoveLoc[1](loc0: Ty0) - 3: Ret + 1: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/globals.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/globals.exp index bd045f1d4f0fe..b844357e1f32c 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/globals.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/globals.exp @@ -21,15 +21,12 @@ B0: 2: Ret } publish(Arg0: &signer) /* def_idx: 1 */ { -L1: loc0: R B0: - 0: LdU64(1) - 1: Pack[0](R) - 2: StLoc[1](loc0: R) - 3: MoveLoc[0](Arg0: &signer) - 4: MoveLoc[1](loc0: R) - 5: MoveTo[0](R) - 6: Ret + 0: MoveLoc[0](Arg0: &signer) + 1: LdU64(1) + 2: Pack[0](R) + 3: MoveTo[0](R) + 4: Ret } read(Arg0: address): u64 /* def_idx: 2 */ { B0: diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/if_else.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/if_else.exp index 905454c60a8de..7e6a2899f6d6a 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/if_else.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/if_else.exp @@ -6,81 +6,63 @@ module 42.if_else { if_else(Arg0: bool, Arg1: u64): u64 /* def_idx: 0 */ { L2: loc0: u64 -L3: loc1: u64 -L4: loc2: u64 B0: 0: MoveLoc[0](Arg0: bool) - 1: BrFalse(9) + 1: BrFalse(7) B1: - 2: LdU64(1) - 3: StLoc[2](loc0: u64) - 4: MoveLoc[1](Arg1: u64) - 5: MoveLoc[2](loc0: u64) - 6: Add - 7: StLoc[3](loc1: u64) - 8: Branch(15) + 2: MoveLoc[1](Arg1: u64) + 3: LdU64(1) + 4: Add + 5: StLoc[2](loc0: u64) + 6: Branch(11) B2: - 9: LdU64(1) - 10: StLoc[4](loc2: u64) - 11: MoveLoc[1](Arg1: u64) - 12: MoveLoc[4](loc2: u64) - 13: Sub - 14: StLoc[3](loc1: u64) + 7: MoveLoc[1](Arg1: u64) + 8: LdU64(1) + 9: Sub + 10: StLoc[2](loc0: u64) B3: - 15: MoveLoc[3](loc1: u64) - 16: Ret + 11: MoveLoc[2](loc0: u64) + 12: Ret } if_else_nested(Arg0: bool, Arg1: u64): u64 /* def_idx: 1 */ { L2: loc0: u64 L3: loc1: u64 L4: loc2: u64 -L5: loc3: u64 -L6: loc4: u64 -L7: loc5: u64 -L8: loc6: u64 B0: 0: MoveLoc[0](Arg0: bool) - 1: BrFalse(9) + 1: BrFalse(7) B1: - 2: LdU64(1) - 3: StLoc[2](loc0: u64) - 4: CopyLoc[1](Arg1: u64) - 5: MoveLoc[2](loc0: u64) - 6: Add - 7: StLoc[3](loc1: u64) - 8: Branch(15) + 2: CopyLoc[1](Arg1: u64) + 3: LdU64(1) + 4: Add + 5: StLoc[2](loc0: u64) + 6: Branch(11) B2: - 9: LdU64(1) - 10: StLoc[4](loc2: u64) - 11: CopyLoc[1](Arg1: u64) - 12: MoveLoc[4](loc2: u64) - 13: Sub - 14: StLoc[3](loc1: u64) + 7: CopyLoc[1](Arg1: u64) + 8: LdU64(1) + 9: Sub + 10: StLoc[2](loc0: u64) B3: - 15: LdU64(10) - 16: StLoc[5](loc3: u64) - 17: MoveLoc[3](loc1: u64) - 18: MoveLoc[5](loc3: u64) - 19: Gt - 20: BrFalse(28) + 11: LdU64(10) + 12: StLoc[3](loc1: u64) + 13: MoveLoc[2](loc0: u64) + 14: MoveLoc[3](loc1: u64) + 15: Gt + 16: BrFalse(22) B4: - 21: LdU64(2) - 22: StLoc[6](loc4: u64) - 23: MoveLoc[1](Arg1: u64) - 24: MoveLoc[6](loc4: u64) - 25: Mul - 26: StLoc[7](loc5: u64) - 27: Branch(34) + 17: MoveLoc[1](Arg1: u64) + 18: LdU64(2) + 19: Mul + 20: StLoc[4](loc2: u64) + 21: Branch(26) B5: - 28: LdU64(2) - 29: StLoc[8](loc6: u64) - 30: MoveLoc[1](Arg1: u64) - 31: MoveLoc[8](loc6: u64) - 32: Div - 33: StLoc[7](loc5: u64) + 22: MoveLoc[1](Arg1: u64) + 23: LdU64(2) + 24: Div + 25: StLoc[4](loc2: u64) B6: - 34: MoveLoc[7](loc5: u64) - 35: Ret + 26: MoveLoc[4](loc2: u64) + 27: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/loop.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/loop.exp index 2548852af5529..4e092c9ac7c46 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/loop.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/loop.exp @@ -5,140 +5,101 @@ module 42.loops { nested_loop(Arg0: u64): u64 /* def_idx: 0 */ { -L1: loc0: u64 -L2: loc1: u64 -L3: loc2: u64 -L4: loc3: u64 -L5: loc4: u64 B0: - 0: LdU64(0) - 1: StLoc[1](loc0: u64) - 2: CopyLoc[0](Arg0: u64) - 3: MoveLoc[1](loc0: u64) - 4: Gt - 5: BrFalse(30) + 0: CopyLoc[0](Arg0: u64) + 1: LdU64(0) + 2: Gt + 3: BrFalse(22) B1: - 6: LdU64(10) - 7: StLoc[2](loc1: u64) - 8: CopyLoc[0](Arg0: u64) - 9: MoveLoc[2](loc1: u64) - 10: Gt - 11: BrFalse(20) + 4: CopyLoc[0](Arg0: u64) + 5: LdU64(10) + 6: Gt + 7: BrFalse(14) B2: - 12: LdU64(1) - 13: StLoc[3](loc2: u64) - 14: MoveLoc[0](Arg0: u64) - 15: MoveLoc[3](loc2: u64) - 16: Sub - 17: StLoc[0](Arg0: u64) - 18: Branch(22) + 8: MoveLoc[0](Arg0: u64) + 9: LdU64(1) + 10: Sub + 11: StLoc[0](Arg0: u64) + 12: Branch(16) B3: - 19: Branch(21) + 13: Branch(15) B4: - 20: Branch(22) + 14: Branch(16) B5: - 21: Branch(6) + 15: Branch(4) B6: - 22: LdU64(1) - 23: StLoc[4](loc3: u64) - 24: MoveLoc[0](Arg0: u64) - 25: MoveLoc[4](loc3: u64) - 26: Sub - 27: StLoc[0](Arg0: u64) - 28: Branch(0) + 16: MoveLoc[0](Arg0: u64) + 17: LdU64(1) + 18: Sub + 19: StLoc[0](Arg0: u64) + 20: Branch(0) B7: - 29: Branch(31) + 21: Branch(23) B8: - 30: Branch(32) + 22: Branch(24) B9: - 31: Branch(0) + 23: Branch(0) B10: - 32: MoveLoc[0](Arg0: u64) - 33: StLoc[5](loc4: u64) - 34: MoveLoc[5](loc4: u64) - 35: Ret + 24: MoveLoc[0](Arg0: u64) + 25: Ret } while_loop(Arg0: u64): u64 /* def_idx: 1 */ { -L1: loc0: u64 -L2: loc1: u64 -L3: loc2: u64 B0: - 0: LdU64(0) - 1: StLoc[1](loc0: u64) - 2: CopyLoc[0](Arg0: u64) - 3: MoveLoc[1](loc0: u64) - 4: Gt - 5: BrFalse(13) + 0: CopyLoc[0](Arg0: u64) + 1: LdU64(0) + 2: Gt + 3: BrFalse(9) B1: - 6: LdU64(1) - 7: StLoc[2](loc1: u64) - 8: MoveLoc[0](Arg0: u64) - 9: MoveLoc[2](loc1: u64) - 10: Sub - 11: StLoc[0](Arg0: u64) - 12: Branch(14) + 4: MoveLoc[0](Arg0: u64) + 5: LdU64(1) + 6: Sub + 7: StLoc[0](Arg0: u64) + 8: Branch(10) B2: - 13: Branch(15) + 9: Branch(11) B3: - 14: Branch(0) + 10: Branch(0) B4: - 15: MoveLoc[0](Arg0: u64) - 16: StLoc[3](loc2: u64) - 17: MoveLoc[3](loc2: u64) - 18: Ret + 11: MoveLoc[0](Arg0: u64) + 12: Ret } while_loop_with_break_and_continue(Arg0: u64): u64 /* def_idx: 2 */ { -L1: loc0: u64 -L2: loc1: u64 -L3: loc2: u64 -L4: loc3: u64 -L5: loc4: u64 B0: - 0: LdU64(0) - 1: StLoc[1](loc0: u64) - 2: CopyLoc[0](Arg0: u64) - 3: MoveLoc[1](loc0: u64) - 4: Gt - 5: BrFalse(29) + 0: CopyLoc[0](Arg0: u64) + 1: LdU64(0) + 2: Gt + 3: BrFalse(21) B1: - 6: LdU64(42) - 7: StLoc[2](loc1: u64) - 8: CopyLoc[0](Arg0: u64) - 9: MoveLoc[2](loc1: u64) - 10: Eq - 11: BrFalse(14) + 4: CopyLoc[0](Arg0: u64) + 5: LdU64(42) + 6: Eq + 7: BrFalse(10) B2: - 12: Branch(31) + 8: Branch(23) B3: - 13: Branch(14) + 9: Branch(10) B4: - 14: LdU64(21) - 15: StLoc[3](loc2: u64) - 16: CopyLoc[0](Arg0: u64) - 17: MoveLoc[3](loc2: u64) - 18: Eq - 19: BrFalse(22) + 10: CopyLoc[0](Arg0: u64) + 11: LdU64(21) + 12: Eq + 13: BrFalse(16) B5: - 20: Branch(0) + 14: Branch(0) B6: - 21: Branch(22) + 15: Branch(16) B7: - 22: LdU64(1) - 23: StLoc[4](loc3: u64) - 24: MoveLoc[0](Arg0: u64) - 25: MoveLoc[4](loc3: u64) - 26: Sub - 27: StLoc[0](Arg0: u64) - 28: Branch(30) + 16: MoveLoc[0](Arg0: u64) + 17: LdU64(1) + 18: Sub + 19: StLoc[0](Arg0: u64) + 20: Branch(22) B8: - 29: Branch(31) + 21: Branch(23) B9: - 30: Branch(0) + 22: Branch(0) B10: - 31: MoveLoc[0](Arg0: u64) - 32: StLoc[5](loc4: u64) - 33: MoveLoc[5](loc4: u64) - 34: Ret + 23: MoveLoc[0](Arg0: u64) + 24: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/multi_use.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/multi_use.exp index f88ec059166e4..dbad90fc3f4b2 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/multi_use.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/multi_use.exp @@ -9,16 +9,13 @@ B0: 0: Ret } public test(Arg0: u64) /* def_idx: 1 */ { -L1: loc0: u64 B0: - 0: LdU64(1) - 1: StLoc[1](loc0: u64) - 2: CopyLoc[0](Arg0: u64) - 3: CopyLoc[0](Arg0: u64) - 4: MoveLoc[1](loc0: u64) - 5: MoveLoc[0](Arg0: u64) - 6: Call consume(u64, u64, u64, u64) - 7: Ret + 0: CopyLoc[0](Arg0: u64) + 1: CopyLoc[0](Arg0: u64) + 2: LdU64(1) + 3: MoveLoc[0](Arg0: u64) + 4: Call consume(u64, u64, u64, u64) + 5: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/operators.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/operators.exp index d5d0dc85afcf0..313ac0f4abb86 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/operators.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/operators.exp @@ -5,25 +5,19 @@ module 42.operators { arithm(Arg0: u64, Arg1: u64): u64 /* def_idx: 0 */ { -L2: loc0: u64 -L3: loc1: u64 B0: 0: CopyLoc[0](Arg0: u64) 1: CopyLoc[1](Arg1: u64) - 2: Sub - 3: StLoc[2](loc0: u64) - 4: CopyLoc[1](Arg1: u64) - 5: MoveLoc[2](loc0: u64) - 6: Div - 7: MoveLoc[1](Arg1: u64) - 8: Mul - 9: CopyLoc[0](Arg0: u64) - 10: Mod - 11: StLoc[3](loc1: u64) - 12: MoveLoc[0](Arg0: u64) - 13: MoveLoc[3](loc1: u64) - 14: Add - 15: Ret + 2: CopyLoc[0](Arg0: u64) + 3: CopyLoc[1](Arg1: u64) + 4: Sub + 5: Div + 6: MoveLoc[1](Arg1: u64) + 7: Mul + 8: MoveLoc[0](Arg0: u64) + 9: Mod + 10: Add + 11: Ret } bits(Arg0: u64, Arg1: u8): u64 /* def_idx: 1 */ { B0: diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_01.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_01.exp index d036275676863..2c32c62eca7a1 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_01.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_01.exp @@ -9,101 +9,44 @@ B0: 0: Ret } public test01(Arg0: u64) /* def_idx: 1 */ { -L1: loc0: u64 -L2: loc1: u64 -L3: loc2: u64 -L4: loc3: u64 -L5: loc4: u64 B0: - 0: LdU64(1) - 1: LdU64(2) - 2: LdU64(3) - 3: LdU64(4) - 4: LdU64(5) - 5: StLoc[1](loc0: u64) - 6: StLoc[2](loc1: u64) - 7: StLoc[3](loc2: u64) - 8: StLoc[4](loc3: u64) - 9: StLoc[5](loc4: u64) - 10: MoveLoc[0](Arg0: u64) - 11: MoveLoc[5](loc4: u64) - 12: MoveLoc[4](loc3: u64) - 13: MoveLoc[3](loc2: u64) - 14: MoveLoc[2](loc1: u64) - 15: MoveLoc[1](loc0: u64) - 16: Call consume(u64, u64, u64, u64, u64, u64) - 17: Ret + 0: MoveLoc[0](Arg0: u64) + 1: LdU64(1) + 2: LdU64(2) + 3: LdU64(3) + 4: LdU64(4) + 5: LdU64(5) + 6: Call consume(u64, u64, u64, u64, u64, u64) + 7: Ret } public test02(Arg0: u64) /* def_idx: 2 */ { -L1: loc0: u64 -L2: loc1: u64 -L3: loc2: u64 -L4: loc3: u64 B0: - 0: LdU64(1) - 1: LdU64(2) - 2: LdU64(4) - 3: LdU64(5) - 4: StLoc[1](loc0: u64) - 5: StLoc[2](loc1: u64) - 6: StLoc[3](loc2: u64) - 7: StLoc[4](loc3: u64) - 8: CopyLoc[0](Arg0: u64) - 9: MoveLoc[4](loc3: u64) - 10: MoveLoc[3](loc2: u64) - 11: MoveLoc[0](Arg0: u64) - 12: MoveLoc[2](loc1: u64) - 13: MoveLoc[1](loc0: u64) - 14: Call consume(u64, u64, u64, u64, u64, u64) - 15: Ret + 0: CopyLoc[0](Arg0: u64) + 1: LdU64(1) + 2: LdU64(2) + 3: MoveLoc[0](Arg0: u64) + 4: LdU64(4) + 5: LdU64(5) + 6: Call consume(u64, u64, u64, u64, u64, u64) + 7: Ret } public test03(Arg0: u64) /* def_idx: 3 */ { -L1: loc0: u64 -L2: loc1: u64 -L3: loc2: u64 -L4: loc3: u64 -L5: loc4: u64 -L6: loc5: u64 -L7: loc6: u64 -L8: loc7: u64 -L9: loc8: u64 -L10: loc9: u64 B0: - 0: LdU64(1) - 1: LdU64(2) - 2: LdU64(3) - 3: LdU64(4) - 4: LdU64(5) - 5: StLoc[1](loc0: u64) - 6: StLoc[2](loc1: u64) - 7: StLoc[3](loc2: u64) - 8: StLoc[4](loc3: u64) - 9: StLoc[5](loc4: u64) - 10: CopyLoc[0](Arg0: u64) - 11: MoveLoc[5](loc4: u64) - 12: MoveLoc[4](loc3: u64) - 13: MoveLoc[3](loc2: u64) - 14: MoveLoc[2](loc1: u64) - 15: MoveLoc[1](loc0: u64) - 16: Call consume(u64, u64, u64, u64, u64, u64) - 17: LdU64(1) - 18: LdU64(2) - 19: LdU64(3) - 20: LdU64(4) - 21: LdU64(5) - 22: StLoc[6](loc5: u64) - 23: StLoc[7](loc6: u64) - 24: StLoc[8](loc7: u64) - 25: StLoc[9](loc8: u64) - 26: StLoc[10](loc9: u64) - 27: MoveLoc[0](Arg0: u64) - 28: MoveLoc[10](loc9: u64) - 29: MoveLoc[9](loc8: u64) - 30: MoveLoc[8](loc7: u64) - 31: MoveLoc[7](loc6: u64) - 32: MoveLoc[6](loc5: u64) - 33: Call consume(u64, u64, u64, u64, u64, u64) - 34: Ret + 0: CopyLoc[0](Arg0: u64) + 1: LdU64(1) + 2: LdU64(2) + 3: LdU64(3) + 4: LdU64(4) + 5: LdU64(5) + 6: Call consume(u64, u64, u64, u64, u64, u64) + 7: MoveLoc[0](Arg0: u64) + 8: LdU64(1) + 9: LdU64(2) + 10: LdU64(3) + 11: LdU64(4) + 12: LdU64(5) + 13: Call consume(u64, u64, u64, u64, u64, u64) + 14: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_02.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_02.exp index 07e0c3132d79f..ffe373d4103a1 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_02.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_02.exp @@ -29,152 +29,65 @@ B0: 4: Ret } public test01(Arg0: &S) /* def_idx: 3 */ { -L1: loc0: u64 -L2: loc1: u64 -L3: loc2: u64 -L4: loc3: u64 -L5: loc4: u64 B0: - 0: LdU64(1) - 1: LdU64(2) - 2: LdU64(3) - 3: LdU64(4) - 4: LdU64(5) - 5: StLoc[1](loc0: u64) - 6: StLoc[2](loc1: u64) - 7: StLoc[3](loc2: u64) - 8: StLoc[4](loc3: u64) - 9: StLoc[5](loc4: u64) - 10: MoveLoc[0](Arg0: &S) - 11: MoveLoc[5](loc4: u64) - 12: MoveLoc[4](loc3: u64) - 13: MoveLoc[3](loc2: u64) - 14: MoveLoc[2](loc1: u64) - 15: MoveLoc[1](loc0: u64) - 16: Call consume1(&S, u64, u64, u64, u64, u64) - 17: Ret + 0: MoveLoc[0](Arg0: &S) + 1: LdU64(1) + 2: LdU64(2) + 3: LdU64(3) + 4: LdU64(4) + 5: LdU64(5) + 6: Call consume1(&S, u64, u64, u64, u64, u64) + 7: Ret } public test02(Arg0: &S) /* def_idx: 4 */ { -L1: loc0: u64 -L2: loc1: u64 -L3: loc2: u64 -L4: loc3: u64 B0: - 0: LdU64(1) - 1: LdU64(2) - 2: LdU64(4) - 3: LdU64(5) - 4: StLoc[1](loc0: u64) - 5: StLoc[2](loc1: u64) - 6: StLoc[3](loc2: u64) - 7: StLoc[4](loc3: u64) - 8: CopyLoc[0](Arg0: &S) - 9: MoveLoc[4](loc3: u64) - 10: MoveLoc[3](loc2: u64) - 11: MoveLoc[0](Arg0: &S) - 12: MoveLoc[2](loc1: u64) - 13: MoveLoc[1](loc0: u64) - 14: Call consume2(&S, u64, u64, &S, u64, u64) - 15: Ret + 0: CopyLoc[0](Arg0: &S) + 1: LdU64(1) + 2: LdU64(2) + 3: MoveLoc[0](Arg0: &S) + 4: LdU64(4) + 5: LdU64(5) + 6: Call consume2(&S, u64, u64, &S, u64, u64) + 7: Ret } public test03(Arg0: &S) /* def_idx: 5 */ { -L1: loc0: u64 -L2: loc1: u64 -L3: loc2: u64 -L4: loc3: u64 -L5: loc4: u64 -L6: loc5: u64 -L7: loc6: u64 -L8: loc7: u64 -L9: loc8: u64 -L10: loc9: u64 B0: - 0: LdU64(1) - 1: LdU64(2) - 2: LdU64(3) - 3: LdU64(4) - 4: LdU64(5) - 5: StLoc[1](loc0: u64) - 6: StLoc[2](loc1: u64) - 7: StLoc[3](loc2: u64) - 8: StLoc[4](loc3: u64) - 9: StLoc[5](loc4: u64) - 10: CopyLoc[0](Arg0: &S) - 11: MoveLoc[5](loc4: u64) - 12: MoveLoc[4](loc3: u64) - 13: MoveLoc[3](loc2: u64) - 14: MoveLoc[2](loc1: u64) - 15: MoveLoc[1](loc0: u64) - 16: Call consume1(&S, u64, u64, u64, u64, u64) - 17: LdU64(1) - 18: LdU64(2) - 19: LdU64(3) - 20: LdU64(4) - 21: LdU64(5) - 22: StLoc[6](loc5: u64) - 23: StLoc[7](loc6: u64) - 24: StLoc[8](loc7: u64) - 25: StLoc[9](loc8: u64) - 26: StLoc[10](loc9: u64) - 27: MoveLoc[0](Arg0: &S) - 28: MoveLoc[10](loc9: u64) - 29: MoveLoc[9](loc8: u64) - 30: MoveLoc[8](loc7: u64) - 31: MoveLoc[7](loc6: u64) - 32: MoveLoc[6](loc5: u64) - 33: Call consume1(&S, u64, u64, u64, u64, u64) - 34: Ret + 0: CopyLoc[0](Arg0: &S) + 1: LdU64(1) + 2: LdU64(2) + 3: LdU64(3) + 4: LdU64(4) + 5: LdU64(5) + 6: Call consume1(&S, u64, u64, u64, u64, u64) + 7: MoveLoc[0](Arg0: &S) + 8: LdU64(1) + 9: LdU64(2) + 10: LdU64(3) + 11: LdU64(4) + 12: LdU64(5) + 13: Call consume1(&S, u64, u64, u64, u64, u64) + 14: Ret } public test04(Arg0: &S) /* def_idx: 6 */ { -L1: loc0: u64 -L2: loc1: &u64 -L3: loc2: u64 -L4: loc3: u64 -L5: loc4: u64 -L6: loc5: u64 -L7: loc6: u64 -L8: loc7: u64 -L9: loc8: u64 -L10: loc9: u64 B0: - 0: LdU64(1) - 1: LdU64(2) - 2: LdU64(3) - 3: CopyLoc[0](Arg0: &S) - 4: ImmBorrowField[0](S.x: u64) - 5: LdU64(5) - 6: StLoc[1](loc0: u64) - 7: StLoc[2](loc1: &u64) - 8: StLoc[3](loc2: u64) - 9: StLoc[4](loc3: u64) - 10: StLoc[5](loc4: u64) - 11: CopyLoc[0](Arg0: &S) - 12: MoveLoc[5](loc4: u64) - 13: MoveLoc[4](loc3: u64) - 14: MoveLoc[3](loc2: u64) - 15: MoveLoc[2](loc1: &u64) - 16: MoveLoc[1](loc0: u64) - 17: Call consume3(&S, u64, u64, u64, &u64, u64) - 18: LdU64(1) - 19: LdU64(2) - 20: LdU64(3) - 21: CopyLoc[0](Arg0: &S) - 22: ImmBorrowField[0](S.x: u64) - 23: ReadRef - 24: LdU64(5) - 25: StLoc[6](loc5: u64) - 26: StLoc[7](loc6: u64) - 27: StLoc[8](loc7: u64) - 28: StLoc[9](loc8: u64) - 29: StLoc[10](loc9: u64) - 30: MoveLoc[0](Arg0: &S) - 31: MoveLoc[10](loc9: u64) - 32: MoveLoc[9](loc8: u64) - 33: MoveLoc[8](loc7: u64) - 34: MoveLoc[7](loc6: u64) - 35: MoveLoc[6](loc5: u64) - 36: Call consume1(&S, u64, u64, u64, u64, u64) - 37: Ret + 0: CopyLoc[0](Arg0: &S) + 1: LdU64(1) + 2: LdU64(2) + 3: LdU64(3) + 4: CopyLoc[0](Arg0: &S) + 5: ImmBorrowField[0](S.x: u64) + 6: LdU64(5) + 7: Call consume3(&S, u64, u64, u64, &u64, u64) + 8: CopyLoc[0](Arg0: &S) + 9: LdU64(1) + 10: LdU64(2) + 11: LdU64(3) + 12: MoveLoc[0](Arg0: &S) + 13: ImmBorrowField[0](S.x: u64) + 14: ReadRef + 15: LdU64(5) + 16: Call consume1(&S, u64, u64, u64, u64, u64) + 17: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_04.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_04.exp index 42e76e110a911..8b175afa80b86 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_04.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_04.exp @@ -15,20 +15,14 @@ B0: 0: Ret } public foo(Arg0: u64) /* def_idx: 2 */ { -L1: loc0: u64 -L2: loc1: u64 B0: 0: MutBorrowLoc[0](Arg0: u64) 1: Call bar(&mut u64) - 2: LdU64(1) - 3: LdU64(2) - 4: StLoc[1](loc0: u64) - 5: StLoc[2](loc1: u64) - 6: MoveLoc[0](Arg0: u64) - 7: MoveLoc[2](loc1: u64) - 8: MoveLoc[1](loc0: u64) - 9: Call baz(u64, u64, u64) - 10: Ret + 2: MoveLoc[0](Arg0: u64) + 3: LdU64(1) + 4: LdU64(2) + 5: Call baz(u64, u64, u64) + 6: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_05.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_05.exp index 3afc5c9ca65d3..baaf060b97b15 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_05.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/opt_load_05.exp @@ -14,43 +14,40 @@ B0: 1: Ret } public test1(Arg0: u64) /* def_idx: 2 */ { -L1: loc0: u64 B0: - 0: LdU64(1) - 1: StLoc[1](loc0: u64) - 2: CopyLoc[0](Arg0: u64) - 3: MoveLoc[0](Arg0: u64) - 4: MoveLoc[1](loc0: u64) - 5: Call consume1(u64, u64, u64) - 6: Ret + 0: CopyLoc[0](Arg0: u64) + 1: MoveLoc[0](Arg0: u64) + 2: LdU64(1) + 3: Call consume1(u64, u64, u64) + 4: Ret } public test2(Arg0: u64) /* def_idx: 3 */ { -L1: loc0: u64 -L2: loc1: u64 B0: 0: Call one(): u64 - 1: LdU64(2) - 2: StLoc[1](loc0: u64) - 3: StLoc[2](loc1: u64) - 4: MoveLoc[2](loc1: u64) - 5: MoveLoc[0](Arg0: u64) - 6: MoveLoc[1](loc0: u64) - 7: Call consume1(u64, u64, u64) - 8: Ret + 1: MoveLoc[0](Arg0: u64) + 2: LdU64(2) + 3: Call consume1(u64, u64, u64) + 4: Ret } public test3(Arg0: u64) /* def_idx: 4 */ { L1: loc0: u64 L2: loc1: u64 +L3: loc2: u64 +L4: loc3: u64 B0: 0: Call one(): u64 - 1: LdU64(3) + 1: MoveLoc[0](Arg0: u64) 2: StLoc[1](loc0: u64) 3: StLoc[2](loc1: u64) - 4: MoveLoc[0](Arg0: u64) - 5: MoveLoc[2](loc1: u64) - 6: MoveLoc[1](loc0: u64) - 7: Call consume1(u64, u64, u64) - 8: Ret + 4: MoveLoc[2](loc1: u64) + 5: LdU64(3) + 6: StLoc[3](loc2: u64) + 7: StLoc[4](loc3: u64) + 8: MoveLoc[1](loc0: u64) + 9: MoveLoc[4](loc3: u64) + 10: MoveLoc[3](loc2: u64) + 11: Call consume1(u64, u64, u64) + 12: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/pack_order.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/pack_order.exp index de87792e4d59d..c0000ffe2f26a 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/pack_order.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/pack_order.exp @@ -21,64 +21,88 @@ L3: loc0: u8 L4: loc1: u8 B0: 0: MoveLoc[0](Arg0: u8) - 1: StLoc[3](loc0: u8) - 2: MoveLoc[1](Arg1: u8) + 1: MoveLoc[1](Arg1: u8) + 2: StLoc[3](loc0: u8) 3: StLoc[4](loc1: u8) - 4: MoveLoc[3](loc0: u8) + 4: MoveLoc[4](loc1: u8) 5: MoveLoc[2](Arg2: u8) - 6: MoveLoc[4](loc1: u8) + 6: MoveLoc[3](loc0: u8) 7: Pack[0](S) 8: Ret } pack3(Arg0: u8, Arg1: u8, Arg2: u8): S /* def_idx: 2 */ { L3: loc0: u8 +L4: loc1: u8 +L5: loc2: u8 B0: 0: MoveLoc[0](Arg0: u8) - 1: StLoc[3](loc0: u8) - 2: MoveLoc[1](Arg1: u8) - 3: MoveLoc[3](loc0: u8) - 4: MoveLoc[2](Arg2: u8) - 5: Pack[0](S) - 6: Ret + 1: MoveLoc[1](Arg1: u8) + 2: StLoc[3](loc0: u8) + 3: StLoc[4](loc1: u8) + 4: MoveLoc[4](loc1: u8) + 5: StLoc[5](loc2: u8) + 6: MoveLoc[3](loc0: u8) + 7: MoveLoc[5](loc2: u8) + 8: MoveLoc[2](Arg2: u8) + 9: Pack[0](S) + 10: Ret } pack4(Arg0: u8, Arg1: u8, Arg2: u8): S /* def_idx: 3 */ { L3: loc0: u8 L4: loc1: u8 +L5: loc2: u8 +L6: loc3: u8 B0: 0: MoveLoc[0](Arg0: u8) - 1: StLoc[3](loc0: u8) - 2: MoveLoc[1](Arg1: u8) - 3: StLoc[4](loc1: u8) - 4: MoveLoc[2](Arg2: u8) - 5: MoveLoc[3](loc0: u8) - 6: MoveLoc[4](loc1: u8) - 7: Pack[0](S) - 8: Ret + 1: MoveLoc[1](Arg1: u8) + 2: MoveLoc[2](Arg2: u8) + 3: StLoc[3](loc0: u8) + 4: StLoc[4](loc1: u8) + 5: StLoc[5](loc2: u8) + 6: MoveLoc[5](loc2: u8) + 7: StLoc[6](loc3: u8) + 8: MoveLoc[3](loc0: u8) + 9: MoveLoc[6](loc3: u8) + 10: MoveLoc[4](loc1: u8) + 11: Pack[0](S) + 12: Ret } pack5(Arg0: u8, Arg1: u8, Arg2: u8): S /* def_idx: 4 */ { L3: loc0: u8 +L4: loc1: u8 +L5: loc2: u8 B0: 0: MoveLoc[0](Arg0: u8) - 1: StLoc[3](loc0: u8) - 2: MoveLoc[1](Arg1: u8) - 3: MoveLoc[2](Arg2: u8) - 4: MoveLoc[3](loc0: u8) - 5: Pack[0](S) - 6: Ret + 1: MoveLoc[1](Arg1: u8) + 2: MoveLoc[2](Arg2: u8) + 3: StLoc[3](loc0: u8) + 4: StLoc[4](loc1: u8) + 5: StLoc[5](loc2: u8) + 6: MoveLoc[4](loc1: u8) + 7: MoveLoc[3](loc0: u8) + 8: MoveLoc[5](loc2: u8) + 9: Pack[0](S) + 10: Ret } pack6(Arg0: u8, Arg1: u8, Arg2: u8): S /* def_idx: 5 */ { L3: loc0: u8 L4: loc1: u8 +L5: loc2: u8 +L6: loc3: u8 B0: 0: MoveLoc[0](Arg0: u8) - 1: StLoc[3](loc0: u8) - 2: MoveLoc[1](Arg1: u8) - 3: StLoc[4](loc1: u8) - 4: MoveLoc[2](Arg2: u8) + 1: MoveLoc[1](Arg1: u8) + 2: MoveLoc[2](Arg2: u8) + 3: StLoc[3](loc0: u8) + 4: StLoc[4](loc1: u8) 5: MoveLoc[4](loc1: u8) - 6: MoveLoc[3](loc0: u8) - 7: Pack[0](S) - 8: Ret + 6: StLoc[5](loc2: u8) + 7: StLoc[6](loc3: u8) + 8: MoveLoc[3](loc0: u8) + 9: MoveLoc[5](loc2: u8) + 10: MoveLoc[6](loc3: u8) + 11: Pack[0](S) + 12: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/pack_unpack.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/pack_unpack.exp index 7e765c50bc3cb..5ddae932e6e0d 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/pack_unpack.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/pack_unpack.exp @@ -11,21 +11,16 @@ struct S { } pack(Arg0: u64, Arg1: u64): S /* def_idx: 0 */ { -L2: loc0: T B0: - 0: MoveLoc[1](Arg1: u64) - 1: Pack[0](T) - 2: StLoc[2](loc0: T) - 3: MoveLoc[0](Arg0: u64) - 4: MoveLoc[2](loc0: T) - 5: Pack[1](S) - 6: Ret + 0: MoveLoc[0](Arg0: u64) + 1: MoveLoc[1](Arg1: u64) + 2: Pack[0](T) + 3: Pack[1](S) + 4: Ret } unpack(Arg0: S): u64 * u64 /* def_idx: 1 */ { L1: loc0: u64 L2: loc1: u64 -L3: loc2: u64 -L4: loc3: u64 B0: 0: MoveLoc[0](Arg0: S) 1: Unpack[1](S) @@ -33,12 +28,8 @@ B0: 3: StLoc[1](loc0: u64) 4: StLoc[2](loc1: u64) 5: MoveLoc[2](loc1: u64) - 6: StLoc[3](loc2: u64) - 7: MoveLoc[1](loc0: u64) - 8: StLoc[4](loc3: u64) - 9: MoveLoc[3](loc2: u64) - 10: MoveLoc[4](loc3: u64) - 11: Ret + 6: MoveLoc[1](loc0: u64) + 7: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/struct_variants.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/struct_variants.exp index 84c3ab844270c..fee04f8b946f4 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/struct_variants.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/struct_variants.exp @@ -65,6 +65,8 @@ enum Outer { public inner_value(Arg0: Inner): u64 /* def_idx: 0 */ { L1: loc0: &Inner L2: loc1: u64 +L3: loc2: u64 +L4: loc3: u64 B0: 0: ImmBorrowLoc[0](Arg0: Inner) 1: StLoc[1](loc0: &Inner) @@ -77,23 +79,27 @@ B1: 7: MoveLoc[0](Arg0: Inner) 8: UnpackVariant[0](Inner/Inner1) 9: StLoc[2](loc1: u64) - 10: Branch(21) + 10: Branch(25) B2: 11: MoveLoc[1](loc0: &Inner) 12: TestVariant[1](Inner/Inner2) - 13: BrFalse(19) + 13: BrFalse(23) B3: 14: MoveLoc[0](Arg0: Inner) 15: UnpackVariant[1](Inner/Inner2) - 16: Add - 17: StLoc[2](loc1: u64) - 18: Branch(21) + 16: StLoc[3](loc2: u64) + 17: StLoc[4](loc3: u64) + 18: MoveLoc[4](loc3: u64) + 19: MoveLoc[3](loc2: u64) + 20: Add + 21: StLoc[2](loc1: u64) + 22: Branch(25) B4: - 19: LdU64(14566554180833181697) - 20: Abort + 23: LdU64(14566554180833181697) + 24: Abort B5: - 21: MoveLoc[2](loc1: u64) - 22: Ret + 25: MoveLoc[2](loc1: u64) + 26: Ret } public is_inner1(Arg0: &Inner): bool /* def_idx: 1 */ { L1: loc0: bool @@ -152,7 +158,6 @@ B5: } public is_some_dropped(Arg0: Option): bool /* def_idx: 3 */ { L1: loc0: bool -L2: loc1: Option B0: 0: ImmBorrowLoc[0](Arg0: Option) 1: TestVariantGeneric[0](Option/None) @@ -165,9 +170,9 @@ B1: 7: Branch(15) B2: 8: MoveLoc[0](Arg0: Option) - 9: StLoc[2](loc1: Option) - 10: LdTrue - 11: StLoc[1](loc0: bool) + 9: LdTrue + 10: StLoc[1](loc0: bool) + 11: Pop 12: Branch(15) B3: 13: LdU64(14566554180833181697) @@ -361,8 +366,7 @@ B12: public outer_value_with_cond(Arg0: Outer): u64 /* def_idx: 7 */ { L1: loc0: &Outer L2: loc1: u64 -L3: loc2: &Inner -L4: loc3: Box +L3: loc2: Box B0: 0: ImmBorrowLoc[0](Arg0: Outer) 1: StLoc[1](loc0: &Outer) @@ -376,65 +380,63 @@ B1: 8: UnpackVariant[4](Outer/None) 9: LdU64(0) 10: StLoc[2](loc1: u64) - 11: Branch(57) + 11: Branch(55) B2: 12: CopyLoc[1](loc0: &Outer) 13: TestVariant[5](Outer/One) 14: BrTrue(16) B3: - 15: Branch(32) + 15: Branch(30) B4: 16: CopyLoc[1](loc0: &Outer) 17: ImmBorrowVariantField[1](One.i: Inner) - 18: StLoc[3](loc2: &Inner) - 19: MoveLoc[3](loc2: &Inner) - 20: Call is_inner1(&Inner): bool - 21: BrTrue(23) + 18: Call is_inner1(&Inner): bool + 19: BrTrue(21) B5: - 22: Branch(32) + 20: Branch(30) B6: - 23: MoveLoc[1](loc0: &Outer) - 24: Pop - 25: MoveLoc[0](Arg0: Outer) - 26: UnpackVariant[5](Outer/One) - 27: Call inner_value(Inner): u64 - 28: LdU64(2) - 29: Mod - 30: StLoc[2](loc1: u64) - 31: Branch(57) + 21: MoveLoc[1](loc0: &Outer) + 22: Pop + 23: MoveLoc[0](Arg0: Outer) + 24: UnpackVariant[5](Outer/One) + 25: Call inner_value(Inner): u64 + 26: LdU64(2) + 27: Mod + 28: StLoc[2](loc1: u64) + 29: Branch(55) B7: - 32: CopyLoc[1](loc0: &Outer) - 33: TestVariant[5](Outer/One) - 34: BrFalse(42) + 30: CopyLoc[1](loc0: &Outer) + 31: TestVariant[5](Outer/One) + 32: BrFalse(40) B8: - 35: MoveLoc[1](loc0: &Outer) - 36: Pop - 37: MoveLoc[0](Arg0: Outer) - 38: UnpackVariant[5](Outer/One) - 39: Call inner_value(Inner): u64 - 40: StLoc[2](loc1: u64) - 41: Branch(57) + 33: MoveLoc[1](loc0: &Outer) + 34: Pop + 35: MoveLoc[0](Arg0: Outer) + 36: UnpackVariant[5](Outer/One) + 37: Call inner_value(Inner): u64 + 38: StLoc[2](loc1: u64) + 39: Branch(55) B9: - 42: MoveLoc[1](loc0: &Outer) - 43: TestVariant[6](Outer/Two) - 44: BrFalse(55) + 40: MoveLoc[1](loc0: &Outer) + 41: TestVariant[6](Outer/Two) + 42: BrFalse(53) B10: - 45: MoveLoc[0](Arg0: Outer) - 46: UnpackVariant[6](Outer/Two) - 47: StLoc[4](loc3: Box) - 48: Call inner_value(Inner): u64 - 49: ImmBorrowLoc[4](loc3: Box) - 50: ImmBorrowField[0](Box.x: u64) - 51: ReadRef - 52: Add - 53: StLoc[2](loc1: u64) - 54: Branch(57) + 43: MoveLoc[0](Arg0: Outer) + 44: UnpackVariant[6](Outer/Two) + 45: StLoc[3](loc2: Box) + 46: Call inner_value(Inner): u64 + 47: ImmBorrowLoc[3](loc2: Box) + 48: ImmBorrowField[0](Box.x: u64) + 49: ReadRef + 50: Add + 51: StLoc[2](loc1: u64) + 52: Branch(55) B11: - 55: LdU64(14566554180833181697) - 56: Abort + 53: LdU64(14566554180833181697) + 54: Abort B12: - 57: MoveLoc[2](loc1: u64) - 58: Ret + 55: MoveLoc[2](loc1: u64) + 56: Ret } public outer_value_with_cond_ref(Arg0: &Outer): bool /* def_idx: 8 */ { L1: loc0: bool diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/unpack_generic_struct.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/unpack_generic_struct.exp index efb4cdee84f64..a2257aaa12612 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/unpack_generic_struct.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/unpack_generic_struct.exp @@ -29,29 +29,19 @@ B3: 9: Ret } public foo(Arg0: E, Arg1: &mut Ty0) /* def_idx: 1 */ { -L2: loc0: E -L3: loc1: Ty0 -L4: loc2: E -L5: loc3: E -L6: loc4: u64 +L2: loc0: Ty0 B0: 0: MoveLoc[0](Arg0: E) - 1: StLoc[2](loc0: E) - 2: MoveLoc[2](loc0: E) + 1: UnpackGeneric[1](E) + 2: PackGeneric[1](E) 3: UnpackGeneric[1](E) - 4: StLoc[3](loc1: Ty0) - 5: MoveLoc[3](loc1: Ty0) - 6: PackGeneric[1](E) - 7: StLoc[4](loc2: E) - 8: MoveLoc[4](loc2: E) - 9: StLoc[5](loc3: E) - 10: MoveLoc[5](loc3: E) - 11: UnpackGeneric[1](E) - 12: LdU64(3) - 13: StLoc[6](loc4: u64) - 14: MoveLoc[1](Arg1: &mut Ty0) - 15: WriteRef - 16: Ret + 4: LdU64(3) + 5: Pop + 6: StLoc[2](loc0: Ty0) + 7: MoveLoc[2](loc0: Ty0) + 8: MoveLoc[1](Arg1: &mut Ty0) + 9: WriteRef + 10: Ret } public is_none(Arg0: &Option): bool /* def_idx: 2 */ { B0: diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/unpack_generic_struct_typed.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/unpack_generic_struct_typed.exp index efb4cdee84f64..a2257aaa12612 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/unpack_generic_struct_typed.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/unpack_generic_struct_typed.exp @@ -29,29 +29,19 @@ B3: 9: Ret } public foo(Arg0: E, Arg1: &mut Ty0) /* def_idx: 1 */ { -L2: loc0: E -L3: loc1: Ty0 -L4: loc2: E -L5: loc3: E -L6: loc4: u64 +L2: loc0: Ty0 B0: 0: MoveLoc[0](Arg0: E) - 1: StLoc[2](loc0: E) - 2: MoveLoc[2](loc0: E) + 1: UnpackGeneric[1](E) + 2: PackGeneric[1](E) 3: UnpackGeneric[1](E) - 4: StLoc[3](loc1: Ty0) - 5: MoveLoc[3](loc1: Ty0) - 6: PackGeneric[1](E) - 7: StLoc[4](loc2: E) - 8: MoveLoc[4](loc2: E) - 9: StLoc[5](loc3: E) - 10: MoveLoc[5](loc3: E) - 11: UnpackGeneric[1](E) - 12: LdU64(3) - 13: StLoc[6](loc4: u64) - 14: MoveLoc[1](Arg1: &mut Ty0) - 15: WriteRef - 16: Ret + 4: LdU64(3) + 5: Pop + 6: StLoc[2](loc0: Ty0) + 7: MoveLoc[2](loc0: Ty0) + 8: MoveLoc[1](Arg1: &mut Ty0) + 9: WriteRef + 10: Ret } public is_none(Arg0: &Option): bool /* def_idx: 2 */ { B0: diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/vector.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/vector.exp index 5a8df708ab8b8..40b822e92a9a0 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/vector.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/vector.exp @@ -10,64 +10,52 @@ use 0000000000000000000000000000000000000000000000000000000000000001::vector as public remove(Arg0: &mut vector, Arg1: u64): Ty0 /* def_idx: 0 */ { L2: loc0: u64 L3: loc1: u64 -L4: loc2: &mut vector -L5: loc3: u64 -L6: loc4: u64 -L7: loc5: u64 B0: 0: CopyLoc[0](Arg0: &mut vector) 1: FreezeRef 2: VecLen(1) - 3: StLoc[2](loc0: u64) - 4: CopyLoc[1](Arg1: u64) - 5: CopyLoc[2](loc0: u64) - 6: Ge - 7: BrFalse(13) + 3: CopyLoc[1](Arg1: u64) + 4: StLoc[2](loc0: u64) + 5: StLoc[3](loc1: u64) + 6: MoveLoc[2](loc0: u64) + 7: CopyLoc[3](loc1: u64) + 8: Ge + 9: BrFalse(15) B1: - 8: MoveLoc[0](Arg0: &mut vector) - 9: Pop - 10: LdU64(1) - 11: Abort + 10: MoveLoc[0](Arg0: &mut vector) + 11: Pop + 12: LdU64(1) + 13: Abort B2: - 12: Branch(13) + 14: Branch(15) B3: - 13: LdU64(1) - 14: StLoc[3](loc1: u64) - 15: MoveLoc[2](loc0: u64) - 16: MoveLoc[3](loc1: u64) + 15: MoveLoc[3](loc1: u64) + 16: LdU64(1) 17: Sub - 18: StLoc[2](loc0: u64) + 18: StLoc[3](loc1: u64) B4: 19: CopyLoc[1](Arg1: u64) - 20: CopyLoc[2](loc0: u64) + 20: CopyLoc[3](loc1: u64) 21: Lt - 22: BrFalse(40) + 22: BrFalse(32) B5: 23: CopyLoc[0](Arg0: &mut vector) - 24: StLoc[4](loc2: &mut vector) - 25: CopyLoc[1](Arg1: u64) - 26: StLoc[5](loc3: u64) - 27: LdU64(1) - 28: StLoc[6](loc4: u64) - 29: MoveLoc[1](Arg1: u64) - 30: MoveLoc[6](loc4: u64) - 31: Add - 32: StLoc[1](Arg1: u64) - 33: CopyLoc[1](Arg1: u64) - 34: StLoc[7](loc5: u64) - 35: MoveLoc[4](loc2: &mut vector) - 36: MoveLoc[5](loc3: u64) - 37: MoveLoc[7](loc5: u64) - 38: VecSwap(1) - 39: Branch(41) + 24: CopyLoc[1](Arg1: u64) + 25: MoveLoc[1](Arg1: u64) + 26: LdU64(1) + 27: Add + 28: StLoc[1](Arg1: u64) + 29: CopyLoc[1](Arg1: u64) + 30: VecSwap(1) + 31: Branch(33) B6: - 40: Branch(42) + 32: Branch(34) B7: - 41: Branch(19) + 33: Branch(19) B8: - 42: MoveLoc[0](Arg0: &mut vector) - 43: VecPopBack(1) - 44: Ret + 34: MoveLoc[0](Arg0: &mut vector) + 35: VecPopBack(1) + 36: Ret } create(): vector /* def_idx: 1 */ { B0: @@ -78,10 +66,6 @@ test_fold() /* def_idx: 2 */ { L0: loc0: vector L1: loc1: u64 L2: loc2: u64 -L3: loc3: u64 -L4: loc4: u64 -L5: loc5: u64 -L6: loc6: u64 B0: 0: LdU64(0) 1: LdConst[1](Vector(U64): [1, 1, 0, 0, 0, 0, 0, 0, 0]) @@ -97,13 +81,13 @@ B1: B2: 10: MutBorrowLoc[0](loc0: vector) 11: VecPopBack(5) - 12: StLoc[2](loc2: u64) - 13: MoveLoc[1](loc1: u64) - 14: StLoc[3](loc3: u64) + 12: MoveLoc[1](loc1: u64) + 13: Pop + 14: StLoc[2](loc2: u64) 15: MoveLoc[2](loc2: u64) - 16: StLoc[4](loc4: u64) - 17: LdU64(0) - 18: StLoc[1](loc1: u64) + 16: LdU64(0) + 17: StLoc[1](loc1: u64) + 18: Pop 19: Branch(21) B3: 20: Branch(22) @@ -111,20 +95,16 @@ B4: 21: Branch(6) B5: 22: MoveLoc[1](loc1: u64) - 23: StLoc[5](loc5: u64) - 24: LdU64(0) - 25: StLoc[6](loc6: u64) - 26: MoveLoc[5](loc5: u64) - 27: MoveLoc[6](loc6: u64) - 28: Eq - 29: BrFalse(31) + 23: LdU64(0) + 24: Eq + 25: BrFalse(27) B6: - 30: Branch(33) + 26: Branch(29) B7: - 31: LdU64(0) - 32: Abort + 27: LdU64(0) + 28: Abort B8: - 33: Ret + 29: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/duplicate_use.no-opt.exp b/third_party/move/move-compiler-v2/tests/reference-safety/duplicate_use.no-opt.exp index f41849f78bc59..8410c0cfc90a9 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/duplicate_use.no-opt.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/duplicate_use.no-opt.exp @@ -5,6 +5,6 @@ error: cannot transfer mutable local `x` since it is borrowed │ 8 │ mut_ref(x, x) │ ^^^^^^^^^^^^^ - │ │ + │ │ │ + │ │ previously mutably borrowed here │ transfer attempted here - │ previously mutably borrowed here diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/freeze.no-opt.exp b/third_party/move/move-compiler-v2/tests/reference-safety/freeze.no-opt.exp index 773015d0f9c65..8167877ca429b 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/freeze.no-opt.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/freeze.no-opt.exp @@ -5,9 +5,9 @@ error: cannot transfer mutable local `r` since it is borrowed │ 18 │ ref_mut_mut(r, r); // error │ ^^^^^^^^^^^^^^^^^ - │ │ + │ │ │ + │ │ previously mutably borrowed here │ transfer attempted here - │ previously mutably borrowed here error: cannot transfer mutable local `r` since it is borrowed ┌─ tests/reference-safety/freeze.move:24:9 diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/multiple_use_invalid.no-opt.exp b/third_party/move/move-compiler-v2/tests/reference-safety/multiple_use_invalid.no-opt.exp index 56d76e7207b0b..22155231434e2 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/multiple_use_invalid.no-opt.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/multiple_use_invalid.no-opt.exp @@ -9,7 +9,7 @@ error: cannot transfer mutable value since it is borrowed │ │ previously mutably borrowed here │ transfer attempted here -error: cannot transfer mutable local `r` since it is borrowed +error: cannot transfer mutable value since it is borrowed ┌─ tests/reference-safety/multiple_use_invalid.move:11:9 │ 10 │ let x = r; diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/v1-borrow-tests/factor_invalid_1.no-opt.exp b/third_party/move/move-compiler-v2/tests/reference-safety/v1-borrow-tests/factor_invalid_1.no-opt.exp index a37612c579b63..56f4e5f2d3b21 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/v1-borrow-tests/factor_invalid_1.no-opt.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/v1-borrow-tests/factor_invalid_1.no-opt.exp @@ -9,7 +9,7 @@ error: cannot transfer mutable local `f` since it is borrowed 12 │ foo(f_g, f); │ ^^^^^^^^^^^ transfer attempted here -error: cannot transfer mutable local `f` since it is borrowed +error: cannot transfer mutable value since it is borrowed ┌─ tests/reference-safety/v1-borrow-tests/factor_invalid_1.move:22:9 │ 19 │ let f_g = &mut f.g; diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/v1-borrow-tests/imm_borrow_global_invalid.no-opt.exp b/third_party/move/move-compiler-v2/tests/reference-safety/v1-borrow-tests/imm_borrow_global_invalid.no-opt.exp index e9543d2bd3ac1..27c3fd7b6be3a 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/v1-borrow-tests/imm_borrow_global_invalid.no-opt.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/v1-borrow-tests/imm_borrow_global_invalid.no-opt.exp @@ -18,7 +18,7 @@ error: cannot mutably borrow `Tester::Pair` since it is already borrowed 36 │ let p2 = freeze(borrow_global_mut(addr2)); │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow attempted here 37 │ p1 == p2 - │ -------- conflicting reference `p1` used here + │ -- conflicting reference `p1` used here error: cannot mutably borrow `Tester::Pair` since it is already borrowed ┌─ tests/reference-safety/v1-borrow-tests/imm_borrow_global_invalid.move:42:19 @@ -28,4 +28,4 @@ error: cannot mutably borrow `Tester::Pair` since it is already borrowed 42 │ let c2 = &borrow_global_mut(addr2).x; │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow attempted here 43 │ c1 == c2 - │ -------- conflicting reference `c1` used here + │ -- conflicting reference `c1` used here diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_mutual_borrows_invalid.no-opt.exp b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_mutual_borrows_invalid.no-opt.exp index 3c2747e18e2d0..6cf64ef5cb91c 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_mutual_borrows_invalid.no-opt.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_mutual_borrows_invalid.no-opt.exp @@ -1,6 +1,6 @@ Diagnostics: -error: cannot transfer mutable local `s1` since it is borrowed +error: cannot transfer mutable value since it is borrowed ┌─ tests/reference-safety/v1-tests/call_mutual_borrows_invalid.move:15:9 │ 14 │ let f = freeze(s1); @@ -8,7 +8,7 @@ error: cannot transfer mutable local `s1` since it is borrowed 15 │ mut_imm(s1, f); │ ^^^^^^^^^^^^^^ transfer attempted here -error: cannot transfer mutable local `s1` since it is borrowed +error: cannot transfer mutable value since it is borrowed ┌─ tests/reference-safety/v1-tests/call_mutual_borrows_invalid.move:17:9 │ 16 │ let f = &s1.f; @@ -39,11 +39,11 @@ error: cannot transfer mutable local `s1` since it is borrowed │ 23 │ mut_mut(s1, s1); │ ^^^^^^^^^^^^^^^ - │ │ + │ │ │ + │ │ previously mutably borrowed here │ transfer attempted here - │ previously mutably borrowed here -error: cannot transfer mutable local `s1` since it is borrowed +error: cannot transfer mutable value since it is borrowed ┌─ tests/reference-safety/v1-tests/call_mutual_borrows_invalid.move:25:9 │ 24 │ let f = &mut s1.f; @@ -70,7 +70,7 @@ error: cannot transfer mutable local `s1` since it is borrowed 29 │ *s; │ -- conflicting reference `s` used here -error: cannot transfer mutable local `s1` since it is borrowed +error: cannot transfer mutable value since it is borrowed ┌─ tests/reference-safety/v1-tests/call_mutual_borrows_invalid.move:31:9 │ 30 │ let f = id_mut(&mut s1.f); diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/copy_full_invalid.no-opt.exp b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/copy_full_invalid.no-opt.exp index e5fbce1d21b8d..cce03ec82b236 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/copy_full_invalid.no-opt.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/copy_full_invalid.no-opt.exp @@ -6,7 +6,7 @@ error: cannot copy local `x` which is still mutably borrowed 12 │ let f = &mut x; │ ------ local `x` previously mutably borrowed here 13 │ x + 0; - │ ^^^^^ copy attempted here + │ ^ copy attempted here 14 │ *f; │ -- conflicting reference `f` used here @@ -16,6 +16,6 @@ error: cannot copy local `x` which is still mutably borrowed 18 │ let f = id_mut(&mut x); │ -------------- local `x` previously mutably borrowed here 19 │ x + 0; - │ ^^^^^ copy attempted here + │ ^ copy attempted here 20 │ *f; │ -- conflicting reference `f` used here diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/deep_exp.no-optimize.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/deep_exp.no-optimize.exp index 756e53eb56d10..baae5717928b6 100644 --- a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/deep_exp.no-optimize.exp +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/deep_exp.no-optimize.exp @@ -1,23 +1,6 @@ -comparison between v1 and v2 failed: -= processed 2 tasks -= -+ task 0 'publish'. lines 1-28: -+ Error: compilation errors: -+ error: exceeded maximal local count: 255 -+ ┌─ TEMPFILE:19:16 -+ │ -+ 19 │ public fun test(): u64 { -+ │ ^^^^ -+ -+ -+ -= task 1 'run'. lines 30-30: -- return values: 625 -+ Error: Function execution failed with VMError: { -+ major_status: LINKER_ERROR, -+ sub_status: None, -+ location: undefined, -+ indices: redacted, -+ offsets: redacted, -+ } -= +processed 2 tasks + +task 1 'run'. lines 30-30: +return values: 625 + +==> Compiler v2 delivered same results! diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/misc/bitwise_features.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/misc/bitwise_features.exp new file mode 100644 index 0000000000000..a6db107b3b9ca --- /dev/null +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/misc/bitwise_features.exp @@ -0,0 +1,3 @@ +processed 2 tasks + +==> Compiler v2 delivered same results! diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/misc/bitwise_features.move b/third_party/move/move-compiler-v2/transactional-tests/tests/misc/bitwise_features.move new file mode 100644 index 0000000000000..22d826b57cfe9 --- /dev/null +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/misc/bitwise_features.move @@ -0,0 +1,58 @@ +//# publish +module 0x42::TestFeatures { + use std::vector; + + /// The enabled features, represented by a bitset stored on chain. + struct Features has key { + features: vector, + } + + /// Helper to check whether a feature flag is enabled. + fun contains(features: &vector, feature: u64): bool { + let byte_index = feature / 8; + let bit_mask = 1 << ((feature % 8) as u8); + byte_index < vector::length(features) && ((*vector::borrow(features, byte_index))) & bit_mask != 0 + } + + fun set(features: &mut vector, feature: u64, include: bool) { + let old_n = vector::length(features); // ghost var + let _old_features = *features; // ghost var + let n = old_n; // ghost var + + let byte_index = feature / 8; + let bit_mask = 1 << ((feature % 8) as u8); + while ({ + vector::length(features) <= byte_index + }) { + vector::push_back(features, 0); + n = n + 1; + }; + let entry = vector::borrow_mut(features, byte_index); + if (include) + *entry = *entry | bit_mask + else + *entry = *entry & (0xff ^ bit_mask) + } + + public fun enable_feature_flags(enable: vector) acquires Features { + let features = &mut borrow_global_mut(@0xbeef).features; + let i = 0; + let n = vector::length(&enable); + while ({ + i < n + }) { + set(features, *vector::borrow(&enable, i), true); + i = i + 1; + }; + } + + public fun test(s: signer) acquires Features { + move_to(&s, Features { features: vector[1, 2, 3] }); + enable_feature_flags(vector[2]); + assert!(contains(&borrow_global(@0xbeef).features, 2), 0); + assert!(!contains(&borrow_global(@0xbeef).features, 1), 1); + assert!(!contains(&borrow_global(@0xbeef).features, 3), 2); + } +} + +//# run 0x42::TestFeatures::test --signers 0xbeef diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/misc/bug_14243_stack_size.no-optimize.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/misc/bug_14243_stack_size.no-optimize.exp index 478e6e10b07a0..43fa023709801 100644 --- a/third_party/move/move-compiler-v2/transactional-tests/tests/misc/bug_14243_stack_size.no-optimize.exp +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/misc/bug_14243_stack_size.no-optimize.exp @@ -7,13 +7,9 @@ comparison between v1 and v2 failed: = = = id_mut(Arg0: &mut Ty0): &mut Ty0 /* def_idx: 0 */ { -+ L1: loc0: &mut Ty0 = B0: = 0: MoveLoc[0](Arg0: &mut Ty0) -- 1: Ret -+ 1: StLoc[1](loc0: &mut Ty0) -+ 2: MoveLoc[1](loc0: &mut Ty0) -+ 3: Ret += 1: Ret = } = t0() /* def_idx: 1 */ { = L0: loc0: u64 diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/assert_one.no-optimize.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/assert_one.no-optimize.exp index 338c3a8756696..6b808b49a2d81 100644 --- a/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/assert_one.no-optimize.exp +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/assert_one.no-optimize.exp @@ -6,5 +6,5 @@ Error: Script execution failed with VMError: { sub_status: Some(14566554180833181696), location: script, indices: [], - offsets: [(FunctionDefinitionIndex(0), 32)], + offsets: [(FunctionDefinitionIndex(0), 26)], } diff --git a/third_party/move/move-model/bytecode/ast-generator-tests/tests/abort_example.exp b/third_party/move/move-model/bytecode/ast-generator-tests/tests/abort_example.exp index bf73e7d811621..bd030fe155637 100644 --- a/third_party/move/move-model/bytecode/ast-generator-tests/tests/abort_example.exp +++ b/third_party/move/move-model/bytecode/ast-generator-tests/tests/abort_example.exp @@ -12,90 +12,89 @@ public fun f(length: u64): u64 { --- Stackless Bytecode public fun m::f($t0|length: u64): u64 { var $t1|$t3: u64 - var $t2|$t11: u64 [unused] + var $t2: u64 var $t3: u64 - var $t4: u64 - var $t5: bool + var $t4: bool + var $t5: u64 var $t6: u64 - var $t7: u64 - var $t8: bool + var $t7: bool + var $t8: u64 var $t9: u64 var $t10: u64 - var $t11: u64 - var $t12: bool + var $t11: bool + var $t12: u64 var $t13: u64 var $t14: u64 var $t15: u64 var $t16: u64 var $t17: u64 - var $t18: u64 - 0: $t3 := copy($t0) - 1: $t4 := 0 - 2: $t5 := >($t3, $t4) - 3: if ($t5) goto 4 else goto 30 + 0: $t2 := copy($t0) + 1: $t3 := 0 + 2: $t4 := >($t2, $t3) + 3: if ($t4) goto 4 else goto 30 4: label L1 - 5: $t6 := copy($t0) - 6: $t7 := 100 - 7: $t8 := <($t6, $t7) - 8: if ($t8) goto 9 else goto 27 + 5: $t5 := copy($t0) + 6: $t6 := 100 + 7: $t7 := <($t5, $t6) + 8: if ($t7) goto 9 else goto 27 9: label L3 - 10: $t9 := 0 - 11: $t1 := $t9 + 10: $t8 := 0 + 11: $t1 := $t8 12: goto 13 13: label L6 - 14: $t10 := copy($t1) - 15: $t11 := copy($t0) - 16: $t12 := <($t10, $t11) - 17: if ($t12) goto 18 else goto 24 + 14: $t9 := copy($t1) + 15: $t10 := copy($t0) + 16: $t11 := <($t9, $t10) + 17: if ($t11) goto 18 else goto 24 18: label L5 - 19: $t13 := move($t1) - 20: $t14 := 1 - 21: $t15 := +($t13, $t14) - 22: $t1 := $t15 + 19: $t12 := move($t1) + 20: $t13 := 1 + 21: $t14 := +($t12, $t13) + 22: $t1 := $t14 23: goto 13 24: label L4 - 25: $t16 := move($t1) - 26: return $t16 + 25: $t15 := move($t1) + 26: return $t15 27: label L2 - 28: $t17 := 2 - 29: abort($t17) + 28: $t16 := 2 + 29: abort($t16) 30: label L0 - 31: $t18 := 1 - 32: abort($t18) + 31: $t17 := 1 + 32: abort($t17) } --- Raw Generated AST -_t3: u64 = length; -_t4: u64 = 0; -_t5: bool = Gt(_t3, _t4); +_t2: u64 = length; +_t3: u64 = 0; +_t4: bool = Gt(_t2, _t3); loop { - if (_t5) break; - _t18: u64 = 1; - Abort(_t18) + if (_t4) break; + _t17: u64 = 1; + Abort(_t17) }; -_t6: u64 = length; -_t7: u64 = 100; -_t8: bool = Lt(_t6, _t7); +_t5: u64 = length; +_t6: u64 = 100; +_t7: bool = Lt(_t5, _t6); loop { - if (_t8) break; - _t17: u64 = 2; - Abort(_t17) + if (_t7) break; + _t16: u64 = 2; + Abort(_t16) }; -_t9: u64 = 0; -_t1: u64 = _t9; +_t8: u64 = 0; +_t1: u64 = _t8; loop { - _t10: u64 = _t1; - _t11: u64 = length; - _t12: bool = Lt(_t10, _t11); - if (Not(_t12)) break; - _t13: u64 = _t1; - _t14: u64 = 1; - _t15: u64 = Add(_t13, _t14); - _t1: u64 = _t15; + _t9: u64 = _t1; + _t10: u64 = length; + _t11: bool = Lt(_t9, _t10); + if (Not(_t11)) break; + _t12: u64 = _t1; + _t13: u64 = 1; + _t14: u64 = Add(_t12, _t13); + _t1: u64 = _t14; continue }; -_t16: u64 = _t1; -return _t16 +_t15: u64 = _t1; +return _t15 --- Assign-Transformed Generated AST loop { diff --git a/third_party/move/move-model/bytecode/ast-generator-tests/tests/bit_vector_loop_example.exp b/third_party/move/move-model/bytecode/ast-generator-tests/tests/bit_vector_loop_example.exp index 732f4d6f359fb..0d69bba7b69b8 100644 --- a/third_party/move/move-model/bytecode/ast-generator-tests/tests/bit_vector_loop_example.exp +++ b/third_party/move/move-model/bytecode/ast-generator-tests/tests/bit_vector_loop_example.exp @@ -8,68 +8,56 @@ public fun is_index_set(self: &BitVector, bit_index: u64): bool { --- Stackless Bytecode public fun m::is_index_set($t0|self: &0x1::m::BitVector, $t1|bit_index: u64): bool { - var $t2|$t4: u64 - var $t3|$t5: u64 - var $t4: u64 - var $t5: &0x1::m::BitVector - var $t6: &vector - var $t7: u64 - var $t8: u64 + var $t2: u64 + var $t3: &0x1::m::BitVector + var $t4: &vector + var $t5: u64 + var $t6: bool + var $t7: &0x1::m::BitVector + var $t8: &vector var $t9: u64 - var $t10: bool - var $t11: &0x1::m::BitVector - var $t12: &vector + var $t10: &bool + var $t11: bool + var $t12: &0x1::m::BitVector var $t13: u64 - var $t14: &bool - var $t15: bool - var $t16: &0x1::m::BitVector - var $t17: u64 - 0: $t4 := copy($t1) - 1: $t2 := $t4 - 2: $t5 := copy($t0) - 3: $t6 := borrow_field<0x1::m::BitVector>.bit_field($t5) - 4: $t7 := vector::length($t6) - 5: $t3 := $t7 - 6: $t8 := move($t2) - 7: $t9 := move($t3) - 8: $t10 := <($t8, $t9) - 9: if ($t10) goto 10 else goto 17 - 10: label L1 - 11: $t11 := move($t0) - 12: $t12 := borrow_field<0x1::m::BitVector>.bit_field($t11) - 13: $t13 := move($t1) - 14: $t14 := vector::borrow($t12, $t13) - 15: $t15 := read_ref($t14) - 16: return $t15 - 17: label L0 - 18: $t16 := move($t0) - 19: drop($t16) - 20: $t17 := 131072 - 21: abort($t17) + 0: $t2 := copy($t1) + 1: $t3 := copy($t0) + 2: $t4 := borrow_field<0x1::m::BitVector>.bit_field($t3) + 3: $t5 := vector::length($t4) + 4: $t6 := <($t2, $t5) + 5: if ($t6) goto 6 else goto 13 + 6: label L1 + 7: $t7 := move($t0) + 8: $t8 := borrow_field<0x1::m::BitVector>.bit_field($t7) + 9: $t9 := move($t1) + 10: $t10 := vector::borrow($t8, $t9) + 11: $t11 := read_ref($t10) + 12: return $t11 + 13: label L0 + 14: $t12 := move($t0) + 15: drop($t12) + 16: $t13 := 131072 + 17: abort($t13) } --- Raw Generated AST -_t4: u64 = bit_index; -_t2: u64 = _t4; -_t5: &BitVector = self; -_t6: &vector = select m::BitVector.bit_field(_t5); -_t7: u64 = vector::length(_t6); -_t3: u64 = _t7; -_t8: u64 = _t2; -_t9: u64 = _t3; -_t10: bool = Lt(_t8, _t9); +_t2: u64 = bit_index; +_t3: &BitVector = self; +_t4: &vector = select m::BitVector.bit_field(_t3); +_t5: u64 = vector::length(_t4); +_t6: bool = Lt(_t2, _t5); loop { - if (_t10) break; - _t16: &BitVector = self; - _t17: u64 = 131072; - Abort(_t17) + if (_t6) break; + _t12: &BitVector = self; + _t13: u64 = 131072; + Abort(_t13) }; -_t11: &BitVector = self; -_t12: &vector = select m::BitVector.bit_field(_t11); -_t13: u64 = bit_index; -_t14: &bool = vector::borrow(_t12, _t13); -_t15: bool = Deref(_t14); -return _t15 +_t7: &BitVector = self; +_t8: &vector = select m::BitVector.bit_field(_t7); +_t9: u64 = bit_index; +_t10: &bool = vector::borrow(_t8, _t9); +_t11: bool = Deref(_t10); +return _t11 --- Assign-Transformed Generated AST loop { @@ -97,75 +85,63 @@ public fun set(self: &mut BitVector, bit_index: u64) { --- Stackless Bytecode public fun m::set($t0|self: &mut 0x1::m::BitVector, $t1|bit_index: u64) { - var $t2|$t3: u64 - var $t3|$t4: u64 - var $t4|x: &mut bool - var $t5: u64 - var $t6: &mut 0x1::m::BitVector - var $t7: &vector - var $t8: u64 - var $t9: u64 + var $t2|x: &mut bool + var $t3: u64 + var $t4: &mut 0x1::m::BitVector + var $t5: &vector + var $t6: u64 + var $t7: bool + var $t8: &mut 0x1::m::BitVector + var $t9: &mut vector var $t10: u64 - var $t11: bool - var $t12: &mut 0x1::m::BitVector - var $t13: &mut vector - var $t14: u64 - var $t15: &mut bool - var $t16: bool - var $t17: &mut bool - var $t18: &mut 0x1::m::BitVector - var $t19: u64 - 0: $t5 := copy($t1) - 1: $t2 := $t5 - 2: $t6 := copy($t0) - 3: $t7 := borrow_field<0x1::m::BitVector>.bit_field($t6) - 4: $t8 := vector::length($t7) - 5: $t3 := $t8 - 6: $t9 := move($t2) - 7: $t10 := move($t3) - 8: $t11 := <($t9, $t10) - 9: if ($t11) goto 10 else goto 20 - 10: label L1 - 11: $t12 := move($t0) - 12: $t13 := borrow_field<0x1::m::BitVector>.bit_field($t12) - 13: $t14 := move($t1) - 14: $t15 := vector::borrow_mut($t13, $t14) - 15: $t4 := $t15 - 16: $t16 := true - 17: $t17 := move($t4) - 18: write_ref($t17, $t16) - 19: return () - 20: label L0 - 21: $t18 := move($t0) - 22: drop($t18) - 23: $t19 := 131072 - 24: abort($t19) + var $t11: &mut bool + var $t12: bool + var $t13: &mut bool + var $t14: &mut 0x1::m::BitVector + var $t15: u64 + 0: $t3 := copy($t1) + 1: $t4 := copy($t0) + 2: $t5 := borrow_field<0x1::m::BitVector>.bit_field($t4) + 3: $t6 := vector::length($t5) + 4: $t7 := <($t3, $t6) + 5: if ($t7) goto 6 else goto 16 + 6: label L1 + 7: $t8 := move($t0) + 8: $t9 := borrow_field<0x1::m::BitVector>.bit_field($t8) + 9: $t10 := move($t1) + 10: $t11 := vector::borrow_mut($t9, $t10) + 11: $t2 := $t11 + 12: $t12 := true + 13: $t13 := move($t2) + 14: write_ref($t13, $t12) + 15: return () + 16: label L0 + 17: $t14 := move($t0) + 18: drop($t14) + 19: $t15 := 131072 + 20: abort($t15) } --- Raw Generated AST -_t5: u64 = bit_index; -_t2: u64 = _t5; -_t6: &mut BitVector = self; -_t7: &vector = select m::BitVector.bit_field(_t6); -_t8: u64 = vector::length(_t7); -_t3: u64 = _t8; -_t9: u64 = _t2; -_t10: u64 = _t3; -_t11: bool = Lt(_t9, _t10); +_t3: u64 = bit_index; +_t4: &mut BitVector = self; +_t5: &vector = select m::BitVector.bit_field(_t4); +_t6: u64 = vector::length(_t5); +_t7: bool = Lt(_t3, _t6); loop { - if (_t11) break; - _t18: &mut BitVector = self; - _t19: u64 = 131072; - Abort(_t19) + if (_t7) break; + _t14: &mut BitVector = self; + _t15: u64 = 131072; + Abort(_t15) }; -_t12: &mut BitVector = self; -_t13: &mut vector = select m::BitVector.bit_field(_t12); -_t14: u64 = bit_index; -_t15: &mut bool = vector::borrow_mut(_t13, _t14); -_t4: &mut bool = _t15; -_t16: bool = true; -_t17: &mut bool = _t4; -_t17 = _t16; +_t8: &mut BitVector = self; +_t9: &mut vector = select m::BitVector.bit_field(_t8); +_t10: u64 = bit_index; +_t11: &mut bool = vector::borrow_mut(_t9, _t10); +_t2: &mut bool = _t11; +_t12: bool = true; +_t13: &mut bool = _t2; +_t13 = _t12; return Tuple() --- Assign-Transformed Generated AST @@ -214,361 +190,320 @@ public fun shift_left(self: &mut BitVector, amount: u64) { --- Stackless Bytecode public fun m::shift_left($t0|self: &mut 0x1::m::BitVector, $t1|amount: u64) { - var $t2|$t3: u64 - var $t3|$t6: &mut vector - var $t4|$t9: u64 - var $t5|$t10: u64 - var $t6|$t13: &mut bool - var $t7: &mut 0x1::m::BitVector - var $t8: &u64 - var $t9: u64 - var $t10: u64 - var $t11: u64 - var $t12: bool - var $t13: &mut 0x1::m::BitVector + var $t2|$t7: &mut vector + var $t3|$t3: u64 + var $t4|$t14: &mut bool + var $t5: u64 + var $t6: &mut 0x1::m::BitVector + var $t7: &u64 + var $t8: u64 + var $t9: bool + var $t10: &mut 0x1::m::BitVector + var $t11: &mut vector + var $t12: u64 + var $t13: u64 var $t14: &mut vector - var $t15: u64 + var $t15: &vector var $t16: u64 - var $t17: &mut vector - var $t18: &vector + var $t17: bool + var $t18: &mut vector var $t19: u64 - var $t20: u64 - var $t21: u64 - var $t22: bool - var $t23: &mut vector + var $t20: &mut bool + var $t21: bool + var $t22: &mut bool + var $t23: u64 var $t24: u64 - var $t25: &mut bool - var $t26: bool - var $t27: &mut bool + var $t25: u64 + var $t26: &mut vector + var $t27: u64 var $t28: u64 - var $t29: u64 - var $t30: u64 - var $t31: &mut vector - var $t32: u64 + var $t29: &mut 0x1::m::BitVector + var $t30: &u64 + var $t31: u64 + var $t32: bool var $t33: &mut 0x1::m::BitVector - var $t34: &u64 + var $t34: &0x1::m::BitVector var $t35: u64 - var $t36: u64 - var $t37: u64 - var $t38: bool - var $t39: &mut 0x1::m::BitVector - var $t40: &0x1::m::BitVector + var $t36: bool + var $t37: &mut 0x1::m::BitVector + var $t38: u64 + var $t39: u64 + var $t40: u64 var $t41: u64 - var $t42: bool + var $t42: u64 var $t43: u64 - var $t44: u64 + var $t44: &mut 0x1::m::BitVector var $t45: u64 - var $t46: &mut 0x1::m::BitVector + var $t46: u64 var $t47: u64 - var $t48: u64 - var $t49: u64 + var $t48: &mut 0x1::m::BitVector + var $t49: &u64 var $t50: u64 var $t51: u64 var $t52: u64 var $t53: u64 var $t54: &mut 0x1::m::BitVector - var $t55: u64 - var $t56: &mut 0x1::m::BitVector - var $t57: &u64 - var $t58: u64 + var $t55: &u64 + var $t56: u64 + var $t57: bool + var $t58: &mut 0x1::m::BitVector var $t59: u64 var $t60: u64 - var $t61: &mut 0x1::m::BitVector - var $t62: &u64 - var $t63: u64 - var $t64: u64 - var $t65: u64 - var $t66: bool - var $t67: &mut 0x1::m::BitVector - var $t68: u64 - var $t69: u64 - var $t70: u64 - var $t71: u64 - var $t72: &mut 0x1::m::BitVector - 0: $t7 := copy($t0) - 1: $t8 := borrow_field<0x1::m::BitVector>.length($t7) - 2: $t9 := read_ref($t8) - 3: $t2 := $t9 - 4: $t10 := copy($t1) - 5: $t11 := move($t2) - 6: $t12 := >=($t10, $t11) - 7: if ($t12) goto 8 else goto 45 - 8: label L1 - 9: $t13 := move($t0) - 10: $t14 := borrow_field<0x1::m::BitVector>.bit_field($t13) - 11: $t3 := $t14 - 12: $t15 := 0 - 13: $t2 := $t15 - 14: goto 15 - 15: label L4 - 16: $t16 := copy($t2) - 17: $t4 := $t16 - 18: $t17 := copy($t3) - 19: $t18 := freeze_ref($t17) - 20: $t19 := vector::length($t18) - 21: $t5 := $t19 - 22: $t20 := move($t4) - 23: $t21 := move($t5) - 24: $t22 := <($t20, $t21) - 25: if ($t22) goto 26 else goto 39 - 26: label L3 - 27: $t23 := copy($t3) - 28: $t24 := copy($t2) - 29: $t25 := vector::borrow_mut($t23, $t24) - 30: $t6 := $t25 - 31: $t26 := false - 32: $t27 := move($t6) - 33: write_ref($t27, $t26) - 34: $t28 := move($t2) - 35: $t29 := 1 - 36: $t30 := +($t28, $t29) - 37: $t2 := $t30 - 38: goto 15 - 39: label L2 - 40: $t31 := move($t3) - 41: drop($t31) + var $t61: u64 + var $t62: u64 + var $t63: &mut 0x1::m::BitVector + 0: $t5 := copy($t1) + 1: $t6 := copy($t0) + 2: $t7 := borrow_field<0x1::m::BitVector>.length($t6) + 3: $t8 := read_ref($t7) + 4: $t9 := >=($t5, $t8) + 5: if ($t9) goto 6 else goto 39 + 6: label L1 + 7: $t10 := move($t0) + 8: $t11 := borrow_field<0x1::m::BitVector>.bit_field($t10) + 9: $t2 := $t11 + 10: $t12 := 0 + 11: $t3 := $t12 + 12: goto 13 + 13: label L4 + 14: $t13 := copy($t3) + 15: $t14 := copy($t2) + 16: $t15 := freeze_ref($t14) + 17: $t16 := vector::length($t15) + 18: $t17 := <($t13, $t16) + 19: if ($t17) goto 20 else goto 33 + 20: label L3 + 21: $t18 := copy($t2) + 22: $t19 := copy($t3) + 23: $t20 := vector::borrow_mut($t18, $t19) + 24: $t4 := $t20 + 25: $t21 := false + 26: $t22 := move($t4) + 27: write_ref($t22, $t21) + 28: $t23 := move($t3) + 29: $t24 := 1 + 30: $t25 := +($t23, $t24) + 31: $t3 := $t25 + 32: goto 13 + 33: label L2 + 34: $t26 := move($t2) + 35: drop($t26) + 36: goto 37 + 37: label L14 + 38: return () + 39: label L0 + 40: $t27 := copy($t1) + 41: $t3 := $t27 42: goto 43 - 43: label L14 - 44: return () - 45: label L0 - 46: $t32 := copy($t1) - 47: $t2 := $t32 - 48: goto 49 - 49: label L9 - 50: $t33 := copy($t0) - 51: $t34 := borrow_field<0x1::m::BitVector>.length($t33) - 52: $t35 := read_ref($t34) - 53: $t4 := $t35 - 54: $t36 := copy($t2) - 55: $t37 := move($t4) - 56: $t38 := <($t36, $t37) - 57: if ($t38) goto 58 else goto 88 - 58: label L6 - 59: $t39 := copy($t0) - 60: $t40 := freeze_ref($t39) - 61: $t41 := copy($t2) - 62: $t42 := m::is_index_set($t40, $t41) - 63: if ($t42) goto 64 else goto 79 - 64: label L8 - 65: $t43 := copy($t2) - 66: $t44 := copy($t1) - 67: $t45 := -($t43, $t44) - 68: $t4 := $t45 - 69: $t46 := copy($t0) - 70: $t47 := move($t4) - 71: m::set($t46, $t47) - 72: goto 73 - 73: label L10 - 74: $t48 := move($t2) - 75: $t49 := 1 - 76: $t50 := +($t48, $t49) - 77: $t2 := $t50 - 78: goto 49 - 79: label L7 - 80: $t51 := copy($t2) - 81: $t52 := copy($t1) - 82: $t53 := -($t51, $t52) - 83: $t4 := $t53 - 84: $t54 := copy($t0) - 85: $t55 := move($t4) - 86: m::unset($t54, $t55) - 87: goto 73 - 88: label L5 - 89: $t56 := copy($t0) - 90: $t57 := borrow_field<0x1::m::BitVector>.length($t56) - 91: $t58 := read_ref($t57) - 92: $t59 := move($t1) - 93: $t60 := -($t58, $t59) - 94: $t2 := $t60 - 95: goto 96 - 96: label L13 - 97: $t61 := copy($t0) - 98: $t62 := borrow_field<0x1::m::BitVector>.length($t61) - 99: $t63 := read_ref($t62) -100: $t1 := $t63 -101: $t64 := copy($t2) -102: $t65 := move($t1) -103: $t66 := <($t64, $t65) -104: if ($t66) goto 105 else goto 114 -105: label L12 -106: $t67 := copy($t0) -107: $t68 := copy($t2) -108: m::unset($t67, $t68) -109: $t69 := move($t2) -110: $t70 := 1 -111: $t71 := +($t69, $t70) -112: $t2 := $t71 -113: goto 96 -114: label L11 -115: $t72 := move($t0) -116: drop($t72) -117: goto 43 + 43: label L9 + 44: $t28 := copy($t3) + 45: $t29 := copy($t0) + 46: $t30 := borrow_field<0x1::m::BitVector>.length($t29) + 47: $t31 := read_ref($t30) + 48: $t32 := <($t28, $t31) + 49: if ($t32) goto 50 else goto 76 + 50: label L6 + 51: $t33 := copy($t0) + 52: $t34 := freeze_ref($t33) + 53: $t35 := copy($t3) + 54: $t36 := m::is_index_set($t34, $t35) + 55: if ($t36) goto 56 else goto 69 + 56: label L8 + 57: $t37 := copy($t0) + 58: $t38 := copy($t3) + 59: $t39 := copy($t1) + 60: $t40 := -($t38, $t39) + 61: m::set($t37, $t40) + 62: goto 63 + 63: label L10 + 64: $t41 := move($t3) + 65: $t42 := 1 + 66: $t43 := +($t41, $t42) + 67: $t3 := $t43 + 68: goto 43 + 69: label L7 + 70: $t44 := copy($t0) + 71: $t45 := copy($t3) + 72: $t46 := copy($t1) + 73: $t47 := -($t45, $t46) + 74: m::unset($t44, $t47) + 75: goto 63 + 76: label L5 + 77: $t48 := copy($t0) + 78: $t49 := borrow_field<0x1::m::BitVector>.length($t48) + 79: $t50 := read_ref($t49) + 80: $t51 := move($t1) + 81: $t52 := -($t50, $t51) + 82: $t3 := $t52 + 83: goto 84 + 84: label L13 + 85: $t53 := copy($t3) + 86: $t54 := copy($t0) + 87: $t55 := borrow_field<0x1::m::BitVector>.length($t54) + 88: $t56 := read_ref($t55) + 89: $t57 := <($t53, $t56) + 90: if ($t57) goto 91 else goto 100 + 91: label L12 + 92: $t58 := copy($t0) + 93: $t59 := copy($t3) + 94: m::unset($t58, $t59) + 95: $t60 := move($t3) + 96: $t61 := 1 + 97: $t62 := +($t60, $t61) + 98: $t3 := $t62 + 99: goto 84 +100: label L11 +101: $t63 := move($t0) +102: drop($t63) +103: goto 37 } --- Raw Generated AST -_t7: &mut BitVector = self; -_t8: &u64 = select m::BitVector.length(_t7); -_t9: u64 = Deref(_t8); -_t2: u64 = _t9; -_t10: u64 = amount; -_t11: u64 = _t2; -_t12: bool = Ge(_t10, _t11); +_t5: u64 = amount; +_t6: &mut BitVector = self; +_t7: &u64 = select m::BitVector.length(_t6); +_t8: u64 = Deref(_t7); +_t9: bool = Ge(_t5, _t8); loop { loop { loop { loop { - if (Not(_t12)) break; - _t13: &mut BitVector = self; - _t14: &mut vector = select m::BitVector.bit_field(_t13); - _t3: &mut vector = _t14; - _t15: u64 = 0; - _t2: u64 = _t15; + if (Not(_t9)) break; + _t10: &mut BitVector = self; + _t11: &mut vector = select m::BitVector.bit_field(_t10); + _t2: &mut vector = _t11; + _t12: u64 = 0; + _t3: u64 = _t12; break[1] }; - _t32: u64 = amount; - _t2: u64 = _t32; + _t27: u64 = amount; + _t3: u64 = _t27; break[1] }; loop { - _t16: u64 = _t2; - _t4: u64 = _t16; - _t17: &mut vector = _t3; - _t18: &vector = Freeze(true)(_t17); - _t19: u64 = vector::length(_t18); - _t5: u64 = _t19; - _t20: u64 = _t4; - _t21: u64 = _t5; - _t22: bool = Lt(_t20, _t21); - if (Not(_t22)) break; - _t23: &mut vector = _t3; - _t24: u64 = _t2; - _t25: &mut bool = vector::borrow_mut(_t23, _t24); - _t6: &mut bool = _t25; - _t26: bool = false; - _t27: &mut bool = _t6; - _t27 = _t26; - _t28: u64 = _t2; - _t29: u64 = 1; - _t30: u64 = Add(_t28, _t29); - _t2: u64 = _t30; + _t13: u64 = _t3; + _t14: &mut vector = _t2; + _t15: &vector = Freeze(true)(_t14); + _t16: u64 = vector::length(_t15); + _t17: bool = Lt(_t13, _t16); + if (Not(_t17)) break; + _t18: &mut vector = _t2; + _t19: u64 = _t3; + _t20: &mut bool = vector::borrow_mut(_t18, _t19); + _t4: &mut bool = _t20; + _t21: bool = false; + _t22: &mut bool = _t4; + _t22 = _t21; + _t23: u64 = _t3; + _t24: u64 = 1; + _t25: u64 = Add(_t23, _t24); + _t3: u64 = _t25; continue }; - _t31: &mut vector = _t3; + _t26: &mut vector = _t2; break[1] }; loop { + _t28: u64 = _t3; + _t29: &mut BitVector = self; + _t30: &u64 = select m::BitVector.length(_t29); + _t31: u64 = Deref(_t30); + _t32: bool = Lt(_t28, _t31); + if (Not(_t32)) break; _t33: &mut BitVector = self; - _t34: &u64 = select m::BitVector.length(_t33); - _t35: u64 = Deref(_t34); - _t4: u64 = _t35; - _t36: u64 = _t2; - _t37: u64 = _t4; - _t38: bool = Lt(_t36, _t37); - if (Not(_t38)) break; - _t39: &mut BitVector = self; - _t40: &BitVector = Freeze(true)(_t39); - _t41: u64 = _t2; - _t42: bool = m::is_index_set(_t40, _t41); + _t34: &BitVector = Freeze(true)(_t33); + _t35: u64 = _t3; + _t36: bool = m::is_index_set(_t34, _t35); loop { loop { - if (Not(_t42)) break; - _t43: u64 = _t2; - _t44: u64 = amount; - _t45: u64 = Sub(_t43, _t44); - _t4: u64 = _t45; - _t46: &mut BitVector = self; - _t47: u64 = _t4; - m::set(_t46, _t47); + if (Not(_t36)) break; + _t37: &mut BitVector = self; + _t38: u64 = _t3; + _t39: u64 = amount; + _t40: u64 = Sub(_t38, _t39); + m::set(_t37, _t40); break[1] }; - _t51: u64 = _t2; - _t52: u64 = amount; - _t53: u64 = Sub(_t51, _t52); - _t4: u64 = _t53; - _t54: &mut BitVector = self; - _t55: u64 = _t4; - m::unset(_t54, _t55); + _t44: &mut BitVector = self; + _t45: u64 = _t3; + _t46: u64 = amount; + _t47: u64 = Sub(_t45, _t46); + m::unset(_t44, _t47); break }; - _t48: u64 = _t2; - _t49: u64 = 1; - _t50: u64 = Add(_t48, _t49); - _t2: u64 = _t50; + _t41: u64 = _t3; + _t42: u64 = 1; + _t43: u64 = Add(_t41, _t42); + _t3: u64 = _t43; continue }; - _t56: &mut BitVector = self; - _t57: &u64 = select m::BitVector.length(_t56); - _t58: u64 = Deref(_t57); - _t59: u64 = amount; - _t60: u64 = Sub(_t58, _t59); - _t2: u64 = _t60; + _t48: &mut BitVector = self; + _t49: &u64 = select m::BitVector.length(_t48); + _t50: u64 = Deref(_t49); + _t51: u64 = amount; + _t52: u64 = Sub(_t50, _t51); + _t3: u64 = _t52; loop { - _t61: &mut BitVector = self; - _t62: &u64 = select m::BitVector.length(_t61); - _t63: u64 = Deref(_t62); - amount: u64 = _t63; - _t64: u64 = _t2; - _t65: u64 = amount; - _t66: bool = Lt(_t64, _t65); - if (Not(_t66)) break; - _t67: &mut BitVector = self; - _t68: u64 = _t2; - m::unset(_t67, _t68); - _t69: u64 = _t2; - _t70: u64 = 1; - _t71: u64 = Add(_t69, _t70); - _t2: u64 = _t71; + _t53: u64 = _t3; + _t54: &mut BitVector = self; + _t55: &u64 = select m::BitVector.length(_t54); + _t56: u64 = Deref(_t55); + _t57: bool = Lt(_t53, _t56); + if (Not(_t57)) break; + _t58: &mut BitVector = self; + _t59: u64 = _t3; + m::unset(_t58, _t59); + _t60: u64 = _t3; + _t61: u64 = 1; + _t62: u64 = Add(_t60, _t61); + _t3: u64 = _t62; continue }; - _t72: &mut BitVector = self; + _t63: &mut BitVector = self; break }; return Tuple() --- Assign-Transformed Generated AST -_t2: u64 = Deref(select m::BitVector.length(self)); loop { loop { loop { loop { - if (Not(Ge(amount, _t2))) break; - _t3: &mut vector = select m::BitVector.bit_field(self); - _t2: u64 = 0; + if (Not(Ge(amount, Deref(select m::BitVector.length(self))))) break; + _t2: &mut vector = select m::BitVector.bit_field(self); + _t3: u64 = 0; break[1] }; - _t2: u64 = amount; + _t3: u64 = amount; break[1] }; loop { - if (Not(Lt(_t2, vector::length(Freeze(true)(_t3))))) break; - vector::borrow_mut(_t3, _t2) = false; - _t2: u64 = Add(_t2, 1); + if (Not(Lt(_t3, vector::length(Freeze(true)(_t2))))) break; + vector::borrow_mut(_t2, _t3) = false; + _t3: u64 = Add(_t3, 1); continue }; break[1] }; loop { - _t4: u64 = Deref(select m::BitVector.length(self)); - if (Not(Lt(_t2, _t4))) break; + if (Not(Lt(_t3, Deref(select m::BitVector.length(self))))) break; loop { loop { - if (Not(m::is_index_set(Freeze(true)(self), _t2))) break; - _t4: u64 = Sub(_t2, amount); - m::set(self, _t4); + if (Not(m::is_index_set(Freeze(true)(self), _t3))) break; + m::set(self, Sub(_t3, amount)); break[1] }; - _t4: u64 = Sub(_t2, amount); - m::unset(self, _t4); + m::unset(self, Sub(_t3, amount)); break }; - _t2: u64 = Add(_t2, 1); + _t3: u64 = Add(_t3, 1); continue }; - _t2: u64 = Sub(Deref(select m::BitVector.length(self)), amount); + _t3: u64 = Sub(Deref(select m::BitVector.length(self)), amount); loop { - if (Not(Lt(_t2, Deref(select m::BitVector.length(self))))) break; - m::unset(self, _t2); - _t2: u64 = Add(_t2, 1); + if (Not(Lt(_t3, Deref(select m::BitVector.length(self))))) break; + m::unset(self, _t3); + _t3: u64 = Add(_t3, 1); continue }; break @@ -576,42 +511,38 @@ loop { return Tuple() --- If-Transformed Generated AST -_t2: u64 = Deref(select m::BitVector.length(self)); loop { loop { - if Ge(amount, _t2) { - _t3: &mut vector = select m::BitVector.bit_field(self); - _t2: u64 = 0 + if Ge(amount, Deref(select m::BitVector.length(self))) { + _t2: &mut vector = select m::BitVector.bit_field(self); + _t3: u64 = 0 } else { - _t2: u64 = amount; + _t3: u64 = amount; break }; loop { - if (Not(Lt(_t2, vector::length(Freeze(true)(_t3))))) break; - vector::borrow_mut(_t3, _t2) = false; - _t2: u64 = Add(_t2, 1); + if (Not(Lt(_t3, vector::length(Freeze(true)(_t2))))) break; + vector::borrow_mut(_t2, _t3) = false; + _t3: u64 = Add(_t3, 1); continue }; break[1] }; loop { - _t4: u64 = Deref(select m::BitVector.length(self)); - if (Not(Lt(_t2, _t4))) break; - if m::is_index_set(Freeze(true)(self), _t2) { - _t4: u64 = Sub(_t2, amount); - m::set(self, _t4) + if (Not(Lt(_t3, Deref(select m::BitVector.length(self))))) break; + if m::is_index_set(Freeze(true)(self), _t3) { + m::set(self, Sub(_t3, amount)) } else { - _t4: u64 = Sub(_t2, amount); - m::unset(self, _t4) + m::unset(self, Sub(_t3, amount)) }; - _t2: u64 = Add(_t2, 1); + _t3: u64 = Add(_t3, 1); continue }; - _t2: u64 = Sub(Deref(select m::BitVector.length(self)), amount); + _t3: u64 = Sub(Deref(select m::BitVector.length(self)), amount); loop { - if (Not(Lt(_t2, Deref(select m::BitVector.length(self))))) break; - m::unset(self, _t2); - _t2: u64 = Add(_t2, 1); + if (Not(Lt(_t3, Deref(select m::BitVector.length(self))))) break; + m::unset(self, _t3); + _t3: u64 = Add(_t3, 1); continue }; break @@ -620,53 +551,46 @@ return Tuple() --- Var-Bound Generated AST { - let _t4: u64; + let _t3: u64; { - let _t3: &mut vector; - { - let _t2: u64; - _t2: u64 = Deref(select m::BitVector.length(self)); + let _t2: &mut vector; + loop { loop { - loop { - if Ge(amount, _t2) { - _t3: &mut vector = select m::BitVector.bit_field(self); - _t2: u64 = 0 - } else { - _t2: u64 = amount; - break - }; - loop { - if (Not(Lt(_t2, vector::length(Freeze(true)(_t3))))) break; - vector::borrow_mut(_t3, _t2) = false; - _t2: u64 = Add(_t2, 1); - continue - }; - break[1] + if Ge(amount, Deref(select m::BitVector.length(self))) { + _t2: &mut vector = select m::BitVector.bit_field(self); + _t3: u64 = 0 + } else { + _t3: u64 = amount; + break }; loop { - _t4: u64 = Deref(select m::BitVector.length(self)); - if (Not(Lt(_t2, _t4))) break; - if m::is_index_set(Freeze(true)(self), _t2) { - _t4: u64 = Sub(_t2, amount); - m::set(self, _t4) - } else { - _t4: u64 = Sub(_t2, amount); - m::unset(self, _t4) - }; - _t2: u64 = Add(_t2, 1); + if (Not(Lt(_t3, vector::length(Freeze(true)(_t2))))) break; + vector::borrow_mut(_t2, _t3) = false; + _t3: u64 = Add(_t3, 1); continue }; - _t2: u64 = Sub(Deref(select m::BitVector.length(self)), amount); - loop { - if (Not(Lt(_t2, Deref(select m::BitVector.length(self))))) break; - m::unset(self, _t2); - _t2: u64 = Add(_t2, 1); - continue + break[1] + }; + loop { + if (Not(Lt(_t3, Deref(select m::BitVector.length(self))))) break; + if m::is_index_set(Freeze(true)(self), _t3) { + m::set(self, Sub(_t3, amount)) + } else { + m::unset(self, Sub(_t3, amount)) }; - break + _t3: u64 = Add(_t3, 1); + continue }; - return Tuple() - } + _t3: u64 = Sub(Deref(select m::BitVector.length(self)), amount); + loop { + if (Not(Lt(_t3, Deref(select m::BitVector.length(self))))) break; + m::unset(self, _t3); + _t3: u64 = Add(_t3, 1); + continue + }; + break + }; + return Tuple() } } @@ -681,75 +605,63 @@ public fun unset(self: &mut BitVector, bit_index: u64) { --- Stackless Bytecode public fun m::unset($t0|self: &mut 0x1::m::BitVector, $t1|bit_index: u64) { - var $t2|$t3: u64 - var $t3|$t4: u64 - var $t4|x: &mut bool - var $t5: u64 - var $t6: &mut 0x1::m::BitVector - var $t7: &vector - var $t8: u64 - var $t9: u64 + var $t2|x: &mut bool + var $t3: u64 + var $t4: &mut 0x1::m::BitVector + var $t5: &vector + var $t6: u64 + var $t7: bool + var $t8: &mut 0x1::m::BitVector + var $t9: &mut vector var $t10: u64 - var $t11: bool - var $t12: &mut 0x1::m::BitVector - var $t13: &mut vector - var $t14: u64 - var $t15: &mut bool - var $t16: bool - var $t17: &mut bool - var $t18: &mut 0x1::m::BitVector - var $t19: u64 - 0: $t5 := copy($t1) - 1: $t2 := $t5 - 2: $t6 := copy($t0) - 3: $t7 := borrow_field<0x1::m::BitVector>.bit_field($t6) - 4: $t8 := vector::length($t7) - 5: $t3 := $t8 - 6: $t9 := move($t2) - 7: $t10 := move($t3) - 8: $t11 := <($t9, $t10) - 9: if ($t11) goto 10 else goto 20 - 10: label L1 - 11: $t12 := move($t0) - 12: $t13 := borrow_field<0x1::m::BitVector>.bit_field($t12) - 13: $t14 := move($t1) - 14: $t15 := vector::borrow_mut($t13, $t14) - 15: $t4 := $t15 - 16: $t16 := false - 17: $t17 := move($t4) - 18: write_ref($t17, $t16) - 19: return () - 20: label L0 - 21: $t18 := move($t0) - 22: drop($t18) - 23: $t19 := 131072 - 24: abort($t19) + var $t11: &mut bool + var $t12: bool + var $t13: &mut bool + var $t14: &mut 0x1::m::BitVector + var $t15: u64 + 0: $t3 := copy($t1) + 1: $t4 := copy($t0) + 2: $t5 := borrow_field<0x1::m::BitVector>.bit_field($t4) + 3: $t6 := vector::length($t5) + 4: $t7 := <($t3, $t6) + 5: if ($t7) goto 6 else goto 16 + 6: label L1 + 7: $t8 := move($t0) + 8: $t9 := borrow_field<0x1::m::BitVector>.bit_field($t8) + 9: $t10 := move($t1) + 10: $t11 := vector::borrow_mut($t9, $t10) + 11: $t2 := $t11 + 12: $t12 := false + 13: $t13 := move($t2) + 14: write_ref($t13, $t12) + 15: return () + 16: label L0 + 17: $t14 := move($t0) + 18: drop($t14) + 19: $t15 := 131072 + 20: abort($t15) } --- Raw Generated AST -_t5: u64 = bit_index; -_t2: u64 = _t5; -_t6: &mut BitVector = self; -_t7: &vector = select m::BitVector.bit_field(_t6); -_t8: u64 = vector::length(_t7); -_t3: u64 = _t8; -_t9: u64 = _t2; -_t10: u64 = _t3; -_t11: bool = Lt(_t9, _t10); +_t3: u64 = bit_index; +_t4: &mut BitVector = self; +_t5: &vector = select m::BitVector.bit_field(_t4); +_t6: u64 = vector::length(_t5); +_t7: bool = Lt(_t3, _t6); loop { - if (_t11) break; - _t18: &mut BitVector = self; - _t19: u64 = 131072; - Abort(_t19) + if (_t7) break; + _t14: &mut BitVector = self; + _t15: u64 = 131072; + Abort(_t15) }; -_t12: &mut BitVector = self; -_t13: &mut vector = select m::BitVector.bit_field(_t12); -_t14: u64 = bit_index; -_t15: &mut bool = vector::borrow_mut(_t13, _t14); -_t4: &mut bool = _t15; -_t16: bool = false; -_t17: &mut bool = _t4; -_t17 = _t16; +_t8: &mut BitVector = self; +_t9: &mut vector = select m::BitVector.bit_field(_t8); +_t10: u64 = bit_index; +_t11: &mut bool = vector::borrow_mut(_t9, _t10); +_t2: &mut bool = _t11; +_t12: bool = false; +_t13: &mut bool = _t2; +_t13 = _t12; return Tuple() --- Assign-Transformed Generated AST @@ -785,41 +697,31 @@ module 0x1::m { *0x1::vector::borrow_mut(&mut self.bit_field, bit_index) = true; } public fun shift_left(self: &mut BitVector, amount: u64) { - let _t4; let _t3; let _t2; - _t2 = *&self.length; 'l0: loop { loop { - if (amount >= _t2) { - _t3 = &mut self.bit_field; - _t2 = 0 + if (amount >= *&self.length) { + _t2 = &mut self.bit_field; + _t3 = 0 } else { - _t2 = amount; + _t3 = amount; break }; - while (_t2 < 0x1::vector::length(/*freeze*/_t3)) { - *0x1::vector::borrow_mut(_t3, _t2) = false; - _t2 = _t2 + 1 + while (_t3 < 0x1::vector::length(/*freeze*/_t2)) { + *0x1::vector::borrow_mut(_t2, _t3) = false; + _t3 = _t3 + 1 }; break 'l0 }; - loop { - _t4 = *&self.length; - if (!(_t2 < _t4)) break; - if (is_index_set(/*freeze*/self, _t2)) { - _t4 = _t2 - amount; - set(self, _t4) - } else { - _t4 = _t2 - amount; - unset(self, _t4) - }; - _t2 = _t2 + 1 + while (_t3 < *&self.length) { + if (is_index_set(/*freeze*/self, _t3)) set(self, _t3 - amount) else unset(self, _t3 - amount); + _t3 = _t3 + 1 }; - _t2 = *&self.length - amount; - while (_t2 < *&self.length) { - unset(self, _t2); - _t2 = _t2 + 1 + _t3 = *&self.length - amount; + while (_t3 < *&self.length) { + unset(self, _t3); + _t3 = _t3 + 1 }; break }; diff --git a/third_party/move/move-model/bytecode/ast-generator-tests/tests/conditionals.exp b/third_party/move/move-model/bytecode/ast-generator-tests/tests/conditionals.exp index be960ad6afff7..e094abccf4145 100644 --- a/third_party/move/move-model/bytecode/ast-generator-tests/tests/conditionals.exp +++ b/third_party/move/move-model/bytecode/ast-generator-tests/tests/conditionals.exp @@ -264,41 +264,40 @@ fun if_else_3(c: bool): u64 { --- Stackless Bytecode fun m::if_else_3($t0|c: bool): u64 { var $t1|r: u64 - var $t2|return: u64 [unused] - var $t3: bool + var $t2: bool + var $t3: u64 var $t4: u64 var $t5: u64 - var $t6: u64 - 0: $t3 := move($t0) - 1: if ($t3) goto 2 else goto 9 + 0: $t2 := move($t0) + 1: if ($t2) goto 2 else goto 9 2: label L1 - 3: $t4 := 1 - 4: $t1 := $t4 + 3: $t3 := 1 + 4: $t1 := $t3 5: goto 6 6: label L2 - 7: $t5 := move($t1) - 8: return $t5 + 7: $t4 := move($t1) + 8: return $t4 9: label L0 - 10: $t6 := 2 - 11: $t1 := $t6 + 10: $t5 := 2 + 11: $t1 := $t5 12: goto 6 } --- Raw Generated AST -_t3: bool = c; +_t2: bool = c; loop { loop { - if (Not(_t3)) break; - _t4: u64 = 1; - _t1: u64 = _t4; + if (Not(_t2)) break; + _t3: u64 = 1; + _t1: u64 = _t3; break[1] }; - _t6: u64 = 2; - _t1: u64 = _t6; + _t5: u64 = 2; + _t1: u64 = _t5; break }; -_t5: u64 = _t1; -return _t5 +_t4: u64 = _t1; +return _t4 --- Assign-Transformed Generated AST loop { @@ -453,8 +452,8 @@ fun if_else_with_shared_exp(x: u64): u64 { --- Stackless Bytecode fun m::if_else_with_shared_exp($t0|x: u64): u64 { - var $t1|$t5: u64 - var $t2|$t7: u64 [unused] + var $t1|$t3: u64 + var $t2: u64 var $t3: u64 var $t4: u64 var $t5: u64 @@ -462,73 +461,72 @@ fun m::if_else_with_shared_exp($t0|x: u64): u64 { var $t7: u64 var $t8: u64 var $t9: u64 - var $t10: u64 - var $t11: bool + var $t10: bool + var $t11: u64 var $t12: u64 var $t13: u64 var $t14: u64 var $t15: u64 var $t16: u64 var $t17: u64 - var $t18: u64 - 0: $t3 := copy($t0) - 1: $t4 := move($t0) - 2: $t5 := +($t3, $t4) - 3: $t0 := $t5 - 4: $t6 := copy($t0) - 5: $t7 := move($t0) - 6: $t8 := *($t6, $t7) - 7: $t0 := $t8 - 8: $t9 := copy($t0) - 9: $t10 := 0 - 10: $t11 := >($t9, $t10) - 11: if ($t11) goto 12 else goto 21 + 0: $t2 := copy($t0) + 1: $t3 := move($t0) + 2: $t4 := +($t2, $t3) + 3: $t0 := $t4 + 4: $t5 := copy($t0) + 5: $t6 := move($t0) + 6: $t7 := *($t5, $t6) + 7: $t0 := $t7 + 8: $t8 := copy($t0) + 9: $t9 := 0 + 10: $t10 := >($t8, $t9) + 11: if ($t10) goto 12 else goto 21 12: label L1 - 13: $t12 := move($t0) - 14: $t13 := 1 - 15: $t14 := +($t12, $t13) - 16: $t1 := $t14 + 13: $t11 := move($t0) + 14: $t12 := 1 + 15: $t13 := +($t11, $t12) + 16: $t1 := $t13 17: goto 18 18: label L2 - 19: $t15 := move($t1) - 20: return $t15 + 19: $t14 := move($t1) + 20: return $t14 21: label L0 - 22: $t16 := move($t0) - 23: $t17 := 1 - 24: $t18 := -($t16, $t17) - 25: $t1 := $t18 + 22: $t15 := move($t0) + 23: $t16 := 1 + 24: $t17 := -($t15, $t16) + 25: $t1 := $t17 26: goto 18 } --- Raw Generated AST +_t2: u64 = x; _t3: u64 = x; -_t4: u64 = x; -_t5: u64 = Add(_t3, _t4); -x: u64 = _t5; +_t4: u64 = Add(_t2, _t3); +x: u64 = _t4; +_t5: u64 = x; _t6: u64 = x; -_t7: u64 = x; -_t8: u64 = Mul(_t6, _t7); -x: u64 = _t8; -_t9: u64 = x; -_t10: u64 = 0; -_t11: bool = Gt(_t9, _t10); +_t7: u64 = Mul(_t5, _t6); +x: u64 = _t7; +_t8: u64 = x; +_t9: u64 = 0; +_t10: bool = Gt(_t8, _t9); loop { loop { - if (Not(_t11)) break; - _t12: u64 = x; - _t13: u64 = 1; - _t14: u64 = Add(_t12, _t13); - _t1: u64 = _t14; + if (Not(_t10)) break; + _t11: u64 = x; + _t12: u64 = 1; + _t13: u64 = Add(_t11, _t12); + _t1: u64 = _t13; break[1] }; - _t16: u64 = x; - _t17: u64 = 1; - _t18: u64 = Sub(_t16, _t17); - _t1: u64 = _t18; + _t15: u64 = x; + _t16: u64 = 1; + _t17: u64 = Sub(_t15, _t16); + _t1: u64 = _t17; break }; -_t15: u64 = _t1; -return _t15 +_t14: u64 = _t1; +return _t14 --- Assign-Transformed Generated AST x: u64 = Add(x, x); diff --git a/third_party/move/move-model/bytecode/ast-generator-tests/tests/loops.exp b/third_party/move/move-model/bytecode/ast-generator-tests/tests/loops.exp index 77603ad0468e7..ef55daa883f37 100644 --- a/third_party/move/move-model/bytecode/ast-generator-tests/tests/loops.exp +++ b/third_party/move/move-model/bytecode/ast-generator-tests/tests/loops.exp @@ -13,79 +13,78 @@ fun loop_1(c: u64): u64 { --- Stackless Bytecode fun m::loop_1($t0|c: u64): u64 { - var $t1|$t3: u64 [unused] + var $t1: u64 var $t2: u64 var $t3: u64 var $t4: u64 var $t5: u64 var $t6: u64 var $t7: u64 - var $t8: u64 - var $t9: bool + var $t8: bool + var $t9: u64 var $t10: u64 var $t11: u64 var $t12: u64 var $t13: u64 var $t14: u64 var $t15: u64 - var $t16: u64 - var $t17: bool - var $t18: u64 + var $t16: bool + var $t17: u64 0: label L2 - 1: $t2 := move($t0) - 2: $t3 := 1 - 3: $t4 := +($t2, $t3) - 4: $t0 := $t4 - 5: $t5 := copy($t0) - 6: $t6 := 2 - 7: $t7 := %($t5, $t6) - 8: $t8 := 0 - 9: $t9 := ==($t7, $t8) - 10: if ($t9) goto 11 else goto 13 + 1: $t1 := move($t0) + 2: $t2 := 1 + 3: $t3 := +($t1, $t2) + 4: $t0 := $t3 + 5: $t4 := copy($t0) + 6: $t5 := 2 + 7: $t6 := %($t4, $t5) + 8: $t7 := 0 + 9: $t8 := ==($t6, $t7) + 10: if ($t8) goto 11 else goto 13 11: label L1 12: goto 0 13: label L0 - 14: $t10 := move($t0) - 15: $t11 := 3 - 16: $t12 := +($t10, $t11) - 17: $t0 := $t12 - 18: $t13 := copy($t0) - 19: $t14 := 2 - 20: $t15 := %($t13, $t14) - 21: $t16 := 1 - 22: $t17 := ==($t15, $t16) - 23: if ($t17) goto 24 else goto 0 + 14: $t9 := move($t0) + 15: $t10 := 3 + 16: $t11 := +($t9, $t10) + 17: $t0 := $t11 + 18: $t12 := copy($t0) + 19: $t13 := 2 + 20: $t14 := %($t12, $t13) + 21: $t15 := 1 + 22: $t16 := ==($t14, $t15) + 23: if ($t16) goto 24 else goto 0 24: label L3 - 25: $t18 := move($t0) - 26: return $t18 + 25: $t17 := move($t0) + 26: return $t17 } --- Raw Generated AST loop { - _t2: u64 = c; - _t3: u64 = 1; - _t4: u64 = Add(_t2, _t3); - c: u64 = _t4; - _t5: u64 = c; - _t6: u64 = 2; - _t7: u64 = Mod(_t5, _t6); - _t8: u64 = 0; - _t9: bool = Eq(_t7, _t8); - if (_t9) continue; - _t10: u64 = c; - _t11: u64 = 3; - _t12: u64 = Add(_t10, _t11); - c: u64 = _t12; - _t13: u64 = c; - _t14: u64 = 2; - _t15: u64 = Mod(_t13, _t14); - _t16: u64 = 1; - _t17: bool = Eq(_t15, _t16); - if (Not(_t17)) continue; + _t1: u64 = c; + _t2: u64 = 1; + _t3: u64 = Add(_t1, _t2); + c: u64 = _t3; + _t4: u64 = c; + _t5: u64 = 2; + _t6: u64 = Mod(_t4, _t5); + _t7: u64 = 0; + _t8: bool = Eq(_t6, _t7); + if (_t8) continue; + _t9: u64 = c; + _t10: u64 = 3; + _t11: u64 = Add(_t9, _t10); + c: u64 = _t11; + _t12: u64 = c; + _t13: u64 = 2; + _t14: u64 = Mod(_t12, _t13); + _t15: u64 = 1; + _t16: bool = Eq(_t14, _t15); + if (Not(_t16)) continue; break }; -_t18: u64 = c; -return _t18 +_t17: u64 = c; +return _t17 --- Assign-Transformed Generated AST loop { @@ -134,72 +133,71 @@ fun nested_loop(x: u64): u64 { --- Stackless Bytecode fun m::nested_loop($t0|x: u64): u64 { - var $t1|$t3: u64 [unused] + var $t1: u64 var $t2: u64 - var $t3: u64 - var $t4: bool + var $t3: bool + var $t4: u64 var $t5: u64 - var $t6: u64 - var $t7: bool + var $t6: bool + var $t7: u64 var $t8: u64 var $t9: u64 var $t10: u64 var $t11: u64 var $t12: u64 var $t13: u64 - var $t14: u64 0: label L5 - 1: $t2 := copy($t0) - 2: $t3 := 0 - 3: $t4 := >($t2, $t3) - 4: if ($t4) goto 5 else goto 22 + 1: $t1 := copy($t0) + 2: $t2 := 0 + 3: $t3 := >($t1, $t2) + 4: if ($t3) goto 5 else goto 22 5: label L1 - 6: $t5 := copy($t0) - 7: $t6 := 10 - 8: $t7 := >($t5, $t6) - 9: if ($t7) goto 10 else goto 16 + 6: $t4 := copy($t0) + 7: $t5 := 10 + 8: $t6 := >($t4, $t5) + 9: if ($t6) goto 10 else goto 16 10: label L2 - 11: $t8 := move($t0) - 12: $t9 := 1 - 13: $t10 := -($t8, $t9) - 14: $t0 := $t10 + 11: $t7 := move($t0) + 12: $t8 := 1 + 13: $t9 := -($t7, $t8) + 14: $t0 := $t9 15: goto 16 16: label L4 - 17: $t11 := move($t0) - 18: $t12 := 1 - 19: $t13 := -($t11, $t12) - 20: $t0 := $t13 + 17: $t10 := move($t0) + 18: $t11 := 1 + 19: $t12 := -($t10, $t11) + 20: $t0 := $t12 21: goto 0 22: label L0 - 23: $t14 := move($t0) - 24: return $t14 + 23: $t13 := move($t0) + 24: return $t13 } --- Raw Generated AST loop { - _t2: u64 = x; - _t3: u64 = 0; - _t4: bool = Gt(_t2, _t3); - if (Not(_t4)) break; - _t5: u64 = x; - _t6: u64 = 10; - _t7: bool = Gt(_t5, _t6); + _t1: u64 = x; + _t2: u64 = 0; + _t3: bool = Gt(_t1, _t2); + if (Not(_t3)) break; + _t4: u64 = x; + _t5: u64 = 10; + _t6: bool = Gt(_t4, _t5); loop { - if (Not(_t7)) break; - _t8: u64 = x; - _t9: u64 = 1; - _t10: u64 = Sub(_t8, _t9); - x: u64 = _t10; + if (Not(_t6)) break; + _t7: u64 = x; + _t8: u64 = 1; + _t9: u64 = Sub(_t7, _t8); + x: u64 = _t9; break }; - _t11: u64 = x; - _t12: u64 = 1; - _t13: u64 = Sub(_t11, _t12); - x: u64 = _t13; + _t10: u64 = x; + _t11: u64 = 1; + _t12: u64 = Sub(_t10, _t11); + x: u64 = _t12; continue }; -_t14: u64 = x; -return _t14 +_t13: u64 = x; +return _t13 --- Assign-Transformed Generated AST loop { @@ -241,23 +239,22 @@ fun while_1(c: u64) { --- Stackless Bytecode fun m::while_1($t0|c: u64) { - var $t1|$t2: u64 [unused] + var $t1: u64 var $t2: u64 - var $t3: u64 - var $t4: bool + var $t3: bool + var $t4: u64 var $t5: u64 var $t6: u64 - var $t7: u64 0: label L2 - 1: $t2 := copy($t0) - 2: $t3 := 0 - 3: $t4 := >($t2, $t3) - 4: if ($t4) goto 5 else goto 11 + 1: $t1 := copy($t0) + 2: $t2 := 0 + 3: $t3 := >($t1, $t2) + 4: if ($t3) goto 5 else goto 11 5: label L1 - 6: $t5 := move($t0) - 7: $t6 := 1 - 8: $t7 := -($t5, $t6) - 9: $t0 := $t7 + 6: $t4 := move($t0) + 7: $t5 := 1 + 8: $t6 := -($t4, $t5) + 9: $t0 := $t6 10: goto 0 11: label L0 12: return () @@ -265,14 +262,14 @@ fun m::while_1($t0|c: u64) { --- Raw Generated AST loop { - _t2: u64 = c; - _t3: u64 = 0; - _t4: bool = Gt(_t2, _t3); - if (Not(_t4)) break; - _t5: u64 = c; - _t6: u64 = 1; - _t7: u64 = Sub(_t5, _t6); - c: u64 = _t7; + _t1: u64 = c; + _t2: u64 = 0; + _t3: bool = Gt(_t1, _t2); + if (Not(_t3)) break; + _t4: u64 = c; + _t5: u64 = 1; + _t6: u64 = Sub(_t4, _t5); + c: u64 = _t6; continue }; return Tuple() @@ -316,62 +313,61 @@ fun while_2(c: u64): u64 { --- Stackless Bytecode fun m::while_2($t0|c: u64): u64 { - var $t1|$t3: u64 [unused] + var $t1: u64 var $t2: u64 - var $t3: u64 - var $t4: bool + var $t3: bool + var $t4: u64 var $t5: u64 - var $t6: u64 - var $t7: bool + var $t6: bool + var $t7: u64 var $t8: u64 var $t9: u64 var $t10: u64 var $t11: u64 var $t12: u64 - var $t13: u64 0: label L4 - 1: $t2 := copy($t0) - 2: $t3 := 0 - 3: $t4 := >($t2, $t3) - 4: if ($t4) goto 5 else goto 16 + 1: $t1 := copy($t0) + 2: $t2 := 0 + 3: $t3 := >($t1, $t2) + 4: if ($t3) goto 5 else goto 16 5: label L1 - 6: $t5 := copy($t0) - 7: $t6 := 10 - 8: $t7 := >=($t5, $t6) - 9: if ($t7) goto 10 else goto 0 + 6: $t4 := copy($t0) + 7: $t5 := 10 + 8: $t6 := >=($t4, $t5) + 9: if ($t6) goto 10 else goto 0 10: label L2 - 11: $t8 := move($t0) - 12: $t9 := 10 - 13: $t10 := -($t8, $t9) - 14: $t0 := $t10 + 11: $t7 := move($t0) + 12: $t8 := 10 + 13: $t9 := -($t7, $t8) + 14: $t0 := $t9 15: goto 0 16: label L0 - 17: $t11 := move($t0) - 18: $t12 := 1 - 19: $t13 := +($t11, $t12) - 20: return $t13 + 17: $t10 := move($t0) + 18: $t11 := 1 + 19: $t12 := +($t10, $t11) + 20: return $t12 } --- Raw Generated AST loop { - _t2: u64 = c; - _t3: u64 = 0; - _t4: bool = Gt(_t2, _t3); - if (Not(_t4)) break; - _t5: u64 = c; - _t6: u64 = 10; - _t7: bool = Ge(_t5, _t6); - if (Not(_t7)) continue; - _t8: u64 = c; - _t9: u64 = 10; - _t10: u64 = Sub(_t8, _t9); - c: u64 = _t10; + _t1: u64 = c; + _t2: u64 = 0; + _t3: bool = Gt(_t1, _t2); + if (Not(_t3)) break; + _t4: u64 = c; + _t5: u64 = 10; + _t6: bool = Ge(_t4, _t5); + if (Not(_t6)) continue; + _t7: u64 = c; + _t8: u64 = 10; + _t9: u64 = Sub(_t7, _t8); + c: u64 = _t9; continue }; -_t11: u64 = c; -_t12: u64 = 1; -_t13: u64 = Add(_t11, _t12); -return _t13 +_t10: u64 = c; +_t11: u64 = 1; +_t12: u64 = Add(_t10, _t11); +return _t12 --- Assign-Transformed Generated AST loop { @@ -413,74 +409,73 @@ fun while_3(c: u64): u64 { --- Stackless Bytecode fun m::while_3($t0|c: u64): u64 { - var $t1|$t3: u64 [unused] + var $t1: u64 var $t2: u64 - var $t3: u64 - var $t4: bool + var $t3: bool + var $t4: u64 var $t5: u64 - var $t6: u64 - var $t7: bool + var $t6: bool + var $t7: u64 var $t8: u64 var $t9: u64 var $t10: u64 var $t11: u64 var $t12: u64 var $t13: u64 - var $t14: u64 0: label L5 - 1: $t2 := copy($t0) - 2: $t3 := 0 - 3: $t4 := >($t2, $t3) - 4: if ($t4) goto 5 else goto 24 + 1: $t1 := copy($t0) + 2: $t2 := 0 + 3: $t3 := >($t1, $t2) + 4: if ($t3) goto 5 else goto 24 5: label L1 6: goto 7 7: label L2 - 8: $t5 := copy($t0) - 9: $t6 := 10 - 10: $t7 := >($t5, $t6) - 11: if ($t7) goto 12 else goto 18 + 8: $t4 := copy($t0) + 9: $t5 := 10 + 10: $t6 := >($t4, $t5) + 11: if ($t6) goto 12 else goto 18 12: label L4 - 13: $t8 := move($t0) - 14: $t9 := 10 - 15: $t10 := -($t8, $t9) - 16: $t0 := $t10 + 13: $t7 := move($t0) + 14: $t8 := 10 + 15: $t9 := -($t7, $t8) + 16: $t0 := $t9 17: goto 7 18: label L3 - 19: $t11 := move($t0) - 20: $t12 := 1 - 21: $t13 := -($t11, $t12) - 22: $t0 := $t13 + 19: $t10 := move($t0) + 20: $t11 := 1 + 21: $t12 := -($t10, $t11) + 22: $t0 := $t12 23: goto 0 24: label L0 - 25: $t14 := move($t0) - 26: return $t14 + 25: $t13 := move($t0) + 26: return $t13 } --- Raw Generated AST loop { - _t2: u64 = c; - _t3: u64 = 0; - _t4: bool = Gt(_t2, _t3); - if (Not(_t4)) break; + _t1: u64 = c; + _t2: u64 = 0; + _t3: bool = Gt(_t1, _t2); + if (Not(_t3)) break; loop { - _t5: u64 = c; - _t6: u64 = 10; - _t7: bool = Gt(_t5, _t6); - if (Not(_t7)) break; - _t8: u64 = c; - _t9: u64 = 10; - _t10: u64 = Sub(_t8, _t9); - c: u64 = _t10; + _t4: u64 = c; + _t5: u64 = 10; + _t6: bool = Gt(_t4, _t5); + if (Not(_t6)) break; + _t7: u64 = c; + _t8: u64 = 10; + _t9: u64 = Sub(_t7, _t8); + c: u64 = _t9; continue }; - _t11: u64 = c; - _t12: u64 = 1; - _t13: u64 = Sub(_t11, _t12); - c: u64 = _t13; + _t10: u64 = c; + _t11: u64 = 1; + _t12: u64 = Sub(_t10, _t11); + c: u64 = _t12; continue }; -_t14: u64 = c; -return _t14 +_t13: u64 = c; +return _t13 --- Assign-Transformed Generated AST loop { diff --git a/third_party/move/move-prover/tests/sources/functional/ModifiesErrorTest.v2_exp b/third_party/move/move-prover/tests/sources/functional/ModifiesErrorTest.v2_exp index 620e4ee6a4e64..4e9f110a47a40 100644 --- a/third_party/move/move-prover/tests/sources/functional/ModifiesErrorTest.v2_exp +++ b/third_party/move/move-prover/tests/sources/functional/ModifiesErrorTest.v2_exp @@ -28,7 +28,6 @@ error: caller does not have permission to modify `B::T` at given address = at tests/sources/functional/ModifiesErrorTest.move:51: move_to_test_incorrect = x0 = = at tests/sources/functional/ModifiesErrorTest.move:52: move_to_test_incorrect - = = error: caller does not have permission to modify `B::T` at given address ┌─ tests/sources/functional/ModifiesErrorTest.move:65:17 diff --git a/third_party/move/move-prover/tests/sources/functional/ModifiesSchemaTest.v2_exp b/third_party/move/move-prover/tests/sources/functional/ModifiesSchemaTest.v2_exp index 1a1a7100ee0d3..2c4601d2f5bfb 100644 --- a/third_party/move/move-prover/tests/sources/functional/ModifiesSchemaTest.v2_exp +++ b/third_party/move/move-prover/tests/sources/functional/ModifiesSchemaTest.v2_exp @@ -14,7 +14,7 @@ error: caller does not have permission to modify `A::S` at given address = at tests/sources/functional/ModifiesSchemaTest.move:12: mutate_at = addr = = at tests/sources/functional/ModifiesSchemaTest.move:13: mutate_at + = s = = at tests/sources/functional/ModifiesSchemaTest.move:14: mutate_at - = = = at tests/sources/functional/ModifiesSchemaTest.move:15: mutate_at = at tests/sources/functional/ModifiesSchemaTest.move:31: mutate_at_wrapper2 diff --git a/third_party/move/move-prover/tests/sources/functional/address_quant.v2_exp b/third_party/move/move-prover/tests/sources/functional/address_quant.v2_exp index 34e81d4b92112..427ee8258709d 100644 --- a/third_party/move/move-prover/tests/sources/functional/address_quant.v2_exp +++ b/third_party/move/move-prover/tests/sources/functional/address_quant.v2_exp @@ -11,6 +11,5 @@ error: post-condition does not hold = at tests/sources/functional/address_quant.move:46: multiple_copy_incorrect = sndr = = at tests/sources/functional/address_quant.move:47: multiple_copy_incorrect - = = = at tests/sources/functional/address_quant.move:48: multiple_copy_incorrect = at tests/sources/functional/address_quant.move:53 diff --git a/third_party/move/move-prover/tests/sources/functional/bitwise_features.v2_exp b/third_party/move/move-prover/tests/sources/functional/bitwise_features.v2_exp new file mode 100644 index 0000000000000..5910dbdcebcb8 --- /dev/null +++ b/third_party/move/move-prover/tests/sources/functional/bitwise_features.v2_exp @@ -0,0 +1,12 @@ +Move prover returns: exiting with verification errors +error: verification out of resources/timeout (global timeout set to 80s) + ┌─ tests/sources/functional/bitwise_features.move:154:5 + │ +154 │ ╭ public fun enable_feature_flags(enable: vector) acquires Features { +155 │ │ let features = &mut borrow_global_mut(@std).features; +156 │ │ let i = 0; +157 │ │ let n = vector::length(&enable); + · │ +170 │ │ }; +171 │ │ } + │ ╰─────^ diff --git a/third_party/move/move-prover/tests/sources/functional/choice.v2_exp b/third_party/move/move-prover/tests/sources/functional/choice.v2_exp index 8717b9158c33c..12365e40fda49 100644 --- a/third_party/move/move-prover/tests/sources/functional/choice.v2_exp +++ b/third_party/move/move-prover/tests/sources/functional/choice.v2_exp @@ -29,9 +29,7 @@ error: post-condition does not hold = s1 = = s2 = = at tests/sources/functional/choice.move:47: populate_R - = = = at tests/sources/functional/choice.move:48: populate_R - = = = at tests/sources/functional/choice.move:49: populate_R = at tests/sources/functional/choice.move:56: populate_R (spec) @@ -129,7 +127,6 @@ error: post-condition does not hold = ballot_account = = at tests/sources/functional/choice.move:284: create_ballot = at tests/sources/functional/choice.move:283: create_ballot - = = = at tests/sources/functional/choice.move:291 = at tests/sources/functional/choice.move:286: create_ballot = at tests/sources/functional/choice.move:272: new_ballot_id diff --git a/third_party/move/move-prover/tests/sources/functional/data_invariant_for_mut_ref_arg.v2_exp b/third_party/move/move-prover/tests/sources/functional/data_invariant_for_mut_ref_arg.v2_exp index 82b4721661b3f..2b5c25e3f356d 100644 --- a/third_party/move/move-prover/tests/sources/functional/data_invariant_for_mut_ref_arg.v2_exp +++ b/third_party/move/move-prover/tests/sources/functional/data_invariant_for_mut_ref_arg.v2_exp @@ -42,8 +42,6 @@ error: data invariant does not hold = at tests/sources/functional/data_invariant_for_mut_ref_arg.move:33: push_3 = at tests/sources/functional/data_invariant_for_mut_ref_arg.move:35: push_3 = s = - = at tests/sources/functional/data_invariant_for_mut_ref_arg.move:36: push_3 - = return = = at tests/sources/functional/data_invariant_for_mut_ref_arg.move:31: push_3 = result = = s = diff --git a/third_party/move/move-prover/tests/sources/functional/data_invariant_in_map.v2_exp b/third_party/move/move-prover/tests/sources/functional/data_invariant_in_map.v2_exp index a8079e5f4d271..72c3d31e14b08 100644 --- a/third_party/move/move-prover/tests/sources/functional/data_invariant_in_map.v2_exp +++ b/third_party/move/move-prover/tests/sources/functional/data_invariant_in_map.v2_exp @@ -8,6 +8,6 @@ error: data invariant does not hold = at tests/sources/functional/data_invariant_in_map.move:20: violation_1 = at tests/sources/functional/data_invariant_in_map.move:21: violation_1 = at tests/sources/functional/data_invariant_in_map.move:22: violation_1 + = s = = at tests/sources/functional/data_invariant_in_map.move:23: violation_1 - = = = at tests/sources/functional/data_invariant_in_map.move:8 diff --git a/third_party/move/move-prover/tests/sources/functional/emits.v2_exp b/third_party/move/move-prover/tests/sources/functional/emits.v2_exp index a3c55d75f67cc..f68f38a31dbea 100644 --- a/third_party/move/move-prover/tests/sources/functional/emits.v2_exp +++ b/third_party/move/move-prover/tests/sources/functional/emits.v2_exp @@ -8,7 +8,6 @@ error: function does not emit the expected event = at tests/sources/functional/emits.move:19: simple_wrong_msg_incorrect = handle = = at tests/sources/functional/emits.move:20: simple_wrong_msg_incorrect - = = = at tests/sources/functional/emits.move:19: simple_wrong_msg_incorrect = handle = = at tests/sources/functional/emits.move:21: simple_wrong_msg_incorrect @@ -24,7 +23,6 @@ error: function does not emit the expected event = handle = = _handle2 = = at tests/sources/functional/emits.move:27: simple_wrong_handle_incorrect - = = = at tests/sources/functional/emits.move:26: simple_wrong_handle_incorrect = handle = = _handle2 = @@ -40,9 +38,7 @@ error: function does not emit the expected event = at tests/sources/functional/emits.move:47: multiple_incorrect = handle = = at tests/sources/functional/emits.move:48: multiple_incorrect - = = = at tests/sources/functional/emits.move:49: multiple_incorrect - = = = at tests/sources/functional/emits.move:47: multiple_incorrect = handle = = at tests/sources/functional/emits.move:50: multiple_incorrect @@ -59,7 +55,6 @@ error: function does not emit the expected event = at tests/sources/functional/emits.move:66: multiple_same_incorrect = handle = = at tests/sources/functional/emits.move:67: multiple_same_incorrect - = = = at tests/sources/functional/emits.move:66: multiple_same_incorrect = handle = = at tests/sources/functional/emits.move:68: multiple_same_incorrect @@ -102,9 +97,7 @@ error: function does not emit the expected event = b = = handle = = at tests/sources/functional/emits.move:150: conditional_multiple_incorrect - = = = at tests/sources/functional/emits.move:151: conditional_multiple_incorrect - = = = at tests/sources/functional/emits.move:152: conditional_multiple_incorrect = at tests/sources/functional/emits.move:149: conditional_multiple_incorrect = handle = @@ -122,9 +115,7 @@ error: function does not emit the expected event = b = = handle = = at tests/sources/functional/emits.move:180: conditional_multiple_same_incorrect - = = = at tests/sources/functional/emits.move:181: conditional_multiple_same_incorrect - = = = at tests/sources/functional/emits.move:182: conditional_multiple_same_incorrect = at tests/sources/functional/emits.move:179: conditional_multiple_same_incorrect = handle = @@ -143,9 +134,7 @@ error: emitted event not covered by any of the `emits` clauses = at tests/sources/functional/emits.move:231: partial_incorrect = handle = = at tests/sources/functional/emits.move:232: partial_incorrect - = = = at tests/sources/functional/emits.move:233: partial_incorrect - = = = at tests/sources/functional/emits.move:231: partial_incorrect = handle = = at tests/sources/functional/emits.move:234: partial_incorrect @@ -163,9 +152,7 @@ error: emitted event not covered by any of the `emits` clauses = at tests/sources/functional/emits.move:251: strict_incorrect = handle = = at tests/sources/functional/emits.move:252: strict_incorrect - = = = at tests/sources/functional/emits.move:253: strict_incorrect - = = = at tests/sources/functional/emits.move:251: strict_incorrect = handle = = at tests/sources/functional/emits.move:254: strict_incorrect @@ -180,10 +167,8 @@ error: function does not emit the expected event = at tests/sources/functional/emits.move:286: opaque_incorrect = handle = = at tests/sources/functional/emits.move:287: opaque_incorrect - = = = at tests/sources/functional/emits.move:288: opaque_incorrect = at tests/sources/functional/emits.move:289: opaque_incorrect - = = = at tests/sources/functional/emits.move:286: opaque_incorrect = handle = = at tests/sources/functional/emits.move:290: opaque_incorrect @@ -206,10 +191,8 @@ error: emitted event not covered by any of the `emits` clauses = at tests/sources/functional/emits.move:309: opaque_completeness_incorrect = handle = = at tests/sources/functional/emits.move:310: opaque_completeness_incorrect - = = = at tests/sources/functional/emits.move:311: opaque_completeness_incorrect = at tests/sources/functional/emits.move:312: opaque_completeness_incorrect - = = = at tests/sources/functional/emits.move:309: opaque_completeness_incorrect = handle = = at tests/sources/functional/emits.move:313: opaque_completeness_incorrect @@ -233,10 +216,8 @@ error: emitted event not covered by any of the `emits` clauses = at tests/sources/functional/emits.move:350: opaque_partial_incorrect = handle = = at tests/sources/functional/emits.move:351: opaque_partial_incorrect - = = = at tests/sources/functional/emits.move:352: opaque_partial_incorrect = at tests/sources/functional/emits.move:353: opaque_partial_incorrect - = = = at tests/sources/functional/emits.move:350: opaque_partial_incorrect = handle = = at tests/sources/functional/emits.move:354: opaque_partial_incorrect diff --git a/third_party/move/move-prover/tests/sources/functional/fixed_point_arithm.v2_exp b/third_party/move/move-prover/tests/sources/functional/fixed_point_arithm.v2_exp index 5c7f71304468c..56eef3ac787fe 100644 --- a/third_party/move/move-prover/tests/sources/functional/fixed_point_arithm.v2_exp +++ b/third_party/move/move-prover/tests/sources/functional/fixed_point_arithm.v2_exp @@ -22,8 +22,6 @@ error: post-condition does not hold = at tests/sources/functional/fixed_point_arithm.move:42: multiply_x_0_incorrect = x = = at tests/sources/functional/fixed_point_arithm.move:43: multiply_x_0_incorrect - = = - = at tests/sources/functional/fixed_point_arithm.move:43: multiply_x_0_incorrect = result = = at tests/sources/functional/fixed_point_arithm.move:44: multiply_x_0_incorrect = at tests/sources/functional/fixed_point_arithm.move:46: multiply_x_0_incorrect (spec) @@ -56,8 +54,6 @@ error: post-condition does not hold = at ../move-stdlib/sources/fixed_point32.move:126 = at ../move-stdlib/sources/fixed_point32.move:127 = at tests/sources/functional/fixed_point_arithm.move:82: multiply_x_1_incorrect - = = - = at tests/sources/functional/fixed_point_arithm.move:82: multiply_x_1_incorrect = result = = at tests/sources/functional/fixed_point_arithm.move:83: multiply_x_1_incorrect = at tests/sources/functional/fixed_point_arithm.move:85: multiply_x_1_incorrect (spec) @@ -80,8 +76,6 @@ error: post-condition does not hold = at ../move-stdlib/sources/fixed_point32.move:151: get_raw_value = y_raw_val = = at tests/sources/functional/fixed_point_arithm.move:106: mul_div_incorrect - = y = - = at tests/sources/functional/fixed_point_arithm.move:106: mul_div_incorrect = at tests/sources/functional/fixed_point_arithm.move:107: mul_div_incorrect = result = = at tests/sources/functional/fixed_point_arithm.move:108: mul_div_incorrect @@ -104,8 +98,6 @@ error: post-condition does not hold = at ../move-stdlib/sources/fixed_point32.move:151: get_raw_value = y_raw_val = = at tests/sources/functional/fixed_point_arithm.move:106: mul_div_incorrect - = y = - = at tests/sources/functional/fixed_point_arithm.move:106: mul_div_incorrect = at tests/sources/functional/fixed_point_arithm.move:107: mul_div_incorrect = result = = at tests/sources/functional/fixed_point_arithm.move:108: mul_div_incorrect diff --git a/third_party/move/move-prover/tests/sources/functional/global_invariants.v2_exp b/third_party/move/move-prover/tests/sources/functional/global_invariants.v2_exp index 30735438b7dc4..5db58204b04cb 100644 --- a/third_party/move/move-prover/tests/sources/functional/global_invariants.v2_exp +++ b/third_party/move/move-prover/tests/sources/functional/global_invariants.v2_exp @@ -8,7 +8,6 @@ error: global memory invariant does not hold = at tests/sources/functional/global_invariants.move:38: create_R_invalid = account = = at tests/sources/functional/global_invariants.move:40: create_R_invalid - = = = at tests/sources/functional/global_invariants.move:38: create_R_invalid = at tests/sources/functional/global_invariants.move:40: create_R_invalid = at tests/sources/functional/global_invariants.move:18 diff --git a/third_party/move/move-prover/tests/sources/functional/global_vars.v2_exp b/third_party/move/move-prover/tests/sources/functional/global_vars.v2_exp index 7248ea9d13615..89dd1b7ce0cb7 100644 --- a/third_party/move/move-prover/tests/sources/functional/global_vars.v2_exp +++ b/third_party/move/move-prover/tests/sources/functional/global_vars.v2_exp @@ -62,7 +62,6 @@ error: global memory invariant does not hold = at tests/sources/functional/global_vars.move:220: publish = s = = at tests/sources/functional/global_vars.move:221: publish - = = = at tests/sources/functional/global_vars.move:222: publish = at tests/sources/functional/global_vars.move:230: limit_change_invalid = at tests/sources/functional/global_vars.move:232: limit_change_invalid (spec) diff --git a/third_party/move/move-prover/tests/sources/functional/loop_unroll.v2_exp b/third_party/move/move-prover/tests/sources/functional/loop_unroll.v2_exp index 10d8fa2f9595e..49a8421362280 100644 --- a/third_party/move/move-prover/tests/sources/functional/loop_unroll.v2_exp +++ b/third_party/move/move-prover/tests/sources/functional/loop_unroll.v2_exp @@ -19,47 +19,35 @@ error: abort not covered by any of the `aborts_if` clauses = at tests/sources/functional/loop_unroll.move:94: t6_failure = at tests/sources/functional/loop_unroll.move:90: t6_failure = at tests/sources/functional/loop_unroll.move:96: t6_failure - = = = i = = at tests/sources/functional/loop_unroll.move:97: t6_failure - = = - = at tests/sources/functional/loop_unroll.move:97: t6_failure = at tests/sources/functional/loop_unroll.move:92: t6_failure = at tests/sources/functional/loop_unroll.move:94: t6_failure = at tests/sources/functional/loop_unroll.move:90: t6_failure = at tests/sources/functional/loop_unroll.move:96: t6_failure - = = = i = = at tests/sources/functional/loop_unroll.move:97: t6_failure - = = = at tests/sources/functional/loop_unroll.move:91: t6_failure = at tests/sources/functional/loop_unroll.move:92: t6_failure = at tests/sources/functional/loop_unroll.move:94: t6_failure = at tests/sources/functional/loop_unroll.move:90: t6_failure = at tests/sources/functional/loop_unroll.move:96: t6_failure - = = = i = = at tests/sources/functional/loop_unroll.move:97: t6_failure - = = = at tests/sources/functional/loop_unroll.move:91: t6_failure = at tests/sources/functional/loop_unroll.move:92: t6_failure = at tests/sources/functional/loop_unroll.move:94: t6_failure = at tests/sources/functional/loop_unroll.move:90: t6_failure = at tests/sources/functional/loop_unroll.move:96: t6_failure - = = = i = = at tests/sources/functional/loop_unroll.move:97: t6_failure - = = = at tests/sources/functional/loop_unroll.move:91: t6_failure = at tests/sources/functional/loop_unroll.move:92: t6_failure = at tests/sources/functional/loop_unroll.move:94: t6_failure = at tests/sources/functional/loop_unroll.move:90: t6_failure = at tests/sources/functional/loop_unroll.move:96: t6_failure - = = = i = = at tests/sources/functional/loop_unroll.move:97: t6_failure - = = - = at tests/sources/functional/loop_unroll.move:97: t6_failure = ABORTED error: abort not covered by any of the `aborts_if` clauses diff --git a/third_party/move/move-prover/tests/sources/functional/loops.v2_exp b/third_party/move/move-prover/tests/sources/functional/loops.v2_exp index 72bdc9792f620..b660af31a58f6 100644 --- a/third_party/move/move-prover/tests/sources/functional/loops.v2_exp +++ b/third_party/move/move-prover/tests/sources/functional/loops.v2_exp @@ -12,7 +12,6 @@ error: function does not abort under this condition = i = = loop invariant holds at current state = at tests/sources/functional/loops.move:51: iter10_no_abort_incorrect - = = = at tests/sources/functional/loops.move:49: iter10_no_abort_incorrect = at tests/sources/functional/loops.move:58: iter10_no_abort_incorrect (spec) @@ -35,11 +34,8 @@ error: abort not covered by any of the `aborts_if` clauses = i = = loop invariant holds at current state = at tests/sources/functional/loops.move:80: iter10_abort_incorrect - = = = at tests/sources/functional/loops.move:78: iter10_abort_incorrect = at tests/sources/functional/loops.move:82: iter10_abort_incorrect - = = - = at tests/sources/functional/loops.move:82: iter10_abort_incorrect = ABORTED error: induction case of the loop invariant does not hold @@ -63,7 +59,6 @@ error: induction case of the loop invariant does not hold = y = = at tests/sources/functional/loops.move:128: nested_loop_outer_invariant_incorrect = at tests/sources/functional/loops.move:131: nested_loop_outer_invariant_incorrect - = = = x = = at tests/sources/functional/loops.move:117: nested_loop_outer_invariant_incorrect = at tests/sources/functional/loops.move:119: nested_loop_outer_invariant_incorrect @@ -86,7 +81,6 @@ error: induction case of the loop invariant does not hold = loop invariant holds at current state = at tests/sources/functional/loops.move:147: nested_loop_inner_invariant_incorrect = at tests/sources/functional/loops.move:150: nested_loop_inner_invariant_incorrect - = = = y = = at tests/sources/functional/loops.move:145: nested_loop_inner_invariant_incorrect @@ -109,7 +103,6 @@ error: induction case of the loop invariant does not hold = at tests/sources/functional/loops.move:191: loop_with_two_back_edges_incorrect = at tests/sources/functional/loops.move:195: loop_with_two_back_edges_incorrect = at tests/sources/functional/loops.move:196: loop_with_two_back_edges_incorrect - = = = x = = at tests/sources/functional/loops.move:197: loop_with_two_back_edges_incorrect = at tests/sources/functional/loops.move:189: loop_with_two_back_edges_incorrect @@ -145,7 +138,6 @@ error: induction case of the loop invariant does not hold = at tests/sources/functional/loops.move:225: loop_invariant_induction_invalid = at tests/sources/functional/loops.move:221: loop_invariant_induction_invalid = at tests/sources/functional/loops.move:227: loop_invariant_induction_invalid - = = = x = = at tests/sources/functional/loops.move:221: loop_invariant_induction_invalid = at tests/sources/functional/loops.move:223: loop_invariant_induction_invalid diff --git a/third_party/move/move-prover/tests/sources/functional/loops_with_memory_ops.v2_exp b/third_party/move/move-prover/tests/sources/functional/loops_with_memory_ops.v2_exp index d6f72efdfd3a5..c54e01557729d 100644 --- a/third_party/move/move-prover/tests/sources/functional/loops_with_memory_ops.v2_exp +++ b/third_party/move/move-prover/tests/sources/functional/loops_with_memory_ops.v2_exp @@ -42,9 +42,7 @@ error: induction case of the loop invariant does not hold = at tests/sources/functional/loops_with_memory_ops.move:81: nested_loop2 = a = = at tests/sources/functional/loops_with_memory_ops.move:81: nested_loop2 - = b = = at tests/sources/functional/loops_with_memory_ops.move:85: nested_loop2 - = = = i = = at tests/sources/functional/loops_with_memory_ops.move:86: nested_loop2 = at tests/sources/functional/loops_with_memory_ops.move:89: nested_loop2 @@ -102,7 +100,6 @@ error: unknown assertion failed = at tests/sources/functional/loops_with_memory_ops.move:81: nested_loop2 = b = = at tests/sources/functional/loops_with_memory_ops.move:85: nested_loop2 - = = = i = = at tests/sources/functional/loops_with_memory_ops.move:86: nested_loop2 = at tests/sources/functional/loops_with_memory_ops.move:93: nested_loop2 diff --git a/third_party/move/move-prover/tests/sources/functional/macro_verification.v2_exp b/third_party/move/move-prover/tests/sources/functional/macro_verification.v2_exp index 782a513256905..9aef5d28d0d93 100644 --- a/third_party/move/move-prover/tests/sources/functional/macro_verification.v2_exp +++ b/third_party/move/move-prover/tests/sources/functional/macro_verification.v2_exp @@ -36,8 +36,6 @@ error: post-condition does not hold = at tests/sources/functional/macro_verification.move:26: foreach = `invariant forall j in i..len(v): v[j] == old(v)[j];` = = at tests/sources/functional/macro_verification.move:17: foreach - = = - = at tests/sources/functional/macro_verification.move:17: foreach = at tests/sources/functional/macro_verification.move:15: foreach = v = = at tests/sources/functional/macro_verification.move:30: foreach (spec) @@ -79,9 +77,6 @@ error: post-condition does not hold = at tests/sources/functional/macro_verification.move:50: reduce = `invariant sum == spec_sum(v, i);` = = at tests/sources/functional/macro_verification.move:43: reduce - = = - = at tests/sources/functional/macro_verification.move:52: reduce - = = = at tests/sources/functional/macro_verification.move:40: reduce = result = = at tests/sources/functional/macro_verification.move:55: reduce (spec) @@ -130,9 +125,6 @@ error: post-condition does not hold = at tests/sources/functional/macro_verification.move:49: reduce = at tests/sources/functional/macro_verification.move:50: reduce = at tests/sources/functional/macro_verification.move:43: reduce - = = - = at tests/sources/functional/macro_verification.move:52: reduce - = = = at tests/sources/functional/macro_verification.move:40: reduce = result = = at tests/sources/functional/macro_verification.move:53: reduce diff --git a/third_party/move/move-prover/tests/sources/functional/module_level_spec.v2_exp b/third_party/move/move-prover/tests/sources/functional/module_level_spec.v2_exp index b82e398208518..15fa6af97d6bb 100644 --- a/third_party/move/move-prover/tests/sources/functional/module_level_spec.v2_exp +++ b/third_party/move/move-prover/tests/sources/functional/module_level_spec.v2_exp @@ -11,5 +11,4 @@ error: global memory invariant does not hold = s = = value = = at tests/sources/functional/module_level_spec.move:11: store_incorrect - = = = at tests/sources/functional/module_level_spec.move:18 diff --git a/third_party/move/move-prover/tests/sources/functional/mut_ref.v2_exp b/third_party/move/move-prover/tests/sources/functional/mut_ref.v2_exp index b3ceba69bb79e..d0db7fb4ce3c1 100644 --- a/third_party/move/move-prover/tests/sources/functional/mut_ref.v2_exp +++ b/third_party/move/move-prover/tests/sources/functional/mut_ref.v2_exp @@ -30,7 +30,6 @@ error: data invariant does not hold = at tests/sources/functional/mut_ref.move:120: call_return_ref_different_path_vec2_incorrect = x = = at tests/sources/functional/mut_ref.move:121: call_return_ref_different_path_vec2_incorrect - = = = at tests/sources/functional/mut_ref.move:90: return_ref_different_path_vec2 = b = = x = diff --git a/third_party/move/move-prover/tests/sources/functional/nested_invariants.v2_exp b/third_party/move/move-prover/tests/sources/functional/nested_invariants.v2_exp index d177659668d6f..b4d83685c0075 100644 --- a/third_party/move/move-prover/tests/sources/functional/nested_invariants.v2_exp +++ b/third_party/move/move-prover/tests/sources/functional/nested_invariants.v2_exp @@ -13,8 +13,8 @@ error: data invariant does not hold = at tests/sources/functional/nested_invariants.move:64: mutate_inner_data_invariant_invalid = o = = at tests/sources/functional/nested_invariants.move:65: mutate_inner_data_invariant_invalid + = r = = at tests/sources/functional/nested_invariants.move:66: mutate_inner_data_invariant_invalid - = = = at tests/sources/functional/nested_invariants.move:29 = at tests/sources/functional/nested_invariants.move:32 = at tests/sources/functional/nested_invariants.move:16 @@ -42,8 +42,8 @@ error: data invariant does not hold = at tests/sources/functional/nested_invariants.move:58: mutate_outer_data_invariant_invalid = o = = at tests/sources/functional/nested_invariants.move:59: mutate_outer_data_invariant_invalid + = r = = at tests/sources/functional/nested_invariants.move:60: mutate_outer_data_invariant_invalid - = = = at tests/sources/functional/nested_invariants.move:29 = at tests/sources/functional/nested_invariants.move:32 diff --git a/third_party/move/move-prover/tests/sources/functional/script_incorrect.v2_exp b/third_party/move/move-prover/tests/sources/functional/script_incorrect.v2_exp index 8334205070254..52227eb833db7 100644 --- a/third_party/move/move-prover/tests/sources/functional/script_incorrect.v2_exp +++ b/third_party/move/move-prover/tests/sources/functional/script_incorrect.v2_exp @@ -25,6 +25,4 @@ error: abort not covered by any of the `aborts_if` clauses = result = = at ../move-stdlib/sources/signer.move:14: address_of = at tests/sources/functional/script_provider.move:10: register - = = - = at tests/sources/functional/script_provider.move:10: register = ABORTED diff --git a/third_party/move/move-prover/tests/sources/functional/specs_in_fun.v2_exp b/third_party/move/move-prover/tests/sources/functional/specs_in_fun.v2_exp index 4dc5d49a730b3..afdb0b70f765d 100644 --- a/third_party/move/move-prover/tests/sources/functional/specs_in_fun.v2_exp +++ b/third_party/move/move-prover/tests/sources/functional/specs_in_fun.v2_exp @@ -20,7 +20,6 @@ error: unknown assertion failed = at tests/sources/functional/specs_in_fun.move:49: simple2_incorrect = x = = at tests/sources/functional/specs_in_fun.move:51: simple2_incorrect - = = = y = = at tests/sources/functional/specs_in_fun.move:53: simple2_incorrect diff --git a/third_party/move/move-prover/tests/sources/functional/strong_edges.v2_exp b/third_party/move/move-prover/tests/sources/functional/strong_edges.v2_exp index 67b7e4f38736e..33c9f0347305e 100644 --- a/third_party/move/move-prover/tests/sources/functional/strong_edges.v2_exp +++ b/third_party/move/move-prover/tests/sources/functional/strong_edges.v2_exp @@ -10,8 +10,8 @@ error: post-condition does not hold = at tests/sources/functional/strong_edges.move:47: glob_and_field_edges_incorrect = addr = = at tests/sources/functional/strong_edges.move:48: glob_and_field_edges_incorrect + = s = = at tests/sources/functional/strong_edges.move:49: glob_and_field_edges_incorrect - = = = at tests/sources/functional/strong_edges.move:50: glob_and_field_edges_incorrect = at tests/sources/functional/strong_edges.move:55: glob_and_field_edges_incorrect (spec) = at tests/sources/functional/strong_edges.move:54: glob_and_field_edges_incorrect (spec) diff --git a/third_party/move/move-prover/tests/sources/functional/trace.v2_exp b/third_party/move/move-prover/tests/sources/functional/trace.v2_exp index 38e6e6733c25b..e24a41719d8a7 100644 --- a/third_party/move/move-prover/tests/sources/functional/trace.v2_exp +++ b/third_party/move/move-prover/tests/sources/functional/trace.v2_exp @@ -47,7 +47,7 @@ error: post-condition does not hold │ = Related Global Memory: = Resource name: TestTracing_R - = Values: {Address(18467): , Default: empty} + = Values: {Address(18467): , Default: TestTracing.R{x = 4}} = Related Bindings: = addr = = exists(addr) = @@ -61,7 +61,6 @@ error: post-condition does not hold = s = = x = = at tests/sources/functional/trace.move:30: publish_invalid - = = = at tests/sources/functional/trace.move:38 = at tests/sources/functional/trace.move:31: publish_invalid = at tests/sources/functional/trace.move:34: publish_invalid (spec) @@ -75,7 +74,7 @@ error: global memory invariant does not hold │ = Related Global Memory: = Resource name: TestTracing_R - = Values: {Address(0): , Default: empty} + = Values: {Address(0): , Default: TestTracing.R{x = 5}} = at tests/sources/functional/trace.move:29: publish_invalid = at tests/sources/functional/trace.move:33: publish_invalid (spec) = `let addr = signer::address_of(s);` = @@ -83,5 +82,4 @@ error: global memory invariant does not hold = s = = x = = at tests/sources/functional/trace.move:30: publish_invalid - = = = at tests/sources/functional/trace.move:38 diff --git a/third_party/move/move-prover/tests/sources/regression/Escape.v2_exp b/third_party/move/move-prover/tests/sources/regression/Escape.v2_exp index 95f6061110c17..6c00121c91033 100644 --- a/third_party/move/move-prover/tests/sources/regression/Escape.v2_exp +++ b/third_party/move/move-prover/tests/sources/regression/Escape.v2_exp @@ -9,7 +9,6 @@ error: global memory invariant does not hold = account = = thing = = at tests/sources/regression/Escape.move:25: install - = = = at tests/sources/regression/Escape.move:36 error: global memory invariant does not hold @@ -22,6 +21,5 @@ error: global memory invariant does not hold = account = = thing = = at tests/sources/regression/Escape.move:25: install - = = = at tests/sources/regression/Escape.move:36 = at tests/sources/regression/Escape.move:37 diff --git a/third_party/move/move-prover/tests/sources/regression/mono_after_global_invariant.v2_exp b/third_party/move/move-prover/tests/sources/regression/mono_after_global_invariant.v2_exp index 9604206e50aa8..a6a667d21ca5d 100644 --- a/third_party/move/move-prover/tests/sources/regression/mono_after_global_invariant.v2_exp +++ b/third_party/move/move-prover/tests/sources/regression/mono_after_global_invariant.v2_exp @@ -13,10 +13,8 @@ error: global memory invariant does not hold = at tests/sources/regression/mono_after_global_invariant.move:9: put_b = s = = at tests/sources/regression/mono_after_global_invariant.move:10: put_b - = = = at tests/sources/regression/mono_after_global_invariant.move:14: put_b = at tests/sources/regression/mono_after_global_invariant.move:32: put_r - = = = at tests/sources/regression/mono_after_global_invariant.move:30: put_r = at tests/sources/regression/mono_after_global_invariant.move:32: put_r = at tests/sources/regression/mono_after_global_invariant.move:44 diff --git a/third_party/move/move-prover/tests/sources/regression/type_param_bug_121721.v2_exp b/third_party/move/move-prover/tests/sources/regression/type_param_bug_121721.v2_exp index aa9b2951d4375..972aa1db72f40 100644 --- a/third_party/move/move-prover/tests/sources/regression/type_param_bug_121721.v2_exp +++ b/third_party/move/move-prover/tests/sources/regression/type_param_bug_121721.v2_exp @@ -18,6 +18,5 @@ error: global memory invariant does not hold = at tests/sources/regression/type_param_bug_121721.move:86: create_ballot = at tests/sources/regression/type_param_bug_121721.move:88: create_ballot = at tests/sources/regression/type_param_bug_121721.move:87: create_ballot - = = = at tests/sources/regression/type_param_bug_121721.move:167 = at tests/sources/regression/type_param_bug_121721.move:173 diff --git a/third_party/move/move-prover/tests/sources/regression/vector_theory_boogie_array.v2_exp b/third_party/move/move-prover/tests/sources/regression/vector_theory_boogie_array.v2_exp index d4f05e0f2ba86..6f3780c21b0d8 100644 --- a/third_party/move/move-prover/tests/sources/regression/vector_theory_boogie_array.v2_exp +++ b/third_party/move/move-prover/tests/sources/regression/vector_theory_boogie_array.v2_exp @@ -12,8 +12,8 @@ error: post-condition does not hold = pool = = addr = = at tests/sources/regression/vector_theory_boogie_array.move:7: f1 - = at tests/sources/regression/vector_theory_boogie_array.move:8: f1 = idx = + = at tests/sources/regression/vector_theory_boogie_array.move:8: f1 = at tests/sources/regression/vector_theory_boogie_array.move:6: f1 = pool = = at tests/sources/regression/vector_theory_boogie_array.move:9: f1 diff --git a/third_party/move/tools/move-decompiler/tests/bit_vector.exp b/third_party/move/tools/move-decompiler/tests/bit_vector.exp index 762f2f5211648..5f27356b6fb61 100644 --- a/third_party/move/tools/move-decompiler/tests/bit_vector.exp +++ b/third_party/move/tools/move-decompiler/tests/bit_vector.exp @@ -12,41 +12,30 @@ module 0x1::bit_vector { *0x1::vector::borrow(&self.bit_field, bit_index) } public fun longest_set_sequence_starting_at(self: &BitVector, start_index: u64): u64 { - let _t3; let _t2; - _t2 = *&self.length; - if (!(start_index < _t2)) abort 131072; - _t3 = start_index; + if (!(start_index < *&self.length)) abort 131072; + _t2 = start_index; loop { { - loop { - _t2 = *&self.length; - if (!(_t3 < _t2)) break; - if (!is_index_set(self, _t3)) break; - _t2 = 1; - _t3 = _t3 + _t2 - }; + while (_t2 < *&self.length && is_index_set(self, _t2)) _t2 = _t2 + 1; break }; break }; - _t3 - start_index + _t2 - start_index } public fun new(length: u64): BitVector { - let _t3; let _t2; let _t1; + if (!(length > 0)) abort 131073; + if (!(length < 1024)) abort 131073; _t1 = 0; - if (!(length > _t1)) abort 131073; - _t1 = 1024; - if (!(length < _t1)) abort 131073; - _t2 = 0; - _t3 = 0x1::vector::empty(); - while (_t2 < length) { - 0x1::vector::push_back(&mut _t3, false); - _t2 = _t2 + 1 + _t2 = 0x1::vector::empty(); + while (_t1 < length) { + 0x1::vector::push_back(&mut _t2, false); + _t1 = _t1 + 1 }; - BitVector{length: length,bit_field: _t3} + BitVector{length: length,bit_field: _t2} } public fun set(self: &mut BitVector, bit_index: u64) { if (!(bit_index < 0x1::vector::length(&self.bit_field))) abort 131072; @@ -56,39 +45,30 @@ module 0x1::bit_vector { let _t4; let _t3; let _t2; - _t2 = *&self.length; 'l0: loop { loop { - if (amount >= _t2) { - _t3 = &mut self.bit_field; - _t2 = 0; - _t4 = 0x1::vector::length(/*freeze*/_t3) + if (amount >= *&self.length) { + _t2 = &mut self.bit_field; + _t3 = 0; + _t4 = 0x1::vector::length(/*freeze*/_t2) } else { - _t2 = amount; + _t3 = amount; break }; - while (_t2 < _t4) { - *0x1::vector::borrow_mut(_t3, _t2) = false; - _t2 = _t2 + 1 + while (_t3 < _t4) { + *0x1::vector::borrow_mut(_t2, _t3) = false; + _t3 = _t3 + 1 }; break 'l0 }; - loop { - _t4 = *&self.length; - if (!(_t2 < _t4)) break; - if (is_index_set(/*freeze*/self, _t2)) { - _t4 = _t2 - amount; - set(self, _t4) - } else { - _t4 = _t2 - amount; - unset(self, _t4) - }; - _t2 = _t2 + 1 + while (_t3 < *&self.length) { + if (is_index_set(/*freeze*/self, _t3)) set(self, _t3 - amount) else unset(self, _t3 - amount); + _t3 = _t3 + 1 }; - _t2 = *&self.length - amount; - while (_t2 < *&self.length) { - unset(self, _t2); - _t2 = _t2 + 1 + _t3 = *&self.length - amount; + while (_t3 < *&self.length) { + unset(self, _t3); + _t3 = _t3 + 1 }; break }; diff --git a/third_party/move/tools/move-decompiler/tests/fixed_point32.exp b/third_party/move/tools/move-decompiler/tests/fixed_point32.exp index f88e3a6e3ab55..a7c9846e00d2a 100644 --- a/third_party/move/tools/move-decompiler/tests/fixed_point32.exp +++ b/third_party/move/tools/move-decompiler/tests/fixed_point32.exp @@ -13,14 +13,14 @@ module 0x1::fixed_point32 { *&(&self).value >> 32u8 } public fun create_from_rational(numerator: u64, denominator: u64): FixedPoint32 { - let _t6; + let _t5; let _t4; let _t3; _t3 = (denominator as u128) << 32u8; if (!(_t3 != 0u128)) abort 65537; _t4 = ((numerator as u128) << 64u8) / _t3; - if (_t4 != 0u128) _t6 = true else _t6 = numerator == 0; - if (!_t6) abort 131077; + if (_t4 != 0u128) _t5 = true else _t5 = numerator == 0; + if (!_t5) abort 131077; if (!(_t4 <= 18446744073709551615u128)) abort 131077; FixedPoint32{value: _t4 as u64} } diff --git a/third_party/move/tools/move-decompiler/tests/simple_map.exp b/third_party/move/tools/move-decompiler/tests/simple_map.exp index 056957264c034..fc003d61fd8b1 100644 --- a/third_party/move/tools/move-decompiler/tests/simple_map.exp +++ b/third_party/move/tools/move-decompiler/tests/simple_map.exp @@ -115,33 +115,33 @@ module 0x1::simple_map { _t2 } public fun to_vec_pair(self: SimpleMap): (vector, vector) { - let _t25; - let _t24; + let _t22; + let _t21; let _t5; let _t4; let _t3; - let _t14; + let _t11; let _t2; let _t1; _t1 = vector::empty(); _t2 = vector::empty(); - SimpleMap{data: _t14} = self; - _t3 = _t14; + SimpleMap{data: _t11} = self; + _t3 = _t11; vector::reverse>(&mut _t3); _t4 = _t3; _t5 = vector::length>(&_t4); while (_t5 > 0) { - Element{key: _t24,value: _t25} = vector::pop_back>(&mut _t4); - vector::push_back(&mut _t1, _t24); - vector::push_back(&mut _t2, _t25); + Element{key: _t21,value: _t22} = vector::pop_back>(&mut _t4); + vector::push_back(&mut _t1, _t21); + vector::push_back(&mut _t2, _t22); _t5 = _t5 - 1 }; vector::destroy_empty>(_t4); (_t1, _t2) } public fun upsert(self: &mut SimpleMap, key: Key, value: Value): (option::Option, option::Option) { - let _t38; - let _t37; + let _t35; + let _t34; let _t5; let _t4; let _t3; @@ -152,8 +152,8 @@ module 0x1::simple_map { while (!(!(_t5 < _t4) || &vector::borrow>(/*freeze*/_t3, _t5).key == &key)) _t5 = _t5 + 1; vector::push_back>(_t3, Element{key: key,value: value}); vector::swap>(_t3, _t5, _t4); - Element{key: _t37,value: _t38} = vector::pop_back>(_t3); - return (option::some(_t37), option::some(_t38)) + Element{key: _t34,value: _t35} = vector::pop_back>(_t3); + return (option::some(_t34), option::some(_t35)) }; vector::push_back>(&mut self.data, Element{key: key,value: value}); (option::none(), option::none()) diff --git a/third_party/move/tools/move-decompiler/tests/string.exp b/third_party/move/tools/move-decompiler/tests/string.exp index 6df58cc3c6ebb..1a87dcb38e007 100644 --- a/third_party/move/tools/move-decompiler/tests/string.exp +++ b/third_party/move/tools/move-decompiler/tests/string.exp @@ -19,18 +19,16 @@ module 0x1::string { vector::append(&mut self.bytes, *&(&r).bytes); } public fun insert(self: &mut String, at: u64, o: String) { - let _t7; let _t6; let _t4; let _t3; _t3 = &self.bytes; - _t4 = at; - if (_t4 <= vector::length(_t3)) _t6 = internal_is_char_boundary(_t3, at) else _t6 = false; - if (!_t6) abort 2; - _t7 = sub_string(/*freeze*/self, 0, at); - append(&mut _t7, o); - append(&mut _t7, sub_string(/*freeze*/self, at, length(/*freeze*/self))); - *self = _t7; + if (at <= vector::length(_t3)) _t4 = internal_is_char_boundary(_t3, at) else _t4 = false; + if (!_t4) abort 2; + _t6 = sub_string(/*freeze*/self, 0, at); + append(&mut _t6, o); + append(&mut _t6, sub_string(/*freeze*/self, at, length(/*freeze*/self))); + *self = _t6; } native fun internal_is_char_boundary(v: &vector, i: u64): bool; public fun sub_string(self: &String, i: u64, j: u64): String { diff --git a/third_party/move/tools/move-decompiler/tests/vector.exp b/third_party/move/tools/move-decompiler/tests/vector.exp index 7462165278356..22e0c75e28a97 100644 --- a/third_party/move/tools/move-decompiler/tests/vector.exp +++ b/third_party/move/tools/move-decompiler/tests/vector.exp @@ -30,14 +30,14 @@ module 0x1::vector { range_with_step(start, end, 1) } public fun range_with_step(start: u64, end: u64, step: u64): vector { - let _t4; + let _t3; if (!(step > 0)) abort 131075; - _t4 = empty(); + _t3 = empty(); while (start < end) { - push_back(&mut _t4, start); + push_back(&mut _t3, start); start = start + step }; - _t4 + _t3 } public fun append(self: &mut vector, other: vector) { reverse(&mut other); @@ -121,16 +121,16 @@ module 0x1::vector { _t1 } public fun slice(self: &vector, start: u64, end: u64): vector { - let _t6; - let _t5; - if (start <= end) _t5 = end <= length(self) else _t5 = false; - if (!_t5) abort 131076; - _t6 = empty(); + let _t4; + let _t3; + if (start <= end) _t3 = end <= length(self) else _t3 = false; + if (!_t3) abort 131076; + _t4 = empty(); while (start < end) { - push_back(&mut _t6, *borrow(self, start)); + push_back(&mut _t4, *borrow(self, start)); start = start + 1 }; - _t6 + _t4 } public fun swap_remove(self: &mut vector, i: u64): Element { if (is_empty(/*freeze*/self)) abort 131072; From 7ccbfaf4facdcedfaef1f6920fd3a7439302097e Mon Sep 17 00:00:00 2001 From: Vineeth Kashyap Date: Sat, 14 Dec 2024 23:16:16 -0500 Subject: [PATCH 54/78] [cli] Bump to 5.1.0 (#15596) --- Cargo.lock | 2 +- crates/aptos/CHANGELOG.md | 3 +++ crates/aptos/Cargo.toml | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 57d19e14925d9..15f52e4b304bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -275,7 +275,7 @@ dependencies = [ [[package]] name = "aptos" -version = "5.0.0" +version = "5.1.0" dependencies = [ "anyhow", "aptos-api-types", diff --git a/crates/aptos/CHANGELOG.md b/crates/aptos/CHANGELOG.md index b1fc2e380c6d7..591c7bff8abb6 100644 --- a/crates/aptos/CHANGELOG.md +++ b/crates/aptos/CHANGELOG.md @@ -3,6 +3,9 @@ All notable changes to the Aptos CLI will be captured in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) and the format set out by [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). # Unreleased + +## [5.1.0] - 2024/12/13 +- More optimizations are now default for compiler v2. - Downgrade bytecode version to v6 before calling the Revela decompiler, if possible, i.e. no enum types are used. This allows to continue to use Revela until the new decompiler is ready. ## [5.0.0] - 2024/12/11 diff --git a/crates/aptos/Cargo.toml b/crates/aptos/Cargo.toml index 4e8c393472f65..a29e4224e2080 100644 --- a/crates/aptos/Cargo.toml +++ b/crates/aptos/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "aptos" description = "Aptos tool for management of nodes and interacting with the blockchain" -version = "5.0.0" +version = "5.1.0" # Workspace inherited keys authors = { workspace = true } From 57117296d7da75278a7e3e6a2104be0b61353375 Mon Sep 17 00:00:00 2001 From: Vineeth Kashyap Date: Sun, 15 Dec 2024 19:17:56 -0500 Subject: [PATCH 55/78] Fix cargo nextest version (#15608) --- scripts/dev_setup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/dev_setup.sh b/scripts/dev_setup.sh index 2fed0701bbf48..7d0fdf70199f9 100755 --- a/scripts/dev_setup.sh +++ b/scripts/dev_setup.sh @@ -507,7 +507,7 @@ function install_cargo_machete { function install_cargo_nextest { if ! command -v cargo-nextest &>/dev/null; then - cargo install cargo-nextest --locked + cargo install cargo-nextest --locked --version 0.9.85 fi } From f69598f7faf70c1217efde4b53b42a2ec3619c83 Mon Sep 17 00:00:00 2001 From: George Mitenkov Date: Mon, 16 Dec 2024 01:27:00 +0000 Subject: [PATCH 56/78] [loader-v2] More tests for global manager (#15563) --- .../src/code_cache_global_manager.rs | 254 ++++++++++++++++-- 1 file changed, 230 insertions(+), 24 deletions(-) diff --git a/aptos-move/block-executor/src/code_cache_global_manager.rs b/aptos-move/block-executor/src/code_cache_global_manager.rs index f90ada6ba1994..be1df2dfe7ce9 100644 --- a/aptos-move/block-executor/src/code_cache_global_manager.rs +++ b/aptos-move/block-executor/src/code_cache_global_manager.rs @@ -312,7 +312,15 @@ mod test { state_store::{state_key::StateKey, state_value::StateValue, MockStateView}, }; use claims::assert_ok; - use std::collections::HashMap; + use move_core_types::identifier::Identifier; + use move_vm_types::{ + code::{mock_verified_code, MockExtension}, + loaded_data::runtime_types::StructIdentifier, + }; + use std::{ + collections::HashMap, + sync::atomic::{AtomicU64, Ordering}, + }; #[test] fn test_prefetch_existing_aptos_framework() { @@ -346,19 +354,48 @@ mod test { assert_eq!(module_cache.num_modules(), 0); } - #[allow(dead_code)] - fn state_view_with_changed_feature_flag( - feature_flag: Option, - ) -> MockStateView { + fn add_struct_identifier(manager: &mut ModuleCacheManager, name: &str) + where + K: Hash + Eq + Clone, + V: Deref>, + E: WithSize, + { + assert_ok!(manager + .environment + .as_mut() + .unwrap() + .runtime_environment() + .struct_name_to_idx_for_test(StructIdentifier { + module: ModuleId::new(AccountAddress::ZERO, Identifier::new("m").unwrap()), + name: Identifier::new(name).unwrap() + })); + } + + fn assert_struct_name_index_map_size_eq( + manager: &ModuleCacheManager, + expected: usize, + ) where + K: Hash + Eq + Clone, + V: Deref>, + E: WithSize, + { + let actual = assert_ok!(manager + .environment + .as_ref() + .unwrap() + .runtime_environment() + .struct_name_index_map_size()); + assert_eq!(actual, expected); + } + + fn state_view_with_changed_feature_flag(feature_flag: FeatureFlag) -> MockStateView { // Tweak feature flags to force a different config. let mut features = Features::default(); - if let Some(feature_flag) = feature_flag { - if features.is_enabled(feature_flag) { - features.disable(feature_flag); - } else { - features.enable(feature_flag); - } + if features.is_enabled(feature_flag) { + features.disable(feature_flag); + } else { + features.enable(feature_flag); } MockStateView::new(HashMap::from([( @@ -368,28 +405,197 @@ mod test { } #[test] - fn test_check_ready_sets_transaction_slice_metadata() { + fn test_check_ready() { + let mut manager = ModuleCacheManager::new(); + assert_eq!( + manager.transaction_slice_metadata, + TransactionSliceMetadata::Unknown + ); + assert_eq!(manager.module_cache.num_modules(), 0); + let state_view = MockStateView::empty(); let config = BlockExecutorModuleCacheLocalConfig { prefetch_framework_code: false, - max_module_cache_size_in_bytes: 8, + max_module_cache_size_in_bytes: 32, max_struct_name_index_map_num_entries: 2, }; + // Populate the cache for testing. + manager + .module_cache + .insert(0, mock_verified_code(0, MockExtension::new(8))); + manager + .module_cache + .insert(1, mock_verified_code(1, MockExtension::new(8))); + manager + .module_cache + .insert(2, mock_verified_code(2, MockExtension::new(8))); + + // Case 1: Initial set-up, modules should not be cached. Metadata and environment are set. + let metadata_1 = TransactionSliceMetadata::block_from_u64(0, 1); + assert_ok!(manager.check_ready(AptosEnvironment::new(&state_view), &config, metadata_1)); + assert_eq!(manager.transaction_slice_metadata, metadata_1); + assert!(manager.environment.is_some()); + assert_eq!(manager.module_cache.num_modules(), 0); + + add_struct_identifier(&mut manager, "foo"); + assert_struct_name_index_map_size_eq(&manager, 1); + manager + .module_cache + .insert(0, mock_verified_code(0, MockExtension::new(8))); + manager + .module_cache + .insert(1, mock_verified_code(1, MockExtension::new(8))); + assert_eq!(manager.module_cache.num_modules(), 2); + + // Case 2: Different metadata => cache is flushed. Here we pass a deep copy of environment. + let metadata_2 = TransactionSliceMetadata::block_from_u64(2, 3); + assert_ok!(manager.check_ready(AptosEnvironment::new(&state_view), &config, metadata_2)); + assert_eq!(manager.transaction_slice_metadata, metadata_2); + assert!(manager.environment.is_some()); + assert_eq!(manager.module_cache.num_modules(), 0); + assert_struct_name_index_map_size_eq(&manager, 0); + + add_struct_identifier(&mut manager, "foo"); + add_struct_identifier(&mut manager, "bar"); + assert_struct_name_index_map_size_eq(&manager, 2); + manager + .module_cache + .insert(0, mock_verified_code(0, MockExtension::new(8))); + manager + .module_cache + .insert(1, mock_verified_code(1, MockExtension::new(8))); + manager + .module_cache + .insert(2, mock_verified_code(2, MockExtension::new(8))); + manager + .module_cache + .insert(3, mock_verified_code(3, MockExtension::new(8))); + assert_eq!(manager.module_cache.num_modules(), 4); + + // Case 3: Metadata follows immediately after and environment is the same. Cache is not + // flushed. + let metadata_3 = TransactionSliceMetadata::block_from_u64(3, 4); + assert!(metadata_3.is_immediately_after(&metadata_2)); + + assert_ok!(manager.check_ready(AptosEnvironment::new(&state_view), &config, metadata_3)); + assert_eq!(manager.transaction_slice_metadata, metadata_3); + assert!(manager.environment.is_some()); + assert_eq!(manager.module_cache.num_modules(), 4); + assert_eq!(manager.module_cache.size_in_bytes(), 32); + assert_struct_name_index_map_size_eq(&manager, 2); + + manager + .module_cache + .insert(4, mock_verified_code(4, MockExtension::new(8))); + assert_eq!(manager.module_cache.num_modules(), 5); + assert_eq!(manager.module_cache.size_in_bytes(), 40); + + // Case 4: Too many modules cached. + let metadata_4 = TransactionSliceMetadata::block_from_u64(4, 5); + assert!(metadata_4.is_immediately_after(&metadata_3)); + + assert_ok!(manager.check_ready(AptosEnvironment::new(&state_view), &config, metadata_4)); + assert_eq!(manager.transaction_slice_metadata, metadata_4); + assert!(manager.environment.is_some()); + assert_eq!(manager.module_cache.num_modules(), 0); + assert_struct_name_index_map_size_eq(&manager, 2); + + manager + .module_cache + .insert(0, mock_verified_code(0, MockExtension::new(8))); + manager + .module_cache + .insert(1, mock_verified_code(1, MockExtension::new(8))); + assert_eq!(manager.module_cache.num_modules(), 2); + + // Case 5: Environment changes. + let metadata_5 = TransactionSliceMetadata::block_from_u64(5, 6); + assert!(metadata_5.is_immediately_after(&metadata_4)); + + let state_view = state_view_with_changed_feature_flag(FeatureFlag::EMIT_FEE_STATEMENT); + + assert_ok!(manager.check_ready(AptosEnvironment::new(&state_view), &config, metadata_5)); + assert_eq!(manager.transaction_slice_metadata, metadata_5); + assert!(manager.environment.is_some()); + assert_eq!(manager.module_cache.num_modules(), 0); + assert_struct_name_index_map_size_eq(&manager, 0); + + add_struct_identifier(&mut manager, "foo"); + add_struct_identifier(&mut manager, "bar"); + add_struct_identifier(&mut manager, "baz"); + assert_struct_name_index_map_size_eq(&manager, 3); + manager + .module_cache + .insert(0, mock_verified_code(0, MockExtension::new(8))); + manager + .module_cache + .insert(1, mock_verified_code(1, MockExtension::new(8))); + assert_eq!(manager.module_cache.num_modules(), 2); + assert_eq!(manager.module_cache.size_in_bytes(), 16); + + // Case 6: Type cache is too large. + let metadata_6 = TransactionSliceMetadata::block_from_u64(6, 5); + assert!(metadata_6.is_immediately_after(&metadata_5)); + + assert_ok!(manager.check_ready(AptosEnvironment::new(&state_view), &config, metadata_6)); + assert_eq!(manager.transaction_slice_metadata, metadata_6); + assert!(manager.environment.is_some()); + assert_eq!(manager.module_cache.num_modules(), 0); + assert_struct_name_index_map_size_eq(&manager, 0); + } + + #[test] + fn test_try_lock_inner_single_thread() { let manager = AptosModuleCacheManager::new(); - assert_eq!( - manager.inner.lock().transaction_slice_metadata, - TransactionSliceMetadata::Unknown - ); - let metadata_1 = TransactionSliceMetadata::block_from_u64(0, 1); - assert_ok!(manager.try_lock(&state_view, &config, metadata_1)); - assert_eq!(manager.inner.lock().transaction_slice_metadata, metadata_1); + let state_view = MockStateView::empty(); + let config = BlockExecutorModuleCacheLocalConfig::default(); + let metadata = TransactionSliceMetadata::block_from_u64(0, 1); - let metadata_2 = TransactionSliceMetadata::block_from_u64(1, 2); - assert_ok!(manager.try_lock(&state_view, &config, metadata_2)); - assert_eq!(manager.inner.lock().transaction_slice_metadata, metadata_2); + let guard = assert_ok!(manager.try_lock(&state_view, &config, metadata)); + assert!(matches!(guard, AptosModuleCacheManagerGuard::Guard { .. })); } - // TODO(loader_v2): Add more unit tests like with previous commits. + #[test] + fn test_try_lock_inner_multiple_threads() { + let manager = Arc::new(AptosModuleCacheManager::new()); + + let state_view = Arc::new(MockStateView::empty()); + let config = Arc::new(BlockExecutorModuleCacheLocalConfig::default()); + let metadata = TransactionSliceMetadata::block_from_u64(0, 1); + + let counter = Arc::new(AtomicU64::new(0)); + let num_threads = 8; + let mut handles = Vec::with_capacity(num_threads); + + for _ in 0..num_threads { + let handle = std::thread::spawn({ + let manager = manager.clone(); + let state_view = state_view.clone(); + let config = config.clone(); + let counter = counter.clone(); + + move || { + let guard = assert_ok!(manager.try_lock_inner(&state_view, &config, metadata)); + + // Wait for all threads to complete. + counter.fetch_add(1, Ordering::SeqCst); + loop { + if counter.load(Ordering::SeqCst) == num_threads as u64 { + break; + } + } + if matches!(guard, AptosModuleCacheManagerGuard::Guard { .. }) { + 1 + } else { + 0 + } + } + }); + handles.push(handle); + } + let sum = handles.into_iter().map(|h| h.join().unwrap()).sum::(); + assert_eq!(sum, 1); + } } From dd0dcd25d894024bce91ad59962fb6da48730653 Mon Sep 17 00:00:00 2001 From: Wolfgang Grieskamp Date: Sun, 15 Dec 2024 19:43:52 -0800 Subject: [PATCH 57/78] [move-prover] Fix a bug in treatment of type reflection in spec funs (#15606) When calling a generic function in a specification expression which transitively uses type reflection, the function call type instantiation wasn't correctly treated for the type info parameters. The refined test generates this situation and failed before but passes now. Removes the boogie compilation error in #15605, but after this the example in this bug times out, even though the package does not contain any specs. I verified that all verification conditions belong to functions in this package, but this does not change this. Should be fixed in subsequent PR before closing the bug. --- third_party/move/move-model/src/model.rs | 11 ++++++++ .../boogie-backend/src/spec_translator.rs | 28 +++++++++++++------ .../src/verification_analysis.rs | 4 +-- .../src/verification_analysis_v2.rs | 2 +- .../sources/functional/type_reflection.move | 14 +++++++++- .../move/tools/move-cli/src/base/prove.rs | 2 +- 6 files changed, 48 insertions(+), 13 deletions(-) diff --git a/third_party/move/move-model/src/model.rs b/third_party/move/move-model/src/model.rs index e7a87dd266c74..63e4749401965 100644 --- a/third_party/move/move-model/src/model.rs +++ b/third_party/move/move-model/src/model.rs @@ -885,6 +885,17 @@ impl GlobalEnv { target_modules } + /// Find all primary target modules and return in a vector + pub fn get_primary_target_modules(&self) -> Vec { + let mut target_modules: Vec = vec![]; + for module_env in self.get_modules() { + if module_env.is_primary_target() { + target_modules.push(module_env); + } + } + target_modules + } + fn add_backtrace(msg: &str, _is_bug: bool) -> String { // Note that you need both MOVE_COMPILER_BACKTRACE=1 and RUST_BACKTRACE=1 for this to // actually generate a backtrace. diff --git a/third_party/move/move-prover/boogie-backend/src/spec_translator.rs b/third_party/move/move-prover/boogie-backend/src/spec_translator.rs index d3157c01a7161..9ef7a69bf9fe3 100644 --- a/third_party/move/move-prover/boogie-backend/src/spec_translator.rs +++ b/third_party/move/move-prover/boogie-backend/src/spec_translator.rs @@ -314,11 +314,27 @@ impl<'env> SpecTranslator<'env> { } }; let type_info_params = if type_reflection { + let mut covered = BTreeSet::new(); (0..fun.type_params.len()) .map(|i| { + // Apply type instantiation if present + let ty = self + .type_inst + .get(i) + .cloned() + .unwrap_or_else(|| Type::TypeParameter(i as u16)); + // There can be name clashes after instantiation. Parameters still need + // to be there but all are instantiated with the same type. We escape + // the redundant parameters. + let prefix = if !covered.insert(ty.clone()) { + format!("_{}_", i) + } else { + "".to_string() + }; format!( - "{}_info: $TypeParamInfo", - boogie_type(self.env, &Type::TypeParameter(i as u16)) + "{}{}_info: $TypeParamInfo", + prefix, + boogie_type(self.env, &ty) ) }) .collect_vec() @@ -1154,13 +1170,9 @@ impl<'env> SpecTranslator<'env> { .env .spec_fun_uses_generic_type_reflection(&module_id.qualified_inst(fun_id, inst.clone())) { - for i in 0..fun_decl.type_params.len() { + for ty in inst { maybe_comma(); - emit!( - self.writer, - "{}_info", - boogie_type(self.env, &Type::TypeParameter(i as u16)) - ) + emit!(self.writer, "{}_info", boogie_type(self.env, ty)) } } // Add memory parameters. diff --git a/third_party/move/move-prover/bytecode-pipeline/src/verification_analysis.rs b/third_party/move/move-prover/bytecode-pipeline/src/verification_analysis.rs index 722077bf3f186..1bcdb94afc03d 100644 --- a/third_party/move/move-prover/bytecode-pipeline/src/verification_analysis.rs +++ b/third_party/move/move-prover/bytecode-pipeline/src/verification_analysis.rs @@ -96,7 +96,7 @@ impl FunctionTargetProcessor for VerificationAnalysisProcessor { // Rule 2: verify the function if it is within the target modules let env = fun_env.module_env.env; - let target_modules = env.get_target_modules(); + let target_modules = env.get_primary_target_modules(); let is_in_target_module = target_modules .iter() @@ -162,7 +162,7 @@ impl FunctionTargetProcessor for VerificationAnalysisProcessor { writeln!(f, "invariant applicability: [")?; let target_invs: BTreeSet<_> = env - .get_target_modules() + .get_primary_target_modules() .iter() .flat_map(|menv| env.get_global_invariants_by_module(menv.get_id())) .collect(); diff --git a/third_party/move/move-prover/bytecode-pipeline/src/verification_analysis_v2.rs b/third_party/move/move-prover/bytecode-pipeline/src/verification_analysis_v2.rs index def589a6d3ecf..5808200509499 100644 --- a/third_party/move/move-prover/bytecode-pipeline/src/verification_analysis_v2.rs +++ b/third_party/move/move-prover/bytecode-pipeline/src/verification_analysis_v2.rs @@ -661,7 +661,7 @@ impl FunctionTargetProcessor for VerificationAnalysisProcessorV2 { _ => {}, } - let target_modules = global_env.get_target_modules(); + let target_modules = global_env.get_primary_target_modules(); let target_fun_ids: BTreeSet> = target_modules .iter() .flat_map(|mod_env| mod_env.get_functions()) diff --git a/third_party/move/move-prover/tests/sources/functional/type_reflection.move b/third_party/move/move-prover/tests/sources/functional/type_reflection.move index 0149dd4cc572a..0f5ae8e30edc8 100644 --- a/third_party/move/move-prover/tests/sources/functional/type_reflection.move +++ b/third_party/move/move-prover/tests/sources/functional/type_reflection.move @@ -110,12 +110,24 @@ module 0x42::test { type_info::type_of() } spec generic_type_info_verification_target { - ensures result == generic_type_info_spec_fun(); + ensures result == generic_type_info_spec_fun() + && result == generic_type_info_spec_fun_2(); } spec fun generic_type_info_spec_fun(): type_info::TypeInfo { type_info::type_of() } + + spec fun generic_type_info_spec_fun_2(): type_info::TypeInfo { + takes_2() + } + + spec fun takes_2(): type_info::TypeInfo { + // Pass on the 2nd type parameter to be sure the instantiation + // of B is correctly handled + type_info::type_of() + } + } module 0x43::test { diff --git a/third_party/move/tools/move-cli/src/base/prove.rs b/third_party/move/tools/move-cli/src/base/prove.rs index 27a499c3db82f..4b029ddf5be39 100644 --- a/third_party/move/tools/move-cli/src/base/prove.rs +++ b/third_party/move/tools/move-cli/src/base/prove.rs @@ -230,7 +230,7 @@ pub fn run_move_prover( } else { "FAILURE".bold().red() }, - model.get_target_modules().len(), + model.get_primary_target_modules().len(), basedir, now.elapsed().as_secs_f64() )?; From fed1684edcbe5881ed9e9527cf302e965103de81 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 18 Dec 2024 10:05:04 -0800 Subject: [PATCH 58/78] Update Docker images (#15541) Co-authored-by: gedigi <19227040+gedigi@users.noreply.github.com> --- docker/builder/docker-bake-rust-all.hcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/builder/docker-bake-rust-all.hcl b/docker/builder/docker-bake-rust-all.hcl index 3ad59abc754d2..77a9aafd7e9d5 100644 --- a/docker/builder/docker-bake-rust-all.hcl +++ b/docker/builder/docker-bake-rust-all.hcl @@ -69,7 +69,7 @@ target "debian-base" { dockerfile = "docker/builder/debian-base.Dockerfile" contexts = { # Run `docker buildx imagetools inspect debian:bullseye` to find the latest multi-platform hash - debian = "docker-image://debian:bullseye@sha256:01559430c84e6bc864bed554345d1bfbfa94ac108ab68f39915cae34604b15c3" + debian = "docker-image://debian:bullseye@sha256:e91d1b0684e0f26a29c2353c52d4814f4d153e10b1faddf9fbde473ed71e2fcf" } } From 38a5f0da94d7e3846f9acb5251a70f33f16fef78 Mon Sep 17 00:00:00 2001 From: Perry Randall Date: Thu, 12 Dec 2024 17:56:19 -0800 Subject: [PATCH 59/78] [forge] Run forge nightly on weekdays --- .github/workflows/forge-stable.yaml | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/.github/workflows/forge-stable.yaml b/.github/workflows/forge-stable.yaml index e9841704cff90..aea8a24b6c8f0 100644 --- a/.github/workflows/forge-stable.yaml +++ b/.github/workflows/forge-stable.yaml @@ -49,10 +49,8 @@ on: description: The number of test jobs to run in parallel. If not specified, defaults to 1 default: 1 - # NOTE: to support testing different branches on different schedules, you need to specify the cron schedule in the 'determine-test-branch' step as well below - # Reference: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#schedule schedule: - - cron: "0 22 * * 0,2,4" # The main branch cadence. This runs every Sun,Tues,Thurs + - cron: "0 22 * * 1-5" # The main branch cadence. This runs every Mon-Fri pull_request: paths: - ".github/workflows/forge-stable.yaml" @@ -147,17 +145,11 @@ jobs: id: determine-test-branch # NOTE: the schedule cron MUST match the one in the 'on.schedule.cron' section above run: | + BRANCH="" if [[ "${{ github.event_name }}" == "schedule" ]]; then - if [[ "${{ github.event.schedule }}" == "0 22 * * 0,2,4" ]]; then - echo "Branch: main" - echo "BRANCH=main" >> $GITHUB_OUTPUT - else - echo "Unknown schedule: ${{ github.event.schedule }}" - exit 1 - fi + echo "BRANCH=main" >> $GITHUB_OUTPUT elif [[ "${{ github.event_name }}" == "push" ]]; then - echo "Branch: ${{ github.ref_name }}" - echo "BRANCH=${{ github.ref_name }}" >> $GITHUB_OUTPUT + echo "BRANCH=${{ github.ref_name }}" >> $GITHUB_OUTPUT # on workflow_dispatch, this will simply use the inputs.GIT_SHA given (or the default) elif [[ -n "${{ inputs.GIT_SHA }}" ]]; then echo "BRANCH=${{ inputs.GIT_SHA }}" >> $GITHUB_OUTPUT @@ -165,6 +157,7 @@ jobs: else echo "BRANCH=${{ github.head_ref }}" >> $GITHUB_OUTPUT fi + echo "Branch: $(grep BRANCH= $GITHUB_OUTPUT)" # Use the branch hash instead of the full branch name to stay under kubernetes namespace length limit - name: Hash the branch id: hash-branch From ac9302a9ca24a091af1ddc312a6cff3c1f6d9c99 Mon Sep 17 00:00:00 2001 From: igor-aptos <110557261+igor-aptos@users.noreply.github.com> Date: Wed, 18 Dec 2024 10:05:49 -0800 Subject: [PATCH 60/78] Fix txn-emitter precission of worker sleeping (#15552) Fix txn-emitter precission of worker sleeping --- .../src/emitter/submission_worker.rs | 101 ++++++++++++------ 1 file changed, 70 insertions(+), 31 deletions(-) diff --git a/crates/transaction-emitter-lib/src/emitter/submission_worker.rs b/crates/transaction-emitter-lib/src/emitter/submission_worker.rs index be3dafccaeaf2..9563e78648b59 100644 --- a/crates/transaction-emitter-lib/src/emitter/submission_worker.rs +++ b/crates/transaction-emitter-lib/src/emitter/submission_worker.rs @@ -30,7 +30,9 @@ use std::{ sync::{atomic::AtomicU64, Arc}, time::Instant, }; -use tokio::time::sleep; +use tokio::time::{sleep, sleep_until}; + +const ALLOWED_EARLY: Duration = Duration::from_micros(500); pub struct SubmissionWorker { pub(crate) accounts: Vec>, @@ -82,31 +84,18 @@ impl SubmissionWorker { pub(crate) async fn run(mut self, start_instant: Instant) -> Vec { let mut wait_until = start_instant + self.start_sleep_duration; - let now = Instant::now(); - if wait_until > now { - self.sleep_check_done(wait_until - now).await; - } + self.sleep_check_done(wait_until).await; let wait_duration = Duration::from_millis(self.params.wait_millis); while !self.stop.load(Ordering::Relaxed) { - let stats_clone = self.stats.clone(); - let loop_stats = stats_clone.get_cur(); - let loop_start_time = Instant::now(); - if wait_duration.as_secs() > 0 - && loop_start_time.duration_since(wait_until) > Duration::from_secs(5) - { - sample!( - SampleRate::Duration(Duration::from_secs(5)), - error!( - "[{:?}] txn_emitter worker drifted out of sync too much: {}s. Is expiration too short, or 5s buffer on top of it?", - self.client().path_prefix_string(), - loop_start_time.duration_since(wait_until).as_secs() - ) - ); + + if wait_duration.as_secs() > 0 { + self.verify_loop_start_drift(loop_start_time, wait_until); } - // always add expected cycle duration, to not drift from expected pace. - wait_until += wait_duration; + + let stats_clone = self.stats.clone(); + let loop_stats = stats_clone.get_cur(); let requests = self.gen_requests(); if !requests.is_empty() { @@ -175,9 +164,10 @@ impl SubmissionWorker { if self.skip_latency_stats { // we also don't want to be stuck waiting for txn_expiration_time_secs // after stop is called, so we sleep until time or stop is set. - self.sleep_check_done(Duration::from_secs( - self.params.txn_expiration_time_secs + 3, - )) + self.sleep_check_done( + Instant::now() + + Duration::from_secs(self.params.txn_expiration_time_secs + 3), + ) .await } @@ -203,9 +193,11 @@ impl SubmissionWorker { .await; } - let now = Instant::now(); - if wait_until > now { - self.sleep_check_done(wait_until - now).await; + if wait_duration.as_secs() > 0 { + // always add expected cycle duration, to not drift from expected pace, + // irrespectively of how long our iteration lasted. + wait_until += wait_duration; + self.sleep_check_done(wait_until).await; } } @@ -216,16 +208,63 @@ impl SubmissionWorker { } // returns true if it returned early - async fn sleep_check_done(&self, duration: Duration) { - let start_time = Instant::now(); + async fn sleep_check_done(&self, sleep_until_time: Instant) { + // sleep has millisecond granularity - so round the sleep + let sleep_poll_interval = Duration::from_secs(1); loop { - sleep(Duration::from_secs(1)).await; if self.stop.load(Ordering::Relaxed) { return; } - if start_time.elapsed() >= duration { + + let now = Instant::now(); + if now + ALLOWED_EARLY > sleep_until_time { return; } + + if sleep_until_time > now + sleep_poll_interval { + sleep(sleep_poll_interval).await; + } else { + sleep_until(sleep_until_time.into()).await; + } + } + } + + fn verify_loop_start_drift(&self, loop_start_time: Instant, wait_until: Instant) { + if loop_start_time > wait_until { + let delay_s = loop_start_time + .saturating_duration_since(wait_until) + .as_secs_f32(); + if delay_s > 5.0 { + sample!( + SampleRate::Duration(Duration::from_secs(2)), + error!( + "[{:?}] txn_emitter worker drifted out of sync too much: {:.3}s. Is machine underprovisioned? Is expiration too short, or 5s buffer on top of it?", + self.client().path_prefix_string(), + delay_s, + ) + ); + } else if delay_s > 0.3 { + sample!( + SampleRate::Duration(Duration::from_secs(5)), + error!( + "[{:?}] txn_emitter worker called a bit out of sync: {:.3}s. Is machine underprovisioned? Is expiration too short, or 5s buffer on top of it?", + self.client().path_prefix_string(), + delay_s, + ) + ); + } + } else { + let early_s = wait_until.saturating_duration_since(loop_start_time); + if early_s > ALLOWED_EARLY { + sample!( + SampleRate::Duration(Duration::from_secs(5)), + error!( + "[{:?}] txn_emitter worker called too early: {:.3}s. There is some bug in waiting.", + self.client().path_prefix_string(), + early_s.as_secs_f32(), + ) + ); + } } } From 9a6cc6ffa668bc8067983783bc3a585fdfc2b222 Mon Sep 17 00:00:00 2001 From: "Brian R. Murphy" <132495859+brmataptos@users.noreply.github.com> Date: Wed, 18 Dec 2024 10:20:08 -0800 Subject: [PATCH 61/78] add a lambda transactional-test, clean up test driver a bit to improve coverage of existing tests (#15463) * add a lambda transactional-test. while modifying test config, add a baseline test config to ensure we are running baseline for all tests. --- .../lambda/inline-parity/subtype_args_ok.exp | 9 + .../inline-parity/subtype_args_ok.lambda.exp | 9 + .../lambda/inline-parity/subtype_args_ok.move | 27 + .../tests/lambda/storable/generic_func.exp | 37 + .../lambda/storable/generic_func.lambda.exp | 1055 +++++++++++++++++ .../tests/lambda/storable/generic_func.move | 71 ++ .../constants/large_vectors.baseline.exp | 9 + .../tests/inlining/deep_exp.baseline.exp | 6 + .../tests/lambda/generic_func.baseline.exp | 71 ++ .../tests/lambda/generic_func.lambda.exp | 75 ++ .../tests/lambda/generic_func.move | 71 ++ .../tests/lambda/generic_func.no-optimize.exp | 71 ++ .../generic_func.optimize-no-simplify.exp | 71 ++ .../tests/lambda/generic_func.optimize.exp | 71 ++ .../misc/bug_14243_stack_size.baseline.exp | 32 + ...dynamic.no-optimize-no-acquires-check.exp} | 0 .../dynamic.optimize-no-acquires-check.exp | 29 + ...optimize-no-simplify-no-acquires-check.exp | 29 + ...generic.no-optimize-no-acquires-check.exp} | 0 .../generic.optimize-no-acquires-check.exp | 18 + ...optimize-no-simplify-no-acquires-check.exp | 18 + ...egation.no-optimize-no-acquires-check.exp} | 0 .../negation.optimize-no-acquires-check.exp | 29 + ...optimize-no-simplify-no-acquires-check.exp | 29 + ...esource.no-optimize-no-acquires-check.exp} | 0 .../resource.optimize-no-acquires-check.exp | 71 ++ ...optimize-no-simplify-no-acquires-check.exp | 71 ++ ...ildcard.no-optimize-no-acquires-check.exp} | 0 .../wildcard.optimize-no-acquires-check.exp | 35 + ...optimize-no-simplify-no-acquires-check.exp | 35 + .../no-v1-comparison/assert_one.baseline.exp | 10 + .../enum/enum_field_select.baseline.exp | 19 + ...eld_select_different_offsets.baseline.exp} | 0 .../enum/enum_scoping.baseline.exp | 37 + .../tests/no-v1-comparison/index.move | 4 +- .../print_bytecode.baseline.exp | 24 + .../transactional-tests/tests/tests.rs | 117 +- third_party/move/move-model/src/metadata.rs | 37 +- 38 files changed, 2264 insertions(+), 33 deletions(-) create mode 100644 third_party/move/move-compiler-v2/tests/lambda/inline-parity/subtype_args_ok.exp create mode 100644 third_party/move/move-compiler-v2/tests/lambda/inline-parity/subtype_args_ok.lambda.exp create mode 100644 third_party/move/move-compiler-v2/tests/lambda/inline-parity/subtype_args_ok.move create mode 100644 third_party/move/move-compiler-v2/tests/lambda/storable/generic_func.exp create mode 100644 third_party/move/move-compiler-v2/tests/lambda/storable/generic_func.lambda.exp create mode 100644 third_party/move/move-compiler-v2/tests/lambda/storable/generic_func.move create mode 100644 third_party/move/move-compiler-v2/transactional-tests/tests/constants/large_vectors.baseline.exp create mode 100644 third_party/move/move-compiler-v2/transactional-tests/tests/inlining/deep_exp.baseline.exp create mode 100644 third_party/move/move-compiler-v2/transactional-tests/tests/lambda/generic_func.baseline.exp create mode 100644 third_party/move/move-compiler-v2/transactional-tests/tests/lambda/generic_func.lambda.exp create mode 100644 third_party/move/move-compiler-v2/transactional-tests/tests/lambda/generic_func.move create mode 100644 third_party/move/move-compiler-v2/transactional-tests/tests/lambda/generic_func.no-optimize.exp create mode 100644 third_party/move/move-compiler-v2/transactional-tests/tests/lambda/generic_func.optimize-no-simplify.exp create mode 100644 third_party/move/move-compiler-v2/transactional-tests/tests/lambda/generic_func.optimize.exp create mode 100644 third_party/move/move-compiler-v2/transactional-tests/tests/misc/bug_14243_stack_size.baseline.exp rename third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/{dynamic.exp => dynamic.no-optimize-no-acquires-check.exp} (100%) create mode 100644 third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/dynamic.optimize-no-acquires-check.exp create mode 100644 third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/dynamic.optimize-no-simplify-no-acquires-check.exp rename third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/{generic.exp => generic.no-optimize-no-acquires-check.exp} (100%) create mode 100644 third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/generic.optimize-no-acquires-check.exp create mode 100644 third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/generic.optimize-no-simplify-no-acquires-check.exp rename third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/{negation.exp => negation.no-optimize-no-acquires-check.exp} (100%) create mode 100644 third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/negation.optimize-no-acquires-check.exp create mode 100644 third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/negation.optimize-no-simplify-no-acquires-check.exp rename third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/{resource.exp => resource.no-optimize-no-acquires-check.exp} (100%) create mode 100644 third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/resource.optimize-no-acquires-check.exp create mode 100644 third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/resource.optimize-no-simplify-no-acquires-check.exp rename third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/{wildcard.exp => wildcard.no-optimize-no-acquires-check.exp} (100%) create mode 100644 third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/wildcard.optimize-no-acquires-check.exp create mode 100644 third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/wildcard.optimize-no-simplify-no-acquires-check.exp create mode 100644 third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/assert_one.baseline.exp create mode 100644 third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/enum/enum_field_select.baseline.exp rename third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/enum/{enum_field_select_different_offsets.exp => enum_field_select_different_offsets.baseline.exp} (100%) create mode 100644 third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/enum/enum_scoping.baseline.exp create mode 100644 third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/print_bytecode.baseline.exp diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/subtype_args_ok.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/subtype_args_ok.exp new file mode 100644 index 0000000000000..a889af242eb9f --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/subtype_args_ok.exp @@ -0,0 +1,9 @@ + +Diagnostics: +error: unexpected token + ┌─ tests/lambda/inline-parity/subtype_args_ok.move:23:37 + │ +23 │ fun t2(f: |&u64, &mut u64| with copy) { + │ - ^ Expected ')' + │ │ + │ To match this '(' diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/subtype_args_ok.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/subtype_args_ok.lambda.exp new file mode 100644 index 0000000000000..a889af242eb9f --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/subtype_args_ok.lambda.exp @@ -0,0 +1,9 @@ + +Diagnostics: +error: unexpected token + ┌─ tests/lambda/inline-parity/subtype_args_ok.move:23:37 + │ +23 │ fun t2(f: |&u64, &mut u64| with copy) { + │ - ^ Expected ')' + │ │ + │ To match this '(' diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/subtype_args_ok.move b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/subtype_args_ok.move new file mode 100644 index 0000000000000..98dbdb729a132 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/subtype_args_ok.move @@ -0,0 +1,27 @@ +module 0x8675309::M { + struct S has drop {} + + fun imm(_x: &T) {} + fun imm_mut(_x: &T, _y: &mut T) {} + fun mut_imm(_x: &mut T, _y: &T) {} + fun imm_imm(_x: &T, _y: &T) {} + + fun t0() { + imm(&mut 0); + imm(&0); + + imm(&mut S{}); + imm(&S{}); + } + + fun t1() { + imm_mut(&mut 0, &mut 0); + mut_imm(&mut 0, &mut 0); + imm_imm(&mut 0, &mut 0); + } + + fun t2(f: |&u64, &mut u64| with copy) { + f(&mut 0, &mut 0); + f(&0, &mut 0); + } +} diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/generic_func.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/generic_func.exp new file mode 100644 index 0000000000000..e951e634b479c --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/generic_func.exp @@ -0,0 +1,37 @@ + +Diagnostics: +error: unsupported language construct + ┌─ tests/lambda/storable/generic_func.move:36:18 + │ +36 │ let f1 = move |addr| 0x42::mod2::item_exists(addr) with store+copy; + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/generic_func.move:36:71 + │ +36 │ let f1 = move |addr| 0x42::mod2::item_exists(addr) with store+copy; + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/generic_func.move:37:18 + │ +37 │ let f2 = move |addr| 0x42::mod2::item_exists(addr) with store+copy; + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/generic_func.move:37:71 + │ +37 │ let f2 = move |addr| 0x42::mod2::item_exists(addr) with store+copy; + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/generic_func.move:53:55 + │ +53 │ assert!(0x42::mod2::item_exists<|address|bool with store+copy>(addr)); + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types + +error: unsupported language construct + ┌─ tests/lambda/storable/generic_func.move:55:58 + │ +55 │ let found_f = 0x42::mod2::get_item<|address|bool with store+copy>(addr); + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/generic_func.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/generic_func.lambda.exp new file mode 100644 index 0000000000000..39abd011a6bd2 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/generic_func.lambda.exp @@ -0,0 +1,1055 @@ +// -- Model dump before env processor pipeline: +module 0x42::mod2 { + struct Registry { + func: F, + } + public fun get_item(addr: address): F + acquires Registry(*) + { + select mod2::Registry.func<&Registry>(BorrowGlobal(Immutable)>(addr)) + } + public fun item_exists(addr: address): bool { + exists>(addr) + } + public fun save_item(owner: &signer,f: F) { + MoveTo>(owner, pack mod2::Registry(f)); + Tuple() + } +} // end 0x42::mod2 +module 0x42::mod3 { + use std::signer; + struct MyStruct1 { + x: u64, + } + struct MyStruct2 { + y: u8, + } + public fun test_item1(owner: signer) { + mod3::test_items(owner, true); + Tuple() + } + public fun test_item2(owner: signer) { + mod3::test_items(owner, false); + Tuple() + } + public fun test_items(owner: signer,use_1: bool) { + { + let struct1: MyStruct1 = pack mod3::MyStruct1(3); + { + let f1: |address|bool with copy+store = move|addr: address| mod2::item_exists(addr) with copy, drop, store; + { + let f2: |address|bool with copy+store = move|addr: address| mod2::item_exists(addr) with copy, drop, store; + { + let addr: address = signer::address_of(Borrow(Immutable)(owner)); + mod2::save_item(Borrow(Immutable)(owner), struct1); + MoveTo(Borrow(Immutable)(owner), struct1); + if use_1 { + mod2::save_item<|address|bool with copy+store>(Borrow(Immutable)(owner), f1); + Tuple() + } else { + mod2::save_item<|address|bool with copy+store>(Borrow(Immutable)(owner), f2); + Tuple() + }; + if mod2::item_exists<|address|bool with copy+store>(addr) { + Tuple() + } else { + Abort(14566554180833181696) + }; + { + let found_f: |address|bool with copy+store = mod2::get_item<|address|bool with copy+store>(addr); + if Eq(use_1, (found_f)(addr)) { + Tuple() + } else { + Abort(14566554180833181696) + }; + Tuple() + } + } + } + } + } + } +} // end 0x42::mod3 + + +// -- Model dump after env processor unused checks: +module 0x42::mod2 { + struct Registry { + func: F, + } + public fun get_item(addr: address): F + acquires Registry(*) + { + select mod2::Registry.func<&Registry>(BorrowGlobal(Immutable)>(addr)) + } + public fun item_exists(addr: address): bool { + exists>(addr) + } + public fun save_item(owner: &signer,f: F) { + MoveTo>(owner, pack mod2::Registry(f)); + Tuple() + } +} // end 0x42::mod2 +module 0x42::mod3 { + use std::signer; + struct MyStruct1 { + x: u64, + } + struct MyStruct2 { + y: u8, + } + public fun test_item1(owner: signer) { + mod3::test_items(owner, true); + Tuple() + } + public fun test_item2(owner: signer) { + mod3::test_items(owner, false); + Tuple() + } + public fun test_items(owner: signer,use_1: bool) { + { + let struct1: MyStruct1 = pack mod3::MyStruct1(3); + { + let f1: |address|bool with copy+store = move|addr: address| mod2::item_exists(addr) with copy, drop, store; + { + let f2: |address|bool with copy+store = move|addr: address| mod2::item_exists(addr) with copy, drop, store; + { + let addr: address = signer::address_of(Borrow(Immutable)(owner)); + mod2::save_item(Borrow(Immutable)(owner), struct1); + MoveTo(Borrow(Immutable)(owner), struct1); + if use_1 { + mod2::save_item<|address|bool with copy+store>(Borrow(Immutable)(owner), f1); + Tuple() + } else { + mod2::save_item<|address|bool with copy+store>(Borrow(Immutable)(owner), f2); + Tuple() + }; + if mod2::item_exists<|address|bool with copy+store>(addr) { + Tuple() + } else { + Abort(14566554180833181696) + }; + { + let found_f: |address|bool with copy+store = mod2::get_item<|address|bool with copy+store>(addr); + if Eq(use_1, (found_f)(addr)) { + Tuple() + } else { + Abort(14566554180833181696) + }; + Tuple() + } + } + } + } + } + } +} // end 0x42::mod3 + + +// -- Model dump after env processor type parameter check: +module 0x42::mod2 { + struct Registry { + func: F, + } + public fun get_item(addr: address): F + acquires Registry(*) + { + select mod2::Registry.func<&Registry>(BorrowGlobal(Immutable)>(addr)) + } + public fun item_exists(addr: address): bool { + exists>(addr) + } + public fun save_item(owner: &signer,f: F) { + MoveTo>(owner, pack mod2::Registry(f)); + Tuple() + } +} // end 0x42::mod2 +module 0x42::mod3 { + use std::signer; + struct MyStruct1 { + x: u64, + } + struct MyStruct2 { + y: u8, + } + public fun test_item1(owner: signer) { + mod3::test_items(owner, true); + Tuple() + } + public fun test_item2(owner: signer) { + mod3::test_items(owner, false); + Tuple() + } + public fun test_items(owner: signer,use_1: bool) { + { + let struct1: MyStruct1 = pack mod3::MyStruct1(3); + { + let f1: |address|bool with copy+store = move|addr: address| mod2::item_exists(addr) with copy, drop, store; + { + let f2: |address|bool with copy+store = move|addr: address| mod2::item_exists(addr) with copy, drop, store; + { + let addr: address = signer::address_of(Borrow(Immutable)(owner)); + mod2::save_item(Borrow(Immutable)(owner), struct1); + MoveTo(Borrow(Immutable)(owner), struct1); + if use_1 { + mod2::save_item<|address|bool with copy+store>(Borrow(Immutable)(owner), f1); + Tuple() + } else { + mod2::save_item<|address|bool with copy+store>(Borrow(Immutable)(owner), f2); + Tuple() + }; + if mod2::item_exists<|address|bool with copy+store>(addr) { + Tuple() + } else { + Abort(14566554180833181696) + }; + { + let found_f: |address|bool with copy+store = mod2::get_item<|address|bool with copy+store>(addr); + if Eq(use_1, (found_f)(addr)) { + Tuple() + } else { + Abort(14566554180833181696) + }; + Tuple() + } + } + } + } + } + } +} // end 0x42::mod3 + + +// -- Model dump after env processor check recursive struct definition: +module 0x42::mod2 { + struct Registry { + func: F, + } + public fun get_item(addr: address): F + acquires Registry(*) + { + select mod2::Registry.func<&Registry>(BorrowGlobal(Immutable)>(addr)) + } + public fun item_exists(addr: address): bool { + exists>(addr) + } + public fun save_item(owner: &signer,f: F) { + MoveTo>(owner, pack mod2::Registry(f)); + Tuple() + } +} // end 0x42::mod2 +module 0x42::mod3 { + use std::signer; + struct MyStruct1 { + x: u64, + } + struct MyStruct2 { + y: u8, + } + public fun test_item1(owner: signer) { + mod3::test_items(owner, true); + Tuple() + } + public fun test_item2(owner: signer) { + mod3::test_items(owner, false); + Tuple() + } + public fun test_items(owner: signer,use_1: bool) { + { + let struct1: MyStruct1 = pack mod3::MyStruct1(3); + { + let f1: |address|bool with copy+store = move|addr: address| mod2::item_exists(addr) with copy, drop, store; + { + let f2: |address|bool with copy+store = move|addr: address| mod2::item_exists(addr) with copy, drop, store; + { + let addr: address = signer::address_of(Borrow(Immutable)(owner)); + mod2::save_item(Borrow(Immutable)(owner), struct1); + MoveTo(Borrow(Immutable)(owner), struct1); + if use_1 { + mod2::save_item<|address|bool with copy+store>(Borrow(Immutable)(owner), f1); + Tuple() + } else { + mod2::save_item<|address|bool with copy+store>(Borrow(Immutable)(owner), f2); + Tuple() + }; + if mod2::item_exists<|address|bool with copy+store>(addr) { + Tuple() + } else { + Abort(14566554180833181696) + }; + { + let found_f: |address|bool with copy+store = mod2::get_item<|address|bool with copy+store>(addr); + if Eq(use_1, (found_f)(addr)) { + Tuple() + } else { + Abort(14566554180833181696) + }; + Tuple() + } + } + } + } + } + } +} // end 0x42::mod3 + + +// -- Model dump after env processor check cyclic type instantiation: +module 0x42::mod2 { + struct Registry { + func: F, + } + public fun get_item(addr: address): F + acquires Registry(*) + { + select mod2::Registry.func<&Registry>(BorrowGlobal(Immutable)>(addr)) + } + public fun item_exists(addr: address): bool { + exists>(addr) + } + public fun save_item(owner: &signer,f: F) { + MoveTo>(owner, pack mod2::Registry(f)); + Tuple() + } +} // end 0x42::mod2 +module 0x42::mod3 { + use std::signer; + struct MyStruct1 { + x: u64, + } + struct MyStruct2 { + y: u8, + } + public fun test_item1(owner: signer) { + mod3::test_items(owner, true); + Tuple() + } + public fun test_item2(owner: signer) { + mod3::test_items(owner, false); + Tuple() + } + public fun test_items(owner: signer,use_1: bool) { + { + let struct1: MyStruct1 = pack mod3::MyStruct1(3); + { + let f1: |address|bool with copy+store = move|addr: address| mod2::item_exists(addr) with copy, drop, store; + { + let f2: |address|bool with copy+store = move|addr: address| mod2::item_exists(addr) with copy, drop, store; + { + let addr: address = signer::address_of(Borrow(Immutable)(owner)); + mod2::save_item(Borrow(Immutable)(owner), struct1); + MoveTo(Borrow(Immutable)(owner), struct1); + if use_1 { + mod2::save_item<|address|bool with copy+store>(Borrow(Immutable)(owner), f1); + Tuple() + } else { + mod2::save_item<|address|bool with copy+store>(Borrow(Immutable)(owner), f2); + Tuple() + }; + if mod2::item_exists<|address|bool with copy+store>(addr) { + Tuple() + } else { + Abort(14566554180833181696) + }; + { + let found_f: |address|bool with copy+store = mod2::get_item<|address|bool with copy+store>(addr); + if Eq(use_1, (found_f)(addr)) { + Tuple() + } else { + Abort(14566554180833181696) + }; + Tuple() + } + } + } + } + } + } +} // end 0x42::mod3 + + +// -- Model dump after env processor unused struct params check: +module 0x42::mod2 { + struct Registry { + func: F, + } + public fun get_item(addr: address): F + acquires Registry(*) + { + select mod2::Registry.func<&Registry>(BorrowGlobal(Immutable)>(addr)) + } + public fun item_exists(addr: address): bool { + exists>(addr) + } + public fun save_item(owner: &signer,f: F) { + MoveTo>(owner, pack mod2::Registry(f)); + Tuple() + } +} // end 0x42::mod2 +module 0x42::mod3 { + use std::signer; + struct MyStruct1 { + x: u64, + } + struct MyStruct2 { + y: u8, + } + public fun test_item1(owner: signer) { + mod3::test_items(owner, true); + Tuple() + } + public fun test_item2(owner: signer) { + mod3::test_items(owner, false); + Tuple() + } + public fun test_items(owner: signer,use_1: bool) { + { + let struct1: MyStruct1 = pack mod3::MyStruct1(3); + { + let f1: |address|bool with copy+store = move|addr: address| mod2::item_exists(addr) with copy, drop, store; + { + let f2: |address|bool with copy+store = move|addr: address| mod2::item_exists(addr) with copy, drop, store; + { + let addr: address = signer::address_of(Borrow(Immutable)(owner)); + mod2::save_item(Borrow(Immutable)(owner), struct1); + MoveTo(Borrow(Immutable)(owner), struct1); + if use_1 { + mod2::save_item<|address|bool with copy+store>(Borrow(Immutable)(owner), f1); + Tuple() + } else { + mod2::save_item<|address|bool with copy+store>(Borrow(Immutable)(owner), f2); + Tuple() + }; + if mod2::item_exists<|address|bool with copy+store>(addr) { + Tuple() + } else { + Abort(14566554180833181696) + }; + { + let found_f: |address|bool with copy+store = mod2::get_item<|address|bool with copy+store>(addr); + if Eq(use_1, (found_f)(addr)) { + Tuple() + } else { + Abort(14566554180833181696) + }; + Tuple() + } + } + } + } + } + } +} // end 0x42::mod3 + + +// -- Model dump after env processor access and use check before inlining: +module 0x42::mod2 { + struct Registry { + func: F, + } + public fun get_item(addr: address): F + acquires Registry(*) + { + select mod2::Registry.func<&Registry>(BorrowGlobal(Immutable)>(addr)) + } + public fun item_exists(addr: address): bool { + exists>(addr) + } + public fun save_item(owner: &signer,f: F) { + MoveTo>(owner, pack mod2::Registry(f)); + Tuple() + } +} // end 0x42::mod2 +module 0x42::mod3 { + use std::signer; + struct MyStruct1 { + x: u64, + } + struct MyStruct2 { + y: u8, + } + public fun test_item1(owner: signer) { + mod3::test_items(owner, true); + Tuple() + } + public fun test_item2(owner: signer) { + mod3::test_items(owner, false); + Tuple() + } + public fun test_items(owner: signer,use_1: bool) { + { + let struct1: MyStruct1 = pack mod3::MyStruct1(3); + { + let f1: |address|bool with copy+store = move|addr: address| mod2::item_exists(addr) with copy, drop, store; + { + let f2: |address|bool with copy+store = move|addr: address| mod2::item_exists(addr) with copy, drop, store; + { + let addr: address = signer::address_of(Borrow(Immutable)(owner)); + mod2::save_item(Borrow(Immutable)(owner), struct1); + MoveTo(Borrow(Immutable)(owner), struct1); + if use_1 { + mod2::save_item<|address|bool with copy+store>(Borrow(Immutable)(owner), f1); + Tuple() + } else { + mod2::save_item<|address|bool with copy+store>(Borrow(Immutable)(owner), f2); + Tuple() + }; + if mod2::item_exists<|address|bool with copy+store>(addr) { + Tuple() + } else { + Abort(14566554180833181696) + }; + { + let found_f: |address|bool with copy+store = mod2::get_item<|address|bool with copy+store>(addr); + if Eq(use_1, (found_f)(addr)) { + Tuple() + } else { + Abort(14566554180833181696) + }; + Tuple() + } + } + } + } + } + } +} // end 0x42::mod3 + + +// -- Model dump after env processor inlining: +module 0x42::mod2 { + struct Registry { + func: F, + } + public fun get_item(addr: address): F + acquires Registry(*) + { + select mod2::Registry.func<&Registry>(BorrowGlobal(Immutable)>(addr)) + } + public fun item_exists(addr: address): bool { + exists>(addr) + } + public fun save_item(owner: &signer,f: F) { + MoveTo>(owner, pack mod2::Registry(f)); + Tuple() + } +} // end 0x42::mod2 +module 0x42::mod3 { + use std::signer; + struct MyStruct1 { + x: u64, + } + struct MyStruct2 { + y: u8, + } + public fun test_item1(owner: signer) { + mod3::test_items(owner, true); + Tuple() + } + public fun test_item2(owner: signer) { + mod3::test_items(owner, false); + Tuple() + } + public fun test_items(owner: signer,use_1: bool) { + { + let struct1: MyStruct1 = pack mod3::MyStruct1(3); + { + let f1: |address|bool with copy+store = move|addr: address| mod2::item_exists(addr) with copy, drop, store; + { + let f2: |address|bool with copy+store = move|addr: address| mod2::item_exists(addr) with copy, drop, store; + { + let addr: address = signer::address_of(Borrow(Immutable)(owner)); + mod2::save_item(Borrow(Immutable)(owner), struct1); + MoveTo(Borrow(Immutable)(owner), struct1); + if use_1 { + mod2::save_item<|address|bool with copy+store>(Borrow(Immutable)(owner), f1); + Tuple() + } else { + mod2::save_item<|address|bool with copy+store>(Borrow(Immutable)(owner), f2); + Tuple() + }; + if mod2::item_exists<|address|bool with copy+store>(addr) { + Tuple() + } else { + Abort(14566554180833181696) + }; + { + let found_f: |address|bool with copy+store = mod2::get_item<|address|bool with copy+store>(addr); + if Eq(use_1, (found_f)(addr)) { + Tuple() + } else { + Abort(14566554180833181696) + }; + Tuple() + } + } + } + } + } + } +} // end 0x42::mod3 + + +// -- Model dump after env processor access and use check after inlining: +module 0x42::mod2 { + struct Registry { + func: F, + } + public fun get_item(addr: address): F + acquires Registry(*) + { + select mod2::Registry.func<&Registry>(BorrowGlobal(Immutable)>(addr)) + } + public fun item_exists(addr: address): bool { + exists>(addr) + } + public fun save_item(owner: &signer,f: F) { + MoveTo>(owner, pack mod2::Registry(f)); + Tuple() + } +} // end 0x42::mod2 +module 0x42::mod3 { + use std::signer; + struct MyStruct1 { + x: u64, + } + struct MyStruct2 { + y: u8, + } + public fun test_item1(owner: signer) { + mod3::test_items(owner, true); + Tuple() + } + public fun test_item2(owner: signer) { + mod3::test_items(owner, false); + Tuple() + } + public fun test_items(owner: signer,use_1: bool) { + { + let struct1: MyStruct1 = pack mod3::MyStruct1(3); + { + let f1: |address|bool with copy+store = move|addr: address| mod2::item_exists(addr) with copy, drop, store; + { + let f2: |address|bool with copy+store = move|addr: address| mod2::item_exists(addr) with copy, drop, store; + { + let addr: address = signer::address_of(Borrow(Immutable)(owner)); + mod2::save_item(Borrow(Immutable)(owner), struct1); + MoveTo(Borrow(Immutable)(owner), struct1); + if use_1 { + mod2::save_item<|address|bool with copy+store>(Borrow(Immutable)(owner), f1); + Tuple() + } else { + mod2::save_item<|address|bool with copy+store>(Borrow(Immutable)(owner), f2); + Tuple() + }; + if mod2::item_exists<|address|bool with copy+store>(addr) { + Tuple() + } else { + Abort(14566554180833181696) + }; + { + let found_f: |address|bool with copy+store = mod2::get_item<|address|bool with copy+store>(addr); + if Eq(use_1, (found_f)(addr)) { + Tuple() + } else { + Abort(14566554180833181696) + }; + Tuple() + } + } + } + } + } + } +} // end 0x42::mod3 + + +// -- Model dump after env processor acquires check: +module 0x42::mod2 { + struct Registry { + func: F, + } + public fun get_item(addr: address): F + acquires Registry(*) + { + select mod2::Registry.func<&Registry>(BorrowGlobal(Immutable)>(addr)) + } + public fun item_exists(addr: address): bool { + exists>(addr) + } + public fun save_item(owner: &signer,f: F) { + MoveTo>(owner, pack mod2::Registry(f)); + Tuple() + } +} // end 0x42::mod2 +module 0x42::mod3 { + use std::signer; + struct MyStruct1 { + x: u64, + } + struct MyStruct2 { + y: u8, + } + public fun test_item1(owner: signer) { + mod3::test_items(owner, true); + Tuple() + } + public fun test_item2(owner: signer) { + mod3::test_items(owner, false); + Tuple() + } + public fun test_items(owner: signer,use_1: bool) { + { + let struct1: MyStruct1 = pack mod3::MyStruct1(3); + { + let f1: |address|bool with copy+store = move|addr: address| mod2::item_exists(addr) with copy, drop, store; + { + let f2: |address|bool with copy+store = move|addr: address| mod2::item_exists(addr) with copy, drop, store; + { + let addr: address = signer::address_of(Borrow(Immutable)(owner)); + mod2::save_item(Borrow(Immutable)(owner), struct1); + MoveTo(Borrow(Immutable)(owner), struct1); + if use_1 { + mod2::save_item<|address|bool with copy+store>(Borrow(Immutable)(owner), f1); + Tuple() + } else { + mod2::save_item<|address|bool with copy+store>(Borrow(Immutable)(owner), f2); + Tuple() + }; + if mod2::item_exists<|address|bool with copy+store>(addr) { + Tuple() + } else { + Abort(14566554180833181696) + }; + { + let found_f: |address|bool with copy+store = mod2::get_item<|address|bool with copy+store>(addr); + if Eq(use_1, (found_f)(addr)) { + Tuple() + } else { + Abort(14566554180833181696) + }; + Tuple() + } + } + } + } + } + } +} // end 0x42::mod3 + + +// -- Model dump after env processor simplifier: +module 0x42::mod2 { + struct Registry { + func: F, + } + public fun get_item(addr: address): F + acquires Registry(*) + { + select mod2::Registry.func<&Registry>(BorrowGlobal(Immutable)>(addr)) + } + public fun item_exists(addr: address): bool { + exists>(addr) + } + public fun save_item(owner: &signer,f: F) { + MoveTo>(owner, pack mod2::Registry(f)); + Tuple() + } +} // end 0x42::mod2 +module 0x42::mod3 { + use std::signer; + struct MyStruct1 { + x: u64, + } + struct MyStruct2 { + y: u8, + } + public fun test_item1(owner: signer) { + mod3::test_items(owner, true); + Tuple() + } + public fun test_item2(owner: signer) { + mod3::test_items(owner, false); + Tuple() + } + public fun test_items(owner: signer,use_1: bool) { + { + let struct1: MyStruct1 = pack mod3::MyStruct1(3); + { + let f1: |address|bool with copy+store = move|addr: address| mod2::item_exists(addr) with copy, drop, store; + { + let f2: |address|bool with copy+store = move|addr: address| mod2::item_exists(addr) with copy, drop, store; + { + let addr: address = signer::address_of(Borrow(Immutable)(owner)); + mod2::save_item(Borrow(Immutable)(owner), struct1); + MoveTo(Borrow(Immutable)(owner), struct1); + if use_1 { + mod2::save_item<|address|bool with copy+store>(Borrow(Immutable)(owner), f1); + Tuple() + } else { + mod2::save_item<|address|bool with copy+store>(Borrow(Immutable)(owner), f2); + Tuple() + }; + if mod2::item_exists<|address|bool with copy+store>(addr) { + Tuple() + } else { + Abort(14566554180833181696) + }; + { + let found_f: |address|bool with copy+store = mod2::get_item<|address|bool with copy+store>(addr); + if Eq(use_1, (found_f)(addr)) { + Tuple() + } else { + Abort(14566554180833181696) + }; + Tuple() + } + } + } + } + } + } +} // end 0x42::mod3 + + +// -- Model dump after env processor lambda-lifting: +module 0x42::mod2 { + struct Registry { + func: F, + } + public fun get_item(addr: address): F + acquires Registry(*) + { + select mod2::Registry.func<&Registry>(BorrowGlobal(Immutable)>(addr)) + } + public fun item_exists(addr: address): bool { + exists>(addr) + } + public fun save_item(owner: &signer,f: F) { + MoveTo>(owner, pack mod2::Registry(f)); + Tuple() + } +} // end 0x42::mod2 +module 0x42::mod3 { + use std::signer; + struct MyStruct1 { + x: u64, + } + struct MyStruct2 { + y: u8, + } + public fun test_item1(owner: signer) { + mod3::test_items(owner, true); + Tuple() + } + public fun test_item2(owner: signer) { + mod3::test_items(owner, false); + Tuple() + } + public fun test_items(owner: signer,use_1: bool) { + { + let struct1: MyStruct1 = pack mod3::MyStruct1(3); + { + let f1: |address|bool with copy+store = mod2::item_exists; + { + let f2: |address|bool with copy+store = mod2::item_exists; + { + let addr: address = signer::address_of(Borrow(Immutable)(owner)); + mod2::save_item(Borrow(Immutable)(owner), struct1); + MoveTo(Borrow(Immutable)(owner), struct1); + if use_1 { + mod2::save_item<|address|bool with copy+store>(Borrow(Immutable)(owner), f1); + Tuple() + } else { + mod2::save_item<|address|bool with copy+store>(Borrow(Immutable)(owner), f2); + Tuple() + }; + if mod2::item_exists<|address|bool with copy+store>(addr) { + Tuple() + } else { + Abort(14566554180833181696) + }; + { + let found_f: |address|bool with copy+store = mod2::get_item<|address|bool with copy+store>(addr); + if Eq(use_1, (found_f)(addr)) { + Tuple() + } else { + Abort(14566554180833181696) + }; + Tuple() + } + } + } + } + } + } +} // end 0x42::mod3 + + +// -- Model dump after env processor specification checker: +module 0x42::mod2 { + struct Registry { + func: F, + } + public fun get_item(addr: address): F + acquires Registry(*) + { + select mod2::Registry.func<&Registry>(BorrowGlobal(Immutable)>(addr)) + } + public fun item_exists(addr: address): bool { + exists>(addr) + } + public fun save_item(owner: &signer,f: F) { + MoveTo>(owner, pack mod2::Registry(f)); + Tuple() + } +} // end 0x42::mod2 +module 0x42::mod3 { + use std::signer; + struct MyStruct1 { + x: u64, + } + struct MyStruct2 { + y: u8, + } + public fun test_item1(owner: signer) { + mod3::test_items(owner, true); + Tuple() + } + public fun test_item2(owner: signer) { + mod3::test_items(owner, false); + Tuple() + } + public fun test_items(owner: signer,use_1: bool) { + { + let struct1: MyStruct1 = pack mod3::MyStruct1(3); + { + let f1: |address|bool with copy+store = mod2::item_exists; + { + let f2: |address|bool with copy+store = mod2::item_exists; + { + let addr: address = signer::address_of(Borrow(Immutable)(owner)); + mod2::save_item(Borrow(Immutable)(owner), struct1); + MoveTo(Borrow(Immutable)(owner), struct1); + if use_1 { + mod2::save_item<|address|bool with copy+store>(Borrow(Immutable)(owner), f1); + Tuple() + } else { + mod2::save_item<|address|bool with copy+store>(Borrow(Immutable)(owner), f2); + Tuple() + }; + if mod2::item_exists<|address|bool with copy+store>(addr) { + Tuple() + } else { + Abort(14566554180833181696) + }; + { + let found_f: |address|bool with copy+store = mod2::get_item<|address|bool with copy+store>(addr); + if Eq(use_1, (found_f)(addr)) { + Tuple() + } else { + Abort(14566554180833181696) + }; + Tuple() + } + } + } + } + } + } +} // end 0x42::mod3 + + +// -- Model dump after env processor specification rewriter: +module 0x42::mod2 { + struct Registry { + func: F, + } + public fun get_item(addr: address): F + acquires Registry(*) + { + select mod2::Registry.func<&Registry>(BorrowGlobal(Immutable)>(addr)) + } + public fun item_exists(addr: address): bool { + exists>(addr) + } + public fun save_item(owner: &signer,f: F) { + MoveTo>(owner, pack mod2::Registry(f)); + Tuple() + } +} // end 0x42::mod2 +module 0x42::mod3 { + use std::signer; + struct MyStruct1 { + x: u64, + } + struct MyStruct2 { + y: u8, + } + public fun test_item1(owner: signer) { + mod3::test_items(owner, true); + Tuple() + } + public fun test_item2(owner: signer) { + mod3::test_items(owner, false); + Tuple() + } + public fun test_items(owner: signer,use_1: bool) { + { + let struct1: MyStruct1 = pack mod3::MyStruct1(3); + { + let f1: |address|bool with copy+store = mod2::item_exists; + { + let f2: |address|bool with copy+store = mod2::item_exists; + { + let addr: address = signer::address_of(Borrow(Immutable)(owner)); + mod2::save_item(Borrow(Immutable)(owner), struct1); + MoveTo(Borrow(Immutable)(owner), struct1); + if use_1 { + mod2::save_item<|address|bool with copy+store>(Borrow(Immutable)(owner), f1); + Tuple() + } else { + mod2::save_item<|address|bool with copy+store>(Borrow(Immutable)(owner), f2); + Tuple() + }; + if mod2::item_exists<|address|bool with copy+store>(addr) { + Tuple() + } else { + Abort(14566554180833181696) + }; + { + let found_f: |address|bool with copy+store = mod2::get_item<|address|bool with copy+store>(addr); + if Eq(use_1, (found_f)(addr)) { + Tuple() + } else { + Abort(14566554180833181696) + }; + Tuple() + } + } + } + } + } + } +} // end 0x42::mod3 + + + +Diagnostics: +error: Function-typed values not yet implemented except as parameters to calls to inline functions + ┌─ tests/lambda/storable/generic_func.move:36:30 + │ +36 │ let f1 = move |addr| 0x42::mod2::item_exists(addr) with store+copy; + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Function-typed values not yet implemented except as parameters to calls to inline functions + ┌─ tests/lambda/storable/generic_func.move:37:30 + │ +37 │ let f2 = move |addr| 0x42::mod2::item_exists(addr) with store+copy; + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Calls to function values other than inline function parameters not yet implemented + ┌─ tests/lambda/storable/generic_func.move:57:26 + │ +57 │ assert!(use_1 == found_f(addr)); + │ ^^^^^^^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/generic_func.move b/third_party/move/move-compiler-v2/tests/lambda/storable/generic_func.move new file mode 100644 index 0000000000000..b7d3baf9f610a --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/generic_func.move @@ -0,0 +1,71 @@ +//# publish --print-bytecode +module 0x42::mod2 { + struct Registry has key, store { + func: F + } + + public fun save_item(owner: &signer, f: F) { + move_to>(owner, Registry { func: f }); + } + + public fun item_exists(addr: address): bool { + exists>(addr) + } + + public fun get_item(addr: address): F acquires Registry { + borrow_global>(addr).func + } +} + +//# publish --print-bytecode +module 0x42::mod3 { + use std::signer; + + struct MyStruct1 has key, store, copy { + x: u64 + } + + struct MyStruct2 has key, store, copy { + y: u8 + } + + public fun test_items(owner: signer, use_1: bool) { + let struct1 = MyStruct1 { x: 3 }; + // let struct2 = MyStruct2 { y: 2 }; + + let f1 = move |addr| 0x42::mod2::item_exists(addr) with store+copy; + let f2 = move |addr| 0x42::mod2::item_exists(addr) with store+copy; + + let addr = signer::address_of(&owner); + 0x42::mod2::save_item(&owner, struct1); + + // Store just MyStruct1 + move_to(&owner, struct1); + + // Store f1 or f2, depending on use_1 + if (use_1) { + 0x42::mod2::save_item(&owner, f1); + } else { + 0x42::mod2::save_item(&owner, f2); + }; + + // In either case, item exists + assert!(0x42::mod2::item_exists<|address|bool with store+copy>(addr)); + + let found_f = 0x42::mod2::get_item<|address|bool with store+copy>(addr); + + assert!(use_1 == found_f(addr)); + } + + public fun test_item1(owner: signer) { + test_items(owner, true); + } + + public fun test_item2(owner: signer) { + test_items(owner, false); + } +} + +//# run --signers 0x42 -- 0x42::mod3::test_item1 + +//# run --signers 0x42 -- 0x42::mod3::test_item2 diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/constants/large_vectors.baseline.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/constants/large_vectors.baseline.exp new file mode 100644 index 0000000000000..12987590c3a8f --- /dev/null +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/constants/large_vectors.baseline.exp @@ -0,0 +1,9 @@ +processed 3 tasks + +task 1 'run'. lines 17-17: +return values: 1027 + +task 2 'run'. lines 19-19: +return values: 1025 + +==> Compiler v2 delivered same results! diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/deep_exp.baseline.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/deep_exp.baseline.exp new file mode 100644 index 0000000000000..baae5717928b6 --- /dev/null +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/deep_exp.baseline.exp @@ -0,0 +1,6 @@ +processed 2 tasks + +task 1 'run'. lines 30-30: +return values: 625 + +==> Compiler v2 delivered same results! diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/lambda/generic_func.baseline.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/lambda/generic_func.baseline.exp new file mode 100644 index 0000000000000..9ced3f98e15e0 --- /dev/null +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/lambda/generic_func.baseline.exp @@ -0,0 +1,71 @@ +comparison between v1 and v2 failed: += processed 4 tasks += += task 0 'publish'. lines 1-18: += += += += task 1 'publish'. lines 20-67: +- Error: error[E01013]: unsupported language construct ++ Error: compilation errors: ++ error: unsupported language construct += ┌─ TEMPFILE1:32:18 += │ += 32 │ let f1 = move |addr| 0x42::mod2::item_exists(addr) with store+copy; += │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression += +- error[E01013]: unsupported language construct ++ error: unsupported language construct += ┌─ TEMPFILE1:32:71 += │ += 32 │ let f1 = move |addr| 0x42::mod2::item_exists(addr) with store+copy; += │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions += +- error[E01013]: unsupported language construct ++ error: unsupported language construct += ┌─ TEMPFILE1:33:18 += │ += 33 │ let f2 = move |addr| 0x42::mod2::item_exists(addr) with store+copy; += │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression += +- error[E01013]: unsupported language construct ++ error: unsupported language construct += ┌─ TEMPFILE1:33:71 += │ += 33 │ let f2 = move |addr| 0x42::mod2::item_exists(addr) with store+copy; += │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions += +- error[E01013]: unsupported language construct ++ error: unsupported language construct += ┌─ TEMPFILE1:45:55 += │ += 45 │ assert!(0x42::mod2::item_exists<|address|bool with store+copy>(addr)); += │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types += +- error[E01013]: unsupported language construct ++ error: unsupported language construct += ┌─ TEMPFILE1:46:58 += │ += 46 │ let found_f = 0x42::mod2::get_item<|address|bool with store+copy>(addr); += │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types += += += += task 2 'run'. lines 69-69: += Error: Function execution failed with VMError: { += major_status: LINKER_ERROR, += sub_status: None, += location: undefined, += indices: redacted, += offsets: redacted, += } += += task 3 'run'. lines 71-71: += Error: Function execution failed with VMError: { += major_status: LINKER_ERROR, += sub_status: None, += location: undefined, += indices: redacted, += offsets: redacted, += } += diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/lambda/generic_func.lambda.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/lambda/generic_func.lambda.exp new file mode 100644 index 0000000000000..14ffdb0cb55b1 --- /dev/null +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/lambda/generic_func.lambda.exp @@ -0,0 +1,75 @@ +comparison between v1 and v2 failed: += processed 4 tasks += += task 0 'publish'. lines 1-18: += += += += task 1 'publish'. lines 20-67: +- Error: error[E01013]: unsupported language construct +- ┌─ TEMPFILE1:32:18 ++ Error: compilation errors: ++ error: Function-typed values not yet implemented except as parameters to calls to inline functions ++ ┌─ TEMPFILE1:32:30 += │ += 32 │ let f1 = move |addr| 0x42::mod2::item_exists(addr) with store+copy; +- │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression ++ │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ += +- error[E01013]: unsupported language construct +- ┌─ TEMPFILE1:32:71 ++ error: Function-typed values not yet implemented except as parameters to calls to inline functions ++ ┌─ TEMPFILE1:33:30 += │ +- 32 │ let f1 = move |addr| 0x42::mod2::item_exists(addr) with store+copy; +- │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions +- +- error[E01013]: unsupported language construct +- ┌─ TEMPFILE1:33:18 +- │ += 33 │ let f2 = move |addr| 0x42::mod2::item_exists(addr) with store+copy; +- │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression ++ │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ += +- error[E01013]: unsupported language construct +- ┌─ TEMPFILE1:33:71 ++ error: Calls to function values other than inline function parameters not yet implemented ++ ┌─ TEMPFILE1:47:26 += │ +- 33 │ let f2 = move |addr| 0x42::mod2::item_exists(addr) with store+copy; +- │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions ++ 47 │ assert!(use_1 == found_f(addr)); ++ │ ^^^^^^^^^^^^^ += +- error[E01013]: unsupported language construct +- ┌─ TEMPFILE1:45:55 +- │ +- 45 │ assert!(0x42::mod2::item_exists<|address|bool with store+copy>(addr)); +- │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types += +- error[E01013]: unsupported language construct +- ┌─ TEMPFILE1:46:58 +- │ +- 46 │ let found_f = 0x42::mod2::get_item<|address|bool with store+copy>(addr); +- │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types += +- +- += task 2 'run'. lines 69-69: += Error: Function execution failed with VMError: { += major_status: LINKER_ERROR, += sub_status: None, += location: undefined, += indices: redacted, += offsets: redacted, += } += += task 3 'run'. lines 71-71: += Error: Function execution failed with VMError: { += major_status: LINKER_ERROR, += sub_status: None, += location: undefined, += indices: redacted, += offsets: redacted, += } += diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/lambda/generic_func.move b/third_party/move/move-compiler-v2/transactional-tests/tests/lambda/generic_func.move new file mode 100644 index 0000000000000..b7d3baf9f610a --- /dev/null +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/lambda/generic_func.move @@ -0,0 +1,71 @@ +//# publish --print-bytecode +module 0x42::mod2 { + struct Registry has key, store { + func: F + } + + public fun save_item(owner: &signer, f: F) { + move_to>(owner, Registry { func: f }); + } + + public fun item_exists(addr: address): bool { + exists>(addr) + } + + public fun get_item(addr: address): F acquires Registry { + borrow_global>(addr).func + } +} + +//# publish --print-bytecode +module 0x42::mod3 { + use std::signer; + + struct MyStruct1 has key, store, copy { + x: u64 + } + + struct MyStruct2 has key, store, copy { + y: u8 + } + + public fun test_items(owner: signer, use_1: bool) { + let struct1 = MyStruct1 { x: 3 }; + // let struct2 = MyStruct2 { y: 2 }; + + let f1 = move |addr| 0x42::mod2::item_exists(addr) with store+copy; + let f2 = move |addr| 0x42::mod2::item_exists(addr) with store+copy; + + let addr = signer::address_of(&owner); + 0x42::mod2::save_item(&owner, struct1); + + // Store just MyStruct1 + move_to(&owner, struct1); + + // Store f1 or f2, depending on use_1 + if (use_1) { + 0x42::mod2::save_item(&owner, f1); + } else { + 0x42::mod2::save_item(&owner, f2); + }; + + // In either case, item exists + assert!(0x42::mod2::item_exists<|address|bool with store+copy>(addr)); + + let found_f = 0x42::mod2::get_item<|address|bool with store+copy>(addr); + + assert!(use_1 == found_f(addr)); + } + + public fun test_item1(owner: signer) { + test_items(owner, true); + } + + public fun test_item2(owner: signer) { + test_items(owner, false); + } +} + +//# run --signers 0x42 -- 0x42::mod3::test_item1 + +//# run --signers 0x42 -- 0x42::mod3::test_item2 diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/lambda/generic_func.no-optimize.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/lambda/generic_func.no-optimize.exp new file mode 100644 index 0000000000000..9ced3f98e15e0 --- /dev/null +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/lambda/generic_func.no-optimize.exp @@ -0,0 +1,71 @@ +comparison between v1 and v2 failed: += processed 4 tasks += += task 0 'publish'. lines 1-18: += += += += task 1 'publish'. lines 20-67: +- Error: error[E01013]: unsupported language construct ++ Error: compilation errors: ++ error: unsupported language construct += ┌─ TEMPFILE1:32:18 += │ += 32 │ let f1 = move |addr| 0x42::mod2::item_exists(addr) with store+copy; += │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression += +- error[E01013]: unsupported language construct ++ error: unsupported language construct += ┌─ TEMPFILE1:32:71 += │ += 32 │ let f1 = move |addr| 0x42::mod2::item_exists(addr) with store+copy; += │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions += +- error[E01013]: unsupported language construct ++ error: unsupported language construct += ┌─ TEMPFILE1:33:18 += │ += 33 │ let f2 = move |addr| 0x42::mod2::item_exists(addr) with store+copy; += │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression += +- error[E01013]: unsupported language construct ++ error: unsupported language construct += ┌─ TEMPFILE1:33:71 += │ += 33 │ let f2 = move |addr| 0x42::mod2::item_exists(addr) with store+copy; += │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions += +- error[E01013]: unsupported language construct ++ error: unsupported language construct += ┌─ TEMPFILE1:45:55 += │ += 45 │ assert!(0x42::mod2::item_exists<|address|bool with store+copy>(addr)); += │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types += +- error[E01013]: unsupported language construct ++ error: unsupported language construct += ┌─ TEMPFILE1:46:58 += │ += 46 │ let found_f = 0x42::mod2::get_item<|address|bool with store+copy>(addr); += │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types += += += += task 2 'run'. lines 69-69: += Error: Function execution failed with VMError: { += major_status: LINKER_ERROR, += sub_status: None, += location: undefined, += indices: redacted, += offsets: redacted, += } += += task 3 'run'. lines 71-71: += Error: Function execution failed with VMError: { += major_status: LINKER_ERROR, += sub_status: None, += location: undefined, += indices: redacted, += offsets: redacted, += } += diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/lambda/generic_func.optimize-no-simplify.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/lambda/generic_func.optimize-no-simplify.exp new file mode 100644 index 0000000000000..9ced3f98e15e0 --- /dev/null +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/lambda/generic_func.optimize-no-simplify.exp @@ -0,0 +1,71 @@ +comparison between v1 and v2 failed: += processed 4 tasks += += task 0 'publish'. lines 1-18: += += += += task 1 'publish'. lines 20-67: +- Error: error[E01013]: unsupported language construct ++ Error: compilation errors: ++ error: unsupported language construct += ┌─ TEMPFILE1:32:18 += │ += 32 │ let f1 = move |addr| 0x42::mod2::item_exists(addr) with store+copy; += │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression += +- error[E01013]: unsupported language construct ++ error: unsupported language construct += ┌─ TEMPFILE1:32:71 += │ += 32 │ let f1 = move |addr| 0x42::mod2::item_exists(addr) with store+copy; += │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions += +- error[E01013]: unsupported language construct ++ error: unsupported language construct += ┌─ TEMPFILE1:33:18 += │ += 33 │ let f2 = move |addr| 0x42::mod2::item_exists(addr) with store+copy; += │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression += +- error[E01013]: unsupported language construct ++ error: unsupported language construct += ┌─ TEMPFILE1:33:71 += │ += 33 │ let f2 = move |addr| 0x42::mod2::item_exists(addr) with store+copy; += │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions += +- error[E01013]: unsupported language construct ++ error: unsupported language construct += ┌─ TEMPFILE1:45:55 += │ += 45 │ assert!(0x42::mod2::item_exists<|address|bool with store+copy>(addr)); += │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types += +- error[E01013]: unsupported language construct ++ error: unsupported language construct += ┌─ TEMPFILE1:46:58 += │ += 46 │ let found_f = 0x42::mod2::get_item<|address|bool with store+copy>(addr); += │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types += += += += task 2 'run'. lines 69-69: += Error: Function execution failed with VMError: { += major_status: LINKER_ERROR, += sub_status: None, += location: undefined, += indices: redacted, += offsets: redacted, += } += += task 3 'run'. lines 71-71: += Error: Function execution failed with VMError: { += major_status: LINKER_ERROR, += sub_status: None, += location: undefined, += indices: redacted, += offsets: redacted, += } += diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/lambda/generic_func.optimize.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/lambda/generic_func.optimize.exp new file mode 100644 index 0000000000000..9ced3f98e15e0 --- /dev/null +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/lambda/generic_func.optimize.exp @@ -0,0 +1,71 @@ +comparison between v1 and v2 failed: += processed 4 tasks += += task 0 'publish'. lines 1-18: += += += += task 1 'publish'. lines 20-67: +- Error: error[E01013]: unsupported language construct ++ Error: compilation errors: ++ error: unsupported language construct += ┌─ TEMPFILE1:32:18 += │ += 32 │ let f1 = move |addr| 0x42::mod2::item_exists(addr) with store+copy; += │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression += +- error[E01013]: unsupported language construct ++ error: unsupported language construct += ┌─ TEMPFILE1:32:71 += │ += 32 │ let f1 = move |addr| 0x42::mod2::item_exists(addr) with store+copy; += │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions += +- error[E01013]: unsupported language construct ++ error: unsupported language construct += ┌─ TEMPFILE1:33:18 += │ += 33 │ let f2 = move |addr| 0x42::mod2::item_exists(addr) with store+copy; += │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression += +- error[E01013]: unsupported language construct ++ error: unsupported language construct += ┌─ TEMPFILE1:33:71 += │ += 33 │ let f2 = move |addr| 0x42::mod2::item_exists(addr) with store+copy; += │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions += +- error[E01013]: unsupported language construct ++ error: unsupported language construct += ┌─ TEMPFILE1:45:55 += │ += 45 │ assert!(0x42::mod2::item_exists<|address|bool with store+copy>(addr)); += │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types += +- error[E01013]: unsupported language construct ++ error: unsupported language construct += ┌─ TEMPFILE1:46:58 += │ += 46 │ let found_f = 0x42::mod2::get_item<|address|bool with store+copy>(addr); += │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types += += += += task 2 'run'. lines 69-69: += Error: Function execution failed with VMError: { += major_status: LINKER_ERROR, += sub_status: None, += location: undefined, += indices: redacted, += offsets: redacted, += } += += task 3 'run'. lines 71-71: += Error: Function execution failed with VMError: { += major_status: LINKER_ERROR, += sub_status: None, += location: undefined, += indices: redacted, += offsets: redacted, += } += diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/misc/bug_14243_stack_size.baseline.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/misc/bug_14243_stack_size.baseline.exp new file mode 100644 index 0000000000000..5644195ea665d --- /dev/null +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/misc/bug_14243_stack_size.baseline.exp @@ -0,0 +1,32 @@ +processed 1 task + +task 0 'print-bytecode'. lines 2-14: +// Move bytecode v7 +module c0ffee.m { + + +id_mut(Arg0: &mut Ty0): &mut Ty0 /* def_idx: 0 */ { +B0: + 0: MoveLoc[0](Arg0: &mut Ty0) + 1: Ret +} +t0() /* def_idx: 1 */ { +L0: loc0: u64 +L1: loc1: &mut u64 +B0: + 0: LdU64(0) + 1: StLoc[0](loc0: u64) + 2: MutBorrowLoc[0](loc0: u64) + 3: StLoc[1](loc1: &mut u64) + 4: CopyLoc[1](loc1: &mut u64) + 5: Call id_mut(&mut u64): &mut u64 + 6: ReadRef + 7: Pop + 8: MoveLoc[1](loc1: &mut u64) + 9: ReadRef + 10: Pop + 11: Ret +} +} + +==> Compiler v2 delivered same results! diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/dynamic.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/dynamic.no-optimize-no-acquires-check.exp similarity index 100% rename from third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/dynamic.exp rename to third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/dynamic.no-optimize-no-acquires-check.exp diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/dynamic.optimize-no-acquires-check.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/dynamic.optimize-no-acquires-check.exp new file mode 100644 index 0000000000000..45fc0b41c318d --- /dev/null +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/dynamic.optimize-no-acquires-check.exp @@ -0,0 +1,29 @@ +processed 6 tasks + +task 2 'run'. lines 30-30: +return values: true + +task 3 'run'. lines 32-32: +return values: true + +task 4 'run'. lines 34-34: +Error: Function execution failed with VMError: { + message: not allowed to perform `reads 0x42::test::R(@0x2)`, + major_status: ACCESS_DENIED, + sub_status: None, + location: 0x42::test, + indices: [], + offsets: [(FunctionDefinitionIndex(1), 1)], + exec_state: Some(ExecutionState { stack_trace: [] }), +} + +task 5 'run'. lines 36-36: +Error: Function execution failed with VMError: { + message: not allowed to perform `reads 0x42::test::R(@0x2)`, + major_status: ACCESS_DENIED, + sub_status: None, + location: 0x42::test, + indices: [], + offsets: [(FunctionDefinitionIndex(2), 3)], + exec_state: Some(ExecutionState { stack_trace: [] }), +} diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/dynamic.optimize-no-simplify-no-acquires-check.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/dynamic.optimize-no-simplify-no-acquires-check.exp new file mode 100644 index 0000000000000..45fc0b41c318d --- /dev/null +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/dynamic.optimize-no-simplify-no-acquires-check.exp @@ -0,0 +1,29 @@ +processed 6 tasks + +task 2 'run'. lines 30-30: +return values: true + +task 3 'run'. lines 32-32: +return values: true + +task 4 'run'. lines 34-34: +Error: Function execution failed with VMError: { + message: not allowed to perform `reads 0x42::test::R(@0x2)`, + major_status: ACCESS_DENIED, + sub_status: None, + location: 0x42::test, + indices: [], + offsets: [(FunctionDefinitionIndex(1), 1)], + exec_state: Some(ExecutionState { stack_trace: [] }), +} + +task 5 'run'. lines 36-36: +Error: Function execution failed with VMError: { + message: not allowed to perform `reads 0x42::test::R(@0x2)`, + major_status: ACCESS_DENIED, + sub_status: None, + location: 0x42::test, + indices: [], + offsets: [(FunctionDefinitionIndex(2), 3)], + exec_state: Some(ExecutionState { stack_trace: [] }), +} diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/generic.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/generic.no-optimize-no-acquires-check.exp similarity index 100% rename from third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/generic.exp rename to third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/generic.no-optimize-no-acquires-check.exp diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/generic.optimize-no-acquires-check.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/generic.optimize-no-acquires-check.exp new file mode 100644 index 0000000000000..041671d6c1dfc --- /dev/null +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/generic.optimize-no-acquires-check.exp @@ -0,0 +1,18 @@ +processed 5 tasks + +task 2 'run'. lines 25-25: +return values: true + +task 3 'run'. lines 27-27: +return values: true + +task 4 'run'. lines 29-29: +Error: Function execution failed with VMError: { + message: not allowed to perform `reads 0x42::test::R(@0x1)`, + major_status: ACCESS_DENIED, + sub_status: None, + location: 0x42::test, + indices: [], + offsets: [(FunctionDefinitionIndex(1), 1)], + exec_state: Some(ExecutionState { stack_trace: [] }), +} diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/generic.optimize-no-simplify-no-acquires-check.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/generic.optimize-no-simplify-no-acquires-check.exp new file mode 100644 index 0000000000000..041671d6c1dfc --- /dev/null +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/generic.optimize-no-simplify-no-acquires-check.exp @@ -0,0 +1,18 @@ +processed 5 tasks + +task 2 'run'. lines 25-25: +return values: true + +task 3 'run'. lines 27-27: +return values: true + +task 4 'run'. lines 29-29: +Error: Function execution failed with VMError: { + message: not allowed to perform `reads 0x42::test::R(@0x1)`, + major_status: ACCESS_DENIED, + sub_status: None, + location: 0x42::test, + indices: [], + offsets: [(FunctionDefinitionIndex(1), 1)], + exec_state: Some(ExecutionState { stack_trace: [] }), +} diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/negation.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/negation.no-optimize-no-acquires-check.exp similarity index 100% rename from third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/negation.exp rename to third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/negation.no-optimize-no-acquires-check.exp diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/negation.optimize-no-acquires-check.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/negation.optimize-no-acquires-check.exp new file mode 100644 index 0000000000000..83fdf74d58abe --- /dev/null +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/negation.optimize-no-acquires-check.exp @@ -0,0 +1,29 @@ +processed 6 tasks + +task 2 'run'. lines 28-28: +return values: true + +task 3 'run'. lines 30-30: +return values: true + +task 4 'run'. lines 32-32: +Error: Function execution failed with VMError: { + message: not allowed to perform `reads 0x42::test::R(@0x1)`, + major_status: ACCESS_DENIED, + sub_status: None, + location: 0x42::test, + indices: [], + offsets: [(FunctionDefinitionIndex(1), 1)], + exec_state: Some(ExecutionState { stack_trace: [] }), +} + +task 5 'run'. lines 34-34: +Error: Function execution failed with VMError: { + message: not allowed to perform `reads 0x42::test::R(@0x1)`, + major_status: ACCESS_DENIED, + sub_status: None, + location: 0x42::test, + indices: [], + offsets: [(FunctionDefinitionIndex(2), 1)], + exec_state: Some(ExecutionState { stack_trace: [] }), +} diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/negation.optimize-no-simplify-no-acquires-check.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/negation.optimize-no-simplify-no-acquires-check.exp new file mode 100644 index 0000000000000..83fdf74d58abe --- /dev/null +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/negation.optimize-no-simplify-no-acquires-check.exp @@ -0,0 +1,29 @@ +processed 6 tasks + +task 2 'run'. lines 28-28: +return values: true + +task 3 'run'. lines 30-30: +return values: true + +task 4 'run'. lines 32-32: +Error: Function execution failed with VMError: { + message: not allowed to perform `reads 0x42::test::R(@0x1)`, + major_status: ACCESS_DENIED, + sub_status: None, + location: 0x42::test, + indices: [], + offsets: [(FunctionDefinitionIndex(1), 1)], + exec_state: Some(ExecutionState { stack_trace: [] }), +} + +task 5 'run'. lines 34-34: +Error: Function execution failed with VMError: { + message: not allowed to perform `reads 0x42::test::R(@0x1)`, + major_status: ACCESS_DENIED, + sub_status: None, + location: 0x42::test, + indices: [], + offsets: [(FunctionDefinitionIndex(2), 1)], + exec_state: Some(ExecutionState { stack_trace: [] }), +} diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/resource.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/resource.no-optimize-no-acquires-check.exp similarity index 100% rename from third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/resource.exp rename to third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/resource.no-optimize-no-acquires-check.exp diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/resource.optimize-no-acquires-check.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/resource.optimize-no-acquires-check.exp new file mode 100644 index 0000000000000..ab23755203d71 --- /dev/null +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/resource.optimize-no-acquires-check.exp @@ -0,0 +1,71 @@ +processed 12 tasks + +task 2 'run'. lines 63-63: +return values: true + +task 3 'run'. lines 65-65: +return values: true + +task 4 'run'. lines 67-67: +return values: true + +task 5 'run'. lines 69-69: +return values: true + +task 6 'run'. lines 71-71: +return values: true + +task 7 'run'. lines 73-73: +Error: Function execution failed with VMError: { + message: not allowed to perform `reads 0x42::test::R(@0x1)`, + major_status: ACCESS_DENIED, + sub_status: None, + location: 0x42::test, + indices: [], + offsets: [(FunctionDefinitionIndex(1), 1)], + exec_state: Some(ExecutionState { stack_trace: [] }), +} + +task 8 'run'. lines 75-75: +Error: Function execution failed with VMError: { + message: not allowed to perform `reads 0x42::test::R(@0x1)`, + major_status: ACCESS_DENIED, + sub_status: None, + location: 0x42::test, + indices: [], + offsets: [(FunctionDefinitionIndex(2), 1)], + exec_state: Some(ExecutionState { stack_trace: [] }), +} + +task 9 'run'. lines 77-77: +Error: Function execution failed with VMError: { + message: not allowed to perform `writes 0x42::test::R(@0x1)`, + major_status: ACCESS_DENIED, + sub_status: None, + location: 0x42::test, + indices: [], + offsets: [(FunctionDefinitionIndex(3), 1)], + exec_state: Some(ExecutionState { stack_trace: [] }), +} + +task 10 'run'. lines 79-79: +Error: Function execution failed with VMError: { + message: not allowed to perform `writes 0x42::test::R(@0x1)`, + major_status: ACCESS_DENIED, + sub_status: None, + location: 0x42::test, + indices: [], + offsets: [(FunctionDefinitionIndex(4), 2)], + exec_state: Some(ExecutionState { stack_trace: [] }), +} + +task 11 'run'. lines 81-81: +Error: Function execution failed with VMError: { + message: not allowed to call `0x0000000000000000000000000000000000000000000000000000000000000042::test::fail_no_subsumes`, + major_status: ACCESS_DENIED, + sub_status: None, + location: undefined, + indices: [], + offsets: [], + exec_state: None, +} diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/resource.optimize-no-simplify-no-acquires-check.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/resource.optimize-no-simplify-no-acquires-check.exp new file mode 100644 index 0000000000000..ab23755203d71 --- /dev/null +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/resource.optimize-no-simplify-no-acquires-check.exp @@ -0,0 +1,71 @@ +processed 12 tasks + +task 2 'run'. lines 63-63: +return values: true + +task 3 'run'. lines 65-65: +return values: true + +task 4 'run'. lines 67-67: +return values: true + +task 5 'run'. lines 69-69: +return values: true + +task 6 'run'. lines 71-71: +return values: true + +task 7 'run'. lines 73-73: +Error: Function execution failed with VMError: { + message: not allowed to perform `reads 0x42::test::R(@0x1)`, + major_status: ACCESS_DENIED, + sub_status: None, + location: 0x42::test, + indices: [], + offsets: [(FunctionDefinitionIndex(1), 1)], + exec_state: Some(ExecutionState { stack_trace: [] }), +} + +task 8 'run'. lines 75-75: +Error: Function execution failed with VMError: { + message: not allowed to perform `reads 0x42::test::R(@0x1)`, + major_status: ACCESS_DENIED, + sub_status: None, + location: 0x42::test, + indices: [], + offsets: [(FunctionDefinitionIndex(2), 1)], + exec_state: Some(ExecutionState { stack_trace: [] }), +} + +task 9 'run'. lines 77-77: +Error: Function execution failed with VMError: { + message: not allowed to perform `writes 0x42::test::R(@0x1)`, + major_status: ACCESS_DENIED, + sub_status: None, + location: 0x42::test, + indices: [], + offsets: [(FunctionDefinitionIndex(3), 1)], + exec_state: Some(ExecutionState { stack_trace: [] }), +} + +task 10 'run'. lines 79-79: +Error: Function execution failed with VMError: { + message: not allowed to perform `writes 0x42::test::R(@0x1)`, + major_status: ACCESS_DENIED, + sub_status: None, + location: 0x42::test, + indices: [], + offsets: [(FunctionDefinitionIndex(4), 2)], + exec_state: Some(ExecutionState { stack_trace: [] }), +} + +task 11 'run'. lines 81-81: +Error: Function execution failed with VMError: { + message: not allowed to call `0x0000000000000000000000000000000000000000000000000000000000000042::test::fail_no_subsumes`, + major_status: ACCESS_DENIED, + sub_status: None, + location: undefined, + indices: [], + offsets: [], + exec_state: None, +} diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/wildcard.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/wildcard.no-optimize-no-acquires-check.exp similarity index 100% rename from third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/wildcard.exp rename to third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/wildcard.no-optimize-no-acquires-check.exp diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/wildcard.optimize-no-acquires-check.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/wildcard.optimize-no-acquires-check.exp new file mode 100644 index 0000000000000..aafc7de64f5ef --- /dev/null +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/wildcard.optimize-no-acquires-check.exp @@ -0,0 +1,35 @@ +processed 8 tasks + +task 2 'run'. lines 36-36: +return values: true + +task 3 'run'. lines 38-38: +return values: true + +task 4 'run'. lines 40-40: +return values: true + +task 5 'run'. lines 42-42: +return values: true + +task 6 'run'. lines 44-44: +Error: Function execution failed with VMError: { + message: not allowed to perform `reads 0x42::test::R(@0x1)`, + major_status: ACCESS_DENIED, + sub_status: None, + location: 0x42::test, + indices: [], + offsets: [(FunctionDefinitionIndex(1), 1)], + exec_state: Some(ExecutionState { stack_trace: [] }), +} + +task 7 'run'. lines 46-46: +Error: Function execution failed with VMError: { + message: not allowed to perform `reads 0x42::test::R(@0x1)`, + major_status: ACCESS_DENIED, + sub_status: None, + location: 0x42::test, + indices: [], + offsets: [(FunctionDefinitionIndex(2), 1)], + exec_state: Some(ExecutionState { stack_trace: [] }), +} diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/wildcard.optimize-no-simplify-no-acquires-check.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/wildcard.optimize-no-simplify-no-acquires-check.exp new file mode 100644 index 0000000000000..aafc7de64f5ef --- /dev/null +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/access_control/wildcard.optimize-no-simplify-no-acquires-check.exp @@ -0,0 +1,35 @@ +processed 8 tasks + +task 2 'run'. lines 36-36: +return values: true + +task 3 'run'. lines 38-38: +return values: true + +task 4 'run'. lines 40-40: +return values: true + +task 5 'run'. lines 42-42: +return values: true + +task 6 'run'. lines 44-44: +Error: Function execution failed with VMError: { + message: not allowed to perform `reads 0x42::test::R(@0x1)`, + major_status: ACCESS_DENIED, + sub_status: None, + location: 0x42::test, + indices: [], + offsets: [(FunctionDefinitionIndex(1), 1)], + exec_state: Some(ExecutionState { stack_trace: [] }), +} + +task 7 'run'. lines 46-46: +Error: Function execution failed with VMError: { + message: not allowed to perform `reads 0x42::test::R(@0x1)`, + major_status: ACCESS_DENIED, + sub_status: None, + location: 0x42::test, + indices: [], + offsets: [(FunctionDefinitionIndex(2), 1)], + exec_state: Some(ExecutionState { stack_trace: [] }), +} diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/assert_one.baseline.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/assert_one.baseline.exp new file mode 100644 index 0000000000000..2161a50d2b658 --- /dev/null +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/assert_one.baseline.exp @@ -0,0 +1,10 @@ +processed 2 tasks + +task 1 'run'. lines 21-34: +Error: Script execution failed with VMError: { + major_status: ABORTED, + sub_status: Some(14566554180833181696), + location: script, + indices: [], + offsets: [(FunctionDefinitionIndex(0), 27)], +} diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/enum/enum_field_select.baseline.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/enum/enum_field_select.baseline.exp new file mode 100644 index 0000000000000..bad82805f9bf7 --- /dev/null +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/enum/enum_field_select.baseline.exp @@ -0,0 +1,19 @@ +processed 5 tasks + +task 1 'run'. lines 37-37: +return values: 43 + +task 2 'run'. lines 39-39: +return values: 43 + +task 3 'run'. lines 41-41: +Error: Function execution failed with VMError: { + major_status: ABORTED, + sub_status: Some(33), + location: 0x42::m, + indices: [], + offsets: [(FunctionDefinitionIndex(0), 10)], +} + +task 4 'run'. lines 43-43: +return values: true diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/enum/enum_field_select_different_offsets.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/enum/enum_field_select_different_offsets.baseline.exp similarity index 100% rename from third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/enum/enum_field_select_different_offsets.exp rename to third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/enum/enum_field_select_different_offsets.baseline.exp diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/enum/enum_scoping.baseline.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/enum/enum_scoping.baseline.exp new file mode 100644 index 0000000000000..4cef654b4343a --- /dev/null +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/enum/enum_scoping.baseline.exp @@ -0,0 +1,37 @@ +processed 2 tasks + +task 0 'publish'. lines 1-43: +warning: Unused local variable `x`. Consider removing or prefixing with an underscore: `_x` + ┌─ TEMPFILE:20:17 + │ +20 │ let x = 4; + │ ^ + +warning: Unused local variable `i`. Consider removing or prefixing with an underscore: `_i` + ┌─ TEMPFILE:35:17 + │ +35 │ Two{i, b} => 3, + │ ^ + +warning: Unused local variable `b`. Consider removing or prefixing with an underscore: `_b` + ┌─ TEMPFILE:35:20 + │ +35 │ Two{i, b} => 3, + │ ^ + +warning: Unused assignment to `b`. Consider removing or prefixing with an underscore: `_b` + ┌─ TEMPFILE:35:13 + │ +35 │ Two{i, b} => 3, + │ ^^^^^^^^^ + +warning: Unused assignment to `i`. Consider removing or prefixing with an underscore: `_i` + ┌─ TEMPFILE:35:13 + │ +35 │ Two{i, b} => 3, + │ ^^^^^^^^^ + + + +task 1 'run'. lines 45-45: +return values: 3 diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/index.move b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/index.move index 66093ecfc1e56..310f791fad512 100644 --- a/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/index.move +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/index.move @@ -320,7 +320,7 @@ module 0x42::test { assert!(v[0].x == 8, 0); } - fun test_receiver() { + fun test_receiver() acquires S, W { let w = W { x: 3 }; @@ -352,7 +352,7 @@ module 0x42::test { move_to(signer, wrapper); } - fun test_receiver_2() { + fun test_receiver_2() acquires Wrapper { assert!(dispatch(@0x1) == 2, 0); let wrapper = Wrapper { inner: 2 diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/print_bytecode.baseline.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/print_bytecode.baseline.exp new file mode 100644 index 0000000000000..d9856e46d5951 --- /dev/null +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/no-v1-comparison/print_bytecode.baseline.exp @@ -0,0 +1,24 @@ +processed 2 tasks + +task 0 'print-bytecode'. lines 1-4: +// Move bytecode v7 +script { + + +main() /* def_idx: 0 */ { +B0: + 0: Ret +} +} + +task 1 'print-bytecode'. lines 6-11: +// Move bytecode v7 +module 3.N { + + +entry public ex(Arg0: signer, Arg1: u64) /* def_idx: 0 */ { +B0: + 0: LdU64(0) + 1: Abort +} +} diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/tests.rs b/third_party/move/move-compiler-v2/transactional-tests/tests/tests.rs index 340a2fc584682..0a7436e31bbff 100644 --- a/third_party/move/move-compiler-v2/transactional-tests/tests/tests.rs +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/tests.rs @@ -27,9 +27,8 @@ struct TestConfig { name: &'static str, runner: fn(&Path) -> datatest_stable::Result<()>, experiments: &'static [(&'static str, bool)], - /// Run the tests with language version 1 (if true), - /// or with latest language version (if false). - is_lang_v1: bool, + /// Run the tests with specified language version. + language_version: LanguageVersion, /// Path substrings for tests to include. If empty, all tests are included. include: &'static [&'static str], /// Path substrings for tests to exclude (applied after the include filter). @@ -37,29 +36,39 @@ struct TestConfig { exclude: &'static [&'static str], } +/// Note that any config which has different output for a test directory +/// *must* be added to the `SEPARATE_BASELINE` array below, so that a +/// special output file `test.foo.exp` will be generated for the output +/// of `test.move` for config `foo`. const TEST_CONFIGS: &[TestConfig] = &[ + // Matches all default experiments + TestConfig { + name: "baseline", + runner: |p| run(p, get_config_by_name("baseline")), + experiments: &[], + language_version: LanguageVersion::latest_stable(), + include: &[], + exclude: &["/operator_eval/", "/access_control/"], + }, + // Test optimize/no-optimize/etc., except for `/access_control/` TestConfig { name: "optimize", runner: |p| run(p, get_config_by_name("optimize")), experiments: &[ (Experiment::OPTIMIZE, true), (Experiment::OPTIMIZE_WAITING_FOR_COMPARE_TESTS, true), - (Experiment::ACQUIRES_CHECK, false), ], - is_lang_v1: false, + language_version: LanguageVersion::latest_stable(), include: &[], // all tests except those excluded below - exclude: &["/operator_eval/"], + exclude: &["/operator_eval/", "/access_control/"], }, TestConfig { name: "no-optimize", runner: |p| run(p, get_config_by_name("no-optimize")), - experiments: &[ - (Experiment::OPTIMIZE, false), - (Experiment::ACQUIRES_CHECK, false), - ], - is_lang_v1: false, + experiments: &[(Experiment::OPTIMIZE, false)], + language_version: LanguageVersion::latest_stable(), include: &[], // all tests except those excluded below - exclude: &["/operator_eval/"], + exclude: &["/operator_eval/", "/access_control/"], }, TestConfig { name: "optimize-no-simplify", @@ -68,17 +77,17 @@ const TEST_CONFIGS: &[TestConfig] = &[ (Experiment::OPTIMIZE, true), (Experiment::OPTIMIZE_WAITING_FOR_COMPARE_TESTS, true), (Experiment::AST_SIMPLIFY, false), - (Experiment::ACQUIRES_CHECK, false), ], - is_lang_v1: false, + language_version: LanguageVersion::latest_stable(), include: &[], // all tests except those excluded below - exclude: &["/operator_eval/"], + exclude: &["/operator_eval/", "/access_control/"], }, + // Test `/operator_eval/` with language version 1 and 2 TestConfig { name: "operator-eval-lang-1", runner: |p| run(p, get_config_by_name("operator-eval-lang-1")), experiments: &[(Experiment::OPTIMIZE, true)], - is_lang_v1: true, + language_version: LanguageVersion::V1, include: &["/operator_eval/"], exclude: &[], }, @@ -86,14 +95,78 @@ const TEST_CONFIGS: &[TestConfig] = &[ name: "operator-eval-lang-2", runner: |p| run(p, get_config_by_name("operator-eval-lang-2")), experiments: &[(Experiment::OPTIMIZE, true)], - is_lang_v1: false, + language_version: LanguageVersion::latest_stable(), include: &["/operator_eval/"], exclude: &[], }, + // Test `/lambda/` with lambdas enabled + TestConfig { + name: "lambda", + runner: |p| run(p, get_config_by_name("lambda")), + experiments: &[ + (Experiment::OPTIMIZE, true), + (Experiment::LAMBDA_FIELDS, true), + (Experiment::LAMBDA_IN_PARAMS, true), + (Experiment::LAMBDA_IN_RETURNS, true), + (Experiment::LAMBDA_VALUES, true), + (Experiment::LAMBDA_LIFTING, true), + ], + language_version: LanguageVersion::V2_2, + include: &["/lambda/"], + exclude: &[], + }, + // Test optimize/no-optimize/etc., just for `/access_control/`, which + // needs to disable `ACQUIRES_CHECK`. + TestConfig { + name: "optimize-no-acquires-check", + runner: |p| run(p, get_config_by_name("optimize-no-acquires-check")), + experiments: &[ + (Experiment::OPTIMIZE, true), + (Experiment::OPTIMIZE_WAITING_FOR_COMPARE_TESTS, true), + (Experiment::ACQUIRES_CHECK, false), + ], + language_version: LanguageVersion::latest_stable(), + include: &["/access_control/"], + exclude: &[], + }, + TestConfig { + name: "no-optimize-no-acquires-check", + runner: |p| run(p, get_config_by_name("no-optimize-no-acquires-check")), + experiments: &[ + (Experiment::OPTIMIZE, false), + (Experiment::ACQUIRES_CHECK, false), + ], + language_version: LanguageVersion::latest_stable(), + include: &["/access_control/"], + exclude: &[], + }, + TestConfig { + name: "optimize-no-simplify-no-acquires-check", + runner: |p| { + run( + p, + get_config_by_name("optimize-no-simplify-no-acquires-check"), + ) + }, + experiments: &[ + (Experiment::OPTIMIZE, true), + (Experiment::OPTIMIZE_WAITING_FOR_COMPARE_TESTS, true), + (Experiment::AST_SIMPLIFY, false), + (Experiment::ACQUIRES_CHECK, false), + ], + language_version: LanguageVersion::latest_stable(), + include: &["/access_control/"], + exclude: &[], + }, ]; /// Test files which must use separate baselines because their result /// is different. +/// +/// Note that each config named "foo" above will compare the output of compiling `test.move` with +/// the same baseline file `test.exp` *unless* there is an entry in this array matching the path of +// `test.move`. If there is such an entry, then each config "foo" will have a +/// separate baseline output file `test.foo.exp`. const SEPARATE_BASELINE: &[&str] = &[ // Runs into too-many-locals or stack overflow if not optimized "inlining/deep_exp.move", @@ -109,6 +182,10 @@ const SEPARATE_BASELINE: &[&str] = &[ "no-v1-comparison/assert_one.move", // Flaky redundant unused assignment error "no-v1-comparison/enum/enum_scoping.move", + // Needs LAMBDA features and V2.2+ to function; baseline checks expected errors + "/lambda/", + // Needs ACQUIRES_CHECK disabled to function; baseline checks expected errors + "/access_control/", ]; fn get_config_by_name(name: &str) -> TestConfig { @@ -136,11 +213,7 @@ fn run(path: &Path, config: TestConfig) -> datatest_stable::Result<()> { // Enable access control file format generation for those tests v2_experiments.push((Experiment::GEN_ACCESS_SPECIFIERS.to_string(), true)) } - let language_version = if config.is_lang_v1 { - LanguageVersion::V1 - } else { - LanguageVersion::latest_stable() - }; + let language_version = config.language_version; let vm_test_config = if p.contains(SKIP_V1_COMPARISON_PATH) || move_test_debug() { TestRunConfig::CompilerV2 { language_version, diff --git a/third_party/move/move-model/src/metadata.rs b/third_party/move/move-model/src/metadata.rs index a26a67ffef4f1..be8a83e5f84fb 100644 --- a/third_party/move/move-model/src/metadata.rs +++ b/third_party/move/move-model/src/metadata.rs @@ -17,8 +17,10 @@ use std::{ }; const UNSTABLE_MARKER: &str = "-unstable"; -pub const LATEST_STABLE_LANGUAGE_VERSION: &str = "2.1"; -pub const LATEST_STABLE_COMPILER_VERSION: &str = "2.0"; +pub const LATEST_STABLE_LANGUAGE_VERSION_VALUE: LanguageVersion = LanguageVersion::V2_1; +pub const LATEST_STABLE_COMPILER_VERSION_VALUE: CompilerVersion = CompilerVersion::V2_0; +pub const LATEST_STABLE_LANGUAGE_VERSION: &str = LATEST_STABLE_LANGUAGE_VERSION_VALUE.to_str(); +pub const LATEST_STABLE_COMPILER_VERSION: &str = LATEST_STABLE_COMPILER_VERSION_VALUE.to_str(); pub static COMPILATION_METADATA_KEY: &[u8] = "compilation_metadata".as_bytes(); @@ -148,13 +150,13 @@ impl CompilerVersion { } /// The latest compiler version. - pub fn latest() -> Self { + pub const fn latest() -> Self { CompilerVersion::V2_1 } /// The latest stable compiler version. - pub fn latest_stable() -> Self { - CompilerVersion::from_str(LATEST_STABLE_COMPILER_VERSION).expect("valid version") + pub const fn latest_stable() -> Self { + LATEST_STABLE_COMPILER_VERSION_VALUE } /// Check whether the compiler version supports the given language version, @@ -180,6 +182,14 @@ impl CompilerVersion { LanguageVersion::latest_stable() } } + + pub const fn to_str(&self) -> &'static str { + match self { + CompilerVersion::V1 => "1", + CompilerVersion::V2_0 => "2.0", + CompilerVersion::V2_1 => "2.1", + } + } } // ================================================================================' @@ -257,7 +267,7 @@ impl From for CompilerLanguageVersion { impl LanguageVersion { /// Whether the language version is unstable. An unstable version /// should not be allowed on production networks. - pub fn unstable(self) -> bool { + pub const fn unstable(self) -> bool { use LanguageVersion::*; match self { V1 | V2_0 | V2_1 => false, @@ -266,13 +276,13 @@ impl LanguageVersion { } /// The latest language version. - pub fn latest() -> Self { + pub const fn latest() -> Self { LanguageVersion::V2_2 } /// The latest stable language version. - pub fn latest_stable() -> Self { - LanguageVersion::from_str(LATEST_STABLE_LANGUAGE_VERSION).expect("valid version") + pub const fn latest_stable() -> Self { + LATEST_STABLE_LANGUAGE_VERSION_VALUE } /// Whether the language version is equal to greater than `ver` @@ -290,6 +300,15 @@ impl LanguageVersion { LanguageVersion::V2_2 => VERSION_DEFAULT_LANG_V2, // Update once we have v8 bytecode }) } + + pub const fn to_str(&self) -> &'static str { + match self { + LanguageVersion::V1 => "1", + LanguageVersion::V2_0 => "2.0", + LanguageVersion::V2_1 => "2.1", + LanguageVersion::V2_2 => "2.2", + } + } } impl Display for LanguageVersion { From 127df5c2c68891362f17c6b8cfe88e454c5ba0c5 Mon Sep 17 00:00:00 2001 From: Sherry Xiao Date: Wed, 18 Dec 2024 12:22:34 -0800 Subject: [PATCH 62/78] Revert "Bumping up the max transaction execution gas limit for gov proposals" This reverts commit e2359fd575313dde0db0e4eea9f13e691318ff51. --- aptos-move/aptos-gas-schedule/src/gas_schedule/transaction.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aptos-move/aptos-gas-schedule/src/gas_schedule/transaction.rs b/aptos-move/aptos-gas-schedule/src/gas_schedule/transaction.rs index 62a09562f1bdf..5c51fa9ee314b 100644 --- a/aptos-move/aptos-gas-schedule/src/gas_schedule/transaction.rs +++ b/aptos-move/aptos-gas-schedule/src/gas_schedule/transaction.rs @@ -212,7 +212,7 @@ crate::gas_schedule::macros::define_gas_parameters!( [ max_execution_gas_gov: InternalGas, { RELEASE_V1_13.. => "max_execution_gas.gov" }, - 4_300_000_000, + 4_000_000_000, ], [ max_io_gas: InternalGas, From 1381c93fd5a656f16fb326d4ffe371947554a330 Mon Sep 17 00:00:00 2001 From: igor-aptos <110557261+igor-aptos@users.noreply.github.com> Date: Wed, 18 Dec 2024 21:09:28 -0800 Subject: [PATCH 63/78] Optimizing vector::replace and compiler-v2 vector depenency fix (#15524) * Optimizing vector::replace with mem::replace * [compiler-v2] Also include all dependencies of vector for compiler v2 from #15528 --------- Co-authored-by: Igor --- .../framework/aptos-stdlib/doc/big_vector.md | 2 +- .../framework/move-stdlib/doc/vector.md | 18 ++++++------ .../framework/move-stdlib/sources/mem.move | 2 +- .../framework/move-stdlib/sources/vector.move | 17 +++++------ third_party/move/move-model/src/lib.rs | 29 +++++++++++++++---- 5 files changed, 42 insertions(+), 26 deletions(-) diff --git a/aptos-move/framework/aptos-stdlib/doc/big_vector.md b/aptos-move/framework/aptos-stdlib/doc/big_vector.md index 7d785a5b730a1..da978bc07ff9e 100644 --- a/aptos-move/framework/aptos-stdlib/doc/big_vector.md +++ b/aptos-move/framework/aptos-stdlib/doc/big_vector.md @@ -502,7 +502,7 @@ Aborts if i is out of bounds. if (self.end_index == i) { return last_val }; - // because the lack of mem::swap, here we swap remove the requested value from the bucket + // because the lack of mem::swap, here we swap remove the requested value from the bucket // and append the last_val to the bucket then swap the last bucket val back let bucket = table_with_length::borrow_mut(&mut self.buckets, i / self.bucket_size); let bucket_len = vector::length(bucket); diff --git a/aptos-move/framework/move-stdlib/doc/vector.md b/aptos-move/framework/move-stdlib/doc/vector.md index 9e837c9c1cfae..18512424c38e8 100644 --- a/aptos-move/framework/move-stdlib/doc/vector.md +++ b/aptos-move/framework/move-stdlib/doc/vector.md @@ -88,7 +88,8 @@ the return on investment didn't seem worth it for these simple functions. - [Function `rotate_slice`](#@Specification_1_rotate_slice) -
+
use 0x1::mem;
+
@@ -930,14 +931,13 @@ Aborts if i is out of bounds.
public fun replace<Element>(self: &mut vector<Element>, i: u64, val: Element): Element {
     let last_idx = length(self);
     assert!(i < last_idx, EINDEX_OUT_OF_BOUNDS);
-    // TODO: Enable after tests are fixed.
-    // if (USE_MOVE_RANGE) {
-    //     mem::replace(borrow_mut(self, i), val)
-    // } else {
-    push_back(self, val);
-    swap(self, i, last_idx);
-    pop_back(self)
-    // }
+    if (USE_MOVE_RANGE) {
+        mem::replace(borrow_mut(self, i), val)
+    } else {
+        push_back(self, val);
+        swap(self, i, last_idx);
+        pop_back(self)
+    }
 }
 
diff --git a/aptos-move/framework/move-stdlib/sources/mem.move b/aptos-move/framework/move-stdlib/sources/mem.move index cf2eae276f9a5..e96db063db6c0 100644 --- a/aptos-move/framework/move-stdlib/sources/mem.move +++ b/aptos-move/framework/move-stdlib/sources/mem.move @@ -2,7 +2,7 @@ module std::mem { // TODO - functions here are `public(friend)` here for one release, // and to be changed to `public` one release later. - // friend std::vector; + friend std::vector; #[test_only] friend std::mem_tests; diff --git a/aptos-move/framework/move-stdlib/sources/vector.move b/aptos-move/framework/move-stdlib/sources/vector.move index b7add1eb2112a..e4d018e4f0b21 100644 --- a/aptos-move/framework/move-stdlib/sources/vector.move +++ b/aptos-move/framework/move-stdlib/sources/vector.move @@ -9,7 +9,7 @@ /// Move functions here because many have loops, requiring loop invariants to prove, and /// the return on investment didn't seem worth it for these simple functions. module std::vector { - // use std::mem; + use std::mem; /// The index into the vector is out of bounds const EINDEX_OUT_OF_BOUNDS: u64 = 0x20000; @@ -357,14 +357,13 @@ module std::vector { public fun replace(self: &mut vector, i: u64, val: Element): Element { let last_idx = length(self); assert!(i < last_idx, EINDEX_OUT_OF_BOUNDS); - // TODO: Enable after tests are fixed. - // if (USE_MOVE_RANGE) { - // mem::replace(borrow_mut(self, i), val) - // } else { - push_back(self, val); - swap(self, i, last_idx); - pop_back(self) - // } + if (USE_MOVE_RANGE) { + mem::replace(borrow_mut(self, i), val) + } else { + push_back(self, val); + swap(self, i, last_idx); + pop_back(self) + } } /// Apply the function to each element in the vector, consuming it. diff --git a/third_party/move/move-model/src/lib.rs b/third_party/move/move-model/src/lib.rs index 737a5a847021d..d16720ecf4642 100644 --- a/third_party/move/move-model/src/lib.rs +++ b/third_party/move/move-model/src/lib.rs @@ -305,13 +305,25 @@ pub fn run_model_builder_with_options_and_compilation_flags< }, }; - // Extract the module/script closure + // Extract the module/script dependency closure let mut visited_modules = BTreeSet::new(); + // Extract the module dependency closure for the vector module + let mut vector_and_its_dependencies = BTreeSet::new(); + let mut seen_vector = false; for (_, mident, mdef) in &expansion_ast.modules { let src_file_hash = mdef.loc.file_hash(); if !dep_files.contains(&src_file_hash) { collect_related_modules_recursive(mident, &expansion_ast.modules, &mut visited_modules); } + if !seen_vector && is_vector(*mident) { + seen_vector = true; + // Collect the vector module and its dependencies. + collect_related_modules_recursive( + mident, + &expansion_ast.modules, + &mut vector_and_its_dependencies, + ); + } } for sdef in expansion_ast.scripts.values() { let src_file_hash = sdef.loc.file_hash(); @@ -330,14 +342,13 @@ pub fn run_model_builder_with_options_and_compilation_flags< let mut expansion_ast = { let E::Program { modules, scripts } = expansion_ast; let modules = modules.filter_map(|mident, mut mdef| { - // We need to always include the `vector` module (only for compiler v2), + // For compiler v2, we need to always include the `vector` module and any of its dependencies, // to handle cases of implicit usage. // E.g., index operation on a vector results in a call to `vector::borrow`. // TODO(#15483): consider refactoring code to avoid this special case. - let is_vector = mident.value.address.into_addr_bytes().into_inner() - == AccountAddress::ONE - && mident.value.module.0.value.as_str() == "vector"; - (is_vector && compile_via_model || visited_modules.contains(&mident.value)).then(|| { + ((compile_via_model && vector_and_its_dependencies.contains(&mident.value)) + || visited_modules.contains(&mident.value)) + .then(|| { mdef.is_source_module = true; mdef }) @@ -416,6 +427,12 @@ pub fn run_model_builder_with_options_and_compilation_flags< } } +/// Is `module_ident` the `vector` module? +fn is_vector(module_ident: ModuleIdent_) -> bool { + module_ident.address.into_addr_bytes().into_inner() == AccountAddress::ONE + && module_ident.module.0.value.as_str() == "vector" +} + fn run_move_checker(env: &mut GlobalEnv, program: E::Program) { let mut builder = ModelBuilder::new(env); for (module_count, (module_id, module_def)) in program From 0ec01ddc09afc3e30fad744dbb089790a84393a4 Mon Sep 17 00:00:00 2001 From: Daniel Porteous Date: Thu, 19 Dec 2024 18:19:49 +0000 Subject: [PATCH 64/78] Lock Rust deps for checking protos --- protos/scripts/install_deps.sh | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/protos/scripts/install_deps.sh b/protos/scripts/install_deps.sh index 60f0e422ba607..07e0c0ab23526 100755 --- a/protos/scripts/install_deps.sh +++ b/protos/scripts/install_deps.sh @@ -4,11 +4,14 @@ # The TS plugins are pulled automatically since we depend on them directly from # the buf.build community plugin registry. +set -e +set -x + # For generating Rust code -cargo install --version 0.2.3 protoc-gen-prost -cargo install --version 0.2.3 protoc-gen-prost-serde -cargo install --version 0.3.1 protoc-gen-prost-crate -cargo install --version 0.3.0 protoc-gen-tonic +cargo install --locked --version 0.2.3 protoc-gen-prost +cargo install --locked --version 0.2.3 protoc-gen-prost-serde +cargo install --locked --version 0.3.1 protoc-gen-prost-crate +cargo install --locked --version 0.3.0 protoc-gen-tonic # For generating Python code cd python From cf5d79099c230c68d20c4d1298014ddd13bfd40b Mon Sep 17 00:00:00 2001 From: Perry Randall Date: Thu, 19 Dec 2024 11:31:57 -0800 Subject: [PATCH 65/78] [forge] Disable the framework upgrade test on most PR Framework upgrade seems to have issue right now with invalid gas schedule Lets temporarily remove this from blocking most PR except those touching the release builder itself Test Plan: run locally, make sure PR passes then merge --- devtools/aptos-cargo-cli/src/lib.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/devtools/aptos-cargo-cli/src/lib.rs b/devtools/aptos-cargo-cli/src/lib.rs index 4dea19a6ec0f9..d10ae82a46959 100644 --- a/devtools/aptos-cargo-cli/src/lib.rs +++ b/devtools/aptos-cargo-cli/src/lib.rs @@ -34,11 +34,12 @@ const RELEVANT_FILE_PATHS_FOR_EXECUTION_PERFORMANCE_TESTS: [&str; 5] = [ "execution/aptos-executor-benchmark", "testsuite/single_node_performance.py", ]; -const RELEVANT_FILE_PATHS_FOR_FRAMEWORK_UPGRADE_TESTS: [&str; 4] = [ - ".github", - "testsuite", +const RELEVANT_FILE_PATHS_FOR_FRAMEWORK_UPGRADE_TESTS: [&str; 1] = [ + // Framework upgrade test is failing right now, disable except for the release builder + // ".github", + // "testsuite", "aptos-move/aptos-release-builder", - "aptos-move/framework", + // "aptos-move/framework", ]; // Relevant packages to monitor when deciding to run the targeted tests From 554f3029ae8ef4e84887fa1cc58fda29fdf5fb8e Mon Sep 17 00:00:00 2001 From: Josh Lind Date: Thu, 19 Dec 2024 15:01:34 -0800 Subject: [PATCH 66/78] [Devtools] Disable framework upgrade test --- devtools/aptos-cargo-cli/src/lib.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/devtools/aptos-cargo-cli/src/lib.rs b/devtools/aptos-cargo-cli/src/lib.rs index d10ae82a46959..fc802650b2dc1 100644 --- a/devtools/aptos-cargo-cli/src/lib.rs +++ b/devtools/aptos-cargo-cli/src/lib.rs @@ -34,12 +34,11 @@ const RELEVANT_FILE_PATHS_FOR_EXECUTION_PERFORMANCE_TESTS: [&str; 5] = [ "execution/aptos-executor-benchmark", "testsuite/single_node_performance.py", ]; -const RELEVANT_FILE_PATHS_FOR_FRAMEWORK_UPGRADE_TESTS: [&str; 1] = [ - // Framework upgrade test is failing right now, disable except for the release builder - // ".github", - // "testsuite", +const RELEVANT_FILE_PATHS_FOR_FRAMEWORK_UPGRADE_TESTS: [&str; 4] = [ + ".github", + "testsuite", "aptos-move/aptos-release-builder", - // "aptos-move/framework", + "aptos-move/framework", ]; // Relevant packages to monitor when deciding to run the targeted tests @@ -259,13 +258,18 @@ impl AptosCargoCommand { self.get_args_and_affected_packages(package_args)?; // Determine if any relevant files or packages were changed - let relevant_changes_detected = detect_relevant_changes( + #[allow(unused_assignments)] + let mut relevant_changes_detected = detect_relevant_changes( RELEVANT_FILE_PATHS_FOR_FRAMEWORK_UPGRADE_TESTS.to_vec(), RELEVANT_PACKAGES_FOR_FRAMEWORK_UPGRADE_TESTS.to_vec(), changed_files, affected_package_paths, ); + // TODO: remove this! This is a temporary fix to disable + // the framework upgrade test while we debug the failures. + relevant_changes_detected = false; + // Output if relevant changes were detected that require the framework upgrade // test. This will be consumed by Github Actions and used to run the test. println!( From 2c9dece4b0d82a1110554d6f38d5b4a94af413eb Mon Sep 17 00:00:00 2001 From: Junkil Park Date: Thu, 19 Dec 2024 16:11:43 -0800 Subject: [PATCH 67/78] Refine Voting Error Codes (#15590) This commit refines voting error codes by introducing more specific classifications: ENO_VOTING_POWER, EINSUFFICIENT_STAKE_LOCKUP, and EPROPOSAL_EXPIRED. --- .../aptos-framework/doc/aptos_governance.md | 81 ++++- .../aptos-framework/doc/delegation_pool.md | 1 + .../framework/aptos-framework/doc/stake.md | 305 +----------------- .../sources/aptos_governance.move | 84 ++++- .../sources/aptos_governance.spec.move | 10 + .../sources/delegation_pool.move | 121 ++++++- .../aptos-framework/sources/stake.spec.move | 4 + 7 files changed, 289 insertions(+), 317 deletions(-) diff --git a/aptos-move/framework/aptos-framework/doc/aptos_governance.md b/aptos-move/framework/aptos-framework/doc/aptos_governance.md index ef3a011b5ed74..c7c97bebe112c 100644 --- a/aptos-move/framework/aptos-framework/doc/aptos_governance.md +++ b/aptos-move/framework/aptos-framework/doc/aptos_governance.md @@ -39,6 +39,7 @@ on a proposal multiple times as long as the total voting power of these votes do - [Function `get_required_proposer_stake`](#0x1_aptos_governance_get_required_proposer_stake) - [Function `has_entirely_voted`](#0x1_aptos_governance_has_entirely_voted) - [Function `get_remaining_voting_power`](#0x1_aptos_governance_get_remaining_voting_power) +- [Function `assert_proposal_expiration`](#0x1_aptos_governance_assert_proposal_expiration) - [Function `create_proposal`](#0x1_aptos_governance_create_proposal) - [Function `create_proposal_v2`](#0x1_aptos_governance_create_proposal_v2) - [Function `create_proposal_v2_impl`](#0x1_aptos_governance_create_proposal_v2_impl) @@ -74,6 +75,7 @@ on a proposal multiple times as long as the total voting power of these votes do - [Function `get_required_proposer_stake`](#@Specification_1_get_required_proposer_stake) - [Function `has_entirely_voted`](#@Specification_1_has_entirely_voted) - [Function `get_remaining_voting_power`](#@Specification_1_get_remaining_voting_power) + - [Function `assert_proposal_expiration`](#@Specification_1_assert_proposal_expiration) - [Function `create_proposal`](#@Specification_1_create_proposal) - [Function `create_proposal_v2`](#@Specification_1_create_proposal_v2) - [Function `create_proposal_v2_impl`](#@Specification_1_create_proposal_v2_impl) @@ -758,6 +760,16 @@ Partial voting feature hasn't been properly initialized. + + +The proposal has expired. + + +
const EPROPOSAL_EXPIRED: u64 = 15;
+
+ + + Proposal is not ready to be resolved. Waiting on time or votes @@ -1160,6 +1172,43 @@ Note: a stake pool's voting power on a proposal could increase over time(e.g. re + + + + +## Function `assert_proposal_expiration` + + + +
public fun assert_proposal_expiration(stake_pool: address, proposal_id: u64)
+
+ + + +
+Implementation + + +
public fun assert_proposal_expiration(stake_pool: address, proposal_id: u64) {
+    assert_voting_initialization();
+    let proposal_expiration = voting::get_proposal_expiration_secs<GovernanceProposal>(
+        @aptos_framework,
+        proposal_id
+    );
+    // The voter's stake needs to be locked up at least as long as the proposal's expiration.
+    assert!(
+        proposal_expiration <= stake::get_lockup_secs(stake_pool),
+        error::invalid_argument(EINSUFFICIENT_STAKE_LOCKUP),
+    );
+    assert!(
+        timestamp::now_seconds() <= proposal_expiration,
+        error::invalid_argument(EPROPOSAL_EXPIRED),
+    );
+}
+
+ + +
@@ -1498,15 +1547,7 @@ cannot vote on the proposal even after partial governance voting is enabled. let voter_address = signer::address_of(voter); assert!(stake::get_delegated_voter(stake_pool) == voter_address, error::invalid_argument(ENOT_DELEGATED_VOTER)); - // The voter's stake needs to be locked up at least as long as the proposal's expiration. - let proposal_expiration = voting::get_proposal_expiration_secs<GovernanceProposal>( - @aptos_framework, - proposal_id - ); - assert!( - stake::get_lockup_secs(stake_pool) >= proposal_expiration, - error::invalid_argument(EINSUFFICIENT_STAKE_LOCKUP), - ); + assert_proposal_expiration(stake_pool, proposal_id); // If a stake pool has already voted on a proposal before partial governance voting is enabled, // `get_remaining_voting_power` returns 0. @@ -2435,6 +2476,28 @@ Abort if structs have already been created. + + +### Function `assert_proposal_expiration` + + +
public fun assert_proposal_expiration(stake_pool: address, proposal_id: u64)
+
+ + + + +
include VotingInitializationAbortIfs;
+include voting::AbortsIfNotContainProposalID<GovernanceProposal>{voting_forum_address: @aptos_framework};
+let proposal_expiration = voting::spec_get_proposal_expiration_secs<GovernanceProposal>(@aptos_framework, proposal_id);
+aborts_if !stake::stake_pool_exists(stake_pool);
+aborts_if proposal_expiration > stake::spec_get_lockup_secs(stake_pool);
+aborts_if !exists<timestamp::CurrentTimeMicroseconds>(@aptos_framework);
+aborts_if timestamp::now_seconds() > proposal_expiration;
+
+ + + ### Function `create_proposal` diff --git a/aptos-move/framework/aptos-framework/doc/delegation_pool.md b/aptos-move/framework/aptos-framework/doc/delegation_pool.md index 268d0618fb722..f9c83df1ff80f 100644 --- a/aptos-move/framework/aptos-framework/doc/delegation_pool.md +++ b/aptos-move/framework/aptos-framework/doc/delegation_pool.md @@ -2955,6 +2955,7 @@ Vote on a proposal with a voter's voting power. To successfully vote, the follow if (voting_power > remaining_voting_power) { voting_power = remaining_voting_power; }; + aptos_governance::assert_proposal_expiration(pool_address, proposal_id); assert!(voting_power > 0, error::invalid_argument(ENO_VOTING_POWER)); let governance_records = borrow_global_mut<GovernanceRecords>(pool_address); diff --git a/aptos-move/framework/aptos-framework/doc/stake.md b/aptos-move/framework/aptos-framework/doc/stake.md index 53d815ae1ed8a..dedfe15027641 100644 --- a/aptos-move/framework/aptos-framework/doc/stake.md +++ b/aptos-move/framework/aptos-framework/doc/stake.md @@ -4565,148 +4565,6 @@ Returns validator's next epoch voting power, including pending_active, active, a - - - - -
fun spec_validator_index_upper_bound(): u64 {
-   len(global<ValidatorPerformance>(@aptos_framework).validators)
-}
-
- - - - - - - -
fun spec_has_stake_pool(a: address): bool {
-   exists<StakePool>(a)
-}
-
- - - - - - - -
fun spec_has_validator_config(a: address): bool {
-   exists<ValidatorConfig>(a)
-}
-
- - - - - - - -
fun spec_rewards_amount(
-   stake_amount: u64,
-   num_successful_proposals: u64,
-   num_total_proposals: u64,
-   rewards_rate: u64,
-   rewards_rate_denominator: u64,
-): u64;
-
- - - - - - - -
fun spec_contains(validators: vector<ValidatorInfo>, addr: address): bool {
-   exists i in 0..len(validators): validators[i].addr == addr
-}
-
- - - - - - - -
fun spec_is_current_epoch_validator(pool_address: address): bool {
-   let validator_set = global<ValidatorSet>(@aptos_framework);
-   !spec_contains(validator_set.pending_active, pool_address)
-       && (spec_contains(validator_set.active_validators, pool_address)
-       || spec_contains(validator_set.pending_inactive, pool_address))
-}
-
- - - - - - - -
schema ResourceRequirement {
-    requires exists<AptosCoinCapabilities>(@aptos_framework);
-    requires exists<ValidatorPerformance>(@aptos_framework);
-    requires exists<ValidatorSet>(@aptos_framework);
-    requires exists<StakingConfig>(@aptos_framework);
-    requires exists<StakingRewardsConfig>(@aptos_framework) || !features::spec_periodical_reward_rate_decrease_enabled();
-    requires exists<timestamp::CurrentTimeMicroseconds>(@aptos_framework);
-}
-
- - - - - - - -
fun spec_get_reward_rate_1(config: StakingConfig): num {
-   if (features::spec_periodical_reward_rate_decrease_enabled()) {
-       let epoch_rewards_rate = global<staking_config::StakingRewardsConfig>(@aptos_framework).rewards_rate;
-       if (epoch_rewards_rate.value == 0) {
-           0
-       } else {
-           let denominator_0 = aptos_std::fixed_point64::spec_divide_u128(staking_config::MAX_REWARDS_RATE, epoch_rewards_rate);
-           let denominator = if (denominator_0 > MAX_U64) {
-               MAX_U64
-           } else {
-               denominator_0
-           };
-           let nominator = aptos_std::fixed_point64::spec_multiply_u128(denominator, epoch_rewards_rate);
-           nominator
-       }
-   } else {
-           config.rewards_rate
-   }
-}
-
- - - - - - - -
fun spec_get_reward_rate_2(config: StakingConfig): num {
-   if (features::spec_periodical_reward_rate_decrease_enabled()) {
-       let epoch_rewards_rate = global<staking_config::StakingRewardsConfig>(@aptos_framework).rewards_rate;
-       if (epoch_rewards_rate.value == 0) {
-           1
-       } else {
-           let denominator_0 = aptos_std::fixed_point64::spec_divide_u128(staking_config::MAX_REWARDS_RATE, epoch_rewards_rate);
-           let denominator = if (denominator_0 > MAX_U64) {
-               MAX_U64
-           } else {
-               denominator_0
-           };
-           denominator
-       }
-   } else {
-           config.rewards_rate_denominator
-   }
-}
-
- - - ### Resource `ValidatorSet` @@ -5492,158 +5350,6 @@ Returns validator's next epoch voting power, including pending_active, active, a - - - - -
schema AddStakeWithCapAbortsIfAndEnsures {
-    owner_cap: OwnerCapability;
-    amount: u64;
-    let pool_address = owner_cap.pool_address;
-    aborts_if !exists<StakePool>(pool_address);
-    let config = global<staking_config::StakingConfig>(@aptos_framework);
-    let validator_set = global<ValidatorSet>(@aptos_framework);
-    let voting_power_increase_limit = config.voting_power_increase_limit;
-    let post post_validator_set = global<ValidatorSet>(@aptos_framework);
-    let update_voting_power_increase = amount != 0 && (spec_contains(validator_set.active_validators, pool_address)
-                                                       || spec_contains(validator_set.pending_active, pool_address));
-    aborts_if update_voting_power_increase && validator_set.total_joining_power + amount > MAX_U128;
-    ensures update_voting_power_increase ==> post_validator_set.total_joining_power == validator_set.total_joining_power + amount;
-    aborts_if update_voting_power_increase && validator_set.total_voting_power > 0
-            && validator_set.total_voting_power * voting_power_increase_limit > MAX_U128;
-    aborts_if update_voting_power_increase && validator_set.total_voting_power > 0
-            && validator_set.total_joining_power + amount > validator_set.total_voting_power * voting_power_increase_limit / 100;
-    let stake_pool = global<StakePool>(pool_address);
-    let post post_stake_pool = global<StakePool>(pool_address);
-    let value_pending_active = stake_pool.pending_active.value;
-    let value_active = stake_pool.active.value;
-    ensures amount != 0 && spec_is_current_epoch_validator(pool_address) ==> post_stake_pool.pending_active.value == value_pending_active + amount;
-    ensures amount != 0 && !spec_is_current_epoch_validator(pool_address) ==> post_stake_pool.active.value == value_active + amount;
-    let maximum_stake = config.maximum_stake;
-    let value_pending_inactive = stake_pool.pending_inactive.value;
-    let next_epoch_voting_power = value_pending_active + value_active + value_pending_inactive;
-    let voting_power = next_epoch_voting_power + amount;
-    aborts_if amount != 0 && voting_power > MAX_U64;
-    aborts_if amount != 0 && voting_power > maximum_stake;
-}
-
- - - - - - - -
schema AddStakeAbortsIfAndEnsures {
-    owner: signer;
-    amount: u64;
-    let owner_address = signer::address_of(owner);
-    aborts_if !exists<OwnerCapability>(owner_address);
-    let owner_cap = global<OwnerCapability>(owner_address);
-    include AddStakeWithCapAbortsIfAndEnsures { owner_cap };
-}
-
- - - - - - - -
fun spec_is_allowed(account: address): bool {
-   if (!exists<AllowedValidators>(@aptos_framework)) {
-       true
-   } else {
-       let allowed = global<AllowedValidators>(@aptos_framework);
-       contains(allowed.accounts, account)
-   }
-}
-
- - - - - - - -
fun spec_find_validator(v: vector<ValidatorInfo>, addr: address): Option<u64>;
-
- - - - - - - -
fun spec_validators_are_initialized(validators: vector<ValidatorInfo>): bool {
-   forall i in 0..len(validators):
-       spec_has_stake_pool(validators[i].addr) &&
-           spec_has_validator_config(validators[i].addr)
-}
-
- - - - - - - -
fun spec_validators_are_initialized_addrs(addrs: vector<address>): bool {
-   forall i in 0..len(addrs):
-       spec_has_stake_pool(addrs[i]) &&
-           spec_has_validator_config(addrs[i])
-}
-
- - - - - - - -
fun spec_validator_indices_are_valid(validators: vector<ValidatorInfo>): bool {
-   spec_validator_indices_are_valid_addr(validators, spec_validator_index_upper_bound()) &&
-       spec_validator_indices_are_valid_config(validators, spec_validator_index_upper_bound())
-}
-
- - - - - - - -
fun spec_validator_indices_are_valid_addr(validators: vector<ValidatorInfo>, upper_bound: u64): bool {
-   forall i in 0..len(validators):
-       global<ValidatorConfig>(validators[i].addr).validator_index < upper_bound
-}
-
- - - - - - - -
fun spec_validator_indices_are_valid_config(validators: vector<ValidatorInfo>, upper_bound: u64): bool {
-   forall i in 0..len(validators):
-       validators[i].config.validator_index < upper_bound
-}
-
- - - - - - - -
fun spec_validator_indices_active_pending_inactive(validator_set: ValidatorSet): bool {
-   len(validator_set.pending_inactive) + len(validator_set.active_validators) == spec_validator_index_upper_bound()
-}
-
- - - ### Function `update_stake_pool` @@ -5755,6 +5461,17 @@ Returns validator's next epoch voting power, including pending_active, active, a + + + + +
fun spec_get_lockup_secs(pool_address: address): u64 {
+   global<StakePool>(pool_address).locked_until_secs
+}
+
+ + + ### Function `calculate_rewards_amount` diff --git a/aptos-move/framework/aptos-framework/sources/aptos_governance.move b/aptos-move/framework/aptos-framework/sources/aptos_governance.move index fb1469bc7e684..f5de768d05864 100644 --- a/aptos-move/framework/aptos-framework/sources/aptos_governance.move +++ b/aptos-move/framework/aptos-framework/sources/aptos_governance.move @@ -62,6 +62,8 @@ module aptos_framework::aptos_governance { const EPARTIAL_VOTING_NOT_INITIALIZED: u64 = 13; /// The proposal in the argument is not a partial voting proposal. const ENOT_PARTIAL_VOTING_PROPOSAL: u64 = 14; + /// The proposal has expired. + const EPROPOSAL_EXPIRED: u64 = 15; /// This matches the same enum const in voting. We have to duplicate it as Move doesn't have support for enums yet. const PROPOSAL_STATE_SUCCEEDED: u64 = 1; @@ -331,6 +333,23 @@ module aptos_framework::aptos_governance { get_voting_power(stake_pool) - used_voting_power } + public fun assert_proposal_expiration(stake_pool: address, proposal_id: u64) { + assert_voting_initialization(); + let proposal_expiration = voting::get_proposal_expiration_secs( + @aptos_framework, + proposal_id + ); + // The voter's stake needs to be locked up at least as long as the proposal's expiration. + assert!( + proposal_expiration <= stake::get_lockup_secs(stake_pool), + error::invalid_argument(EINSUFFICIENT_STAKE_LOCKUP), + ); + assert!( + timestamp::now_seconds() <= proposal_expiration, + error::invalid_argument(EPROPOSAL_EXPIRED), + ); + } + /// Create a single-step proposal with the backing `stake_pool`. /// @param execution_hash Required. This is the hash of the resolution script. When the proposal is resolved, /// only the exact script with matching hash can be successfully executed. @@ -512,15 +531,7 @@ module aptos_framework::aptos_governance { let voter_address = signer::address_of(voter); assert!(stake::get_delegated_voter(stake_pool) == voter_address, error::invalid_argument(ENOT_DELEGATED_VOTER)); - // The voter's stake needs to be locked up at least as long as the proposal's expiration. - let proposal_expiration = voting::get_proposal_expiration_secs( - @aptos_framework, - proposal_id - ); - assert!( - stake::get_lockup_secs(stake_pool) >= proposal_expiration, - error::invalid_argument(EINSUFFICIENT_STAKE_LOCKUP), - ); + assert_proposal_expiration(stake_pool, proposal_id); // If a stake pool has already voted on a proposal before partial governance voting is enabled, // `get_remaining_voting_power` returns 0. @@ -963,7 +974,7 @@ module aptos_framework::aptos_governance { } #[test(aptos_framework = @aptos_framework, proposer = @0x123, voter_1 = @0x234, voter_2 = @345)] - #[expected_failure(abort_code = 0x10004, location = aptos_framework::voting)] + #[expected_failure(abort_code = 65541, location = aptos_framework::aptos_governance)] public entry fun test_cannot_double_vote( aptos_framework: signer, proposer: signer, @@ -975,7 +986,7 @@ module aptos_framework::aptos_governance { create_proposal( &proposer, signer::address_of(&proposer), - b"", + b"0", b"", b"", ); @@ -986,7 +997,54 @@ module aptos_framework::aptos_governance { } #[test(aptos_framework = @aptos_framework, proposer = @0x123, voter_1 = @0x234, voter_2 = @345)] - #[expected_failure(abort_code = 0x10004, location = aptos_framework::voting)] + #[expected_failure(abort_code = 65551, location = aptos_framework::aptos_governance)] + public entry fun test_cannot_vote_for_expired_proposal( + aptos_framework: signer, + proposer: signer, + voter_1: signer, + voter_2: signer, + ) acquires ApprovedExecutionHashes, GovernanceConfig, GovernanceResponsbility, VotingRecords, VotingRecordsV2, GovernanceEvents { + setup_partial_voting_with_initialized_stake(&aptos_framework, &proposer, &voter_1, &voter_2); + + create_proposal( + &proposer, + signer::address_of(&proposer), + b"0", + b"", + b"", + ); + + timestamp::fast_forward_seconds(2000); + stake::end_epoch(); + + // Should abort because the proposal has expired. + vote(&voter_1, signer::address_of(&voter_1), 0, true); + } + + #[test(aptos_framework = @aptos_framework, proposer = @0x123, voter_1 = @0x234, voter_2 = @0x345)] + #[expected_failure(abort_code = 65539, location = aptos_framework::aptos_governance)] + public entry fun test_cannot_vote_due_to_insufficient_stake_lockup( + aptos_framework: signer, + proposer: signer, + voter_1: signer, + voter_2: signer, + ) acquires ApprovedExecutionHashes, GovernanceConfig, GovernanceResponsbility, VotingRecords, VotingRecordsV2, GovernanceEvents { + setup_partial_voting_with_initialized_stake(&aptos_framework, &proposer, &voter_1, &voter_2); + + create_proposal( + &proposer, + signer::address_of(&proposer), + b"0", + b"", + b"", + ); + + // Should abort due to insufficient stake lockup. + vote(&voter_1, signer::address_of(&voter_1), 0, true); + } + + #[test(aptos_framework = @aptos_framework, proposer = @0x123, voter_1 = @0x234, voter_2 = @345)] + #[expected_failure(abort_code = 65541, location = aptos_framework::aptos_governance)] public entry fun test_cannot_double_vote_with_different_voter_addresses( aptos_framework: signer, proposer: signer, @@ -998,7 +1056,7 @@ module aptos_framework::aptos_governance { create_proposal( &proposer, signer::address_of(&proposer), - b"", + b"0", b"", b"", ); diff --git a/aptos-move/framework/aptos-framework/sources/aptos_governance.spec.move b/aptos-move/framework/aptos-framework/sources/aptos_governance.spec.move index c3d18d593533c..3ea2572dd8fea 100644 --- a/aptos-move/framework/aptos-framework/sources/aptos_governance.spec.move +++ b/aptos-move/framework/aptos-framework/sources/aptos_governance.spec.move @@ -832,6 +832,16 @@ spec aptos_framework::aptos_governance { include VotingInitializationAbortIfs; } + spec assert_proposal_expiration(stake_pool: address, proposal_id: u64) { + include VotingInitializationAbortIfs; + include voting::AbortsIfNotContainProposalID{voting_forum_address: @aptos_framework}; + let proposal_expiration = voting::spec_get_proposal_expiration_secs(@aptos_framework, proposal_id); + aborts_if !stake::stake_pool_exists(stake_pool); + aborts_if proposal_expiration > stake::spec_get_lockup_secs(stake_pool); + aborts_if !exists(@aptos_framework); + aborts_if timestamp::now_seconds() > proposal_expiration; + } + spec force_end_epoch(aptos_framework: &signer) { use aptos_framework::reconfiguration_with_dkg; use std::signer; diff --git a/aptos-move/framework/aptos-framework/sources/delegation_pool.move b/aptos-move/framework/aptos-framework/sources/delegation_pool.move index 0e21967dcb53b..3b5cc7600f881 100644 --- a/aptos-move/framework/aptos-framework/sources/delegation_pool.move +++ b/aptos-move/framework/aptos-framework/sources/delegation_pool.move @@ -954,6 +954,7 @@ module aptos_framework::delegation_pool { if (voting_power > remaining_voting_power) { voting_power = remaining_voting_power; }; + aptos_governance::assert_proposal_expiration(pool_address, proposal_id); assert!(voting_power > 0, error::invalid_argument(ENO_VOTING_POWER)); let governance_records = borrow_global_mut(pool_address); @@ -4816,7 +4817,7 @@ module aptos_framework::delegation_pool { validator: &signer, delegator1: &signer, ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage, DelegationPoolAllowlisting { - // This test case checks the scenario where delegation_pool_partial_governance_voting is disabled. + // This test case begins with the delegation_pool_partial_governance_voting feature disabled. features::change_feature_flags_for_testing( aptos_framework, vector[], @@ -4834,6 +4835,124 @@ module aptos_framework::delegation_pool { vote(delegator1, pool_address, proposal1_id, 10 * ONE_APT, true); } + #[test(aptos_framework = @aptos_framework, validator1 = @0x123, validator2 = @0x234, delegator1 = @0x010, delegator2 = @0x020)] + #[expected_failure(abort_code = 65539, location = aptos_framework::aptos_governance)] + public entry fun test_vote_should_failed_due_to_insufficient_stake_lockup ( + aptos_framework: &signer, + validator1: &signer, + validator2: &signer, + delegator1: &signer, + delegator2: &signer, + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage, DelegationPoolAllowlisting { + // This test case begins with the delegation_pool_partial_governance_voting feature disabled. + features::change_feature_flags_for_testing( + aptos_framework, + vector[], + vector[features::get_delegation_pool_partial_governance_voting()] + ); + + let _ = setup_vote(aptos_framework, validator1, false); + + let validator1_address = signer::address_of(validator1); + let pool1_address = get_owned_pool_address(validator1_address); + let delegator1_address = signer::address_of(delegator1); + account::create_account_for_test(delegator1_address); + stake::mint(delegator1, 110 * ONE_APT); + add_stake(delegator1, pool1_address, 10 * ONE_APT); + + timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS - 500); + end_aptos_epoch(); + + initialize_test_validator(validator2, 100 * ONE_APT, true, true); + let validator2_address = signer::address_of(validator2); + let pool2_address = get_owned_pool_address(validator2_address); + let delegator2_address = signer::address_of(delegator2); + account::create_account_for_test(delegator2_address); + stake::mint(delegator2, 110 * ONE_APT); + add_stake(delegator2, pool2_address, 10 * ONE_APT); + + let proposal_id = aptos_governance::create_proposal_v2_impl( + validator2, + pool2_address, + b"0", + b"", + b"", + true, + ); + + features::change_feature_flags_for_testing( + aptos_framework, + vector[features::get_delegation_pool_partial_governance_voting()], + vector[] + ); + enable_partial_governance_voting(pool1_address); + enable_partial_governance_voting(pool2_address); + + vote(delegator2, pool2_address, proposal_id, 10 * ONE_APT, true); + // Should abort with the error EINSUFFICIENT_STAKE_LOCKUP. + vote(delegator1, pool1_address, proposal_id, 10 * ONE_APT, true); + } + + #[test(aptos_framework = @aptos_framework, validator = @0x123, delegator1 = @0x010)] + #[expected_failure(abort_code = 65551, location = aptos_framework::aptos_governance)] + public entry fun test_vote_should_failed_due_to_proposal_expired( + aptos_framework: &signer, + validator: &signer, + delegator1: &signer, + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage, DelegationPoolAllowlisting { + // This test case begins with the delegation_pool_partial_governance_voting feature disabled. + features::change_feature_flags_for_testing( + aptos_framework, + vector[], + vector[features::get_delegation_pool_partial_governance_voting()] + ); + // partial voing hasn't been enabled yet. A proposal has been created by the validator. + let proposal1_id = setup_vote(aptos_framework, validator, true); + + let validator_address = signer::address_of(validator); + let pool_address = get_owned_pool_address(validator_address); + let delegator1_address = signer::address_of(delegator1); + account::create_account_for_test(delegator1_address); + + stake::mint(delegator1, 110 * ONE_APT); + add_stake(delegator1, pool_address, 10 * ONE_APT); + + timestamp::fast_forward_seconds(2000); + end_aptos_epoch(); + + // Should abort with the error EPROPOSAL_EXPIRED. + vote(delegator1, pool_address, proposal1_id, 10 * ONE_APT, true); + } + + #[test(aptos_framework = @aptos_framework, validator = @0x123, delegator1 = @0x010)] + #[expected_failure(abort_code = 0x10010, location = Self)] + public entry fun test_vote_should_failed_due_to_insufficient_voting_power( + aptos_framework: &signer, + validator: &signer, + delegator1: &signer, + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage, DelegationPoolAllowlisting { + // This test case checks the scenario where delegation_pool_partial_governance_voting is disabled. + features::change_feature_flags_for_testing( + aptos_framework, + vector[], + vector[features::get_delegation_pool_partial_governance_voting()] + ); + // partial voing hasn't been enabled yet. A proposal has been created by the validator. + let proposal1_id = setup_vote(aptos_framework, validator, true); + + let validator_address = signer::address_of(validator); + let pool_address = get_owned_pool_address(validator_address); + let delegator1_address = signer::address_of(delegator1); + account::create_account_for_test(delegator1_address); + + stake::mint(delegator1, 110 * ONE_APT); + add_stake(delegator1, pool_address, 10 * ONE_APT); + end_aptos_epoch(); + vote(delegator1, pool_address, proposal1_id, 10 * ONE_APT, true); + // Should abort with the error ENO_VOTING_POWER. + vote(delegator1, pool_address, proposal1_id, 10 * ONE_APT, true); + } + #[test(aptos_framework = @aptos_framework, validator = @0x123, delegator1 = @0x010, voter1 = @0x030)] public entry fun test_delegate_voting_power_should_pass_even_if_no_stake( aptos_framework: &signer, diff --git a/aptos-move/framework/aptos-framework/sources/stake.spec.move b/aptos-move/framework/aptos-framework/sources/stake.spec.move index 975f77bd14b1f..f922821e8ac83 100644 --- a/aptos-move/framework/aptos-framework/sources/stake.spec.move +++ b/aptos-move/framework/aptos-framework/sources/stake.spec.move @@ -586,6 +586,10 @@ spec aptos_framework::stake { } } + spec fun spec_get_lockup_secs(pool_address: address): u64 { + global(pool_address).locked_until_secs + } + spec calculate_rewards_amount { pragma opaque; // TODO: set because of timeout (property proved) From 673023c706fe19d694b4f990e5a753e3ec24ad91 Mon Sep 17 00:00:00 2001 From: Wolfgang Grieskamp Date: Thu, 19 Dec 2024 17:12:43 -0800 Subject: [PATCH 68/78] [move-prover][cli] Add benchmark functionality (#15636) This adds a new option `aptos move prove --benchmark` which lets verification run in the benchmark framework of the `move-prover/lab` tool. This tool verifies function by function and detects timeouts as well as measure verification time. The result of the benchmark will be stored in `/prover_benchmark.fun_data`. A graphic representation will be stored as well in `prover_benchmark.svg`. The PR fixes also some other things on the way which came apparent when working on it, namely trying to identify the reasons for #15605: - Adds new debug print for which verification targets are generated. This is reachable via `move prove -v debug` - Reduces unnecessary verification of symmetric type instantiations `f<#1, #2>` and `f<#2, #1>` - Adds an option `--skip-instance-check` to completely turn off verification of type instantiations. - Removed legacy verification_analysis_v2 and global_invariant_instrumentation_v2. These are dead code since long and confusing when trying to understand what functions are verified --- Cargo.lock | 40 +- Cargo.toml | 1 + aptos-move/framework/Cargo.toml | 2 + aptos-move/framework/src/prover.rs | 174 +++- crates/aptos/CHANGELOG.md | 2 + third_party/move/move-model/src/model.rs | 5 + .../boogie-backend/src/bytecode_translator.rs | 220 +++-- .../move-prover/boogie-backend/src/options.rs | 6 + .../move-prover/bytecode-pipeline/Cargo.toml | 1 - .../global_invariant_instrumentation_v2.rs | 794 ----------------- .../move-prover/bytecode-pipeline/src/lib.rs | 2 - .../src/verification_analysis_v2.rs | 800 ------------------ third_party/move/move-prover/lab/Cargo.toml | 6 +- .../move/move-prover/lab/src/benchmark.rs | 55 +- third_party/move/move-prover/lab/src/main.rs | 2 +- third_party/move/move-prover/src/lib.rs | 30 +- 16 files changed, 360 insertions(+), 1780 deletions(-) delete mode 100644 third_party/move/move-prover/bytecode-pipeline/src/global_invariant_instrumentation_v2.rs delete mode 100644 third_party/move/move-prover/bytecode-pipeline/src/verification_analysis_v2.rs diff --git a/Cargo.lock b/Cargo.lock index 15f52e4b304bb..1d82d5ce72d44 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1923,6 +1923,7 @@ dependencies = [ "move-prover", "move-prover-boogie-backend", "move-prover-bytecode-pipeline", + "move-prover-lab", "move-stackless-bytecode", "move-unit-test", "move-vm-runtime", @@ -1942,6 +1943,7 @@ dependencies = [ "tempfile", "thiserror", "tiny-keccak", + "toml 0.7.8", ] [[package]] @@ -11649,7 +11651,6 @@ dependencies = [ "codespan-reporting", "datatest-stable", "itertools 0.13.0", - "log", "move-binary-format", "move-core-types", "move-model", @@ -11661,6 +11662,23 @@ dependencies = [ "walkdir", ] +[[package]] +name = "move-prover-lab" +version = "0.1.0" +dependencies = [ + "anyhow", + "chrono", + "clap 4.5.21", + "codespan-reporting", + "itertools 0.13.0", + "move-model", + "move-prover", + "move-prover-boogie-backend", + "move-prover-bytecode-pipeline", + "plotters", + "z3tracer", +] + [[package]] name = "move-prover-test-utils" version = "0.1.0" @@ -13981,26 +13999,6 @@ dependencies = [ "protobuf-codegen", ] -[[package]] -name = "prover-lab" -version = "0.1.0" -dependencies = [ - "anyhow", - "chrono", - "clap 4.5.21", - "codespan-reporting", - "itertools 0.13.0", - "log", - "move-compiler", - "move-compiler-v2", - "move-model", - "move-prover", - "move-prover-boogie-backend", - "move-prover-bytecode-pipeline", - "plotters", - "z3tracer", -] - [[package]] name = "psl-types" version = "2.0.11" diff --git a/Cargo.toml b/Cargo.toml index 85473f6bb3de5..fe006c548de84 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -875,6 +875,7 @@ move-prover = { path = "third_party/move/move-prover" } move-prover-boogie-backend = { path = "third_party/move/move-prover/boogie-backend" } move-prover-bytecode-pipeline = { path = "third_party/move/move-prover/bytecode-pipeline" } move-prover-test-utils = { path = "third_party/move/move-prover/test-utils" } +move-prover-lab = { path = "third_party/move/move-prover/lab" } aptos-move-stdlib = { path = "aptos-move/framework/move-stdlib" } aptos-table-natives = { path = "aptos-move/framework/table-natives" } move-resource-viewer = { path = "third_party/move/tools/move-resource-viewer" } diff --git a/aptos-move/framework/Cargo.toml b/aptos-move/framework/Cargo.toml index fb7d4cb4d4495..35946a9a6bc76 100644 --- a/aptos-move/framework/Cargo.toml +++ b/aptos-move/framework/Cargo.toml @@ -60,6 +60,7 @@ move-package = { workspace = true } move-prover = { workspace = true } move-prover-boogie-backend = { workspace = true } move-prover-bytecode-pipeline = { workspace = true } +move-prover-lab = { workspace = true } move-stackless-bytecode = { workspace = true } move-vm-runtime = { workspace = true } move-vm-types = { workspace = true } @@ -78,6 +79,7 @@ smallvec = { workspace = true } tempfile = { workspace = true } thiserror = { workspace = true } tiny-keccak = { workspace = true } +toml = { workspace = true } [dev-dependencies] aptos-aggregator = { workspace = true, features = ["testing"] } diff --git a/aptos-move/framework/src/prover.rs b/aptos-move/framework/src/prover.rs index fbe8a7fed97a1..56952fbae1a9b 100644 --- a/aptos-move/framework/src/prover.rs +++ b/aptos-move/framework/src/prover.rs @@ -2,15 +2,21 @@ // SPDX-License-Identifier: Apache-2.0 use crate::build_model; +use anyhow::bail; use codespan_reporting::{ diagnostic::Severity, term::termcolor::{ColorChoice, StandardStream}, }; -use log::LevelFilter; +use log::{info, LevelFilter}; use move_core_types::account_address::AccountAddress; -use move_model::metadata::{CompilerVersion, LanguageVersion}; +use move_model::{ + metadata::{CompilerVersion, LanguageVersion}, + model::{GlobalEnv, VerificationScope}, +}; +use move_prover::cli::Options; use std::{ collections::{BTreeMap, BTreeSet}, + fs, path::Path, time::Instant, }; @@ -27,6 +33,12 @@ pub struct ProverOptions { #[clap(long, short)] pub filter: Option, + /// Scopes verification to the specified function. This can either be a name of the + /// form "mod::func" or simply "func", in the later case every matching function is + /// taken. + #[clap(long, short)] + pub only: Option, + /// Whether to display additional information in error reports. This may help /// debugging but also can make verification slower. #[clap(long, short)] @@ -84,6 +96,24 @@ pub struct ProverOptions { #[clap(long)] pub dump: bool, + /// Whether to benchmark verification. If selected, each verification target in the + /// current package will be verified independently with timing recorded. This attempts + /// to detect timeouts. A benchmark report will be written to `prover_benchmark.fun_data` in the + /// package directory. The command also writes a `prover_benchmark.svg` graphic, which + /// is build from the data in the file above, comparing with any other `*.fun_data` files + /// in the package directory. Thus, you can rename the data file to something like + /// `prover_benchmark_v1.fun_data` and in the next run, compare benchmarks in the `.svg` + /// file from multiple runs. + #[clap(long = "benchmark")] + pub benchmark: bool, + + /// Whether to skip verification of type instantiations of functions. This may miss + /// some verification conditions if different type instantiations can create + /// different behavior via type reflection or storage access, but can speed up + /// verification. + #[clap(long = "skip-instance-check")] + pub skip_instance_check: bool, + #[clap(skip)] pub for_test: bool, } @@ -93,6 +123,7 @@ impl Default for ProverOptions { Self { verbosity: None, filter: None, + only: None, trace: false, cvc5: false, stratification_depth: 6, @@ -106,7 +137,9 @@ impl Default for ProverOptions { loop_unroll: None, stable_test_output: false, dump: false, + benchmark: false, for_test: false, + skip_instance_check: false, } } } @@ -127,6 +160,7 @@ impl ProverOptions { ) -> anyhow::Result<()> { let now = Instant::now(); let for_test = self.for_test; + let benchmark = self.benchmark; let mut model = build_model( dev_mode, package_path, @@ -140,6 +174,15 @@ impl ProverOptions { experiments.to_vec(), )?; let mut options = self.convert_options(); + options.language_version = language_version; + options.model_builder.language_version = language_version.unwrap_or_default(); + if compiler_version.unwrap_or_default() >= CompilerVersion::V2_0 + || language_version + .unwrap_or_default() + .is_at_least(LanguageVersion::V2_0) + { + options.compiler_v2 = true; + } // Need to ensure a distinct output.bpl file for concurrent execution. In non-test // mode, we actually want to use the static output.bpl for debugging purposes let _temp_holder = if for_test { @@ -163,11 +206,21 @@ impl ProverOptions { template_bytes: include_bytes!("aptos-natives.bpl").to_vec(), module_instance_names: move_prover_boogie_backend::options::custom_native_options(), }); - let mut writer = StandardStream::stderr(ColorChoice::Auto); - if compiler_version.unwrap_or_default() == CompilerVersion::V1 { - move_prover::run_move_prover_with_model(&mut model, &mut writer, options, Some(now))?; + if benchmark { + // Special mode of benchmarking + run_prover_benchmark(package_path, &mut model, options)?; } else { - move_prover::run_move_prover_with_model_v2(&mut model, &mut writer, options, now)?; + let mut writer = StandardStream::stderr(ColorChoice::Auto); + if compiler_version.unwrap_or_default() == CompilerVersion::V1 { + move_prover::run_move_prover_with_model( + &mut model, + &mut writer, + options, + Some(now), + )?; + } else { + move_prover::run_move_prover_with_model_v2(&mut model, &mut writer, options, now)?; + } } Ok(()) } @@ -184,6 +237,11 @@ impl ProverOptions { output_path: "".to_string(), verbosity_level, prover: move_prover_bytecode_pipeline::options::ProverOptions { + verify_scope: if let Some(name) = self.only { + VerificationScope::Only(name) + } else { + VerificationScope::All + }, stable_test_output: self.stable_test_output, auto_trace_level: if self.trace { move_prover_bytecode_pipeline::options::AutoTraceLevel::VerifiedFunction @@ -215,6 +273,7 @@ impl ProverOptions { }, custom_natives: None, loop_unroll: self.loop_unroll, + skip_instance_check: self.skip_instance_check, ..Default::default() }, ..Default::default() @@ -234,3 +293,106 @@ impl ProverOptions { } } } + +fn run_prover_benchmark( + package_path: &Path, + env: &mut GlobalEnv, + mut options: Options, +) -> anyhow::Result<()> { + info!("starting prover benchmark"); + // Determine sources and dependencies from the env + let mut sources = BTreeSet::new(); + let mut deps: Vec = vec![]; + for module in env.get_modules() { + let file_name = module.get_source_path().to_string_lossy().to_string(); + if module.is_primary_target() { + sources.insert(module.get_source_path().to_string_lossy().to_string()); + } else if let Some(p) = Path::new(&file_name) + .parent() + .and_then(|p| p.canonicalize().ok()) + { + // The prover doesn't like to have `p` and `p/s` as dep paths, filter those out + let p = p.to_string_lossy().to_string(); + let mut done = false; + for d in &mut deps { + if p.starts_with(&*d) { + // p is subsumed + done = true; + break; + } else if d.starts_with(&p) { + // p is more general or equal to d, swap it out + *d = p.to_string(); + done = true; + break; + } + } + if !done { + deps.push(p) + } + } else { + bail!("invalid file path `{}`", file_name) + } + } + + // Enrich the prover options by the aliases in the env + for (alias, address) in env.get_address_alias_map() { + options.move_named_address_values.push(format!( + "{}={}", + alias.display(env.symbol_pool()), + address.to_hex_literal() + )) + } + + // Create or override a prover_benchmark.toml in the package dir, reflection `options` + let config_file = package_path.join("prover_benchmark.toml"); + let toml = toml::to_string(&options)?; + std::fs::write(&config_file, toml)?; + + // Args for the benchmark API + let mut args = vec![ + // Command name + "bench".to_string(), + // Benchmark by function not module + "--func".to_string(), + // Use as the config the file we derived from `options` + "--config".to_string(), + config_file.to_string_lossy().to_string(), + ]; + + // Add deps and sources to args and run the tool + for dep in deps { + args.push("-d".to_string()); + args.push(dep) + } + args.extend(sources); + move_prover_lab::benchmark::benchmark(&args); + + // The benchmark stores the result in `.fun_data`, now plot it. + // If there are any other `*.fun_data` files, add them to the plot. + let mut args = vec![ + "plot".to_string(), + format!( + "--out={}", + config_file + .as_path() + .with_extension("svg") + .to_string_lossy() + ), + "--sort".to_string(), + ]; + let main_data_file = config_file + .as_path() + .with_extension("fun_data") + .to_string_lossy() + .to_string(); + args.push(main_data_file.clone()); + let paths = fs::read_dir(package_path)?; + for p in paths.flatten() { + let p = p.path().as_path().to_string_lossy().to_string(); + // Only use this if its is not the main data file we already added + if p.ends_with(".fun_data") && !p.ends_with("/prover_benchmark.fun_data") { + args.push(p) + } + } + move_prover_lab::plot::plot_svg(&args) +} diff --git a/crates/aptos/CHANGELOG.md b/crates/aptos/CHANGELOG.md index 591c7bff8abb6..24fa28425dfc2 100644 --- a/crates/aptos/CHANGELOG.md +++ b/crates/aptos/CHANGELOG.md @@ -3,6 +3,8 @@ All notable changes to the Aptos CLI will be captured in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) and the format set out by [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). # Unreleased +- Add flag `--benchmark` to `aptos move prove`, which allows to benchmark verification times of individual functions in a package. +- Add flag `--only ` to `aptos move prove`, which allows to scope verification to a function. ## [5.1.0] - 2024/12/13 - More optimizations are now default for compiler v2. diff --git a/third_party/move/move-model/src/model.rs b/third_party/move/move-model/src/model.rs index 63e4749401965..c4d08a9f63b74 100644 --- a/third_party/move/move-model/src/model.rs +++ b/third_party/move/move-model/src/model.rs @@ -700,6 +700,11 @@ impl GlobalEnv { self.address_alias_map = map } + /// Gets the global address alias map + pub fn get_address_alias_map(&self) -> &BTreeMap { + &self.address_alias_map + } + /// Indicates that all modules in the environment should be treated as /// target modules, i.e. `module.is_target()` returns true. This can be /// used to temporarily override the default which distinguishes diff --git a/third_party/move/move-prover/boogie-backend/src/bytecode_translator.rs b/third_party/move/move-prover/boogie-backend/src/bytecode_translator.rs index 350e912f8f284..5ebb919eff17f 100644 --- a/third_party/move/move-prover/boogie-backend/src/bytecode_translator.rs +++ b/third_party/move/move-prover/boogie-backend/src/bytecode_translator.rs @@ -31,7 +31,10 @@ use move_model::{ ast::{Attribute, TempIndex, TraceKind}, code_writer::CodeWriter, emit, emitln, - model::{FieldEnv, FieldId, GlobalEnv, Loc, NodeId, QualifiedInstId, StructEnv, StructId}, + model::{ + FieldEnv, FieldId, FunctionEnv, GlobalEnv, Loc, NodeId, QualifiedInstId, StructEnv, + StructId, + }, pragmas::{ ADDITION_OVERFLOW_UNCHECKED_PRAGMA, SEED_PRAGMA, TIMEOUT_PRAGMA, VERIFY_DURATION_ESTIMATE_PRAGMA, @@ -278,6 +281,10 @@ impl<'env> BoogieTranslator<'env> { for (variant, ref fun_target) in self.targets.get_targets(fun_env) { if variant.is_verified() && !self.is_not_verified_timeout(fun_target) { verified_functions_count += 1; + debug!( + "will verify primary function `{}`", + env.display(&module_env.get_id().qualified(fun_target.get_id())) + ); // Always produce a verified functions with an empty instantiation such that // there is at least one top-level entry points for a VC. FunctionTranslator { @@ -289,28 +296,45 @@ impl<'env> BoogieTranslator<'env> { // There maybe more verification targets that needs to be produced as we // defer the instantiation of verified functions to this stage - for type_inst in mono_info - .funs - .get(&(fun_target.func_env.get_qualified_id(), variant)) - .unwrap_or(empty) - { - // Skip the none instantiation (i.e., each type parameter is - // instantiated to itself as a concrete type). This has the same - // effect as `type_inst: &[]` and is already captured above. - let is_none_inst = type_inst.iter().enumerate().all( - |(i, t)| matches!(t, Type::TypeParameter(idx) if *idx == i as u16), - ); - if is_none_inst { - continue; - } + if !self.options.skip_instance_check { + for type_inst in mono_info + .funs + .get(&(fun_target.func_env.get_qualified_id(), variant)) + .unwrap_or(empty) + { + // Skip redundant instantiations. Those are any permutation of + // type parameters. We can simple test this by the same number + // of disjoint type parameters equals the count of type parameters. + // Verifying a disjoint set of type parameters is the same + // as the `&[]` verification already done above. + let type_params_in_inst = type_inst + .iter() + .filter(|t| matches!(t, Type::TypeParameter(_))) + .cloned() + .collect::>(); + if type_params_in_inst.len() == type_inst.len() { + continue; + } - verified_functions_count += 1; - FunctionTranslator { - parent: self, - fun_target, - type_inst, + verified_functions_count += 1; + let tctx = &fun_env.get_type_display_ctx(); + debug!( + "will verify function instantiation `{}`<{}>", + env.display( + &module_env.get_id().qualified(fun_target.get_id()) + ), + type_inst + .iter() + .map(|t| t.display(tctx).to_string()) + .join(", ") + ); + FunctionTranslator { + parent: self, + fun_target, + type_inst, + } + .translate(); } - .translate(); } } else { // This variant is inlined, so translate for all type instantiations. @@ -1464,80 +1488,13 @@ impl<'env> FunctionTranslator<'env> { ) .join(","); - // special casing for type reflection - let mut processed = false; - - // TODO(mengxu): change it to a better address name instead of extlib - if env.get_extlib_address() == *module_env.get_name().addr() { - let qualified_name = format!( - "{}::{}", - module_env.get_name().name().display(env.symbol_pool()), - callee_env.get_name().display(env.symbol_pool()), - ); - if qualified_name == TYPE_NAME_MOVE { - assert_eq!(inst.len(), 1); - if dest_str.is_empty() { - emitln!( - writer, - "{}", - boogie_reflection_type_name(env, &inst[0], false) - ); - } else { - emitln!( - writer, - "{} := {};", - dest_str, - boogie_reflection_type_name(env, &inst[0], false) - ); - } - processed = true; - } else if qualified_name == TYPE_INFO_MOVE { - assert_eq!(inst.len(), 1); - let (flag, info) = boogie_reflection_type_info(env, &inst[0]); - emitln!(writer, "if (!{}) {{", flag); - writer.with_indent(|| emitln!(writer, "call $ExecFailureAbort();")); - emitln!(writer, "}"); - if !dest_str.is_empty() { - emitln!(writer, "else {"); - writer.with_indent(|| { - emitln!(writer, "{} := {};", dest_str, info) - }); - emitln!(writer, "}"); - } - processed = true; - } - } - - if env.get_stdlib_address() == *module_env.get_name().addr() { - let qualified_name = format!( - "{}::{}", - module_env.get_name().name().display(env.symbol_pool()), - callee_env.get_name().display(env.symbol_pool()), - ); - if qualified_name == TYPE_NAME_GET_MOVE { - assert_eq!(inst.len(), 1); - if dest_str.is_empty() { - emitln!( - writer, - "{}", - boogie_reflection_type_name(env, &inst[0], true) - ); - } else { - emitln!( - writer, - "{} := {};", - dest_str, - boogie_reflection_type_name(env, &inst[0], true) - ); - } - processed = true; - } - } - - // regular path - if !processed { + if self.try_reflection_call(writer, env, inst, &callee_env, &dest_str) { + // Special case of reflection call, code is generated + } else { + // regular path let targeted = self.fun_target.module_env().is_target(); - // If the callee has been generated from a native interface, return an error + // If the callee has been generated from a native interface, return + // an error if callee_env.is_native() && targeted { for attr in callee_env.get_attributes() { if let Attribute::Apply(_, name, _) = attr { @@ -2601,6 +2558,81 @@ impl<'env> FunctionTranslator<'env> { emitln!(writer); } + fn try_reflection_call( + &self, + writer: &CodeWriter, + env: &GlobalEnv, + inst: &[Type], + callee_env: &FunctionEnv, + dest_str: &String, + ) -> bool { + let module_env = &callee_env.module_env; + let mk_qualified_name = || { + format!( + "{}::{}", + module_env.get_name().name().display(env.symbol_pool()), + callee_env.get_name().display(env.symbol_pool()), + ) + }; + if env.get_extlib_address() == *module_env.get_name().addr() { + let qualified_name = mk_qualified_name(); + if qualified_name == TYPE_NAME_MOVE { + assert_eq!(inst.len(), 1); + if dest_str.is_empty() { + emitln!( + writer, + "{}", + boogie_reflection_type_name(env, &inst[0], false) + ); + } else { + emitln!( + writer, + "{} := {};", + dest_str, + boogie_reflection_type_name(env, &inst[0], false) + ); + } + return true; + } else if qualified_name == TYPE_INFO_MOVE { + assert_eq!(inst.len(), 1); + let (flag, info) = boogie_reflection_type_info(env, &inst[0]); + emitln!(writer, "if (!{}) {{", flag); + writer.with_indent(|| emitln!(writer, "call $ExecFailureAbort();")); + emitln!(writer, "}"); + if !dest_str.is_empty() { + emitln!(writer, "else {"); + writer.with_indent(|| emitln!(writer, "{} := {};", dest_str, info)); + emitln!(writer, "}"); + } + return true; + } + } + + if env.get_stdlib_address() == *module_env.get_name().addr() { + let qualified_name = mk_qualified_name(); + if qualified_name == TYPE_NAME_GET_MOVE { + assert_eq!(inst.len(), 1); + if dest_str.is_empty() { + emitln!( + writer, + "{}", + boogie_reflection_type_name(env, &inst[0], true) + ); + } else { + emitln!( + writer, + "{} := {};", + dest_str, + boogie_reflection_type_name(env, &inst[0], true) + ); + } + return true; + } + } + + false + } + fn translate_write_back(&self, dest: &BorrowNode, edge: &BorrowEdge, src: TempIndex) { use BorrowNode::*; let writer = self.parent.writer; diff --git a/third_party/move/move-prover/boogie-backend/src/options.rs b/third_party/move/move-prover/boogie-backend/src/options.rs index 989095b5659f3..ea88b5c113704 100644 --- a/third_party/move/move-prover/boogie-backend/src/options.rs +++ b/third_party/move/move-prover/boogie-backend/src/options.rs @@ -159,6 +159,11 @@ pub struct BoogieOptions { /// A hard timeout for boogie execution; if the process does not terminate within /// this time frame, it will be killed. Zero for no timeout. pub hard_timeout_secs: u64, + /// Whether to skip verification of type instantiations of functions. This may miss + /// some verification conditions if different type instantiations can create + /// different behavior via type reflection or storage access, but can speed up + /// verification. + pub skip_instance_check: bool, /// What vector theory to use. pub vector_theory: VectorTheory, /// Whether to generate a z3 trace file and where to put it. @@ -207,6 +212,7 @@ impl Default for BoogieOptions { custom_natives: None, loop_unroll: None, borrow_aggregates: vec![], + skip_instance_check: false, } } } diff --git a/third_party/move/move-prover/bytecode-pipeline/Cargo.toml b/third_party/move/move-prover/bytecode-pipeline/Cargo.toml index 366973ed14db2..2d41dd22fa8a4 100644 --- a/third_party/move/move-prover/bytecode-pipeline/Cargo.toml +++ b/third_party/move/move-prover/bytecode-pipeline/Cargo.toml @@ -11,7 +11,6 @@ abstract-domain-derive = { path = "../../move-model/bytecode/abstract_domain_der anyhow = { workspace = true } codespan-reporting = { workspace = true } itertools = { workspace = true } -log = { workspace = true, features = ["serde"] } move-binary-format = { workspace = true } move-core-types = { workspace = true } move-model = { workspace = true } diff --git a/third_party/move/move-prover/bytecode-pipeline/src/global_invariant_instrumentation_v2.rs b/third_party/move/move-prover/bytecode-pipeline/src/global_invariant_instrumentation_v2.rs deleted file mode 100644 index a71b9be51b73a..0000000000000 --- a/third_party/move/move-prover/bytecode-pipeline/src/global_invariant_instrumentation_v2.rs +++ /dev/null @@ -1,794 +0,0 @@ -// Copyright (c) The Diem Core Contributors -// Copyright (c) The Move Contributors -// SPDX-License-Identifier: Apache-2.0 - -// Transformation which injects global invariants into the bytecode. - -use crate::{options::ProverOptions, verification_analysis_v2::InvariantAnalysisData}; -use itertools::Itertools; -#[allow(unused_imports)] -use log::{debug, info, log, warn}; -#[cfg(invariant_trace)] -use move_model::ty::TypeDisplayContext; -use move_model::{ - ast::{ConditionKind, Exp, GlobalInvariant}, - exp_generator::ExpGenerator, - model::{FunId, FunctionEnv, GlobalEnv, GlobalId, Loc, QualifiedId, QualifiedInstId, StructId}, - pragmas::CONDITION_ISOLATED_PROP, - spec_translator::{SpecTranslator, TranslatedSpec}, - ty::{NoUnificationContext, Type, TypeUnificationAdapter, Variance}, -}; -use move_stackless_bytecode::{ - function_data_builder::FunctionDataBuilder, - function_target::{FunctionData, FunctionTarget}, - function_target_pipeline::{ - FunctionTargetProcessor, FunctionTargetsHolder, FunctionVariant, VerificationFlavor, - }, - stackless_bytecode::{BorrowNode, Bytecode, Operation, PropKind}, - usage_analysis, -}; -use std::collections::{BTreeMap, BTreeSet}; - -const GLOBAL_INVARIANT_FAILS_MESSAGE: &str = "global memory invariant does not hold"; - -pub struct GlobalInvariantInstrumentationProcessorV2 {} - -impl GlobalInvariantInstrumentationProcessorV2 { - pub fn new() -> Box { - Box::new(Self {}) - } -} - -impl FunctionTargetProcessor for GlobalInvariantInstrumentationProcessorV2 { - fn process( - &self, - targets: &mut FunctionTargetsHolder, - fun_env: &FunctionEnv, - data: FunctionData, - _scc_opt: Option<&[FunctionEnv]>, - ) -> FunctionData { - if fun_env.is_native() || fun_env.is_intrinsic() { - // Nothing to do. - return data; - } - if !data.variant.is_verified() { - // Only need to instrument if this is a verification variant - return data; - } - - // Analyze invariants - let target = FunctionTarget::new(fun_env, &data); - let Analyzer { plain, func_insts } = Analyzer::analyze(&target); - - // Collect information - let env = target.global_env(); - - // Create variants for possible function instantiations - let mut func_variants = vec![]; - for (i, (ty_args, mut global_ids)) in func_insts.into_iter().enumerate() { - let variant_data = data.fork_with_instantiation( - env, - &ty_args, - FunctionVariant::Verification(VerificationFlavor::Instantiated(i)), - ); - global_ids.extend(plain.clone().into_iter()); - func_variants.push((variant_data, global_ids)); - } - - // Instrument the main variant - let main = Instrumenter::run(fun_env, data, plain); - - // Instrument the variants representing different instantiations - for (variant_data, variant_global_invariants) in func_variants { - let variant = Instrumenter::run(fun_env, variant_data, variant_global_invariants); - targets.insert_target_data( - &fun_env.get_qualified_id(), - variant.variant.clone(), - variant, - ); - } - - // Return the main variant - main - } - - fn name(&self) -> String { - "global_invariant_instrumenter_v2".to_string() - } -} - -struct Analyzer { - plain: BTreeSet, - func_insts: BTreeMap, BTreeSet>, -} - -impl Analyzer { - pub fn analyze(target: &FunctionTarget) -> Self { - let mut analyzer = Self { - plain: BTreeSet::new(), - func_insts: BTreeMap::new(), - }; - analyzer.collect_related_global_invariants(target); - analyzer - } - - /// Collect global invariants that are read and written by this function - fn collect_related_global_invariants(&mut self, target: &FunctionTarget) { - let env = target.global_env(); - - // get memory (list of structs) read or written by the function target, - // then find all invariants in loaded modules that refer to that memory. - let mut invariants_for_used_memory = BTreeSet::new(); - for mem in usage_analysis::get_memory_usage(target).accessed.all.iter() { - invariants_for_used_memory.extend(env.get_global_invariants_for_memory(mem)); - } - - // filter non-applicable global invariants - for invariant_id in invariants_for_used_memory { - self.check_global_invariant_applicability( - target, - env.get_global_invariant(invariant_id).unwrap(), - ); - } - } - - fn check_global_invariant_applicability( - &mut self, - target: &FunctionTarget, - invariant: &GlobalInvariant, - ) { - // marks whether the invariant will be checked in all instantiations of this function - let mut is_generic = false; - - // collect instantiations of this function that are needed to check this global invariant - let mut func_insts = BTreeSet::new(); - - let fun_mems = &usage_analysis::get_memory_usage(target).accessed.all; - let fun_arity = target.get_type_parameter_count(); - for inv_mem in &invariant.mem_usage { - for fun_mem in fun_mems.iter() { - if inv_mem.module_id != fun_mem.module_id || inv_mem.id != fun_mem.id { - continue; - } - let adapter = - TypeUnificationAdapter::new_vec(&fun_mem.inst, &inv_mem.inst, true, true); - let rel = adapter.unify( - &mut NoUnificationContext, - Variance::SpecVariance, - /* shallow_subst */ false, - ); - match rel { - None => continue, - Some((subs_fun, _)) => { - if subs_fun.is_empty() { - is_generic = true; - } else { - func_insts.insert(Type::type_param_map_to_inst(fun_arity, subs_fun)); - } - }, - } - } - } - - // save the instantiation required to evaluate this invariant - for inst in func_insts { - self.func_insts - .entry(inst) - .or_default() - .insert(invariant.id); - } - if is_generic { - self.plain.insert(invariant.id); - } - } -} - -struct Instrumenter<'a> { - options: &'a ProverOptions, - builder: FunctionDataBuilder<'a>, - _function_inst: Vec, - used_memory: BTreeSet>, - // Invariants that unify with the state used in a function instantiation - related_invariants: BTreeSet, - saved_from_before_instr_or_call: Option<(TranslatedSpec, BTreeSet)>, -} - -impl<'a> Instrumenter<'a> { - fn run( - fun_env: &FunctionEnv<'a>, - data: FunctionData, - related_invariants: BTreeSet, - ) -> FunctionData { - if !data.variant.is_verified() { - // Run the instrumentation only if this is a verification variant. - return data; - } - - let global_env = fun_env.module_env.env; - let options = ProverOptions::get(global_env); - let function_inst = data.get_type_instantiation(fun_env); - let builder = FunctionDataBuilder::new(fun_env, data); - let used_memory: BTreeSet<_> = usage_analysis::get_memory_usage(&builder.get_target()) - .accessed - .get_all_inst(&function_inst); - - #[cfg(invariant_trace)] - { - let tctx = TypeDisplayContext::WithEnv { - env: global_env, - type_param_names: None, - }; - println!( - "{}<{}>: {}", - builder.data.variant, - function_inst - .iter() - .map(|t| t.display(&tctx).to_string()) - .join(","), - used_memory - .iter() - .map(|m| global_env.display(m).to_string()) - .join(",") - ); - } - - let mut instrumenter = Instrumenter { - options: options.as_ref(), - builder, - _function_inst: function_inst, - used_memory, - related_invariants, - saved_from_before_instr_or_call: None, - }; - instrumenter.instrument(global_env); - instrumenter.builder.data - } - - fn instrument(&mut self, global_env: &GlobalEnv) { - // Collect information - let fun_env = self.builder.fun_env; - let fun_id = fun_env.get_qualified_id(); - - let inv_ana_data = global_env.get_extension::().unwrap(); - let disabled_inv_fun_set = &inv_ana_data.disabled_inv_fun_set; - let non_inv_fun_set = &inv_ana_data.non_inv_fun_set; - let target_invariants = &inv_ana_data.target_invariants; - let disabled_invs_for_fun = &inv_ana_data.disabled_invs_for_fun; - - // Extract and clear current code - let old_code = std::mem::take(&mut self.builder.data.code); - - // Emit entrypoint assumptions - let mut entrypoint_invariants = self.filter_entrypoint_invariants(&self.related_invariants); - if non_inv_fun_set.contains(&fun_id) { - if let Some(invs_disabled) = disabled_invs_for_fun.get(&fun_id) { - entrypoint_invariants = entrypoint_invariants - .difference(invs_disabled) - .cloned() - .collect(); - } - } - let xlated_spec = self.translate_invariants(&entrypoint_invariants); - self.assert_or_assume_translated_invariants( - &xlated_spec.invariants, - &entrypoint_invariants, - PropKind::Assume, - ); - - // In addition to the entrypoint invariants assumed just above, it is necessary - // to assume more invariants in a special case. When invariants are disabled in - // this function but not in callers, we will later assert those invariants just - // before return instructions. - // We need to assume those invariants at the beginning of the function in order - // to prove them later. They aren't necessarily entrypoint invariants if we are - // verifying a function in a strict dependency, or in a friend module that does not - // have the target module in its dependencies. - // So, the next code finds the set of target invariants (which will be assumed on return) - // and assumes those that are not entrypoint invariants. - if disabled_inv_fun_set.contains(&fun_id) { - // Separate the update invariants, because we never want to assume them. - let (global_target_invs, _update_target_invs) = - self.separate_update_invariants(target_invariants); - let return_invariants: BTreeSet<_> = global_target_invs - .difference(&entrypoint_invariants) - .cloned() - .collect(); - let xlated_spec = self.translate_invariants(&return_invariants); - self.assert_or_assume_translated_invariants( - &xlated_spec.invariants, - &return_invariants, - PropKind::Assume, - ); - } - - // Generate new instrumented code. - for bc in old_code { - self.instrument_bytecode(bc, fun_id, &inv_ana_data, &entrypoint_invariants); - } - } - - /// Returns list of invariant ids to be assumed at the beginning of the current function. - fn filter_entrypoint_invariants( - &self, - related_invariants: &BTreeSet, - ) -> BTreeSet { - // Emit an assume of each invariant over memory touched by this function. - // Such invariants include - // - invariants declared in this module, or - // - invariants declared in transitively dependent modules - // - // Excludes global invariants that - // - are marked by the user explicitly as `[isolated]`, or - // - are not declared in dependent modules of the module defining the - // function (which may not be the target module) and upon which the - // code should therefore not depend, apart from the update itself, or - // - are "update" invariants. - - // Adds back target invariants that are modified (directly or indirectly) in the function. - - let env = self.builder.global_env(); - let module_env = &self.builder.fun_env.module_env; - - related_invariants - .iter() - .filter_map(|id| { - env.get_global_invariant(*id).filter(|inv| { - // excludes "update invariants" - matches!(inv.kind, ConditionKind::GlobalInvariant(..)) - && module_env.is_transitive_dependency(inv.declaring_module) - && !module_env - .env - .is_property_true(&inv.properties, CONDITION_ISOLATED_PROP) - .unwrap_or(false) - }) - }) - .map(|inv| inv.id) - .collect() - } - - fn instrument_bytecode( - &mut self, - bc: Bytecode, - fun_id: QualifiedId, - inv_ana_data: &InvariantAnalysisData, - entrypoint_invariants: &BTreeSet, - ) { - use BorrowNode::*; - use Bytecode::*; - use Operation::*; - let target_invariants = &inv_ana_data.target_invariants; - let disabled_inv_fun_set = &inv_ana_data.disabled_inv_fun_set; - let always_check_invs: BTreeSet; - if let Some(disabled_invs) = &inv_ana_data.disabled_invs_for_fun.get(&fun_id) { - always_check_invs = entrypoint_invariants - .difference(disabled_invs) - .cloned() - .collect(); - } else { - always_check_invs = entrypoint_invariants.clone(); - } - - match &bc { - Call(_, _, WriteBack(GlobalRoot(mem), ..), ..) => { - self.emit_invariants_for_bytecode( - &bc, - &fun_id, - inv_ana_data, - mem, - &always_check_invs, - ); - }, - Call(_, _, MoveTo(mid, sid, inst), ..) | Call(_, _, MoveFrom(mid, sid, inst), ..) => { - let mem = mid.qualified_inst(*sid, inst.to_owned()); - self.emit_invariants_for_bytecode( - &bc, - &fun_id, - inv_ana_data, - &mem, - &always_check_invs, - ); - }, - // Emit assumes before procedure calls. This also deals with saves for update invariants. - Call(_, _, OpaqueCallBegin(module_id, id, _), _, _) => { - self.assume_invariants_for_opaque_begin( - module_id.qualified(*id), - entrypoint_invariants, - inv_ana_data, - ); - // Then emit the call instruction. - self.builder.emit(bc); - }, - // Emit asserts after procedure calls - Call(_, _, OpaqueCallEnd(module_id, id, _), _, _) => { - // First, emit the call instruction. - self.builder.emit(bc.clone()); - self.assert_invariants_for_opaque_end(module_id.qualified(*id), inv_ana_data) - }, - // An inline call needs to be treated similarly (but there is just one instruction. - Call(_, _, Function(module_id, id, _), _, _) => { - self.assume_invariants_for_opaque_begin( - module_id.qualified(*id), - entrypoint_invariants, - inv_ana_data, - ); - // Then emit the call instruction. - self.builder.emit(bc.clone()); - self.assert_invariants_for_opaque_end(module_id.qualified(*id), inv_ana_data) - }, - // When invariants are disabled in the body of this function but not in its - // callers, assert them just before a return instruction (the caller will be - // assuming they hold). - Ret(_, _) => { - if disabled_inv_fun_set.contains(&fun_id) { - // TODO: It is only necessary to assert invariants that were disabled here. - // Asserting more won't hurt, but generates unnecessary work for the prover. - let (global_target_invs, _update_target_invs) = - self.separate_update_invariants(target_invariants); - let xlated_spec = self.translate_invariants(&global_target_invs); - self.assert_or_assume_translated_invariants( - &xlated_spec.invariants, - &global_target_invs, - PropKind::Assert, - ); - } - self.builder.emit(bc); - }, - _ => self.builder.emit(bc), - } - } - - /// Emit invariants and saves for call to OpaqueCallBegin in the - /// special case where the invariants are not checked in the - /// called function. - fn assume_invariants_for_opaque_begin( - &mut self, - called_fun_id: QualifiedId, - entrypoint_invariants: &BTreeSet, - inv_ana_data: &InvariantAnalysisData, - ) { - let target_invariants = &inv_ana_data.target_invariants; - let disabled_inv_fun_set = &inv_ana_data.disabled_inv_fun_set; - let non_inv_fun_set = &inv_ana_data.non_inv_fun_set; - let funs_that_modify_inv = &inv_ana_data.funs_that_modify_inv; - // Normally, invariants would be assumed and asserted in - // a called function, and so there would be no need to assume - // the invariant before the call. - // When invariants are not disabled in the current function - // but the called function doesn't check them, we are going to - // need to assert the invariant when the call returns (at the - // matching OpaqueCallEnd instruction). So, we assume the - // invariant here, before the OpaqueCallBegin, so that we have - // a hope of proving it later. - let fun_id = self.builder.fun_env.get_qualified_id(); - if !disabled_inv_fun_set.contains(&fun_id) - && !non_inv_fun_set.contains(&fun_id) - && non_inv_fun_set.contains(&called_fun_id) - { - // Do not assume update invs - // This prevents ASSERTING the updates because emit_assumes_and_saves - // stores translated invariants for assertion in assume_invariants_for_opaque_end, - // and we don't want updates to be asserted there. - // TODO: This should all be refactored to eliminate hacks like the previous - // sentence. - let (global_invs, _update_invs) = self.separate_update_invariants(target_invariants); - // assume the invariants that are modified by the called function - let modified_invs = - self.get_invs_modified_by_fun(&global_invs, called_fun_id, funs_that_modify_inv); - self.emit_assumes_and_saves_before_bytecode(modified_invs, entrypoint_invariants); - } - } - - /// Called when invariants need to be checked, but an opaque called function - /// doesn't check them. - fn assert_invariants_for_opaque_end( - &mut self, - called_fun_id: QualifiedId, - inv_ana_data: &InvariantAnalysisData, - ) { - let disabled_inv_fun_set = &inv_ana_data.disabled_inv_fun_set; - let non_inv_fun_set = &inv_ana_data.non_inv_fun_set; - // Add invariant assertions after function call when invariant holds in the - // body of the current function, but the called function does not assert - // invariants. - // The asserted invariant ensures the invariant - // holds in the body of the current function, as is required. - let fun_id = self.builder.fun_env.get_qualified_id(); - if !disabled_inv_fun_set.contains(&fun_id) - && !non_inv_fun_set.contains(&fun_id) - && non_inv_fun_set.contains(&called_fun_id) - { - self.emit_asserts_after_bytecode(); - } - } - - /// Emit invariant-related assumptions and assertions around a bytecode. - /// Before instruction, emit assumptions of global invariants, if necessary, - /// and emit saves of old state for update invariants. - fn emit_invariants_for_bytecode( - &mut self, - bc: &Bytecode, - fun_id: &QualifiedId, - inv_ana_data: &InvariantAnalysisData, - mem: &QualifiedInstId, - entrypoint_invariants: &BTreeSet, - ) { - // When invariants are enabled during the body of the current function, add asserts after - // the operation for each invariant that the operation could modify. Such an operation - // includes write-backs to a GlobalRoot or MoveTo/MoveFrom a location in the global storage. - let target_invariants = &inv_ana_data.target_invariants; - - let env = self.builder.global_env(); - // consider only the invariants that are modified by instruction - // TODO (IMPORTANT): target_invariants and disabled_invs were not computed with unification, - // so it may be that some invariants are not going to be emitted that should be. - let mut modified_invariants: BTreeSet = env - .get_global_invariants_for_memory(mem) - .intersection(target_invariants) - .copied() - .collect(); - - if let Some(disabled_invs) = &inv_ana_data.disabled_invs_for_fun.get(fun_id) { - modified_invariants = modified_invariants - .difference(disabled_invs) - .cloned() - .collect(); - } - self.emit_assumes_and_saves_before_bytecode(modified_invariants, entrypoint_invariants); - // put out the modifying instruction byte code. - self.builder.emit(bc.clone()); - self.emit_asserts_after_bytecode(); - } - - // emit assumptions for invariants that were not assumed on entry and saves for types that are embedded - // in "old" in update invariants. - // When processing assumes before an opaque instruction, modified_invs contains no update invariants. - fn emit_assumes_and_saves_before_bytecode( - &mut self, - modified_invs: BTreeSet, - entrypoint_invariants: &BTreeSet, - ) { - // translate all the invariants. Some were already translated at the entrypoint, but - // that's ok because entrypoint invariants are global invariants that don't have "old", - // so redundant state tags are not going to be a problem. - let mut xlated_invs = self.translate_invariants(&modified_invs); - - let (global_invs, _update_invs) = self.separate_update_invariants(&modified_invs); - - // remove entrypoint invariants so we don't assume them again here. - let modified_assumes: BTreeSet = global_invs - .difference(entrypoint_invariants) - .cloned() - .collect(); - // assume the global invariants that weren't assumed at entrypoint - self.assert_or_assume_translated_invariants( - &xlated_invs.invariants, - &modified_assumes, - PropKind::Assume, - ); - // emit the instructions to save state in the state tags assigned in the previous step - self.emit_state_saves_for_update_invs(&mut xlated_invs); - // Save the translated invariants for use in asserts after instruction or opaque call end - if self.saved_from_before_instr_or_call.is_none() { - self.saved_from_before_instr_or_call = Some((xlated_invs, modified_invs)); - } else { - panic!("self.saved_from_pre should be None"); - } - } - - fn emit_asserts_after_bytecode(&mut self) { - // assert the global and update invariants that instruction modifies, regardless of where they - // were assumed - if let Some((xlated_invs, modified_invs)) = - std::mem::take(&mut self.saved_from_before_instr_or_call) - { - self.assert_or_assume_translated_invariants( - &xlated_invs.invariants, - &modified_invs, - PropKind::Assert, - ); - } else { - // This should never happen - panic!("saved_from_pre should be Some"); - } - } - - /// Given a set of invariants, return a pair of sets: global invariants and update invariants - fn separate_update_invariants( - &self, - invariants: &BTreeSet, - ) -> (BTreeSet, BTreeSet) { - let global_env = self.builder.fun_env.module_env.env; - let mut global_invs: BTreeSet = BTreeSet::new(); - let mut update_invs: BTreeSet = BTreeSet::new(); - for inv_id in invariants { - let inv = global_env.get_global_invariant(*inv_id).unwrap(); - if matches!(inv.kind, ConditionKind::GlobalInvariantUpdate(..)) { - update_invs.insert(*inv_id); - } else { - global_invs.insert(*inv_id); - } - } - (global_invs, update_invs) - } - - /// Returns the set of invariants modified by a function - fn get_invs_modified_by_fun( - &self, - inv_set: &BTreeSet, - fun_id: QualifiedId, - funs_that_modify_inv: &BTreeMap>>, - ) -> BTreeSet { - let mut modified_inv_set: BTreeSet = BTreeSet::new(); - for inv_id in inv_set { - if let Some(fun_id_set) = funs_that_modify_inv.get(inv_id) { - if fun_id_set.contains(&fun_id) { - modified_inv_set.insert(*inv_id); - } - } - } - modified_inv_set - } - - /// Update invariants contain "old" expressions, so it is necessary to save any types in the - /// state that appear in the old expressions. "update_invs" argument must contain only update - /// invariants (not checked). - fn emit_state_saves_for_update_invs(&mut self, xlated_spec: &mut TranslatedSpec) { - // Emit all necessary state saves - self.builder - .set_next_debug_comment("state save for global update invariants".to_string()); - for (mem, label) in std::mem::take(&mut xlated_spec.saved_memory) { - self.builder - .emit_with(|id| Bytecode::SaveMem(id, label, mem)); - } - for (var, label) in std::mem::take(&mut xlated_spec.saved_spec_vars) { - self.builder - .emit_with(|id| Bytecode::SaveSpecVar(id, label, var)); - } - self.builder.clear_next_debug_comment(); - } - - /// emit asserts or assumes (depending on prop_kind argument) for the invariants in - /// xlated_invariants that is also in inv_set at the current location, - fn assert_or_assume_translated_invariants( - &mut self, - xlated_invariants: &[(Loc, GlobalId, Exp)], - inv_set: &BTreeSet, - prop_kind: PropKind, - ) { - let global_env = self.builder.global_env(); - for (loc, mid, cond) in xlated_invariants { - if inv_set.contains(mid) { - // Check for hard-to-debug coding error (this is not a user error) - if inv_set.contains(mid) - && matches!(prop_kind, PropKind::Assume) - && matches!( - global_env.get_global_invariant(*mid).unwrap().kind, - ConditionKind::GlobalInvariantUpdate(..) - ) - { - panic!("Not allowed to assume update invariant"); - } - self.emit_invariant(loc, cond, prop_kind); - } - } - } - - /// Emit an assert or assume for one invariant, give location and expression for the property - fn emit_invariant(&mut self, loc: &Loc, cond: &Exp, prop_kind: PropKind) { - self.builder.set_next_debug_comment(format!( - "global invariant {}", - loc.display(self.builder.global_env()) - )); - // No error messages on assumes - if prop_kind == PropKind::Assert { - self.builder - .set_loc_and_vc_info(loc.clone(), GLOBAL_INVARIANT_FAILS_MESSAGE); - } - self.builder - .emit_with(|id| Bytecode::Prop(id, prop_kind, cond.clone())); - } - - /// Translate the given set of invariants. This will care for instantiating the - /// invariants in the function context. - fn translate_invariants(&mut self, invs: &BTreeSet) -> TranslatedSpec { - let inst_invs = self.compute_instances_for_invariants(invs); - SpecTranslator::translate_invariants_by_id( - self.options.auto_trace_level.invariants(), - &mut self.builder, - inst_invs.into_iter(), - ) - } - - /// Compute the instantiations which need to be verified for each invariant in the input. - /// This may filter out certain invariants which do not have a valid instantiation. - fn compute_instances_for_invariants( - &self, - invs: &BTreeSet, - ) -> Vec<(GlobalId, Vec)> { - invs.iter() - .flat_map(|id| { - let inv = self.builder.global_env().get_global_invariant(*id).unwrap(); - self.compute_invariant_instances(inv).into_iter() - }) - .collect() - } - - /// Compute the instantiations for the given invariant, by comparing the memory accessed - /// by the invariant with that of the enclosing function. - fn compute_invariant_instances( - &self, - inv: &GlobalInvariant, - ) -> BTreeSet<(GlobalId, Vec)> { - // Determine the type arity of this invariant. If it is 0, we shortcut with just - // returning a single empty instance. - let arity = match &inv.kind { - ConditionKind::GlobalInvariant(ps) | ConditionKind::GlobalInvariantUpdate(ps) => { - ps.len() as u16 - }, - _ => 0, - }; - if arity == 0 { - return vec![(inv.id, vec![])].into_iter().collect(); - } - - // Holds possible instantiations per type parameter - let mut per_type_param_insts = BTreeMap::new(); - - // Pairwise unify memory used by the invariant against memory in the function. - // Notice that the function memory is already instantiated for the function variant - // we are instrumenting. - for inv_mem in &inv.mem_usage { - for fun_mem in &self.used_memory { - let adapter = TypeUnificationAdapter::new_vec( - &fun_mem.inst, - &inv_mem.inst, - /* treat_lhs_type_param_as_var */ false, - /* treat_rhs_type_local_as_var */ true, - ); - #[cfg(invariant_trace)] - println!( - "{} =?= {} for inv {}", - self.builder.global_env().display(fun_mem), - self.builder.global_env().display(inv_mem), - inv.loc.display(self.builder.global_env()) - ); - let rel = adapter.unify( - &mut NoUnificationContext, - Variance::SpecVariance, - /* shallow_subst */ false, - ); - match rel { - None => continue, - Some((_, subst_rhs)) => { - #[cfg(invariant_trace)] - println!("unifies {:?}", subst_rhs); - for (k, v) in subst_rhs { - per_type_param_insts - .entry(k) - .or_insert_with(BTreeSet::new) - .insert(v); - } - }, - } - } - } - - // Check whether all type parameters have at least one instantiation. If not, this - // invariant is not applicable (this corresponds to an unbound TypeLocal in the older - // translation scheme). - // TODO: we should generate a type check error if an invariant has unused, dead - // type parameters because such an invariant can never pass this test. - let mut all_insts = BTreeSet::new(); - if (0..arity).collect::>() == per_type_param_insts.keys().cloned().collect() { - // Compute the cartesian product of all individual type parameter instantiations. - for inst in per_type_param_insts - .values() - .map(|tys| tys.iter().cloned()) - .multi_cartesian_product() - { - all_insts.insert((inv.id, inst)); - } - } - all_insts - } -} diff --git a/third_party/move/move-prover/bytecode-pipeline/src/lib.rs b/third_party/move/move-prover/bytecode-pipeline/src/lib.rs index f8d8d9ad95e08..d80434244951d 100644 --- a/third_party/move/move-prover/bytecode-pipeline/src/lib.rs +++ b/third_party/move/move-prover/bytecode-pipeline/src/lib.rs @@ -6,7 +6,6 @@ pub mod data_invariant_instrumentation; pub mod eliminate_imm_refs; pub mod global_invariant_analysis; pub mod global_invariant_instrumentation; -pub mod global_invariant_instrumentation_v2; pub mod inconsistency_check; pub mod loop_analysis; pub mod memory_instrumentation; @@ -20,5 +19,4 @@ pub mod packed_types_analysis; pub mod pipeline_factory; pub mod spec_instrumentation; pub mod verification_analysis; -pub mod verification_analysis_v2; pub mod well_formed_instrumentation; diff --git a/third_party/move/move-prover/bytecode-pipeline/src/verification_analysis_v2.rs b/third_party/move/move-prover/bytecode-pipeline/src/verification_analysis_v2.rs deleted file mode 100644 index 5808200509499..0000000000000 --- a/third_party/move/move-prover/bytecode-pipeline/src/verification_analysis_v2.rs +++ /dev/null @@ -1,800 +0,0 @@ -// Copyright (c) The Diem Core Contributors -// Copyright (c) The Move Contributors -// SPDX-License-Identifier: Apache-2.0 - -//! Analysis which computes an annotation for each function whether - -use crate::options::ProverOptions; -use itertools::Itertools; -use log::debug; -use move_model::{ - model::{FunId, FunctionEnv, GlobalEnv, GlobalId, ModuleEnv, QualifiedId, VerificationScope}, - pragmas::{ - CONDITION_SUSPENDABLE_PROP, DELEGATE_INVARIANTS_TO_CALLER_PRAGMA, - DISABLE_INVARIANTS_IN_BODY_PRAGMA, VERIFY_PRAGMA, - }, -}; -use move_stackless_bytecode::{ - dataflow_domains::SetDomain, - function_target::{FunctionData, FunctionTarget}, - function_target_pipeline::{FunctionTargetProcessor, FunctionTargetsHolder, FunctionVariant}, - usage_analysis, COMPILED_MODULE_AVAILABLE, -}; -use std::collections::{BTreeMap, BTreeSet, VecDeque}; - -/// The annotation for information about verification. -#[derive(Clone, Default)] -pub struct VerificationInfoV2 { - /// Whether the function is target of verification. - pub verified: bool, - /// Whether the function needs to have an inlined variant since it is called from a verified - /// function and is not opaque. - pub inlined: bool, -} - -/// Get verification information for this function. -pub fn get_info(target: &FunctionTarget<'_>) -> VerificationInfoV2 { - target - .get_annotations() - .get::() - .cloned() - .unwrap_or_default() -} - -// Analysis info to save for global_invariant_instrumentation phase -pub struct InvariantAnalysisData { - /// The set of all functions in target module. - pub target_fun_ids: BTreeSet>, - /// Functions in dependent modules that are transitively called by functions in target module. - pub dep_fun_ids: BTreeSet>, - /// functions where invariants are disabled by pragma disable_invariants_in_body - pub disabled_inv_fun_set: BTreeSet>, - /// Functions where invariants are disabled in a transitive caller, or by - /// pragma delegate_invariant_to_caller - pub non_inv_fun_set: BTreeSet>, - /// global and update invariants in the target module - pub target_invariants: BTreeSet, - /// Maps invariant ID to set of functions that modify the invariant - /// Does not include update invariants - pub funs_that_modify_inv: BTreeMap>>, - /// Maps function to the set of invariants that it modifies - /// Does not include update invariants - pub invs_modified_by_fun: BTreeMap, BTreeSet>, - /// Functions that modify some invariant in the target - /// Does not include update invariants - pub funs_that_modify_some_inv: BTreeSet>, - /// functions that are in non_inv_fun_set and `M[I]` for some `I`. - /// We have to verify the callers, which may be in friend modules. - pub funs_that_delegate_to_caller: BTreeSet>, - /// Functions that are not in target or deps, but that call a function - /// in non_inv_fun_set that modifies some invariant from target module - /// and eventually calls a function in target mod or a dependency. - pub friend_fun_ids: BTreeSet>, - /// For each function, give the set of invariants that are disabled in that function. - /// This is defined as the least set satisfying set inequalities: (1) in a function where - /// invariants are disabled, it is the set of invariants modified in the function, and - /// (2) in a function in non_inv_fun_set, it is the least set that includes all disabled_invs - /// for calling functions. - pub disabled_invs_for_fun: BTreeMap, BTreeSet>, -} - -/// Get all invariants from target modules -fn get_target_invariants( - global_env: &GlobalEnv, - target_modules: &[ModuleEnv], -) -> BTreeSet { - let target_mod_ids = target_modules - .iter() - .map(|mod_env| mod_env.get_id()) - .flat_map(|target_mod_id| global_env.get_global_invariants_by_module(target_mod_id)) - .collect(); - target_mod_ids -} - -/// Computes and returns the set of disabled invariants for each function in disabled_inv_fun_set -/// Disabled invariants for a function are the invariants modified (directly or indirectly) by the fun -/// that are also declared to be suspendable via "invariant [suspendable] ..." -fn compute_disabled_invs_for_fun( - global_env: &GlobalEnv, - disabled_inv_fun_set: &BTreeSet>, - invs_modified_by_fun: &BTreeMap, BTreeSet>, -) -> BTreeMap, BTreeSet> { - let mut disabled_invs_for_fun: BTreeMap, BTreeSet> = - BTreeMap::new(); - for module_env in global_env.get_modules() { - for fun_env in module_env.get_functions() { - let fun_id = fun_env.get_qualified_id(); - // If function disables invariants, get the set of invariants modified in the function - // and keep only those that are declared to be suspendable - if disabled_inv_fun_set.contains(&fun_id) { - if let Some(modified_invs) = invs_modified_by_fun.get(&fun_id) { - let disabled_invs: BTreeSet = modified_invs - .iter() - .filter(|inv_id| { - global_env - .is_property_true( - &global_env - .get_global_invariant(**inv_id) - .unwrap() - .properties, - CONDITION_SUSPENDABLE_PROP, - ) - .unwrap_or(false) - }) - .cloned() - .collect(); - debug_print_inv_set( - global_env, - &disabled_invs, - "$$$$$$$$$$$$$$$$\ncompute_disabled_invs_for_fun", - ); - disabled_invs_for_fun.insert(fun_id, disabled_invs.clone()); - } - } - } - } - - // Compute a least fixed point of disable_invs_for_fun. Starts with disabled inv functions and - // all invariants that they modify. Then propagate those to called functions. They're not top-sorted - // (which may not be good enough for recursion, in this case, I'm not sure). So fun_ids go back - // into the worklist until the disable_inv_set for each fun converges (worklist will be empty). - let mut worklist: VecDeque> = disabled_inv_fun_set.iter().cloned().collect(); - while let Some(caller_fun_id) = worklist.pop_front() { - // If None, it's ok to skip because there are no disabled_invs to propagate to called funs - if let Some(disabled_invs_for_caller) = disabled_invs_for_fun.remove(&caller_fun_id) { - let called_funs = global_env - .get_function(caller_fun_id) - .get_called_functions() - .cloned() - .expect(COMPILED_MODULE_AVAILABLE); - for called_fun_id in called_funs { - let disabled_invs_for_called = - disabled_invs_for_fun.entry(called_fun_id).or_default(); - // if caller has any disabled_invs that callee does not, add them to called - // and add called to the worklist for further processing - if !disabled_invs_for_caller.is_subset(disabled_invs_for_called) { - // Add missing inv_ids to called set - for inv_id in &disabled_invs_for_caller { - disabled_invs_for_called.insert(*inv_id); - } - worklist.push_back(called_fun_id); - } - } - // put back disabled_invs_for_caller - disabled_invs_for_fun.insert(caller_fun_id, disabled_invs_for_caller); - } - } - disabled_invs_for_fun -} - -/// Check whether function is callable from unknown sites (i.e., it is public or -/// a script fun) and modifies some invariant in the target module. -/// The second condition is an exception for functions that cannot invalidate -/// any invariants. -fn check_legal_disabled_invariants( - fun_env: &FunctionEnv, - disabled_inv_fun_set: &BTreeSet>, - non_inv_fun_set: &BTreeSet>, - funs_that_modify_some_inv: &BTreeSet>, -) { - let global_env = fun_env.module_env.env; - let fun_id = fun_env.get_qualified_id(); - if non_inv_fun_set.contains(&fun_id) && funs_that_modify_some_inv.contains(&fun_id) { - if disabled_inv_fun_set.contains(&fun_id) { - global_env.error( - &fun_env.get_loc(), - "Functions must not have a disable invariant pragma when invariants are \ - disabled in a transitive caller or there is a \ - pragma delegate_invariants_to_caller", - ); - } else if fun_env.has_unknown_callers() { - if is_fun_delegating(fun_env) { - global_env.error( - &fun_env.get_loc(), - "Public or script functions cannot delegate invariants", - ) - } else { - global_env.error_with_notes( - &fun_env.get_loc(), - "Public or script functions cannot be transitively called by \ - functions disabling or delegating invariants", - compute_non_inv_cause_chain(fun_env), - ) - } - } - } -} - -/// Compute the chain of calls which leads to an implicit non-inv function. -fn compute_non_inv_cause_chain(fun_env: &FunctionEnv<'_>) -> Vec { - let global_env = fun_env.module_env.env; - let mut worklist: BTreeSet>> = fun_env - .get_calling_functions() - .expect(COMPILED_MODULE_AVAILABLE) - .into_iter() - .map(|id| vec![id]) - .collect(); - let mut done = BTreeSet::new(); - let mut result = vec![]; - while let Some(caller_list) = worklist.iter().next().cloned() { - worklist.remove(&caller_list); - let caller_id = *caller_list.iter().last().unwrap(); - done.insert(caller_id); - let caller_env = global_env.get_function_qid(caller_id); - let display_chain = || { - vec![fun_env.get_qualified_id()] - .into_iter() - .chain(caller_list.iter().cloned()) - .map(|id| global_env.get_function_qid(id).get_full_name_str()) - .join(" <- ") - }; - if is_fun_disabled(&caller_env) { - result.push(format!("disabled by {}", display_chain())); - } else if is_fun_delegating(&caller_env) { - result.push(format!("delegated by {}", display_chain())); - } else { - worklist.extend( - caller_env - .get_calling_functions() - .expect(COMPILED_MODULE_AVAILABLE) - .into_iter() - .filter_map(|id| { - if done.contains(&id) { - None - } else { - let mut new_caller_list = caller_list.clone(); - new_caller_list.push(id); - Some(new_caller_list) - } - }), - ); - } - } - if result.is_empty() { - result.push("cannot determine disabling reason (bug?)".to_owned()) - } - result -} - -// Using pragmas, find functions called from a context where invariant -// checking is disabled. -// disabled_inv_fun set are disabled by pragma -// non_inv_fun_set are disabled by pragma or because they're called from -// another function in disabled_inv_fun_set or non_inv_fun_set. -fn compute_disabled_and_non_inv_fun_sets( - global_env: &GlobalEnv, -) -> (BTreeSet>, BTreeSet>) { - let mut non_inv_fun_set: BTreeSet> = BTreeSet::new(); - let mut disabled_inv_fun_set: BTreeSet> = BTreeSet::new(); - // invariant: If a function is in non_inv_fun_set and not in worklist, - // then all the functions it calls are also in fun_set - // or in worklist. When worklist is empty, all callees of a function - // in non_inv_fun_set will also be in non_inv_fun_set. - // Each function is added at most once to the worklist. - let mut worklist = vec![]; - for module_env in global_env.get_modules() { - for fun_env in module_env.get_functions() { - if is_fun_disabled(&fun_env) { - let fun_id = fun_env.get_qualified_id(); - disabled_inv_fun_set.insert(fun_id); - worklist.push(fun_id); - } - if is_fun_delegating(&fun_env) { - let fun_id = fun_env.get_qualified_id(); - if non_inv_fun_set.insert(fun_id) { - // Add to work_list only if fun_id is not in non_inv_fun_set (may have inferred - // this from a caller already). - worklist.push(fun_id); - } - } - // Downward closure of non_inv_fun_set - while let Some(called_fun_id) = worklist.pop() { - let called_funs = global_env - .get_function(called_fun_id) - .get_called_functions() - .cloned() - .expect(COMPILED_MODULE_AVAILABLE); - for called_fun_id in called_funs { - if non_inv_fun_set.insert(called_fun_id) { - // Add to work_list only if fun_id is not in fun_set - worklist.push(called_fun_id); - } - } - } - } - } - (disabled_inv_fun_set, non_inv_fun_set) -} - -fn is_fun_disabled(fun_env: &FunctionEnv<'_>) -> bool { - fun_env.is_pragma_true(DISABLE_INVARIANTS_IN_BODY_PRAGMA, || false) -} - -fn is_fun_delegating(fun_env: &FunctionEnv<'_>) -> bool { - fun_env.is_pragma_true(DELEGATE_INVARIANTS_TO_CALLER_PRAGMA, || false) -} - -/// Collect all functions that are defined in the target module, or called transitively -/// from those functions. -/// TODO: This is not very efficient. It would be better to compute the transitive closure. -fn compute_dep_fun_ids( - global_env: &GlobalEnv, - target_modules: &[ModuleEnv], -) -> BTreeSet> { - let mut dep_fun_ids = BTreeSet::new(); - for module_env in global_env.get_modules() { - for target_env in target_modules { - if target_env.is_transitive_dependency(module_env.get_id()) { - for fun_env in module_env.get_functions() { - dep_fun_ids.insert(fun_env.get_qualified_id()); - } - } - } - } - dep_fun_ids -} - -/// Compute a map from each invariant to the set of functions that modify state -/// appearing in the invariant. Return that, and a second value that is the union -/// of functions over all invariants in the first map. -/// This is not applied to update invariants? -fn compute_funs_that_modify_inv( - global_env: &GlobalEnv, - target_invariants: &BTreeSet, - targets: &mut FunctionTargetsHolder, - variant: FunctionVariant, -) -> ( - BTreeMap>>, - BTreeMap, BTreeSet>, - BTreeSet>, -) { - let mut funs_that_modify_inv: BTreeMap>> = - BTreeMap::new(); - let mut funs_that_modify_some_inv: BTreeSet> = BTreeSet::new(); - let mut invs_modified_by_fun: BTreeMap, BTreeSet> = - BTreeMap::new(); - for inv_id in target_invariants { - // Collect the global state used by inv_id (this is computed in usage_analysis.rs) - let inv_mem_use: SetDomain<_> = global_env - .get_global_invariant(*inv_id) - .unwrap() - .mem_usage - .iter() - .cloned() - .collect(); - // set of functions that modify state in inv_id that we are building - let mut fun_id_set: BTreeSet> = BTreeSet::new(); - // Iterate over all functions in the module cluster - for module_env in global_env.get_modules() { - for fun_env in module_env.get_functions() { - // Get all memory modified by this function. - let fun_target = targets.get_target(&fun_env, &variant); - let modified_memory = &usage_analysis::get_memory_usage(&fun_target).modified.all; - // Add functions to set if it modifies mem used in invariant - // TODO: This should be using unification. - if !modified_memory.is_disjoint(&inv_mem_use) { - let fun_id = fun_env.get_qualified_id(); - fun_id_set.insert(fun_id); - funs_that_modify_some_inv.insert(fun_id); - let inv_set = invs_modified_by_fun.entry(fun_id).or_default(); - inv_set.insert(*inv_id); - } - } - } - if !fun_id_set.is_empty() { - funs_that_modify_inv.insert(*inv_id, fun_id_set); - } - } - ( - funs_that_modify_inv, - invs_modified_by_fun, - funs_that_modify_some_inv, - ) -} - -/// Compute the set of functions that are friend modules of target or deps, but not in -/// target or deps, and that call a function in non_inv_fun_set that modifies some target -/// invariant. The Prover needs to verify that these functions preserve the target invariants. -fn compute_friend_fun_ids( - global_env: &GlobalEnv, - target_fun_ids: &BTreeSet>, - dep_fun_ids: &BTreeSet>, - funs_that_delegate_to_caller: &BTreeSet>, -) -> BTreeSet> { - let mut friend_fun_set: BTreeSet> = BTreeSet::new(); - let mut worklist: Vec> = target_fun_ids.iter().cloned().collect(); - worklist.extend(dep_fun_ids.iter().cloned()); - while let Some(fun_id) = worklist.pop() { - // Check for legacy friend pragma - // TODO: Delete when we stop using pragma friend in DiemFramework - let fun_env = global_env.get_function(fun_id); - let friend_env = fun_env.get_transitive_friend(); - let friend_id = friend_env.get_qualified_id(); - // if no transitive friend, it just returns the original fun_env - if friend_id != fun_env.get_qualified_id() && friend_fun_set.insert(friend_id) { - worklist.push(friend_id); - } - if funs_that_delegate_to_caller.contains(&fun_id) { - let callers = fun_env - .get_calling_functions() - .expect(COMPILED_MODULE_AVAILABLE); - for caller_fun_id in callers { - // Exclude callers that are in target or dep modules, because we will verify them, anyway. - // We also don't need to put them in the worklist, because they were in there initially. - // Also, don't need to process if it's already in friend_fun_set - if !target_fun_ids.contains(&caller_fun_id) - && !dep_fun_ids.contains(&caller_fun_id) - && friend_fun_set.insert(caller_fun_id) - { - worklist.push(caller_fun_id); - } - } - } - } - friend_fun_set -} - -#[allow(dead_code)] -/// Debug print: Print global id and body of each invariant, so we can just print the global -/// id's in sets for compactness -fn debug_print_global_ids(global_env: &GlobalEnv, global_ids: &BTreeSet) { - for inv_id in global_ids { - debug_print_inv_full(global_env, inv_id); - } -} - -/// Debugging function to print a set of function id's using their -/// symbolic function names. -#[allow(dead_code)] -fn debug_print_fun_id_set( - global_env: &GlobalEnv, - fun_ids: &BTreeSet>, - set_name: &str, -) { - debug!( - "****************\n{}: {:?}", - set_name, - fun_ids - .iter() - .map(|fun_id| global_env.get_function(*fun_id).get_name_string()) - .collect::>() - ); -} - -/// Debugging code to print sets of invariants -#[allow(dead_code)] -pub fn debug_print_inv_set( - global_env: &GlobalEnv, - global_ids: &BTreeSet, - set_name: &str, -) { - if global_ids.is_empty() { - return; - } - debug!("{}:", set_name); - // for global_id in global_ids { - // debug!("global_id: {:?}", *global_id); - // } - debug!("++++++++++++++++\n{}:", set_name); - for inv_id in global_ids { - debug_print_inv_full(global_env, inv_id); - } -} - -/// Given global id of invariant, prints the global ID and the source code -/// of the invariant -#[allow(dead_code)] -fn debug_print_inv_full(global_env: &GlobalEnv, inv_id: &GlobalId) { - let inv = global_env.get_global_invariant(*inv_id); - let loc = &inv.unwrap().loc; - debug!( - "{:?} {:?}: {}", - *inv_id, - inv.unwrap().kind, - global_env.get_source(loc).unwrap(), - ); -} - -#[allow(dead_code)] -fn debug_print_fun_inv_map( - global_env: &GlobalEnv, - fun_inv_map: &BTreeMap, BTreeSet>, - map_name: &str, -) { - debug!("****************\nMAP NAME {}:", map_name); - for (fun_id, inv_id_set) in fun_inv_map.iter() { - let fname = global_env.get_function(*fun_id).get_name_string(); - debug!("FUNCTION {}:", fname); - for inv_id in inv_id_set { - debug_print_inv_full(global_env, inv_id); - } - // debug_print_inv_set(global_env, inv_id_set, &fname); - } -} - -// global_env.get_function(*fun_id).get_name_string(); - -/// Print sets and maps computed during verification analysis -#[allow(dead_code)] -fn debug_print_invariant_analysis_data( - global_env: &GlobalEnv, - inv_ana_data: &InvariantAnalysisData, -) { - debug_print_fun_id_set(global_env, &inv_ana_data.target_fun_ids, "target_fun_ids"); - debug_print_fun_id_set(global_env, &inv_ana_data.dep_fun_ids, "dep_fun_ids"); - debug_print_fun_id_set( - global_env, - &inv_ana_data.disabled_inv_fun_set, - "disabled_inv_fun_set", - ); - debug_print_fun_id_set(global_env, &inv_ana_data.non_inv_fun_set, "non_inv_fun_set"); - debug_print_inv_set( - global_env, - &inv_ana_data.target_invariants, - "target_invariants", - ); - - // "funs_modified_by_inv" map - - debug_print_fun_inv_map( - global_env, - &inv_ana_data.invs_modified_by_fun, - "invs_modified_by_fun", - ); - - debug_print_fun_id_set( - global_env, - &inv_ana_data.funs_that_modify_some_inv, - "funs_that_modify_some_inv", - ); - debug_print_fun_id_set( - global_env, - &inv_ana_data.funs_that_delegate_to_caller, - "funs_that_delegate_to_caller", - ); - debug_print_fun_id_set(global_env, &inv_ana_data.friend_fun_ids, "friend_fun_ids"); - - debug_print_fun_inv_map( - global_env, - &inv_ana_data.disabled_invs_for_fun, - "disabled_invs_for_fun", - ); -} - -pub struct VerificationAnalysisProcessorV2(); - -impl VerificationAnalysisProcessorV2 { - pub fn new() -> Box { - Box::new(Self()) - } -} - -impl FunctionTargetProcessor for VerificationAnalysisProcessorV2 { - fn process( - &self, - targets: &mut FunctionTargetsHolder, - fun_env: &FunctionEnv, - data: FunctionData, - _scc_opt: Option<&[FunctionEnv]>, - ) -> FunctionData { - let global_env = fun_env.module_env.env; - let fun_id = fun_env.get_qualified_id(); - let variant = data.variant.clone(); - // When this is called, the data of this function is removed from targets so it can - // be mutated, as per pipeline processor design. We put it back temporarily to have - // a unique model of targets. - targets.insert_target_data(&fun_id, variant.clone(), data); - let inv_ana_data = global_env.get_extension::().unwrap(); - let target_fun_ids = &inv_ana_data.target_fun_ids; - let dep_fun_ids = &inv_ana_data.dep_fun_ids; - let friend_fun_ids = &inv_ana_data.friend_fun_ids; - let funs_that_modify_some_inv = &inv_ana_data.funs_that_modify_some_inv; - // Logic to decide whether to verify this function - // Never verify if "pragma verify = false;" - if fun_env.is_pragma_true(VERIFY_PRAGMA, || true) { - let is_in_target_mod = target_fun_ids.contains(&fun_id); - let is_in_deps_and_modifies_inv = - dep_fun_ids.contains(&fun_id) && funs_that_modify_some_inv.contains(&fun_id); - let is_in_friends = friend_fun_ids.contains(&fun_id); - let is_normally_verified = - is_in_target_mod || is_in_deps_and_modifies_inv || is_in_friends; - let options = ProverOptions::get(global_env); - let is_verified = match &options.verify_scope { - VerificationScope::Public => { - (is_in_target_mod && fun_env.is_exposed()) - || is_in_deps_and_modifies_inv - || is_in_friends - }, - VerificationScope::All => is_normally_verified, - VerificationScope::Only(function_name) => { - fun_env.matches_name(function_name) && is_in_target_mod - }, - VerificationScope::OnlyModule(module_name) => { - is_in_target_mod && fun_env.module_env.matches_name(module_name) - }, - VerificationScope::None => false, - }; - if is_verified { - debug!("marking `{}` to be verified", fun_env.get_full_name_str()); - mark_verified(fun_env, variant.clone(), targets); - } - } - - targets.remove_target_data(&fun_id, &variant) - } - - fn name(&self) -> String { - "verification_analysis_v2".to_string() - } - - fn initialize(&self, global_env: &GlobalEnv, targets: &mut FunctionTargetsHolder) { - let options = ProverOptions::get(global_env); - - // If we are verifying only one function or module, check that this indeed exists. - match &options.verify_scope { - VerificationScope::Only(name) | VerificationScope::OnlyModule(name) => { - let for_module = matches!(&options.verify_scope, VerificationScope::OnlyModule(_)); - let mut target_exists = false; - for module in global_env.get_modules() { - if module.is_target() { - if for_module { - target_exists = module.matches_name(name) - } else { - target_exists = module.get_functions().any(|f| f.matches_name(name)); - } - if target_exists { - break; - } - } - } - if !target_exists { - global_env.error( - &global_env.unknown_loc(), - &format!( - "{} target {} does not exist in target modules", - if for_module { "module" } else { "function" }, - name - ), - ) - } - }, - _ => {}, - } - - let target_modules = global_env.get_primary_target_modules(); - let target_fun_ids: BTreeSet> = target_modules - .iter() - .flat_map(|mod_env| mod_env.get_functions()) - .map(|fun| fun.get_qualified_id()) - .collect(); - let dep_fun_ids = compute_dep_fun_ids(global_env, &target_modules); - let (disabled_inv_fun_set, non_inv_fun_set) = - compute_disabled_and_non_inv_fun_sets(global_env); - let target_invariants = get_target_invariants(global_env, &target_modules); - let (funs_that_modify_inv, invs_modified_by_fun, funs_that_modify_some_inv) = - compute_funs_that_modify_inv( - global_env, - &target_invariants, - targets, - FunctionVariant::Baseline, - ); - let funs_that_delegate_to_caller = non_inv_fun_set - .intersection(&funs_that_modify_some_inv) - .cloned() - .collect(); - let friend_fun_ids = compute_friend_fun_ids( - global_env, - &target_fun_ids, - &dep_fun_ids, - &funs_that_delegate_to_caller, - ); - let disabled_invs_for_fun = - compute_disabled_invs_for_fun(global_env, &disabled_inv_fun_set, &invs_modified_by_fun); - - // Check for public or script functions that are in non_inv_fun_set - for module_env in global_env.get_modules() { - for fun_env in module_env.get_functions() { - check_legal_disabled_invariants( - &fun_env, - &disabled_inv_fun_set, - &non_inv_fun_set, - &funs_that_modify_some_inv, - ); - } - } - let inv_ana_data = InvariantAnalysisData { - target_fun_ids, - dep_fun_ids, - disabled_inv_fun_set, - non_inv_fun_set, - target_invariants, - funs_that_modify_inv, - invs_modified_by_fun, - funs_that_modify_some_inv, - funs_that_delegate_to_caller, - friend_fun_ids, - disabled_invs_for_fun, - }; - - // Note: To print verbose debugging info, use - debug_print_invariant_analysis_data(global_env, &inv_ana_data); - - global_env.set_extension(inv_ana_data); - } -} - -/// Mark this function as being verified. If it has a friend and is verified only in the -/// friends context, mark the friend instead. This also marks all functions directly or -/// indirectly called by this function as inlined if they are not opaque. -fn mark_verified( - fun_env: &FunctionEnv<'_>, - variant: FunctionVariant, - targets: &mut FunctionTargetsHolder, -) { - let actual_env = fun_env.get_transitive_friend(); - if actual_env.get_qualified_id() != fun_env.get_qualified_id() { - // Instead of verifying this function directly, we mark the friend as being verified, - // and this function as inlined. - mark_inlined(fun_env, variant.clone(), targets); - } - // The user can override with `pragma verify = false`, so respect this. - let options = ProverOptions::get(fun_env.module_env.env); - if !actual_env.is_explicitly_not_verified(&options.verify_scope) { - let info = targets - .get_data_mut(&actual_env.get_qualified_id(), &variant) - .expect("function data available") - .annotations - .get_or_default_mut::(true); - if !info.verified { - info.verified = true; - mark_callees_inlined(&actual_env, variant, targets); - } - } -} - -/// Mark this function as inlined if it is not opaque, and if it is -/// are called from a verified function via a chain of zero-or-more -/// inline functions. If it is not called from a verified function, -/// it does not need to be inlined. -fn mark_inlined( - fun_env: &FunctionEnv<'_>, - variant: FunctionVariant, - targets: &mut FunctionTargetsHolder, -) { - if fun_env.is_native() || fun_env.is_intrinsic() { - return; - } - debug_assert!( - targets.get_target_variants(fun_env).contains(&variant), - "`{}` has variant `{:?}`", - fun_env.get_name().display(fun_env.symbol_pool()), - variant - ); - let data = targets - .get_data_mut(&fun_env.get_qualified_id(), &variant) - .expect("function data defined"); - let info = data - .annotations - .get_or_default_mut::(true); - if !info.inlined { - info.inlined = true; - mark_callees_inlined(fun_env, variant, targets); - } -} - -/// Continue transitively marking callees as inlined. -fn mark_callees_inlined( - fun_env: &FunctionEnv<'_>, - variant: FunctionVariant, - targets: &mut FunctionTargetsHolder, -) { - for callee in fun_env - .get_called_functions() - .expect(COMPILED_MODULE_AVAILABLE) - { - let callee_env = fun_env.module_env.env.get_function(*callee); - if !callee_env.is_opaque() { - mark_inlined(&callee_env, variant.clone(), targets); - } - } -} diff --git a/third_party/move/move-prover/lab/Cargo.toml b/third_party/move/move-prover/lab/Cargo.toml index 5ebf0e18075a0..dc90304f53b02 100644 --- a/third_party/move/move-prover/lab/Cargo.toml +++ b/third_party/move/move-prover/lab/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "prover-lab" +name = "move-prover-lab" version = "0.1.0" authors = ["Diem Association "] publish = false @@ -12,13 +12,9 @@ chrono = { workspace = true } clap = { workspace = true, features = ["derive"] } codespan-reporting = { workspace = true } itertools = { workspace = true } -log = { workspace = true, features = ["serde"] } -move-compiler = { workspace = true } -move-compiler-v2 = { workspace = true } move-model = { workspace = true } move-prover = { workspace = true } move-prover-boogie-backend = { workspace = true } move-prover-bytecode-pipeline = { workspace = true } plotters = { workspace = true, features = ["evcxr", "line_series", "histogram"] } z3tracer = { workspace = true } - diff --git a/third_party/move/move-prover/lab/src/benchmark.rs b/third_party/move/move-prover/lab/src/benchmark.rs index b05b6515083a4..edc750c34ef2d 100644 --- a/third_party/move/move-prover/lab/src/benchmark.rs +++ b/third_party/move/move-prover/lab/src/benchmark.rs @@ -13,13 +13,7 @@ use clap::{ }; use codespan_reporting::term::termcolor::{ColorChoice, StandardStream}; use itertools::Itertools; -use log::LevelFilter; -use move_compiler::shared::{known_attributes::KnownAttribute, PackagePaths}; -use move_compiler_v2::{env_pipeline::rewrite_target::RewritingScope, Experiment}; -use move_model::{ - model::{FunctionEnv, GlobalEnv, ModuleEnv, VerificationScope}, - parse_addresses_from_options, run_model_builder_with_options, -}; +use move_model::model::{FunctionEnv, GlobalEnv, ModuleEnv, VerificationScope}; use move_prover::{ check_errors, cli::Options, create_and_process_bytecode, create_init_num_operation_state, generate_boogie, verify_boogie, @@ -149,27 +143,9 @@ fn run_benchmark( } else { Options::default() }; - let addrs = parse_addresses_from_options(options.move_named_address_values.clone())?; + options.move_sources.append(&mut modules.to_vec()); options.move_deps.append(&mut dep_dirs.to_vec()); - let skip_attribute_checks = true; - let known_attributes = KnownAttribute::get_all_attribute_names().clone(); - let mut env = run_model_builder_with_options( - vec![PackagePaths { - name: None, - paths: modules.to_vec(), - named_address_map: addrs.clone(), - }], - vec![], - vec![PackagePaths { - name: None, - paths: options.move_deps.clone(), - named_address_map: addrs, - }], - options.model_builder.clone(), - skip_attribute_checks, - &known_attributes, - )?; - let mut error_writer = StandardStream::stderr(ColorChoice::Auto); + options.skip_attribute_checks = true; if use_aptos_natives { options.backend.custom_natives = @@ -184,14 +160,16 @@ fn run_benchmark( // Do not allow any benchmark to run longer than 60s. If this is exceeded it usually // indicates a bug in boogie or the solver, because we already propagate soft timeouts, but // they are ignored. - options.backend.hard_timeout_secs = 400; + options.backend.hard_timeout_secs = 60; options.backend.global_timeout_overwrite = false; - options.backend.vc_timeout = 300; - - options.verbosity_level = LevelFilter::Warn; + options.backend.vc_timeout = 400; + options.set_quiet(); options.backend.proc_cores = 1; options.backend.derive_options(); options.setup_logging(); + + let mut error_writer = StandardStream::stderr(ColorChoice::Auto); + let env = move_prover::create_move_prover_v2_model(&mut error_writer, options.clone())?; check_errors(&env, &options, &mut error_writer, "unexpected build errors")?; let config_descr = if let Some(config) = config_file_opt { @@ -216,17 +194,6 @@ fn run_benchmark( Notice that execution is slow because we enforce single core execution.", config_descr ); - // Need to run the pipeline to - let compiler_options = move_compiler_v2::Options::default() - .set_experiment(Experiment::OPTIMIZE, false) - .set_experiment(Experiment::SPEC_REWRITE, true); - env.set_extension(compiler_options.clone()); - let pipeline = move_compiler_v2::check_and_rewrite_pipeline( - &compiler_options, - true, - RewritingScope::Everything, - ); - pipeline.run(&mut env); runner.bench(&env) } @@ -261,13 +228,13 @@ impl Runner { // Write data record of benchmark result writeln!( self.out, - "{:<40} {:>12} {:>12}", + "{:<50} {:>15} {:>15}", fun.get_full_name_str(), duration.as_millis(), status )?; - println!("\x08\x08{:.3}s {}.", duration.as_secs_f64(), status); + println!(" {:.3}s {}.", duration.as_secs_f64(), status); Ok(()) } diff --git a/third_party/move/move-prover/lab/src/main.rs b/third_party/move/move-prover/lab/src/main.rs index 1db9219c151c9..a9a8c38bae7ae 100644 --- a/third_party/move/move-prover/lab/src/main.rs +++ b/third_party/move/move-prover/lab/src/main.rs @@ -5,7 +5,7 @@ #![forbid(unsafe_code)] use itertools::Itertools; -use prover_lab::{benchmark, plot}; +use move_prover_lab::{benchmark, plot}; fn main() { let args = std::env::args().collect_vec(); diff --git a/third_party/move/move-prover/src/lib.rs b/third_party/move/move-prover/src/lib.rs index 46810fe825d9d..c41f3df89d222 100644 --- a/third_party/move/move-prover/src/lib.rs +++ b/third_party/move/move-prover/src/lib.rs @@ -15,8 +15,8 @@ use move_compiler_v2::{env_pipeline::rewrite_target::RewritingScope, Experiment} use move_docgen::Docgen; use move_errmapgen::ErrmapGen; use move_model::{ - code_writer::CodeWriter, model::GlobalEnv, parse_addresses_from_options, - run_model_builder_with_options, + code_writer::CodeWriter, metadata::LATEST_STABLE_COMPILER_VERSION_VALUE, model::GlobalEnv, + parse_addresses_from_options, run_model_builder_with_options, }; use move_prover_boogie_backend::{ add_prelude, boogie_wrapper::BoogieWrapper, bytecode_translator::BoogieTranslator, @@ -71,19 +71,26 @@ pub fn run_move_prover_v2( options: Options, ) -> anyhow::Result<()> { let now = Instant::now(); - let cloned_options = options.clone(); + let mut env = create_move_prover_v2_model(error_writer, options.clone())?; + run_move_prover_with_model_v2(&mut env, error_writer, options, now) +} + +pub fn create_move_prover_v2_model( + error_writer: &mut W, + options: Options, +) -> anyhow::Result { let compiler_options = move_compiler_v2::Options { - dependencies: cloned_options.move_deps, - named_address_mapping: cloned_options.move_named_address_values, - output_dir: cloned_options.output_path, - language_version: cloned_options.language_version, - compiler_version: None, // TODO: need to pass v2.x here + dependencies: options.move_deps, + named_address_mapping: options.move_named_address_values, + output_dir: options.output_path, + language_version: options.language_version, + compiler_version: Some(LATEST_STABLE_COMPILER_VERSION_VALUE), skip_attribute_checks: true, known_attributes: Default::default(), - testing: cloned_options.backend.stable_test_output, + testing: options.backend.stable_test_output, experiments: vec![], experiment_cache: Default::default(), - sources: cloned_options.move_sources, + sources: options.move_sources, sources_deps: vec![], warn_deprecated: false, warn_of_deprecation_use_in_aptos_libs: false, @@ -94,8 +101,7 @@ pub fn run_move_prover_v2( external_checks: vec![], }; - let mut env = move_compiler_v2::run_move_compiler_for_analysis(error_writer, compiler_options)?; - run_move_prover_with_model_v2(&mut env, error_writer, options, now) + move_compiler_v2::run_move_compiler_for_analysis(error_writer, compiler_options) } /// Create the initial number operation state for each function and struct From 8aa15a64f26fca76bfae949f96866ff6827d9f86 Mon Sep 17 00:00:00 2001 From: GhostWalker562 <43276017+GhostWalker562@users.noreply.github.com> Date: Thu, 19 Dec 2024 18:55:28 -0800 Subject: [PATCH 69/78] Fix aptos init for existing accounts (#15625) --- crates/aptos/CHANGELOG.md | 2 ++ crates/aptos/src/common/init.rs | 51 ++++++++++++++++++--------------- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/crates/aptos/CHANGELOG.md b/crates/aptos/CHANGELOG.md index 24fa28425dfc2..3bff5c8b2bc12 100644 --- a/crates/aptos/CHANGELOG.md +++ b/crates/aptos/CHANGELOG.md @@ -6,6 +6,8 @@ All notable changes to the Aptos CLI will be captured in this file. This project - Add flag `--benchmark` to `aptos move prove`, which allows to benchmark verification times of individual functions in a package. - Add flag `--only ` to `aptos move prove`, which allows to scope verification to a function. +- Fix `aptos init` to show the explorer link for accounts when account is already created on chain instead of prompting to fund the account. + ## [5.1.0] - 2024/12/13 - More optimizations are now default for compiler v2. - Downgrade bytecode version to v6 before calling the Revela decompiler, if possible, i.e. no enum types are used. This allows to continue to use Revela until the new decompiler is ready. diff --git a/crates/aptos/src/common/init.rs b/crates/aptos/src/common/init.rs index 2dee996cbd185..6053339b51d7b 100644 --- a/crates/aptos/src/common/init.rs +++ b/crates/aptos/src/common/init.rs @@ -372,29 +372,34 @@ impl CliCommand<()> for InitTool { address, profile_name, ); - match network { - Network::Mainnet => { - eprintln!("The account has not been created on chain yet, you will need to create and fund the account by transferring funds from another account"); - }, - Network::Testnet => { - let mint_site_url = get_mint_site_url(Some(address)); - eprintln!("The account has not been created on chain yet. To create the account and get APT on testnet you must visit {}", mint_site_url); - // We don't use `prompt_yes_with_override` here because we only want to - // automatically open the minting site if they're in an interactive setting. - if !self.prompt_options.assume_yes { - eprint!("Press [Enter] to go there now > "); - read_line("Confirmation")?; - open::that(&mint_site_url).map_err(|err| { - CliError::UnexpectedError(format!("Failed to open minting site: {}", err)) - })?; - } - }, - wildcard => { - eprintln!( - "See the account here: {}", - explorer_account_link(address, Some(wildcard)) - ); - }, + if !account_exists { + match network { + Network::Mainnet => { + eprintln!("The account has not been created on chain yet, you will need to create and fund the account by transferring funds from another account"); + }, + Network::Testnet => { + let mint_site_url = get_mint_site_url(Some(address)); + eprintln!("The account has not been created on chain yet. To create the account and get APT on testnet you must visit {}", mint_site_url); + // We don't use `prompt_yes_with_override` here because we only want to + // automatically open the minting site if they're in an interactive setting. + if !self.prompt_options.assume_yes { + eprint!("Press [Enter] to go there now > "); + read_line("Confirmation")?; + open::that(&mint_site_url).map_err(|err| { + CliError::UnexpectedError(format!( + "Failed to open minting site: {}", + err + )) + })?; + } + }, + _ => {}, + } + } else { + eprintln!( + "See the account here: {}", + explorer_account_link(address, Some(network)) + ); } Ok(()) From 2bea962eac4743db6cc0ae2e8a2fd7fcc323b121 Mon Sep 17 00:00:00 2001 From: George Mitenkov Date: Fri, 20 Dec 2024 05:49:56 +0000 Subject: [PATCH 70/78] [move] Stateful (de)serialization for function value lookups & delayed fields improvements (#15594) --- .../state_view_adapter.rs | 9 +- aptos-move/aptos-vm-types/src/resolver.rs | 18 +- aptos-move/aptos-vm/src/block_executor/mod.rs | 2 +- .../aptos-vm/src/move_vm_ext/session/mod.rs | 19 +- .../block-executor/src/captured_reads.rs | 43 +- aptos-move/block-executor/src/executor.rs | 24 +- .../block-executor/src/limit_processor.rs | 7 +- .../src/proptest_types/types.rs | 11 +- aptos-move/block-executor/src/task.rs | 17 +- .../src/txn_last_input_output.rs | 5 +- aptos-move/block-executor/src/types.rs | 15 +- .../block-executor/src/value_exchange.rs | 154 ++++--- aptos-move/block-executor/src/view.rs | 192 +++++---- .../framework/move-stdlib/src/natives/bcs.rs | 13 +- aptos-move/framework/src/natives/event.rs | 68 +-- aptos-move/framework/src/natives/util.rs | 9 +- aptos-move/framework/table-natives/src/lib.rs | 113 +++-- .../fuzz_targets/move/value_deserialize.rs | 5 +- .../move-table-extension/src/lib.rs | 69 +++- .../move/move-stdlib/src/natives/bcs.rs | 6 +- .../integration-tests/src/tests/mod.rs | 1 + .../src/tests/module_storage_tests.rs | 137 +++++++ .../move/move-vm/runtime/src/data_cache.rs | 16 +- third_party/move/move-vm/runtime/src/lib.rs | 4 +- .../move/move-vm/runtime/src/loader/mod.rs | 46 ++- .../move-vm/runtime/src/native_functions.rs | 18 +- .../move/move-vm/runtime/src/runtime.rs | 15 +- .../runtime/src/storage/code_storage.rs | 8 +- .../runtime/src/storage/environment.rs | 9 + .../implementations/unsync_code_storage.rs | 18 +- .../implementations/unsync_module_storage.rs | 12 +- .../move-vm/runtime/src/storage/loader.rs | 104 +---- .../runtime/src/storage/module_storage.rs | 153 ++++++- .../move-vm/runtime/src/storage/publishing.rs | 15 +- .../move/move-vm/types/src/value_serde.rs | 386 +++++++----------- .../types/src/values/serialization_tests.rs | 45 +- .../types/src/values/value_prop_tests.rs | 6 +- .../move-vm/types/src/values/values_impl.rs | 198 ++++----- .../src/framework.rs | 7 +- .../tools/move-unit-test/src/extensions.rs | 23 +- .../tools/move-unit-test/src/test_runner.rs | 9 +- types/src/transaction/mod.rs | 19 - .../signature_verified_transaction.rs | 2 - 43 files changed, 1155 insertions(+), 895 deletions(-) create mode 100644 third_party/move/move-vm/integration-tests/src/tests/module_storage_tests.rs diff --git a/aptos-move/aptos-vm-types/src/module_and_script_storage/state_view_adapter.rs b/aptos-move/aptos-vm-types/src/module_and_script_storage/state_view_adapter.rs index 64627c634797d..40eec5457f640 100644 --- a/aptos-move/aptos-vm-types/src/module_and_script_storage/state_view_adapter.rs +++ b/aptos-move/aptos-vm-types/src/module_and_script_storage/state_view_adapter.rs @@ -15,17 +15,20 @@ use move_binary_format::{ CompiledModule, }; use move_core_types::{ - account_address::AccountAddress, identifier::IdentStr, language_storage::ModuleId, + account_address::AccountAddress, + identifier::IdentStr, + language_storage::{ModuleId, TypeTag}, metadata::Metadata, }; use move_vm_runtime::{ ambassador_impl_CodeStorage, ambassador_impl_ModuleStorage, ambassador_impl_WithRuntimeEnvironment, AsUnsyncCodeStorage, BorrowedOrOwned, CodeStorage, - Module, ModuleStorage, RuntimeEnvironment, Script, UnsyncCodeStorage, UnsyncModuleStorage, - WithRuntimeEnvironment, + Function, Module, ModuleStorage, RuntimeEnvironment, Script, UnsyncCodeStorage, + UnsyncModuleStorage, WithRuntimeEnvironment, }; use move_vm_types::{ code::{ModuleBytesStorage, ModuleCode}, + loaded_data::runtime_types::{StructType, Type}, module_storage_error, }; use std::{ops::Deref, sync::Arc}; diff --git a/aptos-move/aptos-vm-types/src/resolver.rs b/aptos-move/aptos-vm-types/src/resolver.rs index 99e72df4c8140..38bcef0f69a24 100644 --- a/aptos-move/aptos-vm-types/src/resolver.rs +++ b/aptos-move/aptos-vm-types/src/resolver.rs @@ -203,33 +203,27 @@ pub trait StateStorageView { /// TODO: audit and reconsider the default implementation (e.g. should not /// resolve AggregatorV2 via the state-view based default implementation, as it /// doesn't provide a value exchange functionality). -pub trait TExecutorView: +pub trait TExecutorView: TResourceView + TModuleView + TAggregatorV1View - + TDelayedFieldView + + TDelayedFieldView + StateStorageView { } -impl TExecutorView for A where +impl TExecutorView for A where A: TResourceView + TModuleView + TAggregatorV1View - + TDelayedFieldView + + TDelayedFieldView + StateStorageView { } -pub trait ExecutorView: - TExecutorView -{ -} +pub trait ExecutorView: TExecutorView {} -impl ExecutorView for T where - T: TExecutorView -{ -} +impl ExecutorView for T where T: TExecutorView {} pub trait ResourceGroupView: TResourceGroupView diff --git a/aptos-move/aptos-vm/src/block_executor/mod.rs b/aptos-move/aptos-vm/src/block_executor/mod.rs index 168b1bb4a3719..ad3918657a568 100644 --- a/aptos-move/aptos-vm/src/block_executor/mod.rs +++ b/aptos-move/aptos-vm/src/block_executor/mod.rs @@ -354,7 +354,7 @@ impl BlockExecutorTransactionOutput for AptosTransactionOutput { .materialized_size() } - fn get_write_summary(&self) -> HashSet> { + fn get_write_summary(&self) -> HashSet> { let vm_output = self.vm_output.lock(); let output = vm_output .as_ref() diff --git a/aptos-move/aptos-vm/src/move_vm_ext/session/mod.rs b/aptos-move/aptos-vm/src/move_vm_ext/session/mod.rs index e20b94c89c68c..736e2327f953d 100644 --- a/aptos-move/aptos-vm/src/move_vm_ext/session/mod.rs +++ b/aptos-move/aptos-vm/src/move_vm_ext/session/mod.rs @@ -38,10 +38,10 @@ use move_core_types::{ vm_status::StatusCode, }; use move_vm_runtime::{ - move_vm::MoveVM, native_extensions::NativeContextExtensions, session::Session, ModuleStorage, - VerifiedModuleBundle, + move_vm::MoveVM, native_extensions::NativeContextExtensions, session::Session, + AsFunctionValueExtension, ModuleStorage, VerifiedModuleBundle, }; -use move_vm_types::{value_serde::serialize_and_allow_delayed_values, values::Value}; +use move_vm_types::{value_serde::ValueSerDeContext, values::Value}; use std::{ collections::BTreeMap, ops::{Deref, DerefMut}, @@ -127,6 +127,7 @@ impl<'r, 'l> SessionExt<'r, 'l> { module_storage: &impl ModuleStorage, ) -> VMResult<(VMChangeSet, ModuleWriteSet)> { let move_vm = self.inner.get_move_vm(); + let function_extension = module_storage.as_function_value_extension(); let resource_converter = |value: Value, layout: MoveTypeLayout, @@ -136,13 +137,17 @@ impl<'r, 'l> SessionExt<'r, 'l> { // We allow serialization of native values here because we want to // temporarily store native values (via encoding to ensure deterministic // gas charging) in block storage. - serialize_and_allow_delayed_values(&value, &layout)? + ValueSerDeContext::new() + .with_delayed_fields_serde() + .with_func_args_deserialization(&function_extension) + .serialize(&value, &layout)? .map(|bytes| (bytes.into(), Some(Arc::new(layout)))) } else { // Otherwise, there should be no native values so ensure // serialization fails here if there are any. - value - .simple_serialize(&layout) + ValueSerDeContext::new() + .with_func_args_deserialization(&function_extension) + .serialize(&value, &layout)? .map(|bytes| (bytes.into(), None)) }; serialization_result.ok_or_else(|| { @@ -165,7 +170,7 @@ impl<'r, 'l> SessionExt<'r, 'l> { let table_context: NativeTableContext = extensions.remove(); let table_change_set = table_context - .into_change_set() + .into_change_set(&function_extension) .map_err(|e| e.finish(Location::Undefined))?; let aggregator_context: NativeAggregatorContext = extensions.remove(); diff --git a/aptos-move/block-executor/src/captured_reads.rs b/aptos-move/block-executor/src/captured_reads.rs index 7a61f5e3fc16c..4835eaa2c4b63 100644 --- a/aptos-move/block-executor/src/captured_reads.rs +++ b/aptos-move/block-executor/src/captured_reads.rs @@ -1,10 +1,7 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -use crate::{ - code_cache_global::GlobalModuleCache, types::InputOutputKey, - value_exchange::filter_value_for_exchange, -}; +use crate::{code_cache_global::GlobalModuleCache, types::InputOutputKey, view::LatestView}; use anyhow::bail; use aptos_aggregator::{ delta_math::DeltaHistory, @@ -21,15 +18,18 @@ use aptos_mvhashmap::{ }; use aptos_types::{ error::{code_invariant_error, PanicError, PanicOr}, - executable::ModulePath, - state_store::state_value::StateValueMetadata, + executable::{Executable, ModulePath}, + state_store::{state_value::StateValueMetadata, TStateView}, transaction::BlockExecutableTransaction as Transaction, write_set::TransactionWrite, }; use aptos_vm_types::resolver::ResourceGroupSize; use derivative::Derivative; use move_core_types::value::MoveTypeLayout; -use move_vm_types::code::{ModuleCode, SyncModuleCache, WithAddress, WithName, WithSize}; +use move_vm_types::{ + code::{ModuleCode, SyncModuleCache, WithAddress, WithName, WithSize}, + delayed_values::delayed_field_id::DelayedFieldID, +}; use std::{ collections::{ hash_map::{ @@ -325,7 +325,7 @@ pub enum CacheRead { pub(crate) struct CapturedReads { data_reads: HashMap>, group_reads: HashMap>, - delayed_field_reads: HashMap, + delayed_field_reads: HashMap, #[deprecated] pub(crate) deprecated_module_reads: Vec, @@ -359,9 +359,13 @@ where S: WithSize, { // Return an iterator over the captured reads. - pub(crate) fn get_read_values_with_delayed_fields( + pub(crate) fn get_read_values_with_delayed_fields< + SV: TStateView, + X: Executable, + >( &self, - delayed_write_set_ids: &HashSet, + view: &LatestView, + delayed_write_set_ids: &HashSet, skip: &HashSet, ) -> Result)>, PanicError> { self.data_reads @@ -372,7 +376,7 @@ where } if let DataRead::Versioned(_version, value, Some(layout)) = data_read { - filter_value_for_exchange::(value, layout, delayed_write_set_ids, key) + view.filter_value_for_exchange(value, layout, delayed_write_set_ids, key) } else { None } @@ -511,7 +515,7 @@ where pub(crate) fn capture_delayed_field_read( &mut self, - id: T::Identifier, + id: DelayedFieldID, update: bool, read: DelayedFieldRead, ) -> Result<(), PanicOr> { @@ -571,7 +575,7 @@ where pub(crate) fn get_delayed_field_by_kind( &self, - id: &T::Identifier, + id: &DelayedFieldID, min_kind: DelayedFieldReadKind, ) -> Option { self.delayed_field_reads @@ -718,7 +722,7 @@ where // (as it internally uses read_latest_predicted_value to get the current value). pub(crate) fn validate_delayed_field_reads( &self, - delayed_fields: &dyn TVersionedDelayedFieldView, + delayed_fields: &dyn TVersionedDelayedFieldView, idx_to_validate: TxnIndex, ) -> Result { if self.delayed_field_speculative_failure { @@ -779,9 +783,7 @@ where K: Hash + Eq + Ord + Clone + WithAddress + WithName, VC: Deref>, { - pub(crate) fn get_read_summary( - &self, - ) -> HashSet> { + pub(crate) fn get_read_summary(&self) -> HashSet> { let mut ret = HashSet::new(); for (key, read) in &self.data_reads { if let DataRead::Versioned(_, _, _) = read { @@ -822,7 +824,7 @@ where pub(crate) struct UnsyncReadSet { pub(crate) resource_reads: HashSet, pub(crate) group_reads: HashMap>, - pub(crate) delayed_field_reads: HashSet, + pub(crate) delayed_field_reads: HashSet, #[deprecated] pub(crate) deprecated_module_reads: HashSet, @@ -839,9 +841,7 @@ where self.module_reads.insert(key); } - pub(crate) fn get_read_summary( - &self, - ) -> HashSet> { + pub(crate) fn get_read_summary(&self) -> HashSet> { let mut ret = HashSet::new(); for key in &self.resource_reads { ret.insert(InputOutputKey::Resource(key.clone())); @@ -1067,7 +1067,6 @@ mod test { impl Transaction for TestTransactionType { type Event = MockEvent; - type Identifier = DelayedFieldID; type Key = KeyType; type Tag = u32; type Value = ValueType; diff --git a/aptos-move/block-executor/src/executor.rs b/aptos-move/block-executor/src/executor.rs index c0bd5ec56967e..b98b68559583c 100644 --- a/aptos-move/block-executor/src/executor.rs +++ b/aptos-move/block-executor/src/executor.rs @@ -59,7 +59,7 @@ use fail::fail_point; use move_binary_format::CompiledModule; use move_core_types::{language_storage::ModuleId, value::MoveTypeLayout, vm_status::StatusCode}; use move_vm_runtime::{Module, RuntimeEnvironment, WithRuntimeEnvironment}; -use move_vm_types::code::ModuleCache; +use move_vm_types::{code::ModuleCache, delayed_values::delayed_field_id::DelayedFieldID}; use num_cpus; use rayon::ThreadPool; use std::{ @@ -115,7 +115,7 @@ where incarnation: Incarnation, signature_verified_block: &TP, last_input_output: &TxnLastInputOutput, - versioned_cache: &MVHashMap, + versioned_cache: &MVHashMap, executor: &E, base_view: &S, global_module_cache: &GlobalModuleCache< @@ -406,7 +406,7 @@ where Module, AptosModuleExtension, >, - versioned_cache: &MVHashMap, + versioned_cache: &MVHashMap, scheduler: &Scheduler, ) -> bool { let _timer = TASK_VALIDATE_SECONDS.start_timer(); @@ -436,7 +436,7 @@ where fn update_transaction_on_abort( txn_idx: TxnIndex, last_input_output: &TxnLastInputOutput, - versioned_cache: &MVHashMap, + versioned_cache: &MVHashMap, runtime_environment: &RuntimeEnvironment, ) { counters::SPECULATIVE_ABORT_COUNT.inc(); @@ -490,7 +490,7 @@ where valid: bool, validation_wave: Wave, last_input_output: &TxnLastInputOutput, - versioned_cache: &MVHashMap, + versioned_cache: &MVHashMap, scheduler: &Scheduler, runtime_environment: &RuntimeEnvironment, ) -> Result { @@ -520,7 +520,7 @@ where /// returns false (indicating that transaction needs to be re-executed). fn validate_and_commit_delayed_fields( txn_idx: TxnIndex, - versioned_cache: &MVHashMap, + versioned_cache: &MVHashMap, last_input_output: &TxnLastInputOutput, ) -> Result { let read_set = last_input_output @@ -563,7 +563,7 @@ where &self, block_gas_limit_type: &BlockGasLimitType, scheduler: &Scheduler, - versioned_cache: &MVHashMap, + versioned_cache: &MVHashMap, scheduler_task: &mut SchedulerTask, last_input_output: &TxnLastInputOutput, shared_commit_state: &ExplicitSyncWrapper>, @@ -766,7 +766,7 @@ where Module, AptosModuleExtension, >, - versioned_cache: &MVHashMap, + versioned_cache: &MVHashMap, scheduler: &Scheduler, runtime_environment: &RuntimeEnvironment, ) -> Result<(), PanicError> { @@ -788,7 +788,7 @@ where fn materialize_aggregator_v1_delta_writes( txn_idx: TxnIndex, last_input_output: &TxnLastInputOutput, - versioned_cache: &MVHashMap, + versioned_cache: &MVHashMap, base_view: &S, ) -> Vec<(T::Key, WriteOp)> { // Materialize all the aggregator v1 deltas. @@ -840,7 +840,7 @@ where fn materialize_txn_commit( &self, txn_idx: TxnIndex, - versioned_cache: &MVHashMap, + versioned_cache: &MVHashMap, scheduler: &Scheduler, start_shared_counter: u32, shared_counter: &AtomicU32, @@ -953,7 +953,7 @@ where environment: &AptosEnvironment, block: &TP, last_input_output: &TxnLastInputOutput, - versioned_cache: &MVHashMap, + versioned_cache: &MVHashMap, scheduler: &Scheduler, // TODO: should not need to pass base view. base_view: &S, @@ -1274,7 +1274,7 @@ where Module, AptosModuleExtension, >, - unsync_map: &UnsyncMap, + unsync_map: &UnsyncMap, output: &E::Output, resource_write_set: Vec<(T::Key, Arc, Option>)>, ) -> Result<(), SequentialBlockExecutionError> { diff --git a/aptos-move/block-executor/src/limit_processor.rs b/aptos-move/block-executor/src/limit_processor.rs index b687da43e1e39..1b60348d45462 100644 --- a/aptos-move/block-executor/src/limit_processor.rs +++ b/aptos-move/block-executor/src/limit_processor.rs @@ -281,7 +281,6 @@ mod test { proptest_types::types::{KeyType, MockEvent, MockTransaction}, types::InputOutputKey, }; - use move_vm_types::delayed_values::delayed_field_id::DelayedFieldID; use std::collections::HashSet; // TODO: add tests for accumulate_fee_statement / compute_conflict_multiplier for different BlockGasLimitType configs @@ -363,15 +362,13 @@ mod test { assert!(processor.should_end_block_parallel()); } - fn to_map( - reads: &[InputOutputKey], - ) -> HashSet, u32, DelayedFieldID>> { + fn to_map(reads: &[InputOutputKey]) -> HashSet, u32>> { reads .iter() .map(|key| match key { InputOutputKey::Resource(k) => InputOutputKey::Resource(KeyType(*k, false)), InputOutputKey::Group(k, t) => InputOutputKey::Group(KeyType(*k, false), *t), - InputOutputKey::DelayedField(i) => InputOutputKey::DelayedField((*i).into()), + InputOutputKey::DelayedField(i) => InputOutputKey::DelayedField(*i), }) .collect() } diff --git a/aptos-move/block-executor/src/proptest_types/types.rs b/aptos-move/block-executor/src/proptest_types/types.rs index d594f134c2829..bc5ee4395e11d 100644 --- a/aptos-move/block-executor/src/proptest_types/types.rs +++ b/aptos-move/block-executor/src/proptest_types/types.rs @@ -440,7 +440,6 @@ impl< > Transaction for MockTransaction { type Event = E; - type Identifier = DelayedFieldID; type Key = K; type Tag = u32; type Value = ValueType; @@ -848,7 +847,7 @@ where fn execute_transaction( &self, - view: &(impl TExecutorView + view: &(impl TExecutorView + TResourceGroupView + AptosCodeStorage), txn: &Self::Txn, @@ -1112,12 +1111,7 @@ where self.deltas.clone() } - fn delayed_field_change_set( - &self, - ) -> BTreeMap< - ::Identifier, - DelayedChange<::Identifier>, - > { + fn delayed_field_change_set(&self) -> BTreeMap> { // TODO[agg_v2](tests): add aggregators V2 to the proptest? BTreeMap::new() } @@ -1263,7 +1257,6 @@ where crate::types::InputOutputKey< ::Key, ::Tag, - ::Identifier, >, > { HashSet::new() diff --git a/aptos-move/block-executor/src/task.rs b/aptos-move/block-executor/src/task.rs index 3599420e28c3f..4efdc14d7160a 100644 --- a/aptos-move/block-executor/src/task.rs +++ b/aptos-move/block-executor/src/task.rs @@ -21,6 +21,7 @@ use aptos_vm_types::{ resolver::{ResourceGroupSize, TExecutorView, TResourceGroupView}, }; use move_core_types::{value::MoveTypeLayout, vm_status::StatusCode}; +use move_vm_types::delayed_values::delayed_field_id::DelayedFieldID; use std::{ collections::{BTreeMap, HashSet}, fmt::Debug, @@ -77,7 +78,6 @@ pub trait ExecutorTask: Sync { ::Key, ::Tag, MoveTypeLayout, - ::Identifier, ::Value, > + TResourceGroupView< GroupKey = ::Key, @@ -118,12 +118,7 @@ pub trait TransactionOutput: Send + Sync + Debug { fn aggregator_v1_delta_set(&self) -> Vec<(::Key, DeltaOp)>; /// Get the delayed field changes of a transaction from its output. - fn delayed_field_change_set( - &self, - ) -> BTreeMap< - ::Identifier, - DelayedChange<::Identifier>, - >; + fn delayed_field_change_set(&self) -> BTreeMap>; fn reads_needing_delayed_field_exchange( &self, @@ -204,11 +199,5 @@ pub trait TransactionOutput: Send + Sync + Debug { fn get_write_summary( &self, - ) -> HashSet< - InputOutputKey< - ::Key, - ::Tag, - ::Identifier, - >, - >; + ) -> HashSet::Key, ::Tag>>; } diff --git a/aptos-move/block-executor/src/txn_last_input_output.rs b/aptos-move/block-executor/src/txn_last_input_output.rs index fcfbde7452aa7..0907d81202c72 100644 --- a/aptos-move/block-executor/src/txn_last_input_output.rs +++ b/aptos-move/block-executor/src/txn_last_input_output.rs @@ -25,6 +25,7 @@ use dashmap::DashSet; use move_binary_format::CompiledModule; use move_core_types::{language_storage::ModuleId, value::MoveTypeLayout}; use move_vm_runtime::{Module, RuntimeEnvironment}; +use move_vm_types::delayed_values::delayed_field_id::DelayedFieldID; use std::{ collections::{BTreeMap, HashSet}, fmt::Debug, @@ -356,7 +357,7 @@ impl, E: Debug + Send + Clone> pub(crate) fn delayed_field_keys( &self, txn_idx: TxnIndex, - ) -> Option> { + ) -> Option> { self.outputs[txn_idx as usize] .load() .as_ref() @@ -462,7 +463,7 @@ impl, E: Debug + Send + Clone> pub(crate) fn get_write_summary( &self, txn_idx: TxnIndex, - ) -> HashSet> { + ) -> HashSet> { match self.outputs[txn_idx as usize] .load_full() .expect("Output must exist") diff --git a/aptos-move/block-executor/src/types.rs b/aptos-move/block-executor/src/types.rs index 8e4c987d91fe5..cd162d271925b 100644 --- a/aptos-move/block-executor/src/types.rs +++ b/aptos-move/block-executor/src/types.rs @@ -2,24 +2,25 @@ // SPDX-License-Identifier: Apache-2.0 use aptos_types::transaction::BlockExecutableTransaction as Transaction; +use move_vm_types::delayed_values::delayed_field_id::DelayedFieldID; use std::{collections::HashSet, fmt}; #[derive(Eq, Hash, PartialEq, Debug)] -pub enum InputOutputKey { +pub enum InputOutputKey { Resource(K), Group(K, T), - DelayedField(I), + DelayedField(DelayedFieldID), } pub struct ReadWriteSummary { - reads: HashSet>, - writes: HashSet>, + reads: HashSet>, + writes: HashSet>, } impl ReadWriteSummary { pub fn new( - reads: HashSet>, - writes: HashSet>, + reads: HashSet>, + writes: HashSet>, ) -> Self { Self { reads, writes } } @@ -29,7 +30,7 @@ impl ReadWriteSummary { } pub fn collapse_resource_group_conflicts(self) -> Self { - let collapse = |k: InputOutputKey| match k { + let collapse = |k: InputOutputKey| match k { InputOutputKey::Resource(k) => InputOutputKey::Resource(k), InputOutputKey::Group(k, _) => InputOutputKey::Resource(k), InputOutputKey::DelayedField(id) => InputOutputKey::DelayedField(id), diff --git a/aptos-move/block-executor/src/value_exchange.rs b/aptos-move/block-executor/src/value_exchange.rs index e28ec35dddd03..0855164565ee3 100644 --- a/aptos-move/block-executor/src/value_exchange.rs +++ b/aptos-move/block-executor/src/value_exchange.rs @@ -17,9 +17,10 @@ use aptos_types::{ use bytes::Bytes; use move_binary_format::errors::PartialVMResult; use move_core_types::value::{IdentifierMappingKind, MoveTypeLayout}; +use move_vm_runtime::AsFunctionValueExtension; use move_vm_types::{ - delayed_values::delayed_field_id::{ExtractWidth, TryFromMoveValue}, - value_serde::{deserialize_and_allow_delayed_values, ValueToIdentifierMapping}, + delayed_values::delayed_field_id::{DelayedFieldID, ExtractWidth, TryFromMoveValue}, + value_serde::{ValueSerDeContext, ValueToIdentifierMapping}, value_traversal::find_identifiers_in_value, values::Value, }; @@ -35,7 +36,7 @@ pub(crate) struct TemporaryValueToIdentifierMapping< txn_idx: TxnIndex, // These are the delayed field keys that were touched when utilizing this mapping // to replace ids with values or values with ids - delayed_field_ids: RefCell>, + delayed_field_ids: RefCell>, } impl<'a, T: Transaction, S: TStateView, X: Executable> @@ -49,11 +50,11 @@ impl<'a, T: Transaction, S: TStateView, X: Executable> } } - fn generate_delayed_field_id(&self, width: u32) -> T::Identifier { + fn generate_delayed_field_id(&self, width: u32) -> DelayedFieldID { self.latest_view.generate_delayed_field_id(width) } - pub fn into_inner(self) -> HashSet { + pub fn into_inner(self) -> HashSet { self.delayed_field_ids.into_inner() } } @@ -64,14 +65,12 @@ impl<'a, T: Transaction, S: TStateView, X: Executable> impl<'a, T: Transaction, S: TStateView, X: Executable> ValueToIdentifierMapping for TemporaryValueToIdentifierMapping<'a, T, S, X> { - type Identifier = T::Identifier; - fn value_to_identifier( &self, kind: &IdentifierMappingKind, layout: &MoveTypeLayout, value: Value, - ) -> PartialVMResult { + ) -> PartialVMResult { let (base_value, width) = DelayedFieldValue::try_from_move_value(layout, value, kind)?; let id = self.generate_delayed_field_id(width); match &self.latest_view.latest_view { @@ -85,7 +84,7 @@ impl<'a, T: Transaction, S: TStateView, X: Executable> ValueToIden fn identifier_to_value( &self, layout: &MoveTypeLayout, - identifier: Self::Identifier, + identifier: DelayedFieldID, ) -> PartialVMResult { self.delayed_field_ids.borrow_mut().insert(identifier); let delayed_field = match &self.latest_view.latest_view { @@ -106,68 +105,87 @@ impl<'a, T: Transaction, S: TStateView, X: Executable> ValueToIden } } -// Given bytes, where values were already exchanged with identifiers, -// return a list of identifiers present in it. -fn extract_identifiers_from_value( - bytes: &Bytes, - layout: &MoveTypeLayout, -) -> anyhow::Result> { - // TODO[agg_v2](optimize): this performs 2 traversals of a value: - // 1) deserialize, - // 2) find identifiers to populate the set. - // See if can cache identifiers in advance, or combine it with - // deserialization. - let value = deserialize_and_allow_delayed_values(bytes, layout) - .ok_or_else(|| anyhow::anyhow!("Failed to deserialize resource during id replacement"))?; - - let mut identifiers = HashSet::new(); - find_identifiers_in_value(&value, &mut identifiers)?; - // TODO[agg_v2](cleanup): ugly way of converting delayed ids to generic type params. - Ok(identifiers.into_iter().map(T::Identifier::from).collect()) -} +impl<'a, T, S, X> LatestView<'a, T, S, X> +where + T: Transaction, + S: TStateView, + X: Executable, +{ + /// Given bytes, where values were already exchanged with identifiers, returns a list of + /// identifiers present in it. + fn extract_identifiers_from_value( + &self, + bytes: &Bytes, + layout: &MoveTypeLayout, + ) -> anyhow::Result> { + // TODO[agg_v2](optimize): this performs 2 traversals of a value: + // 1) deserialize, + // 2) find identifiers to populate the set. + // See if can cache identifiers in advance, or combine it with + // deserialization. + let function_value_extension = self.as_function_value_extension(); + let value = ValueSerDeContext::new() + .with_func_args_deserialization(&function_value_extension) + .with_delayed_fields_serde() + .deserialize(bytes, layout) + .ok_or_else(|| { + anyhow::anyhow!("Failed to deserialize resource during id replacement") + })?; -// Deletion returns a PanicError. -pub(crate) fn does_value_need_exchange( - value: &T::Value, - layout: &MoveTypeLayout, - delayed_write_set_ids: &HashSet, -) -> Result { - if let Some(bytes) = value.bytes() { - extract_identifiers_from_value::(bytes, layout) - .map(|identifiers_in_read| !delayed_write_set_ids.is_disjoint(&identifiers_in_read)) - .map_err(|e| code_invariant_error(format!("Identifier extraction failed with {:?}", e))) - } else { - // Deletion returns an error. - Err(code_invariant_error( - "Delete shouldn't be in values considered for exchange", - )) + let mut identifiers = HashSet::new(); + find_identifiers_in_value(&value, &mut identifiers)?; + // TODO[agg_v2](cleanup): ugly way of converting delayed ids to generic type params. + Ok(identifiers.into_iter().map(DelayedFieldID::from).collect()) } -} -// Exclude deletions, and values that do not contain any delayed field IDs that were written to. -pub(crate) fn filter_value_for_exchange( - value: &T::Value, - layout: &Arc, - delayed_write_set_ids: &HashSet, - key: &T::Key, -) -> Option)), PanicError>> { - if value.is_deletion() { - None - } else { - does_value_need_exchange::(value, layout, delayed_write_set_ids).map_or_else( - |e| Some(Err(e)), - |needs_exchange| { - needs_exchange.then(|| { - Ok(( - key.clone(), - ( - value.as_state_value_metadata().unwrap().clone(), - value.write_op_size().write_len().unwrap(), - layout.clone(), - ), - )) + // Deletion returns a PanicError. + pub(crate) fn does_value_need_exchange( + &self, + value: &T::Value, + layout: &MoveTypeLayout, + delayed_write_set_ids: &HashSet, + ) -> Result { + if let Some(bytes) = value.bytes() { + self.extract_identifiers_from_value(bytes, layout) + .map(|identifiers_in_read| !delayed_write_set_ids.is_disjoint(&identifiers_in_read)) + .map_err(|e| { + code_invariant_error(format!("Identifier extraction failed with {:?}", e)) }) - }, - ) + } else { + // Deletion returns an error. + Err(code_invariant_error( + "Delete shouldn't be in values considered for exchange", + )) + } + } + + // Exclude deletions, and values that do not contain any delayed field IDs that were written to. + pub(crate) fn filter_value_for_exchange( + &self, + value: &T::Value, + layout: &Arc, + delayed_write_set_ids: &HashSet, + key: &T::Key, + ) -> Option)), PanicError>> { + if value.is_deletion() { + None + } else { + self.does_value_need_exchange(value, layout, delayed_write_set_ids) + .map_or_else( + |e| Some(Err(e)), + |needs_exchange| { + needs_exchange.then(|| { + Ok(( + key.clone(), + ( + value.as_state_value_metadata().unwrap().clone(), + value.write_op_size().write_len().unwrap(), + layout.clone(), + ), + )) + }) + }, + ) + } } } diff --git a/aptos-move/block-executor/src/view.rs b/aptos-move/block-executor/src/view.rs index 7f4b3f3daa053..38d9ef7d30647 100644 --- a/aptos-move/block-executor/src/view.rs +++ b/aptos-move/block-executor/src/view.rs @@ -11,9 +11,7 @@ use crate::{ code_cache_global::GlobalModuleCache, counters, scheduler::{DependencyResult, DependencyStatus, Scheduler, TWaitForDependency}, - value_exchange::{ - does_value_need_exchange, filter_value_for_exchange, TemporaryValueToIdentifierMapping, - }, + value_exchange::TemporaryValueToIdentifierMapping, }; use aptos_aggregator::{ bounded_math::{ok_overflow, BoundedMath, SignedU128}, @@ -57,13 +55,10 @@ use move_binary_format::{ CompiledModule, }; use move_core_types::{language_storage::ModuleId, value::MoveTypeLayout, vm_status::StatusCode}; -use move_vm_runtime::{Module, RuntimeEnvironment}; +use move_vm_runtime::{AsFunctionValueExtension, Module, RuntimeEnvironment}; use move_vm_types::{ - delayed_values::delayed_field_id::ExtractUniqueIndex, - value_serde::{ - deserialize_and_allow_delayed_values, deserialize_and_replace_values_with_ids, - serialize_and_allow_delayed_values, serialize_and_replace_ids_with_values, - }, + delayed_values::delayed_field_id::{DelayedFieldID, ExtractUniqueIndex}, + value_serde::ValueSerDeContext, }; use std::{ cell::RefCell, @@ -163,7 +158,7 @@ trait ResourceGroupState { } pub(crate) struct ParallelState<'a, T: Transaction, X: Executable> { - pub(crate) versioned_map: &'a MVHashMap, + pub(crate) versioned_map: &'a MVHashMap, scheduler: &'a Scheduler, start_counter: u32, counter: &'a AtomicU32, @@ -175,9 +170,9 @@ fn get_delayed_field_value_impl( captured_reads: &RefCell< CapturedReads, >, - versioned_delayed_fields: &dyn TVersionedDelayedFieldView, + versioned_delayed_fields: &dyn TVersionedDelayedFieldView, wait_for: &dyn TWaitForDependency, - id: &T::Identifier, + id: &DelayedFieldID, txn_idx: TxnIndex, ) -> Result> { // We expect only DelayedFieldReadKind::Value (which is set from this function), @@ -315,9 +310,9 @@ fn delayed_field_try_add_delta_outcome_impl( captured_reads: &RefCell< CapturedReads, >, - versioned_delayed_fields: &dyn TVersionedDelayedFieldView, + versioned_delayed_fields: &dyn TVersionedDelayedFieldView, wait_for: &dyn TWaitForDependency, - id: &T::Identifier, + id: &DelayedFieldID, base_delta: &SignedU128, delta: &SignedU128, max_value: u128, @@ -451,7 +446,7 @@ fn wait_for_dependency( impl<'a, T: Transaction, X: Executable> ParallelState<'a, T, X> { pub(crate) fn new( - shared_map: &'a MVHashMap, + shared_map: &'a MVHashMap, shared_scheduler: &'a Scheduler, start_shared_counter: u32, shared_counter: &'a AtomicU32, @@ -465,7 +460,11 @@ impl<'a, T: Transaction, X: Executable> ParallelState<'a, T, X> { } } - pub(crate) fn set_delayed_field_value(&self, id: T::Identifier, base_value: DelayedFieldValue) { + pub(crate) fn set_delayed_field_value( + &self, + id: DelayedFieldID, + base_value: DelayedFieldValue, + ) { self.versioned_map .delayed_fields() .set_base_value(id, base_value) @@ -787,7 +786,7 @@ impl<'a, T: Transaction, X: Executable> ResourceGroupState for ParallelState< } pub(crate) struct SequentialState<'a, T: Transaction> { - pub(crate) unsync_map: &'a UnsyncMap, + pub(crate) unsync_map: &'a UnsyncMap, pub(crate) read_set: RefCell>, pub(crate) start_counter: u32, pub(crate) counter: &'a RefCell, @@ -797,7 +796,7 @@ pub(crate) struct SequentialState<'a, T: Transaction> { impl<'a, T: Transaction> SequentialState<'a, T> { pub fn new( - unsync_map: &'a UnsyncMap, + unsync_map: &'a UnsyncMap, start_counter: u32, counter: &'a RefCell, ) -> Self { @@ -810,11 +809,15 @@ impl<'a, T: Transaction> SequentialState<'a, T> { } } - pub(crate) fn set_delayed_field_value(&self, id: T::Identifier, base_value: DelayedFieldValue) { + pub(crate) fn set_delayed_field_value( + &self, + id: DelayedFieldID, + base_value: DelayedFieldValue, + ) { self.unsync_map.set_base_delayed_field(id, base_value) } - pub(crate) fn read_delayed_field(&self, id: T::Identifier) -> Option { + pub(crate) fn read_delayed_field(&self, id: DelayedFieldID) -> Option { self.unsync_map.fetch_delayed_field(&id) } } @@ -1020,7 +1023,7 @@ impl<'a, T: Transaction, S: TStateView, X: Executable> LatestView< } #[cfg(test)] - fn get_read_summary(&self) -> HashSet> { + fn get_read_summary(&self) -> HashSet> { match &self.latest_view { ViewState::Sync(state) => state.captured_reads.borrow().get_read_summary(), ViewState::Unsync(state) => state.read_set.borrow().get_read_summary(), @@ -1130,20 +1133,28 @@ impl<'a, T: Transaction, S: TStateView, X: Executable> LatestView< &self, state_value: StateValue, layout: &MoveTypeLayout, - ) -> anyhow::Result<(StateValue, HashSet)> { + ) -> anyhow::Result<(StateValue, HashSet)> { let mapping = TemporaryValueToIdentifierMapping::new(self, self.txn_idx); + let function_value_extension = self.as_function_value_extension(); + state_value .map_bytes(|bytes| { // This call will replace all occurrences of aggregator / snapshot // values with unique identifiers with the same type layout. // The values are stored in aggregators multi-version data structure, // see the actual trait implementation for more details. - let patched_value = - deserialize_and_replace_values_with_ids(bytes.as_ref(), layout, &mapping) - .ok_or_else(|| { - anyhow::anyhow!("Failed to deserialize resource during id replacement") - })?; - serialize_and_allow_delayed_values(&patched_value, layout)? + let patched_value = ValueSerDeContext::new() + .with_delayed_fields_replacement(&mapping) + .with_func_args_deserialization(&function_value_extension) + .deserialize(bytes.as_ref(), layout) + .ok_or_else(|| { + anyhow::anyhow!("Failed to deserialize resource during id replacement") + })?; + + ValueSerDeContext::new() + .with_delayed_fields_serde() + .with_func_args_deserialization(&function_value_extension) + .serialize(&patched_value, layout)? .ok_or_else(|| { anyhow::anyhow!( "Failed to serialize value {} after id replacement", @@ -1161,17 +1172,26 @@ impl<'a, T: Transaction, S: TStateView, X: Executable> LatestView< &self, bytes: &Bytes, layout: &MoveTypeLayout, - ) -> anyhow::Result<(Bytes, HashSet)> { + ) -> anyhow::Result<(Bytes, HashSet)> { // This call will replace all occurrences of aggregator / snapshot // identifiers with values with the same type layout. - let value = deserialize_and_allow_delayed_values(bytes, layout).ok_or_else(|| { - anyhow::anyhow!( - "Failed to deserialize resource during id replacement: {:?}", - bytes - ) - })?; + let function_value_extension = self.as_function_value_extension(); + let value = ValueSerDeContext::new() + .with_func_args_deserialization(&function_value_extension) + .with_delayed_fields_serde() + .deserialize(bytes, layout) + .ok_or_else(|| { + anyhow::anyhow!( + "Failed to deserialize resource during id replacement: {:?}", + bytes + ) + })?; + let mapping = TemporaryValueToIdentifierMapping::new(self, self.txn_idx); - let patched_bytes = serialize_and_replace_ids_with_values(&value, layout, &mapping) + let patched_bytes = ValueSerDeContext::new() + .with_delayed_fields_replacement(&mapping) + .with_func_args_deserialization(&function_value_extension) + .serialize(&value, layout)? .ok_or_else(|| anyhow::anyhow!("Failed to serialize resource during id replacement"))? .into(); Ok((patched_bytes, mapping.into_inner())) @@ -1180,8 +1200,8 @@ impl<'a, T: Transaction, S: TStateView, X: Executable> LatestView< fn get_reads_needing_exchange_sequential( &self, read_set: &HashSet, - unsync_map: &UnsyncMap, - delayed_write_set_ids: &HashSet, + unsync_map: &UnsyncMap, + delayed_write_set_ids: &HashSet, skip: &HashSet, ) -> Result)>, PanicError> { read_set @@ -1192,14 +1212,13 @@ impl<'a, T: Transaction, S: TStateView, X: Executable> LatestView< } match unsync_map.fetch_data(key) { - Some(ValueWithLayout::Exchanged(value, Some(layout))) => { - filter_value_for_exchange::( + Some(ValueWithLayout::Exchanged(value, Some(layout))) => self + .filter_value_for_exchange( value.as_ref(), &layout, delayed_write_set_ids, key, - ) - }, + ), Some(ValueWithLayout::Exchanged(_, None)) => None, Some(ValueWithLayout::RawFromStorage(_)) => Some(Err(code_invariant_error( "Cannot exchange value that was not exchanged before", @@ -1213,7 +1232,7 @@ impl<'a, T: Transaction, S: TStateView, X: Executable> LatestView< fn get_group_reads_needing_exchange_parallel( &self, parallel_state: &ParallelState<'a, T, X>, - delayed_write_set_ids: &HashSet, + delayed_write_set_ids: &HashSet, skip: &HashSet, ) -> PartialVMResult> { let reads_with_delayed_fields = parallel_state @@ -1233,12 +1252,9 @@ impl<'a, T: Transaction, S: TStateView, X: Executable> LatestView< let mut resources_needing_delayed_field_exchange = false; for data_read in inner_reads.values() { if let DataRead::Versioned(_version, value, Some(layout)) = data_read { - let needs_exchange = does_value_need_exchange::( - value, - layout.as_ref(), - delayed_write_set_ids, - ) - .map_err(PartialVMError::from)?; + let needs_exchange = self + .does_value_need_exchange(value, layout.as_ref(), delayed_write_set_ids) + .map_err(PartialVMError::from)?; if needs_exchange { resources_needing_delayed_field_exchange = true; @@ -1277,8 +1293,8 @@ impl<'a, T: Transaction, S: TStateView, X: Executable> LatestView< fn get_group_reads_needing_exchange_sequential( &self, group_read_set: &HashMap>, - unsync_map: &UnsyncMap, - delayed_write_set_ids: &HashSet, + unsync_map: &UnsyncMap, + delayed_write_set_ids: &HashSet, skip: &HashSet, ) -> PartialVMResult> { group_read_set @@ -1293,7 +1309,7 @@ impl<'a, T: Transaction, S: TStateView, X: Executable> LatestView< if let ValueWithLayout::Exchanged(value, Some(layout)) = value_with_layout { - let needs_exchange = does_value_need_exchange::( + let needs_exchange = self.does_value_need_exchange( &value, layout.as_ref(), delayed_write_set_ids, @@ -1659,7 +1675,7 @@ impl<'a, T: Transaction, S: TStateView, X: Executable> TAggregator impl<'a, T: Transaction, S: TStateView, X: Executable> TDelayedFieldView for LatestView<'a, T, S, X> { - type Identifier = T::Identifier; + type Identifier = DelayedFieldID; type ResourceGroupTag = T::Tag; type ResourceKey = T::Key; @@ -1770,7 +1786,7 @@ impl<'a, T: Transaction, S: TStateView, X: Executable> TDelayedFie ViewState::Sync(state) => state .captured_reads .borrow() - .get_read_values_with_delayed_fields(delayed_write_set_ids, skip), + .get_read_values_with_delayed_fields(self, delayed_write_set_ids, skip), ViewState::Unsync(state) => { let read_set = state.read_set.borrow(); self.get_reads_needing_exchange_sequential( @@ -1836,7 +1852,6 @@ mod test { write_set::TransactionWrite, }; use aptos_vm_types::resolver::TResourceView; - use bytes::Bytes; use claims::{assert_err_eq, assert_none, assert_ok_eq, assert_some_eq}; use move_core_types::value::{IdentifierMappingKind, MoveStructLayout, MoveTypeLayout}; use move_vm_types::{ @@ -1902,7 +1917,6 @@ mod test { impl BlockExecutableTransaction for TestTransactionType { type Event = MockEvent; - type Identifier = DelayedFieldID; type Key = KeyType; type Tag = u32; type Value = ValueType; @@ -2479,7 +2493,13 @@ mod test { } fn create_state_value(value: &Value, layout: &MoveTypeLayout) -> StateValue { - StateValue::new_legacy(value.simple_serialize(layout).unwrap().into()) + StateValue::new_legacy( + ValueSerDeContext::new() + .serialize(value, layout) + .unwrap() + .unwrap() + .into(), + ) } #[derive(Clone)] @@ -2520,7 +2540,7 @@ mod test { Value::u64(2), Value::u64(3), ])); - let state_value = StateValue::new_legacy(value.simple_serialize(&layout).unwrap().into()); + let state_value = create_state_value(&value, &layout); let (patched_state_value, identifiers) = latest_view .replace_values_with_identifiers(state_value.clone(), &layout) .unwrap(); @@ -2546,8 +2566,7 @@ mod test { let storage_layout = create_struct_layout(create_aggregator_storage_layout(MoveTypeLayout::U64)); let value = create_struct_value(create_aggregator_value_u64(25, 30)); - let state_value = - StateValue::new_legacy(value.simple_serialize(&storage_layout).unwrap().into()); + let state_value = create_state_value(&value, &storage_layout); let layout = create_struct_layout(create_aggregator_layout_u64()); let (patched_state_value, identifiers) = latest_view @@ -2585,8 +2604,7 @@ mod test { create_aggregator_value_u64(35, 65), create_aggregator_value_u64(0, 20), ])); - let state_value = - StateValue::new_legacy(value.simple_serialize(&storage_layout).unwrap().into()); + let state_value = create_state_value(&value, &storage_layout); let layout = create_struct_layout(create_vector_layout(create_aggregator_layout_u64())); let (patched_state_value, identifiers) = latest_view @@ -2619,12 +2637,7 @@ mod test { ])])); assert_eq!( patched_state_value, - StateValue::new_legacy( - patched_value - .simple_serialize(&storage_layout) - .unwrap() - .into() - ) + create_state_value(&patched_value, &storage_layout), ); let (final_state_value, identifiers) = latest_view .replace_identifiers_with_values(patched_state_value.bytes(), &layout) @@ -2649,8 +2662,7 @@ mod test { create_snapshot_value(Value::u128(35)), create_snapshot_value(Value::u128(0)), ])); - let state_value = - StateValue::new_legacy(value.simple_serialize(&storage_layout).unwrap().into()); + let state_value = create_state_value(&value, &storage_layout); let layout = create_struct_layout(create_vector_layout(create_snapshot_layout( MoveTypeLayout::U128, @@ -2682,12 +2694,7 @@ mod test { ])])); assert_eq!( patched_state_value, - StateValue::new_legacy( - patched_value - .simple_serialize(&storage_layout) - .unwrap() - .into() - ) + create_state_value(&patched_value, &storage_layout), ); let (final_state_value, identifiers2) = latest_view .replace_identifiers_with_values(patched_state_value.bytes(), &layout) @@ -2712,8 +2719,7 @@ mod test { create_derived_value("ab", 55), create_derived_value("c", 50), ])); - let state_value = - StateValue::new_legacy(value.simple_serialize(&storage_layout).unwrap().into()); + let state_value = create_state_value(&value, &storage_layout); let layout = create_struct_layout(create_vector_layout(create_derived_string_layout())); let (patched_state_value, identifiers) = latest_view @@ -2744,12 +2750,7 @@ mod test { ])])); assert_eq!( patched_state_value, - StateValue::new_legacy( - patched_value - .simple_serialize(&storage_layout) - .unwrap() - .into() - ) + create_state_value(&patched_value, &storage_layout), ); let (final_state_value, identifiers2) = latest_view .replace_identifiers_with_values(patched_state_value.bytes(), &layout) @@ -3100,18 +3101,13 @@ mod test { #[test] fn test_read_operations() { - let state_value_3 = StateValue::new_legacy(Bytes::from( - Value::u64(12321) - .simple_serialize(&MoveTypeLayout::U64) - .unwrap(), - )); + let state_value_3 = create_state_value(&Value::u64(12321), &MoveTypeLayout::U64); let mut data = HashMap::new(); data.insert(KeyType::(3, false), state_value_3.clone()); let storage_layout = create_struct_layout(create_aggregator_storage_layout(MoveTypeLayout::U64)); let value = create_struct_value(create_aggregator_value_u64(25, 30)); - let state_value_4 = - StateValue::new_legacy(value.simple_serialize(&storage_layout).unwrap().into()); + let state_value_4 = create_state_value(&value, &storage_layout); data.insert(KeyType::(4, false), state_value_4); let start_counter = 1000; @@ -3150,12 +3146,7 @@ mod test { ); let patched_value = create_struct_value(create_aggregator_value_u64(id.as_u64(), 30)); - let state_value_4 = StateValue::new_legacy( - patched_value - .simple_serialize(&storage_layout) - .unwrap() - .into(), - ); + let state_value_4 = create_state_value(&patched_value, &storage_layout); assert_eq!( views .get_resource_state_value(&KeyType::(4, false), Some(&layout)) @@ -3177,8 +3168,11 @@ mod test { let captured_reads = views.latest_view_par.take_parallel_reads(); assert!(captured_reads.validate_data_reads(holder.versioned_map.data(), 1)); // TODO(aggr_v2): what's up with this test case? - let _read_set_with_delayed_fields = - captured_reads.get_read_values_with_delayed_fields(&HashSet::new(), &HashSet::new()); + let _read_set_with_delayed_fields = captured_reads.get_read_values_with_delayed_fields( + &views.latest_view_par, + &HashSet::new(), + &HashSet::new(), + ); // TODO[agg_v2](test): This prints // read: (KeyType(4, false), Versioned(Err(StorageVersion), Some(Struct(Runtime([Struct(Runtime([Tagged(IdentifierMapping(Aggregator), U64), U64]))]))))) diff --git a/aptos-move/framework/move-stdlib/src/natives/bcs.rs b/aptos-move/framework/move-stdlib/src/natives/bcs.rs index 1ba7a7f17ca3f..d7cd0e9d258c4 100644 --- a/aptos-move/framework/move-stdlib/src/natives/bcs.rs +++ b/aptos-move/framework/move-stdlib/src/natives/bcs.rs @@ -21,7 +21,7 @@ use move_vm_runtime::native_functions::NativeFunction; use move_vm_types::{ loaded_data::runtime_types::Type, natives::function::{PartialVMError, PartialVMResult}, - value_serde::serialized_size_allowing_delayed_values, + value_serde::ValueSerDeContext, values::{values_impl::Reference, Struct, Value}, }; use smallvec::{smallvec, SmallVec}; @@ -69,7 +69,10 @@ fn native_to_bytes( // implement it in a more efficient way. let val = ref_to_val.read_ref()?; - let serialized_value = match val.simple_serialize(&layout) { + let serialized_value = match ValueSerDeContext::new() + .with_func_args_deserialization(context.function_value_extension()) + .serialize(&val, &layout)? + { Some(serialized_value) => serialized_value, None => { context.charge(BCS_TO_BYTES_FAILURE)?; @@ -131,7 +134,11 @@ fn serialized_size_impl( // implement it in a more efficient way. let value = reference.read_ref()?; let ty_layout = context.type_to_type_layout(ty)?; - serialized_size_allowing_delayed_values(&value, &ty_layout) + + ValueSerDeContext::new() + .with_func_args_deserialization(context.function_value_extension()) + .with_delayed_fields_serde() + .serialized_size(&value, &ty_layout) } fn native_constant_serialized_size( diff --git a/aptos-move/framework/src/natives/event.rs b/aptos-move/framework/src/natives/event.rs index 01de485b3f4fc..f970335350490 100644 --- a/aptos-move/framework/src/natives/event.rs +++ b/aptos-move/framework/src/natives/event.rs @@ -16,12 +16,9 @@ use move_binary_format::errors::PartialVMError; use move_core_types::{language_storage::TypeTag, value::MoveTypeLayout, vm_status::StatusCode}; use move_vm_runtime::native_functions::NativeFunction; #[cfg(feature = "testing")] -use move_vm_types::value_serde::deserialize_and_allow_delayed_values; -#[cfg(feature = "testing")] use move_vm_types::values::{Reference, Struct, StructRef}; use move_vm_types::{ - loaded_data::runtime_types::Type, value_serde::serialize_and_allow_delayed_values, - values::Value, + loaded_data::runtime_types::Type, value_serde::ValueSerDeContext, values::Value, }; use smallvec::{smallvec, SmallVec}; use std::collections::VecDeque; @@ -92,11 +89,16 @@ fn native_write_to_event_store( let ty_tag = context.type_to_type_tag(&ty)?; let (layout, has_aggregator_lifting) = context.type_to_type_layout_with_identifier_mappings(&ty)?; - let blob = serialize_and_allow_delayed_values(&msg, &layout)?.ok_or_else(|| { - SafeNativeError::InvariantViolation(PartialVMError::new( - StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR, - )) - })?; + + let blob = ValueSerDeContext::new() + .with_delayed_fields_serde() + .with_func_args_deserialization(context.function_value_extension()) + .serialize(&msg, &layout)? + .ok_or_else(|| { + SafeNativeError::InvariantViolation(PartialVMError::new( + StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR, + )) + })?; let key = bcs::from_bytes(guid.as_slice()).map_err(|_| { SafeNativeError::InvariantViolation(PartialVMError::new(StatusCode::EVENT_KEY_MISMATCH)) })?; @@ -147,16 +149,19 @@ fn native_emitted_events_by_handle( let key = EventKey::new(creation_num, addr); let ty_tag = context.type_to_type_tag(&ty)?; let ty_layout = context.type_to_type_layout(&ty)?; - let ctx = context.extensions_mut().get_mut::(); + let ctx = context.extensions().get::(); let events = ctx .emitted_v1_events(&key, &ty_tag) .into_iter() .map(|blob| { - Value::simple_deserialize(blob, &ty_layout).ok_or_else(|| { - SafeNativeError::InvariantViolation(PartialVMError::new( - StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR, - )) - }) + ValueSerDeContext::new() + .with_func_args_deserialization(context.function_value_extension()) + .deserialize(blob, &ty_layout) + .ok_or_else(|| { + SafeNativeError::InvariantViolation(PartialVMError::new( + StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR, + )) + }) }) .collect::>>()?; Ok(smallvec![Value::vector_for_testing_only(events)]) @@ -175,16 +180,21 @@ fn native_emitted_events( let ty_tag = context.type_to_type_tag(&ty)?; let ty_layout = context.type_to_type_layout(&ty)?; - let ctx = context.extensions_mut().get_mut::(); + let ctx = context.extensions().get::(); + let events = ctx .emitted_v2_events(&ty_tag) .into_iter() .map(|blob| { - deserialize_and_allow_delayed_values(blob, &ty_layout).ok_or_else(|| { - SafeNativeError::InvariantViolation(PartialVMError::new( - StatusCode::VALUE_DESERIALIZATION_ERROR, - )) - }) + ValueSerDeContext::new() + .with_func_args_deserialization(context.function_value_extension()) + .with_delayed_fields_serde() + .deserialize(blob, &ty_layout) + .ok_or_else(|| { + SafeNativeError::InvariantViolation(PartialVMError::new( + StatusCode::VALUE_DESERIALIZATION_ERROR, + )) + }) }) .collect::>>()?; Ok(smallvec![Value::vector_for_testing_only(events)]) @@ -234,12 +244,16 @@ fn native_write_module_event_to_store( } let (layout, has_identifier_mappings) = context.type_to_type_layout_with_identifier_mappings(&ty)?; - let blob = serialize_and_allow_delayed_values(&msg, &layout)?.ok_or_else(|| { - SafeNativeError::InvariantViolation( - PartialVMError::new(StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR) - .with_message("Event serialization failure".to_string()), - ) - })?; + let blob = ValueSerDeContext::new() + .with_delayed_fields_serde() + .with_func_args_deserialization(context.function_value_extension()) + .serialize(&msg, &layout)? + .ok_or_else(|| { + SafeNativeError::InvariantViolation( + PartialVMError::new(StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR) + .with_message("Event serialization failure".to_string()), + ) + })?; let ctx = context.extensions_mut().get_mut::(); ctx.events.push(( ContractEvent::new_v2(type_tag, blob), diff --git a/aptos-move/framework/src/natives/util.rs b/aptos-move/framework/src/natives/util.rs index da30858dc4edf..f39239491fae1 100644 --- a/aptos-move/framework/src/natives/util.rs +++ b/aptos-move/framework/src/natives/util.rs @@ -8,7 +8,9 @@ use aptos_native_interface::{ }; use move_core_types::gas_algebra::NumBytes; use move_vm_runtime::native_functions::NativeFunction; -use move_vm_types::{loaded_data::runtime_types::Type, values::Value}; +use move_vm_types::{ + loaded_data::runtime_types::Type, value_serde::ValueSerDeContext, values::Value, +}; use smallvec::{smallvec, SmallVec}; use std::collections::VecDeque; @@ -40,7 +42,10 @@ fn native_from_bytes( context.charge( UTIL_FROM_BYTES_BASE + UTIL_FROM_BYTES_PER_BYTE * NumBytes::new(bytes.len() as u64), )?; - let val = match Value::simple_deserialize(&bytes, &layout) { + let val = match ValueSerDeContext::new() + .with_func_args_deserialization(context.function_value_extension()) + .deserialize(&bytes, &layout) + { Some(val) => val, None => { return Err(SafeNativeError::Abort { diff --git a/aptos-move/framework/table-natives/src/lib.rs b/aptos-move/framework/table-natives/src/lib.rs index d306b7a025890..ab1e0a6dd9190 100644 --- a/aptos-move/framework/table-natives/src/lib.rs +++ b/aptos-move/framework/table-natives/src/lib.rs @@ -28,7 +28,7 @@ pub use move_table_extension::{TableHandle, TableInfo, TableResolver}; use move_vm_runtime::native_functions::NativeFunctionTable; use move_vm_types::{ loaded_data::runtime_types::Type, - value_serde::{deserialize_and_allow_delayed_values, serialize_and_allow_delayed_values}, + value_serde::{FunctionValueExtension, ValueSerDeContext}, values::{GlobalValue, Reference, StructRef, Value}, }; use sha3::{Digest, Sha3_256}; @@ -118,7 +118,10 @@ impl<'a> NativeTableContext<'a> { } /// Computes the change set from a NativeTableContext. - pub fn into_change_set(self) -> PartialVMResult { + pub fn into_change_set( + self, + function_value_extension: &impl FunctionValueExtension, + ) -> PartialVMResult { let NativeTableContext { table_data, .. } = self; let TableData { new_tables, @@ -141,10 +144,24 @@ impl<'a> NativeTableContext<'a> { match op { Op::New(val) => { - entries.insert(key, Op::New(serialize_value(&value_layout_info, &val)?)); + entries.insert( + key, + Op::New(serialize_value( + function_value_extension, + &value_layout_info, + &val, + )?), + ); }, Op::Modify(val) => { - entries.insert(key, Op::Modify(serialize_value(&value_layout_info, &val)?)); + entries.insert( + key, + Op::Modify(serialize_value( + function_value_extension, + &value_layout_info, + &val, + )?), + ); }, Op::Delete => { entries.insert(key, Op::Delete); @@ -204,26 +221,33 @@ impl LayoutInfo { impl Table { fn get_or_create_global_value( &mut self, - context: &NativeTableContext, + function_value_extension: &dyn FunctionValueExtension, + table_context: &NativeTableContext, key: Vec, ) -> PartialVMResult<(&mut GlobalValue, Option>)> { Ok(match self.content.entry(key) { Entry::Vacant(entry) => { // If there is an identifier mapping, we need to pass layout to // ensure it gets recorded. - let data = context.resolver.resolve_table_entry_bytes_with_layout( - &self.handle, - entry.key(), - if self.value_layout_info.has_identifier_mappings { - Some(&self.value_layout_info.layout) - } else { - None - }, - )?; + let data = table_context + .resolver + .resolve_table_entry_bytes_with_layout( + &self.handle, + entry.key(), + if self.value_layout_info.has_identifier_mappings { + Some(&self.value_layout_info.layout) + } else { + None + }, + )?; let (gv, loaded) = match data { Some(val_bytes) => { - let val = deserialize_value(&self.value_layout_info, &val_bytes)?; + let val = deserialize_value( + function_value_extension, + &val_bytes, + &self.value_layout_info, + )?; ( GlobalValue::cached(val)?, Some(NumBytes::new(val_bytes.len() as u64)), @@ -341,6 +365,7 @@ fn native_add_box( context.charge(ADD_BOX_BASE)?; + let function_value_extension = context.function_value_extension(); let table_context = context.extensions().get::(); let mut table_data = table_context.table_data.borrow_mut(); @@ -350,10 +375,11 @@ fn native_add_box( let table = table_data.get_or_create_table(context, handle, &ty_args[0], &ty_args[2])?; - let key_bytes = serialize_key(&table.key_layout, &key)?; + let key_bytes = serialize_key(function_value_extension, &table.key_layout, &key)?; let key_cost = ADD_BOX_PER_BYTE_SERIALIZED * NumBytes::new(key_bytes.len() as u64); - let (gv, loaded) = table.get_or_create_global_value(table_context, key_bytes)?; + let (gv, loaded) = + table.get_or_create_global_value(function_value_extension, table_context, key_bytes)?; let res = match gv.move_to(val) { Ok(_) => Ok(smallvec![]), @@ -381,6 +407,7 @@ fn native_borrow_box( context.charge(BORROW_BOX_BASE)?; + let function_value_extension = context.function_value_extension(); let table_context = context.extensions().get::(); let mut table_data = table_context.table_data.borrow_mut(); @@ -389,10 +416,11 @@ fn native_borrow_box( let table = table_data.get_or_create_table(context, handle, &ty_args[0], &ty_args[2])?; - let key_bytes = serialize_key(&table.key_layout, &key)?; + let key_bytes = serialize_key(function_value_extension, &table.key_layout, &key)?; let key_cost = BORROW_BOX_PER_BYTE_SERIALIZED * NumBytes::new(key_bytes.len() as u64); - let (gv, loaded) = table.get_or_create_global_value(table_context, key_bytes)?; + let (gv, loaded) = + table.get_or_create_global_value(function_value_extension, table_context, key_bytes)?; let res = match gv.borrow_global() { Ok(ref_val) => Ok(smallvec![ref_val]), @@ -420,6 +448,7 @@ fn native_contains_box( context.charge(CONTAINS_BOX_BASE)?; + let function_value_extension = context.function_value_extension(); let table_context = context.extensions().get::(); let mut table_data = table_context.table_data.borrow_mut(); @@ -428,10 +457,11 @@ fn native_contains_box( let table = table_data.get_or_create_table(context, handle, &ty_args[0], &ty_args[2])?; - let key_bytes = serialize_key(&table.key_layout, &key)?; + let key_bytes = serialize_key(function_value_extension, &table.key_layout, &key)?; let key_cost = CONTAINS_BOX_PER_BYTE_SERIALIZED * NumBytes::new(key_bytes.len() as u64); - let (gv, loaded) = table.get_or_create_global_value(table_context, key_bytes)?; + let (gv, loaded) = + table.get_or_create_global_value(function_value_extension, table_context, key_bytes)?; let exists = Value::bool(gv.exists()?); drop(table_data); @@ -453,6 +483,7 @@ fn native_remove_box( context.charge(REMOVE_BOX_BASE)?; + let function_value_extension = context.function_value_extension(); let table_context = context.extensions().get::(); let mut table_data = table_context.table_data.borrow_mut(); @@ -461,10 +492,11 @@ fn native_remove_box( let table = table_data.get_or_create_table(context, handle, &ty_args[0], &ty_args[2])?; - let key_bytes = serialize_key(&table.key_layout, &key)?; + let key_bytes = serialize_key(function_value_extension, &table.key_layout, &key)?; let key_cost = REMOVE_BOX_PER_BYTE_SERIALIZED * NumBytes::new(key_bytes.len() as u64); - let (gv, loaded) = table.get_or_create_global_value(table_context, key_bytes)?; + let (gv, loaded) = + table.get_or_create_global_value(function_value_extension, table_context, key_bytes)?; let res = match gv.move_from() { Ok(val) => Ok(smallvec![val]), Err(_) => Err(SafeNativeError::Abort { @@ -528,34 +560,55 @@ fn get_table_handle(table: &StructRef) -> PartialVMResult { Ok(TableHandle(handle)) } -fn serialize_key(layout: &MoveTypeLayout, key: &Value) -> PartialVMResult> { - key.simple_serialize(layout) +fn serialize_key( + function_value_extension: &dyn FunctionValueExtension, + layout: &MoveTypeLayout, + key: &Value, +) -> PartialVMResult> { + ValueSerDeContext::new() + .with_func_args_deserialization(function_value_extension) + .serialize(key, layout)? .ok_or_else(|| partial_extension_error("cannot serialize table key")) } fn serialize_value( + function_value_extension: &dyn FunctionValueExtension, layout_info: &LayoutInfo, val: &Value, ) -> PartialVMResult<(Bytes, Option>)> { let serialization_result = if layout_info.has_identifier_mappings { // Value contains delayed fields, so we should be able to serialize it. - serialize_and_allow_delayed_values(val, layout_info.layout.as_ref())? + ValueSerDeContext::new() + .with_delayed_fields_serde() + .with_func_args_deserialization(function_value_extension) + .serialize(val, layout_info.layout.as_ref())? .map(|bytes| (bytes.into(), Some(layout_info.layout.clone()))) } else { // No delayed fields, make sure serialization fails if there are any // native values. - val.simple_serialize(layout_info.layout.as_ref()) + ValueSerDeContext::new() + .with_func_args_deserialization(function_value_extension) + .serialize(val, layout_info.layout.as_ref())? .map(|bytes| (bytes.into(), None)) }; serialization_result.ok_or_else(|| partial_extension_error("cannot serialize table value")) } -fn deserialize_value(layout_info: &LayoutInfo, bytes: &[u8]) -> PartialVMResult { +fn deserialize_value( + function_value_extension: &dyn FunctionValueExtension, + bytes: &[u8], + layout_info: &LayoutInfo, +) -> PartialVMResult { let layout = layout_info.layout.as_ref(); let deserialization_result = if layout_info.has_identifier_mappings { - deserialize_and_allow_delayed_values(bytes, layout) + ValueSerDeContext::new() + .with_func_args_deserialization(function_value_extension) + .with_delayed_fields_serde() + .deserialize(bytes, layout) } else { - Value::simple_deserialize(bytes, layout) + ValueSerDeContext::new() + .with_func_args_deserialization(function_value_extension) + .deserialize(bytes, layout) }; deserialization_result.ok_or_else(|| partial_extension_error("cannot deserialize table value")) } diff --git a/testsuite/fuzzer/fuzz/fuzz_targets/move/value_deserialize.rs b/testsuite/fuzzer/fuzz/fuzz_targets/move/value_deserialize.rs index 3cca926099b3b..fcd5cf6ebb645 100644 --- a/testsuite/fuzzer/fuzz/fuzz_targets/move/value_deserialize.rs +++ b/testsuite/fuzzer/fuzz/fuzz_targets/move/value_deserialize.rs @@ -5,7 +5,7 @@ use arbitrary::Arbitrary; use libfuzzer_sys::fuzz_target; use move_core_types::value::MoveTypeLayout; -use move_vm_types::values::Value; +use move_vm_types::value_serde::ValueSerDeContext; mod utils; use utils::helpers::is_valid_layout; @@ -19,5 +19,6 @@ fuzz_target!(|fuzz_data: FuzzData| { if fuzz_data.data.is_empty() || !is_valid_layout(&fuzz_data.layout) { return; } - let _ = Value::simple_deserialize(&fuzz_data.data, &fuzz_data.layout); + // TODO: How do we fuzz function resolution? + let _ = ValueSerDeContext::new().deserialize(&fuzz_data.data, &fuzz_data.layout); }); diff --git a/third_party/move/extensions/move-table-extension/src/lib.rs b/third_party/move/extensions/move-table-extension/src/lib.rs index b9235d3e71de9..3c876513723d1 100644 --- a/third_party/move/extensions/move-table-extension/src/lib.rs +++ b/third_party/move/extensions/move-table-extension/src/lib.rs @@ -26,6 +26,7 @@ use move_vm_types::{ loaded_data::runtime_types::Type, natives::function::NativeResult, pop_arg, + value_serde::{FunctionValueExtension, ValueSerDeContext}, values::{GlobalValue, Reference, StructRef, Value}, }; use sha3::{Digest, Sha3_256}; @@ -154,7 +155,10 @@ impl<'a> NativeTableContext<'a> { } /// Computes the change set from a NativeTableContext. - pub fn into_change_set(self) -> PartialVMResult { + pub fn into_change_set( + self, + function_value_extension: &impl FunctionValueExtension, + ) -> PartialVMResult { let NativeTableContext { table_data, .. } = self; let TableData { new_tables, @@ -177,11 +181,11 @@ impl<'a> NativeTableContext<'a> { match op { Op::New(val) => { - let bytes = serialize(&value_layout, &val)?; + let bytes = serialize(function_value_extension, &value_layout, &val)?; entries.insert(key, Op::New(bytes.into())); }, Op::Modify(val) => { - let bytes = serialize(&value_layout, &val)?; + let bytes = serialize(function_value_extension, &value_layout, &val)?; entries.insert(key, Op::Modify(bytes.into())); }, Op::Delete => { @@ -231,18 +235,19 @@ impl TableData { impl Table { fn get_or_create_global_value( &mut self, - context: &NativeTableContext, + function_value_extension: &dyn FunctionValueExtension, + table_context: &NativeTableContext, key: Vec, ) -> PartialVMResult<(&mut GlobalValue, Option>)> { Ok(match self.content.entry(key) { Entry::Vacant(entry) => { - let (gv, loaded) = match context.resolver.resolve_table_entry_bytes_with_layout( - &self.handle, - entry.key(), - None, - )? { + let (gv, loaded) = match table_context + .resolver + .resolve_table_entry_bytes_with_layout(&self.handle, entry.key(), None)? + { Some(val_bytes) => { - let val = deserialize(&self.value_layout, &val_bytes)?; + let val = + deserialize(function_value_extension, &val_bytes, &self.value_layout)?; ( GlobalValue::cached(val)?, Some(NumBytes::new(val_bytes.len() as u64)), @@ -390,6 +395,7 @@ fn native_add_box( assert_eq!(ty_args.len(), 3); assert_eq!(args.len(), 3); + let function_value_extension = context.function_value_extension(); let table_context = context.extensions().get::(); let mut table_data = table_context.table_data.borrow_mut(); @@ -401,10 +407,11 @@ fn native_add_box( let table = table_data.get_or_create_table(context, handle, &ty_args[0], &ty_args[2])?; - let key_bytes = serialize(&table.key_layout, &key)?; + let key_bytes = serialize(function_value_extension, &table.key_layout, &key)?; cost += gas_params.per_byte_serialized * NumBytes::new(key_bytes.len() as u64); - let (gv, loaded) = table.get_or_create_global_value(table_context, key_bytes)?; + let (gv, loaded) = + table.get_or_create_global_value(function_value_extension, table_context, key_bytes)?; cost += common_gas_params.calculate_load_cost(loaded); match gv.move_to(val) { @@ -440,6 +447,7 @@ fn native_borrow_box( assert_eq!(ty_args.len(), 3); assert_eq!(args.len(), 2); + let function_value_extension = context.function_value_extension(); let table_context = context.extensions().get::(); let mut table_data = table_context.table_data.borrow_mut(); @@ -450,10 +458,11 @@ fn native_borrow_box( let mut cost = gas_params.base; - let key_bytes = serialize(&table.key_layout, &key)?; + let key_bytes = serialize(function_value_extension, &table.key_layout, &key)?; cost += gas_params.per_byte_serialized * NumBytes::new(key_bytes.len() as u64); - let (gv, loaded) = table.get_or_create_global_value(table_context, key_bytes)?; + let (gv, loaded) = + table.get_or_create_global_value(function_value_extension, table_context, key_bytes)?; cost += common_gas_params.calculate_load_cost(loaded); match gv.borrow_global() { @@ -489,6 +498,7 @@ fn native_contains_box( assert_eq!(ty_args.len(), 3); assert_eq!(args.len(), 2); + let function_value_extension = context.function_value_extension(); let table_context = context.extensions().get::(); let mut table_data = table_context.table_data.borrow_mut(); @@ -499,10 +509,11 @@ fn native_contains_box( let mut cost = gas_params.base; - let key_bytes = serialize(&table.key_layout, &key)?; + let key_bytes = serialize(function_value_extension, &table.key_layout, &key)?; cost += gas_params.per_byte_serialized * NumBytes::new(key_bytes.len() as u64); - let (gv, loaded) = table.get_or_create_global_value(table_context, key_bytes)?; + let (gv, loaded) = + table.get_or_create_global_value(function_value_extension, table_context, key_bytes)?; cost += common_gas_params.calculate_load_cost(loaded); let exists = Value::bool(gv.exists()?); @@ -537,6 +548,7 @@ fn native_remove_box( assert_eq!(ty_args.len(), 3); assert_eq!(args.len(), 2); + let function_value_extension = context.function_value_extension(); let table_context = context.extensions().get::(); let mut table_data = table_context.table_data.borrow_mut(); @@ -547,10 +559,11 @@ fn native_remove_box( let mut cost = gas_params.base; - let key_bytes = serialize(&table.key_layout, &key)?; + let key_bytes = serialize(function_value_extension, &table.key_layout, &key)?; cost += gas_params.per_byte_serialized * NumBytes::new(key_bytes.len() as u64); - let (gv, loaded) = table.get_or_create_global_value(table_context, key_bytes)?; + let (gv, loaded) = + table.get_or_create_global_value(function_value_extension, table_context, key_bytes)?; cost += common_gas_params.calculate_load_cost(loaded); match gv.move_from() { @@ -685,13 +698,25 @@ fn get_table_handle(table: &StructRef) -> PartialVMResult { Ok(TableHandle(handle)) } -fn serialize(layout: &MoveTypeLayout, val: &Value) -> PartialVMResult> { - val.simple_serialize(layout) +fn serialize( + function_value_extension: &dyn FunctionValueExtension, + layout: &MoveTypeLayout, + val: &Value, +) -> PartialVMResult> { + ValueSerDeContext::new() + .with_func_args_deserialization(function_value_extension) + .serialize(val, layout)? .ok_or_else(|| partial_extension_error("cannot serialize table key or value")) } -fn deserialize(layout: &MoveTypeLayout, bytes: &[u8]) -> PartialVMResult { - Value::simple_deserialize(bytes, layout) +fn deserialize( + function_value_extension: &dyn FunctionValueExtension, + bytes: &[u8], + layout: &MoveTypeLayout, +) -> PartialVMResult { + ValueSerDeContext::new() + .with_func_args_deserialization(function_value_extension) + .deserialize(bytes, layout) .ok_or_else(|| partial_extension_error("cannot deserialize table key or value")) } diff --git a/third_party/move/move-stdlib/src/natives/bcs.rs b/third_party/move/move-stdlib/src/natives/bcs.rs index a9062a4cbbfad..c1722c0165fa1 100644 --- a/third_party/move/move-stdlib/src/natives/bcs.rs +++ b/third_party/move/move-stdlib/src/natives/bcs.rs @@ -13,6 +13,7 @@ use move_vm_types::{ loaded_data::runtime_types::Type, natives::function::NativeResult, pop_arg, + value_serde::ValueSerDeContext, values::{values_impl::Reference, Value}, }; use smallvec::smallvec; @@ -62,7 +63,10 @@ fn native_to_bytes( }; // serialize value let val = ref_to_val.read_ref()?; - let serialized_value = match val.simple_serialize(&layout) { + let serialized_value = match ValueSerDeContext::new() + .with_func_args_deserialization(context.function_value_extension()) + .serialize(&val, &layout)? + { Some(serialized_value) => serialized_value, None => { cost += gas_params.failure; diff --git a/third_party/move/move-vm/integration-tests/src/tests/mod.rs b/third_party/move/move-vm/integration-tests/src/tests/mod.rs index 23ca581ad7e71..18caef5ac3192 100644 --- a/third_party/move/move-vm/integration-tests/src/tests/mod.rs +++ b/third_party/move/move-vm/integration-tests/src/tests/mod.rs @@ -11,6 +11,7 @@ mod instantiation_tests; mod invariant_violation_tests; mod leak_tests; mod loader_tests; +mod module_storage_tests; mod mutated_accounts_tests; mod native_tests; mod nested_loop_tests; diff --git a/third_party/move/move-vm/integration-tests/src/tests/module_storage_tests.rs b/third_party/move/move-vm/integration-tests/src/tests/module_storage_tests.rs new file mode 100644 index 0000000000000..d5a1f80b228fd --- /dev/null +++ b/third_party/move/move-vm/integration-tests/src/tests/module_storage_tests.rs @@ -0,0 +1,137 @@ +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use crate::compiler::{as_module, compile_units}; +use bytes::Bytes; +use move_binary_format::file_format::{Ability, AbilitySet}; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::Identifier, + language_storage::{ModuleId, TypeTag}, +}; +use move_vm_runtime::{ + AsFunctionValueExtension, AsUnsyncModuleStorage, RuntimeEnvironment, WithRuntimeEnvironment, +}; +use move_vm_test_utils::InMemoryStorage; +use move_vm_types::{ + loaded_data::runtime_types::{AbilityInfo, StructIdentifier, StructNameIndex, TypeBuilder}, + value_serde::FunctionValueExtension, +}; +use std::str::FromStr; + +#[cfg(test)] +fn module_bytes(module_code: &str) -> Bytes { + let compiled_module = as_module(compile_units(module_code).unwrap().pop().unwrap()); + let mut bytes = vec![]; + compiled_module.serialize(&mut bytes).unwrap(); + bytes.into() +} + +#[test] +fn test_function_value_extension() { + let mut module_bytes_storage = InMemoryStorage::new(); + + let code = r#" + module 0x1::test { + struct Foo {} + + fun b() { } + fun c(a: u64, _foo: &Foo): u64 { a } + fun d(_a: A, b: u64, _c: C): u64 { b } + } + "#; + let bytes = module_bytes(code); + let test_id = ModuleId::new(AccountAddress::ONE, Identifier::new("test").unwrap()); + module_bytes_storage.add_module_bytes(&AccountAddress::ONE, ident_str!("test"), bytes); + + let code = r#" + module 0x1::other_test { + struct Bar has drop {} + } + "#; + let bytes = module_bytes(code); + let other_test_id = ModuleId::new(AccountAddress::ONE, Identifier::new("other_test").unwrap()); + module_bytes_storage.add_module_bytes(&AccountAddress::ONE, ident_str!("other_test"), bytes); + + let runtime_environment = RuntimeEnvironment::new(vec![]); + let module_storage = module_bytes_storage.into_unsync_module_storage(runtime_environment); + let function_value_extension = module_storage.as_function_value_extension(); + + let result = function_value_extension.get_function_arg_tys( + &ModuleId::new(AccountAddress::ONE, Identifier::new("test").unwrap()), + ident_str!("a"), + vec![], + ); + assert!(result.is_err()); + + let mut types = function_value_extension + .get_function_arg_tys(&test_id, ident_str!("c"), vec![]) + .unwrap(); + assert_eq!(types.len(), 2); + + let ty_builder = TypeBuilder::with_limits(100, 100); + let foo_ty = types.pop().unwrap(); + let name = module_storage + .runtime_environment() + .idx_to_struct_name_for_test(StructNameIndex(0)) + .unwrap(); + assert_eq!(name, StructIdentifier { + module: test_id.clone(), + name: Identifier::new("Foo").unwrap(), + }); + assert_eq!( + foo_ty, + ty_builder + .create_ref_ty( + &ty_builder + .create_struct_ty(StructNameIndex(0), AbilityInfo::struct_(AbilitySet::EMPTY)), + false + ) + .unwrap() + ); + let u64_ty = types.pop().unwrap(); + assert_eq!(u64_ty, ty_builder.create_u64_ty()); + + // Generic function without type parameters should fail. + let result = function_value_extension.get_function_arg_tys( + &ModuleId::new(AccountAddress::ONE, Identifier::new("test").unwrap()), + ident_str!("d"), + vec![], + ); + assert!(result.is_err()); + + let mut types = function_value_extension + .get_function_arg_tys(&test_id, ident_str!("d"), vec![ + TypeTag::from_str("0x1::other_test::Bar").unwrap(), + TypeTag::Vector(Box::new(TypeTag::U8)), + ]) + .unwrap(); + assert_eq!(types.len(), 3); + + let vec_ty = types.pop().unwrap(); + assert_eq!( + vec_ty, + ty_builder + .create_vec_ty(&ty_builder.create_u8_ty()) + .unwrap() + ); + let u64_ty = types.pop().unwrap(); + assert_eq!(u64_ty, ty_builder.create_u64_ty()); + let bar_ty = types.pop().unwrap(); + let name = module_storage + .runtime_environment() + .idx_to_struct_name_for_test(StructNameIndex(1)) + .unwrap(); + assert_eq!(name, StructIdentifier { + module: other_test_id, + name: Identifier::new("Bar").unwrap(), + }); + assert_eq!( + bar_ty, + ty_builder.create_struct_ty( + StructNameIndex(1), + AbilityInfo::struct_(AbilitySet::from_u8(Ability::Drop as u8).unwrap()) + ) + ); +} diff --git a/third_party/move/move-vm/runtime/src/data_cache.rs b/third_party/move/move-vm/runtime/src/data_cache.rs index 0038b783d457b..197516b5d1dcd 100644 --- a/third_party/move/move-vm/runtime/src/data_cache.rs +++ b/third_party/move/move-vm/runtime/src/data_cache.rs @@ -5,6 +5,7 @@ use crate::{ loader::{LegacyModuleStorageAdapter, Loader}, logging::expect_no_verification_errors, + storage::module_storage::FunctionValueExtensionAdapter, ModuleStorage, }; use bytes::Bytes; @@ -26,7 +27,7 @@ use move_core_types::{ use move_vm_types::{ loaded_data::runtime_types::Type, resolver::MoveResolver, - value_serde::deserialize_and_allow_delayed_values, + value_serde::ValueSerDeContext, values::{GlobalValue, Value}, }; use sha3::{Digest, Sha3_256}; @@ -118,8 +119,10 @@ impl<'r> TransactionDataCache<'r> { ) -> PartialVMResult { let resource_converter = |value: Value, layout: MoveTypeLayout, _: bool| -> PartialVMResult { - value - .simple_serialize(&layout) + let function_value_extension = FunctionValueExtensionAdapter { module_storage }; + ValueSerDeContext::new() + .with_func_args_deserialization(&function_value_extension) + .serialize(&value, &layout)? .map(Into::into) .ok_or_else(|| { PartialVMError::new(StatusCode::INTERNAL_TYPE_ERROR) @@ -275,9 +278,14 @@ impl<'r> TransactionDataCache<'r> { }; load_res = Some(NumBytes::new(bytes_loaded as u64)); + let function_value_extension = FunctionValueExtensionAdapter { module_storage }; let gv = match data { Some(blob) => { - let val = match deserialize_and_allow_delayed_values(&blob, &ty_layout) { + let val = match ValueSerDeContext::new() + .with_func_args_deserialization(&function_value_extension) + .with_delayed_fields_serde() + .deserialize(&blob, &ty_layout) + { Some(val) => val, None => { let msg = diff --git a/third_party/move/move-vm/runtime/src/lib.rs b/third_party/move/move-vm/runtime/src/lib.rs index e9dd6f69a1f20..b4e7641d52cfe 100644 --- a/third_party/move/move-vm/runtime/src/lib.rs +++ b/third_party/move/move-vm/runtime/src/lib.rs @@ -34,7 +34,7 @@ mod frame_type_cache; mod runtime_type_checks; mod storage; -pub use loader::{LoadedFunction, Module, Script}; +pub use loader::{Function, LoadedFunction, Module, Script}; #[cfg(any(test, feature = "testing"))] pub use storage::implementations::unreachable_code_storage; pub use storage::{ @@ -46,6 +46,6 @@ pub use storage::{ unsync_code_storage::{AsUnsyncCodeStorage, UnsyncCodeStorage}, unsync_module_storage::{AsUnsyncModuleStorage, BorrowedOrOwned, UnsyncModuleStorage}, }, - module_storage::{ambassador_impl_ModuleStorage, ModuleStorage}, + module_storage::{ambassador_impl_ModuleStorage, AsFunctionValueExtension, ModuleStorage}, publishing::{StagingModuleStorage, VerifiedModuleBundle}, }; diff --git a/third_party/move/move-vm/runtime/src/loader/mod.rs b/third_party/move/move-vm/runtime/src/loader/mod.rs index 1777fd5ac9b9b..0bafef00c1f06 100644 --- a/third_party/move/move-vm/runtime/src/loader/mod.rs +++ b/third_party/move/move-vm/runtime/src/loader/mod.rs @@ -54,11 +54,12 @@ use crate::{ loader::modules::{StructVariantInfo, VariantFieldInfo}, native_functions::NativeFunctions, storage::{ - loader::LoaderV2, struct_name_index_map::StructNameIndexMap, ty_cache::StructInfoCache, + loader::LoaderV2, module_storage::FunctionValueExtensionAdapter, + struct_name_index_map::StructNameIndexMap, ty_cache::StructInfoCache, }, }; -pub use function::LoadedFunction; -pub(crate) use function::{Function, FunctionHandle, FunctionInstantiation, LoadedFunctionOwner}; +pub use function::{Function, LoadedFunction}; +pub(crate) use function::{FunctionHandle, FunctionInstantiation, LoadedFunctionOwner}; pub use modules::Module; pub(crate) use modules::{LegacyModuleCache, LegacyModuleStorage, LegacyModuleStorageAdapter}; use move_binary_format::file_format::{ @@ -66,7 +67,10 @@ use move_binary_format::file_format::{ VariantFieldInstantiationIndex, VariantIndex, }; use move_vm_metrics::{Timer, VM_TIMER}; -use move_vm_types::loaded_data::runtime_types::{StructLayout, TypeBuilder}; +use move_vm_types::{ + loaded_data::runtime_types::{StructLayout, TypeBuilder}, + value_serde::FunctionValueExtension, +}; pub use script::Script; pub(crate) use script::ScriptCache; use type_loader::intern_type; @@ -308,8 +312,7 @@ impl Loader { .resolve_module_and_function_by_name(module_id, function_name) .map_err(|err| err.finish(Location::Undefined)) }, - Loader::V2(loader) => loader.load_function_without_ty_args( - module_storage, + Loader::V2(_) => module_storage.fetch_function_definition( module_id.address(), module_id.name(), function_name, @@ -330,8 +333,8 @@ impl Loader { ) -> VMResult { match self { Self::V1(loader) => loader.load_type(ty_tag, data_store, module_store), - Self::V2(loader) => loader - .load_ty(module_storage, ty_tag) + Self::V2(_) => module_storage + .fetch_ty(ty_tag) .map_err(|e| e.finish(Location::Undefined)), } } @@ -356,8 +359,7 @@ impl Loader { Loader::V1(_) => { module_store.get_struct_type_by_identifier(&struct_name.name, &struct_name.module) }, - Loader::V2(loader) => loader.load_struct_ty( - module_storage, + Loader::V2(_) => module_storage.fetch_struct_ty( struct_name.module.address(), struct_name.module.name(), struct_name.name.as_ident_str(), @@ -1295,13 +1297,9 @@ impl<'a> Resolver<'a> { Loader::V1(_) => self .module_store .resolve_module_and_function_by_name(module_id, function_name)?, - Loader::V2(loader) => loader - .load_function_without_ty_args( - self.module_storage, - module_id.address(), - module_id.name(), - function_name, - ) + Loader::V2(_) => self + .module_storage + .fetch_function_definition(module_id.address(), module_id.name(), function_name) .map_err(|_| { // Note: legacy loader implementation used this error, so we need to remap. PartialVMError::new(StatusCode::FUNCTION_RESOLUTION_FAILURE).with_message( @@ -1652,6 +1650,20 @@ impl<'a> Resolver<'a> { } } +impl<'a> FunctionValueExtension for Resolver<'a> { + fn get_function_arg_tys( + &self, + module_id: &ModuleId, + function_name: &IdentStr, + ty_arg_tags: Vec, + ) -> PartialVMResult> { + let function_value_extension = FunctionValueExtensionAdapter { + module_storage: self.module_storage, + }; + function_value_extension.get_function_arg_tys(module_id, function_name, ty_arg_tags) + } +} + /// Maximal depth of a value in terms of type depth. pub const VALUE_DEPTH_MAX: u64 = 128; diff --git a/third_party/move/move-vm/runtime/src/native_functions.rs b/third_party/move/move-vm/runtime/src/native_functions.rs index 8cce249a6ebdd..214115c30b4e5 100644 --- a/third_party/move/move-vm/runtime/src/native_functions.rs +++ b/third_party/move/move-vm/runtime/src/native_functions.rs @@ -21,7 +21,8 @@ use move_core_types::{ vm_status::StatusCode, }; use move_vm_types::{ - loaded_data::runtime_types::Type, natives::function::NativeResult, values::Value, + loaded_data::runtime_types::Type, natives::function::NativeResult, + value_serde::FunctionValueExtension, values::Value, }; use std::{ collections::{HashMap, VecDeque}, @@ -197,6 +198,10 @@ impl<'a, 'b, 'c> NativeContext<'a, 'b, 'c> { self.traversal_context } + pub fn function_value_extension(&self) -> &dyn FunctionValueExtension { + self.resolver + } + pub fn load_function( &mut self, module_id: &ModuleId, @@ -220,13 +225,10 @@ impl<'a, 'b, 'c> NativeContext<'a, 'b, 'c> { .module_store() .resolve_module_and_function_by_name(module_id, function_name)? }, - Loader::V2(loader) => loader - .load_function_without_ty_args( - self.resolver.module_storage(), - module_id.address(), - module_id.name(), - function_name, - ) + Loader::V2(_) => self + .resolver + .module_storage() + .fetch_function_definition(module_id.address(), module_id.name(), function_name) // TODO(loader_v2): // Keeping this consistent with loader V1 implementation which returned that // error. Check if we can avoid remapping by replaying transactions. diff --git a/third_party/move/move-vm/runtime/src/runtime.rs b/third_party/move/move-vm/runtime/src/runtime.rs index 0ad885bca6c11..d33a49edfd645 100644 --- a/third_party/move/move-vm/runtime/src/runtime.rs +++ b/third_party/move/move-vm/runtime/src/runtime.rs @@ -12,7 +12,7 @@ use crate::{ native_extensions::NativeContextExtensions, session::SerializedReturnValues, storage::{code_storage::CodeStorage, module_storage::ModuleStorage}, - RuntimeEnvironment, + AsFunctionValueExtension, RuntimeEnvironment, }; use move_binary_format::{ access::ModuleAccess, @@ -29,6 +29,7 @@ use move_vm_metrics::{Timer, VM_TIMER}; use move_vm_types::{ gas::GasMeter, loaded_data::runtime_types::Type, + value_serde::ValueSerDeContext, values::{Locals, Reference, VMValueCast, Value}, }; use std::{borrow::Borrow, collections::BTreeSet, sync::Arc}; @@ -270,7 +271,11 @@ impl VMRuntime { return Err(deserialization_error()); } - match Value::simple_deserialize(arg.borrow(), &layout) { + let function_value_extension = module_storage.as_function_value_extension(); + match ValueSerDeContext::new() + .with_func_args_deserialization(&function_value_extension) + .deserialize(arg.borrow(), &layout) + { Some(val) => Ok(val), None => Err(deserialization_error()), } @@ -354,8 +359,10 @@ impl VMRuntime { return Err(serialization_error()); } - let bytes = value - .simple_serialize(&layout) + let function_value_extension = module_storage.as_function_value_extension(); + let bytes = ValueSerDeContext::new() + .with_func_args_deserialization(&function_value_extension) + .serialize(&value, &layout)? .ok_or_else(serialization_error)?; Ok((bytes, layout)) } diff --git a/third_party/move/move-vm/runtime/src/storage/code_storage.rs b/third_party/move/move-vm/runtime/src/storage/code_storage.rs index 5274a52543186..8afcef7777d32 100644 --- a/third_party/move/move-vm/runtime/src/storage/code_storage.rs +++ b/third_party/move/move-vm/runtime/src/storage/code_storage.rs @@ -1,12 +1,12 @@ // Copyright (c) The Move Contributors // SPDX-License-Identifier: Apache-2.0 -use crate::{loader::Script, logging::expect_no_verification_errors, ModuleStorage}; +use crate::{loader::Script, ModuleStorage}; use ambassador::delegatable_trait; use move_binary_format::{errors::VMResult, file_format::CompiledScript}; use move_vm_types::{ code::{Code, ScriptCache}, - module_linker_error, sha3_256, + sha3_256, }; use std::sync::Arc; @@ -72,9 +72,7 @@ where .immediate_dependencies_iter() .map(|(addr, name)| { // Since module is stored on-chain, we should not see any verification errors here. - self.fetch_verified_module(addr, name) - .map_err(expect_no_verification_errors)? - .ok_or_else(|| module_linker_error!(addr, name)) + self.fetch_existing_verified_module(addr, name) }) .collect::>>()?; let verified_script = self diff --git a/third_party/move/move-vm/runtime/src/storage/environment.rs b/third_party/move/move-vm/runtime/src/storage/environment.rs index 7d5ae85f0640e..9a813576dbdd4 100644 --- a/third_party/move/move-vm/runtime/src/storage/environment.rs +++ b/third_party/move/move-vm/runtime/src/storage/environment.rs @@ -295,6 +295,15 @@ impl RuntimeEnvironment { ) -> PartialVMResult { self.struct_name_index_map.struct_name_to_idx(&struct_name) } + + /// Test-only function to be able to check cached struct names. + #[cfg(any(test, feature = "testing"))] + pub fn idx_to_struct_name_for_test( + &self, + idx: StructNameIndex, + ) -> PartialVMResult { + self.struct_name_index_map.idx_to_struct_name(idx) + } } impl Clone for RuntimeEnvironment { diff --git a/third_party/move/move-vm/runtime/src/storage/implementations/unsync_code_storage.rs b/third_party/move/move-vm/runtime/src/storage/implementations/unsync_code_storage.rs index 19f6f1ae55fee..b559a6c6ab12f 100644 --- a/third_party/move/move-vm/runtime/src/storage/implementations/unsync_code_storage.rs +++ b/third_party/move/move-vm/runtime/src/storage/implementations/unsync_code_storage.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{ - loader::{Module, Script}, + loader::{Function, Module, Script}, storage::{ code_storage::{ambassador_impl_CodeStorage, CodeStorage}, environment::{ @@ -14,10 +14,18 @@ use crate::{ }; use ambassador::Delegate; use bytes::Bytes; -use move_binary_format::{errors::VMResult, file_format::CompiledScript, CompiledModule}; -use move_core_types::{account_address::AccountAddress, identifier::IdentStr, metadata::Metadata}; -use move_vm_types::code::{ - ambassador_impl_ScriptCache, Code, ModuleBytesStorage, ScriptCache, UnsyncScriptCache, +use move_binary_format::{ + errors::{PartialVMResult, VMResult}, + file_format::CompiledScript, + CompiledModule, +}; +use move_core_types::{ + account_address::AccountAddress, identifier::IdentStr, language_storage::TypeTag, + metadata::Metadata, +}; +use move_vm_types::{ + code::{ambassador_impl_ScriptCache, Code, ModuleBytesStorage, ScriptCache, UnsyncScriptCache}, + loaded_data::runtime_types::{StructType, Type}, }; use std::sync::Arc; diff --git a/third_party/move/move-vm/runtime/src/storage/implementations/unsync_module_storage.rs b/third_party/move/move-vm/runtime/src/storage/implementations/unsync_module_storage.rs index fba7581d9d341..b5543e0bb4527 100644 --- a/third_party/move/move-vm/runtime/src/storage/implementations/unsync_module_storage.rs +++ b/third_party/move/move-vm/runtime/src/storage/implementations/unsync_module_storage.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{ - loader::Module, + loader::{Function, Module}, storage::{ environment::{ ambassador_impl_WithRuntimeEnvironment, RuntimeEnvironment, WithRuntimeEnvironment, @@ -12,9 +12,14 @@ use crate::{ }; use ambassador::Delegate; use bytes::Bytes; -use move_binary_format::{errors::VMResult, CompiledModule}; +use move_binary_format::{ + errors::{PartialVMResult, VMResult}, + CompiledModule, +}; use move_core_types::{ - account_address::AccountAddress, identifier::IdentStr, language_storage::ModuleId, + account_address::AccountAddress, + identifier::IdentStr, + language_storage::{ModuleId, TypeTag}, metadata::Metadata, }; use move_vm_types::{ @@ -22,6 +27,7 @@ use move_vm_types::{ ambassador_impl_ModuleCache, ModuleBytesStorage, ModuleCache, ModuleCode, ModuleCodeBuilder, UnsyncModuleCache, WithBytes, WithHash, }, + loaded_data::runtime_types::{StructType, Type}, sha3_256, }; use std::{borrow::Borrow, ops::Deref, sync::Arc}; diff --git a/third_party/move/move-vm/runtime/src/storage/loader.rs b/third_party/move/move-vm/runtime/src/storage/loader.rs index 539a439c0c4f5..3e4d3cfbcd9ca 100644 --- a/third_party/move/move-vm/runtime/src/storage/loader.rs +++ b/third_party/move/move-vm/runtime/src/storage/loader.rs @@ -2,16 +2,12 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{ - config::VMConfig, - loader::{Function, LoadedFunctionOwner, Module}, - logging::expect_no_verification_errors, - module_traversal::TraversalContext, - storage::module_storage::ModuleStorage, - CodeStorage, LoadedFunction, + config::VMConfig, loader::LoadedFunctionOwner, module_traversal::TraversalContext, + storage::module_storage::ModuleStorage, CodeStorage, LoadedFunction, }; use move_binary_format::{ access::{ModuleAccess, ScriptAccess}, - errors::{Location, PartialVMError, PartialVMResult, VMResult}, + errors::{Location, PartialVMResult, VMResult}, CompiledModule, }; use move_core_types::{ @@ -19,11 +15,10 @@ use move_core_types::{ gas_algebra::NumBytes, identifier::IdentStr, language_storage::{ModuleId, TypeTag}, - vm_status::StatusCode, }; use move_vm_types::{ gas::GasMeter, - loaded_data::runtime_types::{StructType, Type, TypeBuilder}, + loaded_data::runtime_types::{Type, TypeBuilder}, module_linker_error, }; use std::{collections::BTreeMap, sync::Arc}; @@ -137,7 +132,7 @@ impl LoaderV2 { // arguments for scripts are verified on the client side. let ty_args = ty_tag_args .iter() - .map(|ty_tag| self.load_ty(code_storage, ty_tag)) + .map(|ty_tag| code_storage.fetch_ty(ty_tag)) .collect::>>() .map_err(|err| err.finish(Location::Script))?; @@ -151,95 +146,6 @@ impl LoaderV2 { function: main, }) } - - /// Returns a loaded & verified module corresponding to the specified name. - pub(crate) fn load_module( - &self, - module_storage: &dyn ModuleStorage, - address: &AccountAddress, - module_name: &IdentStr, - ) -> VMResult> { - module_storage - .fetch_verified_module(address, module_name) - .map_err(expect_no_verification_errors)? - .ok_or_else(|| module_linker_error!(address, module_name)) - } - - /// Returns the function definition corresponding to the specified name, as well as the module - /// where this function is defined. - pub(crate) fn load_function_without_ty_args( - &self, - module_storage: &dyn ModuleStorage, - address: &AccountAddress, - module_name: &IdentStr, - function_name: &IdentStr, - ) -> VMResult<(Arc, Arc)> { - let module = self.load_module(module_storage, address, module_name)?; - let function = module - .function_map - .get(function_name) - .and_then(|idx| module.function_defs.get(*idx)) - .ok_or_else(|| { - PartialVMError::new(StatusCode::FUNCTION_RESOLUTION_FAILURE) - .with_message(format!( - "Function {}::{}::{} does not exist", - address, module_name, function_name - )) - .finish(Location::Undefined) - })? - .clone(); - Ok((module, function)) - } - - /// Returns a struct type corresponding to the specified name. The module - /// containing the struct is loaded. - pub(crate) fn load_struct_ty( - &self, - module_storage: &dyn ModuleStorage, - address: &AccountAddress, - module_name: &IdentStr, - struct_name: &IdentStr, - ) -> PartialVMResult> { - let module = self - .load_module(module_storage, address, module_name) - .map_err(|err| err.to_partial())?; - Ok(module - .struct_map - .get(struct_name) - .and_then(|idx| module.structs.get(*idx)) - .ok_or_else(|| { - PartialVMError::new(StatusCode::TYPE_RESOLUTION_FAILURE).with_message(format!( - "Struct {}::{}::{} does not exist", - address, module_name, struct_name - )) - })? - .definition_struct_type - .clone()) - } - - /// Returns a runtime type corresponding to the specified type tag (file format type - /// representation). In case struct types are transitively loaded, the module containing - /// the struct definition is also loaded. - pub(crate) fn load_ty( - &self, - module_storage: &impl ModuleStorage, - ty_tag: &TypeTag, - ) -> PartialVMResult { - // TODO(loader_v2): Loader V1 uses VMResults everywhere, but partial VM errors - // seem better fit. Here we map error to VMError to reuse existing - // type builder implementation, and then strip the location info. - self.ty_builder() - .create_ty(ty_tag, |st| { - self.load_struct_ty( - module_storage, - &st.address, - st.module.as_ident_str(), - st.name.as_ident_str(), - ) - .map_err(|err| err.finish(Location::Undefined)) - }) - .map_err(|err| err.to_partial()) - } } impl Clone for LoaderV2 { diff --git a/third_party/move/move-vm/runtime/src/storage/module_storage.rs b/third_party/move/move-vm/runtime/src/storage/module_storage.rs index da64fc6dbd001..c96571b046cd1 100644 --- a/third_party/move/move-vm/runtime/src/storage/module_storage.rs +++ b/third_party/move/move-vm/runtime/src/storage/module_storage.rs @@ -1,19 +1,31 @@ // Copyright (c) The Move Contributors // SPDX-License-Identifier: Apache-2.0 -use crate::{loader::Module, WithRuntimeEnvironment}; +use crate::{ + loader::{Function, Module}, + logging::expect_no_verification_errors, + WithRuntimeEnvironment, +}; use ambassador::delegatable_trait; use bytes::Bytes; use hashbrown::HashSet; -use move_binary_format::{errors::VMResult, CompiledModule}; +use move_binary_format::{ + errors::{Location, PartialVMError, PartialVMResult, VMResult}, + CompiledModule, +}; use move_core_types::{ - account_address::AccountAddress, identifier::IdentStr, language_storage::ModuleId, + account_address::AccountAddress, + identifier::IdentStr, + language_storage::{ModuleId, TypeTag}, metadata::Metadata, + vm_status::StatusCode, }; use move_vm_metrics::{Timer, VM_TIMER}; use move_vm_types::{ code::{ModuleCache, ModuleCode, ModuleCodeBuilder, WithBytes, WithHash, WithSize}, + loaded_data::runtime_types::{StructType, Type}, module_cyclic_dependency_error, module_linker_error, + value_serde::FunctionValueExtension, }; use std::sync::Arc; @@ -101,6 +113,91 @@ pub trait ModuleStorage: WithRuntimeEnvironment { address: &AccountAddress, module_name: &IdentStr, ) -> VMResult>>; + + /// Returns the verified module. If it does not exist, a linker error is returned. All other + /// errors are mapped using [expect_no_verification_errors] - since on-chain code should not + /// fail bytecode verification. + fn fetch_existing_verified_module( + &self, + address: &AccountAddress, + module_name: &IdentStr, + ) -> VMResult> { + self.fetch_verified_module(address, module_name) + .map_err(expect_no_verification_errors)? + .ok_or_else(|| module_linker_error!(address, module_name)) + } + + /// Returns a struct type corresponding to the specified name. The module containing the struct + /// will be fetched and cached beforehand. + fn fetch_struct_ty( + &self, + address: &AccountAddress, + module_name: &IdentStr, + struct_name: &IdentStr, + ) -> PartialVMResult> { + let module = self + .fetch_existing_verified_module(address, module_name) + .map_err(|err| err.to_partial())?; + Ok(module + .struct_map + .get(struct_name) + .and_then(|idx| module.structs.get(*idx)) + .ok_or_else(|| { + PartialVMError::new(StatusCode::TYPE_RESOLUTION_FAILURE).with_message(format!( + "Struct {}::{}::{} does not exist", + address, module_name, struct_name + )) + })? + .definition_struct_type + .clone()) + } + + /// Returns a runtime type corresponding to the specified type tag (file format type + /// representation). If a struct type is constructed, the module containing the struct + /// definition is fetched and cached. + fn fetch_ty(&self, ty_tag: &TypeTag) -> PartialVMResult { + // TODO(loader_v2): Loader V1 uses VMResults everywhere, but partial VM errors + // seem better fit. Here we map error to VMError to reuse existing + // type builder implementation, and then strip the location info. + self.runtime_environment() + .vm_config() + .ty_builder + .create_ty(ty_tag, |st| { + self.fetch_struct_ty( + &st.address, + st.module.as_ident_str(), + st.name.as_ident_str(), + ) + .map_err(|err| err.finish(Location::Undefined)) + }) + .map_err(|err| err.to_partial()) + } + + /// Returns the function definition corresponding to the specified name, as well as the module + /// where this function is defined. The returned function can contain uninstantiated generic + /// types and its signature. The returned module is verified. + fn fetch_function_definition( + &self, + address: &AccountAddress, + module_name: &IdentStr, + function_name: &IdentStr, + ) -> VMResult<(Arc, Arc)> { + let module = self.fetch_existing_verified_module(address, module_name)?; + let function = module + .function_map + .get(function_name) + .and_then(|idx| module.function_defs.get(*idx)) + .ok_or_else(|| { + PartialVMError::new(StatusCode::FUNCTION_RESOLUTION_FAILURE) + .with_message(format!( + "Function {}::{}::{} does not exist", + address, module_name, function_name + )) + .finish(Location::Undefined) + })? + .clone(); + Ok((module, function)) + } } impl ModuleStorage for T @@ -302,3 +399,53 @@ where )?; Ok(module.code().verified().clone()) } + +/// Avoids the orphan rule to implement external [FunctionValueExtension] for any generic type that +/// implements [ModuleStorage]. +pub struct FunctionValueExtensionAdapter<'a> { + pub(crate) module_storage: &'a dyn ModuleStorage, +} + +pub trait AsFunctionValueExtension { + fn as_function_value_extension(&self) -> FunctionValueExtensionAdapter; +} + +impl AsFunctionValueExtension for T { + fn as_function_value_extension(&self) -> FunctionValueExtensionAdapter { + FunctionValueExtensionAdapter { + module_storage: self, + } + } +} + +impl<'a> FunctionValueExtension for FunctionValueExtensionAdapter<'a> { + fn get_function_arg_tys( + &self, + module_id: &ModuleId, + function_name: &IdentStr, + substitution_ty_arg_tags: Vec, + ) -> PartialVMResult> { + let substitution_ty_args = substitution_ty_arg_tags + .into_iter() + .map(|tag| self.module_storage.fetch_ty(&tag)) + .collect::>>()?; + + let (_, function) = self + .module_storage + .fetch_function_definition(module_id.address(), module_id.name(), function_name) + .map_err(|err| err.to_partial())?; + + let ty_builder = &self + .module_storage + .runtime_environment() + .vm_config() + .ty_builder; + function + .param_tys() + .iter() + .map(|ty_to_substitute| { + ty_builder.create_ty_with_subst(ty_to_substitute, &substitution_ty_args) + }) + .collect::>>() + } +} diff --git a/third_party/move/move-vm/runtime/src/storage/publishing.rs b/third_party/move/move-vm/runtime/src/storage/publishing.rs index d6d3320e9c54a..b59001ba45897 100644 --- a/third_party/move/move-vm/runtime/src/storage/publishing.rs +++ b/third_party/move/move-vm/runtime/src/storage/publishing.rs @@ -2,25 +2,30 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{ - ambassador_impl_ModuleStorage, ambassador_impl_WithRuntimeEnvironment, AsUnsyncModuleStorage, - Module, ModuleStorage, RuntimeEnvironment, UnsyncModuleStorage, WithRuntimeEnvironment, + ambassador_impl_ModuleStorage, ambassador_impl_WithRuntimeEnvironment, loader::Function, + AsUnsyncModuleStorage, Module, ModuleStorage, RuntimeEnvironment, UnsyncModuleStorage, + WithRuntimeEnvironment, }; use ambassador::Delegate; use bytes::Bytes; use move_binary_format::{ access::ModuleAccess, compatibility::Compatibility, - errors::{verification_error, Location, PartialVMError, VMResult}, + errors::{verification_error, Location, PartialVMError, PartialVMResult, VMResult}, normalized, CompiledModule, IndexKind, }; use move_core_types::{ account_address::AccountAddress, identifier::{IdentStr, Identifier}, - language_storage::ModuleId, + language_storage::{ModuleId, TypeTag}, metadata::Metadata, vm_status::StatusCode, }; -use move_vm_types::{code::ModuleBytesStorage, module_linker_error}; +use move_vm_types::{ + code::ModuleBytesStorage, + loaded_data::runtime_types::{StructType, Type}, + module_linker_error, +}; use std::{ collections::{btree_map, BTreeMap}, sync::Arc, diff --git a/third_party/move/move-vm/types/src/value_serde.rs b/third_party/move/move-vm/types/src/value_serde.rs index 5f17bfe9b3848..c8f390096f9ac 100644 --- a/third_party/move/move-vm/types/src/value_serde.rs +++ b/third_party/move/move-vm/types/src/value_serde.rs @@ -2,182 +2,183 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{ - delayed_values::delayed_field_id::{ - DelayedFieldID, ExtractUniqueIndex, ExtractWidth, TryFromMoveValue, TryIntoMoveValue, - }, + delayed_values::delayed_field_id::DelayedFieldID, + loaded_data::runtime_types::Type, values::{DeserializationSeed, SerializationReadyValue, Value}, }; use move_binary_format::errors::{PartialVMError, PartialVMResult}; use move_core_types::{ + identifier::IdentStr, + language_storage::{ModuleId, TypeTag}, value::{IdentifierMappingKind, MoveTypeLayout}, vm_status::StatusCode, }; -use serde::{ - de::{DeserializeSeed, Error as DeError}, - ser::Error as SerError, - Deserializer, Serialize, Serializer, -}; use std::cell::RefCell; -pub trait CustomDeserializer { - fn custom_deserialize<'d, D: Deserializer<'d>>( - &self, - deserializer: D, - kind: &IdentifierMappingKind, - layout: &MoveTypeLayout, - ) -> Result; -} - -pub trait CustomSerializer { - fn custom_serialize( +/// An extension to (de)serializer to lookup information about function values. +pub trait FunctionValueExtension { + /// Given the module's id and the function name, returns the parameter types of the + /// corresponding function, instantiated with the provided set of type tags. + fn get_function_arg_tys( &self, - serializer: S, - kind: &IdentifierMappingKind, - layout: &MoveTypeLayout, - id: DelayedFieldID, - ) -> Result; + module_id: &ModuleId, + function_name: &IdentStr, + ty_arg_tags: Vec, + ) -> PartialVMResult>; +} + +/// An extension to (de)serializer to lookup information about delayed fields. +pub(crate) struct DelayedFieldsExtension<'a> { + /// Number of delayed fields (de)serialized, capped. + pub(crate) delayed_fields_count: RefCell, + /// Optional mapping to ids/values. The mapping is used to replace ids with values at + /// serialization time and values with ids at deserialization time. If [None], ids and values + /// are serialized as is. + pub(crate) mapping: Option<&'a dyn ValueToIdentifierMapping>, +} + +impl<'a> DelayedFieldsExtension<'a> { + // Temporarily limit the number of delayed fields per resource, until proper charges are + // implemented. + // TODO[agg_v2](clean): + // Propagate up, so this value is controlled by the gas schedule version. + const MAX_DELAYED_FIELDS_PER_RESOURCE: usize = 10; + + /// Increments the delayed fields count, and checks if there are too many of them. If so, an + /// error is returned. + pub(crate) fn inc_and_check_delayed_fields_count(&self) -> PartialVMResult<()> { + *self.delayed_fields_count.borrow_mut() += 1; + if *self.delayed_fields_count.borrow() > Self::MAX_DELAYED_FIELDS_PER_RESOURCE { + return Err(PartialVMError::new(StatusCode::TOO_MANY_DELAYED_FIELDS) + .with_message("Too many Delayed fields in a single resource.".to_string())); + } + Ok(()) + } } -/// Custom (de)serializer which allows delayed values to be (de)serialized as -/// is. This means that when a delayed value is serialized, the deserialization -/// must construct the delayed value back. -pub struct RelaxedCustomSerDe { - delayed_fields_count: RefCell, +/// A (de)serializer context for a single Move [Value], containing optional extensions. If +/// extension is not provided, but required at (de)serialization time, (de)serialization fails. +pub struct ValueSerDeContext<'a> { + #[allow(dead_code)] + pub(crate) function_extension: Option<&'a dyn FunctionValueExtension>, + pub(crate) delayed_fields_extension: Option>, } -impl RelaxedCustomSerDe { +impl<'a> ValueSerDeContext<'a> { + /// Default (de)serializer that disallows delayed fields. #[allow(clippy::new_without_default)] pub fn new() -> Self { Self { - delayed_fields_count: RefCell::new(0), + function_extension: None, + delayed_fields_extension: None, } } -} -// TODO[agg_v2](clean): propagate up, so this value is controlled by the gas schedule version. -// Temporarily limit the number of delayed fields per resource, -// until proper charges are implemented. -pub const MAX_DELAYED_FIELDS_PER_RESOURCE: usize = 10; - -impl CustomDeserializer for RelaxedCustomSerDe { - fn custom_deserialize<'d, D: Deserializer<'d>>( - &self, - deserializer: D, - kind: &IdentifierMappingKind, - layout: &MoveTypeLayout, - ) -> Result { - *self.delayed_fields_count.borrow_mut() += 1; + /// Custom (de)serializer such that supports lookup of the argument types of a function during + /// function value deserialization. + pub fn with_func_args_deserialization( + mut self, + function_extension: &'a dyn FunctionValueExtension, + ) -> Self { + self.function_extension = Some(function_extension); + self + } - let value = DeserializationSeed { - custom_deserializer: None::<&RelaxedCustomSerDe>, - layout, + /// Returns the same extension but without allowing the delayed fields. + pub(crate) fn clone_without_delayed_fields(&self) -> Self { + Self { + function_extension: self.function_extension, + delayed_fields_extension: None, } - .deserialize(deserializer)?; - let (id, _width) = - DelayedFieldID::try_from_move_value(layout, value, &()).map_err(|_| { - D::Error::custom(format!( - "Custom deserialization failed for {:?} with layout {}", - kind, layout - )) - })?; - Ok(Value::delayed_value(id)) } -} -impl CustomSerializer for RelaxedCustomSerDe { - fn custom_serialize( - &self, - serializer: S, - kind: &IdentifierMappingKind, - layout: &MoveTypeLayout, - id: DelayedFieldID, - ) -> Result { - *self.delayed_fields_count.borrow_mut() += 1; + /// Custom (de)serializer such that: + /// 1. when serializing, the delayed value is replaced with a concrete value instance and + /// serialized instead; + /// 2. when deserializing, the concrete value instance is replaced with a delayed id. + pub fn with_delayed_fields_replacement( + mut self, + mapping: &'a dyn ValueToIdentifierMapping, + ) -> Self { + self.delayed_fields_extension = Some(DelayedFieldsExtension { + delayed_fields_count: RefCell::new(0), + mapping: Some(mapping), + }); + self + } - let value = id.try_into_move_value(layout).map_err(|_| { - S::Error::custom(format!( - "Custom serialization failed for {:?} with layout {}", - kind, layout - )) - })?; - SerializationReadyValue { - custom_serializer: None::<&RelaxedCustomSerDe>, + /// Custom (de)serializer that allows delayed values to be (de)serialized as is. This means + /// that when a delayed value is serialized, the deserialization must construct the delayed + /// value back. + pub fn with_delayed_fields_serde(mut self) -> Self { + self.delayed_fields_extension = Some(DelayedFieldsExtension { + delayed_fields_count: RefCell::new(0), + mapping: None, + }); + self + } + + /// Serializes a [Value] based on the provided layout. For legacy reasons, all serialization + /// errors are mapped to [None]. If [DelayedFieldsExtension] is set, and there are too many + /// delayed fields, an error may be returned. + pub fn serialize( + self, + value: &Value, + layout: &MoveTypeLayout, + ) -> PartialVMResult>> { + let value = SerializationReadyValue { + ctx: &self, layout, value: &value.0, + }; + + match bcs::to_bytes(&value).ok() { + Some(bytes) => Ok(Some(bytes)), + None => { + // Check if the error is due to too many delayed fields. If so, to be compatible + // with the older implementation return an error. + if let Some(delayed_fields_extension) = self.delayed_fields_extension { + if delayed_fields_extension.delayed_fields_count.into_inner() + > DelayedFieldsExtension::MAX_DELAYED_FIELDS_PER_RESOURCE + { + return Err(PartialVMError::new(StatusCode::TOO_MANY_DELAYED_FIELDS) + .with_message( + "Too many Delayed fields in a single resource.".to_string(), + )); + } + } + Ok(None) + }, } - .serialize(serializer) } -} -pub fn deserialize_and_allow_delayed_values( - bytes: &[u8], - layout: &MoveTypeLayout, -) -> Option { - let native_deserializer = RelaxedCustomSerDe::new(); - let seed = DeserializationSeed { - custom_deserializer: Some(&native_deserializer), - layout, - }; - bcs::from_bytes_seed(seed, bytes).ok().filter(|_| { - // Should never happen, it should always fail first in serialize_and_allow_delayed_values - // so we can treat it as regular deserialization error. - native_deserializer.delayed_fields_count.into_inner() <= MAX_DELAYED_FIELDS_PER_RESOURCE - }) -} - -pub fn serialize_and_allow_delayed_values( - value: &Value, - layout: &MoveTypeLayout, -) -> PartialVMResult>> { - let native_serializer = RelaxedCustomSerDe::new(); - let value = SerializationReadyValue { - custom_serializer: Some(&native_serializer), - layout, - value: &value.0, - }; - bcs::to_bytes(&value) - .ok() - .map(|v| { - if native_serializer.delayed_fields_count.into_inner() - <= MAX_DELAYED_FIELDS_PER_RESOURCE - { - Ok(v) - } else { - Err(PartialVMError::new(StatusCode::TOO_MANY_DELAYED_FIELDS) - .with_message("Too many Delayed fields in a single resource.".to_string())) - } + /// Returns the serialized size of a [Value] with the associated layout. All errors are mapped + /// to [StatusCode::VALUE_SERIALIZATION_ERROR]. + pub fn serialized_size(self, value: &Value, layout: &MoveTypeLayout) -> PartialVMResult { + let value = SerializationReadyValue { + ctx: &self, + layout, + value: &value.0, + }; + bcs::serialized_size(&value).map_err(|e| { + PartialVMError::new(StatusCode::VALUE_SERIALIZATION_ERROR).with_message(format!( + "failed to compute serialized size of a value: {:?}", + e + )) }) - .transpose() -} + } -/// Returns the serialized size in bytes of a Move value, with compatible layout. -/// Note that the layout should match, as otherwise serialization fails. This -/// method explicitly allows having delayed values inside the passed in Move value -/// because their size is fixed and cannot change. -pub fn serialized_size_allowing_delayed_values( - value: &Value, - layout: &MoveTypeLayout, -) -> PartialVMResult { - let native_serializer = RelaxedCustomSerDe::new(); - let value = SerializationReadyValue { - custom_serializer: Some(&native_serializer), - layout, - value: &value.0, - }; - bcs::serialized_size(&value).map_err(|e| { - PartialVMError::new(StatusCode::VALUE_SERIALIZATION_ERROR).with_message(format!( - "failed to compute serialized size of a value: {:?}", - e - )) - }) + /// Deserializes the bytes using the provided layout into a Move [Value]. + pub fn deserialize(self, bytes: &[u8], layout: &MoveTypeLayout) -> Option { + let seed = DeserializationSeed { ctx: &self, layout }; + bcs::from_bytes_seed(seed, bytes).ok() + } } /// Allow conversion between values and identifiers (delayed values). For example, /// this trait can be implemented to fetch a concrete Move value from the global /// state based on the identifier stored inside a delayed value. pub trait ValueToIdentifierMapping { - type Identifier; - fn value_to_identifier( &self, // We need kind to distinguish between aggregators and snapshots @@ -185,116 +186,11 @@ pub trait ValueToIdentifierMapping { kind: &IdentifierMappingKind, layout: &MoveTypeLayout, value: Value, - ) -> PartialVMResult; + ) -> PartialVMResult; fn identifier_to_value( &self, layout: &MoveTypeLayout, - identifier: Self::Identifier, + identifier: DelayedFieldID, ) -> PartialVMResult; } - -/// Custom (de)serializer such that: -/// 1. when encountering a delayed value, ir uses its id to replace it with a concrete -/// value instance and serialize it instead; -/// 2. when deserializing, the concrete value instance is replaced with a delayed value. -pub struct CustomSerDeWithExchange<'a, I: From + ExtractWidth + ExtractUniqueIndex> { - mapping: &'a dyn ValueToIdentifierMapping, - delayed_fields_count: RefCell, -} - -impl<'a, I: From + ExtractWidth + ExtractUniqueIndex> CustomSerDeWithExchange<'a, I> { - pub fn new(mapping: &'a dyn ValueToIdentifierMapping) -> Self { - Self { - mapping, - delayed_fields_count: RefCell::new(0), - } - } -} - -impl<'a, I: From + ExtractWidth + ExtractUniqueIndex> CustomSerializer - for CustomSerDeWithExchange<'a, I> -{ - fn custom_serialize( - &self, - serializer: S, - _kind: &IdentifierMappingKind, - layout: &MoveTypeLayout, - sized_id: DelayedFieldID, - ) -> Result { - *self.delayed_fields_count.borrow_mut() += 1; - - let value = self - .mapping - .identifier_to_value(layout, sized_id.as_u64().into()) - .map_err(|e| S::Error::custom(format!("{}", e)))?; - SerializationReadyValue { - custom_serializer: None::<&RelaxedCustomSerDe>, - layout, - value: &value.0, - } - .serialize(serializer) - } -} - -impl<'a, I: From + ExtractWidth + ExtractUniqueIndex> CustomDeserializer - for CustomSerDeWithExchange<'a, I> -{ - fn custom_deserialize<'d, D: Deserializer<'d>>( - &self, - deserializer: D, - kind: &IdentifierMappingKind, - layout: &MoveTypeLayout, - ) -> Result { - *self.delayed_fields_count.borrow_mut() += 1; - - let value = DeserializationSeed { - custom_deserializer: None::<&RelaxedCustomSerDe>, - layout, - } - .deserialize(deserializer)?; - let id = self - .mapping - .value_to_identifier(kind, layout, value) - .map_err(|e| D::Error::custom(format!("{}", e)))?; - Ok(Value::delayed_value(DelayedFieldID::new_with_width( - id.extract_unique_index(), - id.extract_width(), - ))) - } -} - -pub fn deserialize_and_replace_values_with_ids + ExtractWidth + ExtractUniqueIndex>( - bytes: &[u8], - layout: &MoveTypeLayout, - mapping: &impl ValueToIdentifierMapping, -) -> Option { - let custom_deserializer = CustomSerDeWithExchange::new(mapping); - let seed = DeserializationSeed { - custom_deserializer: Some(&custom_deserializer), - layout, - }; - bcs::from_bytes_seed(seed, bytes).ok().filter(|_| { - // Should never happen, it should always fail first in serialize_and_allow_delayed_values - // so we can treat it as regular deserialization error. - custom_deserializer.delayed_fields_count.into_inner() <= MAX_DELAYED_FIELDS_PER_RESOURCE - }) -} - -pub fn serialize_and_replace_ids_with_values + ExtractWidth + ExtractUniqueIndex>( - value: &Value, - layout: &MoveTypeLayout, - mapping: &impl ValueToIdentifierMapping, -) -> Option> { - let custom_serializer = CustomSerDeWithExchange::new(mapping); - let value = SerializationReadyValue { - custom_serializer: Some(&custom_serializer), - layout, - value: &value.0, - }; - bcs::to_bytes(&value).ok().filter(|_| { - // Should never happen, it should always fail first in serialize_and_allow_delayed_values - // so we can treat it as regular deserialization error. - custom_serializer.delayed_fields_count.into_inner() <= MAX_DELAYED_FIELDS_PER_RESOURCE - }) -} diff --git a/third_party/move/move-vm/types/src/values/serialization_tests.rs b/third_party/move/move-vm/types/src/values/serialization_tests.rs index 6085a50183e2c..e1c48c082fcbe 100644 --- a/third_party/move/move-vm/types/src/values/serialization_tests.rs +++ b/third_party/move/move-vm/types/src/values/serialization_tests.rs @@ -5,7 +5,7 @@ use crate::{ delayed_values::delayed_field_id::DelayedFieldID, - value_serde::{serialize_and_allow_delayed_values, serialized_size_allowing_delayed_values}, + value_serde::ValueSerDeContext, values::{values_impl, Struct, Value}, }; use claims::{assert_err, assert_ok, assert_some}; @@ -85,10 +85,13 @@ fn enum_round_trip_vm_value() { )), ]; for value in good_values { - let blob = value - .simple_serialize(&layout) + let blob = ValueSerDeContext::new() + .serialize(&value, &layout) + .unwrap() .expect("serialization succeeds"); - let de_value = Value::simple_deserialize(&blob, &layout).expect("deserialization succeeds"); + let de_value = ValueSerDeContext::new() + .deserialize(&blob, &layout) + .expect("deserialization succeeds"); assert!( value.equals(&de_value).unwrap(), "roundtrip serialization succeeds" @@ -96,12 +99,18 @@ fn enum_round_trip_vm_value() { } let bad_tag_value = Value::struct_(Struct::pack_variant(3, [Value::u64(42)])); assert!( - bad_tag_value.simple_serialize(&layout).is_none(), + ValueSerDeContext::new() + .serialize(&bad_tag_value, &layout) + .unwrap() + .is_none(), "serialization fails" ); let bad_struct_value = Value::struct_(Struct::pack([Value::u64(42)])); assert!( - bad_struct_value.simple_serialize(&layout).is_none(), + ValueSerDeContext::new() + .serialize(&bad_struct_value, &layout) + .unwrap() + .is_none(), "serialization fails" ); } @@ -160,14 +169,17 @@ fn enum_rust_round_trip_vm_value() { RustEnum::BoolNumber(true, 13), ]; for (move_value, rust_value) in move_values.into_iter().zip(rust_values) { - let from_move = move_value - .simple_serialize(&layout) + let from_move = ValueSerDeContext::new() + .serialize(&move_value, &layout) + .unwrap() .expect("from move succeeds"); let to_rust = bcs::from_bytes::(&from_move).expect("to rust successful"); assert_eq!(to_rust, rust_value); let from_rust = bcs::to_bytes(&rust_value).expect("from rust succeeds"); - let to_move = Value::simple_deserialize(&from_rust, &layout).expect("to move succeeds"); + let to_move = ValueSerDeContext::new() + .deserialize(&from_rust, &layout) + .expect("to move succeeds"); assert!( to_move.equals(&move_value).unwrap(), "from rust to move failed" @@ -224,10 +236,13 @@ fn test_serialized_size() { ), ]; for (value, layout) in good_values_layouts_sizes { - let bytes = assert_some!(assert_ok!(serialize_and_allow_delayed_values( - &value, &layout - ))); - let size = assert_ok!(serialized_size_allowing_delayed_values(&value, &layout)); + let bytes = assert_some!(assert_ok!(ValueSerDeContext::new() + .with_delayed_fields_serde() + .serialize(&value, &layout))); + + let size = assert_ok!(ValueSerDeContext::new() + .with_delayed_fields_serde() + .serialized_size(&value, &layout)); assert_eq!(size, bytes.len()); } @@ -241,6 +256,8 @@ fn test_serialized_size() { (Value::u64(12), Native(Aggregator, Box::new(U64))), ]; for (value, layout) in bad_values_layouts_sizes { - assert_err!(serialized_size_allowing_delayed_values(&value, &layout)); + assert_err!(ValueSerDeContext::new() + .with_delayed_fields_serde() + .serialized_size(&value, &layout)); } } diff --git a/third_party/move/move-vm/types/src/values/value_prop_tests.rs b/third_party/move/move-vm/types/src/values/value_prop_tests.rs index cd612bac743df..24e2ed8b3422d 100644 --- a/third_party/move/move-vm/types/src/values/value_prop_tests.rs +++ b/third_party/move/move-vm/types/src/values/value_prop_tests.rs @@ -2,15 +2,15 @@ // Copyright (c) The Move Contributors // SPDX-License-Identifier: Apache-2.0 -use crate::values::{prop::layout_and_value_strategy, Value}; +use crate::{value_serde::ValueSerDeContext, values::prop::layout_and_value_strategy}; use move_core_types::value::MoveValue; use proptest::prelude::*; proptest! { #[test] fn serializer_round_trip((layout, value) in layout_and_value_strategy()) { - let blob = value.simple_serialize(&layout).expect("must serialize"); - let value_deserialized = Value::simple_deserialize(&blob, &layout).expect("must deserialize"); + let blob = ValueSerDeContext::new().serialize(&value, &layout).unwrap().expect("must serialize"); + let value_deserialized = ValueSerDeContext::new().deserialize(&blob, &layout).expect("must deserialize"); assert!(value.equals(&value_deserialized).unwrap()); let move_value = value.as_move_value(&layout); diff --git a/third_party/move/move-vm/types/src/values/values_impl.rs b/third_party/move/move-vm/types/src/values/values_impl.rs index 42fbe5d9278c3..fae84d1694a85 100644 --- a/third_party/move/move-vm/types/src/values/values_impl.rs +++ b/third_party/move/move-vm/types/src/values/values_impl.rs @@ -5,22 +5,29 @@ #![allow(clippy::arc_with_non_send_sync)] use crate::{ + delayed_values::delayed_field_id::{DelayedFieldID, TryFromMoveValue, TryIntoMoveValue}, loaded_data::runtime_types::Type, + value_serde::ValueSerDeContext, views::{ValueView, ValueVisitor}, }; use itertools::Itertools; use move_binary_format::{ errors::*, - file_format::{Constant, SignatureToken}, + file_format::{Constant, SignatureToken, VariantIndex}, }; use move_core_types::{ account_address::AccountAddress, effects::Op, gas_algebra::AbstractMemorySize, u256, value, - value::{MoveStructLayout, MoveTypeLayout}, + value::{MoveStruct, MoveStructLayout, MoveTypeLayout, MoveValue}, vm_status::{sub_status::NFE_VECTOR_ERROR_BASE, StatusCode}, }; +use serde::{ + de::{EnumAccess, Error as DeError, Unexpected, VariantAccess}, + ser::{Error as SerError, SerializeSeq, SerializeTuple, SerializeTupleVariant}, + Deserialize, +}; use std::{ cell::RefCell, cmp::Ordering, @@ -3625,57 +3632,12 @@ pub mod debug { * is to involve an explicit representation of the type layout. * **************************************************************************************/ -use crate::value_serde::{CustomDeserializer, CustomSerializer, RelaxedCustomSerDe}; -use move_binary_format::file_format::VariantIndex; -use serde::{ - de::{EnumAccess, Error as DeError, Unexpected, VariantAccess}, - ser::{Error as SerError, SerializeSeq, SerializeTuple, SerializeTupleVariant}, - Deserialize, -}; - -impl Value { - pub fn simple_deserialize(blob: &[u8], layout: &MoveTypeLayout) -> Option { - let seed = DeserializationSeed { - custom_deserializer: None::<&RelaxedCustomSerDe>, - layout, - }; - bcs::from_bytes_seed(seed, blob).ok() - } - - pub fn simple_serialize(&self, layout: &MoveTypeLayout) -> Option> { - bcs::to_bytes(&SerializationReadyValue { - custom_serializer: None::<&RelaxedCustomSerDe>, - layout, - value: &self.0, - }) - .ok() - } -} - -impl Struct { - pub fn simple_deserialize(blob: &[u8], layout: &MoveStructLayout) -> Option { - let seed = DeserializationSeed { - custom_deserializer: None::<&RelaxedCustomSerDe>, - layout, - }; - bcs::from_bytes_seed(seed, blob).ok() - } - - pub fn simple_serialize(&self, layout: &MoveStructLayout) -> Option> { - bcs::to_bytes(&SerializationReadyValue { - custom_serializer: None::<&RelaxedCustomSerDe>, - layout, - value: &self.fields, - }) - .ok() - } -} // Wrapper around value with additional information which can be used by the // serializer. -pub(crate) struct SerializationReadyValue<'c, 'l, 'v, L, V, C> { - // Allows to perform a custom serialization for delayed values. - pub(crate) custom_serializer: Option<&'c C>, +pub(crate) struct SerializationReadyValue<'c, 'l, 'v, L, V> { + // Contains the current (possibly custom) serialization context. + pub(crate) ctx: &'c ValueSerDeContext<'c>, // Layout for guiding serialization. pub(crate) layout: &'l L, // Value to serialize. @@ -3688,8 +3650,8 @@ fn invariant_violation(message: String) -> S::Error { ) } -impl<'c, 'l, 'v, C: CustomSerializer> serde::Serialize - for SerializationReadyValue<'c, 'l, 'v, MoveTypeLayout, ValueImpl, C> +impl<'c, 'l, 'v> serde::Serialize + for SerializationReadyValue<'c, 'l, 'v, MoveTypeLayout, ValueImpl> { fn serialize(&self, serializer: S) -> Result { use MoveTypeLayout as L; @@ -3708,7 +3670,7 @@ impl<'c, 'l, 'v, C: CustomSerializer> serde::Serialize // Structs. (L::Struct(struct_layout), ValueImpl::Container(Container::Struct(r))) => { (SerializationReadyValue { - custom_serializer: self.custom_serializer, + ctx: self.ctx, layout: struct_layout, value: &*r.borrow(), }) @@ -3732,7 +3694,7 @@ impl<'c, 'l, 'v, C: CustomSerializer> serde::Serialize let mut t = serializer.serialize_seq(Some(v.len()))?; for value in v.iter() { t.serialize_element(&SerializationReadyValue { - custom_serializer: self.custom_serializer, + ctx: self.ctx, layout, value, })?; @@ -3756,7 +3718,7 @@ impl<'c, 'l, 'v, C: CustomSerializer> serde::Serialize ))); } (SerializationReadyValue { - custom_serializer: self.custom_serializer, + ctx: self.ctx, layout: &L::Address, value: &v[0], }) @@ -3766,14 +3728,37 @@ impl<'c, 'l, 'v, C: CustomSerializer> serde::Serialize // Delayed values. For their serialization, we must have custom // serialization available, otherwise an error is returned. (L::Native(kind, layout), ValueImpl::DelayedFieldID { id }) => { - match self.custom_serializer { - Some(custom_serializer) => { - custom_serializer.custom_serialize(serializer, kind, layout, *id) + match &self.ctx.delayed_fields_extension { + Some(delayed_fields_extension) => { + delayed_fields_extension + .inc_and_check_delayed_fields_count() + .map_err(S::Error::custom)?; + + let value = match delayed_fields_extension.mapping { + Some(mapping) => mapping + .identifier_to_value(layout, *id) + .map_err(|e| S::Error::custom(format!("{}", e)))?, + None => id.try_into_move_value(layout).map_err(|_| { + S::Error::custom(format!( + "Custom serialization failed for {:?} with layout {}", + kind, layout + )) + })?, + }; + + // The resulting value should not contain any delayed fields, we disallow + // this by using a context without the delayed field extension. + let ctx = self.ctx.clone_without_delayed_fields(); + let value = SerializationReadyValue { + ctx: &ctx, + layout: layout.as_ref(), + value: &value.0, + }; + value.serialize(serializer) }, None => { - // If no custom serializer, it is not known how the - // delayed value should be serialized. So, just return - // an error. + // If no delayed field extension, it is not known how the delayed value + // should be serialized. So, just return an error. Err(invariant_violation::(format!( "no custom serializer for delayed value ({:?}) with layout {}", kind, layout @@ -3791,8 +3776,8 @@ impl<'c, 'l, 'v, C: CustomSerializer> serde::Serialize } } -impl<'c, 'l, 'v, C: CustomSerializer> serde::Serialize - for SerializationReadyValue<'c, 'l, 'v, MoveStructLayout, Vec, C> +impl<'c, 'l, 'v> serde::Serialize + for SerializationReadyValue<'c, 'l, 'v, MoveStructLayout, Vec> { fn serialize(&self, serializer: S) -> Result { let mut values = self.value.as_slice(); @@ -3818,7 +3803,7 @@ impl<'c, 'l, 'v, C: CustomSerializer> serde::Serialize variant_tag, variant_name, &SerializationReadyValue { - custom_serializer: self.custom_serializer, + ctx: self.ctx, layout: &variant_layouts[0], value: &values[0], }, @@ -3832,7 +3817,7 @@ impl<'c, 'l, 'v, C: CustomSerializer> serde::Serialize )?; for (layout, value) in variant_layouts.iter().zip(values) { t.serialize_field(&SerializationReadyValue { - custom_serializer: self.custom_serializer, + ctx: self.ctx, layout, value, })? @@ -3851,7 +3836,7 @@ impl<'c, 'l, 'v, C: CustomSerializer> serde::Serialize } for (field_layout, value) in field_layouts.iter().zip(values.iter()) { t.serialize_element(&SerializationReadyValue { - custom_serializer: self.custom_serializer, + ctx: self.ctx, layout: field_layout, value, })?; @@ -3863,17 +3848,14 @@ impl<'c, 'l, 'v, C: CustomSerializer> serde::Serialize // Seed used by deserializer to ensure there is information about the value // being deserialized. -pub(crate) struct DeserializationSeed<'c, L, C> { - // Allows to deserialize delayed values in the custom format using external - // deserializer. - pub(crate) custom_deserializer: Option<&'c C>, +pub(crate) struct DeserializationSeed<'c, L> { + // Holds extensions external to the deserializer. + pub(crate) ctx: &'c ValueSerDeContext<'c>, // Layout to guide deserialization. pub(crate) layout: L, } -impl<'d, 'c, C: CustomDeserializer> serde::de::DeserializeSeed<'d> - for DeserializationSeed<'c, &MoveTypeLayout, C> -{ +impl<'d, 'c> serde::de::DeserializeSeed<'d> for DeserializationSeed<'c, &MoveTypeLayout> { type Value = Value; fn deserialize>( @@ -3897,7 +3879,7 @@ impl<'d, 'c, C: CustomDeserializer> serde::de::DeserializeSeed<'d> // Structs. L::Struct(struct_layout) => { let seed = DeserializationSeed { - custom_deserializer: self.custom_deserializer, + ctx: self.ctx, layout: struct_layout, }; Ok(Value::struct_(seed.deserialize(deserializer)?)) @@ -3915,7 +3897,7 @@ impl<'d, 'c, C: CustomDeserializer> serde::de::DeserializeSeed<'d> L::Address => Value::vector_address(Vec::deserialize(deserializer)?), layout => { let seed = DeserializationSeed { - custom_deserializer: self.custom_deserializer, + ctx: self.ctx, layout, }; let vector = deserializer.deserialize_seq(VectorElementVisitor(seed))?; @@ -3927,9 +3909,34 @@ impl<'d, 'c, C: CustomDeserializer> serde::de::DeserializeSeed<'d> // Delayed values should always use custom deserialization. L::Native(kind, layout) => { - match self.custom_deserializer { - Some(native_deserializer) => { - native_deserializer.custom_deserialize(deserializer, kind, layout) + match &self.ctx.delayed_fields_extension { + Some(delayed_fields_extension) => { + delayed_fields_extension + .inc_and_check_delayed_fields_count() + .map_err(D::Error::custom)?; + + let value = DeserializationSeed { + ctx: &self.ctx.clone_without_delayed_fields(), + layout: layout.as_ref(), + } + .deserialize(deserializer)?; + let id = match delayed_fields_extension.mapping { + Some(mapping) => mapping + .value_to_identifier(kind, layout, value) + .map_err(|e| D::Error::custom(format!("{}", e)))?, + None => { + let (id, _) = + DelayedFieldID::try_from_move_value(layout, value, &()) + .map_err(|_| { + D::Error::custom(format!( + "Custom deserialization failed for {:?} with layout {}", + kind, layout + )) + })?; + id + }, + }; + Ok(Value::delayed_value(id)) }, None => { // If no custom deserializer, it is not known how the @@ -3949,9 +3956,7 @@ impl<'d, 'c, C: CustomDeserializer> serde::de::DeserializeSeed<'d> } } -impl<'d, C: CustomDeserializer> serde::de::DeserializeSeed<'d> - for DeserializationSeed<'_, &MoveStructLayout, C> -{ +impl<'d> serde::de::DeserializeSeed<'d> for DeserializationSeed<'_, &MoveStructLayout> { type Value = Struct; fn deserialize>( @@ -3962,7 +3967,7 @@ impl<'d, C: CustomDeserializer> serde::de::DeserializeSeed<'d> MoveStructLayout::Runtime(field_layouts) => { let fields = deserializer.deserialize_tuple( field_layouts.len(), - StructFieldVisitor(self.custom_deserializer, field_layouts), + StructFieldVisitor(self.ctx, field_layouts), )?; Ok(Struct::pack(fields)) }, @@ -3974,7 +3979,7 @@ impl<'d, C: CustomDeserializer> serde::de::DeserializeSeed<'d> let fields = deserializer.deserialize_enum( value::MOVE_ENUM_NAME, variant_names, - StructVariantVisitor(self.custom_deserializer, variants), + StructVariantVisitor(self.ctx, variants), )?; Ok(Struct::pack(fields)) }, @@ -3987,9 +3992,9 @@ impl<'d, C: CustomDeserializer> serde::de::DeserializeSeed<'d> } } -struct VectorElementVisitor<'c, 'l, C>(DeserializationSeed<'c, &'l MoveTypeLayout, C>); +struct VectorElementVisitor<'c, 'l>(DeserializationSeed<'c, &'l MoveTypeLayout>); -impl<'d, 'c, 'l, C: CustomDeserializer> serde::de::Visitor<'d> for VectorElementVisitor<'c, 'l, C> { +impl<'d, 'c, 'l> serde::de::Visitor<'d> for VectorElementVisitor<'c, 'l> { type Value = Vec; fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -4002,7 +4007,7 @@ impl<'d, 'c, 'l, C: CustomDeserializer> serde::de::Visitor<'d> for VectorElement { let mut vals = Vec::new(); while let Some(elem) = seq.next_element_seed(DeserializationSeed { - custom_deserializer: self.0.custom_deserializer, + ctx: self.0.ctx, layout: self.0.layout, })? { vals.push(elem.0) @@ -4011,9 +4016,9 @@ impl<'d, 'c, 'l, C: CustomDeserializer> serde::de::Visitor<'d> for VectorElement } } -struct StructFieldVisitor<'c, 'l, C>(Option<&'c C>, &'l [MoveTypeLayout]); +struct StructFieldVisitor<'c, 'l>(&'c ValueSerDeContext<'c>, &'l [MoveTypeLayout]); -impl<'d, 'c, 'l, C: CustomDeserializer> serde::de::Visitor<'d> for StructFieldVisitor<'c, 'l, C> { +impl<'d, 'c, 'l> serde::de::Visitor<'d> for StructFieldVisitor<'c, 'l> { type Value = Vec; fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -4027,7 +4032,7 @@ impl<'d, 'c, 'l, C: CustomDeserializer> serde::de::Visitor<'d> for StructFieldVi let mut val = Vec::new(); for (i, field_layout) in self.1.iter().enumerate() { if let Some(elem) = seq.next_element_seed(DeserializationSeed { - custom_deserializer: self.0, + ctx: self.0, layout: field_layout, })? { val.push(elem) @@ -4039,9 +4044,9 @@ impl<'d, 'c, 'l, C: CustomDeserializer> serde::de::Visitor<'d> for StructFieldVi } } -struct StructVariantVisitor<'c, 'l, C>(Option<&'c C>, &'l [Vec]); +struct StructVariantVisitor<'c, 'l>(&'c ValueSerDeContext<'c>, &'l [Vec]); -impl<'d, 'c, 'l, C: CustomDeserializer> serde::de::Visitor<'d> for StructVariantVisitor<'c, 'l, C> { +impl<'d, 'c, 'l> serde::de::Visitor<'d> for StructVariantVisitor<'c, 'l> { type Value = Vec; fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -4065,7 +4070,7 @@ impl<'d, 'c, 'l, C: CustomDeserializer> serde::de::Visitor<'d> for StructVariant }, 1 => { values.push(rest.newtype_variant_seed(DeserializationSeed { - custom_deserializer: self.0, + ctx: self.0, layout: &fields[0], })?); Ok(values) @@ -4091,7 +4096,7 @@ impl<'d, 'c, 'l, C: CustomDeserializer> serde::de::Visitor<'d> for StructVariant // Note this is actually directly serialized as u16, but this is equivalent // to MoveTypeLayout::U16, so we can reuse the custom deserializer seed. let variant_tag = match seq.next_element_seed(DeserializationSeed { - custom_deserializer: self.0, + ctx: self.0, layout: &MoveTypeLayout::U16, })? { Some(elem) => { @@ -4117,7 +4122,7 @@ impl<'d, 'c, 'l, C: CustomDeserializer> serde::de::Visitor<'d> for StructVariant // Based on the validated variant tag, we know the field types for (i, field_layout) in self.1[variant_tag].iter().enumerate() { if let Some(elem) = seq.next_element_seed(DeserializationSeed { - custom_deserializer: self.0, + ctx: self.0, layout: field_layout, })? { val.push(elem) @@ -4162,7 +4167,7 @@ impl Value { pub fn deserialize_constant(constant: &Constant) -> Option { let layout = Self::constant_sig_token_to_layout(&constant.type_)?; - Value::simple_deserialize(&constant.data, &layout) + ValueSerDeContext::new().deserialize(&constant.data, &layout) } } @@ -4583,9 +4588,6 @@ pub mod prop { } } -use crate::delayed_values::delayed_field_id::DelayedFieldID; -use move_core_types::value::{MoveStruct, MoveValue}; - impl ValueImpl { pub fn as_move_value(&self, layout: &MoveTypeLayout) -> MoveValue { use MoveTypeLayout as L; diff --git a/third_party/move/testing-infra/transactional-test-runner/src/framework.rs b/third_party/move/testing-infra/transactional-test-runner/src/framework.rs index be05bd2c0e333..9fcf18dc3f188 100644 --- a/third_party/move/testing-infra/transactional-test-runner/src/framework.rs +++ b/third_party/move/testing-infra/transactional-test-runner/src/framework.rs @@ -50,6 +50,7 @@ use move_model::{ }; use move_symbol_pool::Symbol; use move_vm_runtime::session::SerializedReturnValues; +use move_vm_types::value_serde::ValueSerDeContext; use once_cell::sync::Lazy; use regex::Regex; use std::{ @@ -621,8 +622,7 @@ fn display_return_values(return_values: SerializedReturnValues) -> Option>(); @@ -641,7 +641,8 @@ fn display_return_values(return_values: SerializedReturnValues) -> Option>(); let printed = values diff --git a/third_party/move/tools/move-unit-test/src/extensions.rs b/third_party/move/tools/move-unit-test/src/extensions.rs index f9fd6d78203c4..05b1058540ef4 100644 --- a/third_party/move/tools/move-unit-test/src/extensions.rs +++ b/third_party/move/tools/move-unit-test/src/extensions.rs @@ -13,6 +13,7 @@ use move_table_extension::NativeTableContext; use move_vm_runtime::native_extensions::NativeContextExtensions; #[cfg(feature = "table-extension")] use move_vm_test_utils::BlankStorage; +use move_vm_types::value_serde::FunctionValueExtension; use once_cell::sync::Lazy; use std::{fmt::Write, sync::Mutex}; @@ -50,22 +51,32 @@ pub(crate) fn new_extensions<'a>() -> NativeContextExtensions<'a> { /// Print the change sets for available native context extensions. #[allow(unused)] -pub(crate) fn print_change_sets(_w: &mut W, extensions: &mut NativeContextExtensions) { +pub(crate) fn print_change_sets( + w: &mut W, + native_extensions: &mut NativeContextExtensions, + function_value_extension: &impl FunctionValueExtension, +) { #[cfg(feature = "table-extension")] - print_table_extension(_w, extensions); + print_table_extension(w, native_extensions, function_value_extension); } // ============================================================================================= // Table Extensions #[cfg(feature = "table-extension")] -fn create_table_extension(extensions: &mut NativeContextExtensions) { - extensions.add(NativeTableContext::new([0u8; 32], &*DUMMY_RESOLVER)); +fn create_table_extension(native_extensions: &mut NativeContextExtensions) { + native_extensions.add(NativeTableContext::new([0u8; 32], &*DUMMY_RESOLVER)); } #[cfg(feature = "table-extension")] -fn print_table_extension(w: &mut W, extensions: &mut NativeContextExtensions) { - let cs = extensions.remove::().into_change_set(); +fn print_table_extension( + w: &mut W, + native_extensions: &mut NativeContextExtensions, + function_value_extension: &impl FunctionValueExtension, +) { + let cs = native_extensions + .remove::() + .into_change_set(function_value_extension); if let Ok(cs) = cs { if !cs.new_tables.is_empty() { writeln!( diff --git a/third_party/move/tools/move-unit-test/src/test_runner.rs b/third_party/move/tools/move-unit-test/src/test_runner.rs index 6c5e839411fc6..03ea88601103e 100644 --- a/third_party/move/tools/move-unit-test/src/test_runner.rs +++ b/third_party/move/tools/move-unit-test/src/test_runner.rs @@ -27,7 +27,7 @@ use move_vm_runtime::{ move_vm::MoveVM, native_extensions::NativeContextExtensions, native_functions::NativeFunctionTable, - AsUnsyncModuleStorage, RuntimeEnvironment, + AsFunctionValueExtension, AsUnsyncModuleStorage, RuntimeEnvironment, }; use move_vm_test_utils::InMemoryStorage; use rayon::prelude::*; @@ -86,6 +86,7 @@ fn print_resources_and_extensions( cs: &ChangeSet, extensions: &mut NativeContextExtensions, storage: &InMemoryStorage, + natives: &NativeFunctionTable, ) -> Result { use std::fmt::Write; let mut buf = String::new(); @@ -104,7 +105,10 @@ fn print_resources_and_extensions( } } - extensions::print_change_sets(&mut buf, extensions); + let runtime_environment = RuntimeEnvironment::new(natives.clone()); + let module_storage = storage.as_unsync_module_storage(runtime_environment); + let function_value_extension = module_storage.as_function_value_extension(); + extensions::print_change_sets(&mut buf, extensions, &function_value_extension); Ok(buf) } @@ -339,6 +343,7 @@ impl SharedTestingConfig { &changeset, &mut extensions, &self.starting_storage_state, + &self.native_function_table, ) .ok() }) diff --git a/types/src/transaction/mod.rs b/types/src/transaction/mod.rs index 138dd8e81496c..5c2560926d9bc 100644 --- a/types/src/transaction/mod.rs +++ b/types/src/transaction/mod.rs @@ -68,9 +68,6 @@ pub use change_set::ChangeSet; pub use module::{Module, ModuleBundle}; pub use move_core_types::transaction_argument::TransactionArgument; use move_core_types::vm_status::AbortLocation; -use move_vm_types::delayed_values::delayed_field_id::{ - ExtractUniqueIndex, ExtractWidth, TryFromMoveValue, TryIntoMoveValue, -}; pub use multisig::{ExecutionError, Multisig, MultisigTransactionPayload}; use once_cell::sync::OnceCell; pub use script::{ @@ -2063,22 +2060,6 @@ pub trait BlockExecutableTransaction: Sync + Send + Clone + 'static { + Debug + DeserializeOwned + Serialize; - /// Delayed field identifier type. - type Identifier: PartialOrd - + Ord - + Send - + Sync - + Clone - + Hash - + Eq - + Debug - + Copy - + From - + From<(u32, u32)> - + ExtractUniqueIndex - + ExtractWidth - + TryIntoMoveValue - + TryFromMoveValue; type Value: Send + Sync + Debug + Clone + TransactionWrite; type Event: Send + Sync + Debug + Clone + TransactionEvent; diff --git a/types/src/transaction/signature_verified_transaction.rs b/types/src/transaction/signature_verified_transaction.rs index cd35b573b42c1..6d405aa54d8fb 100644 --- a/types/src/transaction/signature_verified_transaction.rs +++ b/types/src/transaction/signature_verified_transaction.rs @@ -9,7 +9,6 @@ use crate::{ }; use aptos_crypto::{hash::CryptoHash, HashValue}; use move_core_types::{account_address::AccountAddress, language_storage::StructTag}; -use move_vm_types::delayed_values::delayed_field_id::DelayedFieldID; use serde::{Deserialize, Serialize}; use std::fmt::Debug; @@ -61,7 +60,6 @@ impl SignatureVerifiedTransaction { impl BlockExecutableTransaction for SignatureVerifiedTransaction { type Event = ContractEvent; - type Identifier = DelayedFieldID; type Key = StateKey; type Tag = StructTag; type Value = WriteOp; From 8a0f983a09c9cd900a3b2e7115b8e35f86d6675d Mon Sep 17 00:00:00 2001 From: Balaji Arun Date: Fri, 20 Dec 2024 11:03:16 -0800 Subject: [PATCH 71/78] [forge] exclude new pipeline for compat test (#15644) --- testsuite/forge-cli/src/suites/land_blocking.rs | 1 + testsuite/forge/src/config.rs | 15 +++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/testsuite/forge-cli/src/suites/land_blocking.rs b/testsuite/forge-cli/src/suites/land_blocking.rs index dbae2019a9a43..5b2a2eafbe456 100644 --- a/testsuite/forge-cli/src/suites/land_blocking.rs +++ b/testsuite/forge-cli/src/suites/land_blocking.rs @@ -29,6 +29,7 @@ pub(crate) fn get_land_blocking_test( pub(crate) fn compat() -> ForgeConfig { ForgeConfig::default() + .with_suite_name("compat".into()) .with_initial_validator_count(NonZeroUsize::new(4).unwrap()) .add_network_test(SimpleValidatorUpgrade) .with_success_criteria(SuccessCriteria::new(5000).add_wait_for_catchup_s(240)) diff --git a/testsuite/forge/src/config.rs b/testsuite/forge/src/config.rs index 599cfad0a411b..61584befb8752 100644 --- a/testsuite/forge/src/config.rs +++ b/testsuite/forge/src/config.rs @@ -170,6 +170,7 @@ impl ForgeConfig { let existing_db_tag = self.existing_db_tag.clone(); let validator_resource_override = self.validator_resource_override; let fullnode_resource_override = self.fullnode_resource_override; + let suite_name = self.get_suite_name(); // Override specific helm values. See reference: terraform/helm/aptos-node/values.yaml Some(Arc::new(move |helm_values: &mut serde_yaml::Value| { @@ -239,10 +240,16 @@ impl ForgeConfig { helm_values["validator"]["config"]["indexer_db_config"]["enable_event"] = true.into(); helm_values["fullnode"]["config"]["indexer_db_config"]["enable_event"] = true.into(); - // enable new pipeline - helm_values["validator"]["config"]["consensus"]["enable_pipeline"] = true.into(); - helm_values["fullnode"]["config"]["consensus_observer"]["enable_pipeline"] = - true.into(); + // This is a temporary hack to disable new pipeline for compat tests. + if !suite_name + .as_ref() + .is_some_and(|name| name.eq_ignore_ascii_case("compat")) + { + // enable new pipeline + helm_values["validator"]["config"]["consensus"]["enable_pipeline"] = true.into(); + helm_values["fullnode"]["config"]["consensus_observer"]["enable_pipeline"] = + true.into(); + } })) } From f5d01316eea6f6475ac38c1343b2d0584ae8a162 Mon Sep 17 00:00:00 2001 From: Maksim Kurnikov Date: Mon, 23 Dec 2024 18:53:15 +0100 Subject: [PATCH 72/78] [CLI] Add `compiler-message-format-json` experiment value to `aptos move compile` and `aptos move lint` (#15540) --- Cargo.lock | 2 + crates/aptos/src/move_tool/lint.rs | 6 ++ third_party/move/move-compiler-v2/Cargo.toml | 2 + .../move-compiler-v2/src/diagnostics/human.rs | 33 +++++++++++ .../move-compiler-v2/src/diagnostics/json.rs | 44 ++++++++++++++ .../move-compiler-v2/src/diagnostics/mod.rs | 58 +++++++++++++++++++ .../move/move-compiler-v2/src/experiments.rs | 6 ++ third_party/move/move-compiler-v2/src/lib.rs | 38 +++++++----- .../compiler-message-format-json/errors.exp | 4 ++ .../compiler-message-format-json/errors.move | 6 ++ .../compiler-message-format-json/warnings.exp | 4 ++ .../warnings.move | 6 ++ .../move/move-compiler-v2/tests/testsuite.rs | 43 +++++++++----- third_party/move/move-model/src/model.rs | 20 ++++--- .../src/framework.rs | 5 +- .../move-cli/src/base/test_validation.rs | 7 ++- .../move/tools/move-linter/tests/testsuite.rs | 5 +- .../src/compilation/compiled_package.rs | 10 ++-- 18 files changed, 253 insertions(+), 46 deletions(-) create mode 100644 third_party/move/move-compiler-v2/src/diagnostics/human.rs create mode 100644 third_party/move/move-compiler-v2/src/diagnostics/json.rs create mode 100644 third_party/move/move-compiler-v2/src/diagnostics/mod.rs create mode 100644 third_party/move/move-compiler-v2/tests/compiler-message-format-json/errors.exp create mode 100644 third_party/move/move-compiler-v2/tests/compiler-message-format-json/errors.move create mode 100644 third_party/move/move-compiler-v2/tests/compiler-message-format-json/warnings.exp create mode 100644 third_party/move/move-compiler-v2/tests/compiler-message-format-json/warnings.move diff --git a/Cargo.lock b/Cargo.lock index 1d82d5ce72d44..6248ce77ab1d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11253,6 +11253,7 @@ dependencies = [ "anyhow", "bcs 0.1.4", "clap 4.5.21", + "codespan", "codespan-reporting", "datatest-stable", "ethnum", @@ -11277,6 +11278,7 @@ dependencies = [ "num 0.4.1", "once_cell", "petgraph 0.6.5", + "serde_json", "walkdir", ] diff --git a/crates/aptos/src/move_tool/lint.rs b/crates/aptos/src/move_tool/lint.rs index 0b320098d65bf..954f83b9b9269 100644 --- a/crates/aptos/src/move_tool/lint.rs +++ b/crates/aptos/src/move_tool/lint.rs @@ -75,6 +75,10 @@ pub struct LintPackage { /// See #[clap(long, env = "APTOS_CHECK_TEST_CODE")] pub check_test_code: bool, + + /// Experiments + #[clap(long, hide(true))] + pub experiments: Vec, } impl LintPackage { @@ -89,6 +93,7 @@ impl LintPackage { language_version, skip_attribute_checks, check_test_code, + experiments, } = self.clone(); MovePackageDir { dev, @@ -100,6 +105,7 @@ impl LintPackage { language_version, skip_attribute_checks, check_test_code, + experiments, ..MovePackageDir::new() } } diff --git a/third_party/move/move-compiler-v2/Cargo.toml b/third_party/move/move-compiler-v2/Cargo.toml index f24853b9f9b2b..74654702066d0 100644 --- a/third_party/move/move-compiler-v2/Cargo.toml +++ b/third_party/move/move-compiler-v2/Cargo.toml @@ -14,6 +14,7 @@ abstract-domain-derive = { path = "../move-model/bytecode/abstract_domain_derive anyhow = { workspace = true } bcs = { workspace = true } clap = { workspace = true, features = ["derive", "env"] } +codespan = { workspace = true } codespan-reporting = { workspace = true, features = ["serde", "serialization"] } ethnum = { workspace = true } flexi_logger = { workspace = true } @@ -35,6 +36,7 @@ move-symbol-pool = { workspace = true } num = { workspace = true } once_cell = { workspace = true } petgraph = { workspace = true } +serde_json = { workspace = true } [dev-dependencies] anyhow = { workspace = true } diff --git a/third_party/move/move-compiler-v2/src/diagnostics/human.rs b/third_party/move/move-compiler-v2/src/diagnostics/human.rs new file mode 100644 index 0000000000000..ea15b03a3f791 --- /dev/null +++ b/third_party/move/move-compiler-v2/src/diagnostics/human.rs @@ -0,0 +1,33 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::diagnostics::Emitter; +use codespan::{FileId, Files}; +use codespan_reporting::{ + diagnostic::Diagnostic, + term::{emit, termcolor::WriteColor, Config}, +}; + +/// It's used in the native aptos-cli output to show error messages. +/// Wraps the `codespan_reporting::term::emit()` method. +pub struct HumanEmitter<'w, W: WriteColor> { + writer: &'w mut W, +} + +impl<'w, W> HumanEmitter<'w, W> +where + W: WriteColor, +{ + pub fn new(writer: &'w mut W) -> Self { + HumanEmitter { writer } + } +} + +impl<'w, W> Emitter for HumanEmitter<'w, W> +where + W: WriteColor, +{ + fn emit(&mut self, source_files: &Files, diag: &Diagnostic) { + emit(&mut self.writer, &Config::default(), source_files, diag).expect("emit must not fail") + } +} diff --git a/third_party/move/move-compiler-v2/src/diagnostics/json.rs b/third_party/move/move-compiler-v2/src/diagnostics/json.rs new file mode 100644 index 0000000000000..ee1825c37b48c --- /dev/null +++ b/third_party/move/move-compiler-v2/src/diagnostics/json.rs @@ -0,0 +1,44 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::diagnostics::Emitter; +use codespan::{FileId, Files}; +use codespan_reporting::diagnostic::{Diagnostic, Label}; +use std::io::Write; + +/// Shows compiler errors as a structured JSON output. +/// Exists to support various tools external to the aptos-cli, i.e. IDEs. +pub struct JsonEmitter<'w, W: Write> { + writer: &'w mut W, +} + +impl<'w, W: Write> JsonEmitter<'w, W> { + pub fn new(writer: &'w mut W) -> Self { + JsonEmitter { writer } + } +} + +impl<'w, W: Write> Emitter for JsonEmitter<'w, W> { + fn emit(&mut self, source_files: &Files, diag: &Diagnostic) { + let fpath_labels = diag + .labels + .iter() + .map(|label| { + let fpath = codespan_reporting::files::Files::name(source_files, label.file_id) + .expect("always Ok() in the impl") + .to_string(); + Label::new(label.style, fpath, label.range.clone()) + }) + .collect(); + let mut json_diag = Diagnostic::new(diag.severity) + .with_message(diag.message.clone()) + .with_labels(fpath_labels) + .with_notes(diag.notes.clone()); + if let Some(code) = &diag.code { + json_diag = json_diag.with_code(code) + } + serde_json::to_writer(&mut self.writer, &json_diag).expect("it should be serializable"); + writeln!(&mut self.writer) + .expect("dest is stderr / in-memory buffer, it should always be available"); + } +} diff --git a/third_party/move/move-compiler-v2/src/diagnostics/mod.rs b/third_party/move/move-compiler-v2/src/diagnostics/mod.rs new file mode 100644 index 0000000000000..fc2cb767a3a2f --- /dev/null +++ b/third_party/move/move-compiler-v2/src/diagnostics/mod.rs @@ -0,0 +1,58 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::{ + diagnostics::{human::HumanEmitter, json::JsonEmitter}, + options, Experiment, +}; +use anyhow::bail; +use codespan::{FileId, Files}; +use codespan_reporting::{ + diagnostic::{Diagnostic, Severity}, + term::termcolor::WriteColor, +}; +use move_model::model::GlobalEnv; + +pub mod human; +pub mod json; + +impl options::Options { + pub fn error_emitter<'w, W>(&self, dest: &'w mut W) -> Box + where + W: WriteColor, + { + if self.experiment_on(Experiment::MESSAGE_FORMAT_JSON) { + Box::new(JsonEmitter::new(dest)) + } else { + Box::new(HumanEmitter::new(dest)) + } + } +} + +pub trait Emitter { + fn emit(&mut self, source_files: &Files, diag: &Diagnostic); + + /// Writes accumulated diagnostics of given or higher severity. + fn report_diag(&mut self, global_env: &GlobalEnv, severity: Severity) { + global_env.report_diag_with_filter( + |files, diag| self.emit(files, diag), + |d| d.severity >= severity, + ); + } + + /// Helper function to report diagnostics, check for errors, and fail with a message on + /// errors. This function is idempotent and will not report the same diagnostics again. + fn check_diag( + &mut self, + global_env: &GlobalEnv, + report_severity: Severity, + msg: &str, + ) -> anyhow::Result<()> { + self.report_diag(global_env, report_severity); + if global_env.has_errors() { + bail!("exiting with {}", msg); + } else { + Ok(()) + } + } +} diff --git a/third_party/move/move-compiler-v2/src/experiments.rs b/third_party/move/move-compiler-v2/src/experiments.rs index a519049690013..e7a5176aa78a8 100644 --- a/third_party/move/move-compiler-v2/src/experiments.rs +++ b/third_party/move/move-compiler-v2/src/experiments.rs @@ -271,6 +271,11 @@ pub static EXPERIMENTS: Lazy> = Lazy::new(|| { .to_string(), default: Given(false), }, + Experiment { + name: Experiment::MESSAGE_FORMAT_JSON.to_string(), + description: "Enable json format for compiler messages".to_string(), + default: Given(false), + }, ]; experiments .into_iter() @@ -302,6 +307,7 @@ impl Experiment { pub const LAMBDA_LIFTING: &'static str = "lambda-lifting"; pub const LAMBDA_VALUES: &'static str = "lambda-values"; pub const LINT_CHECKS: &'static str = "lint-checks"; + pub const MESSAGE_FORMAT_JSON: &'static str = "compiler-message-format-json"; pub const OPTIMIZE: &'static str = "optimize"; pub const OPTIMIZE_EXTRA: &'static str = "optimize-extra"; pub const OPTIMIZE_WAITING_FOR_COMPARE_TESTS: &'static str = diff --git a/third_party/move/move-compiler-v2/src/lib.rs b/third_party/move/move-compiler-v2/src/lib.rs index 2b7e6d18b8c25..7f5c6c4139c43 100644 --- a/third_party/move/move-compiler-v2/src/lib.rs +++ b/third_party/move/move-compiler-v2/src/lib.rs @@ -3,6 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 mod bytecode_generator; +pub mod diagnostics; pub mod env_pipeline; mod experiments; pub mod external_checks; @@ -14,6 +15,7 @@ pub mod pipeline; pub mod plan_builder; use crate::{ + diagnostics::Emitter, env_pipeline::{ acquires_checker, ast_simplifier, cyclic_instantiation_checker, flow_insensitive_checkers, function_checker, inliner, lambda_lifter, lambda_lifter::LambdaLiftingOptions, @@ -71,30 +73,31 @@ use move_stackless_bytecode::function_target_pipeline::{ }; use move_symbol_pool::Symbol; pub use options::Options; -use std::{collections::BTreeSet, io::Write, path::Path}; +use std::{collections::BTreeSet, path::Path}; /// Run Move compiler and print errors to stderr. pub fn run_move_compiler_to_stderr( options: Options, ) -> anyhow::Result<(GlobalEnv, Vec)> { - let mut error_writer = StandardStream::stderr(ColorChoice::Auto); - run_move_compiler(&mut error_writer, options) + let mut stderr = StandardStream::stderr(ColorChoice::Auto); + let mut emitter = options.error_emitter(&mut stderr); + run_move_compiler(emitter.as_mut(), options) } /// Run move compiler and print errors to given writer. Returns the set of compiled units. -pub fn run_move_compiler( - error_writer: &mut W, +pub fn run_move_compiler( + emitter: &mut E, options: Options, ) -> anyhow::Result<(GlobalEnv, Vec)> where - W: WriteColor + Write, + E: Emitter + ?Sized, { logging::setup_logging(); info!("Move Compiler v2"); // Run context check. let mut env = run_checker_and_rewriters(options.clone())?; - check_errors(&env, error_writer, "checking errors")?; + check_errors(&env, emitter, "checking errors")?; if options.experiment_on(Experiment::STOP_BEFORE_STACKLESS_BYTECODE) { std::process::exit(0) @@ -102,7 +105,8 @@ where // Run code generator let mut targets = run_bytecode_gen(&env); - check_errors(&env, error_writer, "code generation errors")?; + check_errors(&env, emitter, "code generation errors")?; + debug!("After bytecode_gen, GlobalEnv={}", env.dump_env()); // Run transformation pipeline @@ -129,14 +133,14 @@ where } else { pipeline.run_with_hook(&env, &mut targets, |_| {}, |_, _, _| !env.has_errors()) } - check_errors(&env, error_writer, "stackless-bytecode analysis errors")?; + check_errors(&env, emitter, "stackless-bytecode analysis errors")?; if options.experiment_on(Experiment::STOP_BEFORE_FILE_FORMAT) { std::process::exit(0) } let modules_and_scripts = run_file_format_gen(&mut env, &targets); - check_errors(&env, error_writer, "assembling errors")?; + check_errors(&env, emitter, "assembling errors")?; debug!( "File format bytecode:\n{}", @@ -145,7 +149,7 @@ where let annotated_units = annotate_units(modules_and_scripts); run_bytecode_verifier(&annotated_units, &mut env); - check_errors(&env, error_writer, "bytecode verification errors")?; + check_errors(&env, emitter, "bytecode verification errors")?; // Finally mark this model to be generated by v2 env.set_compiler_v2(true); @@ -163,7 +167,8 @@ pub fn run_move_compiler_for_analysis( options.whole_program = true; // will set `treat_everything_as_target` options = options.set_experiment(Experiment::SPEC_REWRITE, true); options = options.set_experiment(Experiment::ATTACH_COMPILED_MODULE, true); - let (env, _units) = run_move_compiler(error_writer, options)?; + let mut emitter = options.error_emitter(error_writer); + let (env, _units) = run_move_compiler(emitter.as_mut(), options)?; // Reset for subsequent analysis env.treat_everything_as_target(false); Ok(env) @@ -605,13 +610,14 @@ fn get_vm_error_loc(env: &GlobalEnv, source_map: &SourceMap, e: &VMError) -> Opt } /// Report any diags in the env to the writer and fail if there are errors. -pub fn check_errors(env: &GlobalEnv, error_writer: &mut W, msg: &str) -> anyhow::Result<()> +pub fn check_errors(env: &GlobalEnv, emitter: &mut E, msg: &str) -> anyhow::Result<()> where - W: WriteColor + Write, + E: Emitter + ?Sized, { let options = env.get_extension::().unwrap_or_default(); - env.report_diag(error_writer, options.report_severity()); - env.check_diag(error_writer, options.report_severity(), msg) + + emitter.report_diag(env, options.report_severity()); + emitter.check_diag(env, options.report_severity(), msg) } /// Annotate the given compiled units. diff --git a/third_party/move/move-compiler-v2/tests/compiler-message-format-json/errors.exp b/third_party/move/move-compiler-v2/tests/compiler-message-format-json/errors.exp new file mode 100644 index 0000000000000..f64b61007a78d --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/compiler-message-format-json/errors.exp @@ -0,0 +1,4 @@ + +Diagnostics: +{"severity":"Error","code":null,"message":"cannot use `bool` with an operator which expects a value of type `integer`","labels":[{"style":"Primary","file_id":"tests/compiler-message-format-json/errors.move","range":{"start":51,"end":55},"message":""}],"notes":[]} +{"severity":"Error","code":null,"message":"cannot use `bool` with an operator which expects a value of type `integer`","labels":[{"style":"Primary","file_id":"tests/compiler-message-format-json/errors.move","range":{"start":69,"end":73},"message":""}],"notes":[]} diff --git a/third_party/move/move-compiler-v2/tests/compiler-message-format-json/errors.move b/third_party/move/move-compiler-v2/tests/compiler-message-format-json/errors.move new file mode 100644 index 0000000000000..4038807912f3a --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/compiler-message-format-json/errors.move @@ -0,0 +1,6 @@ +module 0x42::errors { + fun main() { + 1 + true; + 2 + true; + } +} diff --git a/third_party/move/move-compiler-v2/tests/compiler-message-format-json/warnings.exp b/third_party/move/move-compiler-v2/tests/compiler-message-format-json/warnings.exp new file mode 100644 index 0000000000000..7950ff370d030 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/compiler-message-format-json/warnings.exp @@ -0,0 +1,4 @@ + +Diagnostics: +{"severity":"Warning","code":null,"message":"Unused local variable `a`. Consider removing or prefixing with an underscore: `_a`","labels":[{"style":"Primary","file_id":"tests/compiler-message-format-json/warnings.move","range":{"start":53,"end":54},"message":""}],"notes":[]} +{"severity":"Warning","code":null,"message":"Unused local variable `b`. Consider removing or prefixing with an underscore: `_b`","labels":[{"style":"Primary","file_id":"tests/compiler-message-format-json/warnings.move","range":{"start":72,"end":73},"message":""}],"notes":[]} diff --git a/third_party/move/move-compiler-v2/tests/compiler-message-format-json/warnings.move b/third_party/move/move-compiler-v2/tests/compiler-message-format-json/warnings.move new file mode 100644 index 0000000000000..f9e857c702fe7 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/compiler-message-format-json/warnings.move @@ -0,0 +1,6 @@ +module 0x42::warnings { + fun main() { + let a = 1; + let b = 2; + } +} diff --git a/third_party/move/move-compiler-v2/tests/testsuite.rs b/third_party/move/move-compiler-v2/tests/testsuite.rs index a5e6ef2322d8d..9233703a0986b 100644 --- a/third_party/move/move-compiler-v2/tests/testsuite.rs +++ b/third_party/move/move-compiler-v2/tests/testsuite.rs @@ -737,6 +737,20 @@ const TEST_CONFIGS: Lazy> = Lazy::new(|| { dump_bytecode: DumpLevel::EndStage, dump_bytecode_filter: None, }, + TestConfig { + name: "compiler-message-format-json", + runner: |p| run_test(p, get_config_by_name("compiler-message-format-json")), + include: vec!["/compiler-message-format-json/"], + exclude: vec![], + exp_suffix: None, + options: opts + .clone() + .set_experiment(Experiment::MESSAGE_FORMAT_JSON, true), + stop_after: StopAfter::AstPipeline, + dump_ast: DumpLevel::None, + dump_bytecode: DumpLevel::None, + dump_bytecode_filter: None, + }, ]; configs.into_iter().map(|c| (c.name, c)).collect() }); @@ -780,7 +794,7 @@ fn run_test(path: &Path, config: TestConfig) -> datatest_stable::Result<()> { // Run context checker let mut env = move_compiler_v2::run_checker(options.clone())?; - let mut ok = check_diags(&mut test_output.borrow_mut(), &env); + let mut ok = check_diags(&mut test_output.borrow_mut(), &env, &options); if ok { // Run env processor pipeline. @@ -796,10 +810,10 @@ fn run_test(path: &Path, config: TestConfig) -> datatest_stable::Result<()> { test_output .borrow_mut() .push_str(&String::from_utf8_lossy(&out.into_inner())); - ok = check_diags(&mut test_output.borrow_mut(), &env); + ok = check_diags(&mut test_output.borrow_mut(), &env, &options); } else { env_pipeline.run(&mut env); - ok = check_diags(&mut test_output.borrow_mut(), &env); + ok = check_diags(&mut test_output.borrow_mut(), &env, &options); if ok && config.dump_ast == DumpLevel::EndStage { test_output.borrow_mut().push_str(&format!( "// -- Model dump before bytecode pipeline\n{}\n", @@ -824,13 +838,13 @@ fn run_test(path: &Path, config: TestConfig) -> datatest_stable::Result<()> { // In real use, this is run outside of the compilation process, but the needed info is // available in `env` once we finish the AST. plan_builder::construct_test_plan(&env, None); - ok = check_diags(&mut test_output.borrow_mut(), &env); + ok = check_diags(&mut test_output.borrow_mut(), &env, &options); } if ok && config.stop_after > StopAfter::AstPipeline { // Run stackless bytecode generator let mut targets = move_compiler_v2::run_bytecode_gen(&env); - ok = check_diags(&mut test_output.borrow_mut(), &env); + ok = check_diags(&mut test_output.borrow_mut(), &env, &options); if ok { // Run the target pipeline. let bytecode_pipeline = if config.stop_after == StopAfter::BytecodeGen { @@ -852,7 +866,7 @@ fn run_test(path: &Path, config: TestConfig) -> datatest_stable::Result<()> { // bytecode from the generator, if requested. |targets_before| { let out = &mut test_output.borrow_mut(); - update_diags(ok.borrow_mut(), out, &env); + update_diags(ok.borrow_mut(), out, &env, &options); if bytecode_dump_enabled(&config, true, INITIAL_BYTECODE_STAGE) { let dump = &move_stackless_bytecode::print_targets_with_annotations_for_test( @@ -870,7 +884,7 @@ fn run_test(path: &Path, config: TestConfig) -> datatest_stable::Result<()> { // bytecode after the processor, if requested. |i, processor, targets_after| { let out = &mut test_output.borrow_mut(); - update_diags(ok.borrow_mut(), out, &env); + update_diags(ok.borrow_mut(), out, &env, &options); if bytecode_dump_enabled(&config, i + 1 == count, processor.name().as_str()) { let title = format!("after {}:", processor.name()); let dump = @@ -890,7 +904,7 @@ fn run_test(path: &Path, config: TestConfig) -> datatest_stable::Result<()> { if *ok.borrow() && config.stop_after == StopAfter::FileFormat { let units = run_file_format_gen(&mut env, &targets); let out = &mut test_output.borrow_mut(); - update_diags(ok.borrow_mut(), out, &env); + update_diags(ok.borrow_mut(), out, &env, &options); if *ok.borrow() { if bytecode_dump_enabled(&config, true, FILE_FORMAT_STAGE) { out.push_str( @@ -904,7 +918,7 @@ fn run_test(path: &Path, config: TestConfig) -> datatest_stable::Result<()> { } else { out.push_str("\n============ bytecode verification failed ========\n"); } - check_diags(out, &env); + check_diags(out, &env, &options); } } } @@ -929,9 +943,12 @@ fn bytecode_dump_enabled(config: &TestConfig, is_last: bool, name: &str) -> bool } /// Checks for diagnostics and adds them to the baseline. -fn check_diags(baseline: &mut String, env: &GlobalEnv) -> bool { +fn check_diags(baseline: &mut String, env: &GlobalEnv, options: &Options) -> bool { let mut error_writer = Buffer::no_color(); - env.report_diag(&mut error_writer, Severity::Note); + { + let mut emitter = options.error_emitter(&mut error_writer); + emitter.report_diag(env, Severity::Note); + } let diag = String::from_utf8_lossy(&error_writer.into_inner()).to_string(); if !diag.is_empty() { *baseline += &format!("\nDiagnostics:\n{}", diag); @@ -941,8 +958,8 @@ fn check_diags(baseline: &mut String, env: &GlobalEnv) -> bool { ok } -fn update_diags(mut ok: RefMut, baseline: &mut String, env: &GlobalEnv) { - if !check_diags(baseline, env) { +fn update_diags(mut ok: RefMut, baseline: &mut String, env: &GlobalEnv, options: &Options) { + if !check_diags(baseline, env, options) { *ok = false; } } diff --git a/third_party/move/move-model/src/model.rs b/third_party/move/move-model/src/model.rs index c4d08a9f63b74..175923e0dade2 100644 --- a/third_party/move/move-model/src/model.rs +++ b/third_party/move/move-model/src/model.rs @@ -1218,7 +1218,12 @@ impl GlobalEnv { /// Writes accumulated diagnostics of given or higher severity. pub fn report_diag(&self, writer: &mut W, severity: Severity) { - self.report_diag_with_filter(writer, |d| d.severity >= severity) + self.report_diag_with_filter( + |files, diag| { + emit(writer, &Config::default(), files, diag).expect("emit must not fail") + }, + |d| d.severity >= severity, + ); } /// Helper function to report diagnostics, check for errors, and fail with a message on @@ -1317,11 +1322,11 @@ impl GlobalEnv { } /// Writes accumulated diagnostics that pass through `filter` - pub fn report_diag_with_filter) -> bool>( - &self, - writer: &mut W, - mut filter: F, - ) { + pub fn report_diag_with_filter(&self, mut emitter: E, mut filter: F) + where + E: FnMut(&Files, &Diagnostic), + F: FnMut(&Diagnostic) -> bool, + { let mut shown = BTreeSet::new(); self.diags.borrow_mut().sort_by(|a, b| { let reported_ordering = a.1.cmp(&b.1); @@ -1343,8 +1348,7 @@ impl GlobalEnv { // Avoid showing the same message twice. This can happen e.g. because of // duplication of expressions via schema inclusion. if shown.insert(format!("{:?}", diag)) { - emit(writer, &Config::default(), &self.source_files, diag) - .expect("emit must not fail"); + emitter(&self.source_files, diag); } *reported = true; } diff --git a/third_party/move/testing-infra/transactional-test-runner/src/framework.rs b/third_party/move/testing-infra/transactional-test-runner/src/framework.rs index 9fcf18dc3f188..2158f95b6a2b7 100644 --- a/third_party/move/testing-infra/transactional-test-runner/src/framework.rs +++ b/third_party/move/testing-infra/transactional-test-runner/src/framework.rs @@ -825,7 +825,10 @@ fn compile_source_unit_v2( options = options.set_experiment(exp, value) } let mut error_writer = termcolor::Buffer::no_color(); - let result = move_compiler_v2::run_move_compiler(&mut error_writer, options); + let result = { + let mut emitter = options.error_emitter(&mut error_writer); + move_compiler_v2::run_move_compiler(emitter.as_mut(), options) + }; let error_str = String::from_utf8_lossy(&error_writer.into_inner()).to_string(); let (model, mut units) = result.map_err(|_| anyhow::anyhow!("compilation errors:\n {}", error_str))?; diff --git a/third_party/move/tools/move-cli/src/base/test_validation.rs b/third_party/move/tools/move-cli/src/base/test_validation.rs index e721eba9fcad4..1203cd581c221 100644 --- a/third_party/move/tools/move-cli/src/base/test_validation.rs +++ b/third_party/move/tools/move-cli/src/base/test_validation.rs @@ -5,7 +5,7 @@ //! This module manages validation of the unit tests, in addition to standard compiler //! checking. -use codespan_reporting::term::{termcolor, termcolor::StandardStream}; +use codespan_reporting::term::{emit, termcolor, termcolor::StandardStream, Config}; use move_model::model::GlobalEnv; use once_cell::sync::Lazy; use std::sync::Mutex; @@ -35,8 +35,11 @@ pub(crate) fn validate(env: &GlobalEnv) { pub fn has_errors_then_report(model: &GlobalEnv) -> bool { let mut has_errors = false; + let mut writer = StandardStream::stderr(termcolor::ColorChoice::Auto); model.report_diag_with_filter( - &mut StandardStream::stderr(termcolor::ColorChoice::Auto), + |files, diag| { + emit(&mut writer, &Config::default(), files, diag).expect("emit must not fail") + }, |d| { let include = d.labels.iter().all(|l| { let fname = model.get_file(l.file_id).to_string_lossy(); diff --git a/third_party/move/tools/move-linter/tests/testsuite.rs b/third_party/move/tools/move-linter/tests/testsuite.rs index 454957cdd161b..02ef906c1bdc9 100644 --- a/third_party/move/tools/move-linter/tests/testsuite.rs +++ b/third_party/move/tools/move-linter/tests/testsuite.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use codespan_reporting::{diagnostic::Severity, term::termcolor::Buffer}; -use move_compiler_v2::{run_move_compiler, Experiment}; +use move_compiler_v2::{diagnostics::human::HumanEmitter, run_move_compiler, Experiment}; use move_linter::MoveLintChecks; use move_model::metadata::{CompilerVersion, LanguageVersion}; use move_prover_test_utils::baseline_test; @@ -30,7 +30,8 @@ fn test_runner(path: &Path) -> datatest_stable::Result<()> { }; let mut output = String::new(); let mut error_writer = Buffer::no_color(); - match run_move_compiler(&mut error_writer, compiler_options) { + let mut emitter = HumanEmitter::new(&mut error_writer); + match run_move_compiler(&mut emitter, compiler_options) { Err(e) => { output.push_str(&format!( "Aborting with compilation errors:\n{:#}\n{}\n", diff --git a/third_party/move/tools/move-package/src/compilation/compiled_package.rs b/third_party/move/tools/move-package/src/compilation/compiled_package.rs index 31fb59bd73bef..3ed670dc3ddb1 100644 --- a/third_party/move/tools/move-package/src/compilation/compiled_package.rs +++ b/third_party/move/tools/move-package/src/compilation/compiled_package.rs @@ -1137,8 +1137,9 @@ pub fn unimplemented_v2_driver(_options: move_compiler_v2::Options) -> CompilerD /// Runs the v2 compiler, exiting the process if any errors occurred. pub fn build_and_report_v2_driver(options: move_compiler_v2::Options) -> CompilerDriverResult { - let mut writer = StandardStream::stderr(ColorChoice::Auto); - match move_compiler_v2::run_move_compiler(&mut writer, options) { + let mut stderr = StandardStream::stderr(ColorChoice::Auto); + let mut emitter = options.error_emitter(&mut stderr); + match move_compiler_v2::run_move_compiler(emitter.as_mut(), options) { Ok((env, units)) => Ok(( move_compiler_v2::make_files_source_text(&env), units, @@ -1155,8 +1156,9 @@ pub fn build_and_report_v2_driver(options: move_compiler_v2::Options) -> Compile pub fn build_and_report_no_exit_v2_driver( options: move_compiler_v2::Options, ) -> CompilerDriverResult { - let mut writer = StandardStream::stderr(ColorChoice::Auto); - let (env, units) = move_compiler_v2::run_move_compiler(&mut writer, options)?; + let mut stderr = StandardStream::stderr(ColorChoice::Auto); + let mut emitter = options.error_emitter(&mut stderr); + let (env, units) = move_compiler_v2::run_move_compiler(emitter.as_mut(), options)?; Ok(( move_compiler_v2::make_files_source_text(&env), units, From 6b09e6337deca18de4ec499bf02cfa0b44bdb461 Mon Sep 17 00:00:00 2001 From: Wolfgang Grieskamp Date: Mon, 23 Dec 2024 14:32:14 -0800 Subject: [PATCH 73/78] [compiler-v2] Make `-v debug` output more concise (#15642) Output using the `debug!` logging facility should not stay permanent in the code, or at leastr be protected by an additional guard, unless it is useful to work with end users. The default output of `debug!` should overall be useful for users to help understand their problems and avoid complex internal data structures. This updates some code in the compiler to follow this guideline, as well as refines the docs for logging to reflect this. This came apparent when trying to use `aptos move prove -v debug` -- the output printed lots of stuff which is probably only relevant for internal debugging. --- .../src/env_pipeline/ast_simplifier.rs | 12 ++++++--- .../src/env_pipeline/inliner.rs | 27 +++++++++++-------- third_party/move/move-compiler-v2/src/lib.rs | 16 +++++++---- .../move/move-compiler-v2/src/logging.rs | 13 ++++++--- 4 files changed, 44 insertions(+), 24 deletions(-) diff --git a/third_party/move/move-compiler-v2/src/env_pipeline/ast_simplifier.rs b/third_party/move/move-compiler-v2/src/env_pipeline/ast_simplifier.rs index 62c9a6cf63d12..98a1b52f95860 100644 --- a/third_party/move/move-compiler-v2/src/env_pipeline/ast_simplifier.rs +++ b/third_party/move/move-compiler-v2/src/env_pipeline/ast_simplifier.rs @@ -66,6 +66,8 @@ use std::{ vec::Vec, }; +const DEBUG: bool = false; + /// Run the AST simplification pass on all target functions in the `env`. /// Optionally do some aggressive simplifications that may eliminate code. pub fn run_simplifier(env: &mut GlobalEnv, eliminate_code: bool) { @@ -91,10 +93,12 @@ pub fn run_simplifier(env: &mut GlobalEnv, eliminate_code: bool) { // Actually do the writing of new definitions. for (qfid, def) in new_definitions.into_iter() { env.set_function_def(qfid, def); - debug!( - "After simplifier, function is `{}`", - env.dump_fun(&env.get_function(qfid)) - ); + if DEBUG { + debug!( + "After simplifier, function is `{}`", + env.dump_fun(&env.get_function(qfid)) + ); + } } } diff --git a/third_party/move/move-compiler-v2/src/env_pipeline/inliner.rs b/third_party/move/move-compiler-v2/src/env_pipeline/inliner.rs index 06eaa909705dd..5eb55655a7fe0 100644 --- a/third_party/move/move-compiler-v2/src/env_pipeline/inliner.rs +++ b/third_party/move/move-compiler-v2/src/env_pipeline/inliner.rs @@ -41,7 +41,7 @@ use crate::env_pipeline::rewrite_target::{ RewriteState, RewriteTarget, RewriteTargets, RewritingScope, }; use codespan_reporting::diagnostic::Severity; -use log::{debug, trace}; +use log::trace; use move_model::{ ast::{Exp, ExpData, Operation, Pattern, Spec, SpecBlockTarget, TempIndex}, exp_rewriter::ExpRewriterFunctions, @@ -61,13 +61,14 @@ use std::{ type QualifiedFunId = QualifiedId; type CallSiteLocations = BTreeMap<(RewriteTarget, QualifiedFunId), BTreeSet>; +const DEBUG: bool = false; + // ====================================================================================== // Entry /// Run inlining on current program's AST. For each function which is target of the compilation, /// visit that function body and inline any calls to functions marked as "inline". pub fn run_inlining(env: &mut GlobalEnv, scope: RewritingScope, keep_inline_functions: bool) { - debug!("Inlining"); // Get non-inline function roots for running inlining. // Also generate an error for any target inline functions lacking a body to inline. let mut targets = RewriteTargets::create(env, scope); @@ -477,18 +478,22 @@ impl<'env, 'inliner> ExpRewriterFunctions for OuterInlinerRewriter<'env, 'inline }; // inline here if let Some(expr) = body_expr { - trace!( - "inlining function `{}` with args `{}`", - self.env.dump_fun(&func_env), - args.iter() - .map(|exp| format!("{}", exp.as_ref().display(self.env))) - .collect::>() - .join(","), - ); + if DEBUG { + trace!( + "inlining function `{}` with args `{}`", + self.env.dump_fun(&func_env), + args.iter() + .map(|exp| format!("{}", exp.as_ref().display(self.env))) + .collect::>() + .join(","), + ); + } let rewritten = InlinedRewriter::inline_call( self.env, call_id, &func_loc, &expr, type_args, parameters, args, ); - trace!("After inlining, expr is `{}`", rewritten.display(self.env)); + if DEBUG { + trace!("After inlining, expr is `{}`", rewritten.display(self.env)); + } Some(rewritten) } else { None diff --git a/third_party/move/move-compiler-v2/src/lib.rs b/third_party/move/move-compiler-v2/src/lib.rs index 7f5c6c4139c43..3fa9674ba0cde 100644 --- a/third_party/move/move-compiler-v2/src/lib.rs +++ b/third_party/move/move-compiler-v2/src/lib.rs @@ -75,6 +75,8 @@ use move_symbol_pool::Symbol; pub use options::Options; use std::{collections::BTreeSet, path::Path}; +const DEBUG: bool = false; + /// Run Move compiler and print errors to stderr. pub fn run_move_compiler_to_stderr( options: Options, @@ -107,7 +109,9 @@ where let mut targets = run_bytecode_gen(&env); check_errors(&env, emitter, "code generation errors")?; - debug!("After bytecode_gen, GlobalEnv={}", env.dump_env()); + if DEBUG { + debug!("After bytecode_gen, GlobalEnv={}", env.dump_env()); + } // Run transformation pipeline let pipeline = bytecode_pipeline(&env); @@ -142,10 +146,12 @@ where let modules_and_scripts = run_file_format_gen(&mut env, &targets); check_errors(&env, emitter, "assembling errors")?; - debug!( - "File format bytecode:\n{}", - disassemble_compiled_units(&modules_and_scripts)? - ); + if DEBUG { + debug!( + "File format bytecode:\n{}", + disassemble_compiled_units(&modules_and_scripts)? + ); + } let annotated_units = annotate_units(modules_and_scripts); run_bytecode_verifier(&annotated_units, &mut env); diff --git a/third_party/move/move-compiler-v2/src/logging.rs b/third_party/move/move-compiler-v2/src/logging.rs index 4284ae7a5b192..03fae1531939e 100644 --- a/third_party/move/move-compiler-v2/src/logging.rs +++ b/third_party/move/move-compiler-v2/src/logging.rs @@ -34,10 +34,15 @@ //! use the boolean macro `log_enabled!(log::Level::Debug)` to check whether a given //! level is enabled. //! -//! In general it is good to keep INFO and higher severity log messages in the code. They -//! may help to debug customer issues in production. However, for keeping the code base clean, -//! uses of the `debug!` and lower logging level should be kept minimal and possibly removed -//! eliminated. Its a judgement call where and for how long to leave them in code. +//! General practice is to use, besides `warn!`, `info!` for progress messages, +//! and `debug!` for helping to debug problems with ready code. `debug!` can also be used +//! during development of a module, but should then be made conditional as in: +//! +//! ```ignore +//! const DEBUG: bool = false; +//! ... +//! if DEBUG { debug!(..) } +//! ``` use flexi_logger::{DeferredNow, FileSpec, LogSpecification, Logger}; use log::Record; From a2bf54b3f8589f2a5d638ffe0acb86ba96fdb62f Mon Sep 17 00:00:00 2001 From: Bo Wu Date: Fri, 13 Dec 2024 09:00:00 -0800 Subject: [PATCH 74/78] add type annotation to python code --- testsuite/replay-verify/README.md | 29 ++-- testsuite/replay-verify/archive_disk_utils.py | 112 +++++++++------ testsuite/replay-verify/main.py | 134 +++++++++--------- 3 files changed, 159 insertions(+), 116 deletions(-) diff --git a/testsuite/replay-verify/README.md b/testsuite/replay-verify/README.md index 457ca421bc087..1c26e26d39288 100644 --- a/testsuite/replay-verify/README.md +++ b/testsuite/replay-verify/README.md @@ -1,12 +1,23 @@ -This script orchestrates the replay and verification of blockchain data using Kubernetes pods. It defines a WorkerPod class to manage individual pods, handling their status, logs, and environment variables. The ReplayScheduler class schedules tasks for these pods, ensuring they run sequentially while managing retries, logging, and error handling. It supports scheduling from specific blockchain versions, skipping defined ranges, and collecting logs from failed or mismatched transactions. The script uses Kubernetes API for pod management and includes configurable hyperparameters for sharding, retries, concurrency, and delays. The main function initializes the scheduler and starts the scheduling process from scratch. +# Replay Verification Tools -## Prerequiste -Install minikube +This folder contains tools for managing and provisioning archive storage used in replay verifying for the Aptos blockchain networks. + +## Files + +### main.py + +The main script for executing replay verify tests. This script is responsible for: + +- Running replay verification tests against specified networks (testnet/mainnet) +- Verifying transaction execution matches expected results +- Handling test orchestration and reporting + +### archive_disk_utils.py + +A utility script for managing archive storage disks used in replay verification. This script: + +- Provisions Google Cloud Storage disks for storing blockchain archive data +- Supports both testnet and mainnet networks +- Is called by GitHub Actions workflows to automatically manage storage resources -## Local test -minikube start --mount --mount-string="/mnt/testnet_archive:/mnt/testnet_archive" --memory=81920 --cpus=17 -minikb apply -f ./testnet-archive.yaml -poetry shell -poetry install # install kubenetes -poetry run \ No newline at end of file diff --git a/testsuite/replay-verify/archive_disk_utils.py b/testsuite/replay-verify/archive_disk_utils.py index b6ddf2379d55a..02eb746899085 100644 --- a/testsuite/replay-verify/archive_disk_utils.py +++ b/testsuite/replay-verify/archive_disk_utils.py @@ -12,6 +12,7 @@ wait_exponential, retry_if_exception_type, ) +from typing import Tuple, List, Optional, Any # Constants @@ -33,11 +34,11 @@ ZONE = "us-central1-a" -def get_region_from_zone(zone): +def get_region_from_zone(zone: str) -> str: return zone.rsplit("-", 1)[0] -def get_kubectl_credentials(project_id, region, cluster_name): +def get_kubectl_credentials(project_id: str, region: str, cluster_name: str) -> None: try: # Command to get kubectl credentials for the cluster command = [ @@ -57,7 +58,9 @@ def get_kubectl_credentials(project_id, region, cluster_name): logger.error(f"Error fetching kubectl credentials: {e}") -def get_snapshot_source_pv_and_zone(project_id, region, cluster_id, namespace): +def get_snapshot_source_pv_and_zone( + project_id: str, region: str, cluster_id: str, namespace: str +) -> Tuple[str, Optional[str]]: get_kubectl_credentials(project_id, region, cluster_id) # Use the Kubernetes API @@ -101,13 +104,13 @@ def get_snapshot_source_pv_and_zone(project_id, region, cluster_id, namespace): def create_snapshot_from_backup_pods( - snapshot_name, - source_project, - source_cluster, - source_region, - source_namespace, - target_project, -): + snapshot_name: str, + source_project: str, + source_cluster: str, + source_region: str, + source_namespace: str, + target_project: str, +) -> None: (volume_name, zone) = get_snapshot_source_pv_and_zone( source_project, source_region, source_cluster, source_namespace ) @@ -121,12 +124,12 @@ def create_snapshot_from_backup_pods( def create_snapshot_with_gcloud( - snapshot_name, - source_project, - source_volume, - source_zone, - target_project, -): + snapshot_name: str, + source_project: str, + source_volume: str, + source_zone: str, + target_project: str, +) -> None: # delete the snapshot if it already exists snapshot_client = compute_v1.SnapshotsClient() try: @@ -173,7 +176,9 @@ def create_snapshot_with_gcloud( raise Exception(f"Error creating snapshot: {e}") -def delete_disk(disk_client, project, zone, disk_name): +def delete_disk( + disk_client: compute_v1.DisksClient, project: str, zone: str, disk_name: str +) -> None: # Check if the disk already exists try: @@ -189,7 +194,7 @@ def delete_disk(disk_client, project, zone, disk_name): logger.info(f"Disk {e} {disk_name} does not exist, no delete needed.") -def generate_disk_name(run_id, snapshot_name, pvc_id): +def generate_disk_name(run_id: str, snapshot_name: str, pvc_id: int) -> str: return f"{snapshot_name}-{run_id}-{pvc_id}" @@ -202,8 +207,13 @@ def generate_disk_name(run_id, snapshot_name, pvc_id): ), ) def create_disk_from_snapshot( - disk_client, snapshot_client, project, zone, snapshot_name, disk_name -): + disk_client: compute_v1.DisksClient, + snapshot_client: compute_v1.SnapshotsClient, + project: str, + zone: str, + snapshot_name: str, + disk_name: str, +) -> None: start_time = time.time() delete_disk(disk_client, project, zone, disk_name) @@ -228,16 +238,16 @@ def create_disk_from_snapshot( # require getting a hold of the kubectrl of the cluster # eg: gcloud container clusters get-credentials replay-on-archive --region us-central1 --project replay-verify def create_final_snapshot( - project, - zone, - cluster_name, - og_snapshot_name, - snapshot_name, - disk_name, - pv_name, - pvc_name, - namespace, -): + project: str, + zone: str, + cluster_name: str, + og_snapshot_name: str, + snapshot_name: str, + disk_name: str, + pv_name: str, + pvc_name: str, + namespace: str, +) -> None: disk_client = compute_v1.DisksClient() snapshot_client = compute_v1.SnapshotsClient() create_disk_from_snapshot( @@ -286,7 +296,7 @@ def create_final_snapshot( delete_pv_and_pvc(repair_pv, repair_pvc, namespace) -def is_job_pod_cleanedup(namespace, job_name): +def is_job_pod_cleanedup(namespace: str, job_name: str) -> bool: config.load_kube_config() v1 = client.BatchV1Api() try: @@ -306,7 +316,12 @@ def is_job_pod_cleanedup(namespace, job_name): return True -def wait_for_operation(project, zone, operation_name, zone_operations_client): +def wait_for_operation( + project: str, + zone: str, + operation_name: str, + zone_operations_client: compute_v1.ZoneOperationsClient, +) -> Any: start_time = time.time() timeout = 3600 # 1 hour timeout @@ -329,7 +344,7 @@ def wait_for_operation(project, zone, operation_name, zone_operations_client): time.sleep(20) -def delete_pv_and_pvc(pv_name, pvc_name, namespace): +def delete_pv_and_pvc(pv_name: str, pvc_name: str, namespace: str) -> None: config.load_kube_config() v1 = client.CoreV1Api() try: @@ -347,8 +362,15 @@ def delete_pv_and_pvc(pv_name, pvc_name, namespace): def create_persistent_volume( - project, zone, disk_name, pv_name, pvc_name, namespace, read_only, label="" -): + project: str, + zone: str, + disk_name: str, + pv_name: str, + pvc_name: str, + namespace: str, + read_only: bool, + label: str = "", +) -> None: config.load_kube_config() v1 = client.CoreV1Api() access_mode = "ReadWriteOnce" if not read_only else "ReadOnlyMany" @@ -422,8 +444,14 @@ def create_persistent_volume( def create_repair_disk_and_its_snapshot( - project, zone, cluster_name, og_snapshot_name, snapshot_name, prefix, namespace -): + project: str, + zone: str, + cluster_name: str, + og_snapshot_name: str, + snapshot_name: str, + prefix: str, + namespace: str, +) -> None: tasks = [] for copy in range(DISK_COPIES): @@ -455,7 +483,7 @@ def create_repair_disk_and_its_snapshot( logger.error(f"Task generated an exception: {e}") -def parse_args(): +def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, description=__doc__, @@ -465,7 +493,9 @@ def parse_args(): return args -def create_one_pvc_from_snapshot(pvc_name, snapshot_name, namespace, label): +def create_one_pvc_from_snapshot( + pvc_name: str, snapshot_name: str, namespace: str, label: str +) -> str: config.load_kube_config() api_instance = client.CoreV1Api() storage_size = "10Ti" if TESTNET_SNAPSHOT_NAME in snapshot_name else "8Ti" @@ -500,8 +530,8 @@ def create_one_pvc_from_snapshot(pvc_name, snapshot_name, namespace, label): def create_replay_verify_pvcs_from_snapshot( - run_id, snapshot_name, namespace, pvc_num, label -): + run_id: str, snapshot_name: str, namespace: str, pvc_num: int, label: str +) -> List[str]: config.load_kube_config() api_instance = client.CustomObjectsApi() diff --git a/testsuite/replay-verify/main.py b/testsuite/replay-verify/main.py index 2d661dee11366..c6d31174b4e6b 100644 --- a/testsuite/replay-verify/main.py +++ b/testsuite/replay-verify/main.py @@ -48,7 +48,9 @@ def from_string(cls, name: str): logger = logging.getLogger(__name__) -def construct_humio_url(labels_run, pod_name, start_time, end_time): +def construct_humio_url( + labels_run: str, pod_name: str, start_time: float, end_time: float +) -> str: query = f'#k8s.cluster = "devinfra-usce1-0" | k8s.labels.run = "{labels_run}" | "k8s.pod_name" = "{pod_name}"' params = { @@ -64,7 +66,7 @@ def construct_humio_url(labels_run, pod_name, start_time, end_time): return url -def set_env_var(container, name, value): +def set_env_var(container: dict, name: str, value: str) -> None: if "env" not in container: container["env"] = [] @@ -78,23 +80,39 @@ def set_env_var(container, name, value): container["env"].append({"name": name, "value": value}) -def get_env_var(name, default_value=""): +def get_env_var(name: str, default_value: str = "") -> str: return os.getenv(name, default_value) +class ReplayConfig: + def __init__(self, network: Network) -> None: + if network == Network.TESTNET: + self.concurrent_replayer = 20 + self.pvc_number = 5 + self.min_range_size = 10_000 + self.range_size = 5_000_000 + self.timeout_secs = 900 + else: + self.concurrent_replayer = 18 + self.pvc_number = 8 + self.min_range_size = 10_000 + self.range_size = 2_000_000 + self.timeout_secs = 400 + + class WorkerPod: def __init__( self, - id, - start_version, - end_version, - label, - image, - pvcs, - replay_config, - network=Network.TESTNET, - namespace="default", - ): + id: int, + start_version: int, + end_version: int, + label: str, + image: str, + pvcs: list[str], + replay_config: ReplayConfig, + network: Network = Network.TESTNET, + namespace: str = "default", + ) -> None: self.id = id self.client = client.CoreV1Api() self.name = f"{label}-replay-verify-{start_version}-{end_version}" @@ -110,7 +128,7 @@ def __init__( self.pvcs = pvcs self.config = replay_config - def update_status(self): + def update_status(self) -> None: if self.status is not None and self.status.status.phase in [ "Succeeded", "Failed", @@ -118,36 +136,36 @@ def update_status(self): return self.status = self.get_pod_status() - def is_completed(self): + def is_completed(self) -> bool: self.update_status() if self.status and self.status.status.phase in ["Succeeded", "Failed"]: return True return False - def is_failed(self): + def is_failed(self) -> bool: self.update_status() if self.status and self.status.status.phase == "Failed": return True return False - def should_reschedule(self): + def should_reschedule(self) -> bool: if self.get_failure_reason() == "Evicted": return True return False - def get_failure_reason(self): + def get_failure_reason(self) -> str | None: self.update_status() if self.status and self.status.status.phase == "Failed": return self.status.status.reason return None - def get_phase(self): + def get_phase(self) -> str | None: self.update_status() if self.status: return self.status.status.phase return None - def has_txn_mismatch(self): + def has_txn_mismatch(self) -> bool: if self.status: container_statuses = self.status.status.container_statuses if ( @@ -158,14 +176,14 @@ def has_txn_mismatch(self): return container_statuses[0].state.terminated.exit_code == 2 return False - def get_target_db_dir(self): + def get_target_db_dir(self) -> str: return "/mnt/archive/db" - def get_claim_name(self): + def get_claim_name(self) -> str: idx = self.id % len(self.pvcs) return self.pvcs[idx] - def start(self): + def start(self) -> None: # Load the worker YAML from the file with open("replay-verify-worker-template.yaml", "r") as f: pod_manifest = yaml.safe_load(f) @@ -243,35 +261,19 @@ def get_humio_log_link(self): return construct_humio_url(self.label, self.name, self.start_time, time.time()) -class ReplayConfig: - def __init__(self, network): - if network == Network.TESTNET: - self.concurrent_replayer = 20 - self.pvc_number = 5 - self.min_range_size = 10_000 - self.range_size = 5_000_000 - self.timeout_secs = 900 - else: - self.concurrent_replayer = 18 - self.pvc_number = 8 - self.min_range_size = 10_000 - self.range_size = 2_000_000 - self.timeout_secs = 400 - - class TaskStats: - def __init__(self, name): - self.name = name - self.start_time = time.time() - self.end_time = None - self.retry_count = 0 - self.durations = [] - - def set_end_time(self): + def __init__(self, name: str) -> None: + self.name: str = name + self.start_time: float = time.time() + self.end_time: float | None = None + self.retry_count: int = 0 + self.durations: list[float] = [] + + def set_end_time(self) -> None: self.end_time = time.time() self.durations.append(self.end_time - self.start_time) - def increment_retry_count(self): + def increment_retry_count(self) -> None: self.retry_count += 1 def __str__(self) -> str: @@ -281,17 +283,17 @@ def __str__(self) -> str: class ReplayScheduler: def __init__( self, - id, - start_version, - end_version, - ranges_to_skip, - worker_cnt, - range_size, - image, - replay_config, - network=Network.TESTNET, - namespace="default", - ): + id: str, + start_version: int, + end_version: int, + ranges_to_skip: list[tuple[int, int]], + worker_cnt: int, + range_size: int, + image: str, + replay_config: ReplayConfig, + network: Network = Network.TESTNET, + namespace: str = "default", + ) -> None: KubernetesConfig.load_kube_config() self.client = client.CoreV1Api() self.id = id @@ -327,7 +329,7 @@ def __str__(self): def get_label(self): return f"{self.id}-{self.network}" - def create_tasks(self): + def create_tasks(self) -> None: current = self.start_version sorted_skips = [ @@ -372,7 +374,7 @@ def create_pvc_from_snapshot(self): assert len(pvcs) == self.config.pvc_number, "failed to create all pvcs" self.pvcs = pvcs - def schedule(self, from_scratch=False): + def schedule(self, from_scratch: bool = False) -> None: if from_scratch: self.kill_all_pods() self.create_tasks() @@ -452,7 +454,7 @@ def delete_all_pvcs(self): label_selector=f"run={self.get_label()}", ) - def collect_all_failed_logs(self): + def collect_all_failed_logs(self) -> tuple[list[str], list[str]]: logger.info("Collecting logs from remaining pods") all_completed = False while not all_completed: @@ -475,7 +477,7 @@ def print_stats(self): # read skip ranges from gcp bucket -def read_skip_ranges(network): +def read_skip_ranges(network: str) -> tuple[int, int, list[tuple[int, int]]]: storage_client = storage.Client() bucket = storage_client.bucket("replay_verify_skip_ranges") source_blob_name = f"{network}_skip_ranges.json" @@ -490,7 +492,7 @@ def read_skip_ranges(network): return (data["start"], data["end"], skip_ranges) -def parse_args(): +def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, description=__doc__, @@ -509,7 +511,7 @@ def parse_args(): return args -def get_image(image_tag=None): +def get_image(image_tag: str | None = None) -> str: shell = forge.LocalShell() git = forge.Git(shell) image_name = "tools" @@ -527,7 +529,7 @@ def get_image(image_tag=None): return full_image -def print_logs(failed_workpod_logs, txn_mismatch_logs): +def print_logs(failed_workpod_logs: list[str], txn_mismatch_logs: list[str]) -> None: if len(failed_workpod_logs) > 0: logger.info("Failed workpods found") for log in failed_workpod_logs: From f2b3234c10ee55e77397846a78f34f2b1381d6f7 Mon Sep 17 00:00:00 2001 From: Bo Wu Date: Sun, 15 Dec 2024 20:55:50 -0800 Subject: [PATCH 75/78] add retry to get pod status --- testsuite/replay-verify/main.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/testsuite/replay-verify/main.py b/testsuite/replay-verify/main.py index c6d31174b4e6b..566a850cf1585 100644 --- a/testsuite/replay-verify/main.py +++ b/testsuite/replay-verify/main.py @@ -10,6 +10,8 @@ import json import argparse import sys +from tenacity import retry, stop_after_attempt, wait_fixed, retry_if_exception_type + sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "../.."))) @@ -251,6 +253,14 @@ def get_pod_exit_code(self): return container_status.state.terminated.exit_code return None + @retry( + stop=stop_after_attempt(MAX_RETRIES), + wait=wait_fixed(RETRY_DELAY), + retry=retry_if_exception_type(ApiException), + before_sleep=lambda retry_state: logger.warning( + f"Retry {retry_state.attempt_number}/{MAX_RETRIES} failed: {retry_state.outcome.exception()}" + ) + ) def get_pod_status(self): pod_status = self.client.read_namespaced_pod_status( name=self.name, namespace=self.namespace From 81a2f4268b9e0f25cb6e1ce5c28bba0a34c27604 Mon Sep 17 00:00:00 2001 From: Bo Wu Date: Sun, 15 Dec 2024 21:07:17 -0800 Subject: [PATCH 76/78] add image-tag to cancel group --- .github/workflows/replay-verify.yaml | 2 +- testsuite/replay-verify/README.md | 10 ++++++++++ testsuite/replay-verify/archive_disk_utils.py | 10 +++++++++- testsuite/replay-verify/main.py | 10 +++++++++- 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/.github/workflows/replay-verify.yaml b/.github/workflows/replay-verify.yaml index 8de27ba546a80..6110eede6036b 100644 --- a/.github/workflows/replay-verify.yaml +++ b/.github/workflows/replay-verify.yaml @@ -42,7 +42,7 @@ permissions: # cancel redundant builds concurrency: # cancel redundant builds on PRs (only on PR, not on branches) - group: ${{ github.workflow }}-${{ (github.event_name == 'pull_request' && github.ref) || github.sha }} + group: ${{ github.workflow }}-${{ (github.event_name == 'pull_request' && github.ref) || github.sha }}-${{ inputs.IMAGE_TAG || 'latest' }} cancel-in-progress: true jobs: diff --git a/testsuite/replay-verify/README.md b/testsuite/replay-verify/README.md index 1c26e26d39288..fc829bbe77b87 100644 --- a/testsuite/replay-verify/README.md +++ b/testsuite/replay-verify/README.md @@ -11,6 +11,11 @@ The main script for executing replay verify tests. This script is responsible fo - Running replay verification tests against specified networks (testnet/mainnet) - Verifying transaction execution matches expected results - Handling test orchestration and reporting +``` test with cli +cd testsuite/replay-verify +poetry shell +python main.py --image_tag YOUR_IMAGE_TAG --network testnet +``` ### archive_disk_utils.py @@ -19,5 +24,10 @@ A utility script for managing archive storage disks used in replay verification. - Provisions Google Cloud Storage disks for storing blockchain archive data - Supports both testnet and mainnet networks - Is called by GitHub Actions workflows to automatically manage storage resources +```test with cli +cd testsuite/replay-verify +poetry shell +python archive_disk_utils.py --network mainnet +``` diff --git a/testsuite/replay-verify/archive_disk_utils.py b/testsuite/replay-verify/archive_disk_utils.py index 02eb746899085..0e02c04497f6f 100644 --- a/testsuite/replay-verify/archive_disk_utils.py +++ b/testsuite/replay-verify/archive_disk_utils.py @@ -201,7 +201,7 @@ def generate_disk_name(run_id: str, snapshot_name: str, pvc_id: int) -> str: @retry( stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10), - retry=retry_if_exception_type((ApiException, Exception)), + retry=retry_if_exception_type(ApiException), before_sleep=lambda retry_state: logger.warning( f"Retrying initial disk creation after error: {retry_state.outcome.exception()}" ), @@ -493,6 +493,14 @@ def parse_args() -> argparse.Namespace: return args +@retry( + stop=stop_after_attempt(3), + wait=wait_exponential(multiplier=1, min=4, max=10), + retry=retry_if_exception_type((ApiException, Exception)), + before_sleep=lambda retry_state: logger.warning( + f"Retrying creating pvc from snapshot after error: {retry_state.outcome.exception()}" + ), +) def create_one_pvc_from_snapshot( pvc_name: str, snapshot_name: str, namespace: str, label: str ) -> str: diff --git a/testsuite/replay-verify/main.py b/testsuite/replay-verify/main.py index 566a850cf1585..dd889745087bd 100644 --- a/testsuite/replay-verify/main.py +++ b/testsuite/replay-verify/main.py @@ -237,6 +237,14 @@ def start(self) -> None: ) time.sleep(RETRY_DELAY) + @retry( + stop=stop_after_attempt(MAX_RETRIES), + wait=wait_fixed(RETRY_DELAY), + retry=retry_if_exception_type(ApiException), + before_sleep=lambda retry_state: logger.warning( + f"Retry {retry_state.attempt_number}/{MAX_RETRIES} failed: {retry_state.outcome.exception()}" + ), + ) def delete_pod(self): response = self.client.delete_namespaced_pod( name=self.name, @@ -259,7 +267,7 @@ def get_pod_exit_code(self): retry=retry_if_exception_type(ApiException), before_sleep=lambda retry_state: logger.warning( f"Retry {retry_state.attempt_number}/{MAX_RETRIES} failed: {retry_state.outcome.exception()}" - ) + ), ) def get_pod_status(self): pod_status = self.client.read_namespaced_pod_status( From 55788f7a6ecfac195e7322eeead42383590d2d98 Mon Sep 17 00:00:00 2001 From: Josh Lind Date: Sun, 5 Jan 2025 19:07:28 -0500 Subject: [PATCH 77/78] [Devtools] Update comment for merge-base commit delays. --- devtools/aptos-cargo-cli/src/common.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devtools/aptos-cargo-cli/src/common.rs b/devtools/aptos-cargo-cli/src/common.rs index 3e93737ee401b..43e5cca1f3195 100644 --- a/devtools/aptos-cargo-cli/src/common.rs +++ b/devtools/aptos-cargo-cli/src/common.rs @@ -45,7 +45,7 @@ const IGNORED_DETERMINATOR_PATHS: [&str; 8] = [ "terraform/*", ]; -// The maximum number of days allowed since the merge-base commit for the branch +// The maximum number of days allowed since the merge-base commit for the branch. const MAX_NUM_DAYS_SINCE_MERGE_BASE: u64 = 7; // The delimiter used to separate the package path and the package name. From 20e25a4a2daf2e27a87030136da5d534da5dab8b Mon Sep 17 00:00:00 2001 From: Zekun Wang <41706692+fEst1ck@users.noreply.github.com> Date: Mon, 6 Jan 2025 13:01:04 -0500 Subject: [PATCH 78/78] [Bugfix][Compiler-V2] Fix `public(package)` causing unit test errors (#15627) * tmp fix * bugfix * format * fix bug and comment --------- Co-authored-by: Zekun Wang --- .../move-compiler-v2/src/env_pipeline/function_checker.rs | 4 +++- third_party/move/move-model/src/builder/model_builder.rs | 5 ++++- third_party/move/move-model/src/model.rs | 8 +++----- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/third_party/move/move-compiler-v2/src/env_pipeline/function_checker.rs b/third_party/move/move-compiler-v2/src/env_pipeline/function_checker.rs index 958a13bde6425..325865f81336a 100644 --- a/third_party/move/move-compiler-v2/src/env_pipeline/function_checker.rs +++ b/third_party/move/move-compiler-v2/src/env_pipeline/function_checker.rs @@ -71,7 +71,7 @@ pub fn check_for_function_typed_parameters(env: &mut GlobalEnv) { } for caller_module in env.get_modules() { - if caller_module.is_primary_target() { + if caller_module.is_target() { for caller_func in caller_module.get_functions() { if !lambda_params_ok || !lambda_return_ok { let caller_name = caller_func.get_full_name_str(); @@ -316,6 +316,7 @@ pub fn check_access_and_use(env: &mut GlobalEnv, before_inlining: bool) { let mut private_funcs: BTreeSet = BTreeSet::new(); for caller_module in env.get_modules() { + // TODO(#13745): fix when we can tell in general if two modules are in the same package if caller_module.is_primary_target() { let caller_module_id = caller_module.get_id(); let caller_module_has_friends = !caller_module.has_no_friends(); @@ -383,6 +384,7 @@ pub fn check_access_and_use(env: &mut GlobalEnv, before_inlining: bool) { == caller_func.module_env.self_address() { // if callee is also a primary target, then they are in the same package + // TODO(#13745): fix when we can tell in general if two modules are in the same package if callee_func.module_env.is_primary_target() { // we should've inferred the friend declaration panic!( diff --git a/third_party/move/move-model/src/builder/model_builder.rs b/third_party/move/move-model/src/builder/model_builder.rs index 55c3b34520c19..60bf8972b7f9d 100644 --- a/third_party/move/move-model/src/builder/model_builder.rs +++ b/third_party/move/move-model/src/builder/model_builder.rs @@ -490,7 +490,10 @@ impl<'env> ModelBuilder<'env> { let target_modules = self .env .get_modules() - .filter(|module_env| module_env.is_primary_target() && !module_env.is_script_module()) + .filter(|module_env| { + (module_env.is_primary_target() || module_env.is_target()) + && !module_env.is_script_module() + }) .map(|module_env| module_env.get_id()) .collect_vec(); for cur_mod in target_modules { diff --git a/third_party/move/move-model/src/model.rs b/third_party/move/move-model/src/model.rs index 175923e0dade2..1280a6c3e9911 100644 --- a/third_party/move/move-model/src/model.rs +++ b/third_party/move/move-model/src/model.rs @@ -2997,9 +2997,7 @@ impl<'env> ModuleEnv<'env> { /// Returns the set of modules in the current package, /// whose public(package) functions are called or referenced in the current module. - /// Requires: `self` is a primary target. pub fn need_to_be_friended_by(&self) -> BTreeSet { - debug_assert!(self.is_primary_target()); let mut deps = BTreeSet::new(); if self.is_script_module() { return deps; @@ -3024,12 +3022,12 @@ impl<'env> ModuleEnv<'env> { } /// Returns true if functions in the current module can call a public(package) function in the given module. - /// Requires: `self` is a primary target. fn can_call_package_fun_in(&self, other: &Self) -> bool { - debug_assert!(self.is_primary_target()); !self.is_script_module() && !other.is_script_module() - && other.is_primary_target() + // TODO(#13745): fix this when we have a way to check if + // two non-primary targets are in the same package + && (!self.is_primary_target() || other.is_primary_target()) && self.self_address() == other.self_address() }