提交 80ae5659 编写于 作者: A Anton Perkov

stake/unstake storage, producers vote for storage_reserve_ratio

上级 f5b6df7d
#pragma once
#include <eosiolib/eosio.hpp>
#include <eosiolib/generic_currency.hpp>
#include <eosiolib/multi_index.hpp>
#include <eosiolib/privileged.hpp>
#include <eosiolib/singleton.hpp>
namespace eosiosystem {
template<account_name SystemAccount>
class common {
public:
static constexpr account_name system_account = SystemAccount;
typedef eosio::generic_currency< eosio::token<system_account,S(4,EOS)> > currency;
typedef typename currency::token_type system_token_type;
struct eosio_parameters : eosio::blockchain_parameters {
uint32_t inflation_rate = 0; // inflation coefficient * 10000 (i.e. inflation in percent * 100)
uint32_t storage_reserve_ratio = 1; // ratio * 1000
uint64_t total_storage_bytes_reserved = 0;
system_token_type total_storage_stake;
eosio_parameters() { bzero(this, sizeof(*this)); }
EOSLIB_SERIALIZE_DERIVED( eosio_parameters, eosio::blockchain_parameters, (inflation_rate)(storage_reserve_ratio)
(storage_reserve_ratio)(total_storage_bytes_reserved)(total_storage_stake) )
};
typedef eosio::singleton<SystemAccount, N(inflation), SystemAccount, eosio_parameters> eosio_parameters_singleton;
};
}
......@@ -3,6 +3,7 @@
* @copyright defined in eos/LICENSE.txt
*/
#pragma once
#include "common.hpp"
#include <eosiolib/eosio.hpp>
#include <eosiolib/token.hpp>
......@@ -27,19 +28,22 @@ namespace eosiosystem {
template<account_name SystemAccount>
class delegate_bandwith {
public:
static const account_name system_account = SystemAccount;
typedef eosio::generic_currency< eosio::token<system_account,S(4,EOS)> > currency;
typedef typename currency::token_type system_token_type;
static constexpr account_name system_account = SystemAccount;
using currency = typename common<SystemAccount>::currency;
using system_token_type = typename common<SystemAccount>::system_token_type;
using eosio_parameters = typename common<SystemAccount>::eosio_parameters;
using eosio_parameters_singleton = typename common<SystemAccount>::eosio_parameters_singleton;
struct total_resources {
account_name owner;
typename currency::token_type total_net_weight;
typename currency::token_type total_cpu_weight;
uint32_t total_ram = 0;
typename currency::token_type total_cpu_weight;
typename currency::token_type total_storage_stake;
uint64_t total_storage_bytes = 0;
uint64_t primary_key()const { return owner; }
EOSLIB_SERIALIZE( total_resources, (owner)(total_net_weight)(total_cpu_weight)(total_ram) )
EOSLIB_SERIALIZE( total_resources, (owner)(total_net_weight)(total_cpu_weight)(total_storage_bytes) )
};
......@@ -50,7 +54,9 @@ namespace eosiosystem {
account_name from;
account_name to;
typename currency::token_type net_weight;
typename currency::token_type cpu_weight;
typename currency::token_type cpu_weight;
typename currency::token_type storage_stake;
uint64_t storage_bytes = 0;
uint32_t start_pending_net_withdraw = 0;
typename currency::token_type pending_net_withdraw;
......@@ -63,7 +69,7 @@ namespace eosiosystem {
uint64_t primary_key()const { return to; }
EOSLIB_SERIALIZE( delegated_bandwidth, (from)(to)(net_weight)(cpu_weight)
EOSLIB_SERIALIZE( delegated_bandwidth, (from)(to)(net_weight)(cpu_weight)(storage_stake)(storage_bytes)
(start_pending_net_withdraw)(pending_net_withdraw)(deferred_net_withdraw_handler)
(start_pending_cpu_withdraw)(pending_cpu_withdraw)(deferred_cpu_withdraw_handler) )
......@@ -82,6 +88,7 @@ namespace eosiosystem {
account_name receiver;
typename currency::token_type stake_net_quantity;
typename currency::token_type stake_cpu_quantity;
typename currency::token_type stake_storage_quantity;
EOSLIB_SERIALIZE( delegatebw, (from)(receiver)(stake_net_quantity)(stake_cpu_quantity) )
......@@ -92,8 +99,9 @@ namespace eosiosystem {
account_name receiver;
typename currency::token_type unstake_net_quantity;
typename currency::token_type unstake_cpu_quantity;
uint64_t unstake_storage_bytes;
EOSLIB_SERIALIZE( undelegatebw, (from)(receiver)(unstake_net_quantity)(unstake_cpu_quantity) )
EOSLIB_SERIALIZE( undelegatebw, (from)(receiver)(unstake_net_quantity)(unstake_cpu_quantity)(unstake_storage_bytes) )
};
/// new id options:
......@@ -104,7 +112,7 @@ namespace eosiosystem {
eosio_assert( del.stake_cpu_quantity.quantity >= 0, "must stake a positive amount" );
eosio_assert( del.stake_net_quantity.quantity >= 0, "must stake a positive amount" );
auto total_stake = del.stake_cpu_quantity + del.stake_net_quantity;
auto total_stake = del.stake_cpu_quantity + del.stake_net_quantity + del.stake_storage_quantity;
eosio_assert( total_stake.quantity >= 0, "must stake a positive amount" );
......@@ -115,19 +123,38 @@ namespace eosiosystem {
//eosio_assert( is_account( del.receiver ), "can only delegate resources to an existing account" );
auto parameters = eosio_parameters_singleton::get_or_default();
auto token_supply = currency::get_total_supply();//.quantity;
//if ( token_supply == 0 || parameters not set) { what to do? }
//make sure that there is no posibility of overflow here
uint64_t storage_bytes_estimated = ( parameters.max_storage_size - parameters.total_storage_bytes_reserved )
* parameters.storage_reserve_ratio * del.stake_storage_quantity
/ ( token_supply - parameters.total_storage_stake ) / 1000 /* reserve ratio coefficient */;
uint64_t storage_bytes = ( parameters.max_storage_size - parameters.total_storage_bytes_reserved - storage_bytes_estimated )
* parameters.storage_reserve_ratio * del.stake_storage_quantity
/ ( token_supply - del.stake_storage_quantity - parameters.total_storage_stake ) / 1000 /* reserve ratio coefficient */;
eosio_assert( 0 < storage_bytes, "stake is too small to increase memory even for 1 byte" );
auto itr = del_index.find( del.receiver);
if( itr != nullptr ) {
del_index.emplace( del.from, [&]( auto& dbo ){
dbo.from = del.from;
dbo.to = del.receiver;
dbo.net_weight = del.stake_net_quantity;
dbo.cpu_weight = del.stake_cpu_quantity;
dbo.from = del.from;
dbo.to = del.receiver;
dbo.net_weight = del.stake_net_quantity;
dbo.cpu_weight = del.stake_cpu_quantity;
dbo.storage_stake = del.stake_storage_quantity;
dbo.storage_bytes = storage_bytes;
});
}
else {
del_index.update( *itr, del.from, [&]( auto& dbo ){
dbo.net_weight = del.stake_net_quantity;
dbo.cpu_weight = del.stake_cpu_quantity;
dbo.net_weight += del.stake_net_quantity;
dbo.cpu_weight += del.stake_cpu_quantity;
dbo.storage_stake += del.stake_storage_quantity;
dbo.storage_bytes += storage_bytes;
});
}
......@@ -135,28 +162,33 @@ namespace eosiosystem {
if( tot_itr == nullptr ) {
tot_itr = &total_index.emplace( del.from, [&]( auto& tot ) {
tot.owner = del.receiver;
tot.total_net_weight += del.stake_net_quantity;
tot.total_cpu_weight += del.stake_cpu_quantity;
tot.total_net_weight = del.stake_net_quantity;
tot.total_cpu_weight = del.stake_cpu_quantity;
tot.total_storage_stake = del.stake_storage_quantity;
tot.total_storage_bytes = storage_bytes;
});
} else {
total_index.update( *tot_itr, 0, [&]( auto& tot ) {
tot.total_net_weight += del.stake_net_quantity;
tot.total_cpu_weight += del.stake_cpu_quantity;
tot.total_net_weight += del.stake_net_quantity;
tot.total_cpu_weight += del.stake_cpu_quantity;
tot.total_storage_stake += del.stake_storage_quantity;
tot.total_storage_bytes += storage_bytes;
});
}
set_resource_limits( tot_itr->owner, tot_itr->total_ram, tot_itr->total_net_weight.quantity, tot_itr->total_cpu_weight.quantity, 0 );
set_resource_limits( tot_itr->owner, tot_itr->total_storage_bytes, tot_itr->total_net_weight.quantity, tot_itr->total_cpu_weight.quantity, 0 );
currency::inline_transfer( del.from, SystemAccount, total_stake, "stake bandwidth" );
parameters.total_storage_bytes_reserved += storage_bytes;
parameters.total_storage_stake += del.stake_storage_quantity;
eosio_parameters_singleton::set(parameters);
} // delegatebw
static void on( const undelegatebw& del ) {
eosio_assert( del.unstake_cpu_quantity.quantity >= 0, "must stake a positive amount" );
eosio_assert( del.unstake_net_quantity.quantity >= 0, "must stake a positive amount" );
auto total_stake = del.unstake_cpu_quantity + del.unstake_net_quantity;
eosio_assert( total_stake.quantity >= 0, "must stake a positive amount" );
require_auth( del.from );
del_bandwidth_index_type del_index( SystemAccount, del.from );
......@@ -168,22 +200,35 @@ namespace eosiosystem {
eosio_assert( dbw.net_weight >= del.unstake_net_quantity, "insufficient staked net bandwidth" );
eosio_assert( dbw.cpu_weight >= del.unstake_cpu_quantity, "insufficient staked cpu bandwidth" );
const auto& totals = total_index.get( del.receiver );
system_token_type storage_stake_decrease = totals.total_storage_stake * del.unstake_storage_bytes / totals.total_storage_bytes;
auto total_refund = del.unstake_cpu_quantity + del.unstake_net_quantity + storage_stake_decrease;
eosio_assert( total_refund.quantity >= 0, "must stake a positive amount" );
del_index.update( dbw, del.from, [&]( auto& dbo ){
dbo.net_weight -= del.unstake_net_quantity;
dbo.cpu_weight -= del.unstake_cpu_quantity;
dbo.storage_stake -= storage_stake_decrease;
dbo.storage_bytes -= del.unstake_storage_bytes;
});
const auto& totals = total_index.get( del.receiver );
total_index.update( totals, 0, [&]( auto& tot ) {
tot.total_net_weight -= del.unstake_net_quantity;
tot.total_cpu_weight -= del.unstake_cpu_quantity;
tot.total_storage_stake -= storage_stake_decrease;
tot.total_storage_bytes -= del.unstake_storage_bytes;
});
set_resource_limits( totals.owner, totals.total_ram, totals.total_net_weight.quantity, totals.total_cpu_weight.quantity, 0 );
set_resource_limits( totals.owner, totals.total_storage_bytes, totals.total_net_weight.quantity, totals.total_cpu_weight.quantity, 0 );
/// TODO: implement / enforce time delays on withdrawing
currency::inline_transfer( SystemAccount, del.from, total_stake, "unstake bandwidth" );
currency::inline_transfer( SystemAccount, del.from, total_refund, "unstake bandwidth" );
auto parameters = eosio_parameters_singleton::get();
parameters.total_storage_bytes_reserved -= del.unstake_storage_bytes;
parameters.total_storage_stake -= storage_stake_decrease;
eosio_parameters_singleton::set( parameters );
} // undelegatebw
};
}
......@@ -3,6 +3,8 @@
* @copyright defined in eos/LICENSE.txt
*/
#pragma once
#include "common.hpp"
#include <eosiolib/eosio.hpp>
#include <eosiolib/token.hpp>
#include <eosiolib/print.hpp>
......@@ -26,30 +28,25 @@ namespace eosiosystem {
using eosio::singleton;
using eosio::transaction;
template<account_name SystemAccount>
class voting {
public:
static const account_name system_account = SystemAccount;
typedef eosio::generic_currency< eosio::token<system_account,S(4,EOS)> > currency;
typedef typename currency::token_type system_token_type;
static constexpr account_name system_account = SystemAccount;
using currency = typename common<SystemAccount>::currency;
using system_token_type = typename common<SystemAccount>::system_token_type;
using eosio_parameters = typename common<SystemAccount>::eosio_parameters;
using eosio_parameters_singleton = typename common<SystemAccount>::eosio_parameters_singleton;
static constexpr uint32_t max_unstake_requests = 10;
static constexpr uint32_t unstake_pay_period = 7*24*3600; // one per week
static constexpr uint32_t unstake_payments = 26; // during 26 weeks
struct producer_preferences : eosio::blockchain_parameters {
uint32_t inflation_rate; // inflation coefficient * 10000 (i.e. inflation in percent * 1000)
producer_preferences() { bzero(this, sizeof(*this)); }
EOSLIB_SERIALIZE_DERIVED( producer_preferences, eosio::blockchain_parameters, (inflation_rate) )
};
struct producer_info {
account_name owner;
uint64_t padding = 0;
uint128_t total_votes = 0;
producer_preferences prefs;
eosio_parameters prefs;
eosio::bytes packed_key; /// a packed public key object
uint64_t primary_key()const { return owner; }
......@@ -63,7 +60,6 @@ namespace eosiosystem {
indexed_by<N(prototalvote), const_mem_fun<producer_info, uint128_t, &producer_info::by_votes> >
> producers_table;
typedef singleton<SystemAccount, N(inflation), SystemAccount, uint32_t> inflation_singleton;
struct account_votes {
account_name owner = 0;
......@@ -99,7 +95,7 @@ namespace eosiosystem {
ACTION( SystemAccount, register_producer ) {
account_name producer;
bytes producer_key;
producer_preferences prefs;
eosio_parameters prefs;
EOSLIB_SERIALIZE( register_producer, (producer)(producer_key)(prefs) )
};
......@@ -132,15 +128,15 @@ namespace eosiosystem {
});
}
ACTION( SystemAccount, change_producer_preferences ) {
ACTION( SystemAccount, change_eosio_parameters ) {
account_name producer;
bytes producer_key;
producer_preferences prefs;
eosio_parameters prefs;
EOSLIB_SERIALIZE( register_producer, (producer)(producer_key)(prefs) )
};
static void on( const change_producer_preferences& change) {
static void on( const change_eosio_parameters& change) {
require_auth( change.producer );
producers_table producers_tbl( SystemAccount, SystemAccount );
......@@ -218,6 +214,7 @@ namespace eosiosystem {
std::array<uint32_t, 21> max_inline_action_size;
std::array<uint32_t, 21> max_generated_transaction_size;
std::array<uint32_t, 21> inflation_rate;
std::array<uint32_t, 21> storage_reserve_ratio;
std::array<account_name, 21> elected;
......@@ -244,6 +241,7 @@ namespace eosiosystem {
max_inline_action_size[n] = it->prefs.max_inline_action_size;
max_generated_transaction_size[n] = it->prefs.max_generated_transaction_size;
storage_reserve_ratio[n] = it->prefs.storage_reserve_ratio;
inflation_rate[n] = it->prefs.inflation_rate;
++n;
}
......@@ -256,25 +254,31 @@ namespace eosiosystem {
set_active_producers( elected.data(), n );
size_t median = n/2;
::blockchain_parameters concensus = {
target_block_size[median],
max_block_size[median],
target_block_acts_per_scope[median],
max_block_acts_per_scope[median],
target_block_acts[median],
max_block_acts[median],
max_storage_size[median],
max_transaction_lifetime[median],
max_transaction_exec_time[median],
max_authority_depth[median],
max_inline_depth[median],
max_inline_action_size[median],
max_generated_transaction_size[median]
};
set_blockchain_parameters(&concensus);
inflation_singleton::set( inflation_rate[median] );
auto parameters = eosio_parameters_singleton::get();
parameters.target_block_size = target_block_size[median];
parameters.max_block_size = max_block_size[median];
parameters.target_block_acts_per_scope = target_block_acts_per_scope[median];
parameters.max_block_acts_per_scope = max_block_acts_per_scope[median];
parameters.target_block_acts = target_block_acts[median];
parameters.max_block_acts = max_block_acts[median];
parameters.max_storage_size = max_storage_size[median];
parameters.max_transaction_lifetime = max_transaction_lifetime[median];
parameters.max_transaction_exec_time = max_transaction_exec_time[median];
parameters.max_authority_depth = max_authority_depth[median];
parameters.max_inline_depth = max_inline_depth[median];
parameters.max_inline_action_size = max_inline_action_size[median];
parameters.max_generated_transaction_size = max_generated_transaction_size[median];
parameters.storage_reserve_ratio = storage_reserve_ratio[median];
parameters.inflation_rate = inflation_rate[median];
if ( parameters.max_storage_size < parameters.total_storage_bytes_reserved ) {
parameters.max_storage_size = parameters.total_storage_bytes_reserved;
}
set_blockchain_parameters(&parameters);
eosio_parameters_singleton::set( parameters );
}
static void on( const stake_vote& sv ) {
......
......@@ -134,6 +134,11 @@ namespace eosio {
act.send();
}
static token_type get_total_supply() {
stats t( code, code );
auto ptr = t.find( symbol );
return ptr ? ptr->supply : token_type(0);
}
static void apply( account_name c, action_name act) {
eosio::dispatch<generic_currency, transfer, issue>(c,act);
......
#pragma once
#include "privileged.h"
#include "serialize.hpp"
......
......@@ -28,7 +28,7 @@ namespace eosio {
*reinterpret_cast<uint64_t *>(temp) = SingletonName;
auto read = load_i64( Code, scope, SingletonName, temp, sizeof(temp) );
eosio_assert( read > 0, "singleton does not exist" );
return unpack<T>( temp + sizeof(SingletonName), read );
return unpack<T>( temp + sizeof(SingletonName), size_t(read) );
}
static T get_or_default( scope_name scope = Code, const T& def = T() ) {
......
......@@ -127,7 +127,7 @@ namespace eosio {
/**
* Multiplies token and integer
* Throws an exception if overflow
* @brief Adds quantity of two tokens and return a new token
* @brief Multiplies quantity of two tokens and return a new token
* @param a token to be multiplied
* @param b multipier
* @return result of addition as a new token
......@@ -141,7 +141,7 @@ namespace eosio {
/**
* Multiplies token and integer
* Throws an exception if overflow
* @brief Adds quantity of two tokens and return a new token
* @brief Multiplies quantity of two tokens and return a new token
* @param a token to be multiplied
* @param b multipier
* @return result of addition as a new token
......@@ -152,6 +152,44 @@ namespace eosio {
return result;
}
/**
* Divides quantity of token by an integer
* Throws an exception if overflow
* @brief Divides quantity of token by an integer
* @param a multipier
* @return this token after addition
*/
token& operator/=( uint64_t a ) {
quantity /= a;
return *this;
}
/**
* Divides token and integer
* Throws an exception if overflow
* @brief Divides quantity of two tokens and return a new token
* @param a token to be multiplied
* @param b multipier
* @return result of addition as a new token
*/
inline friend token operator/( const token& a, uint64_t b ) {
token result = a;
result /= b;
return result;
}
/**
* Divides two tokens
* Throws an exception if overflow
* @brief Divides quantity of two tokens and return a new token
* @param a token
* @param b token
* @return result of addition as a new token
*/
inline friend NumberType operator/( const token& a, const token& b ) {
return a.quantity / b.quantity;
}
/**
* Less than or equal to comparison operator
* @brief Less than or equal to comparison operator
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册