From 4e6f4c8675df7f6fbe1496e0689cfa6ec8ac8b01 Mon Sep 17 00:00:00 2001 From: welbon <2261238+welbon@users.noreply.github.com> Date: Tue, 31 Dec 2024 16:19:45 +0800 Subject: [PATCH 01/29] [asset-mapping] Added the move code for asset mapping --- .../src/starcoin_framework_sdk_builder.rs | 69 ++++++ vm/framework/starcoin-framework/doc/coin.md | 158 +++++++------- .../starcoin-framework/doc/overview.md | 1 + .../sources/asset_mapping.move | 196 ++++++++++++++++++ .../starcoin-framework/sources/coin.move | 1 + 5 files changed, 346 insertions(+), 79 deletions(-) create mode 100644 vm/framework/starcoin-framework/sources/asset_mapping.move diff --git a/vm/framework/cached-packages/src/starcoin_framework_sdk_builder.rs b/vm/framework/cached-packages/src/starcoin_framework_sdk_builder.rs index 0cc0595a14..36e295e48f 100644 --- a/vm/framework/cached-packages/src/starcoin_framework_sdk_builder.rs +++ b/vm/framework/cached-packages/src/starcoin_framework_sdk_builder.rs @@ -150,6 +150,21 @@ pub enum EntryFunctionCall { cap_update_table: Vec, }, + /// Assigns tokens to a recipient account with proof verification + /// @param token_issuer - The token issuer signer + /// @param receiper - Recipient address + /// @param proove - Proof data for verification + /// @param amount - Amount of tokens to assign + /// Requirements: + /// - Valid proof must be provided + /// - Sufficient balance must exist + AssetMappingAssignToAccount { + t: TypeTag, + receiper: AccountAddress, + proove: Vec, + amount: u64, + }, + CoinCreateCoinConversionMap {}, /// Create STC pairing by passing `StarcoinCoin`. @@ -642,6 +657,12 @@ impl EntryFunctionCall { new_public_key_bytes, cap_update_table, ), + AssetMappingAssignToAccount { + t, + receiper, + proove, + amount, + } => asset_mapping_assign_to_account(t, receiper, proove, amount), CoinCreateCoinConversionMap {} => coin_create_coin_conversion_map(), CoinCreatePairing { coin_type } => coin_create_pairing(coin_type), CoinMigrateToFungibleStore { coin_type } => coin_migrate_to_fungible_store(coin_type), @@ -1254,6 +1275,35 @@ pub fn account_rotate_authentication_key_with_rotation_capability( )) } +/// Assigns tokens to a recipient account with proof verification +/// @param token_issuer - The token issuer signer +/// @param receiper - Recipient address +/// @param proove - Proof data for verification +/// @param amount - Amount of tokens to assign +/// Requirements: +/// - Valid proof must be provided +/// - Sufficient balance must exist +pub fn asset_mapping_assign_to_account( + t: TypeTag, + receiper: AccountAddress, + proove: Vec, + amount: u64, +) -> TransactionPayload { + TransactionPayload::EntryFunction(EntryFunction::new( + ModuleId::new( + AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]), + ident_str!("asset_mapping").to_owned(), + ), + ident_str!("assign_to_account").to_owned(), + vec![t], + vec![ + bcs::to_bytes(&receiper).unwrap(), + bcs::to_bytes(&proove).unwrap(), + bcs::to_bytes(&amount).unwrap(), + ], + )) +} + pub fn coin_create_coin_conversion_map() -> TransactionPayload { TransactionPayload::EntryFunction(EntryFunction::new( ModuleId::new( @@ -2521,6 +2571,21 @@ mod decoder { } } + pub fn asset_mapping_assign_to_account( + payload: &TransactionPayload, + ) -> Option { + if let TransactionPayload::EntryFunction(script) = payload { + Some(EntryFunctionCall::AssetMappingAssignToAccount { + t: script.ty_args().get(0)?.clone(), + receiper: bcs::from_bytes(script.args().get(0)?).ok()?, + proove: bcs::from_bytes(script.args().get(1)?).ok()?, + amount: bcs::from_bytes(script.args().get(2)?).ok()?, + }) + } else { + None + } + } + pub fn coin_create_coin_conversion_map( payload: &TransactionPayload, ) -> Option { @@ -3407,6 +3472,10 @@ static SCRIPT_FUNCTION_DECODER_MAP: once_cell::sync::Lazy + + +
fun spec_paired_metadata<CoinType>(): Option<Object<Metadata>> {
+   if (exists<CoinConversionMap>(@starcoin_framework)) {
+       let map = global<CoinConversionMap>(@starcoin_framework).coin_to_fungible_asset_map;
+       if (table::spec_contains(map, type_info::type_of<CoinType>())) {
+           let metadata = table::spec_get(map, type_info::type_of<CoinType>());
+           option::spec_some(metadata)
+       } else {
+           option::spec_none()
+       }
+   } else {
+       option::spec_none()
+   }
+}
+
+ + + + + + + +
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(
+       paired_metadata_opt
+   ) && primary_fungible_store::spec_primary_store_exists(account_addr, option::spec_borrow(paired_metadata_opt)))
+}
+
+ + + + + + + +
schema CoinSubAbortsIf<CoinType> {
+    amount: u64;
+    let addr = type_info::type_of<CoinType>().account_address;
+    let maybe_supply = global<CoinInfo<CoinType>>(addr).supply;
+    include (option::is_some(
+        maybe_supply
+    )) ==> optional_aggregator::SubAbortsIf { optional_aggregator: option::borrow(maybe_supply), value: amount };
+}
+
+ + + + + + + +
schema CoinAddAbortsIf<CoinType> {
+    amount: u64;
+    let addr = type_info::type_of<CoinType>().account_address;
+    let maybe_supply = global<CoinInfo<CoinType>>(addr).supply;
+    include (option::is_some(
+        maybe_supply
+    )) ==> optional_aggregator::AddAbortsIf { optional_aggregator: option::borrow(maybe_supply), value: amount };
+}
+
+ + + + + + + +
schema AbortsIfNotExistCoinInfo<CoinType> {
+    let addr = type_info::type_of<CoinType>().account_address;
+    aborts_if !exists<CoinInfo<CoinType>>(addr);
+}
+
+ + + ### Struct `AggregatableCoin` @@ -4219,85 +4298,6 @@ Get address by reflection. - - - - -
fun spec_paired_metadata<CoinType>(): Option<Object<Metadata>> {
-   if (exists<CoinConversionMap>(@starcoin_framework)) {
-       let map = global<CoinConversionMap>(@starcoin_framework).coin_to_fungible_asset_map;
-       if (table::spec_contains(map, type_info::type_of<CoinType>())) {
-           let metadata = table::spec_get(map, type_info::type_of<CoinType>());
-           option::spec_some(metadata)
-       } else {
-           option::spec_none()
-       }
-   } else {
-       option::spec_none()
-   }
-}
-
- - - - - - - -
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(
-       paired_metadata_opt
-   ) && primary_fungible_store::spec_primary_store_exists(account_addr, option::spec_borrow(paired_metadata_opt)))
-}
-
- - - - - - - -
schema CoinSubAbortsIf<CoinType> {
-    amount: u64;
-    let addr = type_info::type_of<CoinType>().account_address;
-    let maybe_supply = global<CoinInfo<CoinType>>(addr).supply;
-    include (option::is_some(
-        maybe_supply
-    )) ==> optional_aggregator::SubAbortsIf { optional_aggregator: option::borrow(maybe_supply), value: amount };
-}
-
- - - - - - - -
schema CoinAddAbortsIf<CoinType> {
-    amount: u64;
-    let addr = type_info::type_of<CoinType>().account_address;
-    let maybe_supply = global<CoinInfo<CoinType>>(addr).supply;
-    include (option::is_some(
-        maybe_supply
-    )) ==> optional_aggregator::AddAbortsIf { optional_aggregator: option::borrow(maybe_supply), value: amount };
-}
-
- - - - - - - -
schema AbortsIfNotExistCoinInfo<CoinType> {
-    let addr = type_info::type_of<CoinType>().account_address;
-    aborts_if !exists<CoinInfo<CoinType>>(addr);
-}
-
- - - ### Function `name` diff --git a/vm/framework/starcoin-framework/doc/overview.md b/vm/framework/starcoin-framework/doc/overview.md index 2b57111917..31f35ec1e8 100644 --- a/vm/framework/starcoin-framework/doc/overview.md +++ b/vm/framework/starcoin-framework/doc/overview.md @@ -16,6 +16,7 @@ This is the reference documentation of the Starcoin framework. - [`0x1::aggregator`](aggregator.md#0x1_aggregator) - [`0x1::aggregator_factory`](aggregator_factory.md#0x1_aggregator_factory) - [`0x1::aggregator_v2`](aggregator_v2.md#0x1_aggregator_v2) +- [`0x1::asset_mapping`](asset_mapping.md#0x1_asset_mapping) - [`0x1::bcs_util`](bcs_util.md#0x1_bcs_util) - [`0x1::block_reward`](block_reward.md#0x1_block_reward) - [`0x1::block_reward_config`](block_reward_config.md#0x1_block_reward_config) diff --git a/vm/framework/starcoin-framework/sources/asset_mapping.move b/vm/framework/starcoin-framework/sources/asset_mapping.move new file mode 100644 index 0000000000..89a78c886e --- /dev/null +++ b/vm/framework/starcoin-framework/sources/asset_mapping.move @@ -0,0 +1,196 @@ +/// Asset Mapping Module +/// This module implements functionality for managing fungible asset mappings in the Starcoin framework. +/// It provides capabilities for creating stores, managing balances, and assigning assets to accounts +/// with proof verification. +module starcoin_framework::asset_mapping { + + use std::error; + use std::signer; + + use starcoin_framework::coin; + use starcoin_framework::fungible_asset::{Self, FungibleStore, Metadata}; + use starcoin_framework::object; + use starcoin_framework::object::{ExtendRef, Object}; + use starcoin_framework::primary_fungible_store; + use starcoin_framework::stc_util; + use starcoin_framework::system_addresses; + use starcoin_std::debug; + use starcoin_std::smart_table; + + #[test_only] + use std::vector; + #[test_only] + use starcoin_framework::account; + #[test_only] + use starcoin_framework::starcoin_coin::{Self, STC}; + + /// AssetMappingStore represents a store for mapped assets + /// Contains: + /// - extend_ref: Reference for extending object capabilities + /// - fungible_store: The actual store holding fungible assets + struct AssetMappingStore has key, store { + extend_ref: ExtendRef, + fungible_store: Object, + } + + /// AssetMappingPool manages a collection of asset mapping stores + /// Contains: + /// - proof_root: Root hash for proof verification + /// - anchor_height: Block height anchor for the mapping + /// - token_stores: Smart table mapping metadata to stores + struct AssetMappingPool has key, store { + proof_root: vector, + anchor_height: u64, + token_stores: smart_table::SmartTable, AssetMappingStore> + } + + /// Error code for invalid signer + const EINVALID_SIGNER: u64 = 101; + const EINVALID_NOT_PROOF: u64 = 102; + + /// Initializes the asset mapping pool + /// @param framework - The framework signer + /// @param proof_root - Initial proof root for verification + /// @param anchor_height - Initial anchor height + /// Verifies the framework signer and creates a new AssetMappingPool + public fun initialize(framework: &signer, proof_root: vector, anchor_height: u64) { + assert!( + signer::address_of(framework) == system_addresses::get_starcoin_framework(), + error::unauthenticated(EINVALID_SIGNER) + ); + move_to(framework, AssetMappingPool { + proof_root, + anchor_height, + token_stores: smart_table::new, AssetMappingStore>(), + }); + } + + /// Creates a new store from a coin + /// @param token_issuer - The token issuer signer + /// @param coin - The coin to be stored + /// Requirements: + /// - Token issuer must be authorized for the given token type + /// - Converts coin to fungible asset and stores it + public fun create_store_from_coin(token_issuer: &signer, coin: coin::Coin) acquires AssetMappingPool { + let token_issuer_addr = signer::address_of(token_issuer); + assert!( + token_issuer_addr == stc_util::token_issuer(), + error::unauthenticated(EINVALID_SIGNER) + ); + + let fungible_asset = coin::coin_to_fungible_asset(coin); + let token_stores = + &mut borrow_global_mut(system_addresses::get_starcoin_framework()).token_stores; + + + let (metadata, fungible_store, extend_ref) = create_store_for_type(token_issuer); + fungible_asset::deposit(fungible_store, fungible_asset); + smart_table::add(token_stores, metadata, AssetMappingStore { + extend_ref, + fungible_store, + }); + } + + /// Creates a store for a specific token type + /// @param framework - The framework signer + /// @returns (metadata, store, extend_ref): + /// - metadata: Token metadata object + /// - store: Created fungible store + /// - extend_ref: Extension reference for the store + fun create_store_for_type(framework: &signer): (Object, Object, ExtendRef) { + debug::print(&std::string::utf8(b"asset_mapping::create_store_for_type | entered")); + + let metadata = coin::ensure_paired_metadata(); + let construct_ref = object::create_object_from_account(framework); + + let store = fungible_asset::create_store(&construct_ref, metadata); + + // Generate extend reference + let extend_ref = object::generate_extend_ref(&construct_ref); + debug::print(&std::string::utf8(b"asset_mapping::create_store_for_type | exited")); + + (metadata, store, extend_ref) + } + + /// Retrieves the balance for a specific token type + /// @returns Current balance of the token in the mapping pool + fun balance(): u64 acquires AssetMappingPool { + let metadata = coin::ensure_paired_metadata(); + let pool = borrow_global(system_addresses::get_starcoin_framework()); + fungible_asset::balance(smart_table::borrow(&pool.token_stores, metadata).fungible_store) + } + + /// Assigns tokens to a recipient account with proof verification + /// @param token_issuer - The token issuer signer + /// @param receiper - Recipient address + /// @param proove - Proof data for verification + /// @param amount - Amount of tokens to assign + /// Requirements: + /// - Valid proof must be provided + /// - Sufficient balance must exist + public entry fun assign_to_account( + token_issuer: &signer, + receiper: address, + proove: vector, + amount: u64 + ) acquires AssetMappingPool { + let metadata = coin::ensure_paired_metadata(); + let mapping_pool = borrow_global_mut(signer::address_of(token_issuer)); + let mapping_store = smart_table::borrow_mut(&mut mapping_pool.token_stores, metadata); + + assert!(computer_poove(proove), error::unauthenticated(EINVALID_NOT_PROOF)); + // fungible_asset::withdraw(&store.transfer_ref, store.fungible_store, to_account_primary_store, amount); + let store_signer = object::generate_signer_for_extending(&mapping_store.extend_ref); + fungible_asset::deposit( + primary_fungible_store::ensure_primary_store_exists(receiper, metadata), + fungible_asset::withdraw(&store_signer, mapping_store.fungible_store, amount) + ) + } + + /// Computes and verifies the provided proof + /// @param proove - The proof data to verify + /// @returns Boolean indicating proof validity + /// Note: Current implementation returns true (TODO) + public fun computer_poove(proove: vector) : bool { + // TODO(BobOng): implement this function + true + } + + /// Test function for asset mapping store creation and assignment + /// Tests: + /// - Store creation from coin + /// - Balance checking + /// - Asset assignment to account + /// - Final balance verification + #[test(framework= @starcoin_framework, alice=@0x123)] + fun test_asset_mapping_create_store_from_coin(framework: &signer, alice: &signer) acquires AssetMappingPool { + debug::print(&std::string::utf8(b"asset_mapping::test_asset_mapping_create_store_from_coin | entered")); + + let amount = 10000000000; + Self::initialize(framework, vector::empty(), 0); + + // create genesis account + account::create_account_for_test(signer::address_of(framework)); + + let (burn_cap, mint_cap) = starcoin_coin::initialize_for_test(framework); + coin::register(framework); + starcoin_coin::mint(framework, signer::address_of(framework), amount); + + let coin = coin::withdraw(framework, amount); + create_store_from_coin(framework, coin); + assert!(Self::balance() == amount, 10001); + + // Assign to alice + let alice_addr = signer::address_of(alice); + assign_to_account(framework, alice_addr, vector::empty(), amount); + assert!(Self::balance() == 0, 10002); + + let stc_metadata = coin::ensure_paired_metadata(); + assert!(primary_fungible_store::balance(alice_addr, stc_metadata) == amount, 10003); + + coin::destroy_burn_cap(burn_cap); + coin::destroy_mint_cap(mint_cap); + + debug::print(&std::string::utf8(b"asset_mapping::test_asset_mapping_create_store_from_coin | exited")); + } +} diff --git a/vm/framework/starcoin-framework/sources/coin.move b/vm/framework/starcoin-framework/sources/coin.move index 6a1835523c..acfe84336e 100644 --- a/vm/framework/starcoin-framework/sources/coin.move +++ b/vm/framework/starcoin-framework/sources/coin.move @@ -22,6 +22,7 @@ module starcoin_framework::coin { use starcoin_std::type_info::{Self, type_name, TypeInfo}; friend starcoin_framework::starcoin_coin; + friend starcoin_framework::asset_mapping; // // Errors. From 9de5f58983f94724f890a6d8ad3bb6669eb7c849 Mon Sep 17 00:00:00 2001 From: welbon <2261238+welbon@users.noreply.github.com> Date: Tue, 31 Dec 2024 16:23:01 +0800 Subject: [PATCH 02/29] [asset-mapping] fixed the function name --- .../starcoin-framework/sources/starcoin_account.move | 2 +- .../starcoin-framework/sources/starcoin_coin.move | 6 +++--- .../starcoin-framework/tests/starcoin_coin_tests.move | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/vm/framework/starcoin-framework/sources/starcoin_account.move b/vm/framework/starcoin-framework/sources/starcoin_account.move index a22e1cf91a..95987c7b35 100644 --- a/vm/framework/starcoin-framework/sources/starcoin_account.move +++ b/vm/framework/starcoin-framework/sources/starcoin_account.move @@ -437,7 +437,7 @@ module starcoin_framework::starcoin_account { use starcoin_framework::fungible_asset::Metadata; use starcoin_framework::starcoin_coin; - starcoin_coin::ensure_initialized_with_apt_fa_metadata_for_test(); + starcoin_coin::ensure_initialized_with_stc_fa_metadata_for_test(); let apt_metadata = object::address_to_object(@starcoin_fungible_asset); let user_addr = signer::address_of(user); diff --git a/vm/framework/starcoin-framework/sources/starcoin_coin.move b/vm/framework/starcoin-framework/sources/starcoin_coin.move index 77752758bf..56776a12fb 100644 --- a/vm/framework/starcoin-framework/sources/starcoin_coin.move +++ b/vm/framework/starcoin-framework/sources/starcoin_coin.move @@ -158,8 +158,8 @@ module starcoin_framework::starcoin_coin { use starcoin_framework::fungible_asset::FungibleAsset; #[test_only] - public fun mint_apt_fa_for_test(amount: u64): FungibleAsset acquires MintCapStore { - ensure_initialized_with_apt_fa_metadata_for_test(); + public fun mint_stc_fa_for_test(amount: u64): FungibleAsset acquires MintCapStore { + ensure_initialized_with_stc_fa_metadata_for_test(); coin::coin_to_fungible_asset( coin::mint( amount, @@ -169,7 +169,7 @@ module starcoin_framework::starcoin_coin { } #[test_only] - public fun ensure_initialized_with_apt_fa_metadata_for_test() { + public fun ensure_initialized_with_stc_fa_metadata_for_test() { let starcoin_framework = account::create_signer_for_test(@starcoin_framework); if (!exists(@starcoin_framework)) { if (!aggregator_factory::aggregator_factory_exists_for_testing()) { diff --git a/vm/framework/starcoin-framework/tests/starcoin_coin_tests.move b/vm/framework/starcoin-framework/tests/starcoin_coin_tests.move index 92dc654c82..09cbdc698a 100644 --- a/vm/framework/starcoin-framework/tests/starcoin_coin_tests.move +++ b/vm/framework/starcoin-framework/tests/starcoin_coin_tests.move @@ -7,18 +7,18 @@ module starcoin_framework::starcoin_coin_tests { use starcoin_framework::object::{Self, Object}; public fun mint_apt_fa_to_for_test(store: Object, amount: u64) { - fungible_asset::deposit(store, starcoin_coin::mint_apt_fa_for_test(amount)); + fungible_asset::deposit(store, starcoin_coin::mint_stc_fa_for_test(amount)); } public fun mint_apt_fa_to_primary_fungible_store_for_test( owner: address, amount: u64, ) { - primary_fungible_store::deposit(owner, starcoin_coin::mint_apt_fa_for_test(amount)); + primary_fungible_store::deposit(owner, starcoin_coin::mint_stc_fa_for_test(amount)); } #[test(starcoin_framework = @starcoin_framework)] - fun test_apt_setup_and_mint(starcoin_framework: &signer) { + fun test_stc_setup_and_mint(starcoin_framework: &signer) { let (burn_cap, mint_cap) = starcoin_coin::initialize_for_test(starcoin_framework); let coin = coin::mint(100, &mint_cap); let fa = coin::coin_to_fungible_asset(coin); @@ -37,7 +37,7 @@ module starcoin_framework::starcoin_coin_tests { #[test] fun test_fa_helpers_for_test() { assert!(!object::object_exists(@starcoin_fungible_asset), 0); - starcoin_coin::ensure_initialized_with_apt_fa_metadata_for_test(); + starcoin_coin::ensure_initialized_with_stc_fa_metadata_for_test(); assert!(object::object_exists(@starcoin_fungible_asset), 0); mint_apt_fa_to_primary_fungible_store_for_test(@starcoin_framework, 100); let metadata = object::address_to_object(@starcoin_fungible_asset); From 269e06a0f50488b561ff1896fbdc12c482d68c07 Mon Sep 17 00:00:00 2001 From: welbon <2261238+welbon@users.noreply.github.com> Date: Tue, 31 Dec 2024 16:23:21 +0800 Subject: [PATCH 03/29] [asset-mapping] Added the move code for asset mapping --- .../starcoin-framework/doc/asset_mapping.md | 372 ++++++++++++++++++ 1 file changed, 372 insertions(+) create mode 100644 vm/framework/starcoin-framework/doc/asset_mapping.md diff --git a/vm/framework/starcoin-framework/doc/asset_mapping.md b/vm/framework/starcoin-framework/doc/asset_mapping.md new file mode 100644 index 0000000000..db90454486 --- /dev/null +++ b/vm/framework/starcoin-framework/doc/asset_mapping.md @@ -0,0 +1,372 @@ + + + +# Module `0x1::asset_mapping` + +Asset Mapping Module +This module implements functionality for managing fungible asset mappings in the Starcoin framework. +It provides capabilities for creating stores, managing balances, and assigning assets to accounts +with proof verification. + + +- [Resource `AssetMappingStore`](#0x1_asset_mapping_AssetMappingStore) +- [Resource `AssetMappingPool`](#0x1_asset_mapping_AssetMappingPool) +- [Constants](#@Constants_0) +- [Function `initialize`](#0x1_asset_mapping_initialize) +- [Function `create_store_from_coin`](#0x1_asset_mapping_create_store_from_coin) +- [Function `create_store_for_type`](#0x1_asset_mapping_create_store_for_type) +- [Function `balance`](#0x1_asset_mapping_balance) +- [Function `assign_to_account`](#0x1_asset_mapping_assign_to_account) +- [Function `computer_poove`](#0x1_asset_mapping_computer_poove) + + +
use 0x1::coin;
+use 0x1::debug;
+use 0x1::error;
+use 0x1::fungible_asset;
+use 0x1::object;
+use 0x1::primary_fungible_store;
+use 0x1::signer;
+use 0x1::smart_table;
+use 0x1::stc_util;
+use 0x1::string;
+use 0x1::system_addresses;
+
+ + + + + +## Resource `AssetMappingStore` + +AssetMappingStore represents a store for mapped assets +Contains: +- extend_ref: Reference for extending object capabilities +- fungible_store: The actual store holding fungible assets + + +
struct AssetMappingStore has store, key
+
+ + + +
+Fields + + +
+
+extend_ref: object::ExtendRef +
+
+ +
+
+fungible_store: object::Object<fungible_asset::FungibleStore> +
+
+ +
+
+ + +
+ + + +## Resource `AssetMappingPool` + +AssetMappingPool manages a collection of asset mapping stores +Contains: +- proof_root: Root hash for proof verification +- anchor_height: Block height anchor for the mapping +- token_stores: Smart table mapping metadata to stores + + +
struct AssetMappingPool has store, key
+
+ + + +
+Fields + + +
+
+proof_root: vector<u8> +
+
+ +
+
+anchor_height: u64 +
+
+ +
+
+token_stores: smart_table::SmartTable<object::Object<fungible_asset::Metadata>, asset_mapping::AssetMappingStore> +
+
+ +
+
+ + +
+ + + +## Constants + + + + + + +
const EINVALID_NOT_PROOF: u64 = 102;
+
+ + + + + +Error code for invalid signer + + +
const EINVALID_SIGNER: u64 = 101;
+
+ + + + + +## Function `initialize` + +Initializes the asset mapping pool +@param framework - The framework signer +@param proof_root - Initial proof root for verification +@param anchor_height - Initial anchor height +Verifies the framework signer and creates a new AssetMappingPool + + +
public fun initialize(framework: &signer, proof_root: vector<u8>, anchor_height: u64)
+
+ + + +
+Implementation + + +
public fun initialize(framework: &signer, proof_root: vector<u8>, anchor_height: u64) {
+    assert!(
+        signer::address_of(framework) == system_addresses::get_starcoin_framework(),
+        error::unauthenticated(EINVALID_SIGNER)
+    );
+    move_to(framework, AssetMappingPool {
+        proof_root,
+        anchor_height,
+        token_stores: smart_table::new<Object<Metadata>, AssetMappingStore>(),
+    });
+}
+
+ + + +
+ + + +## Function `create_store_from_coin` + +Creates a new store from a coin +@param token_issuer - The token issuer signer +@param coin - The coin to be stored +Requirements: +- Token issuer must be authorized for the given token type +- Converts coin to fungible asset and stores it + + +
public fun create_store_from_coin<T: key>(token_issuer: &signer, coin: coin::Coin<T>)
+
+ + + +
+Implementation + + +
public fun create_store_from_coin<T: key>(token_issuer: &signer, coin: coin::Coin<T>) acquires AssetMappingPool {
+    let token_issuer_addr = signer::address_of(token_issuer);
+    assert!(
+        token_issuer_addr == stc_util::token_issuer<T>(),
+        error::unauthenticated(EINVALID_SIGNER)
+    );
+
+    let fungible_asset = coin::coin_to_fungible_asset(coin);
+    let token_stores =
+        &mut borrow_global_mut<AssetMappingPool>(system_addresses::get_starcoin_framework()).token_stores;
+
+
+    let (metadata, fungible_store, extend_ref) = create_store_for_type<T>(token_issuer);
+    fungible_asset::deposit(fungible_store, fungible_asset);
+    smart_table::add(token_stores, metadata, AssetMappingStore {
+        extend_ref,
+        fungible_store,
+    });
+}
+
+ + + +
+ + + +## Function `create_store_for_type` + +Creates a store for a specific token type +@param framework - The framework signer +@returns (metadata, store, extend_ref): +- metadata: Token metadata object +- store: Created fungible store +- extend_ref: Extension reference for the store + + +
fun create_store_for_type<T>(framework: &signer): (object::Object<fungible_asset::Metadata>, object::Object<fungible_asset::FungibleStore>, object::ExtendRef)
+
+ + + +
+Implementation + + +
fun create_store_for_type<T>(framework: &signer): (Object<Metadata>, Object<FungibleStore>, ExtendRef) {
+    debug::print(&std::string::utf8(b"asset_mapping::create_store_for_type | entered"));
+
+    let metadata = coin::ensure_paired_metadata<T>();
+    let construct_ref = object::create_object_from_account(framework);
+
+    let store = fungible_asset::create_store(&construct_ref, metadata);
+
+    // Generate extend reference
+    let extend_ref = object::generate_extend_ref(&construct_ref);
+    debug::print(&std::string::utf8(b"asset_mapping::create_store_for_type | exited"));
+
+    (metadata, store, extend_ref)
+}
+
+ + + +
+ + + +## Function `balance` + +Retrieves the balance for a specific token type +@returns Current balance of the token in the mapping pool + + +
fun balance<T>(): u64
+
+ + + +
+Implementation + + +
fun balance<T>(): u64 acquires AssetMappingPool {
+    let metadata = coin::ensure_paired_metadata<T>();
+    let pool = borrow_global<AssetMappingPool>(system_addresses::get_starcoin_framework());
+    fungible_asset::balance(smart_table::borrow(&pool.token_stores, metadata).fungible_store)
+}
+
+ + + +
+ + + +## Function `assign_to_account` + +Assigns tokens to a recipient account with proof verification +@param token_issuer - The token issuer signer +@param receiper - Recipient address +@param proove - Proof data for verification +@param amount - Amount of tokens to assign +Requirements: +- Valid proof must be provided +- Sufficient balance must exist + + +
public entry fun assign_to_account<T>(token_issuer: &signer, receiper: address, proove: vector<u8>, amount: u64)
+
+ + + +
+Implementation + + +
public entry fun assign_to_account<T>(
+    token_issuer: &signer,
+    receiper: address,
+    proove: vector<u8>,
+    amount: u64
+) acquires AssetMappingPool {
+    let metadata = coin::ensure_paired_metadata<T>();
+    let mapping_pool = borrow_global_mut<AssetMappingPool>(signer::address_of(token_issuer));
+    let mapping_store = smart_table::borrow_mut(&mut mapping_pool.token_stores, metadata);
+
+    assert!(computer_poove(proove), error::unauthenticated(EINVALID_NOT_PROOF));
+    // fungible_asset::withdraw(&store.transfer_ref, store.fungible_store, to_account_primary_store, amount);
+    let store_signer = object::generate_signer_for_extending(&mapping_store.extend_ref);
+    fungible_asset::deposit(
+        primary_fungible_store::ensure_primary_store_exists(receiper, metadata),
+        fungible_asset::withdraw(&store_signer, mapping_store.fungible_store, amount)
+    )
+}
+
+ + + +
+ + + +## Function `computer_poove` + +Computes and verifies the provided proof +@param proove - The proof data to verify +@returns Boolean indicating proof validity +Note: Current implementation returns true (TODO) + + +
public fun computer_poove(proove: vector<u8>): bool
+
+ + + +
+Implementation + + +
public fun computer_poove(proove: vector<u8>) : bool {
+    // TODO(BobOng): implement this function
+    true
+}
+
+ + + +
+ + +[move-book]: https://starcoin.dev/move/book/SUMMARY From c32b0967a6228ec8aecfe186b6fd2ad57ef0b617 Mon Sep 17 00:00:00 2001 From: welbon <2261238+welbon@users.noreply.github.com> Date: Tue, 31 Dec 2024 21:04:46 +0800 Subject: [PATCH 04/29] [asset-mapping] fixed `initalize_proof` --- .../src/starcoin_framework_sdk_builder.rs | 46 +++++++++ .../starcoin-framework/doc/asset_mapping.md | 96 +++++++++++++++---- .../starcoin-framework/doc/stc_genesis.md | 10 +- .../sources/asset_mapping.move | 56 +++++++---- .../sources/stc/stc_genesis.move | 10 +- 5 files changed, 180 insertions(+), 38 deletions(-) diff --git a/vm/framework/cached-packages/src/starcoin_framework_sdk_builder.rs b/vm/framework/cached-packages/src/starcoin_framework_sdk_builder.rs index 36e295e48f..0fd6d88551 100644 --- a/vm/framework/cached-packages/src/starcoin_framework_sdk_builder.rs +++ b/vm/framework/cached-packages/src/starcoin_framework_sdk_builder.rs @@ -165,6 +165,12 @@ pub enum EntryFunctionCall { amount: u64, }, + /// Called by StarcoinNode after Genesis + AssetMappingInitalizeProof { + proof_root: Vec, + anchor_height: u64, + }, + CoinCreateCoinConversionMap {}, /// Create STC pairing by passing `StarcoinCoin`. @@ -663,6 +669,10 @@ impl EntryFunctionCall { proove, amount, } => asset_mapping_assign_to_account(t, receiper, proove, amount), + AssetMappingInitalizeProof { + proof_root, + anchor_height, + } => asset_mapping_initalize_proof(proof_root, anchor_height), CoinCreateCoinConversionMap {} => coin_create_coin_conversion_map(), CoinCreatePairing { coin_type } => coin_create_pairing(coin_type), CoinMigrateToFungibleStore { coin_type } => coin_migrate_to_fungible_store(coin_type), @@ -1304,6 +1314,25 @@ pub fn asset_mapping_assign_to_account( )) } +/// Called by StarcoinNode after Genesis +pub fn asset_mapping_initalize_proof( + proof_root: Vec, + anchor_height: u64, +) -> TransactionPayload { + TransactionPayload::EntryFunction(EntryFunction::new( + ModuleId::new( + AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]), + ident_str!("asset_mapping").to_owned(), + ), + ident_str!("initalize_proof").to_owned(), + vec![], + vec![ + bcs::to_bytes(&proof_root).unwrap(), + bcs::to_bytes(&anchor_height).unwrap(), + ], + )) +} + pub fn coin_create_coin_conversion_map() -> TransactionPayload { TransactionPayload::EntryFunction(EntryFunction::new( ModuleId::new( @@ -2586,6 +2615,19 @@ mod decoder { } } + pub fn asset_mapping_initalize_proof( + payload: &TransactionPayload, + ) -> Option { + if let TransactionPayload::EntryFunction(script) = payload { + Some(EntryFunctionCall::AssetMappingInitalizeProof { + proof_root: bcs::from_bytes(script.args().get(0)?).ok()?, + anchor_height: bcs::from_bytes(script.args().get(1)?).ok()?, + }) + } else { + None + } + } + pub fn coin_create_coin_conversion_map( payload: &TransactionPayload, ) -> Option { @@ -3476,6 +3518,10 @@ static SCRIPT_FUNCTION_DECODER_MAP: once_cell::sync::Lazyuse 0x1::coin; @@ -94,19 +96,40 @@ Contains:
-proof_root: vector<u8> +token_stores: smart_table::SmartTable<object::Object<fungible_asset::Metadata>, asset_mapping::AssetMappingStore>
+
+ + + + + + +## Resource `AssetMappingProof` + + + +
struct AssetMappingProof has store, key
+
+ + + +
+Fields + + +
-anchor_height: u64 +proof_root: vector<u8>
-token_stores: smart_table::SmartTable<object::Object<fungible_asset::Metadata>, asset_mapping::AssetMappingStore> +anchor_height: u64
@@ -130,6 +153,15 @@ Contains: + + + + +
const EINVALID_PROOF_ROOT: u64 = 102;
+
+ + + Error code for invalid signer @@ -151,7 +183,7 @@ Initializes the asset mapping pool Verifies the framework signer and creates a new AssetMappingPool -
public fun initialize(framework: &signer, proof_root: vector<u8>, anchor_height: u64)
+
public fun initialize(framework: &signer)
 
@@ -160,15 +192,45 @@ Verifies the framework signer and creates a new AssetMappingPool Implementation -
public fun initialize(framework: &signer, proof_root: vector<u8>, anchor_height: u64) {
+
public fun initialize(framework: &signer) {
     assert!(
         signer::address_of(framework) == system_addresses::get_starcoin_framework(),
         error::unauthenticated(EINVALID_SIGNER)
     );
     move_to(framework, AssetMappingPool {
+        token_stores: smart_table::new<Object<Metadata>, AssetMappingStore>(),
+    });
+}
+
+ + + +
+ + + +## Function `initalize_proof` + +Called by StarcoinNode after Genesis + + +
public entry fun initalize_proof(framework: &signer, proof_root: vector<u8>, anchor_height: u64)
+
+ + + +
+Implementation + + +
public entry fun initalize_proof(framework: &signer, proof_root: vector<u8>, anchor_height: u64) {
+    assert!(
+        signer::address_of(framework) == system_addresses::get_starcoin_framework(),
+        error::unauthenticated(EINVALID_SIGNER)
+    );
+    move_to(framework, AssetMappingProof {
         proof_root,
         anchor_height,
-        token_stores: smart_table::new<Object<Metadata>, AssetMappingStore>(),
     });
 }
 
@@ -209,7 +271,6 @@ Requirements: let token_stores = &mut borrow_global_mut<AssetMappingPool>(system_addresses::get_starcoin_framework()).token_stores; - let (metadata, fungible_store, extend_ref) = create_store_for_type<T>(token_issuer); fungible_asset::deposit(fungible_store, fungible_asset); smart_table::add(token_stores, metadata, AssetMappingStore { @@ -321,11 +382,17 @@ Requirements: proove: vector<u8>, amount: u64 ) acquires AssetMappingPool { + assert!( + exists<AssetMappingProof>(system_addresses::get_starcoin_framework()), + error::invalid_state(EINVALID_PROOF_ROOT) + ); + let metadata = coin::ensure_paired_metadata<T>(); let mapping_pool = borrow_global_mut<AssetMappingPool>(signer::address_of(token_issuer)); let mapping_store = smart_table::borrow_mut(&mut mapping_pool.token_stores, metadata); - assert!(computer_poove(proove), error::unauthenticated(EINVALID_NOT_PROOF)); + assert!(calculation_proof(proove, vector::empty()), error::unauthenticated(EINVALID_NOT_PROOF)); + // fungible_asset::withdraw(&store.transfer_ref, store.fungible_store, to_account_primary_store, amount); let store_signer = object::generate_signer_for_extending(&mapping_store.extend_ref); fungible_asset::deposit( @@ -339,17 +406,14 @@ Requirements:
- + -## Function `computer_poove` +## Function `calculation_proof` Computes and verifies the provided proof -@param proove - The proof data to verify -@returns Boolean indicating proof validity -Note: Current implementation returns true (TODO) -
public fun computer_poove(proove: vector<u8>): bool
+
fun calculation_proof(_leaf: vector<u8>, _siblings: vector<vector<u8>>): bool
 
@@ -358,7 +422,7 @@ Note: Current implementation returns true (TODO) Implementation -
public fun computer_poove(proove: vector<u8>) : bool {
+
fun calculation_proof(_leaf: vector<u8>, _siblings: vector<vector<u8>>): bool {
     // TODO(BobOng): implement this function
     true
 }
diff --git a/vm/framework/starcoin-framework/doc/stc_genesis.md b/vm/framework/starcoin-framework/doc/stc_genesis.md
index 84c6362784..9092eb6975 100644
--- a/vm/framework/starcoin-framework/doc/stc_genesis.md
+++ b/vm/framework/starcoin-framework/doc/stc_genesis.md
@@ -16,6 +16,7 @@ The module for init Genesis
 
 
use 0x1::account;
 use 0x1::aggregator_factory;
+use 0x1::asset_mapping;
 use 0x1::block_reward;
 use 0x1::block_reward_config;
 use 0x1::chain_id;
@@ -109,7 +110,6 @@ The module for init Genesis
 ) {
     debug::print(&std::string::utf8(b"stc_genesis::initialize Entered"));
 
-
     // create genesis account
     let (starcoin_framework_account, _genesis_signer_cap) =
         account::create_framework_reserved_account(@starcoin_framework);
@@ -383,6 +383,13 @@ Overall governance allocation strategy:
     time_mint_stc_amount: u128,
     time_mint_stc_period: u64,
 ) {
+    // Initialize asset mapping
+    asset_mapping::initialize(starcoin_framework);
+    // TODO(BobOng): To confirm how many STC put into asset mapping pool
+    let asset_mapping_coin = coin::extract<STC>(&mut total_supply_stc, 1000000000);
+    asset_mapping::create_store_from_coin<STC>(starcoin_framework, asset_mapping_coin);
+
+    // Initialize treasury
     let treasury_withdraw_cap = treasury::initialize(starcoin_framework, total_supply_stc);
 
     if (pre_mine_stc_amount > 0) {
@@ -393,6 +400,7 @@ Overall governance allocation strategy:
         );
         coin::deposit(core_resource_address, stc);
     };
+
     if (time_mint_stc_amount > 0) {
         let liner_withdraw_cap = treasury::issue_linear_withdraw_capability<STC>(
             &mut treasury_withdraw_cap,
diff --git a/vm/framework/starcoin-framework/sources/asset_mapping.move b/vm/framework/starcoin-framework/sources/asset_mapping.move
index 89a78c886e..2935a5f15a 100644
--- a/vm/framework/starcoin-framework/sources/asset_mapping.move
+++ b/vm/framework/starcoin-framework/sources/asset_mapping.move
@@ -6,6 +6,7 @@ module starcoin_framework::asset_mapping {
 
     use std::error;
     use std::signer;
+    use std::vector;
 
     use starcoin_framework::coin;
     use starcoin_framework::fungible_asset::{Self, FungibleStore, Metadata};
@@ -14,11 +15,10 @@ module starcoin_framework::asset_mapping {
     use starcoin_framework::primary_fungible_store;
     use starcoin_framework::stc_util;
     use starcoin_framework::system_addresses;
+
     use starcoin_std::debug;
     use starcoin_std::smart_table;
 
-    #[test_only]
-    use std::vector;
     #[test_only]
     use starcoin_framework::account;
     #[test_only]
@@ -39,29 +39,43 @@ module starcoin_framework::asset_mapping {
     /// - anchor_height: Block height anchor for the mapping
     /// - token_stores: Smart table mapping metadata to stores
     struct AssetMappingPool has key, store {
+        token_stores: smart_table::SmartTable, AssetMappingStore>
+    }
+
+    struct AssetMappingProof has key, store {
         proof_root: vector,
         anchor_height: u64,
-        token_stores: smart_table::SmartTable, AssetMappingStore>
     }
 
     /// Error code for invalid signer
     const EINVALID_SIGNER: u64 = 101;
     const EINVALID_NOT_PROOF: u64 = 102;
+    const EINVALID_PROOF_ROOT: u64 = 102;
 
     /// Initializes the asset mapping pool
     /// @param framework - The framework signer
     /// @param proof_root - Initial proof root for verification
     /// @param anchor_height - Initial anchor height
     /// Verifies the framework signer and creates a new AssetMappingPool
-    public fun initialize(framework: &signer, proof_root: vector, anchor_height: u64) {
+    public fun initialize(framework: &signer) {
         assert!(
             signer::address_of(framework) == system_addresses::get_starcoin_framework(),
             error::unauthenticated(EINVALID_SIGNER)
         );
         move_to(framework, AssetMappingPool {
+            token_stores: smart_table::new, AssetMappingStore>(),
+        });
+    }
+
+    /// Called by StarcoinNode after Genesis
+    public entry fun initalize_proof(framework: &signer, proof_root: vector, anchor_height: u64) {
+        assert!(
+            signer::address_of(framework) == system_addresses::get_starcoin_framework(),
+            error::unauthenticated(EINVALID_SIGNER)
+        );
+        move_to(framework, AssetMappingProof {
             proof_root,
             anchor_height,
-            token_stores: smart_table::new, AssetMappingStore>(),
         });
     }
 
@@ -82,7 +96,6 @@ module starcoin_framework::asset_mapping {
         let token_stores =
             &mut borrow_global_mut(system_addresses::get_starcoin_framework()).token_stores;
 
-
         let (metadata, fungible_store, extend_ref) = create_store_for_type(token_issuer);
         fungible_asset::deposit(fungible_store, fungible_asset);
         smart_table::add(token_stores, metadata, AssetMappingStore {
@@ -134,12 +147,17 @@ module starcoin_framework::asset_mapping {
         proove: vector,
         amount: u64
     ) acquires AssetMappingPool {
+        assert!(
+            exists(system_addresses::get_starcoin_framework()),
+            error::invalid_state(EINVALID_PROOF_ROOT)
+        );
+
         let metadata = coin::ensure_paired_metadata();
         let mapping_pool = borrow_global_mut(signer::address_of(token_issuer));
         let mapping_store = smart_table::borrow_mut(&mut mapping_pool.token_stores, metadata);
 
-        assert!(computer_poove(proove), error::unauthenticated(EINVALID_NOT_PROOF));
-        // fungible_asset::withdraw(&store.transfer_ref, store.fungible_store, to_account_primary_store, amount);
+        assert!(calculation_proof(proove, vector::empty()), error::unauthenticated(EINVALID_NOT_PROOF));
+
         let store_signer = object::generate_signer_for_extending(&mapping_store.extend_ref);
         fungible_asset::deposit(
             primary_fungible_store::ensure_primary_store_exists(receiper, metadata),
@@ -148,26 +166,24 @@ module starcoin_framework::asset_mapping {
     }
 
     /// Computes and verifies the provided proof
-    /// @param proove - The proof data to verify
-    /// @returns Boolean indicating proof validity
-    /// Note: Current implementation returns true (TODO)
-    public fun computer_poove(proove: vector) : bool {
+    fun calculation_proof(_leaf: vector, _siblings: vector>): bool {
         // TODO(BobOng): implement this function
         true
     }
 
-    /// Test function for asset mapping store creation and assignment
-    /// Tests:
-    /// - Store creation from coin
-    /// - Balance checking
-    /// - Asset assignment to account
-    /// - Final balance verification
-    #[test(framework= @starcoin_framework, alice=@0x123)]
+    // Test function for asset mapping store creation and assignment
+    // Tests
+    //  Store creation from coin
+    //  Balance checking
+    //  Asset assignment to account
+    //  Final balance verification
+    #[test(framework= @starcoin_framework, alice= @0x123)]
     fun test_asset_mapping_create_store_from_coin(framework: &signer, alice: &signer) acquires AssetMappingPool {
         debug::print(&std::string::utf8(b"asset_mapping::test_asset_mapping_create_store_from_coin | entered"));
 
         let amount = 10000000000;
-        Self::initialize(framework, vector::empty(), 0);
+        Self::initialize(framework);
+        Self::initalize_proof(framework, vector::empty(), 0);
 
         // create genesis account
         account::create_account_for_test(signer::address_of(framework));
diff --git a/vm/framework/starcoin-framework/sources/stc/stc_genesis.move b/vm/framework/starcoin-framework/sources/stc/stc_genesis.move
index aa5ff13a22..0942ffc378 100644
--- a/vm/framework/starcoin-framework/sources/stc/stc_genesis.move
+++ b/vm/framework/starcoin-framework/sources/stc/stc_genesis.move
@@ -4,6 +4,7 @@ module starcoin_framework::stc_genesis {
     use std::features;
     use std::option;
     use std::vector;
+    use starcoin_framework::asset_mapping;
 
     use starcoin_framework::account;
     use starcoin_framework::aggregator_factory;
@@ -85,7 +86,6 @@ module starcoin_framework::stc_genesis {
     ) {
         debug::print(&std::string::utf8(b"stc_genesis::initialize Entered"));
 
-
         // create genesis account
         let (starcoin_framework_account, _genesis_signer_cap) =
             account::create_framework_reserved_account(@starcoin_framework);
@@ -299,6 +299,13 @@ module starcoin_framework::stc_genesis {
         time_mint_stc_amount: u128,
         time_mint_stc_period: u64,
     ) {
+        // Initialize asset mapping
+        asset_mapping::initialize(starcoin_framework);
+        // TODO(BobOng): To confirm how many STC put into asset mapping pool
+        let asset_mapping_coin = coin::extract(&mut total_supply_stc, 1000000000);
+        asset_mapping::create_store_from_coin(starcoin_framework, asset_mapping_coin);
+
+        // Initialize treasury
         let treasury_withdraw_cap = treasury::initialize(starcoin_framework, total_supply_stc);
 
         if (pre_mine_stc_amount > 0) {
@@ -309,6 +316,7 @@ module starcoin_framework::stc_genesis {
             );
             coin::deposit(core_resource_address, stc);
         };
+
         if (time_mint_stc_amount > 0) {
             let liner_withdraw_cap = treasury::issue_linear_withdraw_capability(
                 &mut treasury_withdraw_cap,

From 960777c3dc01d587378d5ccd6912872a96d8cb6a Mon Sep 17 00:00:00 2001
From: welbon <2261238+welbon@users.noreply.github.com>
Date: Fri, 3 Jan 2025 09:50:57 +0800
Subject: [PATCH 05/29] [asset-mapping] Restore the deployment address check
 related to `check_module_address`

---
 vm/types/src/transaction/package.rs | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/vm/types/src/transaction/package.rs b/vm/types/src/transaction/package.rs
index 52eac11b3e..930f9f486e 100644
--- a/vm/types/src/transaction/package.rs
+++ b/vm/types/src/transaction/package.rs
@@ -70,15 +70,15 @@ impl Package {
     }
 
     fn check_module_address(
-        _package_address: &AccountAddress,
-        _module_address: &AccountAddress,
+        package_address: &AccountAddress,
+        module_address: &AccountAddress,
     ) -> Result<()> {
-        //ensure!(
-        //    package_address == module_address,
-        //    "module's address ({:?}) not same as package module address {:?}",
-        //    module_address,
-        //    package_address,
-        //);
+        ensure!(
+           package_address == module_address,
+           "module's address ({:?}) not same as package module address {:?}",
+           module_address,
+           package_address,
+        );
         Ok(())
     }
 

From 07852152e3391c3a17a4b147915db36d4df7653e Mon Sep 17 00:00:00 2001
From: welbon <2261238+welbon@users.noreply.github.com>
Date: Fri, 3 Jan 2025 10:13:33 +0800
Subject: [PATCH 06/29] [asset-mapping] Put the relevant fields of proof root
 into the genesis initialization function to avoid modifying the initial call
 of the Package

---
 .../src/starcoin_framework_sdk_builder.rs     | 52 +++----------------
 .../starcoin-framework/doc/asset_mapping.md   | 42 +--------------
 .../starcoin-framework/doc/stc_genesis.md     |  9 ++--
 .../sources/asset_mapping.move                | 16 +-----
 .../sources/stc/stc_genesis.move              |  7 ++-
 5 files changed, 21 insertions(+), 105 deletions(-)

diff --git a/vm/framework/cached-packages/src/starcoin_framework_sdk_builder.rs b/vm/framework/cached-packages/src/starcoin_framework_sdk_builder.rs
index 0fd6d88551..3a449da729 100644
--- a/vm/framework/cached-packages/src/starcoin_framework_sdk_builder.rs
+++ b/vm/framework/cached-packages/src/starcoin_framework_sdk_builder.rs
@@ -165,12 +165,6 @@ pub enum EntryFunctionCall {
         amount: u64,
     },
 
-    /// Called by StarcoinNode after Genesis
-    AssetMappingInitalizeProof {
-        proof_root: Vec,
-        anchor_height: u64,
-    },
-
     CoinCreateCoinConversionMap {},
 
     /// Create STC pairing by passing `StarcoinCoin`.
@@ -539,6 +533,7 @@ pub enum EntryFunctionCall {
         transaction_timeout: u64,
         dag_effective_height: u64,
         features: Vec,
+        asset_mapping_proof_root: Vec,
     },
 
     /// Batch transfer token to others.
@@ -669,10 +664,6 @@ impl EntryFunctionCall {
                 proove,
                 amount,
             } => asset_mapping_assign_to_account(t, receiper, proove, amount),
-            AssetMappingInitalizeProof {
-                proof_root,
-                anchor_height,
-            } => asset_mapping_initalize_proof(proof_root, anchor_height),
             CoinCreateCoinConversionMap {} => coin_create_coin_conversion_map(),
             CoinCreatePairing { coin_type } => coin_create_pairing(coin_type),
             CoinMigrateToFungibleStore { coin_type } => coin_migrate_to_fungible_store(coin_type),
@@ -961,6 +952,7 @@ impl EntryFunctionCall {
                 transaction_timeout,
                 dag_effective_height,
                 features,
+                asset_mapping_proof_root,
             } => stc_genesis_initialize(
                 stdlib_version,
                 reward_delay,
@@ -994,6 +986,7 @@ impl EntryFunctionCall {
                 transaction_timeout,
                 dag_effective_height,
                 features,
+                asset_mapping_proof_root,
             ),
             TransferScriptsBatchPeerToPeer {
                 token_type,
@@ -1314,25 +1307,6 @@ pub fn asset_mapping_assign_to_account(
     ))
 }
 
-/// Called by StarcoinNode after Genesis
-pub fn asset_mapping_initalize_proof(
-    proof_root: Vec,
-    anchor_height: u64,
-) -> TransactionPayload {
-    TransactionPayload::EntryFunction(EntryFunction::new(
-        ModuleId::new(
-            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
-            ident_str!("asset_mapping").to_owned(),
-        ),
-        ident_str!("initalize_proof").to_owned(),
-        vec![],
-        vec![
-            bcs::to_bytes(&proof_root).unwrap(),
-            bcs::to_bytes(&anchor_height).unwrap(),
-        ],
-    ))
-}
-
 pub fn coin_create_coin_conversion_map() -> TransactionPayload {
     TransactionPayload::EntryFunction(EntryFunction::new(
         ModuleId::new(
@@ -2271,6 +2245,7 @@ pub fn stc_genesis_initialize(
     transaction_timeout: u64,
     dag_effective_height: u64,
     features: Vec,
+    asset_mapping_proof_root: Vec,
 ) -> TransactionPayload {
     TransactionPayload::EntryFunction(EntryFunction::new(
         ModuleId::new(
@@ -2312,6 +2287,7 @@ pub fn stc_genesis_initialize(
             bcs::to_bytes(&transaction_timeout).unwrap(),
             bcs::to_bytes(&dag_effective_height).unwrap(),
             bcs::to_bytes(&features).unwrap(),
+            bcs::to_bytes(&asset_mapping_proof_root).unwrap(),
         ],
     ))
 }
@@ -2615,19 +2591,6 @@ mod decoder {
         }
     }
 
-    pub fn asset_mapping_initalize_proof(
-        payload: &TransactionPayload,
-    ) -> Option {
-        if let TransactionPayload::EntryFunction(script) = payload {
-            Some(EntryFunctionCall::AssetMappingInitalizeProof {
-                proof_root: bcs::from_bytes(script.args().get(0)?).ok()?,
-                anchor_height: bcs::from_bytes(script.args().get(1)?).ok()?,
-            })
-        } else {
-            None
-        }
-    }
-
     pub fn coin_create_coin_conversion_map(
         payload: &TransactionPayload,
     ) -> Option {
@@ -3340,6 +3303,7 @@ mod decoder {
                 transaction_timeout: bcs::from_bytes(script.args().get(29)?).ok()?,
                 dag_effective_height: bcs::from_bytes(script.args().get(30)?).ok()?,
                 features: bcs::from_bytes(script.args().get(31)?).ok()?,
+                asset_mapping_proof_root: bcs::from_bytes(script.args().get(32)?).ok()?,
             })
         } else {
             None
@@ -3518,10 +3482,6 @@ static SCRIPT_FUNCTION_DECODER_MAP: once_cell::sync::Lazy
 
-
-
-anchor_height: u64 -
-
-
@@ -179,11 +172,10 @@ Error code for invalid signer Initializes the asset mapping pool @param framework - The framework signer @param proof_root - Initial proof root for verification -@param anchor_height - Initial anchor height Verifies the framework signer and creates a new AssetMappingPool -
public fun initialize(framework: &signer)
+
public fun initialize(framework: &signer, proof_root: vector<u8>)
 
@@ -192,7 +184,7 @@ Verifies the framework signer and creates a new AssetMappingPool Implementation -
public fun initialize(framework: &signer) {
+
public fun initialize(framework: &signer, proof_root: vector<u8>) {
     assert!(
         signer::address_of(framework) == system_addresses::get_starcoin_framework(),
         error::unauthenticated(EINVALID_SIGNER)
@@ -200,37 +192,8 @@ Verifies the framework signer and creates a new AssetMappingPool
     move_to(framework, AssetMappingPool {
         token_stores: smart_table::new<Object<Metadata>, AssetMappingStore>(),
     });
-}
-
- - - - - - - -## Function `initalize_proof` - -Called by StarcoinNode after Genesis - - -
public entry fun initalize_proof(framework: &signer, proof_root: vector<u8>, anchor_height: u64)
-
- - - -
-Implementation - - -
public entry fun initalize_proof(framework: &signer, proof_root: vector<u8>, anchor_height: u64) {
-    assert!(
-        signer::address_of(framework) == system_addresses::get_starcoin_framework(),
-        error::unauthenticated(EINVALID_SIGNER)
-    );
     move_to(framework, AssetMappingProof {
         proof_root,
-        anchor_height,
     });
 }
 
@@ -393,7 +356,6 @@ Requirements: assert!(calculation_proof(proove, vector::empty()), error::unauthenticated(EINVALID_NOT_PROOF)); - // fungible_asset::withdraw(&store.transfer_ref, store.fungible_store, to_account_primary_store, amount); let store_signer = object::generate_signer_for_extending(&mapping_store.extend_ref); fungible_asset::deposit( primary_fungible_store::ensure_primary_store_exists(receiper, metadata), diff --git a/vm/framework/starcoin-framework/doc/stc_genesis.md b/vm/framework/starcoin-framework/doc/stc_genesis.md index 9092eb6975..c78c70075e 100644 --- a/vm/framework/starcoin-framework/doc/stc_genesis.md +++ b/vm/framework/starcoin-framework/doc/stc_genesis.md @@ -60,7 +60,7 @@ The module for init Genesis -
public entry fun initialize(stdlib_version: u64, reward_delay: u64, total_stc_amount: u128, pre_mine_stc_amount: u128, time_mint_stc_amount: u128, time_mint_stc_period: u64, parent_hash: vector<u8>, association_auth_key: vector<u8>, genesis_auth_key: vector<u8>, chain_id: u8, _genesis_timestamp: u64, uncle_rate_target: u64, epoch_block_count: u64, base_block_time_target: u64, base_block_difficulty_window: u64, base_reward_per_block: u128, base_reward_per_uncle_percent: u64, min_block_time_target: u64, max_block_time_target: u64, base_max_uncles_per_block: u64, base_block_gas_limit: u64, strategy: u8, script_allowed: bool, module_publishing_allowed: bool, gas_schedule_blob: vector<u8>, voting_delay: u64, voting_period: u64, voting_quorum_rate: u8, min_action_delay: u64, transaction_timeout: u64, dag_effective_height: u64, features: vector<u8>)
+
public entry fun initialize(stdlib_version: u64, reward_delay: u64, total_stc_amount: u128, pre_mine_stc_amount: u128, time_mint_stc_amount: u128, time_mint_stc_period: u64, parent_hash: vector<u8>, association_auth_key: vector<u8>, genesis_auth_key: vector<u8>, chain_id: u8, _genesis_timestamp: u64, uncle_rate_target: u64, epoch_block_count: u64, base_block_time_target: u64, base_block_difficulty_window: u64, base_reward_per_block: u128, base_reward_per_uncle_percent: u64, min_block_time_target: u64, max_block_time_target: u64, base_max_uncles_per_block: u64, base_block_gas_limit: u64, strategy: u8, script_allowed: bool, module_publishing_allowed: bool, gas_schedule_blob: vector<u8>, voting_delay: u64, voting_period: u64, voting_quorum_rate: u8, min_action_delay: u64, transaction_timeout: u64, dag_effective_height: u64, features: vector<u8>, asset_mapping_proof_root: vector<u8>)
 
@@ -107,6 +107,7 @@ The module for init Genesis transaction_timeout: u64, dag_effective_height: u64, features: vector<u8>, + asset_mapping_proof_root: vector<u8>, ) { debug::print(&std::string::utf8(b"stc_genesis::initialize Entered")); @@ -192,6 +193,9 @@ The module for init Genesis debug::print(&std::string::utf8(b"stc_genesis::initialize | initialize_stc ")); + // Asset mapping initialize + asset_mapping::initialize(&starcoin_framework_account, asset_mapping_proof_root); + // Init goverances account let core_resource_account = account::create_account(@core_resources); coin::register<STC>(&core_resource_account); @@ -383,8 +387,6 @@ Overall governance allocation strategy: time_mint_stc_amount: u128, time_mint_stc_period: u64, ) { - // Initialize asset mapping - asset_mapping::initialize(starcoin_framework); // TODO(BobOng): To confirm how many STC put into asset mapping pool let asset_mapping_coin = coin::extract<STC>(&mut total_supply_stc, 1000000000); asset_mapping::create_store_from_coin<STC>(starcoin_framework, asset_mapping_coin); @@ -508,6 +510,7 @@ Overall governance allocation strategy: transaction_timeout, 0, vector::empty(), + vector::empty(), ); }
diff --git a/vm/framework/starcoin-framework/sources/asset_mapping.move b/vm/framework/starcoin-framework/sources/asset_mapping.move index 2935a5f15a..6fd95c65b3 100644 --- a/vm/framework/starcoin-framework/sources/asset_mapping.move +++ b/vm/framework/starcoin-framework/sources/asset_mapping.move @@ -44,7 +44,6 @@ module starcoin_framework::asset_mapping { struct AssetMappingProof has key, store { proof_root: vector, - anchor_height: u64, } /// Error code for invalid signer @@ -55,9 +54,8 @@ module starcoin_framework::asset_mapping { /// Initializes the asset mapping pool /// @param framework - The framework signer /// @param proof_root - Initial proof root for verification - /// @param anchor_height - Initial anchor height /// Verifies the framework signer and creates a new AssetMappingPool - public fun initialize(framework: &signer) { + public fun initialize(framework: &signer, proof_root: vector) { assert!( signer::address_of(framework) == system_addresses::get_starcoin_framework(), error::unauthenticated(EINVALID_SIGNER) @@ -65,17 +63,8 @@ module starcoin_framework::asset_mapping { move_to(framework, AssetMappingPool { token_stores: smart_table::new, AssetMappingStore>(), }); - } - - /// Called by StarcoinNode after Genesis - public entry fun initalize_proof(framework: &signer, proof_root: vector, anchor_height: u64) { - assert!( - signer::address_of(framework) == system_addresses::get_starcoin_framework(), - error::unauthenticated(EINVALID_SIGNER) - ); move_to(framework, AssetMappingProof { proof_root, - anchor_height, }); } @@ -182,8 +171,7 @@ module starcoin_framework::asset_mapping { debug::print(&std::string::utf8(b"asset_mapping::test_asset_mapping_create_store_from_coin | entered")); let amount = 10000000000; - Self::initialize(framework); - Self::initalize_proof(framework, vector::empty(), 0); + Self::initialize(framework, vector::empty()); // create genesis account account::create_account_for_test(signer::address_of(framework)); diff --git a/vm/framework/starcoin-framework/sources/stc/stc_genesis.move b/vm/framework/starcoin-framework/sources/stc/stc_genesis.move index 0942ffc378..45b6188fad 100644 --- a/vm/framework/starcoin-framework/sources/stc/stc_genesis.move +++ b/vm/framework/starcoin-framework/sources/stc/stc_genesis.move @@ -83,6 +83,7 @@ module starcoin_framework::stc_genesis { transaction_timeout: u64, dag_effective_height: u64, features: vector, + asset_mapping_proof_root: vector, ) { debug::print(&std::string::utf8(b"stc_genesis::initialize Entered")); @@ -168,6 +169,9 @@ module starcoin_framework::stc_genesis { debug::print(&std::string::utf8(b"stc_genesis::initialize | initialize_stc ")); + // Asset mapping initialize + asset_mapping::initialize(&starcoin_framework_account, asset_mapping_proof_root); + // Init goverances account let core_resource_account = account::create_account(@core_resources); coin::register(&core_resource_account); @@ -299,8 +303,6 @@ module starcoin_framework::stc_genesis { time_mint_stc_amount: u128, time_mint_stc_period: u64, ) { - // Initialize asset mapping - asset_mapping::initialize(starcoin_framework); // TODO(BobOng): To confirm how many STC put into asset mapping pool let asset_mapping_coin = coin::extract(&mut total_supply_stc, 1000000000); asset_mapping::create_store_from_coin(starcoin_framework, asset_mapping_coin); @@ -405,6 +407,7 @@ module starcoin_framework::stc_genesis { transaction_timeout, 0, vector::empty(), + vector::empty(), ); } } \ No newline at end of file From af5ed066a1a54ada45b5397022844d4fcd3cc01c Mon Sep 17 00:00:00 2001 From: welbon <2261238+welbon@users.noreply.github.com> Date: Fri, 3 Jan 2025 10:45:56 +0800 Subject: [PATCH 07/29] [asset-mapping] Put the relevant fields of proof root into the genesis initialization function to avoid modifying the initial call of the Package --- vm/transaction-builder/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vm/transaction-builder/src/lib.rs b/vm/transaction-builder/src/lib.rs index a126260271..d7e0cf787b 100644 --- a/vm/transaction-builder/src/lib.rs +++ b/vm/transaction-builder/src/lib.rs @@ -395,6 +395,8 @@ pub fn build_init_script(net: &ChainNetwork) -> EntryFunction { // flexidag effective height genesis_config.dag_effective_height, Features::default().features, + // TODO(BobOng): to set proof root + Vec::new(), ); match payload { From 86f533862e5c11d99ad4f7ecac94a8c8628e317e Mon Sep 17 00:00:00 2001 From: welbon <2261238+welbon@users.noreply.github.com> Date: Fri, 3 Jan 2025 14:49:28 +0800 Subject: [PATCH 08/29] [asset-mapping] Add relevant codes for on-chain proofs, which can be used as tool codes --- .../starcoin-framework/doc/overview.md | 4 + .../starcoin-framework/doc/smt_hash.md | 209 +++++++++ .../starcoin-framework/doc/smt_proofs.md | 392 +++++++++++++++++ .../starcoin-framework/doc/smt_tree_hasher.md | 403 ++++++++++++++++++ .../starcoin-framework/doc/smt_utils.md | 286 +++++++++++++ .../sources/smt/smt_hash.move | 63 +++ .../sources/smt/smt_proofs.move | 369 ++++++++++++++++ .../sources/smt/smt_tree_hasher.move | 139 ++++++ .../sources/smt/smt_utils.move | 99 +++++ 9 files changed, 1964 insertions(+) create mode 100644 vm/framework/starcoin-framework/doc/smt_hash.md create mode 100644 vm/framework/starcoin-framework/doc/smt_proofs.md create mode 100644 vm/framework/starcoin-framework/doc/smt_tree_hasher.md create mode 100644 vm/framework/starcoin-framework/doc/smt_utils.md create mode 100644 vm/framework/starcoin-framework/sources/smt/smt_hash.move create mode 100644 vm/framework/starcoin-framework/sources/smt/smt_proofs.move create mode 100644 vm/framework/starcoin-framework/sources/smt/smt_tree_hasher.move create mode 100644 vm/framework/starcoin-framework/sources/smt/smt_utils.move diff --git a/vm/framework/starcoin-framework/doc/overview.md b/vm/framework/starcoin-framework/doc/overview.md index 31f35ec1e8..15ad19191f 100644 --- a/vm/framework/starcoin-framework/doc/overview.md +++ b/vm/framework/starcoin-framework/doc/overview.md @@ -56,6 +56,10 @@ This is the reference documentation of the Starcoin framework. - [`0x1::reserved_accounts_signer`](reserved_accounts_signer.md#0x1_reserved_accounts_signer) - [`0x1::resource_account`](resource_account.md#0x1_resource_account) - [`0x1::ring`](ring.md#0x1_ring) +- [`0x1::smt_hash`](smt_hash.md#0x1_smt_hash) +- [`0x1::smt_proofs`](smt_proofs.md#0x1_smt_proofs) +- [`0x1::smt_tree_hasher`](smt_tree_hasher.md#0x1_smt_tree_hasher) +- [`0x1::smt_utils`](smt_utils.md#0x1_smt_utils) - [`0x1::starcoin_account`](starcoin_account.md#0x1_starcoin_account) - [`0x1::starcoin_coin`](starcoin_coin.md#0x1_starcoin_coin) - [`0x1::stc_block`](stc_block.md#0x1_stc_block) diff --git a/vm/framework/starcoin-framework/doc/smt_hash.md b/vm/framework/starcoin-framework/doc/smt_hash.md new file mode 100644 index 0000000000..487a683661 --- /dev/null +++ b/vm/framework/starcoin-framework/doc/smt_hash.md @@ -0,0 +1,209 @@ + + + +# Module `0x1::smt_hash` + + + +- [Constants](#@Constants_0) +- [Function `size`](#0x1_smt_hash_size) +- [Function `hash`](#0x1_smt_hash_hash) +- [Function `size_zero_bytes`](#0x1_smt_hash_size_zero_bytes) +- [Function `path_bits_to_bool_vector_from_msb`](#0x1_smt_hash_path_bits_to_bool_vector_from_msb) +- [Function `split_side_nodes_data`](#0x1_smt_hash_split_side_nodes_data) + + +
use 0x1::error;
+use 0x1::hash;
+use 0x1::smt_utils;
+
+ + + + + +## Constants + + + + + + +
const ERROR_INVALID_NODES_DATA_PACKAGE_LENGTH: u64 = 103;
+
+ + + + + + + +
const ERROR_INVALID_PATH_BITS_LENGTH: u64 = 102;
+
+ + + + + + + +
const ERROR_INVALID_PATH_BYTES_LENGTH: u64 = 101;
+
+ + + + + + + +
const SIZE_ZERO_BYTES: vector<u8> = [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, 0];
+
+ + + + + +## Function `size` + + + +
public fun size(): u64
+
+ + + +
+Implementation + + +
public fun size(): u64 {
+    32
+}
+
+ + + +
+ + + +## Function `hash` + + + +
public fun hash(data: &vector<u8>): vector<u8>
+
+ + + +
+Implementation + + +
public fun hash(data: &vector<u8>): vector<u8> {
+    hash::sha3_256(*data)
+}
+
+ + + +
+ + + +## Function `size_zero_bytes` + + + +
public fun size_zero_bytes(): vector<u8>
+
+ + + +
+Implementation + + +
public fun size_zero_bytes(): vector<u8> {
+    SIZE_ZERO_BYTES
+}
+
+ + + +
+ + + +## Function `path_bits_to_bool_vector_from_msb` + + + +
public fun path_bits_to_bool_vector_from_msb(path: &vector<u8>): vector<bool>
+
+ + + +
+Implementation + + +
public fun path_bits_to_bool_vector_from_msb(path: &vector<u8>): vector<bool> {
+    let path_len = vector::length<u8>(path);
+    assert!(path_len == Self::size(), error::invalid_argument(ERROR_INVALID_PATH_BYTES_LENGTH));
+    let result_vec = smt_utils::bits_to_bool_vector_from_msb(path);
+    assert!(
+        vector::length<bool>(&result_vec) == Self::size() * 8,// smt_tree_hasher::path_size_in_bits(),
+        error::invalid_state(ERROR_INVALID_PATH_BITS_LENGTH)
+    );
+    result_vec
+}
+
+ + + +
+ + + +## Function `split_side_nodes_data` + + + +
public fun split_side_nodes_data(side_nodes_data: &vector<u8>): vector<vector<u8>>
+
+ + + +
+Implementation + + +
public fun split_side_nodes_data(side_nodes_data: &vector<u8>): vector<vector<u8>> {
+    let node_data_length = Self::size();
+    let len = vector::length(side_nodes_data);
+    assert!(len % node_data_length == 0, error::invalid_state(ERROR_INVALID_NODES_DATA_PACKAGE_LENGTH));
+
+    if (len > 0) {
+        let result = vector::empty<vector<u8>>();
+        let size = len / node_data_length;
+        let idx = 0;
+        while (idx < size) {
+            let start = idx * node_data_length;
+            let end = start + node_data_length;
+            vector::push_back(&mut result, smt_utils::sub_u8_vector(side_nodes_data, start, end));
+            idx = idx + 1;
+        };
+        result
+    } else {
+        vector::empty<vector<u8>>()
+    }
+}
+
+ + + +
+ + +[move-book]: https://starcoin.dev/move/book/SUMMARY diff --git a/vm/framework/starcoin-framework/doc/smt_proofs.md b/vm/framework/starcoin-framework/doc/smt_proofs.md new file mode 100644 index 0000000000..e8edd17d9d --- /dev/null +++ b/vm/framework/starcoin-framework/doc/smt_proofs.md @@ -0,0 +1,392 @@ + + + +# Module `0x1::smt_proofs` + + + +- [Constants](#@Constants_0) +- [Function `verify_non_membership_proof_by_key`](#0x1_smt_proofs_verify_non_membership_proof_by_key) +- [Function `verify_non_membership_proof_by_leaf_path`](#0x1_smt_proofs_verify_non_membership_proof_by_leaf_path) +- [Function `verify_membership_proof_by_key_value`](#0x1_smt_proofs_verify_membership_proof_by_key_value) +- [Function `verify_membership_proof`](#0x1_smt_proofs_verify_membership_proof) +- [Function `compute_root_hash_by_leaf`](#0x1_smt_proofs_compute_root_hash_by_leaf) +- [Function `compute_root_hash_new_leaf_included`](#0x1_smt_proofs_compute_root_hash_new_leaf_included) +- [Function `create_membership_proof`](#0x1_smt_proofs_create_membership_proof) +- [Function `create_membership_side_nodes`](#0x1_smt_proofs_create_membership_side_nodes) +- [Function `compute_root_hash`](#0x1_smt_proofs_compute_root_hash) + + +
use 0x1::debug;
+use 0x1::error;
+use 0x1::smt_tree_hasher;
+use 0x1::smt_utils;
+
+ + + + + +## Constants + + + + + + +
const BIT_RIGHT: bool = true;
+
+ + + + + + + +
const ERROR_COUNT_COMMON_PREFIX: u64 = 102;
+
+ + + + + + + +
const ERROR_KEY_ALREADY_EXISTS_IN_PROOF: u64 = 101;
+
+ + + + + +## Function `verify_non_membership_proof_by_key` + + + +
public fun verify_non_membership_proof_by_key(root_hash: &vector<u8>, non_membership_leaf_data: &vector<u8>, side_nodes: &vector<vector<u8>>, key: &vector<u8>): bool
+
+ + + +
+Implementation + + +
public fun verify_non_membership_proof_by_key(root_hash: &vector<u8>,
+                                              non_membership_leaf_data: &vector<u8>,
+                                              side_nodes: &vector<vector<u8>>,
+                                              key: &vector<u8>): bool {
+    let leaf_path = smt_tree_hasher::digest(key);
+    verify_non_membership_proof_by_leaf_path(root_hash, non_membership_leaf_data, side_nodes, &leaf_path)
+}
+
+ + + +
+ + + +## Function `verify_non_membership_proof_by_leaf_path` + + + +
public fun verify_non_membership_proof_by_leaf_path(root_hash: &vector<u8>, non_membership_leaf_data: &vector<u8>, side_nodes: &vector<vector<u8>>, leaf_path: &vector<u8>): bool
+
+ + + +
+Implementation + + +
public fun verify_non_membership_proof_by_leaf_path(
+    root_hash: &vector<u8>,
+    non_membership_leaf_data: &vector<u8>,
+    side_nodes: &vector<vector<u8>>,
+    leaf_path: &vector<u8>
+): bool {
+    let non_membership_leaf_hash = if (vector::length<u8>(non_membership_leaf_data) > 0) {
+        let (non_membership_leaf_path, _) = smt_tree_hasher::parse_leaf(non_membership_leaf_data);
+        assert!(*leaf_path != *&non_membership_leaf_path, error::invalid_state(ERROR_KEY_ALREADY_EXISTS_IN_PROOF));
+        assert!(
+            (smt_utils::count_common_prefix(leaf_path, &non_membership_leaf_path) >= vector::length(side_nodes)),
+            ERROR_COUNT_COMMON_PREFIX
+        );
+        smt_tree_hasher::digest_leaf_data(non_membership_leaf_data)
+    } else {
+        smt_tree_hasher::placeholder()
+    };
+    compute_root_hash(leaf_path, &non_membership_leaf_hash, side_nodes) == *root_hash
+}
+
+ + + +
+ + + +## Function `verify_membership_proof_by_key_value` + + + +
public fun verify_membership_proof_by_key_value(root_hash: &vector<u8>, side_nodes: &vector<vector<u8>>, key: &vector<u8>, value: &vector<u8>, is_raw_value: bool): bool
+
+ + + +
+Implementation + + +
public fun verify_membership_proof_by_key_value(
+    root_hash: &vector<u8>,
+    side_nodes: &vector<vector<u8>>,
+    key: &vector<u8>,
+    value: &vector<u8>,
+    is_raw_value: bool
+): bool {
+    let leaf_path = smt_tree_hasher::digest(key);
+    let leaf_value_hash = if (is_raw_value) {
+        &smt_tree_hasher::digest(value)
+    } else {
+        value
+    };
+    verify_membership_proof(root_hash, side_nodes, &leaf_path, leaf_value_hash)
+}
+
+ + + +
+ + + +## Function `verify_membership_proof` + + + +
public fun verify_membership_proof(root_hash: &vector<u8>, side_nodes: &vector<vector<u8>>, leaf_path: &vector<u8>, leaf_value_hash: &vector<u8>): bool
+
+ + + +
+Implementation + + +
public fun verify_membership_proof(
+    root_hash: &vector<u8>,
+    side_nodes: &vector<vector<u8>>,
+    leaf_path: &vector<u8>,
+    leaf_value_hash: &vector<u8>
+): bool {
+    let (leaf_hash, _) = smt_tree_hasher::digest_leaf(leaf_path, leaf_value_hash);
+    compute_root_hash(leaf_path, &leaf_hash, side_nodes) == *root_hash
+}
+
+ + + +
+ + + +## Function `compute_root_hash_by_leaf` + + + +
public fun compute_root_hash_by_leaf(leaf_path: &vector<u8>, leaf_value_hash: &vector<u8>, side_nodes: &vector<vector<u8>>): vector<u8>
+
+ + + +
+Implementation + + +
public fun compute_root_hash_by_leaf(
+    leaf_path: &vector<u8>,
+    leaf_value_hash: &vector<u8>,
+    side_nodes: &vector<vector<u8>>)
+: vector<u8> {
+    let (leaf_hash, _) = smt_tree_hasher::digest_leaf(leaf_path, leaf_value_hash);
+    compute_root_hash(leaf_path, &leaf_hash, side_nodes)
+}
+
+ + + +
+ + + +## Function `compute_root_hash_new_leaf_included` + + + +
public fun compute_root_hash_new_leaf_included(leaf_path: &vector<u8>, leaf_value_hash: &vector<u8>, non_membership_leaf_data: &vector<u8>, side_nodes: &vector<vector<u8>>): vector<u8>
+
+ + + +
+Implementation + + +
public fun compute_root_hash_new_leaf_included(leaf_path: &vector<u8>,
+                                               leaf_value_hash: &vector<u8>,
+                                               non_membership_leaf_data: &vector<u8>,
+                                               side_nodes: &vector<vector<u8>>): vector<u8> {
+    let (new_side_nodes, leaf_node_hash) = create_membership_side_nodes(
+        leaf_path,
+        leaf_value_hash,
+        non_membership_leaf_data,
+        side_nodes
+    );
+
+    compute_root_hash(leaf_path, &leaf_node_hash, &new_side_nodes)
+}
+
+ + + +
+ + + +## Function `create_membership_proof` + + + +
public fun create_membership_proof(leaf_path: &vector<u8>, leaf_value_hash: &vector<u8>, non_membership_leaf_data: &vector<u8>, side_nodes: &vector<vector<u8>>): (vector<u8>, vector<vector<u8>>)
+
+ + + +
+Implementation + + +
public fun create_membership_proof(leaf_path: &vector<u8>,
+                                   leaf_value_hash: &vector<u8>,
+                                   non_membership_leaf_data: &vector<u8>,
+                                   side_nodes: &vector<vector<u8>>): (vector<u8>, vector<vector<u8>>) {
+    let (new_side_nodes, leaf_node_hash) = create_membership_side_nodes(
+        leaf_path,
+        leaf_value_hash,
+        non_membership_leaf_data,
+        side_nodes
+    );
+    let new_root_hash = compute_root_hash(leaf_path, &leaf_node_hash, &new_side_nodes);
+    (new_root_hash, new_side_nodes)
+}
+
+ + + +
+ + + +## Function `create_membership_side_nodes` + + + +
fun create_membership_side_nodes(leaf_path: &vector<u8>, leaf_value_hash: &vector<u8>, non_membership_leaf_data: &vector<u8>, side_nodes: &vector<vector<u8>>): (vector<vector<u8>>, vector<u8>)
+
+ + + +
+Implementation + + +
fun create_membership_side_nodes(leaf_path: &vector<u8>,
+                                 leaf_value_hash: &vector<u8>,
+                                 non_membership_leaf_data: &vector<u8>,
+                                 side_nodes: &vector<vector<u8>>): (vector<vector<u8>>, vector<u8>) {
+    let side_nodes_len = vector::length<vector<u8>>(side_nodes);
+    let (new_leaf_hash, _) = smt_tree_hasher::digest_leaf(leaf_path, leaf_value_hash);
+    let new_side_nodes = if (vector::length(non_membership_leaf_data) > 0) {
+        let (non_membership_leaf_path, _) = smt_tree_hasher::parse_leaf(non_membership_leaf_data);
+        assert!(*leaf_path != *&non_membership_leaf_path, error::invalid_state(ERROR_KEY_ALREADY_EXISTS_IN_PROOF));
+
+        let common_prefix_count = smt_utils::count_common_prefix(leaf_path, &non_membership_leaf_path);
+        let old_leaf_hash = smt_tree_hasher::digest_leaf_data(non_membership_leaf_data);
+        let new_side_nodes = vector::empty<vector<u8>>();
+
+        vector::push_back(&mut new_side_nodes, old_leaf_hash);
+        if (common_prefix_count > side_nodes_len) {
+            let place_holder_len = (common_prefix_count - side_nodes_len);
+            // Put placeholders
+            let idx = 0;
+            while (idx < place_holder_len) {
+                vector::push_back(&mut new_side_nodes, smt_tree_hasher::placeholder());
+                idx = idx + 1;
+            };
+        };
+        new_side_nodes
+    } else {
+        vector::empty<vector<u8>>()
+    };
+
+    // Push old siblings into the new siblings array
+    let idx = 0;
+    while (idx < side_nodes_len) {
+        vector::push_back(&mut new_side_nodes, *vector::borrow(side_nodes, idx));
+        idx = idx + 1;
+    };
+    (new_side_nodes, new_leaf_hash)
+}
+
+ + + +
+ + + +## Function `compute_root_hash` + + + +
fun compute_root_hash(path: &vector<u8>, node_hash: &vector<u8>, side_nodes: &vector<vector<u8>>): vector<u8>
+
+ + + +
+Implementation + + +
fun compute_root_hash(path: &vector<u8>,
+                      node_hash: &vector<u8>,
+                      side_nodes: &vector<vector<u8>>): vector<u8> {
+    debug::print(side_nodes);
+    let side_nodes_len = vector::length<vector<u8>>(side_nodes);
+
+    let i = 0;
+    let current_hash = *node_hash;
+    while (i < side_nodes_len) {
+        let bit = smt_utils::get_bit_at_from_msb(path, side_nodes_len - i - 1);
+        let sibling_hash = vector::borrow<vector<u8>>(side_nodes, i);
+        if (bit == BIT_RIGHT) {
+            (current_hash, _) = smt_tree_hasher::digest_node(sibling_hash, ¤t_hash);
+        } else {
+            // left
+            (current_hash, _) = smt_tree_hasher::digest_node(¤t_hash, sibling_hash);
+        };
+        i = i + 1;
+    };
+    current_hash
+}
+
+ + + +
+ + +[move-book]: https://starcoin.dev/move/book/SUMMARY diff --git a/vm/framework/starcoin-framework/doc/smt_tree_hasher.md b/vm/framework/starcoin-framework/doc/smt_tree_hasher.md new file mode 100644 index 0000000000..19968ed255 --- /dev/null +++ b/vm/framework/starcoin-framework/doc/smt_tree_hasher.md @@ -0,0 +1,403 @@ + + + +# Module `0x1::smt_tree_hasher` + + + +- [Constants](#@Constants_0) +- [Function `parse_leaf`](#0x1_smt_tree_hasher_parse_leaf) +- [Function `parse_node`](#0x1_smt_tree_hasher_parse_node) +- [Function `digest_leaf`](#0x1_smt_tree_hasher_digest_leaf) +- [Function `create_leaf_data`](#0x1_smt_tree_hasher_create_leaf_data) +- [Function `digest_leaf_data`](#0x1_smt_tree_hasher_digest_leaf_data) +- [Function `digest_node`](#0x1_smt_tree_hasher_digest_node) +- [Function `path`](#0x1_smt_tree_hasher_path) +- [Function `digest`](#0x1_smt_tree_hasher_digest) +- [Function `path_size`](#0x1_smt_tree_hasher_path_size) +- [Function `path_size_in_bits`](#0x1_smt_tree_hasher_path_size_in_bits) +- [Function `placeholder`](#0x1_smt_tree_hasher_placeholder) + + +
use 0x1::error;
+use 0x1::smt_hash;
+use 0x1::smt_utils;
+
+ + + + + +## Constants + + + + + + +
const ERROR_INVALID_LEAF_DATA: u64 = 102;
+
+ + + + + + + +
const ERROR_INVALID_LEAF_DATA_LENGTH: u64 = 104;
+
+ + + + + + + +
const ERROR_INVALID_NODE_DATA: u64 = 103;
+
+ + + + + + + +
const ERROR_INVALID_NODE_DATA_LENGTH: u64 = 105;
+
+ + + + + + + +
const LEAF_PREFIX: vector<u8> = [0];
+
+ + + + + + + +
const NODE_PREFIX: vector<u8> = [1];
+
+ + + + + +## Function `parse_leaf` + + + +
public fun parse_leaf(data: &vector<u8>): (vector<u8>, vector<u8>)
+
+ + + +
+Implementation + + +
public fun parse_leaf(data: &vector<u8>): (vector<u8>, vector<u8>) {
+    let data_len = vector::length(data);
+
+    let prefix_len = vector::length(&LEAF_PREFIX);
+    assert!(data_len >= prefix_len + path_size(), error::invalid_argument(ERROR_INVALID_LEAF_DATA));
+    assert!(smt_utils::sub_u8_vector(data, 0, prefix_len) == LEAF_PREFIX, error::invalid_argument(ERROR_INVALID_LEAF_DATA));
+
+    let start = 0;
+    let end = prefix_len;
+    _ = start;//let prefix = smt_utils::sub_u8_vector(data, start, end);
+
+    start = end;
+    end = start + path_size();
+    let leaf_node_path = smt_utils::sub_u8_vector(data, start, end);
+
+    start = end;
+    end = vector::length(data);
+    let leaf_node_value = smt_utils::sub_u8_vector(data, start, end);
+    (leaf_node_path, leaf_node_value)
+}
+
+ + + +
+ + + +## Function `parse_node` + + + +
public fun parse_node(data: &vector<u8>): (vector<u8>, vector<u8>)
+
+ + + +
+Implementation + + +
public fun parse_node(data: &vector<u8>): (vector<u8>, vector<u8>) {
+    let data_len = vector::length(data);
+    let prefix_len = vector::length(&NODE_PREFIX);
+    assert!(data_len == prefix_len + path_size() * 2, error::invalid_argument(ERROR_INVALID_NODE_DATA));
+    assert!(smt_utils::sub_u8_vector(data, 0, prefix_len) == NODE_PREFIX, error::invalid_argument(ERROR_INVALID_NODE_DATA));
+
+    let start = 0;
+    let end = prefix_len;
+    _ = start;//let prefix = smt_utils::sub_u8_vector(data, start, end);
+
+    start = end;
+    end = start + path_size();
+    let left_data = smt_utils::sub_u8_vector(data, start, end);
+
+    start = end;
+    end = vector::length(data);
+    let right_data = smt_utils::sub_u8_vector(data, start, end);
+    (left_data, right_data)
+}
+
+ + + +
+ + + +## Function `digest_leaf` + + + +
public fun digest_leaf(path: &vector<u8>, leaf_value: &vector<u8>): (vector<u8>, vector<u8>)
+
+ + + +
+Implementation + + +
public fun digest_leaf(path: &vector<u8>, leaf_value: &vector<u8>): (vector<u8>, vector<u8>) {
+    let value = LEAF_PREFIX;
+    value = smt_utils::concat_u8_vectors(&value, *path);
+    value = smt_utils::concat_u8_vectors(&value, *leaf_value);
+    (smt_hash::hash(&value), value)
+}
+
+ + + +
+ + + +## Function `create_leaf_data` + + + +
public fun create_leaf_data(path: &vector<u8>, leaf_value: &vector<u8>): vector<u8>
+
+ + + +
+Implementation + + +
public fun create_leaf_data(path: &vector<u8>, leaf_value: &vector<u8>): vector<u8> {
+    let value = LEAF_PREFIX;
+    value = smt_utils::concat_u8_vectors(&value, *path);
+    value = smt_utils::concat_u8_vectors(&value, *leaf_value);
+    value
+}
+
+ + + +
+ + + +## Function `digest_leaf_data` + + + +
public fun digest_leaf_data(data: &vector<u8>): vector<u8>
+
+ + + +
+Implementation + + +
public fun digest_leaf_data(data: &vector<u8>): vector<u8> {
+    let data_len = vector::length(data);
+    let prefix_len = vector::length(&LEAF_PREFIX);
+    assert!(data_len >= prefix_len + path_size(), error::invalid_state(ERROR_INVALID_LEAF_DATA_LENGTH));
+    assert!(smt_utils::sub_u8_vector(data, 0, prefix_len) == LEAF_PREFIX, error::invalid_argument(ERROR_INVALID_LEAF_DATA));
+    smt_hash::hash(data)
+}
+
+ + + +
+ + + +## Function `digest_node` + + + +
public fun digest_node(left_data: &vector<u8>, right_data: &vector<u8>): (vector<u8>, vector<u8>)
+
+ + + +
+Implementation + + +
public fun digest_node(left_data: &vector<u8>, right_data: &vector<u8>): (vector<u8>, vector<u8>) {
+    let node_left_right_data_length = smt_hash::size();
+    assert!(vector::length(left_data) == node_left_right_data_length, error::invalid_state(ERROR_INVALID_NODE_DATA_LENGTH));
+    assert!(vector::length(right_data) == node_left_right_data_length, error::invalid_state(ERROR_INVALID_NODE_DATA_LENGTH));
+
+    let value = NODE_PREFIX;
+    value = smt_utils::concat_u8_vectors(&value, *left_data);
+    value = smt_utils::concat_u8_vectors(&value, *right_data);
+    (smt_hash::hash(&value), value)
+}
+
+ + + +
+ + + +## Function `path` + + + +
public fun path(key: &vector<u8>): vector<u8>
+
+ + + +
+Implementation + + +
public fun path(key: &vector<u8>): vector<u8> {
+    digest(key)
+}
+
+ + + +
+ + + +## Function `digest` + + + +
public fun digest(data: &vector<u8>): vector<u8>
+
+ + + +
+Implementation + + +
public fun digest(data: &vector<u8>): vector<u8> {
+    smt_hash::hash(data)
+}
+
+ + + +
+ + + +## Function `path_size` + + + +
public fun path_size(): u64
+
+ + + +
+Implementation + + +
public fun path_size(): u64 {
+    smt_hash::size()
+}
+
+ + + +
+ + + +## Function `path_size_in_bits` + + + +
public fun path_size_in_bits(): u64
+
+ + + +
+Implementation + + +
public fun path_size_in_bits(): u64 {
+    smt_hash::size() * 8
+}
+
+ + + +
+ + + +## Function `placeholder` + + + +
public fun placeholder(): vector<u8>
+
+ + + +
+Implementation + + +
public fun placeholder(): vector<u8> {
+    smt_hash::size_zero_bytes()
+}
+
+ + + +
+ + +[move-book]: https://starcoin.dev/move/book/SUMMARY diff --git a/vm/framework/starcoin-framework/doc/smt_utils.md b/vm/framework/starcoin-framework/doc/smt_utils.md new file mode 100644 index 0000000000..b8bb7e1756 --- /dev/null +++ b/vm/framework/starcoin-framework/doc/smt_utils.md @@ -0,0 +1,286 @@ + + + +# Module `0x1::smt_utils` + + + +- [Constants](#@Constants_0) +- [Function `get_bit_at_from_msb`](#0x1_smt_utils_get_bit_at_from_msb) +- [Function `count_common_prefix`](#0x1_smt_utils_count_common_prefix) +- [Function `count_vector_common_prefix`](#0x1_smt_utils_count_vector_common_prefix) +- [Function `bits_to_bool_vector_from_msb`](#0x1_smt_utils_bits_to_bool_vector_from_msb) +- [Function `concat_u8_vectors`](#0x1_smt_utils_concat_u8_vectors) +- [Function `sub_u8_vector`](#0x1_smt_utils_sub_u8_vector) +- [Function `sub_vector`](#0x1_smt_utils_sub_vector) + + +
use 0x1::error;
+use 0x1::vector;
+
+ + + + + +## Constants + + + + + + +
const BIT_LEFT: bool = false;
+
+ + + + + + + +
const BIT_RIGHT: bool = true;
+
+ + + + + + + +
const ERROR_VECTORS_NOT_SAME_LENGTH: u64 = 103;
+
+ + + + + +## Function `get_bit_at_from_msb` + + + +
public fun get_bit_at_from_msb(data: &vector<u8>, position: u64): bool
+
+ + + +
+Implementation + + +
public fun get_bit_at_from_msb(data: &vector<u8>, position: u64): bool {
+    let byte = (*vector::borrow<u8>(data, position / 8) as u64);
+    // let bit = BitOperators::rshift(byte, ((7 - (position % 8)) as u8));
+    let bit = byte >> ((7 - (position % 8)) as u8);
+    if (bit & 1 != 0) {
+        BIT_RIGHT
+    } else {
+        BIT_LEFT
+    }
+}
+
+ + + +
+ + + +## Function `count_common_prefix` + + + +
public fun count_common_prefix(data1: &vector<u8>, data2: &vector<u8>): u64
+
+ + + +
+Implementation + + +
public fun count_common_prefix(data1: &vector<u8>, data2: &vector<u8>): u64 {
+    let count = 0;
+    let i = 0;
+    while (i < vector::length(data1) * 8) {
+        if (get_bit_at_from_msb(data1, i) == get_bit_at_from_msb(data2, i)) {
+            count = count + 1;
+        } else {
+            break
+        };
+        i = i + 1;
+    };
+    count
+}
+
+ + + +
+ + + +## Function `count_vector_common_prefix` + + + +
public fun count_vector_common_prefix<ElementT: copy, drop>(vec1: &vector<ElementT>, vec2: &vector<ElementT>): u64
+
+ + + +
+Implementation + + +
public fun count_vector_common_prefix<ElementT: copy + drop>(
+    vec1: &vector<ElementT>,
+    vec2: &vector<ElementT>
+): u64 {
+    let vec_len = vector::length<ElementT>(vec1);
+    assert!(vec_len == vector::length<ElementT>(vec2), error::invalid_state(ERROR_VECTORS_NOT_SAME_LENGTH));
+    let idx = 0;
+    while (idx < vec_len) {
+        if (*vector::borrow(vec1, idx) != *vector::borrow(vec2, idx)) {
+            break
+        };
+        idx = idx + 1;
+    };
+    idx
+}
+
+ + + +
+ + + +## Function `bits_to_bool_vector_from_msb` + + + +
public fun bits_to_bool_vector_from_msb(data: &vector<u8>): vector<bool>
+
+ + + +
+Implementation + + +
public fun bits_to_bool_vector_from_msb(data: &vector<u8>): vector<bool> {
+    let i = 0;
+    let vec = vector::empty<bool>();
+    while (i < vector::length(data) * 8) {
+        vector::push_back<bool>(&mut vec, get_bit_at_from_msb(data, i));
+        i = i + 1;
+    };
+    vec
+}
+
+ + + +
+ + + +## Function `concat_u8_vectors` + + + +
public fun concat_u8_vectors(v1: &vector<u8>, v2: vector<u8>): vector<u8>
+
+ + + +
+Implementation + + +
public fun concat_u8_vectors(v1: &vector<u8>, v2: vector<u8>): vector<u8> {
+    let data = *v1;
+    vector::append(&mut data, v2);
+    data
+}
+
+ + + +
+ + + +## Function `sub_u8_vector` + + + +
public fun sub_u8_vector(vec: &vector<u8>, start: u64, end: u64): vector<u8>
+
+ + + +
+Implementation + + +
public fun sub_u8_vector(vec: &vector<u8>, start: u64, end: u64): vector<u8> {
+    let i = start;
+    let result = vector::empty<u8>();
+    let data_len = vector::length(vec);
+    let actual_end = if (end < data_len) {
+        end
+    } else {
+        data_len
+    };
+    while (i < actual_end) {
+        vector::push_back(&mut result, *vector::borrow(vec, i));
+        i = i + 1;
+    };
+    result
+}
+
+ + + +
+ + + +## Function `sub_vector` + + + +
public fun sub_vector<ElementT: copy>(vec: &vector<ElementT>, start: u64, end: u64): vector<ElementT>
+
+ + + +
+Implementation + + +
public fun sub_vector<ElementT: copy>(vec: &vector<ElementT>, start: u64, end: u64): vector<ElementT> {
+    let i = start;
+    let result = vector::empty<ElementT>();
+    let data_len = vector::length(vec);
+    let actual_end = if (end < data_len) {
+        end
+    } else {
+        data_len
+    };
+    while (i < actual_end) {
+        vector::push_back(&mut result, *vector::borrow(vec, i));
+        i = i + 1;
+    };
+    result
+}
+
+ + + +
+ + +[move-book]: https://starcoin.dev/move/book/SUMMARY diff --git a/vm/framework/starcoin-framework/sources/smt/smt_hash.move b/vm/framework/starcoin-framework/sources/smt/smt_hash.move new file mode 100644 index 0000000000..5e98b68585 --- /dev/null +++ b/vm/framework/starcoin-framework/sources/smt/smt_hash.move @@ -0,0 +1,63 @@ +module starcoin_framework::smt_hash { + use std::error; + use std::vector; + + use starcoin_framework::hash; + use starcoin_framework::smt_utils; + + const SIZE_ZERO_BYTES: vector = x"0000000000000000000000000000000000000000000000000000000000000000"; + + public fun size(): u64 { + 32 + } + + public fun hash(data: &vector): vector { + hash::sha3_256(*data) + } + + public fun size_zero_bytes(): vector { + SIZE_ZERO_BYTES + } + + const ERROR_INVALID_PATH_BYTES_LENGTH: u64 = 101; + const ERROR_INVALID_PATH_BITS_LENGTH: u64 = 102; + const ERROR_INVALID_NODES_DATA_PACKAGE_LENGTH: u64 = 103; + //const NODE_DATA_LENGTH: u64 = 32; + + + public fun path_bits_to_bool_vector_from_msb(path: &vector): vector { + let path_len = vector::length(path); + assert!(path_len == Self::size(), error::invalid_argument(ERROR_INVALID_PATH_BYTES_LENGTH)); + let result_vec = smt_utils::bits_to_bool_vector_from_msb(path); + assert!( + vector::length(&result_vec) == Self::size() * 8,// smt_tree_hasher::path_size_in_bits(), + error::invalid_state(ERROR_INVALID_PATH_BITS_LENGTH) + ); + result_vec + } + + + // Split sibling nodes data from concatenated data. + // Due `Move` API call not yet support the parameter type such as vector>, + // so we concat all vectors into one vector. + public fun split_side_nodes_data(side_nodes_data: &vector): vector> { + let node_data_length = Self::size(); + let len = vector::length(side_nodes_data); + assert!(len % node_data_length == 0, error::invalid_state(ERROR_INVALID_NODES_DATA_PACKAGE_LENGTH)); + + if (len > 0) { + let result = vector::empty>(); + let size = len / node_data_length; + let idx = 0; + while (idx < size) { + let start = idx * node_data_length; + let end = start + node_data_length; + vector::push_back(&mut result, smt_utils::sub_u8_vector(side_nodes_data, start, end)); + idx = idx + 1; + }; + result + } else { + vector::empty>() + } + } +} \ No newline at end of file diff --git a/vm/framework/starcoin-framework/sources/smt/smt_proofs.move b/vm/framework/starcoin-framework/sources/smt/smt_proofs.move new file mode 100644 index 0000000000..400b7ebe03 --- /dev/null +++ b/vm/framework/starcoin-framework/sources/smt/smt_proofs.move @@ -0,0 +1,369 @@ +// Sparse Merkle Tree proof for non-membership, +// reference Starcoin project's source file located at: "commons/forkable-jellyfish-merkle/src/proof.rs" +// +// Computes the hash of internal node according to [`JellyfishTree`](crate::JellyfishTree) +// data structure in the logical view. `start` and `nibble_height` determine a subtree whose +// root hash we want to get. For an internal node with 16 children at the bottom level, we compute +// the root hash of it as if a full binary Merkle tree with 16 leaves as below: +// +// ```text +// 4 -> +------ root hash ------+ +// | | +// 3 -> +---- # ----+ +---- # ----+ +// | | | | +// 2 -> # # # # +// / \ / \ / \ / \ +// 1 -> # # # # # # # # +// / \ / \ / \ / \ / \ / \ / \ / \ +// 0 -> 0 1 2 3 4 5 6 7 8 9 A B C D E F +// ^ +// height +// ``` +// +// As illustrated above, at nibble height 0, `0..F` in hex denote 16 chidren hashes. Each `#` +// means the hash of its two direct children, which will be used to generate the hash of its +// parent with the hash of its sibling. Finally, we can get the hash of this internal node. +// +// However, if an internal node doesn't have all 16 chidren exist at height 0 but just a few of +// them, we have a modified hashing rule on top of what is stated above: +// 1. From top to bottom, a node will be replaced by a leaf child if the subtree rooted at this +// node has only one child at height 0 and it is a leaf child. +// 2. From top to bottom, a node will be replaced by the placeholder node if the subtree rooted at +// this node doesn't have any child at height 0. For example, if an internal node has 3 leaf +// children at index 0, 3, 8, respectively, and 1 internal node at index C, then the computation +// graph will be like: +// +// ```text +// 4 -> +------ root hash ------+ +// | | +// 3 -> +---- # ----+ +---- # ----+ +// | | | | +// 2 -> # @ 8 # +// / \ / \ +// 1 -> 0 3 # @ +// / \ +// 0 -> C @ +// ^ +// height +// Note: @ denotes placeholder hash. +// ``` +module starcoin_framework::smt_proofs { + + use std::error; + use std::vector; + + use starcoin_framework::smt_tree_hasher; + use starcoin_framework::smt_utils; + use starcoin_std::debug; + + const ERROR_KEY_ALREADY_EXISTS_IN_PROOF: u64 = 101; + const ERROR_COUNT_COMMON_PREFIX: u64 = 102; + const BIT_RIGHT: bool = true; + + public fun verify_non_membership_proof_by_key(root_hash: &vector, + non_membership_leaf_data: &vector, + side_nodes: &vector>, + key: &vector): bool { + let leaf_path = smt_tree_hasher::digest(key); + verify_non_membership_proof_by_leaf_path(root_hash, non_membership_leaf_data, side_nodes, &leaf_path) + } + + // Verify non-membership proof by leaf path. + // Return true if leaf path(key) is not in the tree. + public fun verify_non_membership_proof_by_leaf_path( + root_hash: &vector, + non_membership_leaf_data: &vector, + side_nodes: &vector>, + leaf_path: &vector + ): bool { + let non_membership_leaf_hash = if (vector::length(non_membership_leaf_data) > 0) { + let (non_membership_leaf_path, _) = smt_tree_hasher::parse_leaf(non_membership_leaf_data); + assert!(*leaf_path != *&non_membership_leaf_path, error::invalid_state(ERROR_KEY_ALREADY_EXISTS_IN_PROOF)); + assert!( + (smt_utils::count_common_prefix(leaf_path, &non_membership_leaf_path) >= vector::length(side_nodes)), + ERROR_COUNT_COMMON_PREFIX + ); + smt_tree_hasher::digest_leaf_data(non_membership_leaf_data) + } else { + smt_tree_hasher::placeholder() + }; + compute_root_hash(leaf_path, &non_membership_leaf_hash, side_nodes) == *root_hash + } + + public fun verify_membership_proof_by_key_value( + root_hash: &vector, + side_nodes: &vector>, + key: &vector, + value: &vector, + is_raw_value: bool + ): bool { + let leaf_path = smt_tree_hasher::digest(key); + let leaf_value_hash = if (is_raw_value) { + &smt_tree_hasher::digest(value) + } else { + value + }; + verify_membership_proof(root_hash, side_nodes, &leaf_path, leaf_value_hash) + } + + public fun verify_membership_proof( + root_hash: &vector, + side_nodes: &vector>, + leaf_path: &vector, + leaf_value_hash: &vector + ): bool { + let (leaf_hash, _) = smt_tree_hasher::digest_leaf(leaf_path, leaf_value_hash); + compute_root_hash(leaf_path, &leaf_hash, side_nodes) == *root_hash + } + + public fun compute_root_hash_by_leaf( + leaf_path: &vector, + leaf_value_hash: &vector, + side_nodes: &vector>) + : vector { + let (leaf_hash, _) = smt_tree_hasher::digest_leaf(leaf_path, leaf_value_hash); + compute_root_hash(leaf_path, &leaf_hash, side_nodes) + } + + // Compute root hash after a new leaf included. + public fun compute_root_hash_new_leaf_included(leaf_path: &vector, + leaf_value_hash: &vector, + non_membership_leaf_data: &vector, + side_nodes: &vector>): vector { + let (new_side_nodes, leaf_node_hash) = create_membership_side_nodes( + leaf_path, + leaf_value_hash, + non_membership_leaf_data, + side_nodes + ); + + compute_root_hash(leaf_path, &leaf_node_hash, &new_side_nodes) + } + + // Create membership proof from non-membership proof. + // Return root hash, side nodes. + public fun create_membership_proof(leaf_path: &vector, + leaf_value_hash: &vector, + non_membership_leaf_data: &vector, + side_nodes: &vector>): (vector, vector>) { + let (new_side_nodes, leaf_node_hash) = create_membership_side_nodes( + leaf_path, + leaf_value_hash, + non_membership_leaf_data, + side_nodes + ); + let new_root_hash = compute_root_hash(leaf_path, &leaf_node_hash, &new_side_nodes); + (new_root_hash, new_side_nodes) + } + + // Create membership proof side nodes from non-membership proof. + fun create_membership_side_nodes(leaf_path: &vector, + leaf_value_hash: &vector, + non_membership_leaf_data: &vector, + side_nodes: &vector>): (vector>, vector) { + let side_nodes_len = vector::length>(side_nodes); + let (new_leaf_hash, _) = smt_tree_hasher::digest_leaf(leaf_path, leaf_value_hash); + let new_side_nodes = if (vector::length(non_membership_leaf_data) > 0) { + let (non_membership_leaf_path, _) = smt_tree_hasher::parse_leaf(non_membership_leaf_data); + assert!(*leaf_path != *&non_membership_leaf_path, error::invalid_state(ERROR_KEY_ALREADY_EXISTS_IN_PROOF)); + + let common_prefix_count = smt_utils::count_common_prefix(leaf_path, &non_membership_leaf_path); + let old_leaf_hash = smt_tree_hasher::digest_leaf_data(non_membership_leaf_data); + let new_side_nodes = vector::empty>(); + + vector::push_back(&mut new_side_nodes, old_leaf_hash); + if (common_prefix_count > side_nodes_len) { + let place_holder_len = (common_prefix_count - side_nodes_len); + // Put placeholders + let idx = 0; + while (idx < place_holder_len) { + vector::push_back(&mut new_side_nodes, smt_tree_hasher::placeholder()); + idx = idx + 1; + }; + }; + new_side_nodes + } else { + vector::empty>() + }; + + // Push old siblings into the new siblings array + let idx = 0; + while (idx < side_nodes_len) { + vector::push_back(&mut new_side_nodes, *vector::borrow(side_nodes, idx)); + idx = idx + 1; + }; + (new_side_nodes, new_leaf_hash) + } + + // Compute root hash. + // The parameter `node_hash` is leaf or internal node hash. + fun compute_root_hash(path: &vector, + node_hash: &vector, + side_nodes: &vector>): vector { + debug::print(side_nodes); + let side_nodes_len = vector::length>(side_nodes); + + let i = 0; + let current_hash = *node_hash; + while (i < side_nodes_len) { + let bit = smt_utils::get_bit_at_from_msb(path, side_nodes_len - i - 1); + let sibling_hash = vector::borrow>(side_nodes, i); + if (bit == BIT_RIGHT) { + (current_hash, _) = smt_tree_hasher::digest_node(sibling_hash, ¤t_hash); + } else { + // left + (current_hash, _) = smt_tree_hasher::digest_node(¤t_hash, sibling_hash); + }; + i = i + 1; + }; + current_hash + } + + // struct SparseMerkleInternalNode has store, drop { + // left_child: vector, + // right_child: vector, + // } + + // struct SparseMerkleLeafNode has store, drop { + // key: vector, + // } +} + +#[test_only] +module starcoin_framework::smt_non_membership_proof_test { + + use std::hash; + use std::vector; + use starcoin_framework::bcs_util; + use starcoin_framework::smt_utils; + use starcoin_framework::smt_tree_hasher; + use starcoin_framework::smt_hash; + use starcoin_std::debug; + + const TEST_CHAIN_ID: u64 = 218; + + struct MerkleInternalNode has store, drop { + left_child: vector, + right_child: vector, + } + + #[test] + public fun test_iter_bits() { + let hash = x"1000000000000000000000000000000000000000000000000000000000000000"; + debug::print(&hash::sha3_256(*&hash)); + + let bit_vec = smt_hash::path_bits_to_bool_vector_from_msb(&hash); + debug::print(&bit_vec); + assert!(vector::length(&bit_vec) == 256, 1101); + + let sub_bits = vector::slice(&bit_vec, 252, 256); + debug::print(&sub_bits); + assert!(vector::length(&sub_bits) == 4, 1102); + } + + // #[test] + // public fun test_bit() { + // assert!(BitOperators::and(1, 2) == 0, 1103); + // assert!(BitOperators::and(1, 3) == 1, 1104); + // assert!(BitOperators::and(1, 16 >> 4) == 1, 1105); + // } + + #[test] + public fun test_print_fix_keyword() { + let k1 = x"01"; + let k2 = b"helloworld"; + debug::print(&k1); + debug::print(&k2); + debug::print(&hash::sha3_256(k1)); + debug::print(&hash::sha3_256(k2)); + } + + + #[test] + public fun test_get_bit() { + // Print origin hash + let origin_hash = x"1000000000000000000000000000000000000000000000000000000000000001"; + debug::print(&origin_hash); + + // Expect first byte is 'F', which binary is 11111111 + let first_byte = *vector::borrow(&origin_hash, 0); + debug::print(&first_byte); + + // let bit = BitOperators::and(BitOperators::rshift((first_byte as u64), 4), (1 as u64)); + let bit = (first_byte >> 4 & 1); + debug::print(&bit); + assert!((first_byte >> 4 & 1) == 1, 1106); + + let bit_hash = vector::empty(); + let i = 0; + while (i < 256) { + vector::push_back(&mut bit_hash, smt_utils::get_bit_at_from_msb(&origin_hash, i)); + i = i + 1; + }; + debug::print(&bit_hash); + + // Test skip bit + vector::reverse(&mut bit_hash); + let skip_bits = vector::slice(&bit_hash, 252, 256); + debug::print(&skip_bits); + + let skip_bits_1 = vector::slice(&bit_hash, 0, 1); + debug::print(&skip_bits_1); + } + + #[test] + public fun test_fixed_leaf_node_data() { + let data = x"0076d3bc41c9f588f7fcd0d5bf4718f8f84b1c41b20882703100b9eb9413807c012767f15c8af2f2c7225d5273fdd683edc714110a987d1054697c348aed4e6cc7"; + let expect = x"da3c17cfd8be129f09b61272f8afcf42bf5b77cf7e405f5aa20c30684a205488"; + + let crypto_hash = smt_tree_hasher::digest_leaf_data(&data); + + debug::print(&crypto_hash); + debug::print(&expect); + assert!(crypto_hash == expect, 1107); + } + + #[test] + public fun test_fixed_internal_node_data() { + let left = x"24a7e02bc5b39e8a4b7d2396d2e637632d0938944d16d571f0485168461f46eb"; + let right = x"42bfc776a76b35ca641ee761a5f4bc6ebf2d4e2441c517f8a8e085dec3ca443c"; + let expect = x"060aec78413605e993f9338255b661ac794a68729ffa50022aca72b01586a306"; + + let (crypto_hash, _) = smt_tree_hasher::digest_node(&left, &right); + + debug::print(&crypto_hash); + debug::print(&expect); + + assert!(crypto_hash == expect, 1108); + } + + #[test] + fun test_common_prefix_bits_len() { + let bits1 = smt_hash::path_bits_to_bool_vector_from_msb( + &x"0000000000000000000000000000000000000000000000000000000000000000" + ); + let bits2 = smt_hash::path_bits_to_bool_vector_from_msb( + &x"1000000000000000000000000000000000000000000000000000000000000000" + ); + debug::print(&bits1); + debug::print(&bits2); + let len = smt_utils::count_vector_common_prefix(&bits1, &bits2); + debug::print(&len); + assert!(len == 3, 1109); + } + + #[test] + public fun test_fixed_split_leaf_node_data() { + let data = x"0076d3bc41c9f588f7fcd0d5bf4718f8f84b1c41b20882703100b9eb9413807c012767f15c8af2f2c7225d5273fdd683edc714110a987d1054697c348aed4e6cc7"; + let (leaf_node_path, leaf_node_value) = smt_tree_hasher::parse_leaf(&data); + //assert!(prefix == x"00", 1110); + + debug::print(&leaf_node_path); + debug::print(&x"76d3bc41c9f588f7fcd0d5bf4718f8f84b1c41b20882703100b9eb9413807c01"); + assert!(leaf_node_path == x"76d3bc41c9f588f7fcd0d5bf4718f8f84b1c41b20882703100b9eb9413807c01", 1106); + + debug::print(&leaf_node_value); + debug::print(&x"2767f15c8af2f2c7225d5273fdd683edc714110a987d1054697c348aed4e6cc7"); + assert!(leaf_node_value == x"2767f15c8af2f2c7225d5273fdd683edc714110a987d1054697c348aed4e6cc7", 1107); + } +} \ No newline at end of file diff --git a/vm/framework/starcoin-framework/sources/smt/smt_tree_hasher.move b/vm/framework/starcoin-framework/sources/smt/smt_tree_hasher.move new file mode 100644 index 0000000000..7f2c376899 --- /dev/null +++ b/vm/framework/starcoin-framework/sources/smt/smt_tree_hasher.move @@ -0,0 +1,139 @@ +module starcoin_framework::smt_tree_hasher { + + use std::error; + use std::vector; + + use starcoin_framework::smt_hash; + use starcoin_framework::smt_utils; + + // sparse merkle tree leaf(node) prefix. + const LEAF_PREFIX: vector = x"00"; + // sparse merkle tree (internal)node prefix. + const NODE_PREFIX: vector = x"01"; + + // Leaf node data include: prefix + leaf_path + leaf_value_hash + //const LEAF_DATA_LENGTH: u64 = 65; + //const NODE_LEFT_RIGHT_DATA_LENGTH: u64 = 32; + //const LEAF_PATH_LENGTH: u64 = 32; + + const ERROR_INVALID_LEAF_DATA: u64 = 102; + const ERROR_INVALID_NODE_DATA: u64 = 103; + const ERROR_INVALID_LEAF_DATA_LENGTH: u64 = 104; + const ERROR_INVALID_NODE_DATA_LENGTH: u64 = 105; + + // Parse leaf data. + // Return values: + // leaf node path. + // leaf node value. + public fun parse_leaf(data: &vector): (vector, vector) { + let data_len = vector::length(data); + + let prefix_len = vector::length(&LEAF_PREFIX); + assert!(data_len >= prefix_len + path_size(), error::invalid_argument(ERROR_INVALID_LEAF_DATA)); + assert!(smt_utils::sub_u8_vector(data, 0, prefix_len) == LEAF_PREFIX, error::invalid_argument(ERROR_INVALID_LEAF_DATA)); + + let start = 0; + let end = prefix_len; + _ = start;//let prefix = smt_utils::sub_u8_vector(data, start, end); + + start = end; + end = start + path_size(); + let leaf_node_path = smt_utils::sub_u8_vector(data, start, end); + + start = end; + end = vector::length(data); + let leaf_node_value = smt_utils::sub_u8_vector(data, start, end); + (leaf_node_path, leaf_node_value) + } + + // #[test] + // #[expected_failure] + // public fun test_parse_leaf_1() { + // let data = x"0189bd5770d361dfa0c06a8c1cf4d89ef194456ab5cf8fc55a9f6744aff0bfef812767f15c8af2f2c7225d5273fdd683edc714110a987d1054697c348aed4e6cc7"; + // let (leaf_node_path, leaf_node_value) = parse_leaf(&data); + // assert!(leaf_node_path == x"89bd5770d361dfa0c06a8c1cf4d89ef194456ab5cf8fc55a9f6744aff0bfef81", 101); + // assert!(leaf_node_value == x"2767f15c8af2f2c7225d5273fdd683edc714110a987d1054697c348aed4e6cc7", 101); + // } + // + // #[test] + // public fun test_parse_leaf_2() { + // let data = x"0089bd5770d361dfa0c06a8c1cf4d89ef194456ab5cf8fc55a9f6744aff0bfef812767f15c8af2f2c7225d5273fdd683edc714110a987d1054697c348aed4e6cc7"; + // let (leaf_node_path, leaf_node_value) = parse_leaf(&data); + // assert!(leaf_node_path == x"89bd5770d361dfa0c06a8c1cf4d89ef194456ab5cf8fc55a9f6744aff0bfef81", 101); + // assert!(leaf_node_value == x"2767f15c8af2f2c7225d5273fdd683edc714110a987d1054697c348aed4e6cc7", 101); + // } + + public fun parse_node(data: &vector): (vector, vector) { + let data_len = vector::length(data); + let prefix_len = vector::length(&NODE_PREFIX); + assert!(data_len == prefix_len + path_size() * 2, error::invalid_argument(ERROR_INVALID_NODE_DATA)); + assert!(smt_utils::sub_u8_vector(data, 0, prefix_len) == NODE_PREFIX, error::invalid_argument(ERROR_INVALID_NODE_DATA)); + + let start = 0; + let end = prefix_len; + _ = start;//let prefix = smt_utils::sub_u8_vector(data, start, end); + + start = end; + end = start + path_size(); + let left_data = smt_utils::sub_u8_vector(data, start, end); + + start = end; + end = vector::length(data); + let right_data = smt_utils::sub_u8_vector(data, start, end); + (left_data, right_data) + } + + public fun digest_leaf(path: &vector, leaf_value: &vector): (vector, vector) { + let value = LEAF_PREFIX; + value = smt_utils::concat_u8_vectors(&value, *path); + value = smt_utils::concat_u8_vectors(&value, *leaf_value); + (smt_hash::hash(&value), value) + } + + public fun create_leaf_data(path: &vector, leaf_value: &vector): vector { + let value = LEAF_PREFIX; + value = smt_utils::concat_u8_vectors(&value, *path); + value = smt_utils::concat_u8_vectors(&value, *leaf_value); + value + } + + // Digest leaf data. The parameter `data` includes leaf key and value. + public fun digest_leaf_data(data: &vector): vector { + let data_len = vector::length(data); + let prefix_len = vector::length(&LEAF_PREFIX); + assert!(data_len >= prefix_len + path_size(), error::invalid_state(ERROR_INVALID_LEAF_DATA_LENGTH)); + assert!(smt_utils::sub_u8_vector(data, 0, prefix_len) == LEAF_PREFIX, error::invalid_argument(ERROR_INVALID_LEAF_DATA)); + smt_hash::hash(data) + } + + public fun digest_node(left_data: &vector, right_data: &vector): (vector, vector) { + let node_left_right_data_length = smt_hash::size(); + assert!(vector::length(left_data) == node_left_right_data_length, error::invalid_state(ERROR_INVALID_NODE_DATA_LENGTH)); + assert!(vector::length(right_data) == node_left_right_data_length, error::invalid_state(ERROR_INVALID_NODE_DATA_LENGTH)); + + let value = NODE_PREFIX; + value = smt_utils::concat_u8_vectors(&value, *left_data); + value = smt_utils::concat_u8_vectors(&value, *right_data); + (smt_hash::hash(&value), value) + } + + public fun path(key: &vector): vector { + digest(key) + } + + public fun digest(data: &vector): vector { + smt_hash::hash(data) + } + + public fun path_size(): u64 { + smt_hash::size() + } + + public fun path_size_in_bits(): u64 { + smt_hash::size() * 8 + } + + public fun placeholder(): vector { + smt_hash::size_zero_bytes() + } +} \ No newline at end of file diff --git a/vm/framework/starcoin-framework/sources/smt/smt_utils.move b/vm/framework/starcoin-framework/sources/smt/smt_utils.move new file mode 100644 index 0000000000..582e24260a --- /dev/null +++ b/vm/framework/starcoin-framework/sources/smt/smt_utils.move @@ -0,0 +1,99 @@ +module starcoin_framework::smt_utils { + + use std::error; + use std::vector; + + const ERROR_VECTORS_NOT_SAME_LENGTH: u64 = 103; + const BIT_RIGHT: bool = true; + const BIT_LEFT: bool = false; + + // Get the bit at an offset from the most significant bit. + public fun get_bit_at_from_msb(data: &vector, position: u64): bool { + let byte = (*vector::borrow(data, position / 8) as u64); + // let bit = BitOperators::rshift(byte, ((7 - (position % 8)) as u8)); + let bit = byte >> ((7 - (position % 8)) as u8); + if (bit & 1 != 0) { + BIT_RIGHT + } else { + BIT_LEFT + } + } + + public fun count_common_prefix(data1: &vector, data2: &vector): u64 { + let count = 0; + let i = 0; + while (i < vector::length(data1) * 8) { + if (get_bit_at_from_msb(data1, i) == get_bit_at_from_msb(data2, i)) { + count = count + 1; + } else { + break + }; + i = i + 1; + }; + count + } + + public fun count_vector_common_prefix( + vec1: &vector, + vec2: &vector + ): u64 { + let vec_len = vector::length(vec1); + assert!(vec_len == vector::length(vec2), error::invalid_state(ERROR_VECTORS_NOT_SAME_LENGTH)); + let idx = 0; + while (idx < vec_len) { + if (*vector::borrow(vec1, idx) != *vector::borrow(vec2, idx)) { + break + }; + idx = idx + 1; + }; + idx + } + + public fun bits_to_bool_vector_from_msb(data: &vector): vector { + let i = 0; + let vec = vector::empty(); + while (i < vector::length(data) * 8) { + vector::push_back(&mut vec, get_bit_at_from_msb(data, i)); + i = i + 1; + }; + vec + } + + public fun concat_u8_vectors(v1: &vector, v2: vector): vector { + let data = *v1; + vector::append(&mut data, v2); + data + } + + public fun sub_u8_vector(vec: &vector, start: u64, end: u64): vector { + let i = start; + let result = vector::empty(); + let data_len = vector::length(vec); + let actual_end = if (end < data_len) { + end + } else { + data_len + }; + while (i < actual_end) { + vector::push_back(&mut result, *vector::borrow(vec, i)); + i = i + 1; + }; + result + } + + public fun sub_vector(vec: &vector, start: u64, end: u64): vector { + let i = start; + let result = vector::empty(); + let data_len = vector::length(vec); + let actual_end = if (end < data_len) { + end + } else { + data_len + }; + while (i < actual_end) { + vector::push_back(&mut result, *vector::borrow(vec, i)); + i = i + 1; + }; + result + } +} \ No newline at end of file From 6fed99e6416504ec822a9d558390bc3b6f457cca Mon Sep 17 00:00:00 2001 From: welbon <2261238+welbon@users.noreply.github.com> Date: Fri, 3 Jan 2025 14:52:55 +0800 Subject: [PATCH 09/29] [asset-mapping] removed unused code --- vm/framework/starcoin-framework/sources/smt/smt_proofs.move | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vm/framework/starcoin-framework/sources/smt/smt_proofs.move b/vm/framework/starcoin-framework/sources/smt/smt_proofs.move index 400b7ebe03..7c42e448b7 100644 --- a/vm/framework/starcoin-framework/sources/smt/smt_proofs.move +++ b/vm/framework/starcoin-framework/sources/smt/smt_proofs.move @@ -234,10 +234,10 @@ module starcoin_framework::smt_non_membership_proof_test { use std::hash; use std::vector; - use starcoin_framework::bcs_util; - use starcoin_framework::smt_utils; - use starcoin_framework::smt_tree_hasher; + use starcoin_framework::smt_hash; + use starcoin_framework::smt_tree_hasher; + use starcoin_framework::smt_utils; use starcoin_std::debug; const TEST_CHAIN_ID: u64 = 218; From 57bfdbfdfac1517c2d64250f31fe405063a4ff29 Mon Sep 17 00:00:00 2001 From: welbon <2261238+welbon@users.noreply.github.com> Date: Fri, 3 Jan 2025 17:15:40 +0800 Subject: [PATCH 10/29] [asset-mapping] reformat some codes --- .../sources/smt/smt_proofs.move | 52 +++++++++++-------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/vm/framework/starcoin-framework/sources/smt/smt_proofs.move b/vm/framework/starcoin-framework/sources/smt/smt_proofs.move index 7c42e448b7..bb2e1eb22c 100644 --- a/vm/framework/starcoin-framework/sources/smt/smt_proofs.move +++ b/vm/framework/starcoin-framework/sources/smt/smt_proofs.move @@ -60,10 +60,12 @@ module starcoin_framework::smt_proofs { const ERROR_COUNT_COMMON_PREFIX: u64 = 102; const BIT_RIGHT: bool = true; - public fun verify_non_membership_proof_by_key(root_hash: &vector, - non_membership_leaf_data: &vector, - side_nodes: &vector>, - key: &vector): bool { + public fun verify_non_membership_proof_by_key( + root_hash: &vector, + non_membership_leaf_data: &vector, + side_nodes: &vector>, + key: &vector + ): bool { let leaf_path = smt_tree_hasher::digest(key); verify_non_membership_proof_by_leaf_path(root_hash, non_membership_leaf_data, side_nodes, &leaf_path) } @@ -119,17 +121,19 @@ module starcoin_framework::smt_proofs { public fun compute_root_hash_by_leaf( leaf_path: &vector, leaf_value_hash: &vector, - side_nodes: &vector>) - : vector { + side_nodes: &vector> + ): vector { let (leaf_hash, _) = smt_tree_hasher::digest_leaf(leaf_path, leaf_value_hash); compute_root_hash(leaf_path, &leaf_hash, side_nodes) } // Compute root hash after a new leaf included. - public fun compute_root_hash_new_leaf_included(leaf_path: &vector, - leaf_value_hash: &vector, - non_membership_leaf_data: &vector, - side_nodes: &vector>): vector { + public fun compute_root_hash_new_leaf_included( + leaf_path: &vector, + leaf_value_hash: &vector, + non_membership_leaf_data: &vector, + side_nodes: &vector> + ): vector { let (new_side_nodes, leaf_node_hash) = create_membership_side_nodes( leaf_path, leaf_value_hash, @@ -142,10 +146,12 @@ module starcoin_framework::smt_proofs { // Create membership proof from non-membership proof. // Return root hash, side nodes. - public fun create_membership_proof(leaf_path: &vector, - leaf_value_hash: &vector, - non_membership_leaf_data: &vector, - side_nodes: &vector>): (vector, vector>) { + public fun create_membership_proof( + leaf_path: &vector, + leaf_value_hash: &vector, + non_membership_leaf_data: &vector, + side_nodes: &vector> + ): (vector, vector>) { let (new_side_nodes, leaf_node_hash) = create_membership_side_nodes( leaf_path, leaf_value_hash, @@ -157,10 +163,12 @@ module starcoin_framework::smt_proofs { } // Create membership proof side nodes from non-membership proof. - fun create_membership_side_nodes(leaf_path: &vector, - leaf_value_hash: &vector, - non_membership_leaf_data: &vector, - side_nodes: &vector>): (vector>, vector) { + fun create_membership_side_nodes( + leaf_path: &vector, + leaf_value_hash: &vector, + non_membership_leaf_data: &vector, + side_nodes: &vector> + ): (vector>, vector) { let side_nodes_len = vector::length>(side_nodes); let (new_leaf_hash, _) = smt_tree_hasher::digest_leaf(leaf_path, leaf_value_hash); let new_side_nodes = if (vector::length(non_membership_leaf_data) > 0) { @@ -197,9 +205,11 @@ module starcoin_framework::smt_proofs { // Compute root hash. // The parameter `node_hash` is leaf or internal node hash. - fun compute_root_hash(path: &vector, - node_hash: &vector, - side_nodes: &vector>): vector { + fun compute_root_hash( + path: &vector, + node_hash: &vector, + side_nodes: &vector> + ): vector { debug::print(side_nodes); let side_nodes_len = vector::length>(side_nodes); From 29274e51a5813e41da0f88aeafea61edb34117c0 Mon Sep 17 00:00:00 2001 From: welbon <2261238+welbon@users.noreply.github.com> Date: Fri, 3 Jan 2025 17:36:33 +0800 Subject: [PATCH 11/29] [asset-mapping] reformat some codes --- .../starcoin-framework/doc/smt_proofs.md | 52 +++++++++++-------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/vm/framework/starcoin-framework/doc/smt_proofs.md b/vm/framework/starcoin-framework/doc/smt_proofs.md index e8edd17d9d..585ad10ce6 100644 --- a/vm/framework/starcoin-framework/doc/smt_proofs.md +++ b/vm/framework/starcoin-framework/doc/smt_proofs.md @@ -72,10 +72,12 @@ Implementation -
public fun verify_non_membership_proof_by_key(root_hash: &vector<u8>,
-                                              non_membership_leaf_data: &vector<u8>,
-                                              side_nodes: &vector<vector<u8>>,
-                                              key: &vector<u8>): bool {
+
public fun verify_non_membership_proof_by_key(
+    root_hash: &vector<u8>,
+    non_membership_leaf_data: &vector<u8>,
+    side_nodes: &vector<vector<u8>>,
+    key: &vector<u8>
+): bool {
     let leaf_path = smt_tree_hasher::digest(key);
     verify_non_membership_proof_by_leaf_path(root_hash, non_membership_leaf_data, side_nodes, &leaf_path)
 }
@@ -209,8 +211,8 @@
 
public fun compute_root_hash_by_leaf(
     leaf_path: &vector<u8>,
     leaf_value_hash: &vector<u8>,
-    side_nodes: &vector<vector<u8>>)
-: vector<u8> {
+    side_nodes: &vector<vector<u8>>
+): vector<u8> {
     let (leaf_hash, _) = smt_tree_hasher::digest_leaf(leaf_path, leaf_value_hash);
     compute_root_hash(leaf_path, &leaf_hash, side_nodes)
 }
@@ -235,10 +237,12 @@
 Implementation
 
 
-
public fun compute_root_hash_new_leaf_included(leaf_path: &vector<u8>,
-                                               leaf_value_hash: &vector<u8>,
-                                               non_membership_leaf_data: &vector<u8>,
-                                               side_nodes: &vector<vector<u8>>): vector<u8> {
+
public fun compute_root_hash_new_leaf_included(
+    leaf_path: &vector<u8>,
+    leaf_value_hash: &vector<u8>,
+    non_membership_leaf_data: &vector<u8>,
+    side_nodes: &vector<vector<u8>>
+): vector<u8> {
     let (new_side_nodes, leaf_node_hash) = create_membership_side_nodes(
         leaf_path,
         leaf_value_hash,
@@ -269,10 +273,12 @@
 Implementation
 
 
-
public fun create_membership_proof(leaf_path: &vector<u8>,
-                                   leaf_value_hash: &vector<u8>,
-                                   non_membership_leaf_data: &vector<u8>,
-                                   side_nodes: &vector<vector<u8>>): (vector<u8>, vector<vector<u8>>) {
+
public fun create_membership_proof(
+    leaf_path: &vector<u8>,
+    leaf_value_hash: &vector<u8>,
+    non_membership_leaf_data: &vector<u8>,
+    side_nodes: &vector<vector<u8>>
+): (vector<u8>, vector<vector<u8>>) {
     let (new_side_nodes, leaf_node_hash) = create_membership_side_nodes(
         leaf_path,
         leaf_value_hash,
@@ -303,10 +309,12 @@
 Implementation
 
 
-
fun create_membership_side_nodes(leaf_path: &vector<u8>,
-                                 leaf_value_hash: &vector<u8>,
-                                 non_membership_leaf_data: &vector<u8>,
-                                 side_nodes: &vector<vector<u8>>): (vector<vector<u8>>, vector<u8>) {
+
fun create_membership_side_nodes(
+    leaf_path: &vector<u8>,
+    leaf_value_hash: &vector<u8>,
+    non_membership_leaf_data: &vector<u8>,
+    side_nodes: &vector<vector<u8>>
+): (vector<vector<u8>>, vector<u8>) {
     let side_nodes_len = vector::length<vector<u8>>(side_nodes);
     let (new_leaf_hash, _) = smt_tree_hasher::digest_leaf(leaf_path, leaf_value_hash);
     let new_side_nodes = if (vector::length(non_membership_leaf_data) > 0) {
@@ -361,9 +369,11 @@
 Implementation
 
 
-
fun compute_root_hash(path: &vector<u8>,
-                      node_hash: &vector<u8>,
-                      side_nodes: &vector<vector<u8>>): vector<u8> {
+
fun compute_root_hash(
+    path: &vector<u8>,
+    node_hash: &vector<u8>,
+    side_nodes: &vector<vector<u8>>
+): vector<u8> {
     debug::print(side_nodes);
     let side_nodes_len = vector::length<vector<u8>>(side_nodes);
 

From b98b96922954314e8d758ec429f92e406af1a473 Mon Sep 17 00:00:00 2001
From: welbon <2261238+welbon@users.noreply.github.com>
Date: Sat, 4 Jan 2025 19:40:26 +0800
Subject: [PATCH 12/29] [asset-mapping] add proof test for asset mapping

---
 executor/tests/executor_test.rs               | 81 +++++++++++++------
 .../sources/smt/smt_proofs.move               | 42 ++++++++++
 2 files changed, 100 insertions(+), 23 deletions(-)

diff --git a/executor/tests/executor_test.rs b/executor/tests/executor_test.rs
index cbb07528ae..a97ccc0269 100644
--- a/executor/tests/executor_test.rs
+++ b/executor/tests/executor_test.rs
@@ -1,45 +1,45 @@
 // Copyright (c) The Starcoin Core Contributors
 // SPDX-License-Identifier: Apache-2.0
 
+
 use anyhow::anyhow;
 use anyhow::Result;
+
 use starcoin_config::{BuiltinNetworkID, ChainNetwork};
 use starcoin_executor::validate_transaction;
 use starcoin_logger::prelude::*;
+use starcoin_state_api::{ChainStateReader, StateReaderExt};
 use starcoin_transaction_builder::{
-    build_batch_payload_same_amount, build_transfer_txn, encode_transfer_script_by_token_code,
-    raw_peer_to_peer_txn, DEFAULT_EXPIRATION_TIME, DEFAULT_MAX_GAS_AMOUNT,
+    build_batch_payload_same_amount, build_transfer_txn, DEFAULT_EXPIRATION_TIME,
+    DEFAULT_MAX_GAS_AMOUNT, encode_transfer_script_by_token_code, raw_peer_to_peer_txn,
 };
-use starcoin_types::account::peer_to_peer_txn;
-use starcoin_types::identifier::Identifier;
-use starcoin_types::language_storage::ModuleId;
-use starcoin_types::transaction::{EntryFunction, RawUserTransaction, TransactionArgument};
 use starcoin_types::{
     account_config, block_metadata::BlockMetadata, transaction::Transaction,
     transaction::TransactionPayload, transaction::TransactionStatus,
 };
-use starcoin_vm_types::account_config::genesis_address;
+use starcoin_types::account::Account;
+use starcoin_types::account::peer_to_peer_txn;
+use starcoin_types::account_config::G_STC_TOKEN_CODE;
+use starcoin_types::identifier::Identifier;
+use starcoin_types::language_storage::{CORE_CODE_ADDRESS, ModuleId, StructTag};
+use starcoin_types::transaction::{EntryFunction, RawUserTransaction, TransactionArgument};
+use starcoin_vm_runtime::starcoin_vm::{chunk_block_transactions, StarcoinVM};
+use starcoin_vm_types::{on_chain_config::{ConsensusConfig, OnChainConfig}, transaction::Package, vm_status::StatusCode};
+use starcoin_vm_types::access_path::AccessPath;
 use starcoin_vm_types::account_config::AccountResource;
+use starcoin_vm_types::account_config::core_code_address;
+use starcoin_vm_types::account_config::genesis_address;
 use starcoin_vm_types::genesis_config::ChainId;
-use starcoin_vm_types::on_chain_config::{ConsensusConfig, OnChainConfig};
+use starcoin_vm_types::state_store::state_key::StateKey;
+use starcoin_vm_types::state_store::state_value::StateValue;
 use starcoin_vm_types::state_store::TStateView;
 use starcoin_vm_types::token::stc::{stc_type_tag, STCUnit};
 use starcoin_vm_types::vm_status::KeptVMStatus;
-use starcoin_vm_types::{transaction::Package, vm_status::StatusCode};
 use test_helper::executor::{
     account_execute, account_execute_should_success, association_execute_should_success,
     blockmeta_execute, build_raw_txn, current_block_number, prepare_customized_genesis,
     TEST_MODULE, TEST_MODULE_1, TEST_MODULE_2,
 };
-
-// use test_helper::Account;
-use starcoin_state_api::StateReaderExt;
-use starcoin_types::account::Account;
-use starcoin_types::account_config::G_STC_TOKEN_CODE;
-use starcoin_vm_runtime::starcoin_vm::{chunk_block_transactions, StarcoinVM};
-use starcoin_vm_types::account_config::core_code_address;
-use starcoin_vm_types::state_store::state_key::StateKey;
-use starcoin_vm_types::state_store::state_value::StateValue;
 use test_helper::executor::{
     compile_modules_with_address, execute_and_apply, get_balance, get_sequence_number,
     prepare_genesis,
@@ -85,7 +85,7 @@ fn test_vm_version() {
         vec![TransactionArgument::Address(genesis_address())],
         None,
     )
-    .unwrap();
+        .unwrap();
 
     let readed_version: u64 = bcs_ext::from_bytes(&value.pop().unwrap().1).unwrap();
     let version = {
@@ -113,7 +113,7 @@ fn test_flexidag_config_get() {
         vec![TransactionArgument::Address(genesis_address())],
         None,
     )
-    .unwrap();
+        .unwrap();
 
     let read_version: u64 = bcs_ext::from_bytes(&value.pop().unwrap().1).unwrap();
     let version = {
@@ -564,7 +564,7 @@ fn test_validate_txn_args() -> Result<()> {
         );
         account1.sign_txn(txn)
     }
-    .unwrap();
+        .unwrap();
     assert!(validate_transaction(&chain_state, txn, None).is_some());
 
     let txn = {
@@ -585,7 +585,7 @@ fn test_validate_txn_args() -> Result<()> {
         );
         account1.sign_txn(txn)
     }
-    .unwrap();
+        .unwrap();
     assert!(validate_transaction(&chain_state, txn, None).is_some());
 
     let txn = {
@@ -606,7 +606,7 @@ fn test_validate_txn_args() -> Result<()> {
         );
         account1.sign_txn(txn)
     }
-    .unwrap();
+        .unwrap();
     assert!(validate_transaction(&chain_state, txn, None).is_some());
     Ok(())
 }
@@ -1134,3 +1134,38 @@ fn test_chunk_block_transactions() -> Result<()> {
 
     Ok(())
 }
+
+
+#[test]
+fn test_get_chain_id_after_genesis_with_proof_verify() -> Result<()> {
+    let (chain_state, _net) = prepare_genesis();
+    let chain_id_struct_tag = StructTag {
+        address: CORE_CODE_ADDRESS,
+        module: Identifier::new("chain_id").unwrap(),
+        name: Identifier::new("ChainId").unwrap(),
+        type_args: vec![],
+    };
+
+    let path_statekey = StateKey::resource(&CORE_CODE_ADDRESS, &chain_id_struct_tag)?;
+
+    // Print 0x1 version resource
+    let resource_value =
+        bcs_ext::from_bytes::(
+            &chain_state.get_resource(CORE_CODE_ADDRESS, &chain_id_struct_tag,
+            )?
+        )?;
+    println!("get_vm_version_verify | path: {:?}, state_value : {:?}", chain_id_struct_tag, resource_value);
+    assert_eq!(resource_value.id(), 0xff, "not expect chain id");
+
+
+    // Get proof and verify proof
+    let mut state_proof = chain_state.get_with_proof(&path_statekey)?;
+    let version_path = AccessPath::resource_access_path(genesis_address(), chain_id_struct_tag);
+    state_proof.verify(chain_state.state_root(), version_path.clone())?;
+
+    state_proof.state.as_mut().unwrap()[0] = 0xFE;
+    assert!(state_proof
+        .verify(chain_state.state_root(), version_path)
+        .is_err());
+    Ok(())
+}
diff --git a/vm/framework/starcoin-framework/sources/smt/smt_proofs.move b/vm/framework/starcoin-framework/sources/smt/smt_proofs.move
index bb2e1eb22c..f0a365f059 100644
--- a/vm/framework/starcoin-framework/sources/smt/smt_proofs.move
+++ b/vm/framework/starcoin-framework/sources/smt/smt_proofs.move
@@ -244,6 +244,7 @@ module starcoin_framework::smt_non_membership_proof_test {
 
     use std::hash;
     use std::vector;
+    use starcoin_framework::smt_proofs::verify_membership_proof_by_key_value;
 
     use starcoin_framework::smt_hash;
     use starcoin_framework::smt_tree_hasher;
@@ -376,4 +377,45 @@ module starcoin_framework::smt_non_membership_proof_test {
         debug::print(&x"2767f15c8af2f2c7225d5273fdd683edc714110a987d1054697c348aed4e6cc7");
         assert!(leaf_node_value == x"2767f15c8af2f2c7225d5273fdd683edc714110a987d1054697c348aed4e6cc7", 1107);
     }
+
+    // This function mainly verifies that the value of the 0x1::chain_id::ChainId structure is 0xff (i.e. 255)
+    // after the genesis of the test network is started.
+    //
+    // The test location of the rust code function name is `test_get_chain_id_after_genesis_with_proof_verify`
+    //
+    // expected_root_hash: HashValue(0xf65860f575bf2a198c069adb4e7872037e3a329b63ef617e40afa39b87b067c8),
+    // element_key: HashValue(0x4cc8bd9df94b37c233555d9a3bba0a712c3c709f047486d1e624b2bcd3b83266),
+    // element_blob: Some(Blob { Raw: 0xff  }),
+    // siblings: [
+    //   HashValue(0xcfb1462d4fc72f736eab2a56b2bf72ca6ad1c4e8c79557046a8b0adce047f007),
+    //   HashValue(0x5350415253455f4d45524b4c455f504c414345484f4c4445525f484153480000),
+    //   HashValue(0x5ca9febe74c7fde3fdcf2bd464de6d8899a0a13d464893aada2714c6fa774f9d),
+    //   HashValue(0x1519a398fed69687cabf51adf831f0ee1650aaf79775d00135fc70f55a73e151),
+    //   HashValue(0x50ce5c38983ba2eb196acd44e0aaedf040b1437ad1106e05ca452d7e27e4e03f),
+    //   HashValue(0x55ed28435637a061a6dd9e20b72849199cd36184570f976b7e306a27bebf2fdf),
+    //   HashValue(0x0dc23e31614798a6f67659b0b808b3eadc3b13a2a7bc03580a9e3004e45c2e6c),
+    //   HashValue(0x83bed048bc0bc452c98cb0e9f1cc0f691919eaf756864fc44940c2d1e01da92a)
+    // ]
+    #[test]
+    public fun test_verify_membership_proof_by_key_value() {
+        let siblings = vector::empty>();
+        vector::push_back(&mut siblings, x"cfb1462d4fc72f736eab2a56b2bf72ca6ad1c4e8c79557046a8b0adce047f007");
+        vector::push_back(&mut siblings, x"5350415253455f4d45524b4c455f504c414345484f4c4445525f484153480000");
+        vector::push_back(&mut siblings, x"5ca9febe74c7fde3fdcf2bd464de6d8899a0a13d464893aada2714c6fa774f9d");
+        vector::push_back(&mut siblings, x"1519a398fed69687cabf51adf831f0ee1650aaf79775d00135fc70f55a73e151");
+        vector::push_back(&mut siblings, x"50ce5c38983ba2eb196acd44e0aaedf040b1437ad1106e05ca452d7e27e4e03f");
+        vector::push_back(&mut siblings, x"55ed28435637a061a6dd9e20b72849199cd36184570f976b7e306a27bebf2fdf");
+        vector::push_back(&mut siblings, x"0dc23e31614798a6f67659b0b808b3eadc3b13a2a7bc03580a9e3004e45c2e6c");
+        vector::push_back(&mut siblings, x"83bed048bc0bc452c98cb0e9f1cc0f691919eaf756864fc44940c2d1e01da92a");
+
+        let expect_root_hash = x"f65860f575bf2a198c069adb4e7872037e3a329b63ef617e40afa39b87b067c8";
+        let element_key = x"4cc8bd9df94b37c233555d9a3bba0a712c3c709f047486d1e624b2bcd3b83266";
+        assert!(verify_membership_proof_by_key_value(
+            &expect_root_hash,
+            &siblings,
+            &element_key,
+            &x"ff",
+            false
+        ), 1111);
+    }
 }
\ No newline at end of file

From 4a92b4e2cd5d055242ffeece05bdb3de5b039102 Mon Sep 17 00:00:00 2001
From: welbon <2261238+welbon@users.noreply.github.com>
Date: Sun, 5 Jan 2025 23:28:01 +0800
Subject: [PATCH 13/29] [asset-mapping] Reorganized some Move codes

---
 .../starcoin-framework/doc/smt_proofs.md      |  39 +++-
 .../sources/smt/smt_hash.move                 |  46 ----
 .../smt/smt_non_membership_proof_test.move    | 138 +++++++++++
 .../sources/smt/smt_proofs.move               | 218 +++++-------------
 .../sources/smt/smt_tree_hasher.move          |   2 +-
 .../sources/smt/smt_utils.move                |  43 ++++
 6 files changed, 272 insertions(+), 214 deletions(-)
 create mode 100644 vm/framework/starcoin-framework/sources/smt/smt_non_membership_proof_test.move

diff --git a/vm/framework/starcoin-framework/doc/smt_proofs.md b/vm/framework/starcoin-framework/doc/smt_proofs.md
index 585ad10ce6..c2d8560c49 100644
--- a/vm/framework/starcoin-framework/doc/smt_proofs.md
+++ b/vm/framework/starcoin-framework/doc/smt_proofs.md
@@ -21,6 +21,7 @@
 use 0x1::error;
 use 0x1::smt_tree_hasher;
 use 0x1::smt_utils;
+use 0x1::string;
 
@@ -169,7 +170,7 @@ -
public fun verify_membership_proof(root_hash: &vector<u8>, side_nodes: &vector<vector<u8>>, leaf_path: &vector<u8>, leaf_value_hash: &vector<u8>): bool
+
public fun verify_membership_proof(expect_root_hash: &vector<u8>, sibling_nodes: &vector<vector<u8>>, leaf_path: &vector<u8>, leaf_value_hash: &vector<u8>): bool
 
@@ -179,13 +180,36 @@
public fun verify_membership_proof(
-    root_hash: &vector<u8>,
-    side_nodes: &vector<vector<u8>>,
+    expect_root_hash: &vector<u8>,
+    sibling_nodes: &vector<vector<u8>>,
     leaf_path: &vector<u8>,
     leaf_value_hash: &vector<u8>
 ): bool {
-    let (leaf_hash, _) = smt_tree_hasher::digest_leaf(leaf_path, leaf_value_hash);
-    compute_root_hash(leaf_path, &leaf_hash, side_nodes) == *root_hash
+    debug::print(
+        &string::utf8(b"smt_proofs::verify_membership_proof | entered, leaf path & leaf value hash & sibling_nodes")
+    );
+    debug::print(leaf_path);
+    debug::print(leaf_value_hash);
+    debug::print(sibling_nodes);
+
+    let (leaf_hash, leaf_value) = smt_tree_hasher::digest_leaf(leaf_path, leaf_value_hash);
+    debug::print(
+        &string::utf8(
+            b"smt_proofs::verify_membership_proof | after smt_tree_hasher::digest_leaf, leaf_path & leaf_value: "
+        )
+    );
+    debug::print(&leaf_hash);
+    debug::print(&leaf_value);
+
+    let ret_hash = compute_root_hash(leaf_path, &leaf_hash, sibling_nodes);
+    debug::print(
+        &string::utf8(
+            b"smt_proofs::verify_membership_proof | after Self::compute_root_hash, ret_hash & expect_root_hash: "
+        )
+    );
+    debug::print(&ret_hash);
+    debug::print(expect_root_hash);
+    ret_hash == *expect_root_hash
 }
 
@@ -360,7 +384,7 @@ -
fun compute_root_hash(path: &vector<u8>, node_hash: &vector<u8>, side_nodes: &vector<vector<u8>>): vector<u8>
+
public fun compute_root_hash(path: &vector<u8>, node_hash: &vector<u8>, side_nodes: &vector<vector<u8>>): vector<u8>
 
@@ -369,12 +393,11 @@ Implementation -
fun compute_root_hash(
+
public fun compute_root_hash(
     path: &vector<u8>,
     node_hash: &vector<u8>,
     side_nodes: &vector<vector<u8>>
 ): vector<u8> {
-    debug::print(side_nodes);
     let side_nodes_len = vector::length<vector<u8>>(side_nodes);
 
     let i = 0;
diff --git a/vm/framework/starcoin-framework/sources/smt/smt_hash.move b/vm/framework/starcoin-framework/sources/smt/smt_hash.move
index 5e98b68585..19a61672be 100644
--- a/vm/framework/starcoin-framework/sources/smt/smt_hash.move
+++ b/vm/framework/starcoin-framework/sources/smt/smt_hash.move
@@ -1,9 +1,5 @@
 module starcoin_framework::smt_hash {
-    use std::error;
-    use std::vector;
-
     use starcoin_framework::hash;
-    use starcoin_framework::smt_utils;
 
     const SIZE_ZERO_BYTES: vector = x"0000000000000000000000000000000000000000000000000000000000000000";
 
@@ -18,46 +14,4 @@ module starcoin_framework::smt_hash {
     public fun size_zero_bytes(): vector {
         SIZE_ZERO_BYTES
     }
-
-    const ERROR_INVALID_PATH_BYTES_LENGTH: u64 = 101;
-    const ERROR_INVALID_PATH_BITS_LENGTH: u64 = 102;
-    const ERROR_INVALID_NODES_DATA_PACKAGE_LENGTH: u64 = 103;
-    //const NODE_DATA_LENGTH: u64 = 32;
-
-
-    public fun path_bits_to_bool_vector_from_msb(path: &vector): vector {
-        let path_len = vector::length(path);
-        assert!(path_len == Self::size(), error::invalid_argument(ERROR_INVALID_PATH_BYTES_LENGTH));
-        let result_vec = smt_utils::bits_to_bool_vector_from_msb(path);
-        assert!(
-            vector::length(&result_vec) == Self::size() * 8,// smt_tree_hasher::path_size_in_bits(),
-            error::invalid_state(ERROR_INVALID_PATH_BITS_LENGTH)
-        );
-        result_vec
-    }
-
-
-    // Split sibling nodes data from concatenated data.
-    // Due `Move` API call not yet support the parameter type such as vector>,
-    // so we concat all vectors into one vector.
-    public fun split_side_nodes_data(side_nodes_data: &vector): vector> {
-        let node_data_length = Self::size();
-        let len = vector::length(side_nodes_data);
-        assert!(len % node_data_length == 0, error::invalid_state(ERROR_INVALID_NODES_DATA_PACKAGE_LENGTH));
-
-        if (len > 0) {
-            let result = vector::empty>();
-            let size = len / node_data_length;
-            let idx = 0;
-            while (idx < size) {
-                let start = idx * node_data_length;
-                let end = start + node_data_length;
-                vector::push_back(&mut result, smt_utils::sub_u8_vector(side_nodes_data, start, end));
-                idx = idx + 1;
-            };
-            result
-        } else {
-            vector::empty>()
-        }
-    }
 }
\ No newline at end of file
diff --git a/vm/framework/starcoin-framework/sources/smt/smt_non_membership_proof_test.move b/vm/framework/starcoin-framework/sources/smt/smt_non_membership_proof_test.move
new file mode 100644
index 0000000000..10c20e27e7
--- /dev/null
+++ b/vm/framework/starcoin-framework/sources/smt/smt_non_membership_proof_test.move
@@ -0,0 +1,138 @@
+
+#[test_only]
+module starcoin_framework::smt_non_membership_proof_test {
+
+    use std::hash;
+    use std::vector;
+
+    use starcoin_framework::smt_tree_hasher;
+    use starcoin_framework::smt_utils;
+    use starcoin_std::debug;
+
+    const TEST_CHAIN_ID: u64 = 218;
+
+    struct MerkleInternalNode has store, drop {
+        left_child: vector,
+        right_child: vector,
+    }
+
+    #[test]
+    public fun test_iter_bits() {
+        let hash = x"1000000000000000000000000000000000000000000000000000000000000000";
+        debug::print(&hash::sha3_256(*&hash));
+
+        let bit_vec = smt_utils::path_bits_to_bool_vector_from_msb(&hash);
+        debug::print(&bit_vec);
+        assert!(vector::length(&bit_vec) == 256, 1101);
+
+        let sub_bits = vector::slice(&bit_vec, 252, 256);
+        debug::print(&sub_bits);
+        assert!(vector::length(&sub_bits) == 4, 1102);
+    }
+
+    // #[test]
+    // public fun test_bit() {
+    //     assert!(BitOperators::and(1, 2) == 0, 1103);
+    //     assert!(BitOperators::and(1, 3) == 1, 1104);
+    //     assert!(BitOperators::and(1, 16 >> 4) == 1, 1105);
+    // }
+
+    #[test]
+    public fun test_print_fix_keyword() {
+        let k1 = x"01";
+        let k2 = b"helloworld";
+        debug::print(&k1);
+        debug::print(&k2);
+        debug::print(&hash::sha3_256(k1));
+        debug::print(&hash::sha3_256(k2));
+    }
+
+
+    #[test]
+    public fun test_get_bit() {
+        // Print origin hash
+        let origin_hash = x"1000000000000000000000000000000000000000000000000000000000000001";
+        debug::print(&origin_hash);
+
+        // Expect first byte is 'F', which binary is 11111111
+        let first_byte = *vector::borrow(&origin_hash, 0);
+        debug::print(&first_byte);
+
+        // let bit = BitOperators::and(BitOperators::rshift((first_byte as u64), 4), (1 as u64));
+        let bit = (first_byte >> 4 & 1);
+        debug::print(&bit);
+        assert!((first_byte >> 4 & 1) == 1, 1106);
+
+        let bit_hash = vector::empty();
+        let i = 0;
+        while (i < 256) {
+            vector::push_back(&mut bit_hash, smt_utils::get_bit_at_from_msb(&origin_hash, i));
+            i = i + 1;
+        };
+        debug::print(&bit_hash);
+
+        // Test skip bit
+        vector::reverse(&mut bit_hash);
+        let skip_bits = vector::slice(&bit_hash, 252, 256);
+        debug::print(&skip_bits);
+
+        let skip_bits_1 = vector::slice(&bit_hash, 0, 1);
+        debug::print(&skip_bits_1);
+    }
+
+    #[test]
+    public fun test_fixed_leaf_node_data() {
+        let data = x"0076d3bc41c9f588f7fcd0d5bf4718f8f84b1c41b20882703100b9eb9413807c012767f15c8af2f2c7225d5273fdd683edc714110a987d1054697c348aed4e6cc7";
+        let expect = x"da3c17cfd8be129f09b61272f8afcf42bf5b77cf7e405f5aa20c30684a205488";
+
+        let crypto_hash = smt_tree_hasher::digest_leaf_data(&data);
+
+        debug::print(&crypto_hash);
+        debug::print(&expect);
+        assert!(crypto_hash == expect, 1107);
+    }
+
+    #[test]
+    public fun test_fixed_internal_node_data() {
+        let left = x"24a7e02bc5b39e8a4b7d2396d2e637632d0938944d16d571f0485168461f46eb";
+        let right = x"42bfc776a76b35ca641ee761a5f4bc6ebf2d4e2441c517f8a8e085dec3ca443c";
+        let expect = x"060aec78413605e993f9338255b661ac794a68729ffa50022aca72b01586a306";
+
+        let (crypto_hash, _) = smt_tree_hasher::digest_node(&left, &right);
+
+        debug::print(&crypto_hash);
+        debug::print(&expect);
+
+        assert!(crypto_hash == expect, 1108);
+    }
+
+    #[test]
+    fun test_common_prefix_bits_len() {
+        let bits1 = smt_utils::path_bits_to_bool_vector_from_msb(
+            &x"0000000000000000000000000000000000000000000000000000000000000000"
+        );
+        let bits2 = smt_utils::path_bits_to_bool_vector_from_msb(
+            &x"1000000000000000000000000000000000000000000000000000000000000000"
+        );
+        debug::print(&bits1);
+        debug::print(&bits2);
+        let len = smt_utils::count_vector_common_prefix(&bits1, &bits2);
+        debug::print(&len);
+        assert!(len == 3, 1109);
+    }
+
+    #[test]
+    public fun test_fixed_split_leaf_node_data() {
+        let data = x"0076d3bc41c9f588f7fcd0d5bf4718f8f84b1c41b20882703100b9eb9413807c012767f15c8af2f2c7225d5273fdd683edc714110a987d1054697c348aed4e6cc7";
+        let (leaf_node_path, leaf_node_value) = smt_tree_hasher::parse_leaf(&data);
+        //assert!(prefix == x"00", 1110);
+
+        debug::print(&leaf_node_path);
+        debug::print(&x"76d3bc41c9f588f7fcd0d5bf4718f8f84b1c41b20882703100b9eb9413807c01");
+        assert!(leaf_node_path == x"76d3bc41c9f588f7fcd0d5bf4718f8f84b1c41b20882703100b9eb9413807c01", 1106);
+
+        debug::print(&leaf_node_value);
+        debug::print(&x"2767f15c8af2f2c7225d5273fdd683edc714110a987d1054697c348aed4e6cc7");
+        assert!(leaf_node_value == x"2767f15c8af2f2c7225d5273fdd683edc714110a987d1054697c348aed4e6cc7", 1107);
+    }
+}
\ No newline at end of file
diff --git a/vm/framework/starcoin-framework/sources/smt/smt_proofs.move b/vm/framework/starcoin-framework/sources/smt/smt_proofs.move
index f0a365f059..d95ab211c6 100644
--- a/vm/framework/starcoin-framework/sources/smt/smt_proofs.move
+++ b/vm/framework/starcoin-framework/sources/smt/smt_proofs.move
@@ -50,12 +50,16 @@
 module starcoin_framework::smt_proofs {
 
     use std::error;
+    use std::string;
     use std::vector;
 
     use starcoin_framework::smt_tree_hasher;
     use starcoin_framework::smt_utils;
     use starcoin_std::debug;
 
+    #[test_only]
+    use starcoin_framework::smt_hash;
+
     const ERROR_KEY_ALREADY_EXISTS_IN_PROOF: u64 = 101;
     const ERROR_COUNT_COMMON_PREFIX: u64 = 102;
     const BIT_RIGHT: bool = true;
@@ -109,13 +113,36 @@ module starcoin_framework::smt_proofs {
     }
 
     public fun verify_membership_proof(
-        root_hash: &vector,
-        side_nodes: &vector>,
+        expect_root_hash: &vector,
+        sibling_nodes: &vector>,
         leaf_path: &vector,
         leaf_value_hash: &vector
     ): bool {
-        let (leaf_hash, _) = smt_tree_hasher::digest_leaf(leaf_path, leaf_value_hash);
-        compute_root_hash(leaf_path, &leaf_hash, side_nodes) == *root_hash
+        debug::print(
+            &string::utf8(b"smt_proofs::verify_membership_proof | entered, leaf path & leaf value hash & sibling_nodes")
+        );
+        debug::print(leaf_path);
+        debug::print(leaf_value_hash);
+        debug::print(sibling_nodes);
+
+        let (leaf_hash, leaf_value) = smt_tree_hasher::digest_leaf(leaf_path, leaf_value_hash);
+        debug::print(
+            &string::utf8(
+                b"smt_proofs::verify_membership_proof | after smt_tree_hasher::digest_leaf, leaf_path & leaf_value: "
+            )
+        );
+        debug::print(&leaf_hash);
+        debug::print(&leaf_value);
+
+        let ret_hash = compute_root_hash(leaf_path, &leaf_hash, sibling_nodes);
+        debug::print(
+            &string::utf8(
+                b"smt_proofs::verify_membership_proof | after Self::compute_root_hash, ret_hash & expect_root_hash: "
+            )
+        );
+        debug::print(&ret_hash);
+        debug::print(expect_root_hash);
+        ret_hash == *expect_root_hash
     }
 
     public fun compute_root_hash_by_leaf(
@@ -205,12 +232,11 @@ module starcoin_framework::smt_proofs {
 
     // Compute root hash.
     // The parameter `node_hash` is leaf or internal node hash.
-    fun compute_root_hash(
+    public fun compute_root_hash(
         path: &vector,
         node_hash: &vector,
         side_nodes: &vector>
     ): vector {
-        debug::print(side_nodes);
         let side_nodes_len = vector::length>(side_nodes);
 
         let i = 0;
@@ -229,154 +255,6 @@ module starcoin_framework::smt_proofs {
         current_hash
     }
 
-    //    struct SparseMerkleInternalNode has store, drop {
-    //        left_child: vector,
-    //        right_child: vector,
-    //    }
-
-    //    struct SparseMerkleLeafNode has store, drop {
-    //        key: vector,
-    //    }
-}
-
-#[test_only]
-module starcoin_framework::smt_non_membership_proof_test {
-
-    use std::hash;
-    use std::vector;
-    use starcoin_framework::smt_proofs::verify_membership_proof_by_key_value;
-
-    use starcoin_framework::smt_hash;
-    use starcoin_framework::smt_tree_hasher;
-    use starcoin_framework::smt_utils;
-    use starcoin_std::debug;
-
-    const TEST_CHAIN_ID: u64 = 218;
-
-    struct MerkleInternalNode has store, drop {
-        left_child: vector,
-        right_child: vector,
-    }
-
-    #[test]
-    public fun test_iter_bits() {
-        let hash = x"1000000000000000000000000000000000000000000000000000000000000000";
-        debug::print(&hash::sha3_256(*&hash));
-
-        let bit_vec = smt_hash::path_bits_to_bool_vector_from_msb(&hash);
-        debug::print(&bit_vec);
-        assert!(vector::length(&bit_vec) == 256, 1101);
-
-        let sub_bits = vector::slice(&bit_vec, 252, 256);
-        debug::print(&sub_bits);
-        assert!(vector::length(&sub_bits) == 4, 1102);
-    }
-
-    // #[test]
-    // public fun test_bit() {
-    //     assert!(BitOperators::and(1, 2) == 0, 1103);
-    //     assert!(BitOperators::and(1, 3) == 1, 1104);
-    //     assert!(BitOperators::and(1, 16 >> 4) == 1, 1105);
-    // }
-
-    #[test]
-    public fun test_print_fix_keyword() {
-        let k1 = x"01";
-        let k2 = b"helloworld";
-        debug::print(&k1);
-        debug::print(&k2);
-        debug::print(&hash::sha3_256(k1));
-        debug::print(&hash::sha3_256(k2));
-    }
-
-
-    #[test]
-    public fun test_get_bit() {
-        // Print origin hash
-        let origin_hash = x"1000000000000000000000000000000000000000000000000000000000000001";
-        debug::print(&origin_hash);
-
-        // Expect first byte is 'F', which binary is 11111111
-        let first_byte = *vector::borrow(&origin_hash, 0);
-        debug::print(&first_byte);
-
-        // let bit = BitOperators::and(BitOperators::rshift((first_byte as u64), 4), (1 as u64));
-        let bit = (first_byte >> 4 & 1);
-        debug::print(&bit);
-        assert!((first_byte >> 4 & 1) == 1, 1106);
-
-        let bit_hash = vector::empty();
-        let i = 0;
-        while (i < 256) {
-            vector::push_back(&mut bit_hash, smt_utils::get_bit_at_from_msb(&origin_hash, i));
-            i = i + 1;
-        };
-        debug::print(&bit_hash);
-
-        // Test skip bit
-        vector::reverse(&mut bit_hash);
-        let skip_bits = vector::slice(&bit_hash, 252, 256);
-        debug::print(&skip_bits);
-
-        let skip_bits_1 = vector::slice(&bit_hash, 0, 1);
-        debug::print(&skip_bits_1);
-    }
-
-    #[test]
-    public fun test_fixed_leaf_node_data() {
-        let data = x"0076d3bc41c9f588f7fcd0d5bf4718f8f84b1c41b20882703100b9eb9413807c012767f15c8af2f2c7225d5273fdd683edc714110a987d1054697c348aed4e6cc7";
-        let expect = x"da3c17cfd8be129f09b61272f8afcf42bf5b77cf7e405f5aa20c30684a205488";
-
-        let crypto_hash = smt_tree_hasher::digest_leaf_data(&data);
-
-        debug::print(&crypto_hash);
-        debug::print(&expect);
-        assert!(crypto_hash == expect, 1107);
-    }
-
-    #[test]
-    public fun test_fixed_internal_node_data() {
-        let left = x"24a7e02bc5b39e8a4b7d2396d2e637632d0938944d16d571f0485168461f46eb";
-        let right = x"42bfc776a76b35ca641ee761a5f4bc6ebf2d4e2441c517f8a8e085dec3ca443c";
-        let expect = x"060aec78413605e993f9338255b661ac794a68729ffa50022aca72b01586a306";
-
-        let (crypto_hash, _) = smt_tree_hasher::digest_node(&left, &right);
-
-        debug::print(&crypto_hash);
-        debug::print(&expect);
-
-        assert!(crypto_hash == expect, 1108);
-    }
-
-    #[test]
-    fun test_common_prefix_bits_len() {
-        let bits1 = smt_hash::path_bits_to_bool_vector_from_msb(
-            &x"0000000000000000000000000000000000000000000000000000000000000000"
-        );
-        let bits2 = smt_hash::path_bits_to_bool_vector_from_msb(
-            &x"1000000000000000000000000000000000000000000000000000000000000000"
-        );
-        debug::print(&bits1);
-        debug::print(&bits2);
-        let len = smt_utils::count_vector_common_prefix(&bits1, &bits2);
-        debug::print(&len);
-        assert!(len == 3, 1109);
-    }
-
-    #[test]
-    public fun test_fixed_split_leaf_node_data() {
-        let data = x"0076d3bc41c9f588f7fcd0d5bf4718f8f84b1c41b20882703100b9eb9413807c012767f15c8af2f2c7225d5273fdd683edc714110a987d1054697c348aed4e6cc7";
-        let (leaf_node_path, leaf_node_value) = smt_tree_hasher::parse_leaf(&data);
-        //assert!(prefix == x"00", 1110);
-
-        debug::print(&leaf_node_path);
-        debug::print(&x"76d3bc41c9f588f7fcd0d5bf4718f8f84b1c41b20882703100b9eb9413807c01");
-        assert!(leaf_node_path == x"76d3bc41c9f588f7fcd0d5bf4718f8f84b1c41b20882703100b9eb9413807c01", 1106);
-
-        debug::print(&leaf_node_value);
-        debug::print(&x"2767f15c8af2f2c7225d5273fdd683edc714110a987d1054697c348aed4e6cc7");
-        assert!(leaf_node_value == x"2767f15c8af2f2c7225d5273fdd683edc714110a987d1054697c348aed4e6cc7", 1107);
-    }
 
     // This function mainly verifies that the value of the 0x1::chain_id::ChainId structure is 0xff (i.e. 255)
     // after the genesis of the test network is started.
@@ -396,8 +274,9 @@ module starcoin_framework::smt_non_membership_proof_test {
     //   HashValue(0x0dc23e31614798a6f67659b0b808b3eadc3b13a2a7bc03580a9e3004e45c2e6c),
     //   HashValue(0x83bed048bc0bc452c98cb0e9f1cc0f691919eaf756864fc44940c2d1e01da92a)
     // ]
+
     #[test]
-    public fun test_verify_membership_proof_by_key_value() {
+    public fun test_verify_membership_proof() {
         let siblings = vector::empty>();
         vector::push_back(&mut siblings, x"cfb1462d4fc72f736eab2a56b2bf72ca6ad1c4e8c79557046a8b0adce047f007");
         vector::push_back(&mut siblings, x"5350415253455f4d45524b4c455f504c414345484f4c4445525f484153480000");
@@ -410,12 +289,33 @@ module starcoin_framework::smt_non_membership_proof_test {
 
         let expect_root_hash = x"f65860f575bf2a198c069adb4e7872037e3a329b63ef617e40afa39b87b067c8";
         let element_key = x"4cc8bd9df94b37c233555d9a3bba0a712c3c709f047486d1e624b2bcd3b83266";
-        assert!(verify_membership_proof_by_key_value(
+        assert!(Self::verify_membership_proof(
             &expect_root_hash,
             &siblings,
             &element_key,
             &x"ff",
-            false
-        ), 1111);
+        ), 1110);
+
+        // let node_data = vector::empty();
+        // vector::append(&mut node_data, element_key);
+        //
+        // let value_hash = smt_hash::hash(&x"00000000000000ff");
+        // debug::print(&string::utf8(b"test_verify_membership_proof | value_hash "));
+        // debug::print(&value_hash);
+        // vector::append(&mut node_data, value_hash);
+        //
+        // let node_hash = smt_hash::hash(&node_data);
+        // debug::print(&string::utf8(b"test_verify_membership_proof | current_hash "));
+        // debug::print(&node_hash);
+        //
+        // let actual_root = Self::compute_root_hash(
+        //     &element_key,
+        //     //&node_hash,
+        //     &x"796c380bdad1231f930708197d9d4ddffe61e8bf2b3d817a0efe21230b11ae2e",
+        //     &siblings,
+        // );
+        // assert!(actual_root == expect_root_hash, 1110);
+
     }
-}
\ No newline at end of file
+}
+
diff --git a/vm/framework/starcoin-framework/sources/smt/smt_tree_hasher.move b/vm/framework/starcoin-framework/sources/smt/smt_tree_hasher.move
index 7f2c376899..49501591d5 100644
--- a/vm/framework/starcoin-framework/sources/smt/smt_tree_hasher.move
+++ b/vm/framework/starcoin-framework/sources/smt/smt_tree_hasher.move
@@ -8,7 +8,7 @@ module starcoin_framework::smt_tree_hasher {
 
     // sparse merkle tree leaf(node) prefix.
     const LEAF_PREFIX: vector = x"00";
-    // sparse merkle tree (internal)node prefix.
+    // sparse merkle tree (internal) node prefix.
     const NODE_PREFIX: vector = x"01";
 
     // Leaf node data include: prefix + leaf_path + leaf_value_hash
diff --git a/vm/framework/starcoin-framework/sources/smt/smt_utils.move b/vm/framework/starcoin-framework/sources/smt/smt_utils.move
index 582e24260a..2b69a28fcb 100644
--- a/vm/framework/starcoin-framework/sources/smt/smt_utils.move
+++ b/vm/framework/starcoin-framework/sources/smt/smt_utils.move
@@ -2,11 +2,17 @@ module starcoin_framework::smt_utils {
 
     use std::error;
     use std::vector;
+    use starcoin_framework::smt_hash;
 
     const ERROR_VECTORS_NOT_SAME_LENGTH: u64 = 103;
     const BIT_RIGHT: bool = true;
     const BIT_LEFT: bool = false;
 
+    const ERROR_INVALID_PATH_BYTES_LENGTH: u64 = 101;
+    const ERROR_INVALID_PATH_BITS_LENGTH: u64 = 102;
+    const ERROR_INVALID_NODES_DATA_PACKAGE_LENGTH: u64 = 103;
+    //const NODE_DATA_LENGTH: u64 = 32;
+
     // Get the bit at an offset from the most significant bit.
     public fun get_bit_at_from_msb(data: &vector, position: u64): bool {
         let byte = (*vector::borrow(data, position / 8) as u64);
@@ -96,4 +102,41 @@ module starcoin_framework::smt_utils {
         };
         result
     }
+
+
+    public fun path_bits_to_bool_vector_from_msb(path: &vector): vector {
+        let path_len = vector::length(path);
+        assert!(path_len == smt_hash::size(), error::invalid_argument(ERROR_INVALID_PATH_BYTES_LENGTH));
+        let result_vec = bits_to_bool_vector_from_msb(path);
+        assert!(
+            vector::length(&result_vec) == smt_hash::size() * 8,// smt_tree_hasher::path_size_in_bits(),
+            error::invalid_state(ERROR_INVALID_PATH_BITS_LENGTH)
+        );
+        result_vec
+    }
+
+
+    // Split sibling nodes data from concatenated data.
+    // Due `Move` API call not yet support the parameter type such as vector>,
+    // so we concat all vectors into one vector.
+    public fun split_side_nodes_data(side_nodes_data: &vector): vector> {
+        let node_data_length = smt_hash::size();
+        let len = vector::length(side_nodes_data);
+        assert!(len % node_data_length == 0, error::invalid_state(ERROR_INVALID_NODES_DATA_PACKAGE_LENGTH));
+
+        if (len > 0) {
+            let result = vector::empty>();
+            let size = len / node_data_length;
+            let idx = 0;
+            while (idx < size) {
+                let start = idx * node_data_length;
+                let end = start + node_data_length;
+                vector::push_back(&mut result, sub_u8_vector(side_nodes_data, start, end));
+                idx = idx + 1;
+            };
+            result
+        } else {
+            vector::empty>()
+        }
+    }
 }
\ No newline at end of file

From d36a2799211b39536b1917142a99fed4715b1455 Mon Sep 17 00:00:00 2001
From: welbon <2261238+welbon@users.noreply.github.com>
Date: Mon, 6 Jan 2025 11:01:57 +0800
Subject: [PATCH 14/29] [asset-mapping] commmit For hash test

---
 Cargo.lock                                    |   2 +
 executor/Cargo.toml                           |   2 +
 executor/tests/executor_test.rs               |  90 ++++++++++-----
 .../starcoin-framework/doc/smt_hash.md        | 105 +-----------------
 .../starcoin-framework/doc/smt_utils.md       | 102 +++++++++++++++++
 5 files changed, 170 insertions(+), 131 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index f1312fa136..5ebba609ea 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -10601,12 +10601,14 @@ version = "2.0.1"
 dependencies = [
  "anyhow",
  "bcs-ext",
+ "forkable-jellyfish-merkle",
  "hex",
  "log 0.4.22",
  "move-transactional-test-runner",
  "once_cell",
  "serde",
  "serde_json",
+ "sha3",
  "starcoin-abi-resolver",
  "starcoin-abi-types",
  "starcoin-config",
diff --git a/executor/Cargo.toml b/executor/Cargo.toml
index 524ac0aab1..b236d90b43 100644
--- a/executor/Cargo.toml
+++ b/executor/Cargo.toml
@@ -34,6 +34,8 @@ stest = { workspace = true }
 tempfile = { workspace = true }
 test-helper = { workspace = true }
 move-transactional-test-runner = { workspace = true }
+forkable-jellyfish-merkle = { workspace = true }
+sha3 = { workspace = true }
 
 [features]
 default = []
diff --git a/executor/tests/executor_test.rs b/executor/tests/executor_test.rs
index a97ccc0269..d90be402d0 100644
--- a/executor/tests/executor_test.rs
+++ b/executor/tests/executor_test.rs
@@ -1,40 +1,48 @@
 // Copyright (c) The Starcoin Core Contributors
 // SPDX-License-Identifier: Apache-2.0
 
-
+use std::hash::Hash;
 use anyhow::anyhow;
 use anyhow::Result;
+use forkable_jellyfish_merkle::node_type::SparseMerkleLeafNode;
+use sha3::{Digest, Sha3_256};
+use starcoin_crypto::hash::PlainCryptoHash;
+use starcoin_crypto::HashValue;
 
 use starcoin_config::{BuiltinNetworkID, ChainNetwork};
 use starcoin_executor::validate_transaction;
 use starcoin_logger::prelude::*;
 use starcoin_state_api::{ChainStateReader, StateReaderExt};
 use starcoin_transaction_builder::{
-    build_batch_payload_same_amount, build_transfer_txn, DEFAULT_EXPIRATION_TIME,
-    DEFAULT_MAX_GAS_AMOUNT, encode_transfer_script_by_token_code, raw_peer_to_peer_txn,
-};
-use starcoin_types::{
-    account_config, block_metadata::BlockMetadata, transaction::Transaction,
-    transaction::TransactionPayload, transaction::TransactionStatus,
+    build_batch_payload_same_amount, build_transfer_txn, encode_transfer_script_by_token_code,
+    raw_peer_to_peer_txn, DEFAULT_EXPIRATION_TIME, DEFAULT_MAX_GAS_AMOUNT,
 };
-use starcoin_types::account::Account;
 use starcoin_types::account::peer_to_peer_txn;
+use starcoin_types::account::Account;
 use starcoin_types::account_config::G_STC_TOKEN_CODE;
 use starcoin_types::identifier::Identifier;
-use starcoin_types::language_storage::{CORE_CODE_ADDRESS, ModuleId, StructTag};
+use starcoin_types::language_storage::{ModuleId, StructTag, CORE_CODE_ADDRESS};
 use starcoin_types::transaction::{EntryFunction, RawUserTransaction, TransactionArgument};
+use starcoin_types::{
+    account_config, block_metadata::BlockMetadata, transaction::Transaction,
+    transaction::TransactionPayload, transaction::TransactionStatus,
+};
 use starcoin_vm_runtime::starcoin_vm::{chunk_block_transactions, StarcoinVM};
-use starcoin_vm_types::{on_chain_config::{ConsensusConfig, OnChainConfig}, transaction::Package, vm_status::StatusCode};
 use starcoin_vm_types::access_path::AccessPath;
-use starcoin_vm_types::account_config::AccountResource;
 use starcoin_vm_types::account_config::core_code_address;
 use starcoin_vm_types::account_config::genesis_address;
+use starcoin_vm_types::account_config::AccountResource;
 use starcoin_vm_types::genesis_config::ChainId;
 use starcoin_vm_types::state_store::state_key::StateKey;
 use starcoin_vm_types::state_store::state_value::StateValue;
 use starcoin_vm_types::state_store::TStateView;
 use starcoin_vm_types::token::stc::{stc_type_tag, STCUnit};
 use starcoin_vm_types::vm_status::KeptVMStatus;
+use starcoin_vm_types::{
+    on_chain_config::{ConsensusConfig, OnChainConfig},
+    transaction::Package,
+    vm_status::StatusCode,
+};
 use test_helper::executor::{
     account_execute, account_execute_should_success, association_execute_should_success,
     blockmeta_execute, build_raw_txn, current_block_number, prepare_customized_genesis,
@@ -85,7 +93,7 @@ fn test_vm_version() {
         vec![TransactionArgument::Address(genesis_address())],
         None,
     )
-        .unwrap();
+    .unwrap();
 
     let readed_version: u64 = bcs_ext::from_bytes(&value.pop().unwrap().1).unwrap();
     let version = {
@@ -113,7 +121,7 @@ fn test_flexidag_config_get() {
         vec![TransactionArgument::Address(genesis_address())],
         None,
     )
-        .unwrap();
+    .unwrap();
 
     let read_version: u64 = bcs_ext::from_bytes(&value.pop().unwrap().1).unwrap();
     let version = {
@@ -564,7 +572,7 @@ fn test_validate_txn_args() -> Result<()> {
         );
         account1.sign_txn(txn)
     }
-        .unwrap();
+    .unwrap();
     assert!(validate_transaction(&chain_state, txn, None).is_some());
 
     let txn = {
@@ -585,7 +593,7 @@ fn test_validate_txn_args() -> Result<()> {
         );
         account1.sign_txn(txn)
     }
-        .unwrap();
+    .unwrap();
     assert!(validate_transaction(&chain_state, txn, None).is_some());
 
     let txn = {
@@ -606,7 +614,7 @@ fn test_validate_txn_args() -> Result<()> {
         );
         account1.sign_txn(txn)
     }
-        .unwrap();
+    .unwrap();
     assert!(validate_transaction(&chain_state, txn, None).is_some());
     Ok(())
 }
@@ -1135,7 +1143,6 @@ fn test_chunk_block_transactions() -> Result<()> {
     Ok(())
 }
 
-
 #[test]
 fn test_get_chain_id_after_genesis_with_proof_verify() -> Result<()> {
     let (chain_state, _net) = prepare_genesis();
@@ -1149,23 +1156,52 @@ fn test_get_chain_id_after_genesis_with_proof_verify() -> Result<()> {
     let path_statekey = StateKey::resource(&CORE_CODE_ADDRESS, &chain_id_struct_tag)?;
 
     // Print 0x1 version resource
-    let resource_value =
-        bcs_ext::from_bytes::(
-            &chain_state.get_resource(CORE_CODE_ADDRESS, &chain_id_struct_tag,
-            )?
-        )?;
-    println!("get_vm_version_verify | path: {:?}, state_value : {:?}", chain_id_struct_tag, resource_value);
+    let resource_value = bcs_ext::from_bytes::(
+        &chain_state.get_resource(CORE_CODE_ADDRESS, &chain_id_struct_tag)?,
+    )?;
+    println!(
+        "test_get_chain_id_after_genesis_with_proof_verify | path: {:?}, state_value : {:?}",
+        chain_id_struct_tag, resource_value
+    );
     assert_eq!(resource_value.id(), 0xff, "not expect chain id");
 
-
     // Get proof and verify proof
     let mut state_proof = chain_state.get_with_proof(&path_statekey)?;
-    let version_path = AccessPath::resource_access_path(genesis_address(), chain_id_struct_tag);
-    state_proof.verify(chain_state.state_root(), version_path.clone())?;
+    let proof_path = AccessPath::resource_access_path(genesis_address(), chain_id_struct_tag);
+    state_proof.verify(chain_state.state_root(), proof_path.clone())?;
 
     state_proof.state.as_mut().unwrap()[0] = 0xFE;
     assert!(state_proof
-        .verify(chain_state.state_root(), version_path)
+        .verify(chain_state.state_root(), proof_path)
         .is_err());
     Ok(())
 }
+
+#[test]
+fn test_sha3_256_diffrent_with_crypto_macro() -> Result<()> {
+    let hash_1 = HashValue::from_hex_literal(
+        "0x4cc8bd9df94b37c233555d9a3bba0a712c3c709f047486d1e624b2bcd3b83266",
+    )?;
+    let hash_2 = HashValue::from_hex_literal(
+        "0x4f2b59b9af93b435e0a33b6ab7a8a90e471dba936be2bc2937629b7782b8ebd0",
+    )?;
+
+    let smt_hash = SparseMerkleLeafNode::new(hash_1, hash_2).crypto_hash();
+    println!(
+        "test_sha3_256_diffrent_with_crypto_macro | SparseMerkleLeafNode crypto hash: {:?}",
+        SparseMerkleLeafNode::new(hash_1, hash_2).crypto_hash()
+    );
+
+    let mut hash_vec = Vec::new();
+    hash_vec.append(&mut hash_1.to_vec());
+    hash_vec.append(&mut hash_2.to_vec());
+    let move_hash = HashValue::sha3_256_of(hash_vec.as_slice());
+    println!(
+        "test_sha3_256_diffrent_with_crypto_macro | sha3 crypto {:?}",
+        HashValue::sha3_256_of(hash_vec.as_slice()),
+    );
+
+    assert_eq!(move_hash, smt_hash, "Failed to get the same hash");
+
+    Ok(())
+}
diff --git a/vm/framework/starcoin-framework/doc/smt_hash.md b/vm/framework/starcoin-framework/doc/smt_hash.md
index 487a683661..f9a32f9a65 100644
--- a/vm/framework/starcoin-framework/doc/smt_hash.md
+++ b/vm/framework/starcoin-framework/doc/smt_hash.md
@@ -9,13 +9,9 @@
 -  [Function `size`](#0x1_smt_hash_size)
 -  [Function `hash`](#0x1_smt_hash_hash)
 -  [Function `size_zero_bytes`](#0x1_smt_hash_size_zero_bytes)
--  [Function `path_bits_to_bool_vector_from_msb`](#0x1_smt_hash_path_bits_to_bool_vector_from_msb)
--  [Function `split_side_nodes_data`](#0x1_smt_hash_split_side_nodes_data)
 
 
-
use 0x1::error;
-use 0x1::hash;
-use 0x1::smt_utils;
+
use 0x1::hash;
 
@@ -25,33 +21,6 @@ ## Constants - - - - -
const ERROR_INVALID_NODES_DATA_PACKAGE_LENGTH: u64 = 103;
-
- - - - - - - -
const ERROR_INVALID_PATH_BITS_LENGTH: u64 = 102;
-
- - - - - - - -
const ERROR_INVALID_PATH_BYTES_LENGTH: u64 = 101;
-
- - - @@ -131,78 +100,6 @@ -
- - - -## Function `path_bits_to_bool_vector_from_msb` - - - -
public fun path_bits_to_bool_vector_from_msb(path: &vector<u8>): vector<bool>
-
- - - -
-Implementation - - -
public fun path_bits_to_bool_vector_from_msb(path: &vector<u8>): vector<bool> {
-    let path_len = vector::length<u8>(path);
-    assert!(path_len == Self::size(), error::invalid_argument(ERROR_INVALID_PATH_BYTES_LENGTH));
-    let result_vec = smt_utils::bits_to_bool_vector_from_msb(path);
-    assert!(
-        vector::length<bool>(&result_vec) == Self::size() * 8,// smt_tree_hasher::path_size_in_bits(),
-        error::invalid_state(ERROR_INVALID_PATH_BITS_LENGTH)
-    );
-    result_vec
-}
-
- - - -
- - - -## Function `split_side_nodes_data` - - - -
public fun split_side_nodes_data(side_nodes_data: &vector<u8>): vector<vector<u8>>
-
- - - -
-Implementation - - -
public fun split_side_nodes_data(side_nodes_data: &vector<u8>): vector<vector<u8>> {
-    let node_data_length = Self::size();
-    let len = vector::length(side_nodes_data);
-    assert!(len % node_data_length == 0, error::invalid_state(ERROR_INVALID_NODES_DATA_PACKAGE_LENGTH));
-
-    if (len > 0) {
-        let result = vector::empty<vector<u8>>();
-        let size = len / node_data_length;
-        let idx = 0;
-        while (idx < size) {
-            let start = idx * node_data_length;
-            let end = start + node_data_length;
-            vector::push_back(&mut result, smt_utils::sub_u8_vector(side_nodes_data, start, end));
-            idx = idx + 1;
-        };
-        result
-    } else {
-        vector::empty<vector<u8>>()
-    }
-}
-
- - -
diff --git a/vm/framework/starcoin-framework/doc/smt_utils.md b/vm/framework/starcoin-framework/doc/smt_utils.md index b8bb7e1756..0b79e070c0 100644 --- a/vm/framework/starcoin-framework/doc/smt_utils.md +++ b/vm/framework/starcoin-framework/doc/smt_utils.md @@ -13,9 +13,12 @@ - [Function `concat_u8_vectors`](#0x1_smt_utils_concat_u8_vectors) - [Function `sub_u8_vector`](#0x1_smt_utils_sub_u8_vector) - [Function `sub_vector`](#0x1_smt_utils_sub_vector) +- [Function `path_bits_to_bool_vector_from_msb`](#0x1_smt_utils_path_bits_to_bool_vector_from_msb) +- [Function `split_side_nodes_data`](#0x1_smt_utils_split_side_nodes_data)
use 0x1::error;
+use 0x1::smt_hash;
 use 0x1::vector;
 
@@ -44,6 +47,33 @@ + + + + +
const ERROR_INVALID_NODES_DATA_PACKAGE_LENGTH: u64 = 103;
+
+ + + + + + + +
const ERROR_INVALID_PATH_BITS_LENGTH: u64 = 102;
+
+ + + + + + + +
const ERROR_INVALID_PATH_BYTES_LENGTH: u64 = 101;
+
+ + + @@ -280,6 +310,78 @@ + + + + +## Function `path_bits_to_bool_vector_from_msb` + + + +
public fun path_bits_to_bool_vector_from_msb(path: &vector<u8>): vector<bool>
+
+ + + +
+Implementation + + +
public fun path_bits_to_bool_vector_from_msb(path: &vector<u8>): vector<bool> {
+    let path_len = vector::length<u8>(path);
+    assert!(path_len == smt_hash::size(), error::invalid_argument(ERROR_INVALID_PATH_BYTES_LENGTH));
+    let result_vec = bits_to_bool_vector_from_msb(path);
+    assert!(
+        vector::length<bool>(&result_vec) == smt_hash::size() * 8,// smt_tree_hasher::path_size_in_bits(),
+        error::invalid_state(ERROR_INVALID_PATH_BITS_LENGTH)
+    );
+    result_vec
+}
+
+ + + +
+ + + +## Function `split_side_nodes_data` + + + +
public fun split_side_nodes_data(side_nodes_data: &vector<u8>): vector<vector<u8>>
+
+ + + +
+Implementation + + +
public fun split_side_nodes_data(side_nodes_data: &vector<u8>): vector<vector<u8>> {
+    let node_data_length = smt_hash::size();
+    let len = vector::length(side_nodes_data);
+    assert!(len % node_data_length == 0, error::invalid_state(ERROR_INVALID_NODES_DATA_PACKAGE_LENGTH));
+
+    if (len > 0) {
+        let result = vector::empty<vector<u8>>();
+        let size = len / node_data_length;
+        let idx = 0;
+        while (idx < size) {
+            let start = idx * node_data_length;
+            let end = start + node_data_length;
+            vector::push_back(&mut result, sub_u8_vector(side_nodes_data, start, end));
+            idx = idx + 1;
+        };
+        result
+    } else {
+        vector::empty<vector<u8>>()
+    }
+}
+
+ + +
From 2e1c55beb96ed2237353fffcaf03cf8468967090 Mon Sep 17 00:00:00 2001 From: nk_ysg Date: Mon, 6 Jan 2025 12:06:11 +0800 Subject: [PATCH 15/29] update test_sha3_256_diffrent_with_crypto_macro --- executor/tests/executor_test.rs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/executor/tests/executor_test.rs b/executor/tests/executor_test.rs index d90be402d0..9ec6aadb82 100644 --- a/executor/tests/executor_test.rs +++ b/executor/tests/executor_test.rs @@ -1,13 +1,13 @@ // Copyright (c) The Starcoin Core Contributors // SPDX-License-Identifier: Apache-2.0 -use std::hash::Hash; use anyhow::anyhow; use anyhow::Result; use forkable_jellyfish_merkle::node_type::SparseMerkleLeafNode; use sha3::{Digest, Sha3_256}; use starcoin_crypto::hash::PlainCryptoHash; use starcoin_crypto::HashValue; +use std::hash::Hash; use starcoin_config::{BuiltinNetworkID, ChainNetwork}; use starcoin_executor::validate_transaction; @@ -1186,19 +1186,25 @@ fn test_sha3_256_diffrent_with_crypto_macro() -> Result<()> { "0x4f2b59b9af93b435e0a33b6ab7a8a90e471dba936be2bc2937629b7782b8ebd0", )?; - let smt_hash = SparseMerkleLeafNode::new(hash_1, hash_2).crypto_hash(); + let leaf_node = SparseMerkleLeafNode::new(hash_1, hash_2); + + let smt_hash = leaf_node.crypto_hash(); println!( "test_sha3_256_diffrent_with_crypto_macro | SparseMerkleLeafNode crypto hash: {:?}", SparseMerkleLeafNode::new(hash_1, hash_2).crypto_hash() ); - let mut hash_vec = Vec::new(); - hash_vec.append(&mut hash_1.to_vec()); - hash_vec.append(&mut hash_2.to_vec()); - let move_hash = HashValue::sha3_256_of(hash_vec.as_slice()); + let ser = bcs_ext::to_bytes(&leaf_node)?; + const STARCOIN_HASH_PREFIX: &[u8] = b"STARCOIN::SparseMerkleLeafNode"; + let hash_vec = [ + HashValue::sha3_256_of(STARCOIN_HASH_PREFIX).as_slice(), + ser.as_slice(), + ] + .concat(); + let move_hash = HashValue::sha3_256_of(&hash_vec[..]); println!( "test_sha3_256_diffrent_with_crypto_macro | sha3 crypto {:?}", - HashValue::sha3_256_of(hash_vec.as_slice()), + move_hash, ); assert_eq!(move_hash, smt_hash, "Failed to get the same hash"); From fc5c593e828d011e9e1dd5b5b10e7639c98d64b9 Mon Sep 17 00:00:00 2001 From: welbon <2261238+welbon@users.noreply.github.com> Date: Mon, 6 Jan 2025 15:37:50 +0800 Subject: [PATCH 16/29] [asset-mapping] remove smt proof and add starcoin proof --- .../starcoin-framework/doc/overview.md | 7 +- .../starcoin-framework/doc/starcoin_proof.md | 374 ++++++++++++++++++ .../sources/smt/smt_hash.move | 17 - .../smt/smt_non_membership_proof_test.move | 138 ------- .../sources/smt/smt_proofs.move | 321 --------------- .../sources/smt/smt_tree_hasher.move | 139 ------- .../sources/smt/smt_utils.move | 142 ------- .../sources/starcoin_proof.move | 122 ++++++ 8 files changed, 499 insertions(+), 761 deletions(-) create mode 100644 vm/framework/starcoin-framework/doc/starcoin_proof.md delete mode 100644 vm/framework/starcoin-framework/sources/smt/smt_hash.move delete mode 100644 vm/framework/starcoin-framework/sources/smt/smt_non_membership_proof_test.move delete mode 100644 vm/framework/starcoin-framework/sources/smt/smt_proofs.move delete mode 100644 vm/framework/starcoin-framework/sources/smt/smt_tree_hasher.move delete mode 100644 vm/framework/starcoin-framework/sources/smt/smt_utils.move create mode 100644 vm/framework/starcoin-framework/sources/starcoin_proof.move diff --git a/vm/framework/starcoin-framework/doc/overview.md b/vm/framework/starcoin-framework/doc/overview.md index 15ad19191f..5234e035a9 100644 --- a/vm/framework/starcoin-framework/doc/overview.md +++ b/vm/framework/starcoin-framework/doc/overview.md @@ -56,12 +56,11 @@ This is the reference documentation of the Starcoin framework. - [`0x1::reserved_accounts_signer`](reserved_accounts_signer.md#0x1_reserved_accounts_signer) - [`0x1::resource_account`](resource_account.md#0x1_resource_account) - [`0x1::ring`](ring.md#0x1_ring) -- [`0x1::smt_hash`](smt_hash.md#0x1_smt_hash) -- [`0x1::smt_proofs`](smt_proofs.md#0x1_smt_proofs) -- [`0x1::smt_tree_hasher`](smt_tree_hasher.md#0x1_smt_tree_hasher) -- [`0x1::smt_utils`](smt_utils.md#0x1_smt_utils) - [`0x1::starcoin_account`](starcoin_account.md#0x1_starcoin_account) - [`0x1::starcoin_coin`](starcoin_coin.md#0x1_starcoin_coin) +- [`0x1::starcoin_proof_bit`](starcoin_proof.md#0x1_starcoin_proof_bit) +- [`0x1::starcoin_proof_structured_hash`](starcoin_proof.md#0x1_starcoin_proof_structured_hash) +- [`0x1::starcoin_proof_verifier`](starcoin_proof.md#0x1_starcoin_proof_verifier) - [`0x1::stc_block`](stc_block.md#0x1_stc_block) - [`0x1::stc_genesis`](stc_genesis.md#0x1_stc_genesis) - [`0x1::stc_language_version`](stc_language_version.md#0x1_stc_language_version) diff --git a/vm/framework/starcoin-framework/doc/starcoin_proof.md b/vm/framework/starcoin-framework/doc/starcoin_proof.md new file mode 100644 index 0000000000..baacea0d21 --- /dev/null +++ b/vm/framework/starcoin-framework/doc/starcoin_proof.md @@ -0,0 +1,374 @@ + + + +# Module `0x1::starcoin_proof_bit` + + + +- [Function `get_bit`](#0x1_starcoin_proof_bit_get_bit) + + +
+ + + + + +## Function `get_bit` + + + +
public fun get_bit(data: &vector<u8>, index: u64): bool
+
+ + + +
+Implementation + + +
public fun get_bit(data: &vector<u8>, index: u64): bool {
+    let pos = index / 8;
+    let bit = (7 - index % 8);
+    (*vector::borrow(data, pos) >> (bit as u8)) & 1u8 != 0
+}
+
+ + + +
+ + + + + +# Module `0x1::starcoin_proof_structured_hash` + + + +- [Constants](#@Constants_0) +- [Function `hash`](#0x1_starcoin_proof_structured_hash_hash) +- [Function `concat`](#0x1_starcoin_proof_structured_hash_concat) + + +
use 0x1::bcs;
+use 0x1::hash;
+use 0x1::vector;
+
+ + + + + +## Constants + + + + + + +
const STARCOIN_HASH_PREFIX: vector<u8> = [83, 84, 65, 82, 67, 79, 73, 78, 58, 58];
+
+ + + + + +## Function `hash` + + + +
public fun hash<MoveValue: store>(structure: vector<u8>, data: &MoveValue): vector<u8>
+
+ + + +
+Implementation + + +
public fun hash<MoveValue: store>(structure: vector<u8>, data: &MoveValue): vector<u8> {
+    let prefix_hash = hash::sha3_256(concat(&STARCOIN_HASH_PREFIX, structure));
+    let bcs_bytes = bcs::to_bytes(data);
+    hash::sha3_256(concat(&prefix_hash, bcs_bytes))
+}
+
+ + + +
+ + + +## Function `concat` + + + +
fun concat(v1: &vector<u8>, v2: vector<u8>): vector<u8>
+
+ + + +
+Implementation + + +
fun concat(v1: &vector<u8>, v2: vector<u8>): vector<u8> {
+    let data = *v1;
+    vector::append(&mut data, v2);
+    data
+}
+
+ + + +
+ + + + + +# Module `0x1::starcoin_proof_verifier` + + + +- [Resource `StarcoinMerkle`](#0x1_starcoin_proof_verifier_StarcoinMerkle) +- [Struct `Node`](#0x1_starcoin_proof_verifier_Node) +- [Constants](#@Constants_0) +- [Function `create`](#0x1_starcoin_proof_verifier_create) +- [Function `verify_on`](#0x1_starcoin_proof_verifier_verify_on) +- [Function `verify`](#0x1_starcoin_proof_verifier_verify) +- [Function `computer_root_hash`](#0x1_starcoin_proof_verifier_computer_root_hash) + + +
use 0x1::hash;
+use 0x1::starcoin_proof_bit;
+use 0x1::starcoin_proof_structured_hash;
+
+ + + + + +## Resource `StarcoinMerkle` + + + +
struct StarcoinMerkle has key
+
+ + + +
+Fields + + +
+
+merkle_root: vector<u8> +
+
+ +
+
+ + +
+ + + +## Struct `Node` + + + +
struct Node has drop, store
+
+ + + +
+Fields + + +
+
+hash1: vector<u8> +
+
+ +
+
+hash2: vector<u8> +
+
+ +
+
+ + +
+ + + +## Constants + + + + + + +
const HASH_LEN_IN_BIT: u64 = 256;
+
+ + + + + + + +
const SPARSE_MERKLE_INTERNAL_NODE: vector<u8> = [83, 112, 97, 114, 115, 101, 77, 101, 114, 107, 108, 101, 73, 110, 116, 101, 114, 110, 97, 108, 78, 111, 100, 101];
+
+ + + + + + + +
const SPARSE_MERKLE_LEAF_NODE: vector<u8> = [83, 112, 97, 114, 115, 101, 77, 101, 114, 107, 108, 101, 76, 101, 97, 102, 78, 111, 100, 101];
+
+ + + + + +## Function `create` + + + +
public fun create(signer: &signer, merkle_root: vector<u8>)
+
+ + + +
+Implementation + + +
public fun create(signer: &signer, merkle_root: vector<u8>) {
+    let s = StarcoinMerkle {
+        merkle_root
+    };
+    move_to(signer, s);
+}
+
+ + + +
+ + + +## Function `verify_on` + + + +
public fun verify_on(merkle_address: address, account_address: vector<u8>, account_state_root_hash: vector<u8>, proofs: vector<vector<u8>>): bool
+
+ + + +
+Implementation + + +
public fun verify_on(
+    merkle_address: address,
+    account_address: vector<u8>,
+    account_state_root_hash: vector<u8>,
+    proofs: vector<vector<u8>>
+): bool
+acquires StarcoinMerkle {
+    let merkle = borrow_global<StarcoinMerkle>(merkle_address);
+    verify(*&merkle.merkle_root, account_address, account_state_root_hash, proofs)
+}
+
+ + + +
+ + + +## Function `verify` + + + +
public fun verify(expected_root: vector<u8>, account_address: vector<u8>, account_state_root_hash: vector<u8>, proofs: vector<vector<u8>>): bool
+
+ + + +
+Implementation + + +
public fun verify(
+    expected_root: vector<u8>,
+    account_address: vector<u8>,
+    account_state_root_hash: vector<u8>,
+    proofs: vector<vector<u8>>
+): bool {
+    Self::computer_root_hash(hash::sha3_256(account_address), account_state_root_hash, proofs) == expected_root
+}
+
+ + + +
+ + + +## Function `computer_root_hash` + + + +
public fun computer_root_hash(element_key: vector<u8>, element_blob_hash: vector<u8>, proofs: vector<vector<u8>>): vector<u8>
+
+ + + +
+Implementation + + +
public fun computer_root_hash(
+    element_key: vector<u8>,
+    element_blob_hash: vector<u8>,
+    proofs: vector<vector<u8>>
+): vector<u8> {
+    let leaf_node = Node { hash1: element_key, hash2: element_blob_hash };
+    let current_hash = starcoin_proof_structured_hash::hash(SPARSE_MERKLE_LEAF_NODE, &leaf_node);
+    let i = 0;
+    let proof_length = vector::length(&proofs);
+    while (i < proof_length) {
+        let sibling = *vector::borrow(&proofs, i);
+        let bit = starcoin_proof_bit::get_bit(&element_key, proof_length - i - 1);
+        let internal_node = if (bit) {
+            Node { hash1: sibling, hash2: current_hash }
+        } else {
+            Node { hash1: current_hash, hash2: sibling }
+        };
+        current_hash = starcoin_proof_structured_hash::hash(SPARSE_MERKLE_INTERNAL_NODE, &internal_node);
+        i = i + 1;
+    };
+    current_hash
+}
+
+ + + +
+ + +[move-book]: https://starcoin.dev/move/book/SUMMARY diff --git a/vm/framework/starcoin-framework/sources/smt/smt_hash.move b/vm/framework/starcoin-framework/sources/smt/smt_hash.move deleted file mode 100644 index 19a61672be..0000000000 --- a/vm/framework/starcoin-framework/sources/smt/smt_hash.move +++ /dev/null @@ -1,17 +0,0 @@ -module starcoin_framework::smt_hash { - use starcoin_framework::hash; - - const SIZE_ZERO_BYTES: vector = x"0000000000000000000000000000000000000000000000000000000000000000"; - - public fun size(): u64 { - 32 - } - - public fun hash(data: &vector): vector { - hash::sha3_256(*data) - } - - public fun size_zero_bytes(): vector { - SIZE_ZERO_BYTES - } -} \ No newline at end of file diff --git a/vm/framework/starcoin-framework/sources/smt/smt_non_membership_proof_test.move b/vm/framework/starcoin-framework/sources/smt/smt_non_membership_proof_test.move deleted file mode 100644 index 10c20e27e7..0000000000 --- a/vm/framework/starcoin-framework/sources/smt/smt_non_membership_proof_test.move +++ /dev/null @@ -1,138 +0,0 @@ - -#[test_only] -module starcoin_framework::smt_non_membership_proof_test { - - use std::hash; - use std::vector; - - use starcoin_framework::smt_tree_hasher; - use starcoin_framework::smt_utils; - use starcoin_std::debug; - - const TEST_CHAIN_ID: u64 = 218; - - struct MerkleInternalNode has store, drop { - left_child: vector, - right_child: vector, - } - - #[test] - public fun test_iter_bits() { - let hash = x"1000000000000000000000000000000000000000000000000000000000000000"; - debug::print(&hash::sha3_256(*&hash)); - - let bit_vec = smt_utils::path_bits_to_bool_vector_from_msb(&hash); - debug::print(&bit_vec); - assert!(vector::length(&bit_vec) == 256, 1101); - - let sub_bits = vector::slice(&bit_vec, 252, 256); - debug::print(&sub_bits); - assert!(vector::length(&sub_bits) == 4, 1102); - } - - // #[test] - // public fun test_bit() { - // assert!(BitOperators::and(1, 2) == 0, 1103); - // assert!(BitOperators::and(1, 3) == 1, 1104); - // assert!(BitOperators::and(1, 16 >> 4) == 1, 1105); - // } - - #[test] - public fun test_print_fix_keyword() { - let k1 = x"01"; - let k2 = b"helloworld"; - debug::print(&k1); - debug::print(&k2); - debug::print(&hash::sha3_256(k1)); - debug::print(&hash::sha3_256(k2)); - } - - - #[test] - public fun test_get_bit() { - // Print origin hash - let origin_hash = x"1000000000000000000000000000000000000000000000000000000000000001"; - debug::print(&origin_hash); - - // Expect first byte is 'F', which binary is 11111111 - let first_byte = *vector::borrow(&origin_hash, 0); - debug::print(&first_byte); - - // let bit = BitOperators::and(BitOperators::rshift((first_byte as u64), 4), (1 as u64)); - let bit = (first_byte >> 4 & 1); - debug::print(&bit); - assert!((first_byte >> 4 & 1) == 1, 1106); - - let bit_hash = vector::empty(); - let i = 0; - while (i < 256) { - vector::push_back(&mut bit_hash, smt_utils::get_bit_at_from_msb(&origin_hash, i)); - i = i + 1; - }; - debug::print(&bit_hash); - - // Test skip bit - vector::reverse(&mut bit_hash); - let skip_bits = vector::slice(&bit_hash, 252, 256); - debug::print(&skip_bits); - - let skip_bits_1 = vector::slice(&bit_hash, 0, 1); - debug::print(&skip_bits_1); - } - - #[test] - public fun test_fixed_leaf_node_data() { - let data = x"0076d3bc41c9f588f7fcd0d5bf4718f8f84b1c41b20882703100b9eb9413807c012767f15c8af2f2c7225d5273fdd683edc714110a987d1054697c348aed4e6cc7"; - let expect = x"da3c17cfd8be129f09b61272f8afcf42bf5b77cf7e405f5aa20c30684a205488"; - - let crypto_hash = smt_tree_hasher::digest_leaf_data(&data); - - debug::print(&crypto_hash); - debug::print(&expect); - assert!(crypto_hash == expect, 1107); - } - - #[test] - public fun test_fixed_internal_node_data() { - let left = x"24a7e02bc5b39e8a4b7d2396d2e637632d0938944d16d571f0485168461f46eb"; - let right = x"42bfc776a76b35ca641ee761a5f4bc6ebf2d4e2441c517f8a8e085dec3ca443c"; - let expect = x"060aec78413605e993f9338255b661ac794a68729ffa50022aca72b01586a306"; - - let (crypto_hash, _) = smt_tree_hasher::digest_node(&left, &right); - - debug::print(&crypto_hash); - debug::print(&expect); - - assert!(crypto_hash == expect, 1108); - } - - #[test] - fun test_common_prefix_bits_len() { - let bits1 = smt_utils::path_bits_to_bool_vector_from_msb( - &x"0000000000000000000000000000000000000000000000000000000000000000" - ); - let bits2 = smt_utils::path_bits_to_bool_vector_from_msb( - &x"1000000000000000000000000000000000000000000000000000000000000000" - ); - debug::print(&bits1); - debug::print(&bits2); - let len = smt_utils::count_vector_common_prefix(&bits1, &bits2); - debug::print(&len); - assert!(len == 3, 1109); - } - - #[test] - public fun test_fixed_split_leaf_node_data() { - let data = x"0076d3bc41c9f588f7fcd0d5bf4718f8f84b1c41b20882703100b9eb9413807c012767f15c8af2f2c7225d5273fdd683edc714110a987d1054697c348aed4e6cc7"; - let (leaf_node_path, leaf_node_value) = smt_tree_hasher::parse_leaf(&data); - //assert!(prefix == x"00", 1110); - - debug::print(&leaf_node_path); - debug::print(&x"76d3bc41c9f588f7fcd0d5bf4718f8f84b1c41b20882703100b9eb9413807c01"); - assert!(leaf_node_path == x"76d3bc41c9f588f7fcd0d5bf4718f8f84b1c41b20882703100b9eb9413807c01", 1106); - - debug::print(&leaf_node_value); - debug::print(&x"2767f15c8af2f2c7225d5273fdd683edc714110a987d1054697c348aed4e6cc7"); - assert!(leaf_node_value == x"2767f15c8af2f2c7225d5273fdd683edc714110a987d1054697c348aed4e6cc7", 1107); - } -} \ No newline at end of file diff --git a/vm/framework/starcoin-framework/sources/smt/smt_proofs.move b/vm/framework/starcoin-framework/sources/smt/smt_proofs.move deleted file mode 100644 index d95ab211c6..0000000000 --- a/vm/framework/starcoin-framework/sources/smt/smt_proofs.move +++ /dev/null @@ -1,321 +0,0 @@ -// Sparse Merkle Tree proof for non-membership, -// reference Starcoin project's source file located at: "commons/forkable-jellyfish-merkle/src/proof.rs" -// -// Computes the hash of internal node according to [`JellyfishTree`](crate::JellyfishTree) -// data structure in the logical view. `start` and `nibble_height` determine a subtree whose -// root hash we want to get. For an internal node with 16 children at the bottom level, we compute -// the root hash of it as if a full binary Merkle tree with 16 leaves as below: -// -// ```text -// 4 -> +------ root hash ------+ -// | | -// 3 -> +---- # ----+ +---- # ----+ -// | | | | -// 2 -> # # # # -// / \ / \ / \ / \ -// 1 -> # # # # # # # # -// / \ / \ / \ / \ / \ / \ / \ / \ -// 0 -> 0 1 2 3 4 5 6 7 8 9 A B C D E F -// ^ -// height -// ``` -// -// As illustrated above, at nibble height 0, `0..F` in hex denote 16 chidren hashes. Each `#` -// means the hash of its two direct children, which will be used to generate the hash of its -// parent with the hash of its sibling. Finally, we can get the hash of this internal node. -// -// However, if an internal node doesn't have all 16 chidren exist at height 0 but just a few of -// them, we have a modified hashing rule on top of what is stated above: -// 1. From top to bottom, a node will be replaced by a leaf child if the subtree rooted at this -// node has only one child at height 0 and it is a leaf child. -// 2. From top to bottom, a node will be replaced by the placeholder node if the subtree rooted at -// this node doesn't have any child at height 0. For example, if an internal node has 3 leaf -// children at index 0, 3, 8, respectively, and 1 internal node at index C, then the computation -// graph will be like: -// -// ```text -// 4 -> +------ root hash ------+ -// | | -// 3 -> +---- # ----+ +---- # ----+ -// | | | | -// 2 -> # @ 8 # -// / \ / \ -// 1 -> 0 3 # @ -// / \ -// 0 -> C @ -// ^ -// height -// Note: @ denotes placeholder hash. -// ``` -module starcoin_framework::smt_proofs { - - use std::error; - use std::string; - use std::vector; - - use starcoin_framework::smt_tree_hasher; - use starcoin_framework::smt_utils; - use starcoin_std::debug; - - #[test_only] - use starcoin_framework::smt_hash; - - const ERROR_KEY_ALREADY_EXISTS_IN_PROOF: u64 = 101; - const ERROR_COUNT_COMMON_PREFIX: u64 = 102; - const BIT_RIGHT: bool = true; - - public fun verify_non_membership_proof_by_key( - root_hash: &vector, - non_membership_leaf_data: &vector, - side_nodes: &vector>, - key: &vector - ): bool { - let leaf_path = smt_tree_hasher::digest(key); - verify_non_membership_proof_by_leaf_path(root_hash, non_membership_leaf_data, side_nodes, &leaf_path) - } - - // Verify non-membership proof by leaf path. - // Return true if leaf path(key) is not in the tree. - public fun verify_non_membership_proof_by_leaf_path( - root_hash: &vector, - non_membership_leaf_data: &vector, - side_nodes: &vector>, - leaf_path: &vector - ): bool { - let non_membership_leaf_hash = if (vector::length(non_membership_leaf_data) > 0) { - let (non_membership_leaf_path, _) = smt_tree_hasher::parse_leaf(non_membership_leaf_data); - assert!(*leaf_path != *&non_membership_leaf_path, error::invalid_state(ERROR_KEY_ALREADY_EXISTS_IN_PROOF)); - assert!( - (smt_utils::count_common_prefix(leaf_path, &non_membership_leaf_path) >= vector::length(side_nodes)), - ERROR_COUNT_COMMON_PREFIX - ); - smt_tree_hasher::digest_leaf_data(non_membership_leaf_data) - } else { - smt_tree_hasher::placeholder() - }; - compute_root_hash(leaf_path, &non_membership_leaf_hash, side_nodes) == *root_hash - } - - public fun verify_membership_proof_by_key_value( - root_hash: &vector, - side_nodes: &vector>, - key: &vector, - value: &vector, - is_raw_value: bool - ): bool { - let leaf_path = smt_tree_hasher::digest(key); - let leaf_value_hash = if (is_raw_value) { - &smt_tree_hasher::digest(value) - } else { - value - }; - verify_membership_proof(root_hash, side_nodes, &leaf_path, leaf_value_hash) - } - - public fun verify_membership_proof( - expect_root_hash: &vector, - sibling_nodes: &vector>, - leaf_path: &vector, - leaf_value_hash: &vector - ): bool { - debug::print( - &string::utf8(b"smt_proofs::verify_membership_proof | entered, leaf path & leaf value hash & sibling_nodes") - ); - debug::print(leaf_path); - debug::print(leaf_value_hash); - debug::print(sibling_nodes); - - let (leaf_hash, leaf_value) = smt_tree_hasher::digest_leaf(leaf_path, leaf_value_hash); - debug::print( - &string::utf8( - b"smt_proofs::verify_membership_proof | after smt_tree_hasher::digest_leaf, leaf_path & leaf_value: " - ) - ); - debug::print(&leaf_hash); - debug::print(&leaf_value); - - let ret_hash = compute_root_hash(leaf_path, &leaf_hash, sibling_nodes); - debug::print( - &string::utf8( - b"smt_proofs::verify_membership_proof | after Self::compute_root_hash, ret_hash & expect_root_hash: " - ) - ); - debug::print(&ret_hash); - debug::print(expect_root_hash); - ret_hash == *expect_root_hash - } - - public fun compute_root_hash_by_leaf( - leaf_path: &vector, - leaf_value_hash: &vector, - side_nodes: &vector> - ): vector { - let (leaf_hash, _) = smt_tree_hasher::digest_leaf(leaf_path, leaf_value_hash); - compute_root_hash(leaf_path, &leaf_hash, side_nodes) - } - - // Compute root hash after a new leaf included. - public fun compute_root_hash_new_leaf_included( - leaf_path: &vector, - leaf_value_hash: &vector, - non_membership_leaf_data: &vector, - side_nodes: &vector> - ): vector { - let (new_side_nodes, leaf_node_hash) = create_membership_side_nodes( - leaf_path, - leaf_value_hash, - non_membership_leaf_data, - side_nodes - ); - - compute_root_hash(leaf_path, &leaf_node_hash, &new_side_nodes) - } - - // Create membership proof from non-membership proof. - // Return root hash, side nodes. - public fun create_membership_proof( - leaf_path: &vector, - leaf_value_hash: &vector, - non_membership_leaf_data: &vector, - side_nodes: &vector> - ): (vector, vector>) { - let (new_side_nodes, leaf_node_hash) = create_membership_side_nodes( - leaf_path, - leaf_value_hash, - non_membership_leaf_data, - side_nodes - ); - let new_root_hash = compute_root_hash(leaf_path, &leaf_node_hash, &new_side_nodes); - (new_root_hash, new_side_nodes) - } - - // Create membership proof side nodes from non-membership proof. - fun create_membership_side_nodes( - leaf_path: &vector, - leaf_value_hash: &vector, - non_membership_leaf_data: &vector, - side_nodes: &vector> - ): (vector>, vector) { - let side_nodes_len = vector::length>(side_nodes); - let (new_leaf_hash, _) = smt_tree_hasher::digest_leaf(leaf_path, leaf_value_hash); - let new_side_nodes = if (vector::length(non_membership_leaf_data) > 0) { - let (non_membership_leaf_path, _) = smt_tree_hasher::parse_leaf(non_membership_leaf_data); - assert!(*leaf_path != *&non_membership_leaf_path, error::invalid_state(ERROR_KEY_ALREADY_EXISTS_IN_PROOF)); - - let common_prefix_count = smt_utils::count_common_prefix(leaf_path, &non_membership_leaf_path); - let old_leaf_hash = smt_tree_hasher::digest_leaf_data(non_membership_leaf_data); - let new_side_nodes = vector::empty>(); - - vector::push_back(&mut new_side_nodes, old_leaf_hash); - if (common_prefix_count > side_nodes_len) { - let place_holder_len = (common_prefix_count - side_nodes_len); - // Put placeholders - let idx = 0; - while (idx < place_holder_len) { - vector::push_back(&mut new_side_nodes, smt_tree_hasher::placeholder()); - idx = idx + 1; - }; - }; - new_side_nodes - } else { - vector::empty>() - }; - - // Push old siblings into the new siblings array - let idx = 0; - while (idx < side_nodes_len) { - vector::push_back(&mut new_side_nodes, *vector::borrow(side_nodes, idx)); - idx = idx + 1; - }; - (new_side_nodes, new_leaf_hash) - } - - // Compute root hash. - // The parameter `node_hash` is leaf or internal node hash. - public fun compute_root_hash( - path: &vector, - node_hash: &vector, - side_nodes: &vector> - ): vector { - let side_nodes_len = vector::length>(side_nodes); - - let i = 0; - let current_hash = *node_hash; - while (i < side_nodes_len) { - let bit = smt_utils::get_bit_at_from_msb(path, side_nodes_len - i - 1); - let sibling_hash = vector::borrow>(side_nodes, i); - if (bit == BIT_RIGHT) { - (current_hash, _) = smt_tree_hasher::digest_node(sibling_hash, ¤t_hash); - } else { - // left - (current_hash, _) = smt_tree_hasher::digest_node(¤t_hash, sibling_hash); - }; - i = i + 1; - }; - current_hash - } - - - // This function mainly verifies that the value of the 0x1::chain_id::ChainId structure is 0xff (i.e. 255) - // after the genesis of the test network is started. - // - // The test location of the rust code function name is `test_get_chain_id_after_genesis_with_proof_verify` - // - // expected_root_hash: HashValue(0xf65860f575bf2a198c069adb4e7872037e3a329b63ef617e40afa39b87b067c8), - // element_key: HashValue(0x4cc8bd9df94b37c233555d9a3bba0a712c3c709f047486d1e624b2bcd3b83266), - // element_blob: Some(Blob { Raw: 0xff }), - // siblings: [ - // HashValue(0xcfb1462d4fc72f736eab2a56b2bf72ca6ad1c4e8c79557046a8b0adce047f007), - // HashValue(0x5350415253455f4d45524b4c455f504c414345484f4c4445525f484153480000), - // HashValue(0x5ca9febe74c7fde3fdcf2bd464de6d8899a0a13d464893aada2714c6fa774f9d), - // HashValue(0x1519a398fed69687cabf51adf831f0ee1650aaf79775d00135fc70f55a73e151), - // HashValue(0x50ce5c38983ba2eb196acd44e0aaedf040b1437ad1106e05ca452d7e27e4e03f), - // HashValue(0x55ed28435637a061a6dd9e20b72849199cd36184570f976b7e306a27bebf2fdf), - // HashValue(0x0dc23e31614798a6f67659b0b808b3eadc3b13a2a7bc03580a9e3004e45c2e6c), - // HashValue(0x83bed048bc0bc452c98cb0e9f1cc0f691919eaf756864fc44940c2d1e01da92a) - // ] - - #[test] - public fun test_verify_membership_proof() { - let siblings = vector::empty>(); - vector::push_back(&mut siblings, x"cfb1462d4fc72f736eab2a56b2bf72ca6ad1c4e8c79557046a8b0adce047f007"); - vector::push_back(&mut siblings, x"5350415253455f4d45524b4c455f504c414345484f4c4445525f484153480000"); - vector::push_back(&mut siblings, x"5ca9febe74c7fde3fdcf2bd464de6d8899a0a13d464893aada2714c6fa774f9d"); - vector::push_back(&mut siblings, x"1519a398fed69687cabf51adf831f0ee1650aaf79775d00135fc70f55a73e151"); - vector::push_back(&mut siblings, x"50ce5c38983ba2eb196acd44e0aaedf040b1437ad1106e05ca452d7e27e4e03f"); - vector::push_back(&mut siblings, x"55ed28435637a061a6dd9e20b72849199cd36184570f976b7e306a27bebf2fdf"); - vector::push_back(&mut siblings, x"0dc23e31614798a6f67659b0b808b3eadc3b13a2a7bc03580a9e3004e45c2e6c"); - vector::push_back(&mut siblings, x"83bed048bc0bc452c98cb0e9f1cc0f691919eaf756864fc44940c2d1e01da92a"); - - let expect_root_hash = x"f65860f575bf2a198c069adb4e7872037e3a329b63ef617e40afa39b87b067c8"; - let element_key = x"4cc8bd9df94b37c233555d9a3bba0a712c3c709f047486d1e624b2bcd3b83266"; - assert!(Self::verify_membership_proof( - &expect_root_hash, - &siblings, - &element_key, - &x"ff", - ), 1110); - - // let node_data = vector::empty(); - // vector::append(&mut node_data, element_key); - // - // let value_hash = smt_hash::hash(&x"00000000000000ff"); - // debug::print(&string::utf8(b"test_verify_membership_proof | value_hash ")); - // debug::print(&value_hash); - // vector::append(&mut node_data, value_hash); - // - // let node_hash = smt_hash::hash(&node_data); - // debug::print(&string::utf8(b"test_verify_membership_proof | current_hash ")); - // debug::print(&node_hash); - // - // let actual_root = Self::compute_root_hash( - // &element_key, - // //&node_hash, - // &x"796c380bdad1231f930708197d9d4ddffe61e8bf2b3d817a0efe21230b11ae2e", - // &siblings, - // ); - // assert!(actual_root == expect_root_hash, 1110); - - } -} - diff --git a/vm/framework/starcoin-framework/sources/smt/smt_tree_hasher.move b/vm/framework/starcoin-framework/sources/smt/smt_tree_hasher.move deleted file mode 100644 index 49501591d5..0000000000 --- a/vm/framework/starcoin-framework/sources/smt/smt_tree_hasher.move +++ /dev/null @@ -1,139 +0,0 @@ -module starcoin_framework::smt_tree_hasher { - - use std::error; - use std::vector; - - use starcoin_framework::smt_hash; - use starcoin_framework::smt_utils; - - // sparse merkle tree leaf(node) prefix. - const LEAF_PREFIX: vector = x"00"; - // sparse merkle tree (internal) node prefix. - const NODE_PREFIX: vector = x"01"; - - // Leaf node data include: prefix + leaf_path + leaf_value_hash - //const LEAF_DATA_LENGTH: u64 = 65; - //const NODE_LEFT_RIGHT_DATA_LENGTH: u64 = 32; - //const LEAF_PATH_LENGTH: u64 = 32; - - const ERROR_INVALID_LEAF_DATA: u64 = 102; - const ERROR_INVALID_NODE_DATA: u64 = 103; - const ERROR_INVALID_LEAF_DATA_LENGTH: u64 = 104; - const ERROR_INVALID_NODE_DATA_LENGTH: u64 = 105; - - // Parse leaf data. - // Return values: - // leaf node path. - // leaf node value. - public fun parse_leaf(data: &vector): (vector, vector) { - let data_len = vector::length(data); - - let prefix_len = vector::length(&LEAF_PREFIX); - assert!(data_len >= prefix_len + path_size(), error::invalid_argument(ERROR_INVALID_LEAF_DATA)); - assert!(smt_utils::sub_u8_vector(data, 0, prefix_len) == LEAF_PREFIX, error::invalid_argument(ERROR_INVALID_LEAF_DATA)); - - let start = 0; - let end = prefix_len; - _ = start;//let prefix = smt_utils::sub_u8_vector(data, start, end); - - start = end; - end = start + path_size(); - let leaf_node_path = smt_utils::sub_u8_vector(data, start, end); - - start = end; - end = vector::length(data); - let leaf_node_value = smt_utils::sub_u8_vector(data, start, end); - (leaf_node_path, leaf_node_value) - } - - // #[test] - // #[expected_failure] - // public fun test_parse_leaf_1() { - // let data = x"0189bd5770d361dfa0c06a8c1cf4d89ef194456ab5cf8fc55a9f6744aff0bfef812767f15c8af2f2c7225d5273fdd683edc714110a987d1054697c348aed4e6cc7"; - // let (leaf_node_path, leaf_node_value) = parse_leaf(&data); - // assert!(leaf_node_path == x"89bd5770d361dfa0c06a8c1cf4d89ef194456ab5cf8fc55a9f6744aff0bfef81", 101); - // assert!(leaf_node_value == x"2767f15c8af2f2c7225d5273fdd683edc714110a987d1054697c348aed4e6cc7", 101); - // } - // - // #[test] - // public fun test_parse_leaf_2() { - // let data = x"0089bd5770d361dfa0c06a8c1cf4d89ef194456ab5cf8fc55a9f6744aff0bfef812767f15c8af2f2c7225d5273fdd683edc714110a987d1054697c348aed4e6cc7"; - // let (leaf_node_path, leaf_node_value) = parse_leaf(&data); - // assert!(leaf_node_path == x"89bd5770d361dfa0c06a8c1cf4d89ef194456ab5cf8fc55a9f6744aff0bfef81", 101); - // assert!(leaf_node_value == x"2767f15c8af2f2c7225d5273fdd683edc714110a987d1054697c348aed4e6cc7", 101); - // } - - public fun parse_node(data: &vector): (vector, vector) { - let data_len = vector::length(data); - let prefix_len = vector::length(&NODE_PREFIX); - assert!(data_len == prefix_len + path_size() * 2, error::invalid_argument(ERROR_INVALID_NODE_DATA)); - assert!(smt_utils::sub_u8_vector(data, 0, prefix_len) == NODE_PREFIX, error::invalid_argument(ERROR_INVALID_NODE_DATA)); - - let start = 0; - let end = prefix_len; - _ = start;//let prefix = smt_utils::sub_u8_vector(data, start, end); - - start = end; - end = start + path_size(); - let left_data = smt_utils::sub_u8_vector(data, start, end); - - start = end; - end = vector::length(data); - let right_data = smt_utils::sub_u8_vector(data, start, end); - (left_data, right_data) - } - - public fun digest_leaf(path: &vector, leaf_value: &vector): (vector, vector) { - let value = LEAF_PREFIX; - value = smt_utils::concat_u8_vectors(&value, *path); - value = smt_utils::concat_u8_vectors(&value, *leaf_value); - (smt_hash::hash(&value), value) - } - - public fun create_leaf_data(path: &vector, leaf_value: &vector): vector { - let value = LEAF_PREFIX; - value = smt_utils::concat_u8_vectors(&value, *path); - value = smt_utils::concat_u8_vectors(&value, *leaf_value); - value - } - - // Digest leaf data. The parameter `data` includes leaf key and value. - public fun digest_leaf_data(data: &vector): vector { - let data_len = vector::length(data); - let prefix_len = vector::length(&LEAF_PREFIX); - assert!(data_len >= prefix_len + path_size(), error::invalid_state(ERROR_INVALID_LEAF_DATA_LENGTH)); - assert!(smt_utils::sub_u8_vector(data, 0, prefix_len) == LEAF_PREFIX, error::invalid_argument(ERROR_INVALID_LEAF_DATA)); - smt_hash::hash(data) - } - - public fun digest_node(left_data: &vector, right_data: &vector): (vector, vector) { - let node_left_right_data_length = smt_hash::size(); - assert!(vector::length(left_data) == node_left_right_data_length, error::invalid_state(ERROR_INVALID_NODE_DATA_LENGTH)); - assert!(vector::length(right_data) == node_left_right_data_length, error::invalid_state(ERROR_INVALID_NODE_DATA_LENGTH)); - - let value = NODE_PREFIX; - value = smt_utils::concat_u8_vectors(&value, *left_data); - value = smt_utils::concat_u8_vectors(&value, *right_data); - (smt_hash::hash(&value), value) - } - - public fun path(key: &vector): vector { - digest(key) - } - - public fun digest(data: &vector): vector { - smt_hash::hash(data) - } - - public fun path_size(): u64 { - smt_hash::size() - } - - public fun path_size_in_bits(): u64 { - smt_hash::size() * 8 - } - - public fun placeholder(): vector { - smt_hash::size_zero_bytes() - } -} \ No newline at end of file diff --git a/vm/framework/starcoin-framework/sources/smt/smt_utils.move b/vm/framework/starcoin-framework/sources/smt/smt_utils.move deleted file mode 100644 index 2b69a28fcb..0000000000 --- a/vm/framework/starcoin-framework/sources/smt/smt_utils.move +++ /dev/null @@ -1,142 +0,0 @@ -module starcoin_framework::smt_utils { - - use std::error; - use std::vector; - use starcoin_framework::smt_hash; - - const ERROR_VECTORS_NOT_SAME_LENGTH: u64 = 103; - const BIT_RIGHT: bool = true; - const BIT_LEFT: bool = false; - - const ERROR_INVALID_PATH_BYTES_LENGTH: u64 = 101; - const ERROR_INVALID_PATH_BITS_LENGTH: u64 = 102; - const ERROR_INVALID_NODES_DATA_PACKAGE_LENGTH: u64 = 103; - //const NODE_DATA_LENGTH: u64 = 32; - - // Get the bit at an offset from the most significant bit. - public fun get_bit_at_from_msb(data: &vector, position: u64): bool { - let byte = (*vector::borrow(data, position / 8) as u64); - // let bit = BitOperators::rshift(byte, ((7 - (position % 8)) as u8)); - let bit = byte >> ((7 - (position % 8)) as u8); - if (bit & 1 != 0) { - BIT_RIGHT - } else { - BIT_LEFT - } - } - - public fun count_common_prefix(data1: &vector, data2: &vector): u64 { - let count = 0; - let i = 0; - while (i < vector::length(data1) * 8) { - if (get_bit_at_from_msb(data1, i) == get_bit_at_from_msb(data2, i)) { - count = count + 1; - } else { - break - }; - i = i + 1; - }; - count - } - - public fun count_vector_common_prefix( - vec1: &vector, - vec2: &vector - ): u64 { - let vec_len = vector::length(vec1); - assert!(vec_len == vector::length(vec2), error::invalid_state(ERROR_VECTORS_NOT_SAME_LENGTH)); - let idx = 0; - while (idx < vec_len) { - if (*vector::borrow(vec1, idx) != *vector::borrow(vec2, idx)) { - break - }; - idx = idx + 1; - }; - idx - } - - public fun bits_to_bool_vector_from_msb(data: &vector): vector { - let i = 0; - let vec = vector::empty(); - while (i < vector::length(data) * 8) { - vector::push_back(&mut vec, get_bit_at_from_msb(data, i)); - i = i + 1; - }; - vec - } - - public fun concat_u8_vectors(v1: &vector, v2: vector): vector { - let data = *v1; - vector::append(&mut data, v2); - data - } - - public fun sub_u8_vector(vec: &vector, start: u64, end: u64): vector { - let i = start; - let result = vector::empty(); - let data_len = vector::length(vec); - let actual_end = if (end < data_len) { - end - } else { - data_len - }; - while (i < actual_end) { - vector::push_back(&mut result, *vector::borrow(vec, i)); - i = i + 1; - }; - result - } - - public fun sub_vector(vec: &vector, start: u64, end: u64): vector { - let i = start; - let result = vector::empty(); - let data_len = vector::length(vec); - let actual_end = if (end < data_len) { - end - } else { - data_len - }; - while (i < actual_end) { - vector::push_back(&mut result, *vector::borrow(vec, i)); - i = i + 1; - }; - result - } - - - public fun path_bits_to_bool_vector_from_msb(path: &vector): vector { - let path_len = vector::length(path); - assert!(path_len == smt_hash::size(), error::invalid_argument(ERROR_INVALID_PATH_BYTES_LENGTH)); - let result_vec = bits_to_bool_vector_from_msb(path); - assert!( - vector::length(&result_vec) == smt_hash::size() * 8,// smt_tree_hasher::path_size_in_bits(), - error::invalid_state(ERROR_INVALID_PATH_BITS_LENGTH) - ); - result_vec - } - - - // Split sibling nodes data from concatenated data. - // Due `Move` API call not yet support the parameter type such as vector>, - // so we concat all vectors into one vector. - public fun split_side_nodes_data(side_nodes_data: &vector): vector> { - let node_data_length = smt_hash::size(); - let len = vector::length(side_nodes_data); - assert!(len % node_data_length == 0, error::invalid_state(ERROR_INVALID_NODES_DATA_PACKAGE_LENGTH)); - - if (len > 0) { - let result = vector::empty>(); - let size = len / node_data_length; - let idx = 0; - while (idx < size) { - let start = idx * node_data_length; - let end = start + node_data_length; - vector::push_back(&mut result, sub_u8_vector(side_nodes_data, start, end)); - idx = idx + 1; - }; - result - } else { - vector::empty>() - } - } -} \ No newline at end of file diff --git a/vm/framework/starcoin-framework/sources/starcoin_proof.move b/vm/framework/starcoin-framework/sources/starcoin_proof.move new file mode 100644 index 0000000000..77cb586daf --- /dev/null +++ b/vm/framework/starcoin-framework/sources/starcoin_proof.move @@ -0,0 +1,122 @@ +module starcoin_framework::starcoin_proof_verifier { + use std::hash; + use std::vector; + + use starcoin_framework::starcoin_proof_bit; + use starcoin_framework::starcoin_proof_structured_hash; + + struct StarcoinMerkle has key { + merkle_root: vector, + } + + struct Node has store, drop { + hash1: vector, + hash2: vector, + } + + const HASH_LEN_IN_BIT: u64 = 32 * 8; + const SPARSE_MERKLE_LEAF_NODE: vector = b"SparseMerkleLeafNode"; + const SPARSE_MERKLE_INTERNAL_NODE: vector = b"SparseMerkleInternalNode"; + + public fun create(signer: &signer, merkle_root: vector) { + let s = StarcoinMerkle { + merkle_root + }; + move_to(signer, s); + } + + public fun verify_on( + merkle_address: address, + account_address: vector, + account_state_root_hash: vector, + proofs: vector> + ): bool + acquires StarcoinMerkle { + let merkle = borrow_global(merkle_address); + verify(*&merkle.merkle_root, account_address, account_state_root_hash, proofs) + } + + public fun verify( + expected_root: vector, + account_address: vector, + account_state_root_hash: vector, + proofs: vector> + ): bool { + Self::computer_root_hash(hash::sha3_256(account_address), account_state_root_hash, proofs) == expected_root + } + + public fun computer_root_hash( + element_key: vector, + element_blob_hash: vector, + proofs: vector> + ): vector { + let leaf_node = Node { hash1: element_key, hash2: element_blob_hash }; + let current_hash = starcoin_proof_structured_hash::hash(SPARSE_MERKLE_LEAF_NODE, &leaf_node); + let i = 0; + let proof_length = vector::length(&proofs); + while (i < proof_length) { + let sibling = *vector::borrow(&proofs, i); + let bit = starcoin_proof_bit::get_bit(&element_key, proof_length - i - 1); + let internal_node = if (bit) { + Node { hash1: sibling, hash2: current_hash } + } else { + Node { hash1: current_hash, hash2: sibling } + }; + current_hash = starcoin_proof_structured_hash::hash(SPARSE_MERKLE_INTERNAL_NODE, &internal_node); + i = i + 1; + }; + current_hash + } + + #[test] + public fun test_starcoin_proof_verify_is_expect_root() { + let siblings = vector::empty>(); + vector::push_back(&mut siblings, x"cfb1462d4fc72f736eab2a56b2bf72ca6ad1c4e8c79557046a8b0adce047f007"); + vector::push_back(&mut siblings, x"5350415253455f4d45524b4c455f504c414345484f4c4445525f484153480000"); + vector::push_back(&mut siblings, x"5ca9febe74c7fde3fdcf2bd464de6d8899a0a13d464893aada2714c6fa774f9d"); + vector::push_back(&mut siblings, x"1519a398fed69687cabf51adf831f0ee1650aaf79775d00135fc70f55a73e151"); + vector::push_back(&mut siblings, x"50ce5c38983ba2eb196acd44e0aaedf040b1437ad1106e05ca452d7e27e4e03f"); + vector::push_back(&mut siblings, x"55ed28435637a061a6dd9e20b72849199cd36184570f976b7e306a27bebf2fdf"); + vector::push_back(&mut siblings, x"0dc23e31614798a6f67659b0b808b3eadc3b13a2a7bc03580a9e3004e45c2e6c"); + vector::push_back(&mut siblings, x"83bed048bc0bc452c98cb0e9f1cc0f691919eaf756864fc44940c2d1e01da92a"); + + let expect_root_hash = x"f65860f575bf2a198c069adb4e7872037e3a329b63ef617e40afa39b87b067c8"; + let element_key = x"4cc8bd9df94b37c233555d9a3bba0a712c3c709f047486d1e624b2bcd3b83266"; + let actual_root_hash = Self::computer_root_hash( + element_key, + x"4f2b59b9af93b435e0a33b6ab7a8a90e471dba936be2bc2937629b7782b8ebd0", + siblings, + ); + assert!(actual_root_hash == expect_root_hash, 1000); + } +} + +module starcoin_framework::starcoin_proof_structured_hash { + use std::bcs; + use std::hash; + use std::vector; + + const STARCOIN_HASH_PREFIX: vector = b"STARCOIN::"; + + public fun hash(structure: vector, data: &MoveValue): vector { + let prefix_hash = hash::sha3_256(concat(&STARCOIN_HASH_PREFIX, structure)); + let bcs_bytes = bcs::to_bytes(data); + hash::sha3_256(concat(&prefix_hash, bcs_bytes)) + } + + fun concat(v1: &vector, v2: vector): vector { + let data = *v1; + vector::append(&mut data, v2); + data + } +} + +module starcoin_framework::starcoin_proof_bit { + use std::vector; + + public fun get_bit(data: &vector, index: u64): bool { + let pos = index / 8; + let bit = (7 - index % 8); + (*vector::borrow(data, pos) >> (bit as u8)) & 1u8 != 0 + } +} \ No newline at end of file From c71ae376dec97faeef9e5c7536ff6c4674f4e032 Mon Sep 17 00:00:00 2001 From: welbon <2261238+welbon@users.noreply.github.com> Date: Mon, 6 Jan 2025 15:49:15 +0800 Subject: [PATCH 17/29] [asset-mapping] split starcoin_proof.move to more files --- .../starcoin-framework/doc/overview.md | 4 +- .../starcoin-framework/doc/starcoin_proof.md | 137 +----------------- .../doc/starcoin_proof_bit.md | 42 ++++++ .../doc/starcoin_proof_structured_hash.md | 87 +++++++++++ .../sources/{ => proof}/starcoin_proof.move | 28 ---- .../sources/proof/starcoin_proof_bit.move | 9 ++ .../proof/starcoin_proof_structured_hash.move | 19 +++ 7 files changed, 164 insertions(+), 162 deletions(-) create mode 100644 vm/framework/starcoin-framework/doc/starcoin_proof_bit.md create mode 100644 vm/framework/starcoin-framework/doc/starcoin_proof_structured_hash.md rename vm/framework/starcoin-framework/sources/{ => proof}/starcoin_proof.move (81%) create mode 100644 vm/framework/starcoin-framework/sources/proof/starcoin_proof_bit.move create mode 100644 vm/framework/starcoin-framework/sources/proof/starcoin_proof_structured_hash.move diff --git a/vm/framework/starcoin-framework/doc/overview.md b/vm/framework/starcoin-framework/doc/overview.md index 5234e035a9..9031493613 100644 --- a/vm/framework/starcoin-framework/doc/overview.md +++ b/vm/framework/starcoin-framework/doc/overview.md @@ -58,8 +58,8 @@ This is the reference documentation of the Starcoin framework. - [`0x1::ring`](ring.md#0x1_ring) - [`0x1::starcoin_account`](starcoin_account.md#0x1_starcoin_account) - [`0x1::starcoin_coin`](starcoin_coin.md#0x1_starcoin_coin) -- [`0x1::starcoin_proof_bit`](starcoin_proof.md#0x1_starcoin_proof_bit) -- [`0x1::starcoin_proof_structured_hash`](starcoin_proof.md#0x1_starcoin_proof_structured_hash) +- [`0x1::starcoin_proof_bit`](starcoin_proof_bit.md#0x1_starcoin_proof_bit) +- [`0x1::starcoin_proof_structured_hash`](starcoin_proof_structured_hash.md#0x1_starcoin_proof_structured_hash) - [`0x1::starcoin_proof_verifier`](starcoin_proof.md#0x1_starcoin_proof_verifier) - [`0x1::stc_block`](stc_block.md#0x1_stc_block) - [`0x1::stc_genesis`](stc_genesis.md#0x1_stc_genesis) diff --git a/vm/framework/starcoin-framework/doc/starcoin_proof.md b/vm/framework/starcoin-framework/doc/starcoin_proof.md index baacea0d21..bd417ec870 100644 --- a/vm/framework/starcoin-framework/doc/starcoin_proof.md +++ b/vm/framework/starcoin-framework/doc/starcoin_proof.md @@ -1,131 +1,4 @@ - - -# Module `0x1::starcoin_proof_bit` - - - -- [Function `get_bit`](#0x1_starcoin_proof_bit_get_bit) - - -
- - - - - -## Function `get_bit` - - - -
public fun get_bit(data: &vector<u8>, index: u64): bool
-
- - - -
-Implementation - - -
public fun get_bit(data: &vector<u8>, index: u64): bool {
-    let pos = index / 8;
-    let bit = (7 - index % 8);
-    (*vector::borrow(data, pos) >> (bit as u8)) & 1u8 != 0
-}
-
- - - -
- - - - - -# Module `0x1::starcoin_proof_structured_hash` - - - -- [Constants](#@Constants_0) -- [Function `hash`](#0x1_starcoin_proof_structured_hash_hash) -- [Function `concat`](#0x1_starcoin_proof_structured_hash_concat) - - -
use 0x1::bcs;
-use 0x1::hash;
-use 0x1::vector;
-
- - - - - -## Constants - - - - - - -
const STARCOIN_HASH_PREFIX: vector<u8> = [83, 84, 65, 82, 67, 79, 73, 78, 58, 58];
-
- - - - - -## Function `hash` - - - -
public fun hash<MoveValue: store>(structure: vector<u8>, data: &MoveValue): vector<u8>
-
- - - -
-Implementation - - -
public fun hash<MoveValue: store>(structure: vector<u8>, data: &MoveValue): vector<u8> {
-    let prefix_hash = hash::sha3_256(concat(&STARCOIN_HASH_PREFIX, structure));
-    let bcs_bytes = bcs::to_bytes(data);
-    hash::sha3_256(concat(&prefix_hash, bcs_bytes))
-}
-
- - - -
- - - -## Function `concat` - - - -
fun concat(v1: &vector<u8>, v2: vector<u8>): vector<u8>
-
- - - -
-Implementation - - -
fun concat(v1: &vector<u8>, v2: vector<u8>): vector<u8> {
-    let data = *v1;
-    vector::append(&mut data, v2);
-    data
-}
-
- - - -
- - - # Module `0x1::starcoin_proof_verifier` @@ -142,8 +15,8 @@
use 0x1::hash;
-use 0x1::starcoin_proof_bit;
-use 0x1::starcoin_proof_structured_hash;
+use 0x1::starcoin_proof_bit;
+use 0x1::starcoin_proof_structured_hash;
 
@@ -348,18 +221,18 @@ proofs: vector<vector<u8>> ): vector<u8> { let leaf_node = Node { hash1: element_key, hash2: element_blob_hash }; - let current_hash = starcoin_proof_structured_hash::hash(SPARSE_MERKLE_LEAF_NODE, &leaf_node); + let current_hash = starcoin_proof_structured_hash::hash(SPARSE_MERKLE_LEAF_NODE, &leaf_node); let i = 0; let proof_length = vector::length(&proofs); while (i < proof_length) { let sibling = *vector::borrow(&proofs, i); - let bit = starcoin_proof_bit::get_bit(&element_key, proof_length - i - 1); + let bit = starcoin_proof_bit::get_bit(&element_key, proof_length - i - 1); let internal_node = if (bit) { Node { hash1: sibling, hash2: current_hash } } else { Node { hash1: current_hash, hash2: sibling } }; - current_hash = starcoin_proof_structured_hash::hash(SPARSE_MERKLE_INTERNAL_NODE, &internal_node); + current_hash = starcoin_proof_structured_hash::hash(SPARSE_MERKLE_INTERNAL_NODE, &internal_node); i = i + 1; }; current_hash diff --git a/vm/framework/starcoin-framework/doc/starcoin_proof_bit.md b/vm/framework/starcoin-framework/doc/starcoin_proof_bit.md new file mode 100644 index 0000000000..e27a83cf8a --- /dev/null +++ b/vm/framework/starcoin-framework/doc/starcoin_proof_bit.md @@ -0,0 +1,42 @@ + + + +# Module `0x1::starcoin_proof_bit` + + + +- [Function `get_bit`](#0x1_starcoin_proof_bit_get_bit) + + +
+ + + + + +## Function `get_bit` + + + +
public fun get_bit(data: &vector<u8>, index: u64): bool
+
+ + + +
+Implementation + + +
public fun get_bit(data: &vector<u8>, index: u64): bool {
+    let pos = index / 8;
+    let bit = (7 - index % 8);
+    (*vector::borrow(data, pos) >> (bit as u8)) & 1u8 != 0
+}
+
+ + + +
+ + +[move-book]: https://starcoin.dev/move/book/SUMMARY diff --git a/vm/framework/starcoin-framework/doc/starcoin_proof_structured_hash.md b/vm/framework/starcoin-framework/doc/starcoin_proof_structured_hash.md new file mode 100644 index 0000000000..3698755a39 --- /dev/null +++ b/vm/framework/starcoin-framework/doc/starcoin_proof_structured_hash.md @@ -0,0 +1,87 @@ + + + +# Module `0x1::starcoin_proof_structured_hash` + + + +- [Constants](#@Constants_0) +- [Function `hash`](#0x1_starcoin_proof_structured_hash_hash) +- [Function `concat`](#0x1_starcoin_proof_structured_hash_concat) + + +
use 0x1::bcs;
+use 0x1::hash;
+use 0x1::vector;
+
+ + + + + +## Constants + + + + + + +
const STARCOIN_HASH_PREFIX: vector<u8> = [83, 84, 65, 82, 67, 79, 73, 78, 58, 58];
+
+ + + + + +## Function `hash` + + + +
public fun hash<MoveValue: store>(structure: vector<u8>, data: &MoveValue): vector<u8>
+
+ + + +
+Implementation + + +
public fun hash<MoveValue: store>(structure: vector<u8>, data: &MoveValue): vector<u8> {
+    let prefix_hash = hash::sha3_256(concat(&STARCOIN_HASH_PREFIX, structure));
+    let bcs_bytes = bcs::to_bytes(data);
+    hash::sha3_256(concat(&prefix_hash, bcs_bytes))
+}
+
+ + + +
+ + + +## Function `concat` + + + +
fun concat(v1: &vector<u8>, v2: vector<u8>): vector<u8>
+
+ + + +
+Implementation + + +
fun concat(v1: &vector<u8>, v2: vector<u8>): vector<u8> {
+    let data = *v1;
+    vector::append(&mut data, v2);
+    data
+}
+
+ + + +
+ + +[move-book]: https://starcoin.dev/move/book/SUMMARY diff --git a/vm/framework/starcoin-framework/sources/starcoin_proof.move b/vm/framework/starcoin-framework/sources/proof/starcoin_proof.move similarity index 81% rename from vm/framework/starcoin-framework/sources/starcoin_proof.move rename to vm/framework/starcoin-framework/sources/proof/starcoin_proof.move index 77cb586daf..f30c64f5db 100644 --- a/vm/framework/starcoin-framework/sources/starcoin_proof.move +++ b/vm/framework/starcoin-framework/sources/proof/starcoin_proof.move @@ -91,32 +91,4 @@ module starcoin_framework::starcoin_proof_verifier { } } -module starcoin_framework::starcoin_proof_structured_hash { - use std::bcs; - use std::hash; - use std::vector; - - const STARCOIN_HASH_PREFIX: vector = b"STARCOIN::"; - public fun hash(structure: vector, data: &MoveValue): vector { - let prefix_hash = hash::sha3_256(concat(&STARCOIN_HASH_PREFIX, structure)); - let bcs_bytes = bcs::to_bytes(data); - hash::sha3_256(concat(&prefix_hash, bcs_bytes)) - } - - fun concat(v1: &vector, v2: vector): vector { - let data = *v1; - vector::append(&mut data, v2); - data - } -} - -module starcoin_framework::starcoin_proof_bit { - use std::vector; - - public fun get_bit(data: &vector, index: u64): bool { - let pos = index / 8; - let bit = (7 - index % 8); - (*vector::borrow(data, pos) >> (bit as u8)) & 1u8 != 0 - } -} \ No newline at end of file diff --git a/vm/framework/starcoin-framework/sources/proof/starcoin_proof_bit.move b/vm/framework/starcoin-framework/sources/proof/starcoin_proof_bit.move new file mode 100644 index 0000000000..249aec05f4 --- /dev/null +++ b/vm/framework/starcoin-framework/sources/proof/starcoin_proof_bit.move @@ -0,0 +1,9 @@ +module starcoin_framework::starcoin_proof_bit { + use std::vector; + + public fun get_bit(data: &vector, index: u64): bool { + let pos = index / 8; + let bit = (7 - index % 8); + (*vector::borrow(data, pos) >> (bit as u8)) & 1u8 != 0 + } +} \ No newline at end of file diff --git a/vm/framework/starcoin-framework/sources/proof/starcoin_proof_structured_hash.move b/vm/framework/starcoin-framework/sources/proof/starcoin_proof_structured_hash.move new file mode 100644 index 0000000000..019d7caee0 --- /dev/null +++ b/vm/framework/starcoin-framework/sources/proof/starcoin_proof_structured_hash.move @@ -0,0 +1,19 @@ +module starcoin_framework::starcoin_proof_structured_hash { + use std::bcs; + use std::hash; + use std::vector; + + const STARCOIN_HASH_PREFIX: vector = b"STARCOIN::"; + + public fun hash(structure: vector, data: &MoveValue): vector { + let prefix_hash = hash::sha3_256(concat(&STARCOIN_HASH_PREFIX, structure)); + let bcs_bytes = bcs::to_bytes(data); + hash::sha3_256(concat(&prefix_hash, bcs_bytes)) + } + + fun concat(v1: &vector, v2: vector): vector { + let data = *v1; + vector::append(&mut data, v2); + data + } +} \ No newline at end of file From 21f57e36e0901535356d84eafb6bd952e61c160b Mon Sep 17 00:00:00 2001 From: welbon <2261238+welbon@users.noreply.github.com> Date: Mon, 6 Jan 2025 22:32:05 +0800 Subject: [PATCH 18/29] [asset-mapping] 1. append starcoin verify into asset_mapping; 2. bind old token string with Object; 3. Append test `test_asset_mapping_proof_coin_type_name` --- executor/tests/executor_test.rs | 33 +++- .../src/starcoin_framework_sdk_builder.rs | 68 +++---- .../starcoin-framework/doc/asset_mapping.md | 163 +++++++++++++-- .../starcoin-framework/doc/stc_genesis.md | 6 +- .../sources/asset_mapping.move | 186 +++++++++++++++--- .../sources/stc/stc_genesis.move | 6 +- 6 files changed, 377 insertions(+), 85 deletions(-) diff --git a/executor/tests/executor_test.rs b/executor/tests/executor_test.rs index 9ec6aadb82..8ee0191e97 100644 --- a/executor/tests/executor_test.rs +++ b/executor/tests/executor_test.rs @@ -4,6 +4,7 @@ use anyhow::anyhow; use anyhow::Result; use forkable_jellyfish_merkle::node_type::SparseMerkleLeafNode; +use forkable_jellyfish_merkle::RawKey; use sha3::{Digest, Sha3_256}; use starcoin_crypto::hash::PlainCryptoHash; use starcoin_crypto::HashValue; @@ -21,7 +22,7 @@ use starcoin_types::account::peer_to_peer_txn; use starcoin_types::account::Account; use starcoin_types::account_config::G_STC_TOKEN_CODE; use starcoin_types::identifier::Identifier; -use starcoin_types::language_storage::{ModuleId, StructTag, CORE_CODE_ADDRESS}; +use starcoin_types::language_storage::{ModuleId, StructTag, TypeTag, CORE_CODE_ADDRESS}; use starcoin_types::transaction::{EntryFunction, RawUserTransaction, TransactionArgument}; use starcoin_types::{ account_config, block_metadata::BlockMetadata, transaction::Transaction, @@ -1200,7 +1201,7 @@ fn test_sha3_256_diffrent_with_crypto_macro() -> Result<()> { HashValue::sha3_256_of(STARCOIN_HASH_PREFIX).as_slice(), ser.as_slice(), ] - .concat(); + .concat(); let move_hash = HashValue::sha3_256_of(&hash_vec[..]); println!( "test_sha3_256_diffrent_with_crypto_macro | sha3 crypto {:?}", @@ -1208,6 +1209,34 @@ fn test_sha3_256_diffrent_with_crypto_macro() -> Result<()> { ); assert_eq!(move_hash, smt_hash, "Failed to get the same hash"); + Ok(()) +} + +#[test] +fn test_asset_mapping_for_specified_coin_type() -> Result<()> { + let (_chain_state, _net) = prepare_genesis(); + let chain_id_struct_tag = StructTag { + address: CORE_CODE_ADDRESS, + module: Identifier::new("coin").unwrap(), + name: Identifier::new("CoinStore").unwrap(), + type_args: vec![TypeTag::Struct(Box::new(StructTag { + address: CORE_CODE_ADDRESS, + module: Identifier::new("starcoin_coin").unwrap(), + name: Identifier::new("STC").unwrap(), + type_args: vec![], + }))], + }; + + let access_path = AccessPath::resource_access_path(genesis_address(), chain_id_struct_tag); + let (account_address, data_path) = access_path.into_inner(); + + println!( + "test_asset_mapping_for_specified_coin_type | account {:?}, data_path: {:?}, data_path key hash: {:?}", + account_address, + data_path.encode_key()?, + data_path.key_hash() + ); + Ok(()) } diff --git a/vm/framework/cached-packages/src/starcoin_framework_sdk_builder.rs b/vm/framework/cached-packages/src/starcoin_framework_sdk_builder.rs index 3a449da729..4870aa89b0 100644 --- a/vm/framework/cached-packages/src/starcoin_framework_sdk_builder.rs +++ b/vm/framework/cached-packages/src/starcoin_framework_sdk_builder.rs @@ -150,18 +150,11 @@ pub enum EntryFunctionCall { cap_update_table: Vec, }, - /// Assigns tokens to a recipient account with proof verification - /// @param token_issuer - The token issuer signer - /// @param receiper - Recipient address - /// @param proove - Proof data for verification - /// @param amount - Amount of tokens to assign - /// Requirements: - /// - Valid proof must be provided - /// - Sufficient balance must exist - AssetMappingAssignToAccount { - t: TypeTag, + AssetMappingAssignToAccountWithProof { receiper: AccountAddress, - proove: Vec, + old_token_str: Vec, + proof_path: Vec, + proof_siblings: Vec, amount: u64, }, @@ -658,12 +651,19 @@ impl EntryFunctionCall { new_public_key_bytes, cap_update_table, ), - AssetMappingAssignToAccount { - t, + AssetMappingAssignToAccountWithProof { receiper, - proove, + old_token_str, + proof_path, + proof_siblings, amount, - } => asset_mapping_assign_to_account(t, receiper, proove, amount), + } => asset_mapping_assign_to_account_with_proof( + receiper, + old_token_str, + proof_path, + proof_siblings, + amount, + ), CoinCreateCoinConversionMap {} => coin_create_coin_conversion_map(), CoinCreatePairing { coin_type } => coin_create_pairing(coin_type), CoinMigrateToFungibleStore { coin_type } => coin_migrate_to_fungible_store(coin_type), @@ -1278,18 +1278,11 @@ pub fn account_rotate_authentication_key_with_rotation_capability( )) } -/// Assigns tokens to a recipient account with proof verification -/// @param token_issuer - The token issuer signer -/// @param receiper - Recipient address -/// @param proove - Proof data for verification -/// @param amount - Amount of tokens to assign -/// Requirements: -/// - Valid proof must be provided -/// - Sufficient balance must exist -pub fn asset_mapping_assign_to_account( - t: TypeTag, +pub fn asset_mapping_assign_to_account_with_proof( receiper: AccountAddress, - proove: Vec, + old_token_str: Vec, + proof_path: Vec, + proof_siblings: Vec, amount: u64, ) -> TransactionPayload { TransactionPayload::EntryFunction(EntryFunction::new( @@ -1297,11 +1290,13 @@ pub fn asset_mapping_assign_to_account( AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]), ident_str!("asset_mapping").to_owned(), ), - ident_str!("assign_to_account").to_owned(), - vec![t], + ident_str!("assign_to_account_with_proof").to_owned(), + vec![], vec![ bcs::to_bytes(&receiper).unwrap(), - bcs::to_bytes(&proove).unwrap(), + bcs::to_bytes(&old_token_str).unwrap(), + bcs::to_bytes(&proof_path).unwrap(), + bcs::to_bytes(&proof_siblings).unwrap(), bcs::to_bytes(&amount).unwrap(), ], )) @@ -2576,15 +2571,16 @@ mod decoder { } } - pub fn asset_mapping_assign_to_account( + pub fn asset_mapping_assign_to_account_with_proof( payload: &TransactionPayload, ) -> Option { if let TransactionPayload::EntryFunction(script) = payload { - Some(EntryFunctionCall::AssetMappingAssignToAccount { - t: script.ty_args().get(0)?.clone(), + Some(EntryFunctionCall::AssetMappingAssignToAccountWithProof { receiper: bcs::from_bytes(script.args().get(0)?).ok()?, - proove: bcs::from_bytes(script.args().get(1)?).ok()?, - amount: bcs::from_bytes(script.args().get(2)?).ok()?, + old_token_str: bcs::from_bytes(script.args().get(1)?).ok()?, + proof_path: bcs::from_bytes(script.args().get(2)?).ok()?, + proof_siblings: bcs::from_bytes(script.args().get(3)?).ok()?, + amount: bcs::from_bytes(script.args().get(4)?).ok()?, }) } else { None @@ -3479,8 +3475,8 @@ static SCRIPT_FUNCTION_DECODER_MAP: once_cell::sync::Lazyuse 0x1::coin; +
use 0x1::bcs;
+use 0x1::coin;
 use 0x1::debug;
 use 0x1::error;
 use 0x1::fungible_asset;
+use 0x1::hash;
 use 0x1::object;
 use 0x1::primary_fungible_store;
 use 0x1::signer;
 use 0x1::smart_table;
+use 0x1::starcoin_proof_verifier;
 use 0x1::stc_util;
 use 0x1::string;
 use 0x1::system_addresses;
@@ -130,6 +136,35 @@ Contains:
 
 
 
+
+
+
+
+## Resource `AssetMappingCoinType`
+
+AssetMappingCoinType represents a mapping that from old version token types to now version asset stores
+eg. 0x1::STC::STC -> 0x1::starcoin_coin::STC
+
+
+
struct AssetMappingCoinType has store, key
+
+ + + +
+Fields + + +
+
+token_mapping: smart_table::SmartTable<string::String, object::Object<fungible_asset::Metadata>> +
+
+ +
+
+ +
@@ -195,6 +230,9 @@ Verifies the framework signer and creates a new AssetMappingPool move_to(framework, AssetMappingProof { proof_root, }); + move_to(framework, AssetMappingCoinType { + token_mapping: smart_table::new<string::String, Object<Metadata>>(), + }) }
@@ -214,7 +252,7 @@ Requirements: - Converts coin to fungible asset and stores it -
public fun create_store_from_coin<T: key>(token_issuer: &signer, coin: coin::Coin<T>)
+
public fun create_store_from_coin<T: key>(token_issuer: &signer, old_token_str: string::String, coin: coin::Coin<T>)
 
@@ -223,7 +261,11 @@ Requirements: Implementation -
public fun create_store_from_coin<T: key>(token_issuer: &signer, coin: coin::Coin<T>) acquires AssetMappingPool {
+
public fun create_store_from_coin<T: key>(
+    token_issuer: &signer,
+    old_token_str: string::String,
+    coin: coin::Coin<T>
+) acquires AssetMappingPool, AssetMappingCoinType {
     let token_issuer_addr = signer::address_of(token_issuer);
     assert!(
         token_issuer_addr == stc_util::token_issuer<T>(),
@@ -240,6 +282,11 @@ Requirements:
         extend_ref,
         fungible_store,
     });
+
+    // Add token mapping coin type
+    let asset_coin_type =
+        borrow_global_mut<AssetMappingCoinType>(system_addresses::get_starcoin_framework());
+    smart_table::add(&mut asset_coin_type.token_mapping, old_token_str, metadata);
 }
 
@@ -314,6 +361,48 @@ Retrieves the balance for a specific token type + + + + +## Function `assign_to_account_with_proof` + + + +
public entry fun assign_to_account_with_proof(token_issuer: &signer, receiper: address, old_token_str: vector<u8>, proof_path: vector<u8>, proof_siblings: vector<u8>, amount: u64)
+
+ + + +
+Implementation + + +
public entry fun assign_to_account_with_proof(
+    token_issuer: &signer,
+    receiper: address,
+    old_token_str: vector<u8>,
+    proof_path: vector<u8>,
+    proof_siblings: vector<u8>,
+    amount: u64
+) acquires AssetMappingPool, AssetMappingCoinType, AssetMappingProof {
+    assert!(
+        exists<AssetMappingProof>(system_addresses::get_starcoin_framework()),
+        error::invalid_state(EINVALID_PROOF_ROOT)
+    );
+
+    // Verify that the token type of the request mapping is the passed-in verification type
+    assert!(
+        calculation_proof(proof_path, amount, split_proof_siblings_from_vec(proof_siblings)),
+        error::unauthenticated(EINVALID_NOT_PROOF)
+    );
+
+    assign_to_account(token_issuer, receiper, old_token_str, amount);
+}
+
+ + +
@@ -330,7 +419,7 @@ Requirements: - Sufficient balance must exist -
public entry fun assign_to_account<T>(token_issuer: &signer, receiper: address, proove: vector<u8>, amount: u64)
+
fun assign_to_account(token_issuer: &signer, receiper: address, old_token_str: vector<u8>, amount: u64)
 
@@ -339,26 +428,23 @@ Requirements: Implementation -
public entry fun assign_to_account<T>(
+
fun assign_to_account(
     token_issuer: &signer,
     receiper: address,
-    proove: vector<u8>,
+    old_token_str: vector<u8>,
     amount: u64
-) acquires AssetMappingPool {
-    assert!(
-        exists<AssetMappingProof>(system_addresses::get_starcoin_framework()),
-        error::invalid_state(EINVALID_PROOF_ROOT)
-    );
-
-    let metadata = coin::ensure_paired_metadata<T>();
+) acquires AssetMappingPool, AssetMappingCoinType {
+    let coin_type_mapping = borrow_global<AssetMappingCoinType>(system_addresses::get_starcoin_framework());
+    let metadata = smart_table::borrow(&coin_type_mapping.token_mapping, string::utf8(old_token_str));
     let mapping_pool = borrow_global_mut<AssetMappingPool>(signer::address_of(token_issuer));
-    let mapping_store = smart_table::borrow_mut(&mut mapping_pool.token_stores, metadata);
-
-    assert!(calculation_proof(proove, vector::empty()), error::unauthenticated(EINVALID_NOT_PROOF));
+    let mapping_store = smart_table::borrow_mut(
+        &mut mapping_pool.token_stores,
+        *metadata
+    );
 
     let store_signer = object::generate_signer_for_extending(&mapping_store.extend_ref);
     fungible_asset::deposit(
-        primary_fungible_store::ensure_primary_store_exists(receiper, metadata),
+        primary_fungible_store::ensure_primary_store_exists(receiper, *metadata),
         fungible_asset::withdraw(&store_signer, mapping_store.fungible_store, amount)
     )
 }
@@ -366,6 +452,31 @@ Requirements:
 
 
 
+
+
+
+
+## Function `split_proof_siblings_from_vec`
+
+
+
+
fun split_proof_siblings_from_vec(_siblings: vector<u8>): vector<vector<u8>>
+
+ + + +
+Implementation + + +
fun split_proof_siblings_from_vec(_siblings: vector<u8>): vector<vector<u8>> {
+    // TODO(BobOng): implement this function
+    vector::empty()
+}
+
+ + +
@@ -375,7 +486,7 @@ Requirements: Computes and verifies the provided proof -
fun calculation_proof(_leaf: vector<u8>, _siblings: vector<vector<u8>>): bool
+
fun calculation_proof(proof_path_hash: vector<u8>, amount: u64, proof_siblings: vector<vector<u8>>): bool
 
@@ -384,9 +495,19 @@ Computes and verifies the provided proof Implementation -
fun calculation_proof(_leaf: vector<u8>, _siblings: vector<vector<u8>>): bool {
-    // TODO(BobOng): implement this function
-    true
+
fun calculation_proof(
+    proof_path_hash: vector<u8>,
+    amount: u64,
+    proof_siblings: vector<vector<u8>>
+): bool acquires AssetMappingProof {
+    let expect_proof_root =
+        borrow_global_mut<AssetMappingProof>(system_addresses::get_starcoin_framework()).proof_root;
+    let actual_root = starcoin_proof_verifier::computer_root_hash(
+        proof_path_hash,
+        hash::sha3_256(bcs::to_bytes(&amount)),
+        proof_siblings
+    );
+    expect_proof_root == actual_root
 }
 
diff --git a/vm/framework/starcoin-framework/doc/stc_genesis.md b/vm/framework/starcoin-framework/doc/stc_genesis.md index c78c70075e..cd89e4268f 100644 --- a/vm/framework/starcoin-framework/doc/stc_genesis.md +++ b/vm/framework/starcoin-framework/doc/stc_genesis.md @@ -389,7 +389,11 @@ Overall governance allocation strategy: ) { // TODO(BobOng): To confirm how many STC put into asset mapping pool let asset_mapping_coin = coin::extract<STC>(&mut total_supply_stc, 1000000000); - asset_mapping::create_store_from_coin<STC>(starcoin_framework, asset_mapping_coin); + asset_mapping::create_store_from_coin<STC>( + starcoin_framework, + std::string::utf8(b"0x1::STC::STC"), + asset_mapping_coin + ); // Initialize treasury let treasury_withdraw_cap = treasury::initialize(starcoin_framework, total_supply_stc); diff --git a/vm/framework/starcoin-framework/sources/asset_mapping.move b/vm/framework/starcoin-framework/sources/asset_mapping.move index 6fd95c65b3..376b9aa85a 100644 --- a/vm/framework/starcoin-framework/sources/asset_mapping.move +++ b/vm/framework/starcoin-framework/sources/asset_mapping.move @@ -4,18 +4,20 @@ /// with proof verification. module starcoin_framework::asset_mapping { + use std::bcs; use std::error; + use std::hash; use std::signer; + use std::string; use std::vector; use starcoin_framework::coin; use starcoin_framework::fungible_asset::{Self, FungibleStore, Metadata}; - use starcoin_framework::object; - use starcoin_framework::object::{ExtendRef, Object}; + use starcoin_framework::object::{Self, ExtendRef, Object}; use starcoin_framework::primary_fungible_store; + use starcoin_framework::starcoin_proof_verifier; use starcoin_framework::stc_util; use starcoin_framework::system_addresses; - use starcoin_std::debug; use starcoin_std::smart_table; @@ -23,6 +25,8 @@ module starcoin_framework::asset_mapping { use starcoin_framework::account; #[test_only] use starcoin_framework::starcoin_coin::{Self, STC}; + #[test_only] + use starcoin_std::type_info; /// AssetMappingStore represents a store for mapped assets /// Contains: @@ -39,13 +43,20 @@ module starcoin_framework::asset_mapping { /// - anchor_height: Block height anchor for the mapping /// - token_stores: Smart table mapping metadata to stores struct AssetMappingPool has key, store { - token_stores: smart_table::SmartTable, AssetMappingStore> + token_stores: smart_table::SmartTable, AssetMappingStore>, } struct AssetMappingProof has key, store { proof_root: vector, } + /// AssetMappingCoinType represents a mapping that from old version token types to now version asset stores + /// eg. 0x1::STC::STC -> 0x1::starcoin_coin::STC + /// + struct AssetMappingCoinType has key, store { + token_mapping: smart_table::SmartTable>, + } + /// Error code for invalid signer const EINVALID_SIGNER: u64 = 101; const EINVALID_NOT_PROOF: u64 = 102; @@ -66,6 +77,9 @@ module starcoin_framework::asset_mapping { move_to(framework, AssetMappingProof { proof_root, }); + move_to(framework, AssetMappingCoinType { + token_mapping: smart_table::new>(), + }) } /// Creates a new store from a coin @@ -74,7 +88,11 @@ module starcoin_framework::asset_mapping { /// Requirements: /// - Token issuer must be authorized for the given token type /// - Converts coin to fungible asset and stores it - public fun create_store_from_coin(token_issuer: &signer, coin: coin::Coin) acquires AssetMappingPool { + public fun create_store_from_coin( + token_issuer: &signer, + old_token_str: string::String, + coin: coin::Coin + ) acquires AssetMappingPool, AssetMappingCoinType { let token_issuer_addr = signer::address_of(token_issuer); assert!( token_issuer_addr == stc_util::token_issuer(), @@ -91,6 +109,11 @@ module starcoin_framework::asset_mapping { extend_ref, fungible_store, }); + + // Add token mapping coin type + let asset_coin_type = + borrow_global_mut(system_addresses::get_starcoin_framework()); + smart_table::add(&mut asset_coin_type.token_mapping, old_token_str, metadata); } /// Creates a store for a specific token type @@ -122,6 +145,28 @@ module starcoin_framework::asset_mapping { fungible_asset::balance(smart_table::borrow(&pool.token_stores, metadata).fungible_store) } + public entry fun assign_to_account_with_proof( + token_issuer: &signer, + receiper: address, + old_token_str: vector, + proof_path: vector, + proof_siblings: vector, + amount: u64 + ) acquires AssetMappingPool, AssetMappingCoinType, AssetMappingProof { + assert!( + exists(system_addresses::get_starcoin_framework()), + error::invalid_state(EINVALID_PROOF_ROOT) + ); + + // Verify that the token type of the request mapping is the passed-in verification type + assert!( + calculation_proof(proof_path, amount, split_proof_siblings_from_vec(proof_siblings)), + error::unauthenticated(EINVALID_NOT_PROOF) + ); + + assign_to_account(token_issuer, receiper, old_token_str, amount); + } + /// Assigns tokens to a recipient account with proof verification /// @param token_issuer - The token issuer signer /// @param receiper - Recipient address @@ -130,34 +175,46 @@ module starcoin_framework::asset_mapping { /// Requirements: /// - Valid proof must be provided /// - Sufficient balance must exist - public entry fun assign_to_account( + fun assign_to_account( token_issuer: &signer, receiper: address, - proove: vector, + old_token_str: vector, amount: u64 - ) acquires AssetMappingPool { - assert!( - exists(system_addresses::get_starcoin_framework()), - error::invalid_state(EINVALID_PROOF_ROOT) - ); - - let metadata = coin::ensure_paired_metadata(); + ) acquires AssetMappingPool, AssetMappingCoinType { + let coin_type_mapping = borrow_global(system_addresses::get_starcoin_framework()); + let metadata = smart_table::borrow(&coin_type_mapping.token_mapping, string::utf8(old_token_str)); let mapping_pool = borrow_global_mut(signer::address_of(token_issuer)); - let mapping_store = smart_table::borrow_mut(&mut mapping_pool.token_stores, metadata); - - assert!(calculation_proof(proove, vector::empty()), error::unauthenticated(EINVALID_NOT_PROOF)); + let mapping_store = smart_table::borrow_mut( + &mut mapping_pool.token_stores, + *metadata + ); let store_signer = object::generate_signer_for_extending(&mapping_store.extend_ref); fungible_asset::deposit( - primary_fungible_store::ensure_primary_store_exists(receiper, metadata), + primary_fungible_store::ensure_primary_store_exists(receiper, *metadata), fungible_asset::withdraw(&store_signer, mapping_store.fungible_store, amount) ) } - /// Computes and verifies the provided proof - fun calculation_proof(_leaf: vector, _siblings: vector>): bool { + fun split_proof_siblings_from_vec(_siblings: vector): vector> { // TODO(BobOng): implement this function - true + vector::empty() + } + + /// Computes and verifies the provided proof + fun calculation_proof( + proof_path_hash: vector, + amount: u64, + proof_siblings: vector> + ): bool acquires AssetMappingProof { + let expect_proof_root = + borrow_global_mut(system_addresses::get_starcoin_framework()).proof_root; + let actual_root = starcoin_proof_verifier::computer_root_hash( + proof_path_hash, + hash::sha3_256(bcs::to_bytes(&amount)), + proof_siblings + ); + expect_proof_root == actual_root } // Test function for asset mapping store creation and assignment @@ -167,7 +224,10 @@ module starcoin_framework::asset_mapping { // Asset assignment to account // Final balance verification #[test(framework= @starcoin_framework, alice= @0x123)] - fun test_asset_mapping_create_store_from_coin(framework: &signer, alice: &signer) acquires AssetMappingPool { + fun test_asset_mapping_create_store_from_coin( + framework: &signer, + alice: &signer + ) acquires AssetMappingPool, AssetMappingCoinType { debug::print(&std::string::utf8(b"asset_mapping::test_asset_mapping_create_store_from_coin | entered")); let amount = 10000000000; @@ -180,13 +240,26 @@ module starcoin_framework::asset_mapping { coin::register(framework); starcoin_coin::mint(framework, signer::address_of(framework), amount); + + // Construct Old token string + let old_token_str = string::utf8(b"0x00000000000000000000000000000001::starcoin_coin::STC"); + let coin = coin::withdraw(framework, amount); - create_store_from_coin(framework, coin); + create_store_from_coin( + framework, + old_token_str, + coin + ); assert!(Self::balance() == amount, 10001); // Assign to alice let alice_addr = signer::address_of(alice); - assign_to_account(framework, alice_addr, vector::empty(), amount); + assign_to_account( + framework, + alice_addr, + *string::bytes(&old_token_str), + amount + ); assert!(Self::balance() == 0, 10002); let stc_metadata = coin::ensure_paired_metadata(); @@ -197,4 +270,69 @@ module starcoin_framework::asset_mapping { debug::print(&std::string::utf8(b"asset_mapping::test_asset_mapping_create_store_from_coin | exited")); } + + #[test(framework= @starcoin_framework)] + fun test_asset_mapping_calculation_proof(framework: &signer) acquires AssetMappingProof { + let siblings = vector::empty>(); + vector::push_back(&mut siblings, x"cfb1462d4fc72f736eab2a56b2bf72ca6ad1c4e8c79557046a8b0adce047f007"); + vector::push_back(&mut siblings, x"5350415253455f4d45524b4c455f504c414345484f4c4445525f484153480000"); + vector::push_back(&mut siblings, x"5ca9febe74c7fde3fdcf2bd464de6d8899a0a13d464893aada2714c6fa774f9d"); + vector::push_back(&mut siblings, x"1519a398fed69687cabf51adf831f0ee1650aaf79775d00135fc70f55a73e151"); + vector::push_back(&mut siblings, x"50ce5c38983ba2eb196acd44e0aaedf040b1437ad1106e05ca452d7e27e4e03f"); + vector::push_back(&mut siblings, x"55ed28435637a061a6dd9e20b72849199cd36184570f976b7e306a27bebf2fdf"); + vector::push_back(&mut siblings, x"0dc23e31614798a6f67659b0b808b3eadc3b13a2a7bc03580a9e3004e45c2e6c"); + vector::push_back(&mut siblings, x"83bed048bc0bc452c98cb0e9f1cc0f691919eaf756864fc44940c2d1e01da92a"); + + let element_key = x"4cc8bd9df94b37c233555d9a3bba0a712c3c709f047486d1e624b2bcd3b83266"; + Self::initialize(framework, x"f65860f575bf2a198c069adb4e7872037e3a329b63ef617e40afa39b87b067c8"); + assert!(Self::calculation_proof(element_key, 0xff, siblings), 10010); + } + + #[test] + fun test_asset_mapping_proof_coin_type_name() { + debug::print(&std::string::utf8(b"asset_mapping::test_asset_mapping_coin_type_verify | entered")); + + // Check type path name + let type_name = type_info::type_name>(); + debug::print( + &std::string::utf8( + b"asset_mapping::test_asset_mapping_coin_type_verify | type of coin::CoinStore" + ) + ); + debug::print(&type_name); + assert!( + type_name == std::string::utf8( + b"0x00000000000000000000000000000001::coin::CoinStore<0x00000000000000000000000000000001::starcoin_coin::STC>" + ), + 10020 + ); + debug::print(&std::string::utf8(b"asset_mapping::test_asset_mapping_coin_type_verify | exited")); + } + + + // let expected_hash = x"9afe1e0e6013eb63b6004a4eb6b1bf76bdb04b725619648163d9dbc3194f224c"; + // + // // TODO(BobOng) Expect type_hash == expected_hash + // let type_data = std::string::bytes(&type_name); + // debug::print(&std::string::utf8(b"asset_mapping::test_asset_mapping_coin_type_verify | type_hash")); + // debug::print(type_data); + // debug::print( + // &bcs::to_bytes>( + // &b"0x00000000000000000000000000000001::coin::CoinStore<0x00000000000000000000000000000001::starcoin_coin::STC>" + // ) + // ); + // let type_hash = hash::sha3_256(*type_data); + // debug::print(&type_hash); + // // assert!(type_hash == expected_hash, 10011); + // + // // TODO(BobOng) Expect type_data == example_type_path_data + // let example_type_path_data = vector[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 99, 111, 105, 110, 9, 67, 111, 105, 110, 83, 116, 111, 114, 101, 1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 13, 115, 116, 97, 114, 99, 111, 105, 110, 95, 99, 111, 105, 110, 3, 83, 84, 67, 0]; + // debug::print(&example_type_path_data); + // debug::print(type_data); + // // assert!(*type_data == example_type_path_data, 10011); + // + // // TODO(BobOng) Expect example_type_path_data == expected_hash + // let example_actual_hash = hash::sha3_256(example_type_path_data); + // debug::print(&example_actual_hash); + // assert!(example_actual_hash == expected_hash, 10012); } diff --git a/vm/framework/starcoin-framework/sources/stc/stc_genesis.move b/vm/framework/starcoin-framework/sources/stc/stc_genesis.move index 45b6188fad..04cd99f4eb 100644 --- a/vm/framework/starcoin-framework/sources/stc/stc_genesis.move +++ b/vm/framework/starcoin-framework/sources/stc/stc_genesis.move @@ -305,7 +305,11 @@ module starcoin_framework::stc_genesis { ) { // TODO(BobOng): To confirm how many STC put into asset mapping pool let asset_mapping_coin = coin::extract(&mut total_supply_stc, 1000000000); - asset_mapping::create_store_from_coin(starcoin_framework, asset_mapping_coin); + asset_mapping::create_store_from_coin( + starcoin_framework, + std::string::utf8(b"0x1::STC::STC"), + asset_mapping_coin + ); // Initialize treasury let treasury_withdraw_cap = treasury::initialize(starcoin_framework, total_supply_stc); From f05d0169da816d4f7dd8b976f06ba3683c5ca0fa Mon Sep 17 00:00:00 2001 From: welbon <2261238+welbon@users.noreply.github.com> Date: Tue, 7 Jan 2025 11:41:15 +0800 Subject: [PATCH 19/29] [asset-mapping] add blob hash check --- executor/tests/executor_test.rs | 69 ++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 32 deletions(-) diff --git a/executor/tests/executor_test.rs b/executor/tests/executor_test.rs index 8ee0191e97..40ab422c71 100644 --- a/executor/tests/executor_test.rs +++ b/executor/tests/executor_test.rs @@ -1,49 +1,47 @@ // Copyright (c) The Starcoin Core Contributors // SPDX-License-Identifier: Apache-2.0 +use std::hash::Hash; + use anyhow::anyhow; use anyhow::Result; -use forkable_jellyfish_merkle::node_type::SparseMerkleLeafNode; -use forkable_jellyfish_merkle::RawKey; -use sha3::{Digest, Sha3_256}; -use starcoin_crypto::hash::PlainCryptoHash; -use starcoin_crypto::HashValue; -use std::hash::Hash; +use starcoin_crypto::{hash::PlainCryptoHash, HashValue}; +use forkable_jellyfish_merkle::{blob::Blob, node_type::SparseMerkleLeafNode, RawKey}; use starcoin_config::{BuiltinNetworkID, ChainNetwork}; use starcoin_executor::validate_transaction; use starcoin_logger::prelude::*; use starcoin_state_api::{ChainStateReader, StateReaderExt}; use starcoin_transaction_builder::{ - build_batch_payload_same_amount, build_transfer_txn, encode_transfer_script_by_token_code, - raw_peer_to_peer_txn, DEFAULT_EXPIRATION_TIME, DEFAULT_MAX_GAS_AMOUNT, + build_batch_payload_same_amount, build_transfer_txn, DEFAULT_EXPIRATION_TIME, + DEFAULT_MAX_GAS_AMOUNT, encode_transfer_script_by_token_code, raw_peer_to_peer_txn, }; -use starcoin_types::account::peer_to_peer_txn; -use starcoin_types::account::Account; -use starcoin_types::account_config::G_STC_TOKEN_CODE; -use starcoin_types::identifier::Identifier; -use starcoin_types::language_storage::{ModuleId, StructTag, TypeTag, CORE_CODE_ADDRESS}; -use starcoin_types::transaction::{EntryFunction, RawUserTransaction, TransactionArgument}; use starcoin_types::{ account_config, block_metadata::BlockMetadata, transaction::Transaction, transaction::TransactionPayload, transaction::TransactionStatus, }; +use starcoin_types::account::Account; +use starcoin_types::account::peer_to_peer_txn; +use starcoin_types::account_config::G_STC_TOKEN_CODE; +use starcoin_types::identifier::Identifier; +use starcoin_types::language_storage::{CORE_CODE_ADDRESS, ModuleId, StructTag, TypeTag}; +use starcoin_types::transaction::{EntryFunction, RawUserTransaction, TransactionArgument}; use starcoin_vm_runtime::starcoin_vm::{chunk_block_transactions, StarcoinVM}; +use starcoin_vm_types::{ + on_chain_config::{ConsensusConfig, OnChainConfig}, + transaction::Package, + vm_status::StatusCode, +}; use starcoin_vm_types::access_path::AccessPath; +use starcoin_vm_types::account_config::AccountResource; use starcoin_vm_types::account_config::core_code_address; use starcoin_vm_types::account_config::genesis_address; -use starcoin_vm_types::account_config::AccountResource; use starcoin_vm_types::genesis_config::ChainId; use starcoin_vm_types::state_store::state_key::StateKey; use starcoin_vm_types::state_store::state_value::StateValue; use starcoin_vm_types::state_store::TStateView; use starcoin_vm_types::token::stc::{stc_type_tag, STCUnit}; use starcoin_vm_types::vm_status::KeptVMStatus; -use starcoin_vm_types::{ - on_chain_config::{ConsensusConfig, OnChainConfig}, - transaction::Package, - vm_status::StatusCode, -}; use test_helper::executor::{ account_execute, account_execute_should_success, association_execute_should_success, blockmeta_execute, build_raw_txn, current_block_number, prepare_customized_genesis, @@ -94,7 +92,7 @@ fn test_vm_version() { vec![TransactionArgument::Address(genesis_address())], None, ) - .unwrap(); + .unwrap(); let readed_version: u64 = bcs_ext::from_bytes(&value.pop().unwrap().1).unwrap(); let version = { @@ -122,7 +120,7 @@ fn test_flexidag_config_get() { vec![TransactionArgument::Address(genesis_address())], None, ) - .unwrap(); + .unwrap(); let read_version: u64 = bcs_ext::from_bytes(&value.pop().unwrap().1).unwrap(); let version = { @@ -573,7 +571,7 @@ fn test_validate_txn_args() -> Result<()> { ); account1.sign_txn(txn) } - .unwrap(); + .unwrap(); assert!(validate_transaction(&chain_state, txn, None).is_some()); let txn = { @@ -594,7 +592,7 @@ fn test_validate_txn_args() -> Result<()> { ); account1.sign_txn(txn) } - .unwrap(); + .unwrap(); assert!(validate_transaction(&chain_state, txn, None).is_some()); let txn = { @@ -615,7 +613,7 @@ fn test_validate_txn_args() -> Result<()> { ); account1.sign_txn(txn) } - .unwrap(); + .unwrap(); assert!(validate_transaction(&chain_state, txn, None).is_some()); Ok(()) } @@ -1180,19 +1178,19 @@ fn test_get_chain_id_after_genesis_with_proof_verify() -> Result<()> { #[test] fn test_sha3_256_diffrent_with_crypto_macro() -> Result<()> { - let hash_1 = HashValue::from_hex_literal( + let element_key_hash = HashValue::from_hex_literal( "0x4cc8bd9df94b37c233555d9a3bba0a712c3c709f047486d1e624b2bcd3b83266", )?; - let hash_2 = HashValue::from_hex_literal( + let blob_hash = HashValue::from_hex_literal( "0x4f2b59b9af93b435e0a33b6ab7a8a90e471dba936be2bc2937629b7782b8ebd0", )?; - let leaf_node = SparseMerkleLeafNode::new(hash_1, hash_2); + let leaf_node = SparseMerkleLeafNode::new(element_key_hash, blob_hash); let smt_hash = leaf_node.crypto_hash(); println!( "test_sha3_256_diffrent_with_crypto_macro | SparseMerkleLeafNode crypto hash: {:?}", - SparseMerkleLeafNode::new(hash_1, hash_2).crypto_hash() + SparseMerkleLeafNode::new(element_key_hash, blob_hash).crypto_hash() ); let ser = bcs_ext::to_bytes(&leaf_node)?; @@ -1201,14 +1199,22 @@ fn test_sha3_256_diffrent_with_crypto_macro() -> Result<()> { HashValue::sha3_256_of(STARCOIN_HASH_PREFIX).as_slice(), ser.as_slice(), ] - .concat(); + .concat(); + let move_hash = HashValue::sha3_256_of(&hash_vec[..]); println!( "test_sha3_256_diffrent_with_crypto_macro | sha3 crypto {:?}", move_hash, ); - assert_eq!(move_hash, smt_hash, "Failed to get the same hash"); + + let check_blob_hash = Blob::from(Vec::from([255])).crypto_hash(); + assert_eq!( + check_blob_hash, + blob_hash, + "Check not equal with crypto_hash from Blob" + ); + Ok(()) } @@ -1237,6 +1243,5 @@ fn test_asset_mapping_for_specified_coin_type() -> Result<()> { data_path.key_hash() ); - Ok(()) } From 4587bcadf02a13119cc435534492dcebdbaed47e Mon Sep 17 00:00:00 2001 From: welbon <2261238+welbon@users.noreply.github.com> Date: Tue, 7 Jan 2025 11:46:02 +0800 Subject: [PATCH 20/29] [asset-mapping] add proof_value_hash to assign_to_account_with_proof --- .../sources/asset_mapping.move | 44 ++++++------------- 1 file changed, 13 insertions(+), 31 deletions(-) diff --git a/vm/framework/starcoin-framework/sources/asset_mapping.move b/vm/framework/starcoin-framework/sources/asset_mapping.move index 376b9aa85a..43302c4a8e 100644 --- a/vm/framework/starcoin-framework/sources/asset_mapping.move +++ b/vm/framework/starcoin-framework/sources/asset_mapping.move @@ -149,7 +149,8 @@ module starcoin_framework::asset_mapping { token_issuer: &signer, receiper: address, old_token_str: vector, - proof_path: vector, + proof_path_hash: vector, + proof_value_hash: vector, proof_siblings: vector, amount: u64 ) acquires AssetMappingPool, AssetMappingCoinType, AssetMappingProof { @@ -160,7 +161,7 @@ module starcoin_framework::asset_mapping { // Verify that the token type of the request mapping is the passed-in verification type assert!( - calculation_proof(proof_path, amount, split_proof_siblings_from_vec(proof_siblings)), + calculation_proof(proof_path_hash, proof_value_hash, split_proof_siblings_from_vec(proof_siblings)), error::unauthenticated(EINVALID_NOT_PROOF) ); @@ -204,14 +205,14 @@ module starcoin_framework::asset_mapping { /// Computes and verifies the provided proof fun calculation_proof( proof_path_hash: vector, - amount: u64, + blob_hash: vector, proof_siblings: vector> ): bool acquires AssetMappingProof { let expect_proof_root = borrow_global_mut(system_addresses::get_starcoin_framework()).proof_root; let actual_root = starcoin_proof_verifier::computer_root_hash( proof_path_hash, - hash::sha3_256(bcs::to_bytes(&amount)), + blob_hash, proof_siblings ); expect_proof_root == actual_root @@ -285,7 +286,14 @@ module starcoin_framework::asset_mapping { let element_key = x"4cc8bd9df94b37c233555d9a3bba0a712c3c709f047486d1e624b2bcd3b83266"; Self::initialize(framework, x"f65860f575bf2a198c069adb4e7872037e3a329b63ef617e40afa39b87b067c8"); - assert!(Self::calculation_proof(element_key, 0xff, siblings), 10010); + assert!( + Self::calculation_proof( + element_key, + x"4f2b59b9af93b435e0a33b6ab7a8a90e471dba936be2bc2937629b7782b8ebd0", + siblings + ), + 10010 + ); } #[test] @@ -309,30 +317,4 @@ module starcoin_framework::asset_mapping { debug::print(&std::string::utf8(b"asset_mapping::test_asset_mapping_coin_type_verify | exited")); } - - // let expected_hash = x"9afe1e0e6013eb63b6004a4eb6b1bf76bdb04b725619648163d9dbc3194f224c"; - // - // // TODO(BobOng) Expect type_hash == expected_hash - // let type_data = std::string::bytes(&type_name); - // debug::print(&std::string::utf8(b"asset_mapping::test_asset_mapping_coin_type_verify | type_hash")); - // debug::print(type_data); - // debug::print( - // &bcs::to_bytes>( - // &b"0x00000000000000000000000000000001::coin::CoinStore<0x00000000000000000000000000000001::starcoin_coin::STC>" - // ) - // ); - // let type_hash = hash::sha3_256(*type_data); - // debug::print(&type_hash); - // // assert!(type_hash == expected_hash, 10011); - // - // // TODO(BobOng) Expect type_data == example_type_path_data - // let example_type_path_data = vector[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 99, 111, 105, 110, 9, 67, 111, 105, 110, 83, 116, 111, 114, 101, 1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 13, 115, 116, 97, 114, 99, 111, 105, 110, 95, 99, 111, 105, 110, 3, 83, 84, 67, 0]; - // debug::print(&example_type_path_data); - // debug::print(type_data); - // // assert!(*type_data == example_type_path_data, 10011); - // - // // TODO(BobOng) Expect example_type_path_data == expected_hash - // let example_actual_hash = hash::sha3_256(example_type_path_data); - // debug::print(&example_actual_hash); - // assert!(example_actual_hash == expected_hash, 10012); } From 6dfdb15f78e9cb1f189a9370c6ee39bda8e030aa Mon Sep 17 00:00:00 2001 From: welbon <2261238+welbon@users.noreply.github.com> Date: Tue, 7 Jan 2025 15:22:58 +0800 Subject: [PATCH 21/29] [asset-mapping] Since the parameters of the move entry function do not support vector>, we need to put all the data into a separate vector parameter when passing the proof parameter `sibilings`, and split it with `|` to ensure that the move layer can receive it smoothly. --- .../src/starcoin_framework_sdk_builder.rs | 22 +++-- .../starcoin-framework/doc/asset_mapping.md | 17 ++-- .../starcoin-framework/doc/starcoin_proof.md | 81 +++++++++++++++++++ .../sources/asset_mapping.move | 40 ++++++--- .../sources/proof/starcoin_proof.move | 56 +++++++++++++ 5 files changed, 187 insertions(+), 29 deletions(-) diff --git a/vm/framework/cached-packages/src/starcoin_framework_sdk_builder.rs b/vm/framework/cached-packages/src/starcoin_framework_sdk_builder.rs index 4870aa89b0..057bf9b81d 100644 --- a/vm/framework/cached-packages/src/starcoin_framework_sdk_builder.rs +++ b/vm/framework/cached-packages/src/starcoin_framework_sdk_builder.rs @@ -153,7 +153,8 @@ pub enum EntryFunctionCall { AssetMappingAssignToAccountWithProof { receiper: AccountAddress, old_token_str: Vec, - proof_path: Vec, + proof_path_hash: Vec, + proof_value_hash: Vec, proof_siblings: Vec, amount: u64, }, @@ -654,13 +655,15 @@ impl EntryFunctionCall { AssetMappingAssignToAccountWithProof { receiper, old_token_str, - proof_path, + proof_path_hash, + proof_value_hash, proof_siblings, amount, } => asset_mapping_assign_to_account_with_proof( receiper, old_token_str, - proof_path, + proof_path_hash, + proof_value_hash, proof_siblings, amount, ), @@ -1281,7 +1284,8 @@ pub fn account_rotate_authentication_key_with_rotation_capability( pub fn asset_mapping_assign_to_account_with_proof( receiper: AccountAddress, old_token_str: Vec, - proof_path: Vec, + proof_path_hash: Vec, + proof_value_hash: Vec, proof_siblings: Vec, amount: u64, ) -> TransactionPayload { @@ -1295,7 +1299,8 @@ pub fn asset_mapping_assign_to_account_with_proof( vec![ bcs::to_bytes(&receiper).unwrap(), bcs::to_bytes(&old_token_str).unwrap(), - bcs::to_bytes(&proof_path).unwrap(), + bcs::to_bytes(&proof_path_hash).unwrap(), + bcs::to_bytes(&proof_value_hash).unwrap(), bcs::to_bytes(&proof_siblings).unwrap(), bcs::to_bytes(&amount).unwrap(), ], @@ -2578,9 +2583,10 @@ mod decoder { Some(EntryFunctionCall::AssetMappingAssignToAccountWithProof { receiper: bcs::from_bytes(script.args().get(0)?).ok()?, old_token_str: bcs::from_bytes(script.args().get(1)?).ok()?, - proof_path: bcs::from_bytes(script.args().get(2)?).ok()?, - proof_siblings: bcs::from_bytes(script.args().get(3)?).ok()?, - amount: bcs::from_bytes(script.args().get(4)?).ok()?, + proof_path_hash: bcs::from_bytes(script.args().get(2)?).ok()?, + proof_value_hash: bcs::from_bytes(script.args().get(3)?).ok()?, + proof_siblings: bcs::from_bytes(script.args().get(4)?).ok()?, + amount: bcs::from_bytes(script.args().get(5)?).ok()?, }) } else { None diff --git a/vm/framework/starcoin-framework/doc/asset_mapping.md b/vm/framework/starcoin-framework/doc/asset_mapping.md index eb7855fe8c..fb0ec67b38 100644 --- a/vm/framework/starcoin-framework/doc/asset_mapping.md +++ b/vm/framework/starcoin-framework/doc/asset_mapping.md @@ -24,12 +24,10 @@ with proof verification. - [Function `calculation_proof`](#0x1_asset_mapping_calculation_proof) -
use 0x1::bcs;
-use 0x1::coin;
+
use 0x1::coin;
 use 0x1::debug;
 use 0x1::error;
 use 0x1::fungible_asset;
-use 0x1::hash;
 use 0x1::object;
 use 0x1::primary_fungible_store;
 use 0x1::signer;
@@ -369,7 +367,7 @@ Retrieves the balance for a specific token type
 
 
 
-
public entry fun assign_to_account_with_proof(token_issuer: &signer, receiper: address, old_token_str: vector<u8>, proof_path: vector<u8>, proof_siblings: vector<u8>, amount: u64)
+
public entry fun assign_to_account_with_proof(token_issuer: &signer, receiper: address, old_token_str: vector<u8>, proof_path_hash: vector<u8>, proof_value_hash: vector<u8>, proof_siblings: vector<u8>, amount: u64)
 
@@ -382,7 +380,8 @@ Retrieves the balance for a specific token type token_issuer: &signer, receiper: address, old_token_str: vector<u8>, - proof_path: vector<u8>, + proof_path_hash: vector<u8>, + proof_value_hash: vector<u8>, proof_siblings: vector<u8>, amount: u64 ) acquires AssetMappingPool, AssetMappingCoinType, AssetMappingProof { @@ -393,7 +392,7 @@ Retrieves the balance for a specific token type // Verify that the token type of the request mapping is the passed-in verification type assert!( - calculation_proof(proof_path, amount, split_proof_siblings_from_vec(proof_siblings)), + calculation_proof(proof_path_hash, proof_value_hash, split_proof_siblings_from_vec(proof_siblings)), error::unauthenticated(EINVALID_NOT_PROOF) ); @@ -486,7 +485,7 @@ Requirements: Computes and verifies the provided proof -
fun calculation_proof(proof_path_hash: vector<u8>, amount: u64, proof_siblings: vector<vector<u8>>): bool
+
fun calculation_proof(proof_path_hash: vector<u8>, blob_hash: vector<u8>, proof_siblings: vector<vector<u8>>): bool
 
@@ -497,14 +496,14 @@ Computes and verifies the provided proof
fun calculation_proof(
     proof_path_hash: vector<u8>,
-    amount: u64,
+    blob_hash: vector<u8>,
     proof_siblings: vector<vector<u8>>
 ): bool acquires AssetMappingProof {
     let expect_proof_root =
         borrow_global_mut<AssetMappingProof>(system_addresses::get_starcoin_framework()).proof_root;
     let actual_root = starcoin_proof_verifier::computer_root_hash(
         proof_path_hash,
-        hash::sha3_256(bcs::to_bytes(&amount)),
+        blob_hash,
         proof_siblings
     );
     expect_proof_root == actual_root
diff --git a/vm/framework/starcoin-framework/doc/starcoin_proof.md b/vm/framework/starcoin-framework/doc/starcoin_proof.md
index bd417ec870..7b786843e3 100644
--- a/vm/framework/starcoin-framework/doc/starcoin_proof.md
+++ b/vm/framework/starcoin-framework/doc/starcoin_proof.md
@@ -12,11 +12,14 @@
 -  [Function `verify_on`](#0x1_starcoin_proof_verifier_verify_on)
 -  [Function `verify`](#0x1_starcoin_proof_verifier_verify)
 -  [Function `computer_root_hash`](#0x1_starcoin_proof_verifier_computer_root_hash)
+-  [Function `splite_symbol`](#0x1_starcoin_proof_verifier_splite_symbol)
+-  [Function `split`](#0x1_starcoin_proof_verifier_split)
 
 
 
use 0x1::hash;
 use 0x1::starcoin_proof_bit;
 use 0x1::starcoin_proof_structured_hash;
+use 0x1::vector;
 
@@ -86,6 +89,15 @@ ## Constants + + + + +
const DELMITER: u8 = 124;
+
+ + + @@ -241,6 +253,75 @@ + + + + +## Function `splite_symbol` + + + +
public fun splite_symbol(): u8
+
+ + + +
+Implementation + + +
public fun splite_symbol(): u8 {
+    DELMITER
+}
+
+ + + +
+ + + +## Function `split` + + + +
public fun split(input: vector<u8>): vector<vector<u8>>
+
+ + + +
+Implementation + + +
public fun split(input: vector<u8>): vector<vector<u8>> {
+    let result: vector<vector<u8>> = vector::empty();
+    let current_segment = vector::empty<u8>();
+    let i = 0;
+    let len = vector::length(&input);
+
+    while (i < len) {
+        let current_byte = *vector::borrow(&input, i);
+        if (current_byte == DELMITER) {
+            if (!vector::is_empty(¤t_segment)) {
+                vector::push_back(&mut result, current_segment);
+                current_segment = vector::empty();
+            };
+        } else {
+            vector::push_back(&mut current_segment, current_byte);
+        };
+        i = i + 1;
+    };
+
+    if (!vector::is_empty(¤t_segment)) {
+        vector::push_back(&mut result, current_segment);
+    };
+    result
+}
+
+ + +
diff --git a/vm/framework/starcoin-framework/sources/asset_mapping.move b/vm/framework/starcoin-framework/sources/asset_mapping.move index 43302c4a8e..2ffa35260f 100644 --- a/vm/framework/starcoin-framework/sources/asset_mapping.move +++ b/vm/framework/starcoin-framework/sources/asset_mapping.move @@ -4,9 +4,7 @@ /// with proof verification. module starcoin_framework::asset_mapping { - use std::bcs; use std::error; - use std::hash; use std::signer; use std::string; use std::vector; @@ -26,6 +24,8 @@ module starcoin_framework::asset_mapping { #[test_only] use starcoin_framework::starcoin_coin::{Self, STC}; #[test_only] + use starcoin_framework::starcoin_proof_verifier::splite_symbol; + #[test_only] use starcoin_std::type_info; /// AssetMappingStore represents a store for mapped assets @@ -274,15 +274,32 @@ module starcoin_framework::asset_mapping { #[test(framework= @starcoin_framework)] fun test_asset_mapping_calculation_proof(framework: &signer) acquires AssetMappingProof { - let siblings = vector::empty>(); - vector::push_back(&mut siblings, x"cfb1462d4fc72f736eab2a56b2bf72ca6ad1c4e8c79557046a8b0adce047f007"); - vector::push_back(&mut siblings, x"5350415253455f4d45524b4c455f504c414345484f4c4445525f484153480000"); - vector::push_back(&mut siblings, x"5ca9febe74c7fde3fdcf2bd464de6d8899a0a13d464893aada2714c6fa774f9d"); - vector::push_back(&mut siblings, x"1519a398fed69687cabf51adf831f0ee1650aaf79775d00135fc70f55a73e151"); - vector::push_back(&mut siblings, x"50ce5c38983ba2eb196acd44e0aaedf040b1437ad1106e05ca452d7e27e4e03f"); - vector::push_back(&mut siblings, x"55ed28435637a061a6dd9e20b72849199cd36184570f976b7e306a27bebf2fdf"); - vector::push_back(&mut siblings, x"0dc23e31614798a6f67659b0b808b3eadc3b13a2a7bc03580a9e3004e45c2e6c"); - vector::push_back(&mut siblings, x"83bed048bc0bc452c98cb0e9f1cc0f691919eaf756864fc44940c2d1e01da92a"); + let siblings_data = vector::empty(); + vector::append(&mut siblings_data, x"cfb1462d4fc72f736eab2a56b2bf72ca6ad1c4e8c79557046a8b0adce047f007"); + vector::push_back(&mut siblings_data, splite_symbol()); + + vector::append(&mut siblings_data, x"5350415253455f4d45524b4c455f504c414345484f4c4445525f484153480000"); + vector::push_back(&mut siblings_data, splite_symbol()); + + vector::append(&mut siblings_data, x"5ca9febe74c7fde3fdcf2bd464de6d8899a0a13d464893aada2714c6fa774f9d"); + vector::push_back(&mut siblings_data, splite_symbol()); + + vector::append(&mut siblings_data, x"1519a398fed69687cabf51adf831f0ee1650aaf79775d00135fc70f55a73e151"); + vector::push_back(&mut siblings_data, splite_symbol()); + + vector::append(&mut siblings_data, x"50ce5c38983ba2eb196acd44e0aaedf040b1437ad1106e05ca452d7e27e4e03f"); + vector::push_back(&mut siblings_data, splite_symbol()); + + vector::append(&mut siblings_data, x"55ed28435637a061a6dd9e20b72849199cd36184570f976b7e306a27bebf2fdf"); + vector::push_back(&mut siblings_data, splite_symbol()); + + vector::append(&mut siblings_data, x"0dc23e31614798a6f67659b0b808b3eadc3b13a2a7bc03580a9e3004e45c2e6c"); + vector::push_back(&mut siblings_data, splite_symbol()); + + vector::append(&mut siblings_data, x"83bed048bc0bc452c98cb0e9f1cc0f691919eaf756864fc44940c2d1e01da92a"); + vector::push_back(&mut siblings_data, splite_symbol()); + + let siblings = starcoin_proof_verifier::split(siblings_data); let element_key = x"4cc8bd9df94b37c233555d9a3bba0a712c3c709f047486d1e624b2bcd3b83266"; Self::initialize(framework, x"f65860f575bf2a198c069adb4e7872037e3a329b63ef617e40afa39b87b067c8"); @@ -316,5 +333,4 @@ module starcoin_framework::asset_mapping { ); debug::print(&std::string::utf8(b"asset_mapping::test_asset_mapping_coin_type_verify | exited")); } - } diff --git a/vm/framework/starcoin-framework/sources/proof/starcoin_proof.move b/vm/framework/starcoin-framework/sources/proof/starcoin_proof.move index f30c64f5db..2a1cfc1ccc 100644 --- a/vm/framework/starcoin-framework/sources/proof/starcoin_proof.move +++ b/vm/framework/starcoin-framework/sources/proof/starcoin_proof.move @@ -68,6 +68,39 @@ module starcoin_framework::starcoin_proof_verifier { current_hash } + + // ASCII for '|' + const DELMITER: u8 = 124; + + public fun splite_symbol(): u8 { + DELMITER + } + + public fun split(input: vector): vector> { + let result: vector> = vector::empty(); + let current_segment = vector::empty(); + let i = 0; + let len = vector::length(&input); + + while (i < len) { + let current_byte = *vector::borrow(&input, i); + if (current_byte == DELMITER) { + if (!vector::is_empty(¤t_segment)) { + vector::push_back(&mut result, current_segment); + current_segment = vector::empty(); + }; + } else { + vector::push_back(&mut current_segment, current_byte); + }; + i = i + 1; + }; + + if (!vector::is_empty(¤t_segment)) { + vector::push_back(&mut result, current_segment); + }; + result + } + #[test] public fun test_starcoin_proof_verify_is_expect_root() { let siblings = vector::empty>(); @@ -89,6 +122,29 @@ module starcoin_framework::starcoin_proof_verifier { ); assert!(actual_root_hash == expect_root_hash, 1000); } + + #[test] + public fun test_starcoin_proof_split() { + // Test case 1: Normal split + let input1 = b"hello|world|test"; + let result1 = split(input1); + assert!(vector::length(&result1) == 3, 10010); + + // Test case 2: Empty segments + let input2 = b"||test||"; + let result2 = split(input2); + assert!(vector::length(&result2) == 1, 10011); + + // Test case 3: Single segment + let input3 = b"hello"; + let result3 = split(input3); + assert!(vector::length(&result3) == 1, 10012); + + // Test case 4: Empty input + let input4 = b""; + let result4 = split(input4); + assert!(vector::length(&result4) == 0, 10013); + } } From 19e580a38c7eb2f3b99388f14ed4db1032af8c32 Mon Sep 17 00:00:00 2001 From: welbon <2261238+welbon@users.noreply.github.com> Date: Tue, 7 Jan 2025 22:01:18 +0800 Subject: [PATCH 22/29] [asset-mapping] add asset-mapping project --- Cargo.lock | 15 ++++ Cargo.toml | 3 + asset-mapping/Cargo.toml | 21 +++++ asset-mapping/src/lib.rs | 134 ++++++++++++++++++++++++++++++ config/src/genesis_config.rs | 12 +++ executor/tests/executor_test.rs | 103 ----------------------- vm/transaction-builder/src/lib.rs | 3 +- 7 files changed, 186 insertions(+), 105 deletions(-) create mode 100644 asset-mapping/Cargo.toml create mode 100644 asset-mapping/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 5ebba609ea..b11bde8377 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10160,6 +10160,21 @@ dependencies = [ "test-case", ] +[[package]] +name = "starcoin-asset-mapping" +version = "2.0.1" +dependencies = [ + "anyhow", + "bcs-ext", + "forkable-jellyfish-merkle", + "starcoin-config", + "starcoin-crypto", + "starcoin-state-api", + "starcoin-types", + "starcoin-vm-types", + "test-helper", +] + [[package]] name = "starcoin-block-relayer" version = "2.0.1" diff --git a/Cargo.toml b/Cargo.toml index 7b22e373e4..b9c041ffa4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -122,6 +122,7 @@ members = [ "cmd/db-exporter", "cmd/genesis-nft-miner", "flexidag", + "asset-mapping", ] default-members = [ @@ -238,6 +239,7 @@ default-members = [ "cmd/miner_client/api", "cmd/db-exporter", "flexidag", + "asset-mapping", ] [workspace.lints.clippy] @@ -513,6 +515,7 @@ starcoin-account-api = { path = "account/api" } starcoin-account-provider = { path = "account/provider" } starcoin-account-service = { path = "account/service" } starcoin-accumulator = { path = "commons/accumulator", package = "starcoin-accumulator" } +starcoin-asset-mapping = { path = "asset-mapping" } starcoin-block-relayer = { path = "block-relayer" } starcoin-chain = { path = "chain" } starcoin-chain-api = { path = "chain/api" } diff --git a/asset-mapping/Cargo.toml b/asset-mapping/Cargo.toml new file mode 100644 index 0000000000..cefc6b8972 --- /dev/null +++ b/asset-mapping/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "starcoin-asset-mapping" +version = "2.0.1" +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 } +bcs-ext = { workspace = true } +test-helper = { workspace = true } +starcoin-crypto = { workspace = true } +starcoin-types = { workspace = true } +starcoin-state-api = { workspace = true } +starcoin-vm-types = { workspace = true } +starcoin-config = { workspace = true } +forkable-jellyfish-merkle = { workspace = true } \ No newline at end of file diff --git a/asset-mapping/src/lib.rs b/asset-mapping/src/lib.rs new file mode 100644 index 0000000000..9af0209d99 --- /dev/null +++ b/asset-mapping/src/lib.rs @@ -0,0 +1,134 @@ +use anyhow::Result; +use starcoin_crypto::{ + hash::PlainCryptoHash, + HashValue +}; + +use forkable_jellyfish_merkle::{ + blob::Blob, + node_type::SparseMerkleLeafNode, + RawKey +}; +use starcoin_config::ChainNetwork; +use starcoin_state_api::ChainStateReader; +use starcoin_types::{ + account_config::CORE_CODE_ADDRESS, + identifier::Identifier, + language_storage::{ + StructTag, + TypeTag + }, +}; +use starcoin_vm_types::{ + access_path::AccessPath, + account_config::genesis_address, + genesis_config::ChainId, + state_store::state_key::StateKey, + state_view::StateReaderExt +}; +use test_helper::executor::{prepare_genesis}; + +#[test] +fn test_get_chain_id_after_genesis_with_proof_verify() -> Result<()> { + let (chain_state, _) = prepare_genesis(); + let chain_id_struct_tag = StructTag { + address: CORE_CODE_ADDRESS, + module: Identifier::new("chain_id").unwrap(), + name: Identifier::new("ChainId").unwrap(), + type_args: vec![], + }; + + let path_statekey = StateKey::resource(&CORE_CODE_ADDRESS, &chain_id_struct_tag)?; + + // Print 0x1 version resource + let resource_value = bcs_ext::from_bytes::( + &chain_state.get_resource(CORE_CODE_ADDRESS, &chain_id_struct_tag)?, + )?; + println!( + "test_get_chain_id_after_genesis_with_proof_verify | path: {:?}, state_value : {:?}", + chain_id_struct_tag, resource_value + ); + assert_eq!(resource_value.id(), 0xff, "not expect chain id"); + + // Get proof and verify proof + let mut state_proof = chain_state.get_with_proof(&path_statekey)?; + let proof_path = AccessPath::resource_access_path(genesis_address(), chain_id_struct_tag); + state_proof.verify(chain_state.state_root(), proof_path.clone())?; + + state_proof.state.as_mut().unwrap()[0] = 0xFE; + assert!(state_proof + .verify(chain_state.state_root(), proof_path) + .is_err()); + Ok(()) +} + +#[test] +fn test_sha3_256_diffrent_with_crypto_macro() -> Result<()> { + let element_key_hash = HashValue::from_hex_literal( + "0x4cc8bd9df94b37c233555d9a3bba0a712c3c709f047486d1e624b2bcd3b83266", + )?; + let blob_hash = HashValue::from_hex_literal( + "0x4f2b59b9af93b435e0a33b6ab7a8a90e471dba936be2bc2937629b7782b8ebd0", + )?; + + let leaf_node = SparseMerkleLeafNode::new(element_key_hash, blob_hash); + + let smt_hash = leaf_node.crypto_hash(); + println!( + "test_sha3_256_diffrent_with_crypto_macro | SparseMerkleLeafNode crypto hash: {:?}", + SparseMerkleLeafNode::new(element_key_hash, blob_hash).crypto_hash() + ); + + let ser = bcs_ext::to_bytes(&leaf_node)?; + const STARCOIN_HASH_PREFIX: &[u8] = b"STARCOIN::SparseMerkleLeafNode"; + let hash_vec = [ + HashValue::sha3_256_of(STARCOIN_HASH_PREFIX).as_slice(), + ser.as_slice(), + ] + .concat(); + + let move_hash = HashValue::sha3_256_of(&hash_vec[..]); + println!( + "test_sha3_256_diffrent_with_crypto_macro | sha3 crypto {:?}", + move_hash, + ); + assert_eq!(move_hash, smt_hash, "Failed to get the same hash"); + + let check_blob_hash = Blob::from(Vec::from([255])).crypto_hash(); + assert_eq!( + check_blob_hash, + blob_hash, + "Check not equal with crypto_hash from Blob" + ); + + Ok(()) +} + +#[test] +fn test_asset_mapping_for_specified_coin_type() -> Result<()> { + let (_chain_state, _net) = prepare_genesis(); + let chain_id_struct_tag = StructTag { + address: CORE_CODE_ADDRESS, + module: Identifier::new("coin").unwrap(), + name: Identifier::new("CoinStore").unwrap(), + type_args: vec![TypeTag::Struct(Box::new(StructTag { + address: CORE_CODE_ADDRESS, + module: Identifier::new("starcoin_coin").unwrap(), + name: Identifier::new("STC").unwrap(), + type_args: vec![], + }))], + }; + + let access_path = AccessPath::resource_access_path(genesis_address(), chain_id_struct_tag); + let (account_address, data_path) = access_path.into_inner(); + + println!( + "test_asset_mapping_for_specified_coin_type | account {:?}, data_path: {:?}, data_path key hash: {:?}", + account_address, + data_path.encode_key()?, + data_path.key_hash() + ); + + Ok(()) +} + diff --git a/config/src/genesis_config.rs b/config/src/genesis_config.rs index d8717d4610..98a1531027 100644 --- a/config/src/genesis_config.rs +++ b/config/src/genesis_config.rs @@ -650,6 +650,9 @@ pub struct GenesisConfig { /// Flexidag effective height pub dag_effective_height: u64, + + /// Asset mapping proof root hash + pub asset_mapping_root_hash: HashValue, } impl GenesisConfig { @@ -799,6 +802,7 @@ pub static G_DAG_TEST_CONFIG: Lazy = Lazy::new(|| { }, transaction_timeout: ONE_DAY, dag_effective_height: 0, + asset_mapping_root_hash: HashValue::zero(), } }); @@ -854,6 +858,7 @@ pub static G_TEST_CONFIG: Lazy = Lazy::new(|| { }, transaction_timeout: ONE_DAY, dag_effective_height: u64::MAX, + asset_mapping_root_hash: HashValue::zero(), } }); @@ -912,6 +917,7 @@ pub static G_DEV_CONFIG: Lazy = Lazy::new(|| { }, transaction_timeout: ONE_DAY, dag_effective_height: 0, + asset_mapping_root_hash: HashValue::zero(), } }); @@ -975,6 +981,7 @@ pub static G_HALLEY_CONFIG: Lazy = Lazy::new(|| { }, transaction_timeout: ONE_DAY, dag_effective_height: 0, + asset_mapping_root_hash: HashValue::zero(), } }); @@ -1034,6 +1041,7 @@ pub static G_PROXIMA_CONFIG: Lazy = Lazy::new(|| { }, transaction_timeout: ONE_DAY, dag_effective_height: 0u64, + asset_mapping_root_hash: HashValue::zero(), } }); @@ -1092,6 +1100,7 @@ pub static G_BARNARD_CONFIG: Lazy = Lazy::new(|| { }, transaction_timeout: ONE_DAY, dag_effective_height: u64::MAX, + asset_mapping_root_hash: HashValue::zero(), } }); @@ -1164,6 +1173,8 @@ pub static G_MAIN_CONFIG: Lazy = Lazy::new(|| { }, transaction_timeout: ONE_DAY, dag_effective_height: u64::MAX, + // TODO(BobOng): to confirm the asset mapping proof root hash + asset_mapping_root_hash: HashValue::zero(), } }); @@ -1218,6 +1229,7 @@ pub static G_VEGA_CONFIG: Lazy = Lazy::new(|| { }, transaction_timeout: ONE_DAY, dag_effective_height: 0, + asset_mapping_root_hash: HashValue::zero(), } }); diff --git a/executor/tests/executor_test.rs b/executor/tests/executor_test.rs index 40ab422c71..c9d6773e37 100644 --- a/executor/tests/executor_test.rs +++ b/executor/tests/executor_test.rs @@ -1142,106 +1142,3 @@ fn test_chunk_block_transactions() -> Result<()> { Ok(()) } -#[test] -fn test_get_chain_id_after_genesis_with_proof_verify() -> Result<()> { - let (chain_state, _net) = prepare_genesis(); - let chain_id_struct_tag = StructTag { - address: CORE_CODE_ADDRESS, - module: Identifier::new("chain_id").unwrap(), - name: Identifier::new("ChainId").unwrap(), - type_args: vec![], - }; - - let path_statekey = StateKey::resource(&CORE_CODE_ADDRESS, &chain_id_struct_tag)?; - - // Print 0x1 version resource - let resource_value = bcs_ext::from_bytes::( - &chain_state.get_resource(CORE_CODE_ADDRESS, &chain_id_struct_tag)?, - )?; - println!( - "test_get_chain_id_after_genesis_with_proof_verify | path: {:?}, state_value : {:?}", - chain_id_struct_tag, resource_value - ); - assert_eq!(resource_value.id(), 0xff, "not expect chain id"); - - // Get proof and verify proof - let mut state_proof = chain_state.get_with_proof(&path_statekey)?; - let proof_path = AccessPath::resource_access_path(genesis_address(), chain_id_struct_tag); - state_proof.verify(chain_state.state_root(), proof_path.clone())?; - - state_proof.state.as_mut().unwrap()[0] = 0xFE; - assert!(state_proof - .verify(chain_state.state_root(), proof_path) - .is_err()); - Ok(()) -} - -#[test] -fn test_sha3_256_diffrent_with_crypto_macro() -> Result<()> { - let element_key_hash = HashValue::from_hex_literal( - "0x4cc8bd9df94b37c233555d9a3bba0a712c3c709f047486d1e624b2bcd3b83266", - )?; - let blob_hash = HashValue::from_hex_literal( - "0x4f2b59b9af93b435e0a33b6ab7a8a90e471dba936be2bc2937629b7782b8ebd0", - )?; - - let leaf_node = SparseMerkleLeafNode::new(element_key_hash, blob_hash); - - let smt_hash = leaf_node.crypto_hash(); - println!( - "test_sha3_256_diffrent_with_crypto_macro | SparseMerkleLeafNode crypto hash: {:?}", - SparseMerkleLeafNode::new(element_key_hash, blob_hash).crypto_hash() - ); - - let ser = bcs_ext::to_bytes(&leaf_node)?; - const STARCOIN_HASH_PREFIX: &[u8] = b"STARCOIN::SparseMerkleLeafNode"; - let hash_vec = [ - HashValue::sha3_256_of(STARCOIN_HASH_PREFIX).as_slice(), - ser.as_slice(), - ] - .concat(); - - let move_hash = HashValue::sha3_256_of(&hash_vec[..]); - println!( - "test_sha3_256_diffrent_with_crypto_macro | sha3 crypto {:?}", - move_hash, - ); - assert_eq!(move_hash, smt_hash, "Failed to get the same hash"); - - let check_blob_hash = Blob::from(Vec::from([255])).crypto_hash(); - assert_eq!( - check_blob_hash, - blob_hash, - "Check not equal with crypto_hash from Blob" - ); - - Ok(()) -} - -#[test] -fn test_asset_mapping_for_specified_coin_type() -> Result<()> { - let (_chain_state, _net) = prepare_genesis(); - let chain_id_struct_tag = StructTag { - address: CORE_CODE_ADDRESS, - module: Identifier::new("coin").unwrap(), - name: Identifier::new("CoinStore").unwrap(), - type_args: vec![TypeTag::Struct(Box::new(StructTag { - address: CORE_CODE_ADDRESS, - module: Identifier::new("starcoin_coin").unwrap(), - name: Identifier::new("STC").unwrap(), - type_args: vec![], - }))], - }; - - let access_path = AccessPath::resource_access_path(genesis_address(), chain_id_struct_tag); - let (account_address, data_path) = access_path.into_inner(); - - println!( - "test_asset_mapping_for_specified_coin_type | account {:?}, data_path: {:?}, data_path key hash: {:?}", - account_address, - data_path.encode_key()?, - data_path.key_hash() - ); - - Ok(()) -} diff --git a/vm/transaction-builder/src/lib.rs b/vm/transaction-builder/src/lib.rs index d7e0cf787b..4e77319576 100644 --- a/vm/transaction-builder/src/lib.rs +++ b/vm/transaction-builder/src/lib.rs @@ -395,8 +395,7 @@ pub fn build_init_script(net: &ChainNetwork) -> EntryFunction { // flexidag effective height genesis_config.dag_effective_height, Features::default().features, - // TODO(BobOng): to set proof root - Vec::new(), + genesis_config.asset_mapping_root_hash.to_vec(), ); match payload { From 0165271397275747af86dae57194e36d7135cde4 Mon Sep 17 00:00:00 2001 From: welbon <2261238+welbon@users.noreply.github.com> Date: Thu, 9 Jan 2025 17:04:37 +0800 Subject: [PATCH 23/29] [asset-mapping] add test_asset_mapping_whole_process for whole asset mapping process --- Cargo.lock | 4 + asset-mapping/Cargo.toml | 8 +- asset-mapping/src/lib.rs | 189 ++++++++++++++++++++++++++------ executor/tests/executor_test.rs | 39 ++++--- 4 files changed, 185 insertions(+), 55 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b11bde8377..f876c5d992 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10167,9 +10167,13 @@ dependencies = [ "anyhow", "bcs-ext", "forkable-jellyfish-merkle", + "starcoin-cached-packages", + "starcoin-chain", "starcoin-config", + "starcoin-consensus", "starcoin-crypto", "starcoin-state-api", + "starcoin-transaction-builder", "starcoin-types", "starcoin-vm-types", "test-helper", diff --git a/asset-mapping/Cargo.toml b/asset-mapping/Cargo.toml index cefc6b8972..792f7192f1 100644 --- a/asset-mapping/Cargo.toml +++ b/asset-mapping/Cargo.toml @@ -12,10 +12,14 @@ rust-version = { workspace = true } [dependencies] anyhow = { workspace = true } bcs-ext = { workspace = true } -test-helper = { workspace = true } +forkable-jellyfish-merkle = { workspace = true } +starcoin-transaction-builder = { workspace = true } +starcoin-chain = { workspace = true } +starcoin-consensus = { workspace = true } starcoin-crypto = { workspace = true } starcoin-types = { workspace = true } starcoin-state-api = { workspace = true } starcoin-vm-types = { workspace = true } starcoin-config = { workspace = true } -forkable-jellyfish-merkle = { workspace = true } \ No newline at end of file +test-helper = { workspace = true } +starcoin-cached-packages = { workspace = true } \ No newline at end of file diff --git a/asset-mapping/src/lib.rs b/asset-mapping/src/lib.rs index 9af0209d99..2320c07d93 100644 --- a/asset-mapping/src/lib.rs +++ b/asset-mapping/src/lib.rs @@ -1,32 +1,28 @@ +use std::str::FromStr; +use std::sync::Arc; + use anyhow::Result; -use starcoin_crypto::{ - hash::PlainCryptoHash, - HashValue -}; +use starcoin_crypto::{hash::PlainCryptoHash, HashValue}; -use forkable_jellyfish_merkle::{ - blob::Blob, - node_type::SparseMerkleLeafNode, - RawKey -}; -use starcoin_config::ChainNetwork; +use forkable_jellyfish_merkle::{blob::Blob, node_type::SparseMerkleLeafNode, RawKey}; +use starcoin_cached_packages::starcoin_framework_sdk_builder::asset_mapping_assign_to_account_with_proof; +use starcoin_chain::{ChainReader, ChainWriter}; +use starcoin_config::{ChainNetwork, NodeConfig, G_TEST_CONFIG}; +use starcoin_consensus::Consensus; use starcoin_state_api::ChainStateReader; +use starcoin_transaction_builder::DEFAULT_MAX_GAS_AMOUNT; use starcoin_types::{ - account_config::CORE_CODE_ADDRESS, - identifier::Identifier, - language_storage::{ - StructTag, - TypeTag - }, + account::DEFAULT_EXPIRATION_TIME, account_address::AccountAddress, + account_config::CORE_CODE_ADDRESS, identifier::Identifier, language_storage::StructTag, }; +use starcoin_types::account::Account; +use starcoin_vm_types::account_config::stc_type_tag; use starcoin_vm_types::{ - access_path::AccessPath, - account_config::genesis_address, - genesis_config::ChainId, - state_store::state_key::StateKey, - state_view::StateReaderExt + access_path::AccessPath, account_config, account_config::genesis_address, + genesis_config::ChainId, state_store::state_key::StateKey, state_view::StateReaderExt, }; -use test_helper::executor::{prepare_genesis}; +use starcoin_vm_types::transaction::TransactionPayload; +use test_helper::executor::prepare_genesis; #[test] fn test_get_chain_id_after_genesis_with_proof_verify() -> Result<()> { @@ -85,7 +81,7 @@ fn test_sha3_256_diffrent_with_crypto_macro() -> Result<()> { HashValue::sha3_256_of(STARCOIN_HASH_PREFIX).as_slice(), ser.as_slice(), ] - .concat(); + .concat(); let move_hash = HashValue::sha3_256_of(&hash_vec[..]); println!( @@ -96,8 +92,7 @@ fn test_sha3_256_diffrent_with_crypto_macro() -> Result<()> { let check_blob_hash = Blob::from(Vec::from([255])).crypto_hash(); assert_eq!( - check_blob_hash, - blob_hash, + check_blob_hash, blob_hash, "Check not equal with crypto_hash from Blob" ); @@ -107,19 +102,14 @@ fn test_sha3_256_diffrent_with_crypto_macro() -> Result<()> { #[test] fn test_asset_mapping_for_specified_coin_type() -> Result<()> { let (_chain_state, _net) = prepare_genesis(); - let chain_id_struct_tag = StructTag { + let stc_store_tag = StructTag { address: CORE_CODE_ADDRESS, module: Identifier::new("coin").unwrap(), name: Identifier::new("CoinStore").unwrap(), - type_args: vec![TypeTag::Struct(Box::new(StructTag { - address: CORE_CODE_ADDRESS, - module: Identifier::new("starcoin_coin").unwrap(), - name: Identifier::new("STC").unwrap(), - type_args: vec![], - }))], + type_args: vec![stc_type_tag()], }; - let access_path = AccessPath::resource_access_path(genesis_address(), chain_id_struct_tag); + let access_path = AccessPath::resource_access_path(genesis_address(), stc_store_tag); let (account_address, data_path) = access_path.into_inner(); println!( @@ -128,7 +118,140 @@ fn test_asset_mapping_for_specified_coin_type() -> Result<()> { data_path.encode_key()?, data_path.key_hash() ); + Ok(()) +} + +#[test] +fn test_asset_mapping_whole_process() -> Result<()> { + let block_gas_limit: u64 = 10000000; + let initial_balance: u128 = 1000000000000; + let receiver = AccountAddress::from_str("0xd0c5a06ae6100ce115cad1600fe59e96").unwrap(); + + // Create a source BlockChain + let (proof_root_hash, proof_path_hash, proof_value_hash, proof_siblings) = { + // construct a test network + let config = Arc::new(NodeConfig::random_for_test()); + let mut block_chain = test_helper::gen_blockchain_with_blocks_for_test(0, config.net())?; + + let association_sequence_num = { + block_chain + .chain_state_reader() + .get_sequence_number(account_config::association_address())? + }; + + let transaction_txn = starcoin_transaction_builder::build_transfer_from_association( + receiver, + association_sequence_num, + initial_balance, + config.net().time_service().now_secs() + DEFAULT_EXPIRATION_TIME, + config.net(), + ) + .try_into()?; + + let (block_template, _excluded) = block_chain + .create_block_template( + account_config::association_address(), + None, + vec![transaction_txn], + vec![], + Some(block_gas_limit), + None, + ) + .unwrap(); + + let block = block_chain + .consensus() + .create_block(block_template, block_chain.time_service().as_ref())?; + + block_chain.apply(block)?; + + { + let chain_state = block_chain.chain_state_reader(); + + // Check balance is initial_balance + let balance = block_chain.chain_state_reader().get_balance(receiver)?; + assert_eq!(balance, initial_balance); + + let proof = chain_state.get_with_proof(&StateKey::resource( + &CORE_CODE_ADDRESS, + &StructTag { + address: CORE_CODE_ADDRESS, + module: Identifier::new("coin").unwrap(), + name: Identifier::new("CoinStore").unwrap(), + type_args: vec![stc_type_tag()], + }, + )?)?; + ( + chain_state.state_root(), + proof.proof.account_state_proof.leaf.unwrap().0, + proof.proof.account_state_proof.leaf.unwrap().1, + proof.proof.account_state_proof.siblings, + ) + } + }; + + println!( + "test_asset_mapping_whole_process | proof_root_hash: {:?}, proof_path_hash: {:?}, proof_value_hash: {:?}, proof_siblings: {:?}", + proof_root_hash, proof_path_hash, proof_value_hash, proof_siblings, + ); + + { + let custom_chain_id = ChainId::new(100); + let mut genesis_config = G_TEST_CONFIG.clone(); + genesis_config.asset_mapping_root_hash = proof_root_hash; + let net = ChainNetwork::new_custom("asset_mapping_test".parse()?, custom_chain_id, genesis_config)?; + let mut block_chain = test_helper::gen_blockchain_with_blocks_for_test(0, &net)?; + + let mut proof_encoded_siblings: Vec = Vec::new(); + proof_siblings.iter().for_each(|hash| { + proof_encoded_siblings.extend_from_slice(hash.as_ref()); + proof_encoded_siblings.push(0x7c); + }); + + let genesis_sequence_number = { + block_chain + .chain_state_reader() + .get_sequence_number(genesis_address())? + }; + + let asset_mapping_txn = Account::new_genesis_account(genesis_address()).create_signed_txn_with_args( + asset_mapping_assign_to_account_with_proof( + receiver, + "0x1::STC::STC".as_bytes().to_vec(), + proof_path_hash.to_vec(), + proof_value_hash.to_vec(), + proof_encoded_siblings, + initial_balance as u64, + ), + genesis_sequence_number, + DEFAULT_MAX_GAS_AMOUNT, + block_gas_limit, + DEFAULT_EXPIRATION_TIME, + net.chain_id(), + ); + + let (block_template, _excluded) = block_chain + .create_block_template( + account_config::association_address(), + None, + vec![asset_mapping_txn], + vec![], + Some(block_gas_limit), + None, + ) + .unwrap(); + + block_chain.apply(block_chain + .consensus() + .create_block(block_template, block_chain.time_service().as_ref())?)?; + + { + let balance = block_chain.chain_state_reader().get_balance(receiver)?; + assert_eq!(balance, initial_balance); + } + } Ok(()) } +fn execute_block_with_txn() {} diff --git a/executor/tests/executor_test.rs b/executor/tests/executor_test.rs index c9d6773e37..3cbade23bf 100644 --- a/executor/tests/executor_test.rs +++ b/executor/tests/executor_test.rs @@ -13,35 +13,35 @@ use starcoin_executor::validate_transaction; use starcoin_logger::prelude::*; use starcoin_state_api::{ChainStateReader, StateReaderExt}; use starcoin_transaction_builder::{ - build_batch_payload_same_amount, build_transfer_txn, DEFAULT_EXPIRATION_TIME, - DEFAULT_MAX_GAS_AMOUNT, encode_transfer_script_by_token_code, raw_peer_to_peer_txn, + build_batch_payload_same_amount, build_transfer_txn, encode_transfer_script_by_token_code, + raw_peer_to_peer_txn, DEFAULT_EXPIRATION_TIME, DEFAULT_MAX_GAS_AMOUNT, }; -use starcoin_types::{ - account_config, block_metadata::BlockMetadata, transaction::Transaction, - transaction::TransactionPayload, transaction::TransactionStatus, -}; -use starcoin_types::account::Account; use starcoin_types::account::peer_to_peer_txn; +use starcoin_types::account::Account; use starcoin_types::account_config::G_STC_TOKEN_CODE; use starcoin_types::identifier::Identifier; -use starcoin_types::language_storage::{CORE_CODE_ADDRESS, ModuleId, StructTag, TypeTag}; +use starcoin_types::language_storage::{ModuleId, StructTag, TypeTag, CORE_CODE_ADDRESS}; use starcoin_types::transaction::{EntryFunction, RawUserTransaction, TransactionArgument}; -use starcoin_vm_runtime::starcoin_vm::{chunk_block_transactions, StarcoinVM}; -use starcoin_vm_types::{ - on_chain_config::{ConsensusConfig, OnChainConfig}, - transaction::Package, - vm_status::StatusCode, +use starcoin_types::{ + account_config, block_metadata::BlockMetadata, transaction::Transaction, + transaction::TransactionPayload, transaction::TransactionStatus, }; +use starcoin_vm_runtime::starcoin_vm::{chunk_block_transactions, StarcoinVM}; use starcoin_vm_types::access_path::AccessPath; -use starcoin_vm_types::account_config::AccountResource; use starcoin_vm_types::account_config::core_code_address; use starcoin_vm_types::account_config::genesis_address; +use starcoin_vm_types::account_config::AccountResource; use starcoin_vm_types::genesis_config::ChainId; use starcoin_vm_types::state_store::state_key::StateKey; use starcoin_vm_types::state_store::state_value::StateValue; use starcoin_vm_types::state_store::TStateView; use starcoin_vm_types::token::stc::{stc_type_tag, STCUnit}; use starcoin_vm_types::vm_status::KeptVMStatus; +use starcoin_vm_types::{ + on_chain_config::{ConsensusConfig, OnChainConfig}, + transaction::Package, + vm_status::StatusCode, +}; use test_helper::executor::{ account_execute, account_execute_should_success, association_execute_should_success, blockmeta_execute, build_raw_txn, current_block_number, prepare_customized_genesis, @@ -92,7 +92,7 @@ fn test_vm_version() { vec![TransactionArgument::Address(genesis_address())], None, ) - .unwrap(); + .unwrap(); let readed_version: u64 = bcs_ext::from_bytes(&value.pop().unwrap().1).unwrap(); let version = { @@ -120,7 +120,7 @@ fn test_flexidag_config_get() { vec![TransactionArgument::Address(genesis_address())], None, ) - .unwrap(); + .unwrap(); let read_version: u64 = bcs_ext::from_bytes(&value.pop().unwrap().1).unwrap(); let version = { @@ -571,7 +571,7 @@ fn test_validate_txn_args() -> Result<()> { ); account1.sign_txn(txn) } - .unwrap(); + .unwrap(); assert!(validate_transaction(&chain_state, txn, None).is_some()); let txn = { @@ -592,7 +592,7 @@ fn test_validate_txn_args() -> Result<()> { ); account1.sign_txn(txn) } - .unwrap(); + .unwrap(); assert!(validate_transaction(&chain_state, txn, None).is_some()); let txn = { @@ -613,7 +613,7 @@ fn test_validate_txn_args() -> Result<()> { ); account1.sign_txn(txn) } - .unwrap(); + .unwrap(); assert!(validate_transaction(&chain_state, txn, None).is_some()); Ok(()) } @@ -1141,4 +1141,3 @@ fn test_chunk_block_transactions() -> Result<()> { Ok(()) } - From c031cd9b2cc84495818fba32e519940df39a34d1 Mon Sep 17 00:00:00 2001 From: welbon <2261238+welbon@users.noreply.github.com> Date: Fri, 10 Jan 2025 10:24:24 +0800 Subject: [PATCH 24/29] [asset-mapping] reformat codes --- asset-mapping/src/lib.rs | 169 +++++++++++++++++++++++---------------- 1 file changed, 101 insertions(+), 68 deletions(-) diff --git a/asset-mapping/src/lib.rs b/asset-mapping/src/lib.rs index 2320c07d93..54bfd18358 100644 --- a/asset-mapping/src/lib.rs +++ b/asset-mapping/src/lib.rs @@ -6,22 +6,25 @@ use starcoin_crypto::{hash::PlainCryptoHash, HashValue}; use forkable_jellyfish_merkle::{blob::Blob, node_type::SparseMerkleLeafNode, RawKey}; use starcoin_cached_packages::starcoin_framework_sdk_builder::asset_mapping_assign_to_account_with_proof; -use starcoin_chain::{ChainReader, ChainWriter}; +use starcoin_chain::{BlockChain, ChainReader, ChainWriter}; use starcoin_config::{ChainNetwork, NodeConfig, G_TEST_CONFIG}; use starcoin_consensus::Consensus; use starcoin_state_api::ChainStateReader; use starcoin_transaction_builder::DEFAULT_MAX_GAS_AMOUNT; +use starcoin_types::account::Account; use starcoin_types::{ account::DEFAULT_EXPIRATION_TIME, account_address::AccountAddress, account_config::CORE_CODE_ADDRESS, identifier::Identifier, language_storage::StructTag, }; -use starcoin_types::account::Account; -use starcoin_vm_types::account_config::stc_type_tag; +use starcoin_vm_types::transaction::SignedUserTransaction; use starcoin_vm_types::{ - access_path::AccessPath, account_config, account_config::genesis_address, - genesis_config::ChainId, state_store::state_key::StateKey, state_view::StateReaderExt, + access_path::AccessPath, + account_config, + account_config::{genesis_address, stc_type_tag}, + genesis_config::ChainId, + state_store::state_key::StateKey, + state_view::StateReaderExt, }; -use starcoin_vm_types::transaction::TransactionPayload; use test_helper::executor::prepare_genesis; #[test] @@ -133,37 +136,15 @@ fn test_asset_mapping_whole_process() -> Result<()> { let config = Arc::new(NodeConfig::random_for_test()); let mut block_chain = test_helper::gen_blockchain_with_blocks_for_test(0, config.net())?; - let association_sequence_num = { - block_chain - .chain_state_reader() - .get_sequence_number(account_config::association_address())? + let peer_to_peer_txn = { + local_build_peer_to_peer_from_association( + &block_chain, + receiver, + initial_balance, + config.net(), + )? }; - - let transaction_txn = starcoin_transaction_builder::build_transfer_from_association( - receiver, - association_sequence_num, - initial_balance, - config.net().time_service().now_secs() + DEFAULT_EXPIRATION_TIME, - config.net(), - ) - .try_into()?; - - let (block_template, _excluded) = block_chain - .create_block_template( - account_config::association_address(), - None, - vec![transaction_txn], - vec![], - Some(block_gas_limit), - None, - ) - .unwrap(); - - let block = block_chain - .consensus() - .create_block(block_template, block_chain.time_service().as_ref())?; - - block_chain.apply(block)?; + local_block_chain_excecute_txn(&mut block_chain, peer_to_peer_txn)?; { let chain_state = block_chain.chain_state_reader(); @@ -195,11 +176,18 @@ fn test_asset_mapping_whole_process() -> Result<()> { proof_root_hash, proof_path_hash, proof_value_hash, proof_siblings, ); + // Create a new blockchain and verify proof { let custom_chain_id = ChainId::new(100); let mut genesis_config = G_TEST_CONFIG.clone(); genesis_config.asset_mapping_root_hash = proof_root_hash; - let net = ChainNetwork::new_custom("asset_mapping_test".parse()?, custom_chain_id, genesis_config)?; + + let net = ChainNetwork::new_custom( + "asset_mapping_test".parse()?, + custom_chain_id, + genesis_config, + )?; + let mut block_chain = test_helper::gen_blockchain_with_blocks_for_test(0, &net)?; let mut proof_encoded_siblings: Vec = Vec::new(); @@ -214,44 +202,89 @@ fn test_asset_mapping_whole_process() -> Result<()> { .get_sequence_number(genesis_address())? }; - let asset_mapping_txn = Account::new_genesis_account(genesis_address()).create_signed_txn_with_args( - asset_mapping_assign_to_account_with_proof( - receiver, - "0x1::STC::STC".as_bytes().to_vec(), - proof_path_hash.to_vec(), - proof_value_hash.to_vec(), - proof_encoded_siblings, - initial_balance as u64, + // Transfer STC from association account to receiver account + let peer_to_peer_txn = + { local_build_peer_to_peer_from_association(&block_chain, receiver, 1, &net)? }; + local_block_chain_excecute_txn(&mut block_chain, peer_to_peer_txn)?; + + // Verify proof and assign asset mapping to receiver account + local_block_chain_excecute_txn( + &mut block_chain, + Account::new_genesis_account(genesis_address()).create_signed_txn_with_args( + asset_mapping_assign_to_account_with_proof( + receiver, + "0x1::STC::STC".as_bytes().to_vec(), + proof_path_hash.to_vec(), + proof_value_hash.to_vec(), + proof_encoded_siblings, + initial_balance as u64, + ), + genesis_sequence_number, + DEFAULT_MAX_GAS_AMOUNT, + block_gas_limit, + DEFAULT_EXPIRATION_TIME, + net.chain_id(), ), - genesis_sequence_number, - DEFAULT_MAX_GAS_AMOUNT, - block_gas_limit, - DEFAULT_EXPIRATION_TIME, - net.chain_id(), - ); - - let (block_template, _excluded) = block_chain - .create_block_template( - account_config::association_address(), - None, - vec![asset_mapping_txn], - vec![], - Some(block_gas_limit), - None, - ) - .unwrap(); - - block_chain.apply(block_chain - .consensus() - .create_block(block_template, block_chain.time_service().as_ref())?)?; + )?; { let balance = block_chain.chain_state_reader().get_balance(receiver)?; - assert_eq!(balance, initial_balance); + println!("The verify blockchain receiver balance is: {:?}", balance); + assert_eq!(balance, initial_balance + 1); } } Ok(()) } -fn execute_block_with_txn() {} +fn local_build_peer_to_peer_from_association( + chain: &BlockChain, + receiver: AccountAddress, + amount: u128, + net: &ChainNetwork, +) -> Result { + let association_sequence_num = { + chain + .chain_state_reader() + .get_sequence_number(account_config::association_address())? + }; + + Ok( + starcoin_transaction_builder::build_transfer_from_association( + receiver, + association_sequence_num, + amount, + net.time_service().now_secs() + DEFAULT_EXPIRATION_TIME, + net, + ) + .try_into()?, + ) +} + +fn local_block_chain_excecute_txn( + chain: &mut BlockChain, + txn: SignedUserTransaction, +) -> Result<()> { + let block_gas_limit: u64 = 10000000; + let (block_template, excluded) = chain + .create_block_template( + account_config::association_address(), + None, + vec![txn], + vec![], + Some(block_gas_limit), + None, + ) + .unwrap(); + + assert!(excluded.discarded_txns.is_empty(), "Execute txn failed!"); + assert!(excluded.untouched_txns.is_empty(), "Execute txn failed!"); + + let block = chain + .consensus() + .create_block(block_template, chain.time_service().as_ref())?; + + chain.apply(block)?; + + Ok(()) +} From bf6dbad7cc32438d2b7be4a74518024db8cb97a7 Mon Sep 17 00:00:00 2001 From: welbon <2261238+welbon@users.noreply.github.com> Date: Sat, 11 Jan 2025 00:29:43 +0800 Subject: [PATCH 25/29] [asset-mapping] reformat codes And add some debug logs --- Cargo.lock | 1 + asset-mapping/Cargo.toml | 9 +- asset-mapping/src/lib.rs | 26 ++- config/src/genesis_config.rs | 2 +- .../starcoin-framework/doc/asset_mapping.md | 209 +++++++++--------- vm/framework/starcoin-framework/doc/coin.md | 13 ++ .../starcoin-framework/doc/fungible_asset.md | 15 ++ vm/framework/starcoin-framework/doc/object.md | 8 +- .../doc/primary_fungible_store.md | 13 ++ .../doc/starcoin_account.md | 7 +- .../starcoin-framework/doc/stc_genesis.md | 6 +- .../integration-tests/asset_mapping/basic.exp | 17 ++ .../asset_mapping/basic.move | 19 ++ .../sources/asset_mapping.move | 149 ++++++++----- .../starcoin-framework/sources/coin.move | 13 ++ .../sources/fungible_asset.move | 15 ++ .../starcoin-framework/sources/object.move | 10 +- .../sources/primary_fungible_store.move | 13 ++ .../sources/starcoin_account.move | 7 +- .../sources/starcoin_coin.move | 5 + .../sources/stc/stc_genesis.move | 6 +- 21 files changed, 370 insertions(+), 193 deletions(-) create mode 100644 vm/framework/starcoin-framework/integration-tests/asset_mapping/basic.exp create mode 100644 vm/framework/starcoin-framework/integration-tests/asset_mapping/basic.move diff --git a/Cargo.lock b/Cargo.lock index f876c5d992..f4f3c04864 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10172,6 +10172,7 @@ dependencies = [ "starcoin-config", "starcoin-consensus", "starcoin-crypto", + "starcoin-logger", "starcoin-state-api", "starcoin-transaction-builder", "starcoin-types", diff --git a/asset-mapping/Cargo.toml b/asset-mapping/Cargo.toml index 792f7192f1..927efd14a1 100644 --- a/asset-mapping/Cargo.toml +++ b/asset-mapping/Cargo.toml @@ -15,11 +15,12 @@ bcs-ext = { workspace = true } forkable-jellyfish-merkle = { workspace = true } starcoin-transaction-builder = { workspace = true } starcoin-chain = { workspace = true } +starcoin-config = { workspace = true } starcoin-consensus = { workspace = true } starcoin-crypto = { workspace = true } -starcoin-types = { workspace = true } +starcoin-cached-packages = { workspace = true } +starcoin-logger = { workspace = true } starcoin-state-api = { workspace = true } +starcoin-types = { workspace = true } starcoin-vm-types = { workspace = true } -starcoin-config = { workspace = true } -test-helper = { workspace = true } -starcoin-cached-packages = { workspace = true } \ No newline at end of file +test-helper = { workspace = true } \ No newline at end of file diff --git a/asset-mapping/src/lib.rs b/asset-mapping/src/lib.rs index 54bfd18358..4cb9704ccf 100644 --- a/asset-mapping/src/lib.rs +++ b/asset-mapping/src/lib.rs @@ -126,8 +126,10 @@ fn test_asset_mapping_for_specified_coin_type() -> Result<()> { #[test] fn test_asset_mapping_whole_process() -> Result<()> { + starcoin_logger::init_for_test(); + let block_gas_limit: u64 = 10000000; - let initial_balance: u128 = 1000000000000; + let initial_balance: u128 = 100000000000; // 1000 STC let receiver = AccountAddress::from_str("0xd0c5a06ae6100ce115cad1600fe59e96").unwrap(); // Create a source BlockChain @@ -202,10 +204,19 @@ fn test_asset_mapping_whole_process() -> Result<()> { .get_sequence_number(genesis_address())? }; - // Transfer STC from association account to receiver account - let peer_to_peer_txn = - { local_build_peer_to_peer_from_association(&block_chain, receiver, 1, &net)? }; - local_block_chain_excecute_txn(&mut block_chain, peer_to_peer_txn)?; + { + // Transfer STC from association account to receiver account + let peer_to_peer_txn = + { local_build_peer_to_peer_from_association(&block_chain, receiver, 1, &net)? }; + local_block_chain_excecute_txn(&mut block_chain, peer_to_peer_txn)?; + } + + { + // Transfer STC from association account to framework account for gas fee + let peer_to_peer_txn = + { local_build_peer_to_peer_from_association(&block_chain, AccountAddress::from_hex_literal("0x1").unwrap(), 1000000000, &net)? }; + local_block_chain_excecute_txn(&mut block_chain, peer_to_peer_txn)?; + } // Verify proof and assign asset mapping to receiver account local_block_chain_excecute_txn( @@ -221,7 +232,7 @@ fn test_asset_mapping_whole_process() -> Result<()> { ), genesis_sequence_number, DEFAULT_MAX_GAS_AMOUNT, - block_gas_limit, + 1, DEFAULT_EXPIRATION_TIME, net.chain_id(), ), @@ -265,14 +276,13 @@ fn local_block_chain_excecute_txn( chain: &mut BlockChain, txn: SignedUserTransaction, ) -> Result<()> { - let block_gas_limit: u64 = 10000000; let (block_template, excluded) = chain .create_block_template( account_config::association_address(), None, vec![txn], vec![], - Some(block_gas_limit), + Some(DEFAULT_MAX_GAS_AMOUNT), None, ) .unwrap(); diff --git a/config/src/genesis_config.rs b/config/src/genesis_config.rs index 98a1531027..3b9ad4b6cd 100644 --- a/config/src/genesis_config.rs +++ b/config/src/genesis_config.rs @@ -1173,7 +1173,7 @@ pub static G_MAIN_CONFIG: Lazy = Lazy::new(|| { }, transaction_timeout: ONE_DAY, dag_effective_height: u64::MAX, - // TODO(BobOng): to confirm the asset mapping proof root hash + // TODO(BobOng): [asset-mapping] To confirm the asset mapping proof root hash asset_mapping_root_hash: HashValue::zero(), } }); diff --git a/vm/framework/starcoin-framework/doc/asset_mapping.md b/vm/framework/starcoin-framework/doc/asset_mapping.md index fb0ec67b38..ddcc566050 100644 --- a/vm/framework/starcoin-framework/doc/asset_mapping.md +++ b/vm/framework/starcoin-framework/doc/asset_mapping.md @@ -10,17 +10,15 @@ with proof verification. - [Resource `AssetMappingStore`](#0x1_asset_mapping_AssetMappingStore) -- [Resource `AssetMappingPool`](#0x1_asset_mapping_AssetMappingPool) - [Resource `AssetMappingProof`](#0x1_asset_mapping_AssetMappingProof) -- [Resource `AssetMappingCoinType`](#0x1_asset_mapping_AssetMappingCoinType) +- [Resource `AssetMappingPool`](#0x1_asset_mapping_AssetMappingPool) - [Constants](#@Constants_0) - [Function `initialize`](#0x1_asset_mapping_initialize) - [Function `create_store_from_coin`](#0x1_asset_mapping_create_store_from_coin) -- [Function `create_store_for_type`](#0x1_asset_mapping_create_store_for_type) -- [Function `balance`](#0x1_asset_mapping_balance) +- [Function `create_store_for_coin_type`](#0x1_asset_mapping_create_store_for_coin_type) +- [Function `fungible_store_balance`](#0x1_asset_mapping_fungible_store_balance) - [Function `assign_to_account_with_proof`](#0x1_asset_mapping_assign_to_account_with_proof) - [Function `assign_to_account`](#0x1_asset_mapping_assign_to_account) -- [Function `split_proof_siblings_from_vec`](#0x1_asset_mapping_split_proof_siblings_from_vec) - [Function `calculation_proof`](#0x1_asset_mapping_calculation_proof) @@ -48,6 +46,7 @@ AssetMappingStore represents a store for mapped assets Contains: - extend_ref: Reference for extending object capabilities - fungible_store: The actual store holding fungible assets +- fungible_metadata: The type of fungible assets
struct AssetMappingStore has store, key
@@ -72,34 +71,8 @@ Contains:
 
- - - - - - - -## Resource `AssetMappingPool` - -AssetMappingPool manages a collection of asset mapping stores -Contains: -- proof_root: Root hash for proof verification -- anchor_height: Block height anchor for the mapping -- token_stores: Smart table mapping metadata to stores - - -
struct AssetMappingPool has store, key
-
- - - -
-Fields - - -
-token_stores: smart_table::SmartTable<object::Object<fungible_asset::Metadata>, asset_mapping::AssetMappingStore> +fungible_metadata: object::Object<fungible_asset::Metadata>
@@ -136,15 +109,15 @@ Contains:
- + -## Resource `AssetMappingCoinType` +## Resource `AssetMappingPool` AssetMappingCoinType represents a mapping that from old version token types to now version asset stores eg. 0x1::STC::STC -> 0x1::starcoin_coin::STC -
struct AssetMappingCoinType has store, key
+
struct AssetMappingPool has store, key
 
@@ -155,7 +128,7 @@ eg. 0x1::STC::STC -> 0x1::starcoin_coin::STC
-token_mapping: smart_table::SmartTable<string::String, object::Object<fungible_asset::Metadata>> +token_mapping: smart_table::SmartTable<string::String, asset_mapping::AssetMappingStore>
@@ -170,11 +143,20 @@ eg. 0x1::STC::STC -> 0x1::starcoin_coin::STC ## Constants + + + + +
const EINVALID_ASSET_MAPPING_POOL: u64 = 104;
+
+ + + -
const EINVALID_NOT_PROOF: u64 = 102;
+
const EINVALID_NOT_PROOF: u64 = 103;
 
@@ -222,14 +204,11 @@ Verifies the framework signer and creates a new AssetMappingPool signer::address_of(framework) == system_addresses::get_starcoin_framework(), error::unauthenticated(EINVALID_SIGNER) ); - move_to(framework, AssetMappingPool { - token_stores: smart_table::new<Object<Metadata>, AssetMappingStore>(), - }); move_to(framework, AssetMappingProof { proof_root, }); - move_to(framework, AssetMappingCoinType { - token_mapping: smart_table::new<string::String, Object<Metadata>>(), + move_to(framework, AssetMappingPool { + token_mapping: smart_table::new<string::String, AssetMappingStore>(), }) }
@@ -250,7 +229,7 @@ Requirements: - Converts coin to fungible asset and stores it -
public fun create_store_from_coin<T: key>(token_issuer: &signer, old_token_str: string::String, coin: coin::Coin<T>)
+
public fun create_store_from_coin<T: key>(token_issuer: &signer, old_token_str: vector<u8>, coin: coin::Coin<T>)
 
@@ -261,9 +240,11 @@ Requirements:
public fun create_store_from_coin<T: key>(
     token_issuer: &signer,
-    old_token_str: string::String,
+    old_token_str: vector<u8>,
     coin: coin::Coin<T>
-) acquires AssetMappingPool, AssetMappingCoinType {
+) acquires AssetMappingPool {
+    debug::print(&string::utf8(b"asset_mapping::create_store_from_coin | entered"));
+
     let token_issuer_addr = signer::address_of(token_issuer);
     assert!(
         token_issuer_addr == stc_util::token_issuer<T>(),
@@ -271,20 +252,43 @@ Requirements:
     );
 
     let fungible_asset = coin::coin_to_fungible_asset(coin);
-    let token_stores =
-        &mut borrow_global_mut<AssetMappingPool>(system_addresses::get_starcoin_framework()).token_stores;
 
-    let (metadata, fungible_store, extend_ref) = create_store_for_type<T>(token_issuer);
-    fungible_asset::deposit(fungible_store, fungible_asset);
-    smart_table::add(token_stores, metadata, AssetMappingStore {
-        extend_ref,
+    let (
+        fungible_metadata,
         fungible_store,
-    });
+        extend_ref
+    ) = create_store_for_coin_type<T>(token_issuer);
+
+    debug::print(&string::utf8(b"asset_mapping::create_store_from_coin | created token store"));
+    debug::print(&fungible_store);
+
+    fungible_asset::deposit(fungible_store, fungible_asset);
+
+    // debug::print(&string::utf8(b"asset_mapping::create_store_from_coin | withdraw test begin"));
+    // {
+    //     let test_fa = fungible_asset::withdraw(
+    //         &object::generate_signer_for_extending(&extend_ref),
+    //         fungible_store,
+    //         10000
+    //     );
+    //     assert!(fungible_asset::amount(&test_fa) == 10000, 10000);
+    //     fungible_asset::deposit(fungible_store, test_fa);
+    // };
+    // debug::print(&string::utf8(b"asset_mapping::create_store_from_coin | withdraw test end"));
 
     // Add token mapping coin type
     let asset_coin_type =
-        borrow_global_mut<AssetMappingCoinType>(system_addresses::get_starcoin_framework());
-    smart_table::add(&mut asset_coin_type.token_mapping, old_token_str, metadata);
+        borrow_global_mut<AssetMappingPool>(system_addresses::get_starcoin_framework());
+    smart_table::add(
+        &mut asset_coin_type.token_mapping,
+        string::utf8(old_token_str),
+        AssetMappingStore {
+            fungible_store,
+            fungible_metadata,
+            extend_ref,
+        }
+    );
+    debug::print(&string::utf8(b"asset_mapping::create_store_from_coin | exited"));
 }
 
@@ -292,9 +296,9 @@ Requirements: - + -## Function `create_store_for_type` +## Function `create_store_for_coin_type` Creates a store for a specific token type @param framework - The framework signer @@ -304,7 +308,7 @@ Creates a store for a specific token type - extend_ref: Extension reference for the store -
fun create_store_for_type<T>(framework: &signer): (object::Object<fungible_asset::Metadata>, object::Object<fungible_asset::FungibleStore>, object::ExtendRef)
+
fun create_store_for_coin_type<T>(framework: &signer): (object::Object<fungible_asset::Metadata>, object::Object<fungible_asset::FungibleStore>, object::ExtendRef)
 
@@ -313,8 +317,8 @@ Creates a store for a specific token type Implementation -
fun create_store_for_type<T>(framework: &signer): (Object<Metadata>, Object<FungibleStore>, ExtendRef) {
-    debug::print(&std::string::utf8(b"asset_mapping::create_store_for_type | entered"));
+
fun create_store_for_coin_type<T>(framework: &signer): (Object<Metadata>, Object<FungibleStore>, ExtendRef) {
+    debug::print(&std::string::utf8(b"asset_mapping::create_store_for_type | entered"));
 
     let metadata = coin::ensure_paired_metadata<T>();
     let construct_ref = object::create_object_from_account(framework);
@@ -323,7 +327,7 @@ Creates a store for a specific token type
 
     // Generate extend reference
     let extend_ref = object::generate_extend_ref(&construct_ref);
-    debug::print(&std::string::utf8(b"asset_mapping::create_store_for_type | exited"));
+    debug::print(&std::string::utf8(b"asset_mapping::create_store_for_type | exited"));
 
     (metadata, store, extend_ref)
 }
@@ -333,15 +337,15 @@ Creates a store for a specific token type
 
 
 
-
+
 
-## Function `balance`
+## Function `fungible_store_balance`
 
 Retrieves the balance for a specific token type
 @returns Current balance of the token in the mapping pool
 
 
-
fun balance<T>(): u64
+
fun fungible_store_balance(old_asset_str: vector<u8>): u64
 
@@ -350,10 +354,12 @@ Retrieves the balance for a specific token type Implementation -
fun balance<T>(): u64 acquires AssetMappingPool {
-    let metadata = coin::ensure_paired_metadata<T>();
+
fun fungible_store_balance(old_asset_str: vector<u8>): u64 acquires AssetMappingPool {
+    // let metadata = coin::ensure_paired_metadata<T>();
     let pool = borrow_global<AssetMappingPool>(system_addresses::get_starcoin_framework());
-    fungible_asset::balance(smart_table::borrow(&pool.token_stores, metadata).fungible_store)
+    let fungible_asset_store =
+        smart_table::borrow(&pool.token_mapping, string::utf8(old_asset_str)).fungible_store;
+    fungible_asset::balance(fungible_asset_store)
 }
 
@@ -384,7 +390,7 @@ Retrieves the balance for a specific token type proof_value_hash: vector<u8>, proof_siblings: vector<u8>, amount: u64 -) acquires AssetMappingPool, AssetMappingCoinType, AssetMappingProof { +) acquires AssetMappingPool, AssetMappingProof { assert!( exists<AssetMappingProof>(system_addresses::get_starcoin_framework()), error::invalid_state(EINVALID_PROOF_ROOT) @@ -392,7 +398,7 @@ Retrieves the balance for a specific token type // Verify that the token type of the request mapping is the passed-in verification type assert!( - calculation_proof(proof_path_hash, proof_value_hash, split_proof_siblings_from_vec(proof_siblings)), + calculation_proof(proof_path_hash, proof_value_hash, starcoin_proof_verifier::split(proof_siblings)), error::unauthenticated(EINVALID_NOT_PROOF) ); @@ -418,7 +424,7 @@ Requirements: - Sufficient balance must exist -
fun assign_to_account(token_issuer: &signer, receiper: address, old_token_str: vector<u8>, amount: u64)
+
public fun assign_to_account(token_issuer: &signer, receiver: address, old_token_str: vector<u8>, amount: u64)
 
@@ -427,50 +433,43 @@ Requirements: Implementation -
fun assign_to_account(
+
public fun assign_to_account(
     token_issuer: &signer,
-    receiper: address,
+    receiver: address,
     old_token_str: vector<u8>,
     amount: u64
-) acquires AssetMappingPool, AssetMappingCoinType {
-    let coin_type_mapping = borrow_global<AssetMappingCoinType>(system_addresses::get_starcoin_framework());
-    let metadata = smart_table::borrow(&coin_type_mapping.token_mapping, string::utf8(old_token_str));
-    let mapping_pool = borrow_global_mut<AssetMappingPool>(signer::address_of(token_issuer));
-    let mapping_store = smart_table::borrow_mut(
-        &mut mapping_pool.token_stores,
-        *metadata
-    );
-
-    let store_signer = object::generate_signer_for_extending(&mapping_store.extend_ref);
-    fungible_asset::deposit(
-        primary_fungible_store::ensure_primary_store_exists(receiper, *metadata),
-        fungible_asset::withdraw(&store_signer, mapping_store.fungible_store, amount)
-    )
-}
-
- - - - - - - -## Function `split_proof_siblings_from_vec` - - - -
fun split_proof_siblings_from_vec(_siblings: vector<u8>): vector<vector<u8>>
-
+) acquires AssetMappingPool { + debug::print(&string::utf8(b"asset_mapping::assign_to_account | entered")); + assert!( + exists<AssetMappingPool>(signer::address_of(token_issuer)), + error::invalid_state(EINVALID_ASSET_MAPPING_POOL) + ); + let coin_type_mapping = + borrow_global<AssetMappingPool>(system_addresses::get_starcoin_framework()); + debug::print(&string::utf8(b"asset_mapping::assign_to_account | coin_type_mapping")); -
-Implementation + let mapping_store = smart_table::borrow( + &coin_type_mapping.token_mapping, + string::utf8(old_token_str) + ); + debug::print(&string::utf8(b"asset_mapping::assign_to_account | metadata")); + debug::print(&fungible_asset::is_frozen(mapping_store.fungible_store)); + + debug::print(&string::utf8(b"asset_mapping::assign_to_account | fungible_asset::withdraw:")); + let mapping_fa = fungible_asset::withdraw( + &object::generate_signer_for_extending(&mapping_store.extend_ref), + mapping_store.fungible_store, + amount + ); + debug::print(&string::utf8(b"asset_mapping::assign_to_account | Getting receiver fungible store: ")); + let target_store = + primary_fungible_store::ensure_primary_store_exists(receiver, mapping_store.fungible_metadata); -
fun split_proof_siblings_from_vec(_siblings: vector<u8>): vector<vector<u8>> {
-    // TODO(BobOng): implement this function
-    vector::empty()
+    fungible_asset::deposit(target_store, mapping_fa);
+    debug::print(&string::utf8(b"asset_mapping::assign_to_account | exited"));
 }
 
diff --git a/vm/framework/starcoin-framework/doc/coin.md b/vm/framework/starcoin-framework/doc/coin.md index 5ed62c57e5..b93e67c8ee 100644 --- a/vm/framework/starcoin-framework/doc/coin.md +++ b/vm/framework/starcoin-framework/doc/coin.md @@ -1450,12 +1450,25 @@ Create STC pairing by passing StarcoinCoin. let map = borrow_global_mut<CoinConversionMap>(@starcoin_framework); let type = type_info::type_of<CoinType>(); if (!table::contains(&map.coin_to_fungible_asset_map, type)) { + debug::print( + &std::string::utf8(b"coin::create_and_return_paired_metadata_if_not_exist | map not contain type") + ); let is_stc = is_stc<CoinType>(); assert!(!is_stc || allow_stc_creation, error::invalid_state(EAPT_PAIRING_IS_NOT_ENABLED)); let metadata_object_cref = if (is_stc) { + debug::print( + &std::string::utf8( + b"coin::create_and_return_paired_metadata_if_not_exist | type is stc, create sticky object at 0x1" + ) + ); object::create_sticky_object_at_address(@starcoin_framework, @starcoin_fungible_asset) } else { + debug::print( + &std::string::utf8( + b"coin::create_and_return_paired_metadata_if_not_exist | type is not stc, create new asset sub object" + ) + ); object::create_named_object( &create_signer::create_signer(@starcoin_fungible_asset), *string::bytes(&type_info::type_name<CoinType>()) diff --git a/vm/framework/starcoin-framework/doc/fungible_asset.md b/vm/framework/starcoin-framework/doc/fungible_asset.md index be6434bb05..38d8d52948 100644 --- a/vm/framework/starcoin-framework/doc/fungible_asset.md +++ b/vm/framework/starcoin-framework/doc/fungible_asset.md @@ -2593,6 +2593,9 @@ Applications can use this to create multiple stores for isolating fungible asset constructor_ref: &ConstructorRef, metadata: Object<T>, ): Object<FungibleStore> { + debug::print(&string::utf8(b"fungible_asset::create_store | entered")); + debug::print(constructor_ref); + let store_obj = &object::generate_signer(constructor_ref); move_to(store_obj, FungibleStore { metadata: object::convert(metadata), @@ -2610,6 +2613,8 @@ Applications can use this to create multiple stores for isolating fungible asset }); }; + debug::print(&string::utf8(b"fungible_asset::create_store | exited")); + object::object_from_constructor_ref<FungibleStore>(constructor_ref) }
@@ -2635,6 +2640,9 @@ Used to delete a store. Requires the store to be completely empty prior to remo
public fun remove_store(delete_ref: &DeleteRef) acquires FungibleStore, FungibleAssetEvents, ConcurrentFungibleBalance {
+    debug::print(&string::utf8(b"fungible_asset::remove_store | entered"));
+    debug::print(delete_ref);
+
     let store = &object::object_from_delete_ref<FungibleStore>(delete_ref);
     let addr = object::object_address(store);
     let FungibleStore { metadata: _, balance, frozen: _ }
@@ -2657,6 +2665,7 @@ Used to delete a store.  Requires the store to be completely empty prior to remo
         event::destroy_handle(withdraw_events);
         event::destroy_handle(frozen_events);
     };
+    debug::print(&string::utf8(b"fungible_asset::remove_store | exited"));
 }
 
@@ -2779,8 +2788,11 @@ Deposit amount of the fungible asset to store.
public fun deposit<T: key>(store: Object<T>, fa: FungibleAsset) acquires FungibleStore, DispatchFunctionStore, ConcurrentFungibleBalance {
+    debug::print(&string::utf8(b"fungible_asset::deposit | entered"));
+    debug::print(&store);
     deposit_sanity_check(store, true);
     deposit_internal(object::object_address(&store), fa);
+    debug::print(&string::utf8(b"fungible_asset::deposit | exited"));
 }
 
@@ -3564,8 +3576,11 @@ Decrease the supply of a fungible asset by burning.
inline fun borrow_store_resource<T: key>(store: &Object<T>): &FungibleStore acquires FungibleStore {
+    debug::print(&string::utf8(b"fungible_asset::borrow_store_resource | entered"));
     let store_addr = object::object_address(store);
+    debug::print(&store_addr);
     assert!(exists<FungibleStore>(store_addr), error::not_found(EFUNGIBLE_STORE_EXISTENCE));
+    debug::print(&string::utf8(b"fungible_asset::borrow_store_resource | exited"));
     borrow_global<FungibleStore>(store_addr)
 }
 
diff --git a/vm/framework/starcoin-framework/doc/object.md b/vm/framework/starcoin-framework/doc/object.md index 3a043c2b8c..d9bc8d748e 100644 --- a/vm/framework/starcoin-framework/doc/object.md +++ b/vm/framework/starcoin-framework/doc/object.md @@ -139,6 +139,7 @@ make it so that a reference to a global object can be returned from a function. use 0x1::bcs; use 0x1::bcs_util; use 0x1::create_signer; +use 0x1::debug; use 0x1::error; use 0x1::event; use 0x1::features; @@ -146,6 +147,7 @@ make it so that a reference to a global object can be returned from a function. use 0x1::guid; use 0x1::hash; use 0x1::signer; +use 0x1::string; use 0x1::transaction_context; use 0x1::vector;
@@ -1329,7 +1331,9 @@ doesn't have the same bottlenecks. object: address, can_delete: bool, ): ConstructorRef { - // debug::print(&string::utf8(b"object::create_object_internal | entered")); + debug::print(&string::utf8(b"object::create_object_internal | entered")); + debug::print(&creator_address); + debug::print(&object); assert!(!exists<ObjectCore>(object), error::already_exists(EOBJECT_EXISTS)); @@ -1347,7 +1351,7 @@ doesn't have the same bottlenecks. }, ); - // debug::print(&string::utf8(b"object::create_object_internal | exited")); + debug::print(&string::utf8(b"object::create_object_internal | exited")); ConstructorRef { self: object, can_delete } }
diff --git a/vm/framework/starcoin-framework/doc/primary_fungible_store.md b/vm/framework/starcoin-framework/doc/primary_fungible_store.md index 5043b16dca..347e673d26 100644 --- a/vm/framework/starcoin-framework/doc/primary_fungible_store.md +++ b/vm/framework/starcoin-framework/doc/primary_fungible_store.md @@ -117,6 +117,7 @@ so that users can easily deposit/withdraw/transfer fungible assets. icon_uri: String, project_uri: String, ) { + debug::print(&string::utf8(b"primary_fungible_store::create_primary_store_enabled_fungible_asset | entered")); fungible_asset::add_fungibility( constructor_ref, maximum_supply, @@ -130,6 +131,7 @@ so that users can easily deposit/withdraw/transfer fungible assets. move_to(metadata_obj, DeriveRefPod { metadata_derive_ref: object::generate_derive_ref(constructor_ref), }); + debug::print(&string::utf8(b"primary_fungible_store::create_primary_store_enabled_fungible_asset | exited")); }
@@ -158,6 +160,8 @@ Ensure that the primary store object for the given address exists. If it doesn't metadata: Object<T>, ): Object<FungibleStore> acquires DeriveRefPod { debug::print(&string::utf8(b"primary_fungible_store::ensure_primary_store_exists | entered")); + debug::print(&owner); + let store_addr = primary_store_address(owner, metadata); let ret = if (fungible_asset::store_exists(store_addr)) { object::address_to_object(store_addr) @@ -198,13 +202,22 @@ Create a primary store object to hold fungible asset for the given address. debug::print(&metadata); let metadata_addr = object::object_address(&metadata); + debug::print(&string::utf8(b"primary_fungible_store::create_primary_store | 1")); + debug::print(&metadata_addr); + object::address_to_object<Metadata>(metadata_addr); + + debug::print(&string::utf8(b"primary_fungible_store::create_primary_store | 2")); let derive_ref = &borrow_global<DeriveRefPod>(metadata_addr).metadata_derive_ref; let constructor_ref = &object::create_user_derived_object(owner_addr, derive_ref); + + debug::print(&string::utf8(b"primary_fungible_store::create_primary_store | 3")); // Disable ungated transfer as deterministic stores shouldn't be transferrable. let transfer_ref = &object::generate_transfer_ref(constructor_ref); object::disable_ungated_transfer(transfer_ref); + debug::print(&string::utf8(b"primary_fungible_store::create_primary_store | 4")); + let ret = fungible_asset::create_store(constructor_ref, metadata); debug::print(&string::utf8(b"primary_fungible_store::create_primary_store | exited")); debug::print(&ret); diff --git a/vm/framework/starcoin-framework/doc/starcoin_account.md b/vm/framework/starcoin-framework/doc/starcoin_account.md index a8bd45c9de..66ead12446 100644 --- a/vm/framework/starcoin-framework/doc/starcoin_account.md +++ b/vm/framework/starcoin-framework/doc/starcoin_account.md @@ -693,7 +693,12 @@ Ensure that APT Primary FungibleStore exists (and create if it doesn't) if (fungible_asset::store_exists(store_addr)) { store_addr } else { - object::object_address(&primary_fungible_store::create_primary_store(owner, object::address_to_object<Metadata>(@starcoin_fungible_asset))) + object::object_address( + &primary_fungible_store::create_primary_store( + owner, + object::address_to_object<Metadata>(@starcoin_fungible_asset) + ) + ) } }
diff --git a/vm/framework/starcoin-framework/doc/stc_genesis.md b/vm/framework/starcoin-framework/doc/stc_genesis.md index cd89e4268f..9d59577a9d 100644 --- a/vm/framework/starcoin-framework/doc/stc_genesis.md +++ b/vm/framework/starcoin-framework/doc/stc_genesis.md @@ -387,11 +387,11 @@ Overall governance allocation strategy: time_mint_stc_amount: u128, time_mint_stc_period: u64, ) { - // TODO(BobOng): To confirm how many STC put into asset mapping pool - let asset_mapping_coin = coin::extract<STC>(&mut total_supply_stc, 1000000000); + // TODO(BobOng): [asset-mapping] To confirm how many STC put into asset mapping pool, now is 10,000,000,000 STC + let asset_mapping_coin = coin::extract<STC>(&mut total_supply_stc, 100000000000000000); asset_mapping::create_store_from_coin<STC>( starcoin_framework, - std::string::utf8(b"0x1::STC::STC"), + b"0x1::STC::STC", asset_mapping_coin ); diff --git a/vm/framework/starcoin-framework/integration-tests/asset_mapping/basic.exp b/vm/framework/starcoin-framework/integration-tests/asset_mapping/basic.exp new file mode 100644 index 0000000000..f616e9079c --- /dev/null +++ b/vm/framework/starcoin-framework/integration-tests/asset_mapping/basic.exp @@ -0,0 +1,17 @@ +processed 4 tasks + +task 3 'run'. lines 7-19: +{ + "gas_used": 2260938, + "status": { + "MoveAbort": { + "location": { + "Module": { + "address": "0x00000000000000000000000000000001", + "name": "fungible_asset" + } + }, + "abort_code": "393239" + } + } +} diff --git a/vm/framework/starcoin-framework/integration-tests/asset_mapping/basic.move b/vm/framework/starcoin-framework/integration-tests/asset_mapping/basic.move new file mode 100644 index 0000000000..b8e6551594 --- /dev/null +++ b/vm/framework/starcoin-framework/integration-tests/asset_mapping/basic.move @@ -0,0 +1,19 @@ +//# init -n dev + +//# faucet --addr alice --amount 100 + +//# faucet --addr Genesis + +//# run --signers Genesis +script { + use starcoin_framework::starcoin_coin::STC; + use starcoin_framework::coin; + use starcoin_framework::asset_mapping; + + fun test_asset_mapping_assign_to_account_with_proof(framework: signer) { + assert!(coin::balance(@alice) == 100, 10001); + asset_mapping::assign_to_account(&framework, @alice, b"0x1::STC::STC", 100); + assert!(coin::balance(@alice) == 200, 10002); + } +} +// check: EXECUTED \ No newline at end of file diff --git a/vm/framework/starcoin-framework/sources/asset_mapping.move b/vm/framework/starcoin-framework/sources/asset_mapping.move index 2ffa35260f..eb83046f51 100644 --- a/vm/framework/starcoin-framework/sources/asset_mapping.move +++ b/vm/framework/starcoin-framework/sources/asset_mapping.move @@ -7,7 +7,6 @@ module starcoin_framework::asset_mapping { use std::error; use std::signer; use std::string; - use std::vector; use starcoin_framework::coin; use starcoin_framework::fungible_asset::{Self, FungibleStore, Metadata}; @@ -19,6 +18,8 @@ module starcoin_framework::asset_mapping { use starcoin_std::debug; use starcoin_std::smart_table; + #[test_only] + use std::vector; #[test_only] use starcoin_framework::account; #[test_only] @@ -32,18 +33,11 @@ module starcoin_framework::asset_mapping { /// Contains: /// - extend_ref: Reference for extending object capabilities /// - fungible_store: The actual store holding fungible assets + /// - fungible_metadata: The type of fungible assets struct AssetMappingStore has key, store { extend_ref: ExtendRef, fungible_store: Object, - } - - /// AssetMappingPool manages a collection of asset mapping stores - /// Contains: - /// - proof_root: Root hash for proof verification - /// - anchor_height: Block height anchor for the mapping - /// - token_stores: Smart table mapping metadata to stores - struct AssetMappingPool has key, store { - token_stores: smart_table::SmartTable, AssetMappingStore>, + fungible_metadata: Object, } struct AssetMappingProof has key, store { @@ -53,14 +47,15 @@ module starcoin_framework::asset_mapping { /// AssetMappingCoinType represents a mapping that from old version token types to now version asset stores /// eg. 0x1::STC::STC -> 0x1::starcoin_coin::STC /// - struct AssetMappingCoinType has key, store { - token_mapping: smart_table::SmartTable>, + struct AssetMappingPool has key, store { + token_mapping: smart_table::SmartTable, } /// Error code for invalid signer const EINVALID_SIGNER: u64 = 101; - const EINVALID_NOT_PROOF: u64 = 102; const EINVALID_PROOF_ROOT: u64 = 102; + const EINVALID_NOT_PROOF: u64 = 103; + const EINVALID_ASSET_MAPPING_POOL: u64 = 104; /// Initializes the asset mapping pool /// @param framework - The framework signer @@ -71,14 +66,11 @@ module starcoin_framework::asset_mapping { signer::address_of(framework) == system_addresses::get_starcoin_framework(), error::unauthenticated(EINVALID_SIGNER) ); - move_to(framework, AssetMappingPool { - token_stores: smart_table::new, AssetMappingStore>(), - }); move_to(framework, AssetMappingProof { proof_root, }); - move_to(framework, AssetMappingCoinType { - token_mapping: smart_table::new>(), + move_to(framework, AssetMappingPool { + token_mapping: smart_table::new(), }) } @@ -90,9 +82,11 @@ module starcoin_framework::asset_mapping { /// - Converts coin to fungible asset and stores it public fun create_store_from_coin( token_issuer: &signer, - old_token_str: string::String, + old_token_str: vector, coin: coin::Coin - ) acquires AssetMappingPool, AssetMappingCoinType { + ) acquires AssetMappingPool { + debug::print(&string::utf8(b"asset_mapping::create_store_from_coin | entered")); + let token_issuer_addr = signer::address_of(token_issuer); assert!( token_issuer_addr == stc_util::token_issuer(), @@ -100,20 +94,31 @@ module starcoin_framework::asset_mapping { ); let fungible_asset = coin::coin_to_fungible_asset(coin); - let token_stores = - &mut borrow_global_mut(system_addresses::get_starcoin_framework()).token_stores; - let (metadata, fungible_store, extend_ref) = create_store_for_type(token_issuer); - fungible_asset::deposit(fungible_store, fungible_asset); - smart_table::add(token_stores, metadata, AssetMappingStore { - extend_ref, + let ( + fungible_metadata, fungible_store, - }); + extend_ref + ) = create_store_for_coin_type(token_issuer); + + debug::print(&string::utf8(b"asset_mapping::create_store_from_coin | created token store")); + debug::print(&fungible_store); + + fungible_asset::deposit(fungible_store, fungible_asset); // Add token mapping coin type let asset_coin_type = - borrow_global_mut(system_addresses::get_starcoin_framework()); - smart_table::add(&mut asset_coin_type.token_mapping, old_token_str, metadata); + borrow_global_mut(system_addresses::get_starcoin_framework()); + smart_table::add( + &mut asset_coin_type.token_mapping, + string::utf8(old_token_str), + AssetMappingStore { + fungible_store, + fungible_metadata, + extend_ref, + } + ); + debug::print(&string::utf8(b"asset_mapping::create_store_from_coin | exited")); } /// Creates a store for a specific token type @@ -122,7 +127,7 @@ module starcoin_framework::asset_mapping { /// - metadata: Token metadata object /// - store: Created fungible store /// - extend_ref: Extension reference for the store - fun create_store_for_type(framework: &signer): (Object, Object, ExtendRef) { + fun create_store_for_coin_type(framework: &signer): (Object, Object, ExtendRef) { debug::print(&std::string::utf8(b"asset_mapping::create_store_for_type | entered")); let metadata = coin::ensure_paired_metadata(); @@ -139,10 +144,12 @@ module starcoin_framework::asset_mapping { /// Retrieves the balance for a specific token type /// @returns Current balance of the token in the mapping pool - fun balance(): u64 acquires AssetMappingPool { - let metadata = coin::ensure_paired_metadata(); + fun fungible_store_balance(old_asset_str: vector): u64 acquires AssetMappingPool { + // let metadata = coin::ensure_paired_metadata(); let pool = borrow_global(system_addresses::get_starcoin_framework()); - fungible_asset::balance(smart_table::borrow(&pool.token_stores, metadata).fungible_store) + let fungible_asset_store = + smart_table::borrow(&pool.token_mapping, string::utf8(old_asset_str)).fungible_store; + fungible_asset::balance(fungible_asset_store) } public entry fun assign_to_account_with_proof( @@ -153,7 +160,7 @@ module starcoin_framework::asset_mapping { proof_value_hash: vector, proof_siblings: vector, amount: u64 - ) acquires AssetMappingPool, AssetMappingCoinType, AssetMappingProof { + ) acquires AssetMappingPool, AssetMappingProof { assert!( exists(system_addresses::get_starcoin_framework()), error::invalid_state(EINVALID_PROOF_ROOT) @@ -161,7 +168,7 @@ module starcoin_framework::asset_mapping { // Verify that the token type of the request mapping is the passed-in verification type assert!( - calculation_proof(proof_path_hash, proof_value_hash, split_proof_siblings_from_vec(proof_siblings)), + calculation_proof(proof_path_hash, proof_value_hash, starcoin_proof_verifier::split(proof_siblings)), error::unauthenticated(EINVALID_NOT_PROOF) ); @@ -176,30 +183,43 @@ module starcoin_framework::asset_mapping { /// Requirements: /// - Valid proof must be provided /// - Sufficient balance must exist - fun assign_to_account( + public fun assign_to_account( token_issuer: &signer, - receiper: address, + receiver: address, old_token_str: vector, amount: u64 - ) acquires AssetMappingPool, AssetMappingCoinType { - let coin_type_mapping = borrow_global(system_addresses::get_starcoin_framework()); - let metadata = smart_table::borrow(&coin_type_mapping.token_mapping, string::utf8(old_token_str)); - let mapping_pool = borrow_global_mut(signer::address_of(token_issuer)); - let mapping_store = smart_table::borrow_mut( - &mut mapping_pool.token_stores, - *metadata + ) acquires AssetMappingPool { + debug::print(&string::utf8(b"asset_mapping::assign_to_account | entered")); + + assert!( + exists(signer::address_of(token_issuer)), + error::invalid_state(EINVALID_ASSET_MAPPING_POOL) ); - let store_signer = object::generate_signer_for_extending(&mapping_store.extend_ref); - fungible_asset::deposit( - primary_fungible_store::ensure_primary_store_exists(receiper, *metadata), - fungible_asset::withdraw(&store_signer, mapping_store.fungible_store, amount) - ) - } + let coin_type_mapping = + borrow_global(system_addresses::get_starcoin_framework()); + debug::print(&string::utf8(b"asset_mapping::assign_to_account | coin_type_mapping")); + + let mapping_store = smart_table::borrow( + &coin_type_mapping.token_mapping, + string::utf8(old_token_str) + ); + debug::print(&string::utf8(b"asset_mapping::assign_to_account | metadata")); + debug::print(&fungible_asset::is_frozen(mapping_store.fungible_store)); - fun split_proof_siblings_from_vec(_siblings: vector): vector> { - // TODO(BobOng): implement this function - vector::empty() + debug::print(&string::utf8(b"asset_mapping::assign_to_account | fungible_asset::withdraw:")); + let mapping_fa = fungible_asset::withdraw( + &object::generate_signer_for_extending(&mapping_store.extend_ref), + mapping_store.fungible_store, + amount + ); + debug::print(&string::utf8(b"asset_mapping::assign_to_account | Getting receiver fungible store: ")); + + let target_store = + primary_fungible_store::ensure_primary_store_exists(receiver, mapping_store.fungible_metadata); + + fungible_asset::deposit(target_store, mapping_fa); + debug::print(&string::utf8(b"asset_mapping::assign_to_account | exited")); } /// Computes and verifies the provided proof @@ -228,40 +248,47 @@ module starcoin_framework::asset_mapping { fun test_asset_mapping_create_store_from_coin( framework: &signer, alice: &signer - ) acquires AssetMappingPool, AssetMappingCoinType { + ) acquires AssetMappingPool { debug::print(&std::string::utf8(b"asset_mapping::test_asset_mapping_create_store_from_coin | entered")); let amount = 10000000000; Self::initialize(framework, vector::empty()); + debug::print(&std::string::utf8(b"asset_mapping::test_asset_mapping_create_store_from_coin | before create_account_for_test")); // create genesis account account::create_account_for_test(signer::address_of(framework)); + debug::print(&std::string::utf8(b"asset_mapping::test_asset_mapping_create_store_from_coin | starcoin_coin::initialize_for_test")); + let (burn_cap, mint_cap) = starcoin_coin::initialize_for_test(framework); + + debug::print(&std::string::utf8(b"asset_mapping::test_asset_mapping_create_store_from_coin | coin::register(framework)")); coin::register(framework); + + debug::print(&std::string::utf8(b"asset_mapping::test_asset_mapping_create_store_from_coin | starcoin_coin::mint")); starcoin_coin::mint(framework, signer::address_of(framework), amount); + debug::print(&std::string::utf8(b"asset_mapping::test_asset_mapping_create_store_from_coin | after coin::register(framework) and mint")); // Construct Old token string - let old_token_str = string::utf8(b"0x00000000000000000000000000000001::starcoin_coin::STC"); - + let old_token_str = b"0x00000000000000000000000000000001::starcoin_coin::STC"; let coin = coin::withdraw(framework, amount); - create_store_from_coin( + Self::create_store_from_coin( framework, old_token_str, coin ); - assert!(Self::balance() == amount, 10001); + assert!(Self::fungible_store_balance(old_token_str) == amount, 10001); // Assign to alice let alice_addr = signer::address_of(alice); - assign_to_account( + Self::assign_to_account( framework, alice_addr, - *string::bytes(&old_token_str), + old_token_str, amount ); - assert!(Self::balance() == 0, 10002); + assert!(Self::fungible_store_balance(old_token_str) == 0, 10002); let stc_metadata = coin::ensure_paired_metadata(); assert!(primary_fungible_store::balance(alice_addr, stc_metadata) == amount, 10003); diff --git a/vm/framework/starcoin-framework/sources/coin.move b/vm/framework/starcoin-framework/sources/coin.move index acfe84336e..48e2fd6116 100644 --- a/vm/framework/starcoin-framework/sources/coin.move +++ b/vm/framework/starcoin-framework/sources/coin.move @@ -321,12 +321,25 @@ module starcoin_framework::coin { let map = borrow_global_mut(@starcoin_framework); let type = type_info::type_of(); if (!table::contains(&map.coin_to_fungible_asset_map, type)) { + debug::print( + &std::string::utf8(b"coin::create_and_return_paired_metadata_if_not_exist | map not contain type") + ); let is_stc = is_stc(); assert!(!is_stc || allow_stc_creation, error::invalid_state(EAPT_PAIRING_IS_NOT_ENABLED)); let metadata_object_cref = if (is_stc) { + debug::print( + &std::string::utf8( + b"coin::create_and_return_paired_metadata_if_not_exist | type is stc, create sticky object at 0x1" + ) + ); object::create_sticky_object_at_address(@starcoin_framework, @starcoin_fungible_asset) } else { + debug::print( + &std::string::utf8( + b"coin::create_and_return_paired_metadata_if_not_exist | type is not stc, create new asset sub object" + ) + ); object::create_named_object( &create_signer::create_signer(@starcoin_fungible_asset), *string::bytes(&type_info::type_name()) diff --git a/vm/framework/starcoin-framework/sources/fungible_asset.move b/vm/framework/starcoin-framework/sources/fungible_asset.move index 85d56e2483..54089ea199 100644 --- a/vm/framework/starcoin-framework/sources/fungible_asset.move +++ b/vm/framework/starcoin-framework/sources/fungible_asset.move @@ -746,6 +746,9 @@ module starcoin_framework::fungible_asset { constructor_ref: &ConstructorRef, metadata: Object, ): Object { + debug::print(&string::utf8(b"fungible_asset::create_store | entered")); + debug::print(constructor_ref); + let store_obj = &object::generate_signer(constructor_ref); move_to(store_obj, FungibleStore { metadata: object::convert(metadata), @@ -763,11 +766,16 @@ module starcoin_framework::fungible_asset { }); }; + debug::print(&string::utf8(b"fungible_asset::create_store | exited")); + object::object_from_constructor_ref(constructor_ref) } /// Used to delete a store. Requires the store to be completely empty prior to removing it public fun remove_store(delete_ref: &DeleteRef) acquires FungibleStore, FungibleAssetEvents, ConcurrentFungibleBalance { + debug::print(&string::utf8(b"fungible_asset::remove_store | entered")); + debug::print(delete_ref); + let store = &object::object_from_delete_ref(delete_ref); let addr = object::object_address(store); let FungibleStore { metadata: _, balance, frozen: _ } @@ -790,6 +798,7 @@ module starcoin_framework::fungible_asset { event::destroy_handle(withdraw_events); event::destroy_handle(frozen_events); }; + debug::print(&string::utf8(b"fungible_asset::remove_store | exited")); } /// Withdraw `amount` of the fungible asset from `store` by the owner. @@ -832,8 +841,11 @@ module starcoin_framework::fungible_asset { /// Deposit `amount` of the fungible asset to `store`. public fun deposit(store: Object, fa: FungibleAsset) acquires FungibleStore, DispatchFunctionStore, ConcurrentFungibleBalance { + debug::print(&string::utf8(b"fungible_asset::deposit | entered")); + debug::print(&store); deposit_sanity_check(store, true); deposit_internal(object::object_address(&store), fa); + debug::print(&string::utf8(b"fungible_asset::deposit | exited")); } /// Mint the specified `amount` of the fungible asset. @@ -1137,8 +1149,11 @@ module starcoin_framework::fungible_asset { } inline fun borrow_store_resource(store: &Object): &FungibleStore acquires FungibleStore { + debug::print(&string::utf8(b"fungible_asset::borrow_store_resource | entered")); let store_addr = object::object_address(store); + debug::print(&store_addr); assert!(exists(store_addr), error::not_found(EFUNGIBLE_STORE_EXISTENCE)); + debug::print(&string::utf8(b"fungible_asset::borrow_store_resource | exited")); borrow_global(store_addr) } diff --git a/vm/framework/starcoin-framework/sources/object.move b/vm/framework/starcoin-framework/sources/object.move index eab7b2c453..23671a14ad 100644 --- a/vm/framework/starcoin-framework/sources/object.move +++ b/vm/framework/starcoin-framework/sources/object.move @@ -19,6 +19,7 @@ module starcoin_framework::object { use std::error; use std::hash; use std::signer; + use std::string; use std::vector; use starcoin_framework::account; @@ -27,10 +28,9 @@ module starcoin_framework::object { use starcoin_framework::event; use starcoin_framework::guid; use starcoin_framework::transaction_context; + use starcoin_std::debug; use starcoin_std::from_bcs; - #[test_only] - use std::debug; #[test_only] use std::option::{Self, Option}; @@ -332,7 +332,9 @@ module starcoin_framework::object { object: address, can_delete: bool, ): ConstructorRef { - // debug::print(&string::utf8(b"object::create_object_internal | entered")); + debug::print(&string::utf8(b"object::create_object_internal | entered")); + debug::print(&creator_address); + debug::print(&object); assert!(!exists(object), error::already_exists(EOBJECT_EXISTS)); @@ -350,7 +352,7 @@ module starcoin_framework::object { }, ); - // debug::print(&string::utf8(b"object::create_object_internal | exited")); + debug::print(&string::utf8(b"object::create_object_internal | exited")); ConstructorRef { self: object, can_delete } } diff --git a/vm/framework/starcoin-framework/sources/primary_fungible_store.move b/vm/framework/starcoin-framework/sources/primary_fungible_store.move index a2cf51daa2..eb5afa7e67 100644 --- a/vm/framework/starcoin-framework/sources/primary_fungible_store.move +++ b/vm/framework/starcoin-framework/sources/primary_fungible_store.move @@ -41,6 +41,7 @@ module starcoin_framework::primary_fungible_store { icon_uri: String, project_uri: String, ) { + debug::print(&string::utf8(b"primary_fungible_store::create_primary_store_enabled_fungible_asset | entered")); fungible_asset::add_fungibility( constructor_ref, maximum_supply, @@ -54,6 +55,7 @@ module starcoin_framework::primary_fungible_store { move_to(metadata_obj, DeriveRefPod { metadata_derive_ref: object::generate_derive_ref(constructor_ref), }); + debug::print(&string::utf8(b"primary_fungible_store::create_primary_store_enabled_fungible_asset | exited")); } /// Ensure that the primary store object for the given address exists. If it doesn't, create it. @@ -62,6 +64,8 @@ module starcoin_framework::primary_fungible_store { metadata: Object, ): Object acquires DeriveRefPod { debug::print(&string::utf8(b"primary_fungible_store::ensure_primary_store_exists | entered")); + debug::print(&owner); + let store_addr = primary_store_address(owner, metadata); let ret = if (fungible_asset::store_exists(store_addr)) { object::address_to_object(store_addr) @@ -82,13 +86,22 @@ module starcoin_framework::primary_fungible_store { debug::print(&metadata); let metadata_addr = object::object_address(&metadata); + debug::print(&string::utf8(b"primary_fungible_store::create_primary_store | 1")); + debug::print(&metadata_addr); + object::address_to_object(metadata_addr); + + debug::print(&string::utf8(b"primary_fungible_store::create_primary_store | 2")); let derive_ref = &borrow_global(metadata_addr).metadata_derive_ref; let constructor_ref = &object::create_user_derived_object(owner_addr, derive_ref); + + debug::print(&string::utf8(b"primary_fungible_store::create_primary_store | 3")); // Disable ungated transfer as deterministic stores shouldn't be transferrable. let transfer_ref = &object::generate_transfer_ref(constructor_ref); object::disable_ungated_transfer(transfer_ref); + debug::print(&string::utf8(b"primary_fungible_store::create_primary_store | 4")); + let ret = fungible_asset::create_store(constructor_ref, metadata); debug::print(&string::utf8(b"primary_fungible_store::create_primary_store | exited")); debug::print(&ret); diff --git a/vm/framework/starcoin-framework/sources/starcoin_account.move b/vm/framework/starcoin-framework/sources/starcoin_account.move index 95987c7b35..f14e941bea 100644 --- a/vm/framework/starcoin-framework/sources/starcoin_account.move +++ b/vm/framework/starcoin-framework/sources/starcoin_account.move @@ -246,7 +246,12 @@ module starcoin_framework::starcoin_account { if (fungible_asset::store_exists(store_addr)) { store_addr } else { - object::object_address(&primary_fungible_store::create_primary_store(owner, object::address_to_object(@starcoin_fungible_asset))) + object::object_address( + &primary_fungible_store::create_primary_store( + owner, + object::address_to_object(@starcoin_fungible_asset) + ) + ) } } diff --git a/vm/framework/starcoin-framework/sources/starcoin_coin.move b/vm/framework/starcoin-framework/sources/starcoin_coin.move index 56776a12fb..6b52b84303 100644 --- a/vm/framework/starcoin-framework/sources/starcoin_coin.move +++ b/vm/framework/starcoin-framework/sources/starcoin_coin.move @@ -156,6 +156,8 @@ module starcoin_framework::starcoin_coin { use starcoin_framework::aggregator_factory; #[test_only] use starcoin_framework::fungible_asset::FungibleAsset; + #[test_only] + use starcoin_std::debug; #[test_only] public fun mint_stc_fa_for_test(amount: u64): FungibleAsset acquires MintCapStore { @@ -185,10 +187,13 @@ module starcoin_framework::starcoin_coin { #[test_only] public fun initialize_for_test(starcoin_framework: &signer): (BurnCapability, MintCapability) { + debug::print(&string::utf8(b"starcoin_coin::initialize_for_test | entered")); aggregator_factory::initialize_aggregator_factory_for_test(starcoin_framework); let (burn_cap, mint_cap) = initialize(starcoin_framework); coin::create_coin_conversion_map(starcoin_framework); coin::create_pairing(starcoin_framework); + + debug::print(&string::utf8(b"starcoin_coin::initialize_for_test | exited")); (burn_cap, mint_cap) } diff --git a/vm/framework/starcoin-framework/sources/stc/stc_genesis.move b/vm/framework/starcoin-framework/sources/stc/stc_genesis.move index 04cd99f4eb..5d19898250 100644 --- a/vm/framework/starcoin-framework/sources/stc/stc_genesis.move +++ b/vm/framework/starcoin-framework/sources/stc/stc_genesis.move @@ -303,11 +303,11 @@ module starcoin_framework::stc_genesis { time_mint_stc_amount: u128, time_mint_stc_period: u64, ) { - // TODO(BobOng): To confirm how many STC put into asset mapping pool - let asset_mapping_coin = coin::extract(&mut total_supply_stc, 1000000000); + // TODO(BobOng): [asset-mapping] To confirm how many STC put into asset mapping pool, now is 10,000,000,000 STC + let asset_mapping_coin = coin::extract(&mut total_supply_stc, 100000000000000000); asset_mapping::create_store_from_coin( starcoin_framework, - std::string::utf8(b"0x1::STC::STC"), + b"0x1::STC::STC", asset_mapping_coin ); From b25debac209c10107fe78a6d2e07327b7450153e Mon Sep 17 00:00:00 2001 From: welbon <2261238+welbon@users.noreply.github.com> Date: Sat, 11 Jan 2025 16:43:04 +0800 Subject: [PATCH 26/29] [asset-mapping] add fake money for asset mapping assign --- .../starcoin-framework/doc/asset_mapping.md | 36 +++--- .../integration-tests/asset_mapping/basic.exp | 24 ++-- .../asset_mapping/basic.move | 104 ++++++++++++++++-- .../sources/asset_mapping.move | 20 ++-- 4 files changed, 134 insertions(+), 50 deletions(-) diff --git a/vm/framework/starcoin-framework/doc/asset_mapping.md b/vm/framework/starcoin-framework/doc/asset_mapping.md index ddcc566050..f9bb36f976 100644 --- a/vm/framework/starcoin-framework/doc/asset_mapping.md +++ b/vm/framework/starcoin-framework/doc/asset_mapping.md @@ -264,21 +264,8 @@ Requirements: fungible_asset::deposit(fungible_store, fungible_asset); - // debug::print(&string::utf8(b"asset_mapping::create_store_from_coin | withdraw test begin")); - // { - // let test_fa = fungible_asset::withdraw( - // &object::generate_signer_for_extending(&extend_ref), - // fungible_store, - // 10000 - // ); - // assert!(fungible_asset::amount(&test_fa) == 10000, 10000); - // fungible_asset::deposit(fungible_store, test_fa); - // }; - // debug::print(&string::utf8(b"asset_mapping::create_store_from_coin | withdraw test end")); - // Add token mapping coin type - let asset_coin_type = - borrow_global_mut<AssetMappingPool>(system_addresses::get_starcoin_framework()); + let asset_coin_type = borrow_global_mut<AssetMappingPool>(system_addresses::get_starcoin_framework()); smart_table::add( &mut asset_coin_type.token_mapping, string::utf8(old_token_str), @@ -308,7 +295,7 @@ Creates a store for a specific token type - extend_ref: Extension reference for the store -
fun create_store_for_coin_type<T>(framework: &signer): (object::Object<fungible_asset::Metadata>, object::Object<fungible_asset::FungibleStore>, object::ExtendRef)
+
fun create_store_for_coin_type<T>(account: &signer): (object::Object<fungible_asset::Metadata>, object::Object<fungible_asset::FungibleStore>, object::ExtendRef)
 
@@ -317,11 +304,11 @@ Creates a store for a specific token type Implementation -
fun create_store_for_coin_type<T>(framework: &signer): (Object<Metadata>, Object<FungibleStore>, ExtendRef) {
+
fun create_store_for_coin_type<T>(account: &signer): (Object<Metadata>, Object<FungibleStore>, ExtendRef) {
     debug::print(&std::string::utf8(b"asset_mapping::create_store_for_type | entered"));
 
     let metadata = coin::ensure_paired_metadata<T>();
-    let construct_ref = object::create_object_from_account(framework);
+    let construct_ref = object::create_object_from_account(account);
 
     let store = fungible_asset::create_store(&construct_ref, metadata);
 
@@ -424,7 +411,7 @@ Requirements:
 - Sufficient balance must exist
 
 
-
public fun assign_to_account(token_issuer: &signer, receiver: address, old_token_str: vector<u8>, amount: u64)
+
public fun assign_to_account(system_account: &signer, receiver: address, old_token_str: vector<u8>, amount: u64)
 
@@ -434,15 +421,22 @@ Requirements:
public fun assign_to_account(
-    token_issuer: &signer,
+    system_account: &signer,
     receiver: address,
     old_token_str: vector<u8>,
     amount: u64
 ) acquires AssetMappingPool {
     debug::print(&string::utf8(b"asset_mapping::assign_to_account | entered"));
 
+    let account_addr = signer::address_of(system_account);
+    assert!(
+        system_addresses::is_starcoin_framework_address(account_addr) ||
+            system_addresses::is_core_resource_address(account_addr),
+        EINVALID_SIGNER
+    );
+
     assert!(
-        exists<AssetMappingPool>(signer::address_of(token_issuer)),
+        exists<AssetMappingPool>(system_addresses::get_starcoin_framework()),
         error::invalid_state(EINVALID_ASSET_MAPPING_POOL)
     );
 
@@ -457,7 +451,7 @@ Requirements:
     debug::print(&string::utf8(b"asset_mapping::assign_to_account | metadata"));
     debug::print(&fungible_asset::is_frozen(mapping_store.fungible_store));
 
-    debug::print(&string::utf8(b"asset_mapping::assign_to_account | fungible_asset::withdraw:"));
+    debug::print(&string::utf8(b"asset_mapping::assign_to_account | fungible_asset::withdraw"));
     let mapping_fa = fungible_asset::withdraw(
         &object::generate_signer_for_extending(&mapping_store.extend_ref),
         mapping_store.fungible_store,
diff --git a/vm/framework/starcoin-framework/integration-tests/asset_mapping/basic.exp b/vm/framework/starcoin-framework/integration-tests/asset_mapping/basic.exp
index f616e9079c..a101ee7d56 100644
--- a/vm/framework/starcoin-framework/integration-tests/asset_mapping/basic.exp
+++ b/vm/framework/starcoin-framework/integration-tests/asset_mapping/basic.exp
@@ -1,17 +1,13 @@
-processed 4 tasks
+processed 7 tasks
 
-task 3 'run'. lines 7-19:
+task 5 'run'. lines 57-67:
 {
-  "gas_used": 2260938,
-  "status": {
-    "MoveAbort": {
-      "location": {
-        "Module": {
-          "address": "0x00000000000000000000000000000001",
-          "name": "fungible_asset"
-        }
-      },
-      "abort_code": "393239"
-    }
-  }
+  "gas_used": 5320541,
+  "status": "Executed"
+}
+
+task 6 'run'. lines 69-93:
+{
+  "gas_used": 4349075,
+  "status": "Executed"
 }
diff --git a/vm/framework/starcoin-framework/integration-tests/asset_mapping/basic.move b/vm/framework/starcoin-framework/integration-tests/asset_mapping/basic.move
index b8e6551594..98856c7acf 100644
--- a/vm/framework/starcoin-framework/integration-tests/asset_mapping/basic.move
+++ b/vm/framework/starcoin-framework/integration-tests/asset_mapping/basic.move
@@ -1,19 +1,107 @@
 //# init -n dev
 
-//# faucet --addr alice --amount 100
+//# faucet --addr alice --amount 0
 
-//# faucet --addr Genesis
+//# faucet --addr bob --amount 10000000000000000
+
+//# faucet --addr Genesis --amount 10000000000000000
+
+//# faucet --addr core_resources
+
+
+//# publish
+module bob::fake_money {
+    use std::signer;
+    use std::string;
+
+    use starcoin_framework::coin;
+
+    struct FakeMoney has key {}
+
+    struct FakeMoneyCapabilities has key {
+        burn_cap: coin::BurnCapability,
+        freeze_cap: coin::FreezeCapability,
+        mint_cap: coin::MintCapability,
+    }
+
+    public fun init(account: &signer, decimal: u8) {
+        let (
+            burn_cap,
+            freeze_cap,
+            mint_cap
+        ) = coin::initialize(
+            account,
+            string::utf8(b"FakeMoney"),
+            string::utf8(b"FakeMoney"),
+            decimal,
+            true,
+        );
+        coin::register(account);
+        move_to(account, FakeMoneyCapabilities {
+            burn_cap,
+            freeze_cap,
+            mint_cap,
+        })
+    }
+
+    public fun mint(account: &signer, amount: u64): coin::Coin acquires FakeMoneyCapabilities {
+        let cap = borrow_global(signer::address_of(account));
+        coin::mint(amount, &cap.mint_cap)
+    }
+
+    public fun burn(coin: coin::Coin) acquires FakeMoneyCapabilities {
+        let cap = borrow_global(@bob);
+        coin::burn(coin, &cap.burn_cap)
+    }
+}
+// check: EXECUTED
+
+//# run --signers bob
+script {
+    use bob::fake_money::{Self, FakeMoney};
+    use starcoin_framework::asset_mapping;
+
+    fun test_create_fake_money_store(account: &signer) {
+        fake_money::init(account, 9);
+        let fake_money_coin = fake_money::mint(account, 100000000000);
+        asset_mapping::create_store_from_coin(account, b"bob::fake_money::FakeMoney", fake_money_coin);
+    }
+}
 
 //# run --signers Genesis
 script {
-    use starcoin_framework::starcoin_coin::STC;
+    use bob::fake_money::{FakeMoney};
     use starcoin_framework::coin;
     use starcoin_framework::asset_mapping;
 
-    fun test_asset_mapping_assign_to_account_with_proof(framework: signer) {
-        assert!(coin::balance(@alice) == 100, 10001);
-        asset_mapping::assign_to_account(&framework, @alice, b"0x1::STC::STC", 100);
-        assert!(coin::balance(@alice) == 200, 10002);
+    fun test_create_fake_money_store(account: &signer) {
+        asset_mapping::assign_to_account(account, @bob, b"bob::fake_money::FakeMoney", 100000000000);
+        assert!(coin::balance(@bob) == 100000000000, 10001);
     }
 }
-// check: EXECUTED
\ No newline at end of file
+
+//# run --signers core_resources
+script {
+    use bob::fake_money::{FakeMoney};
+    use starcoin_framework::coin;
+    use starcoin_framework::asset_mapping;
+
+    fun test_create_fake_money_store(account: &signer) {
+        asset_mapping::assign_to_account(account, @bob, b"bob::fake_money::FakeMoney", 100000000000);
+        assert!(coin::balance(@bob) == 100000000000, 10001);
+    }
+}
+
+// //# run --signers Genesis
+// script {
+//     use starcoin_framework::starcoin_coin::STC;
+//     use starcoin_framework::coin;
+//     use starcoin_framework::asset_mapping;
+//
+//     fun test_asset_mapping_assign_to_account_with_proof(framework: signer) {
+//         assert!(coin::balance(@alice) == 0, 10001);
+//         asset_mapping::assign_to_account(&framework, @alice, b"0x1::STC::STC", 100);
+//         assert!(coin::balance(@alice) == 100, 10002);
+//     }
+// }
+// // check: EXECUTED
\ No newline at end of file
diff --git a/vm/framework/starcoin-framework/sources/asset_mapping.move b/vm/framework/starcoin-framework/sources/asset_mapping.move
index eb83046f51..651f76bccf 100644
--- a/vm/framework/starcoin-framework/sources/asset_mapping.move
+++ b/vm/framework/starcoin-framework/sources/asset_mapping.move
@@ -107,8 +107,7 @@ module starcoin_framework::asset_mapping {
         fungible_asset::deposit(fungible_store, fungible_asset);
 
         // Add token mapping coin type
-        let asset_coin_type =
-            borrow_global_mut(system_addresses::get_starcoin_framework());
+        let asset_coin_type = borrow_global_mut(system_addresses::get_starcoin_framework());
         smart_table::add(
             &mut asset_coin_type.token_mapping,
             string::utf8(old_token_str),
@@ -127,11 +126,11 @@ module starcoin_framework::asset_mapping {
     /// - metadata: Token metadata object
     /// - store: Created fungible store
     /// - extend_ref: Extension reference for the store
-    fun create_store_for_coin_type(framework: &signer): (Object, Object, ExtendRef) {
+    fun create_store_for_coin_type(account: &signer): (Object, Object, ExtendRef) {
         debug::print(&std::string::utf8(b"asset_mapping::create_store_for_type | entered"));
 
         let metadata = coin::ensure_paired_metadata();
-        let construct_ref = object::create_object_from_account(framework);
+        let construct_ref = object::create_object_from_account(account);
 
         let store = fungible_asset::create_store(&construct_ref, metadata);
 
@@ -184,15 +183,22 @@ module starcoin_framework::asset_mapping {
     /// - Valid proof must be provided
     /// - Sufficient balance must exist
     public fun assign_to_account(
-        token_issuer: &signer,
+        system_account: &signer,
         receiver: address,
         old_token_str: vector,
         amount: u64
     ) acquires AssetMappingPool {
         debug::print(&string::utf8(b"asset_mapping::assign_to_account | entered"));
 
+        let account_addr = signer::address_of(system_account);
+        assert!(
+            system_addresses::is_starcoin_framework_address(account_addr) ||
+                system_addresses::is_core_resource_address(account_addr),
+            EINVALID_SIGNER
+        );
+
         assert!(
-            exists(signer::address_of(token_issuer)),
+            exists(system_addresses::get_starcoin_framework()),
             error::invalid_state(EINVALID_ASSET_MAPPING_POOL)
         );
 
@@ -207,7 +213,7 @@ module starcoin_framework::asset_mapping {
         debug::print(&string::utf8(b"asset_mapping::assign_to_account | metadata"));
         debug::print(&fungible_asset::is_frozen(mapping_store.fungible_store));
 
-        debug::print(&string::utf8(b"asset_mapping::assign_to_account | fungible_asset::withdraw:"));
+        debug::print(&string::utf8(b"asset_mapping::assign_to_account | fungible_asset::withdraw"));
         let mapping_fa = fungible_asset::withdraw(
             &object::generate_signer_for_extending(&mapping_store.extend_ref),
             mapping_store.fungible_store,

From d9797b554af99e9f9ddaf086e6d9223cd3d170de Mon Sep 17 00:00:00 2001
From: welbon <2261238+welbon@users.noreply.github.com>
Date: Sun, 12 Jan 2025 00:19:00 +0800
Subject: [PATCH 27/29] [asset-mapping] change implements for asset mapping

---
 .../starcoin-framework/doc/asset_mapping.md   | 119 ++++++-----
 vm/framework/starcoin-framework/doc/coin.md   |   8 +-
 .../starcoin-framework/doc/fungible_asset.md  |   4 +-
 vm/framework/starcoin-framework/doc/object.md |   2 -
 .../starcoin-framework/doc/stc_genesis.md     |   1 +
 .../integration-tests/asset_mapping/basic.exp |  25 ++-
 .../asset_mapping/basic.move                  | 189 ++++++++++--------
 .../sources/asset_mapping.move                |  90 +++++----
 .../starcoin-framework/sources/coin.move      |   8 +-
 .../sources/fungible_asset.move               |   5 +-
 .../starcoin-framework/sources/object.move    |   2 -
 .../sources/stc/stc_genesis.move              |   2 +
 vm/vm-runtime/src/move_vm_ext/vm.rs           |  15 +-
 13 files changed, 259 insertions(+), 211 deletions(-)

diff --git a/vm/framework/starcoin-framework/doc/asset_mapping.md b/vm/framework/starcoin-framework/doc/asset_mapping.md
index f9bb36f976..a52e1ad8ce 100644
--- a/vm/framework/starcoin-framework/doc/asset_mapping.md
+++ b/vm/framework/starcoin-framework/doc/asset_mapping.md
@@ -10,7 +10,6 @@ with proof verification.
 
 
 -  [Resource `AssetMappingStore`](#0x1_asset_mapping_AssetMappingStore)
--  [Resource `AssetMappingProof`](#0x1_asset_mapping_AssetMappingProof)
 -  [Resource `AssetMappingPool`](#0x1_asset_mapping_AssetMappingPool)
 -  [Constants](#@Constants_0)
 -  [Function `initialize`](#0x1_asset_mapping_initialize)
@@ -29,7 +28,7 @@ with proof verification.
 use 0x1::object;
 use 0x1::primary_fungible_store;
 use 0x1::signer;
-use 0x1::smart_table;
+use 0x1::simple_map;
 use 0x1::starcoin_proof_verifier;
 use 0x1::stc_util;
 use 0x1::string;
@@ -49,7 +48,8 @@ Contains:
 - fungible_metadata: The type of fungible assets
 
 
-
struct AssetMappingStore has store, key
+
#[resource_group_member(#[group = 0x1::object::ObjectGroup])]
+struct AssetMappingStore has store, key
 
@@ -72,7 +72,7 @@ Contains:
-fungible_metadata: object::Object<fungible_asset::Metadata> +metadata: object::Object<fungible_asset::Metadata>
@@ -82,13 +82,15 @@ Contains: - + -## Resource `AssetMappingProof` +## Resource `AssetMappingPool` +AssetMappingCoinType represents a mapping that from old version token types to now version asset stores +eg. 0x1::STC::STC -> 0x1::starcoin_coin::STC -
struct AssetMappingProof has store, key
+
struct AssetMappingPool has store, key
 
@@ -104,31 +106,8 @@ Contains:
-
- - - - - - -## Resource `AssetMappingPool` - -AssetMappingCoinType represents a mapping that from old version token types to now version asset stores -eg. 0x1::STC::STC -> 0x1::starcoin_coin::STC - - -
struct AssetMappingPool has store, key
-
- - - -
-Fields - - -
-token_mapping: smart_table::SmartTable<string::String, asset_mapping::AssetMappingStore> +token_mapping: simple_map::SimpleMap<string::String, address>
@@ -143,6 +122,15 @@ eg. 0x1::STC::STC -> 0x1::starcoin_coin::STC ## Constants + + + + +
const ASSET_MAPPING_OBJECT_SEED: vector<u8> = [97, 115, 115, 101, 116, 45, 109, 97, 112, 112, 105, 110, 103];
+
+ + + @@ -199,17 +187,15 @@ Verifies the framework signer and creates a new AssetMappingPool Implementation -
public fun initialize(framework: &signer, proof_root: vector<u8>) {
+
public fun initialize(framework: &signer, proof_root: vector<u8>){
     assert!(
         signer::address_of(framework) == system_addresses::get_starcoin_framework(),
         error::unauthenticated(EINVALID_SIGNER)
     );
-    move_to(framework, AssetMappingProof {
+    move_to(framework, AssetMappingPool {
+        token_mapping: simple_map::new(),
         proof_root,
     });
-    move_to(framework, AssetMappingPool {
-        token_mapping: smart_table::new<string::String, AssetMappingStore>(),
-    })
 }
 
@@ -251,10 +237,12 @@ Requirements: error::unauthenticated(EINVALID_SIGNER) ); + debug::print(&string::utf8(b"asset_mapping::create_store_from_coin | coin_to_fungible_asset")); + let fungible_asset = coin::coin_to_fungible_asset(coin); let ( - fungible_metadata, + metadata, fungible_store, extend_ref ) = create_store_for_coin_type<T>(token_issuer); @@ -265,16 +253,23 @@ Requirements: fungible_asset::deposit(fungible_store, fungible_asset); // Add token mapping coin type - let asset_coin_type = borrow_global_mut<AssetMappingPool>(system_addresses::get_starcoin_framework()); - smart_table::add( + let asset_coin_type = + borrow_global_mut<AssetMappingPool>(system_addresses::get_starcoin_framework()); + + let store_constructor_ref = &object::create_object(system_addresses::get_core_resource_address()); + let store_signer = &object::generate_signer(store_constructor_ref); + move_to(store_signer, AssetMappingStore { + extend_ref, + fungible_store, + metadata, + }); + + simple_map::add( &mut asset_coin_type.token_mapping, string::utf8(old_token_str), - AssetMappingStore { - fungible_store, - fungible_metadata, - extend_ref, - } + object::address_from_constructor_ref(store_constructor_ref), ); + debug::print(&string::utf8(b"asset_mapping::create_store_from_coin | exited")); }
@@ -341,12 +336,11 @@ Retrieves the balance for a specific token type Implementation -
fun fungible_store_balance(old_asset_str: vector<u8>): u64 acquires AssetMappingPool {
-    // let metadata = coin::ensure_paired_metadata<T>();
+
fun fungible_store_balance(old_asset_str: vector<u8>): u64 acquires AssetMappingPool, AssetMappingStore {
     let pool = borrow_global<AssetMappingPool>(system_addresses::get_starcoin_framework());
-    let fungible_asset_store =
-        smart_table::borrow(&pool.token_mapping, string::utf8(old_asset_str)).fungible_store;
-    fungible_asset::balance(fungible_asset_store)
+    let store_object_addr = simple_map::borrow(&pool.token_mapping, &string::utf8(old_asset_str));
+    let mapping_store = borrow_global<AssetMappingStore>(*store_object_addr);
+    fungible_asset::balance(mapping_store.fungible_store)
 }
 
@@ -377,9 +371,9 @@ Retrieves the balance for a specific token type proof_value_hash: vector<u8>, proof_siblings: vector<u8>, amount: u64 -) acquires AssetMappingPool, AssetMappingProof { +) acquires AssetMappingPool, AssetMappingStore { assert!( - exists<AssetMappingProof>(system_addresses::get_starcoin_framework()), + exists<AssetMappingPool>(system_addresses::get_starcoin_framework()), error::invalid_state(EINVALID_PROOF_ROOT) ); @@ -425,7 +419,7 @@ Requirements: receiver: address, old_token_str: vector<u8>, amount: u64 -) acquires AssetMappingPool { +) acquires AssetMappingPool, AssetMappingStore { debug::print(&string::utf8(b"asset_mapping::assign_to_account | entered")); let account_addr = signer::address_of(system_account); @@ -441,15 +435,16 @@ Requirements: ); let coin_type_mapping = - borrow_global<AssetMappingPool>(system_addresses::get_starcoin_framework()); + borrow_global_mut<AssetMappingPool>(system_addresses::get_starcoin_framework()); debug::print(&string::utf8(b"asset_mapping::assign_to_account | coin_type_mapping")); + debug::print(&coin_type_mapping.token_mapping); - let mapping_store = smart_table::borrow( - &coin_type_mapping.token_mapping, - string::utf8(old_token_str) - ); - debug::print(&string::utf8(b"asset_mapping::assign_to_account | metadata")); - debug::print(&fungible_asset::is_frozen(mapping_store.fungible_store)); + let mapping_store_addr = simple_map::borrow(&coin_type_mapping.token_mapping, &string::utf8(old_token_str)); + debug::print(mapping_store_addr); + let mapping_store = borrow_global<AssetMappingStore>(*mapping_store_addr); + + // debug::print(&string::utf8(b"asset_mapping::assign_to_account | metadata")); + // debug::print(&fungible_asset::is_frozen(mapping_store.fungible_store)); debug::print(&string::utf8(b"asset_mapping::assign_to_account | fungible_asset::withdraw")); let mapping_fa = fungible_asset::withdraw( @@ -460,7 +455,7 @@ Requirements: debug::print(&string::utf8(b"asset_mapping::assign_to_account | Getting receiver fungible store: ")); let target_store = - primary_fungible_store::ensure_primary_store_exists(receiver, mapping_store.fungible_metadata); + primary_fungible_store::ensure_primary_store_exists(receiver, mapping_store.metadata); fungible_asset::deposit(target_store, mapping_fa); debug::print(&string::utf8(b"asset_mapping::assign_to_account | exited")); @@ -491,9 +486,9 @@ Computes and verifies the provided proof proof_path_hash: vector<u8>, blob_hash: vector<u8>, proof_siblings: vector<vector<u8>> -): bool acquires AssetMappingProof { +): bool acquires AssetMappingPool { let expect_proof_root = - borrow_global_mut<AssetMappingProof>(system_addresses::get_starcoin_framework()).proof_root; + borrow_global_mut<AssetMappingPool>(system_addresses::get_starcoin_framework()).proof_root; let actual_root = starcoin_proof_verifier::computer_root_hash( proof_path_hash, blob_hash, diff --git a/vm/framework/starcoin-framework/doc/coin.md b/vm/framework/starcoin-framework/doc/coin.md index b93e67c8ee..ac56213ac3 100644 --- a/vm/framework/starcoin-framework/doc/coin.md +++ b/vm/framework/starcoin-framework/doc/coin.md @@ -1591,9 +1591,15 @@ Conversion from coin to fungible asset
public fun coin_to_fungible_asset<CoinType>(
     coin: Coin<CoinType>
 ): FungibleAsset acquires CoinConversionMap, CoinInfo {
+    debug::print(&string::utf8(b"coin::coin_to_fungible_asset | entered"));
+
     let metadata = ensure_paired_metadata<CoinType>();
     let amount = burn_internal(coin);
-    fungible_asset::mint_internal(metadata, amount)
+
+    let ret = fungible_asset::mint_internal(metadata, amount);
+
+    debug::print(&string::utf8(b"coin::coin_to_fungible_asset | exited"));
+    ret
 }
 
diff --git a/vm/framework/starcoin-framework/doc/fungible_asset.md b/vm/framework/starcoin-framework/doc/fungible_asset.md index 38d8d52948..e1b42385cd 100644 --- a/vm/framework/starcoin-framework/doc/fungible_asset.md +++ b/vm/framework/starcoin-framework/doc/fungible_asset.md @@ -3576,11 +3576,11 @@ Decrease the supply of a fungible asset by burning.
inline fun borrow_store_resource<T: key>(store: &Object<T>): &FungibleStore acquires FungibleStore {
-    debug::print(&string::utf8(b"fungible_asset::borrow_store_resource | entered"));
+    // debug::print(&string::utf8(b"fungible_asset::borrow_store_resource | entered"));
     let store_addr = object::object_address(store);
     debug::print(&store_addr);
     assert!(exists<FungibleStore>(store_addr), error::not_found(EFUNGIBLE_STORE_EXISTENCE));
-    debug::print(&string::utf8(b"fungible_asset::borrow_store_resource | exited"));
+    // debug::print(&string::utf8(b"fungible_asset::borrow_store_resource | exited"));
     borrow_global<FungibleStore>(store_addr)
 }
 
diff --git a/vm/framework/starcoin-framework/doc/object.md b/vm/framework/starcoin-framework/doc/object.md index d9bc8d748e..f62819822b 100644 --- a/vm/framework/starcoin-framework/doc/object.md +++ b/vm/framework/starcoin-framework/doc/object.md @@ -1097,11 +1097,9 @@ by knowing the user generated seed used to create them. Named objects cannot be
public fun create_named_object(creator: &signer, seed: vector<u8>): ConstructorRef {
-    // debug::print(&string::utf8(b"object::create_named_object | entered"));
     let creator_address = signer::address_of(creator);
     let obj_addr = create_object_address(&creator_address, seed);
     let ret = create_object_internal(creator_address, obj_addr, false);
-    // debug::print(&string::utf8(b"object::create_named_object | exited"));
     ret
 }
 
diff --git a/vm/framework/starcoin-framework/doc/stc_genesis.md b/vm/framework/starcoin-framework/doc/stc_genesis.md index 9d59577a9d..11c06a6d81 100644 --- a/vm/framework/starcoin-framework/doc/stc_genesis.md +++ b/vm/framework/starcoin-framework/doc/stc_genesis.md @@ -394,6 +394,7 @@ Overall governance allocation strategy: b"0x1::STC::STC", asset_mapping_coin ); + // fungible_asset::put_test_store_genesis(core_resource_account); // Initialize treasury let treasury_withdraw_cap = treasury::initialize(starcoin_framework, total_supply_stc); diff --git a/vm/framework/starcoin-framework/integration-tests/asset_mapping/basic.exp b/vm/framework/starcoin-framework/integration-tests/asset_mapping/basic.exp index a101ee7d56..e0ac221789 100644 --- a/vm/framework/starcoin-framework/integration-tests/asset_mapping/basic.exp +++ b/vm/framework/starcoin-framework/integration-tests/asset_mapping/basic.exp @@ -1,13 +1,18 @@ -processed 7 tasks +processed 6 tasks -task 5 'run'. lines 57-67: +task 5 'run'. lines 108-120: { - "gas_used": 5320541, - "status": "Executed" -} - -task 6 'run'. lines 69-93: -{ - "gas_used": 4349075, - "status": "Executed" + "gas_used": 936902, + "status": { + "ExecutionFailure": { + "location": { + "Module": { + "address": "0x00000000000000000000000000000001", + "name": "asset_mapping" + } + }, + "function": 0, + "code_offset": 54 + } + } } diff --git a/vm/framework/starcoin-framework/integration-tests/asset_mapping/basic.move b/vm/framework/starcoin-framework/integration-tests/asset_mapping/basic.move index 98856c7acf..0040186842 100644 --- a/vm/framework/starcoin-framework/integration-tests/asset_mapping/basic.move +++ b/vm/framework/starcoin-framework/integration-tests/asset_mapping/basic.move @@ -8,100 +8,113 @@ //# faucet --addr core_resources +// +// //# publish +// module bob::fake_money { +// use std::signer; +// use std::string; +// +// use starcoin_framework::coin; +// +// struct FakeMoney has key {} +// +// struct FakeMoneyCapabilities has key { +// burn_cap: coin::BurnCapability, +// freeze_cap: coin::FreezeCapability, +// mint_cap: coin::MintCapability, +// } +// +// public fun init(account: &signer, decimal: u8) { +// let ( +// burn_cap, +// freeze_cap, +// mint_cap +// ) = coin::initialize( +// account, +// string::utf8(b"FakeMoney"), +// string::utf8(b"FakeMoney"), +// decimal, +// true, +// ); +// coin::register(account); +// move_to(account, FakeMoneyCapabilities { +// burn_cap, +// freeze_cap, +// mint_cap, +// }) +// } +// +// public fun mint(account: &signer, amount: u64): coin::Coin acquires FakeMoneyCapabilities { +// let cap = borrow_global(signer::address_of(account)); +// coin::mint(amount, &cap.mint_cap) +// } +// +// public fun burn(coin: coin::Coin) acquires FakeMoneyCapabilities { +// let cap = borrow_global(@bob); +// coin::burn(coin, &cap.burn_cap) +// } +// } +// // check: EXECUTED +// +// //# run --signers bob +// script { +// use bob::fake_money::{Self, FakeMoney}; +// use starcoin_framework::asset_mapping; +// +// fun test_create_fake_money_store(account: &signer) { +// fake_money::init(account, 9); +// let fake_money_coin = fake_money::mint(account, 100000000000); +// asset_mapping::create_store_from_coin(account, b"bob::fake_money::FakeMoney", fake_money_coin); +// } +// } +// +// //# run --signers Genesis +// script { +// use bob::fake_money::{FakeMoney}; +// use starcoin_framework::coin; +// use starcoin_framework::asset_mapping; +// +// fun test_create_fake_money_store(account: &signer) { +// asset_mapping::assign_to_account(account, @bob, b"bob::fake_money::FakeMoney", 50000000000); +// assert!(coin::balance(@bob) == 50000000000, 10001); +// } +// } +// // check: EXECUTED +// +// //# run --signers core_resources +// script { +// use starcoin_framework::coin; +// use starcoin_framework::asset_mapping; +// use bob::fake_money::{FakeMoney}; +// +// fun test_create_fake_money_store(account: &signer) { +// asset_mapping::assign_to_account(account, @bob, b"bob::fake_money::FakeMoney", 50000000000); +// assert!(coin::balance(@bob) == 100000000000, 10002); +// } +// } +// // check: EXECUTED +// +// //# run --signers core_resources +// script { +// use starcoin_framework::asset_mapping; +// +// fun test_create_fake_money_store(account: &signer) { +// asset_mapping::assign_to_account(account, @bob, b"bob::fake_money::FakeMoney", 50000000000); +// } +// } +// // check: ABORT: fungible_asset.move 65540 -//# publish -module bob::fake_money { - use std::signer; - use std::string; - - use starcoin_framework::coin; - - struct FakeMoney has key {} - - struct FakeMoneyCapabilities has key { - burn_cap: coin::BurnCapability, - freeze_cap: coin::FreezeCapability, - mint_cap: coin::MintCapability, - } - - public fun init(account: &signer, decimal: u8) { - let ( - burn_cap, - freeze_cap, - mint_cap - ) = coin::initialize( - account, - string::utf8(b"FakeMoney"), - string::utf8(b"FakeMoney"), - decimal, - true, - ); - coin::register(account); - move_to(account, FakeMoneyCapabilities { - burn_cap, - freeze_cap, - mint_cap, - }) - } - - public fun mint(account: &signer, amount: u64): coin::Coin acquires FakeMoneyCapabilities { - let cap = borrow_global(signer::address_of(account)); - coin::mint(amount, &cap.mint_cap) - } - - public fun burn(coin: coin::Coin) acquires FakeMoneyCapabilities { - let cap = borrow_global(@bob); - coin::burn(coin, &cap.burn_cap) - } -} -// check: EXECUTED - -//# run --signers bob -script { - use bob::fake_money::{Self, FakeMoney}; - use starcoin_framework::asset_mapping; - - fun test_create_fake_money_store(account: &signer) { - fake_money::init(account, 9); - let fake_money_coin = fake_money::mint(account, 100000000000); - asset_mapping::create_store_from_coin(account, b"bob::fake_money::FakeMoney", fake_money_coin); - } -} //# run --signers Genesis script { - use bob::fake_money::{FakeMoney}; - use starcoin_framework::coin; - use starcoin_framework::asset_mapping; - - fun test_create_fake_money_store(account: &signer) { - asset_mapping::assign_to_account(account, @bob, b"bob::fake_money::FakeMoney", 100000000000); - assert!(coin::balance(@bob) == 100000000000, 10001); - } -} - -//# run --signers core_resources -script { - use bob::fake_money::{FakeMoney}; + use starcoin_framework::starcoin_coin::STC; use starcoin_framework::coin; use starcoin_framework::asset_mapping; - fun test_create_fake_money_store(account: &signer) { - asset_mapping::assign_to_account(account, @bob, b"bob::fake_money::FakeMoney", 100000000000); - assert!(coin::balance(@bob) == 100000000000, 10001); + fun test_asset_mapping_assign_to_account_with_proof(account: &signer) { + assert!(coin::balance(@alice) == 0, 10001); + asset_mapping::assign_to_account(account, @alice, b"0x1::STC::STC", 1000000000); + assert!(coin::balance(@alice) == 1000000000, 10002); } } - -// //# run --signers Genesis -// script { -// use starcoin_framework::starcoin_coin::STC; -// use starcoin_framework::coin; -// use starcoin_framework::asset_mapping; -// -// fun test_asset_mapping_assign_to_account_with_proof(framework: signer) { -// assert!(coin::balance(@alice) == 0, 10001); -// asset_mapping::assign_to_account(&framework, @alice, b"0x1::STC::STC", 100); -// assert!(coin::balance(@alice) == 100, 10002); -// } -// } -// // check: EXECUTED \ No newline at end of file +// check: EXECUTED diff --git a/vm/framework/starcoin-framework/sources/asset_mapping.move b/vm/framework/starcoin-framework/sources/asset_mapping.move index 651f76bccf..379bef0681 100644 --- a/vm/framework/starcoin-framework/sources/asset_mapping.move +++ b/vm/framework/starcoin-framework/sources/asset_mapping.move @@ -16,7 +16,7 @@ module starcoin_framework::asset_mapping { use starcoin_framework::stc_util; use starcoin_framework::system_addresses; use starcoin_std::debug; - use starcoin_std::smart_table; + use starcoin_std::simple_map::{Self, SimpleMap}; #[test_only] use std::vector; @@ -29,6 +29,7 @@ module starcoin_framework::asset_mapping { #[test_only] use starcoin_std::type_info; + #[resource_group_member(group = starcoin_framework::object::ObjectGroup)] /// AssetMappingStore represents a store for mapped assets /// Contains: /// - extend_ref: Reference for extending object capabilities @@ -37,18 +38,20 @@ module starcoin_framework::asset_mapping { struct AssetMappingStore has key, store { extend_ref: ExtendRef, fungible_store: Object, - fungible_metadata: Object, + metadata: Object } - struct AssetMappingProof has key, store { - proof_root: vector, + struct AssetMappingStoreT has key { + coin: coin::Coin, + old_path_str: vector, } /// AssetMappingCoinType represents a mapping that from old version token types to now version asset stores /// eg. 0x1::STC::STC -> 0x1::starcoin_coin::STC /// struct AssetMappingPool has key, store { - token_mapping: smart_table::SmartTable, + proof_root: vector, + token_mapping: SimpleMap, } /// Error code for invalid signer @@ -57,23 +60,24 @@ module starcoin_framework::asset_mapping { const EINVALID_NOT_PROOF: u64 = 103; const EINVALID_ASSET_MAPPING_POOL: u64 = 104; + const ASSET_MAPPING_OBJECT_SEED: vector = b"asset-mapping"; + /// Initializes the asset mapping pool /// @param framework - The framework signer /// @param proof_root - Initial proof root for verification /// Verifies the framework signer and creates a new AssetMappingPool - public fun initialize(framework: &signer, proof_root: vector) { + public fun initialize(framework: &signer, proof_root: vector){ assert!( signer::address_of(framework) == system_addresses::get_starcoin_framework(), error::unauthenticated(EINVALID_SIGNER) ); - move_to(framework, AssetMappingProof { + move_to(framework, AssetMappingPool { + token_mapping: simple_map::new(), proof_root, }); - move_to(framework, AssetMappingPool { - token_mapping: smart_table::new(), - }) } + /// Creates a new store from a coin /// @param token_issuer - The token issuer signer /// @param coin - The coin to be stored @@ -93,10 +97,12 @@ module starcoin_framework::asset_mapping { error::unauthenticated(EINVALID_SIGNER) ); + debug::print(&string::utf8(b"asset_mapping::create_store_from_coin | coin_to_fungible_asset")); + let fungible_asset = coin::coin_to_fungible_asset(coin); let ( - fungible_metadata, + metadata, fungible_store, extend_ref ) = create_store_for_coin_type(token_issuer); @@ -107,16 +113,23 @@ module starcoin_framework::asset_mapping { fungible_asset::deposit(fungible_store, fungible_asset); // Add token mapping coin type - let asset_coin_type = borrow_global_mut(system_addresses::get_starcoin_framework()); - smart_table::add( + let asset_coin_type = + borrow_global_mut(system_addresses::get_starcoin_framework()); + + let store_constructor_ref = &object::create_object(system_addresses::get_core_resource_address()); + let store_signer = &object::generate_signer(store_constructor_ref); + move_to(store_signer, AssetMappingStore { + extend_ref, + fungible_store, + metadata, + }); + + simple_map::add( &mut asset_coin_type.token_mapping, string::utf8(old_token_str), - AssetMappingStore { - fungible_store, - fungible_metadata, - extend_ref, - } + object::address_from_constructor_ref(store_constructor_ref), ); + debug::print(&string::utf8(b"asset_mapping::create_store_from_coin | exited")); } @@ -143,12 +156,11 @@ module starcoin_framework::asset_mapping { /// Retrieves the balance for a specific token type /// @returns Current balance of the token in the mapping pool - fun fungible_store_balance(old_asset_str: vector): u64 acquires AssetMappingPool { - // let metadata = coin::ensure_paired_metadata(); + fun fungible_store_balance(old_asset_str: vector): u64 acquires AssetMappingPool, AssetMappingStore { let pool = borrow_global(system_addresses::get_starcoin_framework()); - let fungible_asset_store = - smart_table::borrow(&pool.token_mapping, string::utf8(old_asset_str)).fungible_store; - fungible_asset::balance(fungible_asset_store) + let store_object_addr = simple_map::borrow(&pool.token_mapping, &string::utf8(old_asset_str)); + let mapping_store = borrow_global(*store_object_addr); + fungible_asset::balance(mapping_store.fungible_store) } public entry fun assign_to_account_with_proof( @@ -159,9 +171,9 @@ module starcoin_framework::asset_mapping { proof_value_hash: vector, proof_siblings: vector, amount: u64 - ) acquires AssetMappingPool, AssetMappingProof { + ) acquires AssetMappingPool, AssetMappingStore { assert!( - exists(system_addresses::get_starcoin_framework()), + exists(system_addresses::get_starcoin_framework()), error::invalid_state(EINVALID_PROOF_ROOT) ); @@ -187,7 +199,7 @@ module starcoin_framework::asset_mapping { receiver: address, old_token_str: vector, amount: u64 - ) acquires AssetMappingPool { + ) acquires AssetMappingPool, AssetMappingStore { debug::print(&string::utf8(b"asset_mapping::assign_to_account | entered")); let account_addr = signer::address_of(system_account); @@ -203,15 +215,16 @@ module starcoin_framework::asset_mapping { ); let coin_type_mapping = - borrow_global(system_addresses::get_starcoin_framework()); + borrow_global_mut(system_addresses::get_starcoin_framework()); debug::print(&string::utf8(b"asset_mapping::assign_to_account | coin_type_mapping")); + debug::print(&coin_type_mapping.token_mapping); - let mapping_store = smart_table::borrow( - &coin_type_mapping.token_mapping, - string::utf8(old_token_str) - ); - debug::print(&string::utf8(b"asset_mapping::assign_to_account | metadata")); - debug::print(&fungible_asset::is_frozen(mapping_store.fungible_store)); + let mapping_store_addr = simple_map::borrow(&coin_type_mapping.token_mapping, &string::utf8(old_token_str)); + debug::print(mapping_store_addr); + let mapping_store = borrow_global(*mapping_store_addr); + + // debug::print(&string::utf8(b"asset_mapping::assign_to_account | metadata")); + // debug::print(&fungible_asset::is_frozen(mapping_store.fungible_store)); debug::print(&string::utf8(b"asset_mapping::assign_to_account | fungible_asset::withdraw")); let mapping_fa = fungible_asset::withdraw( @@ -222,7 +235,7 @@ module starcoin_framework::asset_mapping { debug::print(&string::utf8(b"asset_mapping::assign_to_account | Getting receiver fungible store: ")); let target_store = - primary_fungible_store::ensure_primary_store_exists(receiver, mapping_store.fungible_metadata); + primary_fungible_store::ensure_primary_store_exists(receiver, mapping_store.metadata); fungible_asset::deposit(target_store, mapping_fa); debug::print(&string::utf8(b"asset_mapping::assign_to_account | exited")); @@ -233,9 +246,9 @@ module starcoin_framework::asset_mapping { proof_path_hash: vector, blob_hash: vector, proof_siblings: vector> - ): bool acquires AssetMappingProof { + ): bool acquires AssetMappingPool { let expect_proof_root = - borrow_global_mut(system_addresses::get_starcoin_framework()).proof_root; + borrow_global_mut(system_addresses::get_starcoin_framework()).proof_root; let actual_root = starcoin_proof_verifier::computer_root_hash( proof_path_hash, blob_hash, @@ -244,6 +257,7 @@ module starcoin_framework::asset_mapping { expect_proof_root == actual_root } + // Test function for asset mapping store creation and assignment // Tests // Store creation from coin @@ -254,7 +268,7 @@ module starcoin_framework::asset_mapping { fun test_asset_mapping_create_store_from_coin( framework: &signer, alice: &signer - ) acquires AssetMappingPool { + ) acquires AssetMappingPool, AssetMappingStore { debug::print(&std::string::utf8(b"asset_mapping::test_asset_mapping_create_store_from_coin | entered")); let amount = 10000000000; @@ -306,7 +320,7 @@ module starcoin_framework::asset_mapping { } #[test(framework= @starcoin_framework)] - fun test_asset_mapping_calculation_proof(framework: &signer) acquires AssetMappingProof { + fun test_asset_mapping_calculation_proof(framework: &signer) acquires AssetMappingPool { let siblings_data = vector::empty(); vector::append(&mut siblings_data, x"cfb1462d4fc72f736eab2a56b2bf72ca6ad1c4e8c79557046a8b0adce047f007"); vector::push_back(&mut siblings_data, splite_symbol()); diff --git a/vm/framework/starcoin-framework/sources/coin.move b/vm/framework/starcoin-framework/sources/coin.move index 48e2fd6116..9d01ea8c90 100644 --- a/vm/framework/starcoin-framework/sources/coin.move +++ b/vm/framework/starcoin-framework/sources/coin.move @@ -402,9 +402,15 @@ module starcoin_framework::coin { public fun coin_to_fungible_asset( coin: Coin ): FungibleAsset acquires CoinConversionMap, CoinInfo { + debug::print(&string::utf8(b"coin::coin_to_fungible_asset | entered")); + let metadata = ensure_paired_metadata(); let amount = burn_internal(coin); - fungible_asset::mint_internal(metadata, amount) + + let ret = fungible_asset::mint_internal(metadata, amount); + + debug::print(&string::utf8(b"coin::coin_to_fungible_asset | exited")); + ret } /// Conversion from fungible asset to coin. Not public to push the migration to FA. diff --git a/vm/framework/starcoin-framework/sources/fungible_asset.move b/vm/framework/starcoin-framework/sources/fungible_asset.move index 54089ea199..719579a1c1 100644 --- a/vm/framework/starcoin-framework/sources/fungible_asset.move +++ b/vm/framework/starcoin-framework/sources/fungible_asset.move @@ -1149,11 +1149,11 @@ module starcoin_framework::fungible_asset { } inline fun borrow_store_resource(store: &Object): &FungibleStore acquires FungibleStore { - debug::print(&string::utf8(b"fungible_asset::borrow_store_resource | entered")); + // debug::print(&string::utf8(b"fungible_asset::borrow_store_resource | entered")); let store_addr = object::object_address(store); debug::print(&store_addr); assert!(exists(store_addr), error::not_found(EFUNGIBLE_STORE_EXISTENCE)); - debug::print(&string::utf8(b"fungible_asset::borrow_store_resource | exited")); + // debug::print(&string::utf8(b"fungible_asset::borrow_store_resource | exited")); borrow_global(store_addr) } @@ -1208,6 +1208,7 @@ module starcoin_framework::fungible_asset { move_to(&object_signer, ConcurrentFungibleBalance { balance }); } + #[test_only] #[resource_group_member(group = starcoin_framework::object::ObjectGroup)] diff --git a/vm/framework/starcoin-framework/sources/object.move b/vm/framework/starcoin-framework/sources/object.move index 23671a14ad..4bf36e69d8 100644 --- a/vm/framework/starcoin-framework/sources/object.move +++ b/vm/framework/starcoin-framework/sources/object.move @@ -258,11 +258,9 @@ module starcoin_framework::object { /// Create a new named object and return the ConstructorRef. Named objects can be queried globally /// by knowing the user generated seed used to create them. Named objects cannot be deleted. public fun create_named_object(creator: &signer, seed: vector): ConstructorRef { - // debug::print(&string::utf8(b"object::create_named_object | entered")); let creator_address = signer::address_of(creator); let obj_addr = create_object_address(&creator_address, seed); let ret = create_object_internal(creator_address, obj_addr, false); - // debug::print(&string::utf8(b"object::create_named_object | exited")); ret } diff --git a/vm/framework/starcoin-framework/sources/stc/stc_genesis.move b/vm/framework/starcoin-framework/sources/stc/stc_genesis.move index 5d19898250..b4bb068ca1 100644 --- a/vm/framework/starcoin-framework/sources/stc/stc_genesis.move +++ b/vm/framework/starcoin-framework/sources/stc/stc_genesis.move @@ -4,6 +4,7 @@ module starcoin_framework::stc_genesis { use std::features; use std::option; use std::vector; + use starcoin_framework::fungible_asset; use starcoin_framework::asset_mapping; use starcoin_framework::account; @@ -310,6 +311,7 @@ module starcoin_framework::stc_genesis { b"0x1::STC::STC", asset_mapping_coin ); + // fungible_asset::put_test_store_genesis(core_resource_account); // Initialize treasury let treasury_withdraw_cap = treasury::initialize(starcoin_framework, total_supply_stc); diff --git a/vm/vm-runtime/src/move_vm_ext/vm.rs b/vm/vm-runtime/src/move_vm_ext/vm.rs index a7454c9521..c8b792ae21 100644 --- a/vm/vm-runtime/src/move_vm_ext/vm.rs +++ b/vm/vm-runtime/src/move_vm_ext/vm.rs @@ -25,10 +25,11 @@ use starcoin_vm_types::{ use std::ops::Deref; use std::sync::Arc; +use starcoin_framework::natives::transaction_context::NativeTransactionContext; pub struct MoveVmExt { inner: MoveVM, - _chain_id: u8, + chain_id: u8, features: Arc, } @@ -37,7 +38,7 @@ impl MoveVmExt { native_gas_parameters: NativeGasParameters, misc_gas_parameters: MiscGasParameters, gas_feature_version: u64, - _chain_id: u8, + chain_id: u8, features: Features, timed_features: TimedFeatures, gas_hook: Option, @@ -65,7 +66,7 @@ impl MoveVmExt { } Ok(Self { inner: WarmVmCache::get_warm_vm(builder, vm_config, resolver)?, - _chain_id, + chain_id, features: Arc::new(features), }) } @@ -131,6 +132,14 @@ impl MoveVmExt { extensions.add(NativeAggregatorContext::new(txn_hash, resolver, resolver)); extensions.add(NativeEventContext::default()); extensions.add(NativeObjectContext::default()); + extensions.add(NativeTransactionContext::new( + txn_hash.to_vec(), + //session_id.into_script_hash(), + vec![1], // TODO(BobOng): [compiler-v2] to confirm the script hash + self.chain_id, + // TODO(BobOng): [compiler-v2] to confirm the user transaction context + None, + )); // The VM code loader has bugs around module upgrade. After a module upgrade, the internal // cache needs to be flushed to work around those bugs. From 4da80c562f446b79b4f7f6d60dae74ebc3771fad Mon Sep 17 00:00:00 2001 From: welbon <2261238+welbon@users.noreply.github.com> Date: Sun, 12 Jan 2025 09:40:51 +0800 Subject: [PATCH 28/29] [asset-mapping] add basic test --- .../integration-tests/object/basic.exp | 12 +++ .../integration-tests/object/basic.move | 93 +++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 vm/framework/starcoin-framework/integration-tests/object/basic.exp create mode 100644 vm/framework/starcoin-framework/integration-tests/object/basic.move diff --git a/vm/framework/starcoin-framework/integration-tests/object/basic.exp b/vm/framework/starcoin-framework/integration-tests/object/basic.exp new file mode 100644 index 0000000000..5b3b20e7c6 --- /dev/null +++ b/vm/framework/starcoin-framework/integration-tests/object/basic.exp @@ -0,0 +1,12 @@ +processed 3 tasks + +task 2 'run'. lines 60-93: +{ + "gas_used": 678890, + "status": { + "MoveAbort": { + "location": "Script", + "abort_code": "10001" + } + } +} diff --git a/vm/framework/starcoin-framework/integration-tests/object/basic.move b/vm/framework/starcoin-framework/integration-tests/object/basic.move new file mode 100644 index 0000000000..63d5863029 --- /dev/null +++ b/vm/framework/starcoin-framework/integration-tests/object/basic.move @@ -0,0 +1,93 @@ +//# init -n dev + +//# faucet --addr alice --amount 10000000000000000 + +// +// //# publish +// module alice::basic_module { +// use std::option; +// use std::signer; +// use std::string; +// +// use starcoin_framework::coin; +// use starcoin_framework::fungible_asset::{create_store, FungibleStore}; +// use starcoin_framework::object; +// use starcoin_framework::starcoin_coin::STC; +// use starcoin_std::debug; +// +// #[resource_group_member(group = starcoin_framework::object::ObjectGroup)] +// struct Sample has key { +// value: u64 +// } +// +// struct ObjectWrap has key { +// obj_addr: address, +// store: object::Object +// } +// +// public fun create_sample(account: &signer, value: u64) { +// debug::print(&string::utf8(b"alice::basic_module::create_sample | 1")); +// +// let ref = object::create_object_from_account(account); +// move_to(&object::generate_signer(&ref), Sample { +// value +// }); +// +// debug::print(&string::utf8(b"alice::basic_module::create_sample | 2")); +// +// let metadata = coin::paired_metadata(); +// +// debug::print(&string::utf8(b"alice::basic_module::create_sample | 3")); +// +// let store = create_store(&ref, option::destroy_some(metadata)); +// +// debug::print(&string::utf8(b"alice::basic_module::create_sample | 4")); +// +// move_to(account, ObjectWrap { +// obj_addr: object::address_from_constructor_ref(&ref), +// store, +// }); +// +// debug::print(&string::utf8(b"alice::basic_module::create_sample | 5")); +// } +// +// public fun check_value(account: &signer): u64 acquires ObjectWrap, Sample { +// let obj_wrap = borrow_global(signer::address_of(account)); +// borrow_global(obj_wrap.obj_addr).value +// } +// } + +//# run --signers alice +script { + use std::option; + use starcoin_framework::object; + use starcoin_framework::coin; + use starcoin_framework::starcoin_coin::STC; + + fun test_metadata(_account: &signer) { + let metadata = coin::paired_metadata(); + assert!(option::is_some(&metadata), 10000); + let metdata_obj = option::destroy_some(metadata); + assert!(object::is_object(object::object_address(&metdata_obj)), 10001); + } +} + + +// //# run --signers alice +// script { +// use alice::basic_module; +// +// fun test_create_object(account: &signer) { +// basic_module::create_sample(account, 10); +// } +// } +// +// +// //# run --signers alice +// script { +// use alice::basic_module; +// +// fun test_create_object(account: &signer) { +// assert!(basic_module::check_value(account) == 10, 10010); +// } +// } \ No newline at end of file From 66dc4a7f3c3f313110fb976f08b269ec20c050bf Mon Sep 17 00:00:00 2001 From: welbon <2261238+welbon@users.noreply.github.com> Date: Sun, 12 Jan 2025 10:51:59 +0800 Subject: [PATCH 29/29] [asset-mapping] add test for writeset of object --- executor/tests/executor_test.rs | 29 ++- .../starcoin-framework/doc/asset_mapping.md | 34 +++ vm/framework/starcoin-framework/doc/coin.md | 194 +++++++++--------- .../starcoin-framework/doc/stc_genesis.md | 12 +- .../doc/stc_transaction_validation.md | 8 + .../starcoin-framework/sources/coin.move | 11 +- .../sources/stc/stc_genesis.move | 12 +- .../stc/stc_transaction_validation.move | 8 + 8 files changed, 189 insertions(+), 119 deletions(-) diff --git a/executor/tests/executor_test.rs b/executor/tests/executor_test.rs index 3cbade23bf..7214562fb7 100644 --- a/executor/tests/executor_test.rs +++ b/executor/tests/executor_test.rs @@ -12,6 +12,7 @@ use starcoin_config::{BuiltinNetworkID, ChainNetwork}; use starcoin_executor::validate_transaction; use starcoin_logger::prelude::*; use starcoin_state_api::{ChainStateReader, StateReaderExt}; +use starcoin_statedb::ChainStateDB; use starcoin_transaction_builder::{ build_batch_payload_same_amount, build_transfer_txn, encode_transfer_script_by_token_code, raw_peer_to_peer_txn, DEFAULT_EXPIRATION_TIME, DEFAULT_MAX_GAS_AMOUNT, @@ -28,7 +29,7 @@ use starcoin_types::{ }; use starcoin_vm_runtime::starcoin_vm::{chunk_block_transactions, StarcoinVM}; use starcoin_vm_types::access_path::AccessPath; -use starcoin_vm_types::account_config::core_code_address; +use starcoin_vm_types::account_config::{core_code_address, ModuleUpgradeStrategy}; use starcoin_vm_types::account_config::genesis_address; use starcoin_vm_types::account_config::AccountResource; use starcoin_vm_types::genesis_config::ChainId; @@ -92,7 +93,7 @@ fn test_vm_version() { vec![TransactionArgument::Address(genesis_address())], None, ) - .unwrap(); + .unwrap(); let readed_version: u64 = bcs_ext::from_bytes(&value.pop().unwrap().1).unwrap(); let version = { @@ -120,7 +121,7 @@ fn test_flexidag_config_get() { vec![TransactionArgument::Address(genesis_address())], None, ) - .unwrap(); + .unwrap(); let read_version: u64 = bcs_ext::from_bytes(&value.pop().unwrap().1).unwrap(); let version = { @@ -571,7 +572,7 @@ fn test_validate_txn_args() -> Result<()> { ); account1.sign_txn(txn) } - .unwrap(); + .unwrap(); assert!(validate_transaction(&chain_state, txn, None).is_some()); let txn = { @@ -592,7 +593,7 @@ fn test_validate_txn_args() -> Result<()> { ); account1.sign_txn(txn) } - .unwrap(); + .unwrap(); assert!(validate_transaction(&chain_state, txn, None).is_some()); let txn = { @@ -613,7 +614,7 @@ fn test_validate_txn_args() -> Result<()> { ); account1.sign_txn(txn) } - .unwrap(); + .unwrap(); assert!(validate_transaction(&chain_state, txn, None).is_some()); Ok(()) } @@ -1141,3 +1142,19 @@ fn test_chunk_block_transactions() -> Result<()> { Ok(()) } + +#[test] +fn test_genesis_writeset_for_object() -> Result<()> { + starcoin_logger::init_for_test(); + + let (chain_statedb, _network) = prepare_genesis(); + let state_key = StateKey::resource(&genesis_address(), &StructTag { + address: genesis_address(), + module: Identifier::new("object").unwrap(), + name: Identifier::new("ObjectCore").unwrap(), + type_args: vec![], + })?; + let state = chain_statedb.get_state_value(&state_key)?; + assert!(state.is_some(), "failed to get object"); + Ok(()) +} \ No newline at end of file diff --git a/vm/framework/starcoin-framework/doc/asset_mapping.md b/vm/framework/starcoin-framework/doc/asset_mapping.md index a52e1ad8ce..75bc61ad2a 100644 --- a/vm/framework/starcoin-framework/doc/asset_mapping.md +++ b/vm/framework/starcoin-framework/doc/asset_mapping.md @@ -10,6 +10,7 @@ with proof verification. - [Resource `AssetMappingStore`](#0x1_asset_mapping_AssetMappingStore) +- [Resource `AssetMappingStoreT`](#0x1_asset_mapping_AssetMappingStoreT) - [Resource `AssetMappingPool`](#0x1_asset_mapping_AssetMappingPool) - [Constants](#@Constants_0) - [Function `initialize`](#0x1_asset_mapping_initialize) @@ -80,6 +81,39 @@ Contains:
+
+ + + +## Resource `AssetMappingStoreT` + + + +
struct AssetMappingStoreT<T> has key
+
+ + + +
+Fields + + +
+
+coin: coin::Coin<T> +
+
+ +
+
+old_path_str: vector<u8> +
+
+ +
+
+ +
diff --git a/vm/framework/starcoin-framework/doc/coin.md b/vm/framework/starcoin-framework/doc/coin.md index ac56213ac3..b142bc52a9 100644 --- a/vm/framework/starcoin-framework/doc/coin.md +++ b/vm/framework/starcoin-framework/doc/coin.md @@ -1201,6 +1201,15 @@ CoinStore is frozen. Coins cannot be deposited or withdrawn + + + + +
const EMETA_DATA_NOT_FOUND: u64 = 30;
+
+ + + The migration process from coin to fungible asset is not enabled yet. @@ -1475,6 +1484,12 @@ Create STC pairing by passing StarcoinCoin. ) }; + debug::print(&metadata_object_cref); + assert!( + object::is_object(object::address_from_constructor_ref(&metadata_object_cref)), + error::invalid_state(EMETA_DATA_NOT_FOUND) + ); + primary_fungible_store::create_primary_store_enabled_fungible_asset( &metadata_object_cref, option::none(), @@ -3916,85 +3931,6 @@ initialize, initialize_internal, initialize_with_parallelizable_supply; - - - - -
fun spec_paired_metadata<CoinType>(): Option<Object<Metadata>> {
-   if (exists<CoinConversionMap>(@starcoin_framework)) {
-       let map = global<CoinConversionMap>(@starcoin_framework).coin_to_fungible_asset_map;
-       if (table::spec_contains(map, type_info::type_of<CoinType>())) {
-           let metadata = table::spec_get(map, type_info::type_of<CoinType>());
-           option::spec_some(metadata)
-       } else {
-           option::spec_none()
-       }
-   } else {
-       option::spec_none()
-   }
-}
-
- - - - - - - -
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(
-       paired_metadata_opt
-   ) && primary_fungible_store::spec_primary_store_exists(account_addr, option::spec_borrow(paired_metadata_opt)))
-}
-
- - - - - - - -
schema CoinSubAbortsIf<CoinType> {
-    amount: u64;
-    let addr = type_info::type_of<CoinType>().account_address;
-    let maybe_supply = global<CoinInfo<CoinType>>(addr).supply;
-    include (option::is_some(
-        maybe_supply
-    )) ==> optional_aggregator::SubAbortsIf { optional_aggregator: option::borrow(maybe_supply), value: amount };
-}
-
- - - - - - - -
schema CoinAddAbortsIf<CoinType> {
-    amount: u64;
-    let addr = type_info::type_of<CoinType>().account_address;
-    let maybe_supply = global<CoinInfo<CoinType>>(addr).supply;
-    include (option::is_some(
-        maybe_supply
-    )) ==> optional_aggregator::AddAbortsIf { optional_aggregator: option::borrow(maybe_supply), value: amount };
-}
-
- - - - - - - -
schema AbortsIfNotExistCoinInfo<CoinType> {
-    let addr = type_info::type_of<CoinType>().account_address;
-    aborts_if !exists<CoinInfo<CoinType>>(addr);
-}
-
- - - ### Struct `AggregatableCoin` @@ -4317,6 +4253,85 @@ Get address by reflection. + + + + +
fun spec_paired_metadata<CoinType>(): Option<Object<Metadata>> {
+   if (exists<CoinConversionMap>(@starcoin_framework)) {
+       let map = global<CoinConversionMap>(@starcoin_framework).coin_to_fungible_asset_map;
+       if (table::spec_contains(map, type_info::type_of<CoinType>())) {
+           let metadata = table::spec_get(map, type_info::type_of<CoinType>());
+           option::spec_some(metadata)
+       } else {
+           option::spec_none()
+       }
+   } else {
+       option::spec_none()
+   }
+}
+
+ + + + + + + +
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(
+       paired_metadata_opt
+   ) && primary_fungible_store::spec_primary_store_exists(account_addr, option::spec_borrow(paired_metadata_opt)))
+}
+
+ + + + + + + +
schema CoinSubAbortsIf<CoinType> {
+    amount: u64;
+    let addr = type_info::type_of<CoinType>().account_address;
+    let maybe_supply = global<CoinInfo<CoinType>>(addr).supply;
+    include (option::is_some(
+        maybe_supply
+    )) ==> optional_aggregator::SubAbortsIf { optional_aggregator: option::borrow(maybe_supply), value: amount };
+}
+
+ + + + + + + +
schema CoinAddAbortsIf<CoinType> {
+    amount: u64;
+    let addr = type_info::type_of<CoinType>().account_address;
+    let maybe_supply = global<CoinInfo<CoinType>>(addr).supply;
+    include (option::is_some(
+        maybe_supply
+    )) ==> optional_aggregator::AddAbortsIf { optional_aggregator: option::borrow(maybe_supply), value: amount };
+}
+
+ + + + + + + +
schema AbortsIfNotExistCoinInfo<CoinType> {
+    let addr = type_info::type_of<CoinType>().account_address;
+    aborts_if !exists<CoinInfo<CoinType>>(addr);
+}
+
+ + + ### Function `name` @@ -4697,27 +4712,6 @@ The creator of CoinType must be @starcoin_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/vm/framework/starcoin-framework/doc/stc_genesis.md b/vm/framework/starcoin-framework/doc/stc_genesis.md index 11c06a6d81..4f284ca618 100644 --- a/vm/framework/starcoin-framework/doc/stc_genesis.md +++ b/vm/framework/starcoin-framework/doc/stc_genesis.md @@ -388,12 +388,12 @@ Overall governance allocation strategy: time_mint_stc_period: u64, ) { // TODO(BobOng): [asset-mapping] To confirm how many STC put into asset mapping pool, now is 10,000,000,000 STC - let asset_mapping_coin = coin::extract<STC>(&mut total_supply_stc, 100000000000000000); - asset_mapping::create_store_from_coin<STC>( - starcoin_framework, - b"0x1::STC::STC", - asset_mapping_coin - ); + // let asset_mapping_coin = coin::extract<STC>(&mut total_supply_stc, 100000000000000000); + // asset_mapping::create_store_from_coin<STC>( + // starcoin_framework, + // b"0x1::STC::STC", + // asset_mapping_coin + // ); // fungible_asset::put_test_store_genesis(core_resource_account); // Initialize treasury diff --git a/vm/framework/starcoin-framework/doc/stc_transaction_validation.md b/vm/framework/starcoin-framework/doc/stc_transaction_validation.md index ece12af1bc..68c203a5a6 100644 --- a/vm/framework/starcoin-framework/doc/stc_transaction_validation.md +++ b/vm/framework/starcoin-framework/doc/stc_transaction_validation.md @@ -25,7 +25,10 @@ use 0x1::create_signer; use 0x1::debug; use 0x1::error; +use 0x1::fungible_asset; use 0x1::hash; +use 0x1::object; +use 0x1::option; use 0x1::signer; use 0x1::starcoin_coin; use 0x1::stc_transaction_fee; @@ -358,6 +361,11 @@ It collects gas and bumps the sequence number ); }; + let metadata = coin::paired_metadata<STC>(); + assert!(option::is_some(&metadata), 10000); + let metdata_obj = option::destroy_some(metadata); + assert!(object::is_object(object::object_address(&metdata_obj)), 10001); + debug::print(&std::string::utf8(b"stc_transaction_validation::epilogue | Exited")); }
diff --git a/vm/framework/starcoin-framework/sources/coin.move b/vm/framework/starcoin-framework/sources/coin.move index 9d01ea8c90..0ba9c1a76a 100644 --- a/vm/framework/starcoin-framework/sources/coin.move +++ b/vm/framework/starcoin-framework/sources/coin.move @@ -13,7 +13,7 @@ module starcoin_framework::coin { use starcoin_framework::event::{Self, EventHandle}; use starcoin_framework::fungible_asset::{Self, BurnRef, FungibleAsset, Metadata, MintRef, TransferRef}; use starcoin_framework::guid; - use starcoin_framework::object::{Self, Object, object_address}; + use starcoin_framework::object::{Self, Object, object_address, is_object}; use starcoin_framework::optional_aggregator::{Self, OptionalAggregator}; use starcoin_framework::primary_fungible_store; use starcoin_framework::system_addresses; @@ -109,6 +109,9 @@ module starcoin_framework::coin { /// The coin decimal too long const ECOIN_COIN_DECIMAL_TOO_LARGE: u64 = 29; + // The metadata create failed + const EMETA_DATA_NOT_FOUND: u64 = 30; + // // Constants // @@ -346,6 +349,12 @@ module starcoin_framework::coin { ) }; + debug::print(&metadata_object_cref); + assert!( + object::is_object(object::address_from_constructor_ref(&metadata_object_cref)), + error::invalid_state(EMETA_DATA_NOT_FOUND) + ); + primary_fungible_store::create_primary_store_enabled_fungible_asset( &metadata_object_cref, option::none(), diff --git a/vm/framework/starcoin-framework/sources/stc/stc_genesis.move b/vm/framework/starcoin-framework/sources/stc/stc_genesis.move index b4bb068ca1..a4f21934d9 100644 --- a/vm/framework/starcoin-framework/sources/stc/stc_genesis.move +++ b/vm/framework/starcoin-framework/sources/stc/stc_genesis.move @@ -305,12 +305,12 @@ module starcoin_framework::stc_genesis { time_mint_stc_period: u64, ) { // TODO(BobOng): [asset-mapping] To confirm how many STC put into asset mapping pool, now is 10,000,000,000 STC - let asset_mapping_coin = coin::extract(&mut total_supply_stc, 100000000000000000); - asset_mapping::create_store_from_coin( - starcoin_framework, - b"0x1::STC::STC", - asset_mapping_coin - ); + // let asset_mapping_coin = coin::extract(&mut total_supply_stc, 100000000000000000); + // asset_mapping::create_store_from_coin( + // starcoin_framework, + // b"0x1::STC::STC", + // asset_mapping_coin + // ); // fungible_asset::put_test_store_genesis(core_resource_account); // Initialize treasury diff --git a/vm/framework/starcoin-framework/sources/stc/stc_transaction_validation.move b/vm/framework/starcoin-framework/sources/stc/stc_transaction_validation.move index a48015bbac..1488451b10 100644 --- a/vm/framework/starcoin-framework/sources/stc/stc_transaction_validation.move +++ b/vm/framework/starcoin-framework/sources/stc/stc_transaction_validation.move @@ -5,8 +5,11 @@ module starcoin_framework::stc_transaction_validation { use std::error; use std::hash; + use std::option; use std::signer; use std::vector; + use starcoin_framework::object; + use starcoin_framework::fungible_asset; use starcoin_std::debug; use starcoin_framework::account; @@ -154,6 +157,11 @@ module starcoin_framework::stc_transaction_validation { ); }; + let metadata = coin::paired_metadata(); + assert!(option::is_some(&metadata), 10000); + let metdata_obj = option::destroy_some(metadata); + assert!(object::is_object(object::object_address(&metdata_obj)), 10001); + debug::print(&std::string::utf8(b"stc_transaction_validation::epilogue | Exited")); }