Skip to content

Commit

Permalink
[gh-1622] remove resource account in account.move.
Browse files Browse the repository at this point in the history
  • Loading branch information
Feliciss committed May 21, 2024
1 parent eb3cf1a commit 82ab117
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 247 deletions.
95 changes: 94 additions & 1 deletion examples/steal_split/sources/steal_split.move
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,16 @@ module rooch_examples::rooch_examples {
const ErrorBothPlayersDoNotHaveDecisionsSubmitted: u64 = 7;
const ErrorPlayerHasDecisionSubmitted: u64 = 8;

// TODO: remove resource account address
struct ResouceAccountAddress has key {
addr: address
}

// TODO: Account holder holds an account of the resource
struct AccountHolder {
account: Object<Account>,
}

struct State has key {
next_game_id: u128,
games: SimpleMap<u128, Game>,
Expand Down Expand Up @@ -107,9 +113,96 @@ module rooch_examples::rooch_examples {
event_creation_timestamp_in_seconds: u64
}

/// ----------TODO---------- ///
/// Scheme identifier used when hashing an account's address together with a seed to derive the address (not the
/// authentication key) of a resource account. This is an abuse of the notion of a scheme identifier which, for now,
/// serves to domain separate hashes used to derive resource account addresses from hashes used to derive
/// authentication keys. Without such separation, an adversary could create (and get a signer for) a resource account
/// whose address matches an existing address of a MultiEd25519 wallet.
const SCHEME_DERIVE_RESOURCE_ACCOUNT: u8 = 255;

/// A resource account is used to manage resources independent of an account managed by a user.
/// In Rooch a resource account is created based upon the sha3 256 of the source's address and additional seed data.
/// A resource account can only be created once
public fun create_resource_account(source: &signer): (signer, SignerCapability) {
let source_addr = signer::address_of(source);
let seed = account::generate_seed_bytes(&source_addr);
let resource_addr = create_resource_address(&source_addr, seed);
assert!(!is_resource_account(resource_addr), ErrorAccountIsAlreadyResourceAccount);
let resource_signer = if (exists_at(resource_addr)) {
let object_id = account_object_id(resource_addr);
let obj = object::borrow_object<Account>(object_id);
let account = object::borrow<Account>(obj);
assert!(account.sequence_number == 0, ErrorResourceAccountAlreadyUsed);
create_signer(resource_addr)
} else {
create_account_unchecked(resource_addr)
};

move_resource_to<ResourceAccount>(&resource_signer,ResourceAccount {});

let signer_cap = SignerCapability { addr: resource_addr };

account_authentication::init_authentication_keys(&resource_signer);
account_coin_store::init_account_coin_stores(&resource_signer);
(resource_signer, signer_cap)
}

public fun is_resource_account(addr: address): bool {
exists_resource<ResourceAccount>(addr)
}

/// This is a helper function to compute resource addresses. Computation of the address
/// involves the use of a cryptographic hash operation and should be use thoughtfully.
fun create_resource_address(source: &address, seed: vector<u8>): address {
let bytes = bcs::to_bytes(source);
vector::append(&mut bytes, seed);
vector::push_back(&mut bytes, SCHEME_DERIVE_RESOURCE_ACCOUNT);
bcs::to_address(hash::sha3_256(bytes))
}

#[test]
fun test_create_resource_account() {
let alice_addr = @123456;
let alice = create_account_for_testing(alice_addr);
let (resource_account, resource_account_cap) = create_resource_account(&alice);
let signer_cap_addr = get_signer_capability_address(&resource_account_cap);
move_resource_to<CapResponsbility>(
&resource_account,
CapResponsbility {
cap: resource_account_cap
}
);

let resource_addr = signer::address_of(&resource_account);
std::debug::print(&100100);
std::debug::print(&resource_addr);
assert!(resource_addr != signer::address_of(&alice), 106);
assert!(resource_addr == signer_cap_addr, 107);
}

//TODO figure out why this test should failed
#[test(sender=@0x42, resource_account=@0xbb6e573f7feb9d8474ac20813fc086cc3100b8b7d49c246b0f4aee8ea19eaef4)]
#[expected_failure(abort_code = ErrorResourceAccountAlreadyUsed, location = Self)]
fun test_failure_create_resource_account_wrong_sequence_number(sender: address, resource_account: address){
{
create_account_for_testing(resource_account);
increment_sequence_number_internal(resource_account);
};
let sender_signer = create_account_for_testing(sender);
let (signer, cap) = create_resource_account(&sender_signer);
move_resource_to<CapResponsbility>(
&signer,
CapResponsbility {
cap
}
);
}
/// ----------TODO---------- ///

fun init(account: &signer) {
// let source_addr = signer::address_of(account);
let (signer, cap) = account_entry::create_resource_account(account);
let (signer, cap) = create_resource_account(account);
let resource_address = signer::address_of(&signer);

account::move_resource_to(account, ResouceAccountAddress {
Expand Down
94 changes: 5 additions & 89 deletions frameworks/moveos-stdlib/doc/account.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,16 @@


- [Resource `Account`](#0x2_account_Account)
- [Resource `ResourceAccount`](#0x2_account_ResourceAccount)
- [Struct `SignerCapability`](#0x2_account_SignerCapability)
- [Constants](#@Constants_0)
- [Function `create_account_by_system`](#0x2_account_create_account_by_system)
- [Function `create_system_reserved_account`](#0x2_account_create_system_reserved_account)
- [Function `sequence_number`](#0x2_account_sequence_number)
- [Function `increment_sequence_number_for_system`](#0x2_account_increment_sequence_number_for_system)
- [Function `signer_address`](#0x2_account_signer_address)
- [Function `is_resource_account`](#0x2_account_is_resource_account)
- [Function `exists_at`](#0x2_account_exists_at)
- [Function `create_signer_for_system`](#0x2_account_create_signer_for_system)
- [Function `create_signer`](#0x2_account_create_signer)
- [Function `create_resource_account`](#0x2_account_create_resource_account)
- [Function `create_signer_with_capability`](#0x2_account_create_signer_with_capability)
- [Function `get_signer_capability_address`](#0x2_account_get_signer_capability_address)
- [Function `account_object_id`](#0x2_account_account_object_id)
Expand Down Expand Up @@ -62,18 +59,6 @@ It is also used to store the account's resources



<a name="0x2_account_ResourceAccount"></a>

## Resource `ResourceAccount`

ResourceAccount can only be stored under address, not in other structs.


<pre><code><b>struct</b> <a href="account.md#0x2_account_ResourceAccount">ResourceAccount</a> <b>has</b> key
</code></pre>



<a name="0x2_account_SignerCapability"></a>

## Struct `SignerCapability`
Expand Down Expand Up @@ -120,32 +105,12 @@ Account already exists



<a name="0x2_account_ErrorAccountIsAlreadyResourceAccount"></a>

Resource Account can't derive resource account


<pre><code><b>const</b> <a href="account.md#0x2_account_ErrorAccountIsAlreadyResourceAccount">ErrorAccountIsAlreadyResourceAccount</a>: u64 = 6;
</code></pre>



<a name="0x2_account_ErrorAccountNotExists"></a>

Account does not exists


<pre><code><b>const</b> <a href="account.md#0x2_account_ErrorAccountNotExists">ErrorAccountNotExists</a>: u64 = 2;
</code></pre>



<a name="0x2_account_ErrorAddressReserved"></a>

Cannot create account because address is reserved


<pre><code><b>const</b> <a href="account.md#0x2_account_ErrorAddressReserved">ErrorAddressReserved</a>: u64 = 4;
<pre><code><b>const</b> <a href="account.md#0x2_account_ErrorAddressReserved">ErrorAddressReserved</a>: u64 = 3;
</code></pre>


Expand All @@ -155,17 +120,7 @@ Cannot create account because address is reserved
Address to create is not a valid reserved address


<pre><code><b>const</b> <a href="account.md#0x2_account_ErrorNotValidSystemReservedAddress">ErrorNotValidSystemReservedAddress</a>: u64 = 7;
</code></pre>



<a name="0x2_account_ErrorResourceAccountAlreadyUsed"></a>

An attempt to create a resource account on an account that has a committed transaction


<pre><code><b>const</b> <a href="account.md#0x2_account_ErrorResourceAccountAlreadyUsed">ErrorResourceAccountAlreadyUsed</a>: u64 = 5;
<pre><code><b>const</b> <a href="account.md#0x2_account_ErrorNotValidSystemReservedAddress">ErrorNotValidSystemReservedAddress</a>: u64 = 4;
</code></pre>


Expand All @@ -175,7 +130,7 @@ An attempt to create a resource account on an account that has a committed trans
The resource with the given type already exists


<pre><code><b>const</b> <a href="account.md#0x2_account_ErrorResourceAlreadyExists">ErrorResourceAlreadyExists</a>: u64 = 8;
<pre><code><b>const</b> <a href="account.md#0x2_account_ErrorResourceAlreadyExists">ErrorResourceAlreadyExists</a>: u64 = 5;
</code></pre>


Expand All @@ -185,7 +140,7 @@ The resource with the given type already exists
The resource with the given type not exists


<pre><code><b>const</b> <a href="account.md#0x2_account_ErrorResourceNotExists">ErrorResourceNotExists</a>: u64 = 9;
<pre><code><b>const</b> <a href="account.md#0x2_account_ErrorResourceNotExists">ErrorResourceNotExists</a>: u64 = 6;
</code></pre>


Expand All @@ -195,21 +150,7 @@ The resource with the given type not exists
Sequence number exceeds the maximum value for a u64


<pre><code><b>const</b> <a href="account.md#0x2_account_ErrorSequenceNumberTooBig">ErrorSequenceNumberTooBig</a>: u64 = 3;
</code></pre>



<a name="0x2_account_SCHEME_DERIVE_RESOURCE_ACCOUNT"></a>

Scheme identifier used when hashing an account's address together with a seed to derive the address (not the
authentication key) of a resource account. This is an abuse of the notion of a scheme identifier which, for now,
serves to domain separate hashes used to derive resource account addresses from hashes used to derive
authentication keys. Without such separation, an adversary could create (and get a signer for) a resource account
whose address matches an existing address of a MultiEd25519 wallet.


<pre><code><b>const</b> <a href="account.md#0x2_account_SCHEME_DERIVE_RESOURCE_ACCOUNT">SCHEME_DERIVE_RESOURCE_ACCOUNT</a>: u8 = 255;
<pre><code><b>const</b> <a href="account.md#0x2_account_ErrorSequenceNumberTooBig">ErrorSequenceNumberTooBig</a>: u64 = 2;
</code></pre>


Expand Down Expand Up @@ -283,17 +224,6 @@ Return the current sequence number at <code>addr</code>



<a name="0x2_account_is_resource_account"></a>

## Function `is_resource_account`



<pre><code><b>public</b> <b>fun</b> <a href="account.md#0x2_account_is_resource_account">is_resource_account</a>(addr: <b>address</b>): bool
</code></pre>



<a name="0x2_account_exists_at"></a>

## Function `exists_at`
Expand Down Expand Up @@ -327,20 +257,6 @@ Return the current sequence number at <code>addr</code>



<a name="0x2_account_create_resource_account"></a>

## Function `create_resource_account`

A resource account is used to manage resources independent of an account managed by a user.
In Rooch a resource account is created based upon the sha3 256 of the source's address and additional seed data.
A resource account can only be created once


<pre><code><b>public</b> <b>fun</b> <a href="account.md#0x2_account_create_resource_account">create_resource_account</a>(source: &<a href="">signer</a>): (<a href="">signer</a>, <a href="account.md#0x2_account_SignerCapability">account::SignerCapability</a>)
</code></pre>



<a name="0x2_account_create_signer_with_capability"></a>

## Function `create_signer_with_capability`
Expand Down
Loading

0 comments on commit 82ab117

Please sign in to comment.