From 103f3b1aadcb7c00676e6a59d3ab4f2ae22b6705 Mon Sep 17 00:00:00 2001 From: Illia Polosukhin Date: Mon, 14 Sep 2020 09:20:08 -0700 Subject: [PATCH] Adding implicit account creation (#71) * Adding implicit account creation * Update docs * Update comment Co-authored-by: Evgeny Kuzyakov --- specs/DataStructures/Account.md | 28 ++++++++++++++++++- .../RuntimeFeeConfig/ActionCreationConfig.md | 4 +++ specs/RuntimeSpec/Actions.md | 2 ++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/specs/DataStructures/Account.md b/specs/DataStructures/Account.md index fae3d3977..76469d9ea 100644 --- a/specs/DataStructures/Account.md +++ b/specs/DataStructures/Account.md @@ -12,12 +12,15 @@ NEAR Protocol has an account names system. Account ID is similar to a username. - maximum length is 64 - **Account ID** consists of **Account ID parts** separated by `.` - **Account ID part** consists of lowercase alphanumeric symbols separated by either `_` or `-`. +- **Account ID** that is 64 characters long consists of lowercase hex characters is a specific **implicit account ID**. Account names are similar to a domain names. -Anyone can create a top level account (TLA) without separators, e.g. `near`. +Top level account (TLA) like `near`, `com`, `eth` can only be created by `registrar` account (see next section for more details). Only `near` can create `alice.near`. And only `alice.near` can create `app.alice.near` and so on. Note, `near` can NOT create `app.alice.near` directly. +Additionally, there is an implicit account creation path. Account ids, that are 64 character long, can only be created with `AccessKey` that matches account id via `hex` derivation. Allowing to create new key pair - and the sender of funds to this account to actually create an account. + Regex for a full account ID, without checking for length: ```regex @@ -86,6 +89,29 @@ me@google.com // @ is not allowed (it was allowed in the past) abcdefghijklmnopqrstuvwxyz.abcdefghijklmnopqrstuvwxyz.abcdefghijklmnopqrstuvwxyz ``` + +## Implicit account IDs + +Implicit accounts work similarly to Bitcoin/Ethereum accounts. +It allows you to reserve an account ID before it's created by generating a ED25519 key-pair locally. +This key-pair has a public key that maps to the account ID. The account ID is a lowercase hex representation of the public key. +ED25519 Public key is 32 bytes that maps to 64 characters account ID. + +Example: public key in base58 `BGCCDDHfysuuVnaNVtEhhqeT4k9Muyem3Kpgq2U1m9HX` will map to an account ID `98793cd91a3f870fb126f66285808c7e094afcfc4eda8a970f6648cdf0dbd6de`. + +The corresponding secret key allows you to sign transactions on behalf of this account once it's created on chain. + +### Implicit account creation + +An account with implicit account ID can only be created by sending a transaction/receipt with a single `Transfer` action to the implicit account ID receiver: +- The account will be created with the account ID. +- The account will have a new full access key with the ED25519-curve public key of `decode_hex(account_id)` and nonce `0`. +- The account balance will have a transfer balance deposited to it. + +This account can not be created using `CreateAccount` action to avoid being able to hijack the account without having the corresponding private key. + +Once an implicit account is created it acts as a regular account until it's deleted. + ## Account [account]: #account diff --git a/specs/GenesisConfig/RuntimeFeeConfig/ActionCreationConfig.md b/specs/GenesisConfig/RuntimeFeeConfig/ActionCreationConfig.md index 50bcd656b..5019a3c06 100644 --- a/specs/GenesisConfig/RuntimeFeeConfig/ActionCreationConfig.md +++ b/specs/GenesisConfig/RuntimeFeeConfig/ActionCreationConfig.md @@ -38,6 +38,10 @@ _type: Fee_ Base cost of making a transfer. +NOTE: If the account ID is an implicit account ID (64-length hex account ID), then the cost of the transfer fee +will be `transfer_cost + create_account_cost + add_key_cost.full_access_cost`. +This is needed to account for the implicit account creation costs. + ## stake_cost _type: Fee_ diff --git a/specs/RuntimeSpec/Actions.md b/specs/RuntimeSpec/Actions.md index 335c44e5a..94cde78fe 100644 --- a/specs/RuntimeSpec/Actions.md +++ b/specs/RuntimeSpec/Actions.md @@ -35,6 +35,8 @@ for the rest of the actions until `DeleteAccount`. This gives permission by anot pub struct CreateAccountAction {} ``` +If `receiver_id` has length == 64, this account id is considered to be `hex(public_key)`, meaning creation of account only succeeds if followed up with `AddKey(public_key)` action. + **Outcome**: - creates an account with `id` = `receiver_id` - sets Account `storage_usage` to `account_cost` (genesis config)