Skip to content

Commit

Permalink
First compilable version
Browse files Browse the repository at this point in the history
  • Loading branch information
guilledk committed Nov 2, 2022
1 parent f5ea538 commit 95c795e
Show file tree
Hide file tree
Showing 9 changed files with 970 additions and 80 deletions.
221 changes: 215 additions & 6 deletions contracts/eosio.system/include/eosio.system/eosio.system.hpp

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions contracts/eosio.system/include/eosio.system/native.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,17 @@ namespace eosiosystem {
using eosio::permission_level;
using eosio::public_key;

// TELOS BEGIN
struct producer_metric {
name bp_name;
uint32_t missed_blocks_per_cycle = 12;

// explicit serialization macro is not necessary, used here only to improve
// compilation time
EOSLIB_SERIALIZE(producer_metric, (bp_name)(missed_blocks_per_cycle))
};
// TELOS END

/**
* A weighted permission.
*
Expand Down
20 changes: 18 additions & 2 deletions contracts/eosio.system/src/delegate_bandwidth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ namespace eosiosystem {
}
}

/* TELOS BEGIN DELETION
void validate_b1_vesting( int64_t stake ) {
const int64_t base_time = 1527811200; /// Friday, June 1, 2018 12:00:00 AM UTC
const int64_t current_time = 1638921540; /// Tuesday, December 7, 2021 11:59:00 PM UTC
Expand All @@ -166,6 +167,7 @@ namespace eosiosystem {
check( max_claimable - claimable <= stake, "b1 can only claim their tokens over 10 years" );
}
TELOS END DELETION */

void system_contract::changebw( name from, const name& receiver,
const asset& stake_net_delta, const asset& stake_cpu_delta, bool transfer )
Expand Down Expand Up @@ -361,9 +363,11 @@ namespace eosiosystem {

check( 0 <= voter_itr->staked, "stake for voting cannot be negative" );

/* TELOS BEGIN DELETION
if( voter == "b1"_n ) {
validate_b1_vesting( voter_itr->staked );
}
TELOS END DELETION */

if( voter_itr->producers.size() || voter_itr->proxy ) {
update_votes( voter, voter_itr->proxy, voter_itr->producers, false );
Expand All @@ -381,6 +385,12 @@ namespace eosiosystem {
check( !transfer || from != receiver, "cannot use transfer flag if delegating to self" );

changebw( from, receiver, stake_net_quantity, stake_cpu_quantity, transfer);
// TELOS BEGIN
//notify telos decide of stake change
if (from == receiver) {
require_recipient("telos.decide"_n);
}
// TELOS END
} // delegatebw

void system_contract::undelegatebw( const name& from, const name& receiver,
Expand All @@ -390,10 +400,16 @@ namespace eosiosystem {
check( unstake_cpu_quantity >= zero_asset, "must unstake a positive amount" );
check( unstake_net_quantity >= zero_asset, "must unstake a positive amount" );
check( unstake_cpu_quantity.amount + unstake_net_quantity.amount > 0, "must unstake a positive amount" );
check( _gstate.thresh_activated_stake_time != time_point(),
"cannot undelegate bandwidth until the chain is activated (at least 15% of all tokens participate in voting)" );
check( _gstate.block_num > block_num_network_activation || _gstate.thresh_activated_stake_time > time_point(),
"cannot undelegate bandwidth until the chain is activated (1,000,000 blocks produced)" );

changebw( from, receiver, -unstake_net_quantity, -unstake_cpu_quantity, false);
// TELOS BEGIN
//notify telos decide of stake change
if (from == receiver) {
require_recipient("telos.decide"_n);
}
// TELOS END
} // undelegatebw


Expand Down
43 changes: 42 additions & 1 deletion contracts/eosio.system/src/eosio.system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,23 @@ namespace eosiosystem {
_rexretbuckets(get_self(), get_self().value),
_rexfunds(get_self(), get_self().value),
_rexbalance(get_self(), get_self().value),
_rexorders(get_self(), get_self().value)
_rexorders(get_self(), get_self().value),
// TELOS BEGIN
_schedule_metrics(_self, _self.value),
_rotation(_self, _self.value),
_payrate(_self, _self.value),
_payments(_self, _self.value)
// TELOS END
{
_gstate = _global.exists() ? _global.get() : get_default_parameters();
_gstate2 = _global2.exists() ? _global2.get() : eosio_global_state2{};
_gstate3 = _global3.exists() ? _global3.get() : eosio_global_state3{};
_gstate4 = _global4.exists() ? _global4.get() : get_default_inflation_parameters();
// TELOS BEGIN
_gschedule_metrics = _schedule_metrics.get_or_create(_self, schedule_metrics_state{ name(0), 0, std::vector<producer_metric>() });
_grotation = _rotation.get_or_create(_self, rotation_state{ name(0), name(0), 21, 75, block_timestamp(), block_timestamp() });
_gpayrate = _payrate.get_or_create(_self, payrates{ max_bpay_rate, max_worker_monthly_amount });
// TELOS END
}

eosio_global_state system_contract::get_default_parameters() {
Expand All @@ -62,6 +73,11 @@ namespace eosiosystem {
_global2.set( _gstate2, get_self() );
_global3.set( _gstate3, get_self() );
_global4.set( _gstate4, get_self() );
// TELOS BEGIN
_schedule_metrics.set(_gschedule_metrics, _self);
_rotation.set(_grotation, _self);
_payrate.set(_gpayrate, _self);
// TELOS END
}

void system_contract::setram( uint64_t max_ram_size ) {
Expand Down Expand Up @@ -511,4 +527,29 @@ namespace eosiosystem {
open_act.send( rex_account, core, get_self() );
}

// TELOS BEGIN
void system_contract::votebpout(name bp, uint32_t penalty_hours) {
require_auth(_self);
check(penalty_hours != 0, "The penalty should be greater than zero.");

auto pitr = _producers.find(bp.value);
check(pitr != _producers.end(), "Producer account was not found");

_producers.modify(pitr, same_payer, [&](auto &p) {
p.kick(kick_type::BPS_VOTING, penalty_hours);
});
}

void system_contract::setpayrates(uint64_t bpay, uint64_t worker) {
require_auth(_self);
check(worker <= max_worker_monthly_amount, "WPS rate exceeds the max");
check(bpay <= max_bpay_rate, "BPAY rate exceeds the max");
_gpayrate.bpay_rate = bpay;
_gpayrate.worker_amount = worker;
}

void system_contract::distviarex(name from, asset amount) {
system_contract::channel_to_rex(from, amount);
}
// TELOS END
} /// eosio.system
172 changes: 168 additions & 4 deletions contracts/eosio.system/src/producer_pay.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
#include <eosio.system/eosio.system.hpp>
#include <eosio.token/eosio.token.hpp>
// TELOS BEGIN
#include "system_kick.cpp"
#define MAX_PRODUCERS 42 // revised for TEDP 2 Phase 2, also set in system_rotation.cpp, change in both places
// TELOS END

namespace eosiosystem {

Expand Down Expand Up @@ -30,12 +34,26 @@ namespace eosiosystem {
_gstate2.last_block_num = timestamp;

/** until activation, no new rewards are paid */
if( _gstate.thresh_activated_stake_time == time_point() )
return;
// TELOS BEGIN
_gstate.block_num++;
if (_gstate.thresh_activated_stake_time == time_point()) {
if(_gstate.block_num >= block_num_network_activation && _gstate.total_producer_vote_weight > 0) {
_gstate.thresh_activated_stake_time = current_time_point();
_gstate.last_claimrewards = timestamp.slot;
}
return;
}
// TELOS END

if( _gstate.last_pervote_bucket_fill == time_point() ) /// start the presses
_gstate.last_pervote_bucket_fill = current_time_point();

// TELOS BEGIN
if(check_missed_blocks(timestamp, producer)) {
update_missed_blocks_per_rotation();
reset_schedule_metrics(producer);
}
// TELOS END

/**
* At startup the initial producer may not be one that is registered / elected
Expand All @@ -46,9 +64,12 @@ namespace eosiosystem {
_gstate.total_unpaid_blocks++;
_producers.modify( prod, same_payer, [&](auto& p ) {
p.unpaid_blocks++;
p.lifetime_produced_blocks++; // TELOS
});
}

recalculate_votes(); // TELOS

/// only update block producers once every minute, block_timestamp is in half seconds
if( timestamp.slot - _gstate.last_producer_schedule_update.slot > 120 ) {
update_elected_producers( timestamp );
Expand All @@ -71,6 +92,13 @@ namespace eosiosystem {
}
}
}
// TELOS BEGIN
//called once per day to set payments snapshot
if (_gstate.last_claimrewards + uint32_t(3600) <= timestamp.slot) { //172800 blocks in a day
claimrewards_snapshot();
_gstate.last_claimrewards = timestamp.slot;
}
// TELOS END
}

void system_contract::claimrewards( const name& owner ) {
Expand All @@ -79,9 +107,26 @@ namespace eosiosystem {
const auto& prod = _producers.get( owner.value );
check( prod.active(), "producer does not have an active key" );

check( _gstate.thresh_activated_stake_time != time_point(),
"cannot claim rewards until the chain is activated (at least 15% of all tokens participate in voting)" );
// TELOS BEGIN
check( _gstate.thresh_activated_stake_time > time_point(),
"cannot claim rewards until the chain is activated (1,000,000 blocks produced)");

auto p = _payments.find(owner.value);
check(p != _payments.end(), "No payment exists for account");
auto prod_payment = *p;
auto pay_amount = prod_payment.pay;

//NOTE: consider resetting producer's last claim time to 0 here, instead of during snapshot.
{
token::transfer_action transfer_act{ token_account, { bpay_account, active_permission } };
transfer_act.send( bpay_account, owner, pay_amount, "Producer/Standby Payment" );
}

_payments.erase(p);
// TELOS END

// TELOS BEGIN REDACTED, REST OF STOCK PAYMENT LOGIC MOVED TO claimrewards_snapshot
/*
const auto ct = current_time_point();
check( ct - prod.last_claim_time > microseconds(useconds_per_day), "already claimed rewards within past day" );
Expand Down Expand Up @@ -194,6 +239,125 @@ namespace eosiosystem {
token::transfer_action transfer_act{ token_account, { {vpay_account, active_permission}, {owner, active_permission} } };
transfer_act.send( vpay_account, owner, asset(producer_per_vote_pay, core_symbol()), "producer vote pay" );
}
*/
}

void system_contract::claimrewards_snapshot() {
check(_gstate.thresh_activated_stake_time > time_point(), "cannot take snapshot until chain is activated");

//skips action, since there are no rewards to claim
if (_gstate.total_unpaid_blocks <= 0) {
return;
}

auto ct = current_time_point();

const asset token_supply = eosio::token::get_supply(token_account, core_symbol().code() );
const auto usecs_since_last_fill = (ct - _gstate.last_pervote_bucket_fill).count();

if (usecs_since_last_fill > 0 && _gstate.last_pervote_bucket_fill > time_point())
{
double bpay_rate = double(_gpayrate.bpay_rate) / double(100000); //NOTE: both bpay_rate and divisor were int64s which evaluated to 0. The divisor must be a double to get percentage.
auto to_workers = static_cast<int64_t>((12 * double(_gpayrate.worker_amount) * double(usecs_since_last_fill)) / double(useconds_per_year));
auto to_producers = static_cast<int64_t>((bpay_rate * double(token_supply.amount) * double(usecs_since_last_fill)) / double(useconds_per_year));
auto new_tokens = to_workers + to_producers;

//NOTE: This line can cause failure if eosio.tedp doesn't have a balance emplacement
asset tedp_balance = eosio::token::get_balance(token_account, tedp_account, core_symbol().code());

int64_t transfer_tokens = 0;
int64_t issue_tokens = 0;
if (tedp_balance.amount > 0) {
if (tedp_balance.amount >= new_tokens) {
transfer_tokens = new_tokens;
} else {
transfer_tokens = tedp_balance.amount;
issue_tokens = new_tokens - transfer_tokens;
}
} else {
issue_tokens = new_tokens;
}

if (transfer_tokens > 0) {
token::transfer_action transfer_act{ token_account, { tedp_account, active_permission } };
transfer_act.send( tedp_account, get_self(), asset(transfer_tokens, core_symbol()), "TEDP: Inflation offset" );
}

token::transfer_action transfer_act{ token_account, { get_self(), active_permission } };

if (issue_tokens > 0) {
token::issue_action issue_action{ token_account, { get_self(), active_permission }};
issue_action.send(get_self(), asset(issue_tokens, core_symbol()), "Issue new TLOS tokens");
}

if(to_workers > 0) {
transfer_act.send(get_self(), works_account, asset(to_workers, core_symbol()), "Transfer worker proposal share to works.decide account");
}

if(to_producers > 0) {
transfer_act.send(get_self(), bpay_account, asset(to_producers, core_symbol()), "Transfer producer share to per-block bucket");
}

_gstate.perblock_bucket += to_producers;
_gstate.last_pervote_bucket_fill = ct;
}

//sort producers table
auto sortedprods = _producers.get_index<"prototalvote"_n>();

//calculate shares, based on MAX_PRODUCERS
uint32_t activecount = 0;

for (const auto &prod : sortedprods)
{
if (prod.active() && activecount < MAX_PRODUCERS) //only count activated producers
activecount++;
else
break;
}

// if we don't have standbys (21 active or less), don't attempt to calculate for standbys, just do total activecount X 2
// if we have standbys, do 42 shares for the top 21 plus 1 share per standby, so 42 plus the total activecount minus 21
uint32_t sharecount = activecount <= 21 ? (activecount * 2) : (42 + (activecount - 21));

auto shareValue = (_gstate.perblock_bucket / sharecount);
int32_t index = 0;

for (const auto &prod : sortedprods) {

if (!prod.active()) //skip inactive producers
continue;

int64_t pay_amount = 0;
index++;

if (index <= 21) {
pay_amount = (shareValue * int64_t(2));
} else if (index >= 22 && index <= MAX_PRODUCERS) {
pay_amount = shareValue;
} else
break;

_gstate.perblock_bucket -= pay_amount;
_gstate.total_unpaid_blocks -= prod.unpaid_blocks;

_producers.modify(prod, same_payer, [&](auto &p) {
p.last_claim_time = ct;
p.unpaid_blocks = 0;
});

auto itr = _payments.find(prod.owner.value);

if (itr == _payments.end()) {
_payments.emplace(_self, [&]( auto& a ) {
a.bp = prod.owner;
a.pay = asset(pay_amount, core_symbol());
});
} else //adds new payment to existing payment
_payments.modify(itr, same_payer, [&]( auto& a ) {
a.pay += asset(pay_amount, core_symbol());
});
}
}

} //namespace eosiosystem
6 changes: 5 additions & 1 deletion contracts/eosio.system/src/rex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ namespace eosiosystem {

check( amount.symbol == core_symbol(), "asset must be core token" );
check( 0 < amount.amount, "must use positive amount" );
/* TELOS Remove requirement to vote 21 BPs or select a proxy to stake to REX
check_voting_requirement( from );
*/
transfer_from_fund( from, amount );
const asset rex_received = add_to_rex_pool( amount );
const asset delta_rex_stake = add_to_rex_balance( from, amount, rex_received );
Expand All @@ -61,7 +63,9 @@ namespace eosiosystem {
check( from_net.symbol == core_symbol() && from_cpu.symbol == core_symbol(), "asset must be core token" );
check( (0 <= from_net.amount) && (0 <= from_cpu.amount) && (0 < from_net.amount || 0 < from_cpu.amount),
"must unstake a positive amount to buy rex" );
check_voting_requirement( owner );
/* TELOS Remove requirement to vote 21 BPs or select a proxy to stake to REX
check_voting_requirement( from );
*/

{
del_bandwidth_table dbw_table( get_self(), owner.value );
Expand Down
Loading

0 comments on commit 95c795e

Please sign in to comment.