diff --git a/build/StarcoinFramework/BuildInfo.yaml b/build/StarcoinFramework/BuildInfo.yaml index 4fbcde53..7f16c6f0 100644 --- a/build/StarcoinFramework/BuildInfo.yaml +++ b/build/StarcoinFramework/BuildInfo.yaml @@ -312,7 +312,7 @@ compiled_package_info: ? address: "0x00000000000000000000000000000001" name: YieldFarmingV2 : StarcoinFramework - source_digest: 5F36AADE9312D2934E215C4971621A24AF18EA5B56A52D2BE1D8E173174D0F3C + source_digest: 465BD18AAFF08B609377C24DF93A365C461646250126145426395BBBD12FD8CC build_flags: dev_mode: false test_mode: false diff --git a/build/StarcoinFramework/bytecode_modules/Account.mv b/build/StarcoinFramework/bytecode_modules/Account.mv index f13513b1..b197aad8 100644 Binary files a/build/StarcoinFramework/bytecode_modules/Account.mv and b/build/StarcoinFramework/bytecode_modules/Account.mv differ diff --git a/build/StarcoinFramework/docs/Account.md b/build/StarcoinFramework/docs/Account.md index 9c337ccb..826f5009 100644 --- a/build/StarcoinFramework/docs/Account.md +++ b/build/StarcoinFramework/docs/Account.md @@ -36,6 +36,7 @@ The module for the account resource that governs every account - [Function `create_account_with_initial_amount`](#0x1_Account_create_account_with_initial_amount) - [Function `create_account_with_initial_amount_v2`](#0x1_Account_create_account_with_initial_amount_v2) - [Function `create_delegate_account`](#0x1_Account_create_delegate_account) +- [Function `generate_fresh_address`](#0x1_Account_generate_fresh_address) - [Function `deposit_to_self`](#0x1_Account_deposit_to_self) - [Function `deposit`](#0x1_Account_deposit) - [Function `deposit_with_metadata`](#0x1_Account_deposit_with_metadata) @@ -1302,23 +1303,7 @@ Generate an new address and create a new account, then delegate the account and
public fun create_delegate_account(sender: &signer) : (address, SignerCapability) acquires Balance, Account, EventStore {
-    let sender_address = Signer::address_of(sender);
-    let sequence_number = Self::sequence_number(sender_address);
-    // use stc balance as part of seed, just for new address more random.
-    let stc_balance = Self::balance<STC>(sender_address);
-
-    let seed_bytes = BCS::to_bytes(&sender_address);
-    Vector::append(&mut seed_bytes, BCS::to_bytes(&sequence_number));
-    Vector::append(&mut seed_bytes, BCS::to_bytes(&stc_balance));
-
-    let seed_hash = Hash::sha3_256(seed_bytes);
-    let i = 0;
-    let address_bytes = Vector::empty();
-    while (i < ADDRESS_LENGTH) {
-        Vector::push_back(&mut address_bytes, *Vector::borrow(&seed_hash,i));
-        i = i + 1;
-    };
-    let new_address = BCS::to_address(address_bytes);
+    let new_address = generate_fresh_address(sender);
     Self::create_account_with_address<STC>(new_address);
     let new_signer = Self::create_signer(new_address);
     (new_address, Self::remove_signer_capability(&new_signer))
@@ -1339,6 +1324,60 @@ Generate an new address and create a new account, then delegate the account and
 
 
 
+
+
+
+
+## Function `generate_fresh_address`
+
+Generate a fresh address from the sender address and the sender's sequence number, and ensure the generated address is not exists onchain.
+
+
+
public fun generate_fresh_address(sender: &signer): address
+
+ + + +
+Implementation + + +
public fun generate_fresh_address(sender: &signer) : address acquires Balance, Account {
+    let try_times = 0u64;
+    while(true){
+        let sender_address = Signer::address_of(sender);
+        let sequence_number = Self::sequence_number(sender_address);
+        // use stc balance as part of seed, just for new address more random.
+        let stc_balance = Self::balance<STC>(sender_address);
+
+        let seed_bytes = BCS::to_bytes(&sender_address);
+        Vector::append(&mut seed_bytes, BCS::to_bytes(&sequence_number));
+        Vector::append(&mut seed_bytes, BCS::to_bytes(&stc_balance));
+        Vector::append(&mut seed_bytes, BCS::to_bytes(&try_times));
+
+        let seed_hash = Hash::sha3_256(seed_bytes);
+
+        let i = 0;
+        let address_bytes = Vector::empty();
+        while (i < ADDRESS_LENGTH) {
+            Vector::push_back(&mut address_bytes, *Vector::borrow(&seed_hash,i));
+            i = i + 1;
+        };
+        let new_address = BCS::to_address(address_bytes);
+        if (Self::exists_at(new_address)){
+            try_times = try_times + 1;
+            continue
+        }else{
+            return new_address
+        }
+    };
+    //unreachable
+    abort 0
+}
+
+ + +
diff --git a/build/StarcoinFramework/source_maps/Account.mvsm b/build/StarcoinFramework/source_maps/Account.mvsm index 1cbc24c3..543155e5 100644 Binary files a/build/StarcoinFramework/source_maps/Account.mvsm and b/build/StarcoinFramework/source_maps/Account.mvsm differ diff --git a/integration-tests/account/delegate_account.exp b/integration-tests/account/delegate_account.exp index ab8bcdcb..55b9b9d3 100644 --- a/integration-tests/account/delegate_account.exp +++ b/integration-tests/account/delegate_account.exp @@ -2,7 +2,7 @@ processed 7 tasks task 5 'run'. lines 27-44: { - "gas_used": 618395, + "gas_used": 638014, "status": "Executed" } diff --git a/integration-tests/account/delegate_account_retry.exp b/integration-tests/account/delegate_account_retry.exp new file mode 100644 index 00000000..95d7c98c --- /dev/null +++ b/integration-tests/account/delegate_account_retry.exp @@ -0,0 +1,7 @@ +processed 3 tasks + +task 2 'run'. lines 5-26: +{ + "gas_used": 13887841, + "status": "Executed" +} diff --git a/integration-tests/account/delegate_account_retry.move b/integration-tests/account/delegate_account_retry.move new file mode 100644 index 00000000..4fdaa1e3 --- /dev/null +++ b/integration-tests/account/delegate_account_retry.move @@ -0,0 +1,27 @@ +//# init -n dev + +//# faucet --addr alice --amount 2000000000 + +//# run --signers alice + +script { + use StarcoinFramework::Account; + + fun main(sender: signer) { + let (_new_address, signer_cap) = Account::create_delegate_account(&sender); + let new_account_signer = Account::create_signer_with_cap(&signer_cap); + + let (address_0, cap_0) = Account::create_delegate_account(&new_account_signer); + let i = 1; + while(i < 10){ + let (address_i, cap_i) = Account::create_delegate_account(&new_account_signer); + assert!(address_0 != address_i, 1000); + Account::destroy_signer_cap(cap_i); + i = i + 1; + }; + Account::destroy_signer_cap(cap_0); + Account::destroy_signer_cap(signer_cap); + } +} +// check: EXECUTED + diff --git a/integration-tests/daospace/dao_account.exp b/integration-tests/daospace/dao_account.exp index ef37a113..9836ccaf 100644 --- a/integration-tests/daospace/dao_account.exp +++ b/integration-tests/daospace/dao_account.exp @@ -2,7 +2,7 @@ processed 6 tasks task 2 'run'. lines 6-23: { - "gas_used": 858490, + "gas_used": 878109, "status": "Executed" } @@ -14,7 +14,7 @@ task 3 'run'. lines 28-40: task 4 'run'. lines 42-51: { - "gas_used": 733860, + "gas_used": 753479, "status": { "MoveAbort": { "location": { @@ -30,7 +30,7 @@ task 4 'run'. lines 42-51: task 5 'run'. lines 53-61: { - "gas_used": 732629, + "gas_used": 752248, "status": { "MoveAbort": { "location": { diff --git a/sources/Account.move b/sources/Account.move index ba370a60..ffd79eaa 100644 --- a/sources/Account.move +++ b/sources/Account.move @@ -333,28 +333,46 @@ module Account { /// Generate an new address and create a new account, then delegate the account and return the new account address and `SignerCapability` public fun create_delegate_account(sender: &signer) : (address, SignerCapability) acquires Balance, Account, EventStore { - let sender_address = Signer::address_of(sender); - let sequence_number = Self::sequence_number(sender_address); - // use stc balance as part of seed, just for new address more random. - let stc_balance = Self::balance(sender_address); - - let seed_bytes = BCS::to_bytes(&sender_address); - Vector::append(&mut seed_bytes, BCS::to_bytes(&sequence_number)); - Vector::append(&mut seed_bytes, BCS::to_bytes(&stc_balance)); - - let seed_hash = Hash::sha3_256(seed_bytes); - let i = 0; - let address_bytes = Vector::empty(); - while (i < ADDRESS_LENGTH) { - Vector::push_back(&mut address_bytes, *Vector::borrow(&seed_hash,i)); - i = i + 1; - }; - let new_address = BCS::to_address(address_bytes); + let new_address = generate_fresh_address(sender); Self::create_account_with_address(new_address); let new_signer = Self::create_signer(new_address); (new_address, Self::remove_signer_capability(&new_signer)) } + /// Generate a fresh address from the sender address and the sender's sequence number, and ensure the generated address is not exists onchain. + public fun generate_fresh_address(sender: &signer) : address acquires Balance, Account { + let try_times = 0u64; + while(true){ + let sender_address = Signer::address_of(sender); + let sequence_number = Self::sequence_number(sender_address); + // use stc balance as part of seed, just for new address more random. + let stc_balance = Self::balance(sender_address); + + let seed_bytes = BCS::to_bytes(&sender_address); + Vector::append(&mut seed_bytes, BCS::to_bytes(&sequence_number)); + Vector::append(&mut seed_bytes, BCS::to_bytes(&stc_balance)); + Vector::append(&mut seed_bytes, BCS::to_bytes(&try_times)); + + let seed_hash = Hash::sha3_256(seed_bytes); + + let i = 0; + let address_bytes = Vector::empty(); + while (i < ADDRESS_LENGTH) { + Vector::push_back(&mut address_bytes, *Vector::borrow(&seed_hash,i)); + i = i + 1; + }; + let new_address = BCS::to_address(address_bytes); + if (Self::exists_at(new_address)){ + try_times = try_times + 1; + continue + }else{ + return new_address + } + }; + //unreachable + abort 0 + } + spec create_delegate_account { pragma verify = false; //TODO write spec