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