Skip to content

Commit

Permalink
Onboarding patches (#788)
Browse files Browse the repository at this point in the history
* patch panic on autopay parse

* end user genesis tower state patch

* add changelog md file

* patch tx scripts for account creation to include a proper error if the account already exists.

* change submit_tx to return transaction view on error

* better error reporting for validator account creation

* remove don't send arg for most cli transactions

* build stdlib and document the stdlib.mv hash

* rename miner binary in ol cli

* patch ol start behavior when node is not yet running
  • Loading branch information
0o-de-lally authored Oct 31, 2021
1 parent 36c60c0 commit 3b2e34c
Show file tree
Hide file tree
Showing 47 changed files with 495 additions and 213 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ dev-join: clear fix fix-genesis dev-wizard

dev-wizard:
# REQUIRES there is a genesis.blob in the fixtures/genesis/<version> you are testing
MNEM='${MNEM}' cargo run -p onboard -- val --skip-mining --genesis-ceremony --chain-id 1 --github-org OLSF --repo dev-genesis --upstream-peer http://161.35.13.169:8080
MNEM='${MNEM}' cargo run -p onboard -- val --prebuilt-genesis ${DATA_PATH}/genesis.blob --skip-mining --chain-id 1 --upstream-peer http://64.225.2.108

#### DEVNET RESTART ####
# usually do this on Alice, which has the dev-epoch-archive repo, and dev-genesis
Expand Down
24 changes: 10 additions & 14 deletions language/diem-framework/modules/0L/TowerState.move
Original file line number Diff line number Diff line change
Expand Up @@ -189,32 +189,27 @@ module TowerState {
}

/// This function is called to submit proofs to the chain
/// Note, the sender of this transaction can differ from the signer,
/// to facilitate onboarding
/// Function index: 01
/// Permissions: PUBLIC, ANYONE
public fun commit_state(
miner_sign: &signer,
proof: Proof
) acquires TowerProofHistory, TowerList, TowerStats {

// NOTE: Does not check that the Sender is the Signer.
// Which we must skip for the onboarding transaction.

// Get address, assumes the sender is the signer.
let miner_addr = Signer::address_of(miner_sign);

// Abort if not initialized.
assert(exists<TowerProofHistory>(miner_addr), Errors::not_published(130101));

// Get vdf difficulty constant. Will be different in tests than in production.
let difficulty_constant = Globals::get_vdf_difficulty();
// This may be the 0th proof of an end user that hasn't had tower state initialized
if (!is_init(miner_addr)) {
init_miner_state(miner_sign, &proof.challenge, &proof.solution, proof.difficulty, proof.security);
return
};

// Skip this check on local tests, we need tests to send different difficulties.
if (!Testnet::is_testnet()){
// Get vdf difficulty constant. Will be different in tests than in production.
let difficulty_constant = Globals::get_vdf_difficulty();
assert(&proof.difficulty == &difficulty_constant, Errors::invalid_argument(130102));
};

// Process the proof
verify_and_update_state(miner_addr, proof, true);
}
Expand All @@ -233,7 +228,8 @@ module TowerState {

// Get address, assumes the sender is the signer.
assert(ValidatorConfig::get_operator(miner_addr) == Signer::address_of(operator_sig), Errors::requires_role(130103));
// Abort if not initialized.

// Abort if not initialized. Assumes the validator Owner account already has submitted the 0th miner proof in onboarding.
assert(exists<TowerProofHistory>(miner_addr), Errors::not_published(130104));

// return early if difficulty and security are not correct.
Expand Down Expand Up @@ -262,6 +258,7 @@ module TowerState {
proof: Proof,
steady_state: bool
) acquires TowerProofHistory, TowerList, TowerStats {

let miner_history = borrow_global<TowerProofHistory>(miner_addr);
assert(
miner_history.count_proofs_in_epoch < Globals::get_epoch_mining_thres_upper(),
Expand Down Expand Up @@ -409,7 +406,6 @@ module TowerState {
contiguous_epochs_validating_and_mining: 0u64,
epochs_since_last_account_creation: 0u64,
});

// create the initial proof submission
let proof = Proof {
challenge: *challenge,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,20 @@ module AccountScripts {
use 0x1::GAS::GAS;
use 0x1::ValidatorConfig;
use 0x1::Globals;
use 0x1::VDF;
use 0x1::Errors;

const ACCOUNT_ALREADY_EXISTS: u64 = 0;

public(script) fun create_user_by_coin_tx(
sender: signer,
account: address,
authkey_prefix: vector<u8>,
unscaled_value: u64,
) {
// check if the account already exists.
assert(!DiemAccount::exists_at(account), Errors::invalid_state(ACCOUNT_ALREADY_EXISTS));

// IMPORTANT: the human representation of a value is unscaled. The user which expects to send 10 coins, will input that as an unscaled_value. This script converts it to the Move internal scale by multiplying by COIN_SCALING_FACTOR.
let value = unscaled_value * Globals::get_coin_scaling_factor();
let new_account_address = DiemAccount::create_user_account_with_coin(
Expand Down Expand Up @@ -63,7 +70,13 @@ module AccountScripts {
op_fullnode_network_addresses: vector<u8>,
op_human_name: vector<u8>,
) {
let new_account_address = DiemAccount::create_validator_account_with_proof(

// check if this account exists
let (new_account_address, _) = VDF::extract_address_from_challenge(&challenge);
assert(!DiemAccount::exists_at(new_account_address), Errors::invalid_state(ACCOUNT_ALREADY_EXISTS));


DiemAccount::create_validator_account_with_proof(
&sender,
&challenge,
&solution,
Expand Down
24 changes: 10 additions & 14 deletions language/diem-framework/modules/doc/TowerState.md
Original file line number Diff line number Diff line change
Expand Up @@ -620,8 +620,6 @@ adds <code>tower</code> to list of towers
## Function `commit_state`

This function is called to submit proofs to the chain
Note, the sender of this transaction can differ from the signer,
to facilitate onboarding
Function index: 01
Permissions: PUBLIC, ANYONE

Expand All @@ -639,24 +637,21 @@ Permissions: PUBLIC, ANYONE
miner_sign: &signer,
proof: <a href="TowerState.md#0x1_TowerState_Proof">Proof</a>
) <b>acquires</b> <a href="TowerState.md#0x1_TowerState_TowerProofHistory">TowerProofHistory</a>, <a href="TowerState.md#0x1_TowerState_TowerList">TowerList</a>, <a href="TowerState.md#0x1_TowerState_TowerStats">TowerStats</a> {

// NOTE: Does not check that the Sender is the <a href="../../../../../../move-stdlib/docs/Signer.md#0x1_Signer">Signer</a>.
// Which we must skip for the onboarding transaction.

// Get address, assumes the sender is the signer.
<b>let</b> miner_addr = <a href="../../../../../../move-stdlib/docs/Signer.md#0x1_Signer_address_of">Signer::address_of</a>(miner_sign);

// Abort <b>if</b> not initialized.
<b>assert</b>(<b>exists</b>&lt;<a href="TowerState.md#0x1_TowerState_TowerProofHistory">TowerProofHistory</a>&gt;(miner_addr), <a href="../../../../../../move-stdlib/docs/Errors.md#0x1_Errors_not_published">Errors::not_published</a>(130101));

// Get vdf difficulty constant. Will be different in tests than in production.
<b>let</b> difficulty_constant = <a href="Globals.md#0x1_Globals_get_vdf_difficulty">Globals::get_vdf_difficulty</a>();
// This may be the 0th proof of an end user that hasn't had tower state initialized
<b>if</b> (!<a href="TowerState.md#0x1_TowerState_is_init">is_init</a>(miner_addr)) {
<a href="TowerState.md#0x1_TowerState_init_miner_state">init_miner_state</a>(miner_sign, &proof.challenge, &proof.solution, proof.difficulty, proof.security);
<b>return</b>
};

// Skip this check on local tests, we need tests <b>to</b> send different difficulties.
<b>if</b> (!<a href="Testnet.md#0x1_Testnet_is_testnet">Testnet::is_testnet</a>()){
// Get vdf difficulty constant. Will be different in tests than in production.
<b>let</b> difficulty_constant = <a href="Globals.md#0x1_Globals_get_vdf_difficulty">Globals::get_vdf_difficulty</a>();
<b>assert</b>(&proof.difficulty == &difficulty_constant, <a href="../../../../../../move-stdlib/docs/Errors.md#0x1_Errors_invalid_argument">Errors::invalid_argument</a>(130102));
};

// Process the proof
<a href="TowerState.md#0x1_TowerState_verify_and_update_state">verify_and_update_state</a>(miner_addr, proof, <b>true</b>);
}
Expand Down Expand Up @@ -691,7 +686,8 @@ Permissions: PUBLIC, ANYONE

// Get address, assumes the sender is the signer.
<b>assert</b>(<a href="ValidatorConfig.md#0x1_ValidatorConfig_get_operator">ValidatorConfig::get_operator</a>(miner_addr) == <a href="../../../../../../move-stdlib/docs/Signer.md#0x1_Signer_address_of">Signer::address_of</a>(operator_sig), <a href="../../../../../../move-stdlib/docs/Errors.md#0x1_Errors_requires_role">Errors::requires_role</a>(130103));
// Abort <b>if</b> not initialized.

// Abort <b>if</b> not initialized. Assumes the validator Owner account already has submitted the 0th miner proof in onboarding.
<b>assert</b>(<b>exists</b>&lt;<a href="TowerState.md#0x1_TowerState_TowerProofHistory">TowerProofHistory</a>&gt;(miner_addr), <a href="../../../../../../move-stdlib/docs/Errors.md#0x1_Errors_not_published">Errors::not_published</a>(130104));

// <b>return</b> early <b>if</b> difficulty and security are not correct.
Expand Down Expand Up @@ -737,6 +733,7 @@ Permissions: PUBLIC, ANYONE
proof: <a href="TowerState.md#0x1_TowerState_Proof">Proof</a>,
steady_state: bool
) <b>acquires</b> <a href="TowerState.md#0x1_TowerState_TowerProofHistory">TowerProofHistory</a>, <a href="TowerState.md#0x1_TowerState_TowerList">TowerList</a>, <a href="TowerState.md#0x1_TowerState_TowerStats">TowerStats</a> {

<b>let</b> miner_history = borrow_global&lt;<a href="TowerState.md#0x1_TowerState_TowerProofHistory">TowerProofHistory</a>&gt;(miner_addr);
<b>assert</b>(
miner_history.count_proofs_in_epoch &lt; <a href="Globals.md#0x1_Globals_get_epoch_mining_thres_upper">Globals::get_epoch_mining_thres_upper</a>(),
Expand Down Expand Up @@ -953,7 +950,6 @@ Checks to see if miner submitted enough proofs to be considered compliant
contiguous_epochs_validating_and_mining: 0u64,
epochs_since_last_account_creation: 0u64,
});

// create the initial proof submission
<b>let</b> proof = <a href="TowerState.md#0x1_TowerState_Proof">Proof</a> {
challenge: *challenge,
Expand Down
28 changes: 27 additions & 1 deletion language/diem-framework/modules/doc/ol_account.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,36 @@



- [Constants](#@Constants_0)
- [Function `create_user_by_coin_tx`](#0x1_AccountScripts_create_user_by_coin_tx)
- [Function `create_acc_user`](#0x1_AccountScripts_create_acc_user)
- [Function `create_acc_val`](#0x1_AccountScripts_create_acc_val)


<pre><code><b>use</b> <a href="DiemAccount.md#0x1_DiemAccount">0x1::DiemAccount</a>;
<b>use</b> <a href="../../../../../../move-stdlib/docs/Errors.md#0x1_Errors">0x1::Errors</a>;
<b>use</b> <a href="GAS.md#0x1_GAS">0x1::GAS</a>;
<b>use</b> <a href="Globals.md#0x1_Globals">0x1::Globals</a>;
<b>use</b> <a href="VDF.md#0x1_VDF">0x1::VDF</a>;
<b>use</b> <a href="ValidatorConfig.md#0x1_ValidatorConfig">0x1::ValidatorConfig</a>;
</code></pre>



<a name="@Constants_0"></a>

## Constants


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



<pre><code><b>const</b> <a href="ol_account.md#0x1_AccountScripts_ACCOUNT_ALREADY_EXISTS">ACCOUNT_ALREADY_EXISTS</a>: u64 = 0;
</code></pre>



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

## Function `create_user_by_coin_tx`
Expand All @@ -39,6 +56,9 @@
authkey_prefix: vector&lt;u8&gt;,
unscaled_value: u64,
) {
// check <b>if</b> the account already <b>exists</b>.
<b>assert</b>(!<a href="DiemAccount.md#0x1_DiemAccount_exists_at">DiemAccount::exists_at</a>(account), <a href="../../../../../../move-stdlib/docs/Errors.md#0x1_Errors_invalid_state">Errors::invalid_state</a>(<a href="ol_account.md#0x1_AccountScripts_ACCOUNT_ALREADY_EXISTS">ACCOUNT_ALREADY_EXISTS</a>));

// IMPORTANT: the human representation of a value is unscaled. The user which expects <b>to</b> send 10 coins, will input that <b>as</b> an unscaled_value. This <b>script</b> converts it <b>to</b> the Move internal scale by multiplying by COIN_SCALING_FACTOR.
<b>let</b> value = unscaled_value * <a href="Globals.md#0x1_Globals_get_coin_scaling_factor">Globals::get_coin_scaling_factor</a>();
<b>let</b> new_account_address = <a href="DiemAccount.md#0x1_DiemAccount_create_user_account_with_coin">DiemAccount::create_user_account_with_coin</a>(
Expand Down Expand Up @@ -125,7 +145,13 @@
op_fullnode_network_addresses: vector&lt;u8&gt;,
op_human_name: vector&lt;u8&gt;,
) {
<b>let</b> new_account_address = <a href="DiemAccount.md#0x1_DiemAccount_create_validator_account_with_proof">DiemAccount::create_validator_account_with_proof</a>(

// check <b>if</b> this account <b>exists</b>
<b>let</b> (new_account_address, _) = <a href="VDF.md#0x1_VDF_extract_address_from_challenge">VDF::extract_address_from_challenge</a>(&challenge);
<b>assert</b>(!<a href="DiemAccount.md#0x1_DiemAccount_exists_at">DiemAccount::exists_at</a>(new_account_address), <a href="../../../../../../move-stdlib/docs/Errors.md#0x1_Errors_invalid_state">Errors::invalid_state</a>(<a href="ol_account.md#0x1_AccountScripts_ACCOUNT_ALREADY_EXISTS">ACCOUNT_ALREADY_EXISTS</a>));


<a href="DiemAccount.md#0x1_DiemAccount_create_validator_account_with_proof">DiemAccount::create_validator_account_with_proof</a>(
&sender,
&challenge,
&solution,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -620,8 +620,6 @@ adds <code>tower</code> to list of towers
## Function `commit_state`

This function is called to submit proofs to the chain
Note, the sender of this transaction can differ from the signer,
to facilitate onboarding
Function index: 01
Permissions: PUBLIC, ANYONE

Expand All @@ -639,24 +637,21 @@ Permissions: PUBLIC, ANYONE
miner_sign: &signer,
proof: <a href="TowerState.md#0x1_TowerState_Proof">Proof</a>
) <b>acquires</b> <a href="TowerState.md#0x1_TowerState_TowerProofHistory">TowerProofHistory</a>, <a href="TowerState.md#0x1_TowerState_TowerList">TowerList</a>, <a href="TowerState.md#0x1_TowerState_TowerStats">TowerStats</a> {

// NOTE: Does not check that the Sender is the <a href="../../../../../../move-stdlib/docs/Signer.md#0x1_Signer">Signer</a>.
// Which we must skip for the onboarding transaction.

// Get address, assumes the sender is the signer.
<b>let</b> miner_addr = <a href="../../../../../../move-stdlib/docs/Signer.md#0x1_Signer_address_of">Signer::address_of</a>(miner_sign);

// Abort <b>if</b> not initialized.
<b>assert</b>(<b>exists</b>&lt;<a href="TowerState.md#0x1_TowerState_TowerProofHistory">TowerProofHistory</a>&gt;(miner_addr), <a href="../../../../../../move-stdlib/docs/Errors.md#0x1_Errors_not_published">Errors::not_published</a>(130101));

// Get vdf difficulty constant. Will be different in tests than in production.
<b>let</b> difficulty_constant = <a href="Globals.md#0x1_Globals_get_vdf_difficulty">Globals::get_vdf_difficulty</a>();
// This may be the 0th proof of an end user that hasn't had tower state initialized
<b>if</b> (!<a href="TowerState.md#0x1_TowerState_is_init">is_init</a>(miner_addr)) {
<a href="TowerState.md#0x1_TowerState_init_miner_state">init_miner_state</a>(miner_sign, &proof.challenge, &proof.solution, proof.difficulty, proof.security);
<b>return</b>
};

// Skip this check on local tests, we need tests <b>to</b> send different difficulties.
<b>if</b> (!<a href="Testnet.md#0x1_Testnet_is_testnet">Testnet::is_testnet</a>()){
// Get vdf difficulty constant. Will be different in tests than in production.
<b>let</b> difficulty_constant = <a href="Globals.md#0x1_Globals_get_vdf_difficulty">Globals::get_vdf_difficulty</a>();
<b>assert</b>(&proof.difficulty == &difficulty_constant, <a href="../../../../../../move-stdlib/docs/Errors.md#0x1_Errors_invalid_argument">Errors::invalid_argument</a>(130102));
};

// Process the proof
<a href="TowerState.md#0x1_TowerState_verify_and_update_state">verify_and_update_state</a>(miner_addr, proof, <b>true</b>);
}
Expand Down Expand Up @@ -691,7 +686,8 @@ Permissions: PUBLIC, ANYONE

// Get address, assumes the sender is the signer.
<b>assert</b>(<a href="ValidatorConfig.md#0x1_ValidatorConfig_get_operator">ValidatorConfig::get_operator</a>(miner_addr) == <a href="../../../../../../move-stdlib/docs/Signer.md#0x1_Signer_address_of">Signer::address_of</a>(operator_sig), <a href="../../../../../../move-stdlib/docs/Errors.md#0x1_Errors_requires_role">Errors::requires_role</a>(130103));
// Abort <b>if</b> not initialized.

// Abort <b>if</b> not initialized. Assumes the validator Owner account already has submitted the 0th miner proof in onboarding.
<b>assert</b>(<b>exists</b>&lt;<a href="TowerState.md#0x1_TowerState_TowerProofHistory">TowerProofHistory</a>&gt;(miner_addr), <a href="../../../../../../move-stdlib/docs/Errors.md#0x1_Errors_not_published">Errors::not_published</a>(130104));

// <b>return</b> early <b>if</b> difficulty and security are not correct.
Expand Down Expand Up @@ -737,6 +733,7 @@ Permissions: PUBLIC, ANYONE
proof: <a href="TowerState.md#0x1_TowerState_Proof">Proof</a>,
steady_state: bool
) <b>acquires</b> <a href="TowerState.md#0x1_TowerState_TowerProofHistory">TowerProofHistory</a>, <a href="TowerState.md#0x1_TowerState_TowerList">TowerList</a>, <a href="TowerState.md#0x1_TowerState_TowerStats">TowerStats</a> {

<b>let</b> miner_history = borrow_global&lt;<a href="TowerState.md#0x1_TowerState_TowerProofHistory">TowerProofHistory</a>&gt;(miner_addr);
<b>assert</b>(
miner_history.count_proofs_in_epoch &lt; <a href="Globals.md#0x1_Globals_get_epoch_mining_thres_upper">Globals::get_epoch_mining_thres_upper</a>(),
Expand Down Expand Up @@ -953,7 +950,6 @@ Checks to see if miner submitted enough proofs to be considered compliant
contiguous_epochs_validating_and_mining: 0u64,
epochs_since_last_account_creation: 0u64,
});

// create the initial proof submission
<b>let</b> proof = <a href="TowerState.md#0x1_TowerState_Proof">Proof</a> {
challenge: *challenge,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,36 @@



- [Constants](#@Constants_0)
- [Function `create_user_by_coin_tx`](#0x1_AccountScripts_create_user_by_coin_tx)
- [Function `create_acc_user`](#0x1_AccountScripts_create_acc_user)
- [Function `create_acc_val`](#0x1_AccountScripts_create_acc_val)


<pre><code><b>use</b> <a href="DiemAccount.md#0x1_DiemAccount">0x1::DiemAccount</a>;
<b>use</b> <a href="../../../../../../move-stdlib/docs/Errors.md#0x1_Errors">0x1::Errors</a>;
<b>use</b> <a href="GAS.md#0x1_GAS">0x1::GAS</a>;
<b>use</b> <a href="Globals.md#0x1_Globals">0x1::Globals</a>;
<b>use</b> <a href="VDF.md#0x1_VDF">0x1::VDF</a>;
<b>use</b> <a href="ValidatorConfig.md#0x1_ValidatorConfig">0x1::ValidatorConfig</a>;
</code></pre>



<a name="@Constants_0"></a>

## Constants


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



<pre><code><b>const</b> <a href="ol_account.md#0x1_AccountScripts_ACCOUNT_ALREADY_EXISTS">ACCOUNT_ALREADY_EXISTS</a>: u64 = 0;
</code></pre>



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

## Function `create_user_by_coin_tx`
Expand All @@ -39,6 +56,9 @@
authkey_prefix: vector&lt;u8&gt;,
unscaled_value: u64,
) {
// check <b>if</b> the account already <b>exists</b>.
<b>assert</b>(!<a href="DiemAccount.md#0x1_DiemAccount_exists_at">DiemAccount::exists_at</a>(account), <a href="../../../../../../move-stdlib/docs/Errors.md#0x1_Errors_invalid_state">Errors::invalid_state</a>(<a href="ol_account.md#0x1_AccountScripts_ACCOUNT_ALREADY_EXISTS">ACCOUNT_ALREADY_EXISTS</a>));

// IMPORTANT: the human representation of a value is unscaled. The user which expects <b>to</b> send 10 coins, will input that <b>as</b> an unscaled_value. This <b>script</b> converts it <b>to</b> the Move internal scale by multiplying by COIN_SCALING_FACTOR.
<b>let</b> value = unscaled_value * <a href="Globals.md#0x1_Globals_get_coin_scaling_factor">Globals::get_coin_scaling_factor</a>();
<b>let</b> new_account_address = <a href="DiemAccount.md#0x1_DiemAccount_create_user_account_with_coin">DiemAccount::create_user_account_with_coin</a>(
Expand Down Expand Up @@ -125,7 +145,13 @@
op_fullnode_network_addresses: vector&lt;u8&gt;,
op_human_name: vector&lt;u8&gt;,
) {
<b>let</b> new_account_address = <a href="DiemAccount.md#0x1_DiemAccount_create_validator_account_with_proof">DiemAccount::create_validator_account_with_proof</a>(

// check <b>if</b> this account <b>exists</b>
<b>let</b> (new_account_address, _) = <a href="VDF.md#0x1_VDF_extract_address_from_challenge">VDF::extract_address_from_challenge</a>(&challenge);
<b>assert</b>(!<a href="DiemAccount.md#0x1_DiemAccount_exists_at">DiemAccount::exists_at</a>(new_account_address), <a href="../../../../../../move-stdlib/docs/Errors.md#0x1_Errors_invalid_state">Errors::invalid_state</a>(<a href="ol_account.md#0x1_AccountScripts_ACCOUNT_ALREADY_EXISTS">ACCOUNT_ALREADY_EXISTS</a>));


<a href="DiemAccount.md#0x1_DiemAccount_create_validator_account_with_proof">DiemAccount::create_validator_account_with_proof</a>(
&sender,
&challenge,
&solution,
Expand Down
Binary file not shown.
Binary file not shown.
Binary file modified language/diem-framework/staged/stdlib.mv
Binary file not shown.
Loading

0 comments on commit 3b2e34c

Please sign in to comment.