提交 2280dba7 编写于 作者: T Todd Fleming

Merge remote-tracking branch 'origin/master' into cleos-more-producers

......@@ -92,10 +92,16 @@
"base": "",
"fields": [
{"name": "proposal_name", "type": "name"},
{"name": "requested_approvals", "type": "permission_level[]"},
{"name": "provided_approvals", "type": "permission_level[]"},
{"name": "packed_transaction", "type": "bytes"}
]
},{
"name": "approvals_info",
"base": "",
"fields": [
{"name": "proposal_name", "type": "name"},
{"name": "requested_approvals", "type": "permission_level[]"},
{"name": "provided_approvals", "type": "permission_level[]"}
]
}
],
"actions": [{
......@@ -127,6 +133,12 @@
"index_type": "i64",
"key_names" : ["proposal_name"],
"key_types" : ["name"]
},{
"name": "approvals",
"type": "approvals_info",
"index_type": "i64",
"key_names" : ["proposal_name"],
"key_types" : ["name"]
}
],
"ricardian_clauses": []
......
......@@ -50,38 +50,41 @@ void multisig::propose() {
proptable.emplace( proposer, [&]( auto& prop ) {
prop.proposal_name = proposal_name;
prop.packed_transaction = bytes( buffer+trx_pos, buffer+size );
prop.requested_approvals = std::move(requested);
});
approvals apptable( _self, proposer );
apptable.emplace( proposer, [&]( auto& a ) {
a.proposal_name = proposal_name;
a.requested_approvals = std::move(requested);
});
}
void multisig::approve( account_name proposer, name proposal_name, permission_level level ) {
require_auth( level );
proposals proptable( _self, proposer );
auto prop_it = proptable.find( proposal_name );
eosio_assert( prop_it != proptable.end(), "proposal not found" );
approvals apptable( _self, proposer );
auto& apps = apptable.get( proposal_name, "proposal not found" );
auto itr = std::find( prop_it->requested_approvals.begin(), prop_it->requested_approvals.end(), level );
eosio_assert( itr != prop_it->requested_approvals.end(), "approval is not on the list of requested approvals" );
auto itr = std::find( apps.requested_approvals.begin(), apps.requested_approvals.end(), level );
eosio_assert( itr != apps.requested_approvals.end(), "approval is not on the list of requested approvals" );
proptable.modify( prop_it, proposer, [&]( auto& mprop ) {
mprop.provided_approvals.push_back( level );
mprop.requested_approvals.erase( itr );
apptable.modify( apps, proposer, [&]( auto& a ) {
a.provided_approvals.push_back( level );
a.requested_approvals.erase( itr );
});
}
void multisig::unapprove( account_name proposer, name proposal_name, permission_level level ) {
require_auth( level );
proposals proptable( _self, proposer );
auto prop_it = proptable.find( proposal_name );
eosio_assert( prop_it != proptable.end(), "proposal not found" );
auto itr = std::find( prop_it->provided_approvals.begin(), prop_it->provided_approvals.end(), level );
eosio_assert( itr != prop_it->provided_approvals.end(), "no approval previously granted" );
proptable.modify( prop_it, proposer, [&]( auto& mprop ) {
mprop.requested_approvals.push_back(level);
mprop.provided_approvals.erase(itr);
approvals apptable( _self, proposer );
auto& apps = apptable.get( proposal_name, "proposal not found" );
auto itr = std::find( apps.provided_approvals.begin(), apps.provided_approvals.end(), level );
eosio_assert( itr != apps.provided_approvals.end(), "no approval previously granted" );
apptable.modify( apps, proposer, [&]( auto& a ) {
a.requested_approvals.push_back(level);
a.provided_approvals.erase(itr);
});
}
......@@ -89,38 +92,44 @@ void multisig::cancel( account_name proposer, name proposal_name, account_name c
require_auth( canceler );
proposals proptable( _self, proposer );
auto prop_it = proptable.find( proposal_name );
eosio_assert( prop_it != proptable.end(), "proposal not found" );
auto& prop = proptable.get( proposal_name, "proposal not found" );
if( canceler != proposer ) {
eosio_assert( unpack<transaction_header>( prop_it->packed_transaction ).expiration < eosio::time_point_sec(now()), "cannot cancel until expiration" );
eosio_assert( unpack<transaction_header>( prop.packed_transaction ).expiration < eosio::time_point_sec(now()), "cannot cancel until expiration" );
}
proptable.erase(prop_it);
approvals apptable( _self, proposer );
auto& apps = apptable.get( proposal_name, "proposal not found" );
proptable.erase(prop);
apptable.erase(apps);
}
void multisig::exec( account_name proposer, name proposal_name, account_name executer ) {
require_auth( executer );
proposals proptable( _self, proposer );
auto prop_it = proptable.find( proposal_name );
eosio_assert( prop_it != proptable.end(), "proposal not found" );
auto& prop = proptable.get( proposal_name, "proposal not found" );
approvals apptable( _self, proposer );
auto& apps = apptable.get( proposal_name, "proposal not found" );
transaction_header trx_header;
datastream<const char*> ds( prop_it->packed_transaction.data(), prop_it->packed_transaction.size() );
datastream<const char*> ds( prop.packed_transaction.data(), prop.packed_transaction.size() );
ds >> trx_header;
eosio_assert( trx_header.expiration >= eosio::time_point_sec(now()), "transaction expired" );
bytes packed_provided_approvals = pack(prop_it->provided_approvals);
auto res = ::check_transaction_authorization( prop_it->packed_transaction.data(), prop_it->packed_transaction.size(),
bytes packed_provided_approvals = pack(apps.provided_approvals);
auto res = ::check_transaction_authorization( prop.packed_transaction.data(), prop.packed_transaction.size(),
(const char*)0, 0,
packed_provided_approvals.data(), packed_provided_approvals.size()
);
eosio_assert( res > 0, "transaction authorization failed" );
send_deferred( (uint128_t(proposer) << 64) | proposal_name, executer, prop_it->packed_transaction.data(), prop_it->packed_transaction.size() );
send_deferred( (uint128_t(proposer) << 64) | proposal_name, executer, prop.packed_transaction.data(), prop.packed_transaction.size() );
proptable.erase(prop_it);
proptable.erase(prop);
apptable.erase(apps);
}
} /// namespace eosio
......
......@@ -17,13 +17,20 @@ namespace eosio {
private:
struct proposal {
name proposal_name;
vector<permission_level> requested_approvals;
vector<permission_level> provided_approvals;
vector<char> packed_transaction;
auto primary_key()const { return proposal_name.value; }
};
typedef eosio::multi_index<N(proposal),proposal> proposals;
struct approvals_info {
name proposal_name;
vector<permission_level> requested_approvals;
vector<permission_level> provided_approvals;
auto primary_key()const { return proposal_name.value; }
};
typedef eosio::multi_index<N(approvals),approvals_info> approvals;
};
} /// namespace eosio
......@@ -98,10 +98,9 @@ namespace eosiosystem {
const authority& owner,
const authority& active*/ ) {
auto name_str = eosio::name{newact}.to_string();
eosio::print( eosio::name{creator}, " created ", eosio::name{newact}, "\n");
eosio_assert( name_str.size() == 12, "account names must be 12 chars long" );
eosio_assert( name_str.find_first_of('.') == std::string::npos, "account names cannot contain '.' character");
eosio_assert( name_str.size() == 12 || creator == N(eosio), "account names must be 12 chars long" );
eosio_assert( name_str.find_first_of('.') == std::string::npos || creator == N(eosio), "account names cannot contain '.' character");
user_resources_table userres( _self, newact);
......@@ -123,7 +122,6 @@ namespace eosiosystem {
auto itr = _rammarket.find(S(4,RAMEOS));
auto tmp = *itr;
auto eosout = tmp.convert( asset(bytes,S(0,RAM)), S(4,EOS) );
print( "eosout: ", eosout, " ", tmp.base.balance, " ", tmp.quote.balance, "\n" );
buyram( payer, receiver, eosout );
}
......@@ -139,7 +137,6 @@ namespace eosiosystem {
*/
void system_contract::buyram( account_name payer, account_name receiver, asset quant )
{
// print( "\n payer: ", eosio::name{payer}, " buys ram for ", eosio::name{receiver}, " with ", quant, "\n" );
require_auth( payer );
eosio_assert( quant.amount > 0, "must purchase a positive amount" );
......@@ -148,7 +145,6 @@ namespace eosiosystem {
{ payer, N(eosio), quant, std::string("buy ram") } );
}
// print( "free ram: ", _gstate.free_ram(), "\n");
int64_t bytes_out;
......@@ -157,12 +153,11 @@ namespace eosiosystem {
bytes_out = es.convert( quant, S(0,RAM) ).amount;
});
// print( "ram bytes out: ", bytes_out, "\n" );
eosio_assert( bytes_out > 0, "must reserve a positive amount" );
_gstate.total_ram_bytes_reserved += uint64_t(bytes_out);
_gstate.total_ram_stake.amount += quant.amount;
_gstate.total_ram_stake += quant.amount;
user_resources_table userres( _self, receiver );
auto res_itr = userres.find( receiver );
......@@ -185,28 +180,27 @@ namespace eosiosystem {
* refunds the purchase price to the account. In this way there is no profit to be made through buying
* and selling ram.
*/
void system_contract::sellram( account_name account, uint64_t bytes ) {
void system_contract::sellram( account_name account, int64_t bytes ) {
require_auth( account );
int64_t ibytes = static_cast<int64_t>(bytes);
eosio_assert( bytes > 0, "cannot sell negative byte" );
user_resources_table userres( _self, account );
auto res_itr = userres.find( account );
eosio_assert( res_itr != userres.end(), "no resource row" );
eosio_assert( res_itr->ram_bytes >= ibytes, "insufficient quota" );
eosio_assert( res_itr->ram_bytes >= bytes, "insufficient quota" );
asset tokens_out;
auto itr = _rammarket.find(S(4,RAMEOS));
_rammarket.modify( itr, 0, [&]( auto& es ) {
/// the cast to int64_t of bytes is safe because we certify bytes is <= quota which is limited by prior purchases
tokens_out = es.convert( asset(ibytes,S(0,RAM)), S(4,EOS) );
// print( "out: ", tokens_out, "\n" );
tokens_out = es.convert( asset(bytes,S(0,RAM)), S(4,EOS) );
});
_gstate.total_ram_bytes_reserved -= bytes;
_gstate.total_ram_stake.amount -= tokens_out.amount;
_gstate.total_ram_stake -= tokens_out.amount;
//// this shouldn't happen, but just in case it does we should prevent it
eosio_assert( _gstate.total_ram_stake.amount >= 0, "error, attempt to unstake more tokens than previously staked" );
eosio_assert( _gstate.total_ram_stake >= 0, "error, attempt to unstake more tokens than previously staked" );
userres.modify( res_itr, account, [&]( auto& res ) {
res.ram_bytes -= bytes;
......@@ -225,7 +219,6 @@ namespace eosiosystem {
{
require_auth( from );
// print( "from: ", eosio::name{from}, " to: ", eosio::name{receiver}, " net: ", stake_net_quantity, " cpu: ", stake_cpu_quantity );
eosio_assert( stake_cpu_quantity >= asset(0), "must stake a positive amount" );
eosio_assert( stake_net_quantity >= asset(0), "must stake a positive amount" );
......
......@@ -87,24 +87,26 @@
"name": "blockchain_parameters",
"base": "",
"fields": [
{"name":"max_block_net_usage", "type": "uint32"},
{"name":"target_block_net_usage_pct", "type": "uint32"},
{"name":"max_transaction_net_usage", "type":"uint32"},
{"name":"base_per_transaction_net_usage", "type":"uint32"},
{"name":"net_usage_leeway", "type":"uint32"},
{"name":"max_block_net_usage", "type":"uint64"},
{"name":"target_block_net_usage_pct", "type":"uint32"},
{"name":"max_transaction_net_usage", "type":"uint32"},
{"name":"base_per_transaction_net_usage", "type":"uint32"},
{"name":"net_usage_leeway", "type":"uint32"},
{"name":"context_free_discount_net_usage_num", "type":"uint32"},
{"name":"context_free_discount_net_usage_den", "type":"uint32"},
{"name":"max_block_cpu_usage", "type": "uint64"},
{"name":"target_block_cpu_usage_pct", "type": "uint32"},
{"name":"max_transaction_cpu_usage", "type":"uint32"},
{"name":"min_transaction_cpu_usage", "type":"uint32"},
{"name":"max_transaction_lifetime", "type":"uint32"},
{"name":"deferred_trx_expiration_window", "type":"uint32"},
{"name":"max_transaction_delay", "type":"uint32"},
{"name":"max_inline_action_size", "type":"uint32"},
{"name":"max_inline_action_depth", "type":"uint16"},
{"name":"max_authority_depth", "type":"uint16"},
{"name":"max_generated_transaction_count", "type":"uint32"}
{"name":"max_block_cpu_usage", "type":"uint32"},
{"name":"target_block_cpu_usage_pct", "type":"uint32"},
{"name":"max_transaction_cpu_usage", "type":"uint32"},
{"name":"min_transaction_cpu_usage", "type":"uint32"},
{"name":"max_transaction_lifetime", "type":"uint32"},
{"name":"deferred_trx_expiration_window", "type":"uint32"},
{"name":"max_transaction_delay", "type":"uint32"},
{"name":"max_inline_action_size", "type":"uint32"},
{"name":"max_inline_action_depth", "type":"uint16"},
{"name":"max_authority_depth", "type":"uint16"},
{"name":"max_generated_transaction_count", "type":"uint32"}
]
},{
"name": "eosio_parameters",
......@@ -117,13 +119,16 @@
"base": "eosio_parameters",
"fields": [
{"name":"total_ram_bytes_reserved", "type":"uint64"},
{"name":"total_ram_stake", "type":"asset"},
{"name":"total_ram_stake", "type":"int64"},
{"name":"last_producer_schedule_update", "type":"time_point_sec"},
{"name":"last_pervote_bucket_fill", "type":"uint64"},
{"name":"pervote_bucket", "type":"asset"},
{"name":"savings", "type":"asset"},
{"name":"pervote_bucket", "type":"int64"},
{"name":"perblock_bucket", "type":"int64"},
{"name":"savings", "type":"int64"},
{"name":"total_unpaid_blocks", "type":"uint32"},
{"name":"total_activated_stake", "type":"int64"},
{"name":"last_producer_schedule_id", "type":"checksum160"},
{"name":"total_activatied_stake", "type":"int64"}
{"name":"total_producer_vote_weight", "type":"float64"}
]
},{
"name": "producer_info",
......@@ -133,7 +138,7 @@
{"name":"total_votes", "type":"float64"},
{"name":"producer_key", "type":"public_key"},
{"name":"url", "type":"string"},
{"name":"produced_blocks", "type":"uint32"},
{"name":"unpaid_blocks", "type":"uint32"},
{"name":"last_claim_time", "type":"uint64"},
{"name":"location", "type":"uint16"},
{"name":"time_became_active", "type":"uint32"},
......@@ -196,7 +201,14 @@
"fields": [
{"name":"owner", "type":"account_name"}
]
}
},{
"name": "setpriv",
"base": "",
"fields": [
{"name":"account", "type":"account_name"},
{"name":"is_priv", "type":"int8"}
]
}
],
"actions": [
{
......@@ -247,6 +259,10 @@
"name": "claimrewards",
"type": "claimrewards",
"ricardian_contract": ""
},{
"name": "setpriv",
"type": "setpriv",
"ricardian_contract": ""
}
],
"tables": [{
......
......@@ -72,6 +72,11 @@ namespace eosiosystem {
_global.set( _gstate, _self );
}
void system_contract::setpriv( account_name account, uint8_t ispriv ) {
require_auth( _self );
set_privileged( account, ispriv );
}
} /// eosio.system
......@@ -85,7 +90,8 @@ EOSIO_ABI( eosiosystem::system_contract,
(regproxy)(regproducer)(unregprod)(voteproducer)
(claimrewards)
// native.hpp
//XXX
(onblock)
(newaccount)(updateauth)(deleteauth)(linkauth)(unlinkauth)(postrecovery)(passrecovery)(vetorecovery)(onerror)(canceldelay)
//this file
(setpriv)
)
......@@ -6,6 +6,7 @@
#include <eosio.system/native.hpp>
#include <eosiolib/asset.hpp>
#include <eosiolib/time.hpp>
#include <eosiolib/privileged.hpp>
#include <eosiolib/singleton.hpp>
#include <eosio.system/exchange_state.hpp>
......@@ -17,6 +18,7 @@ namespace eosiosystem {
using eosio::asset;
using eosio::indexed_by;
using eosio::const_mem_fun;
using eosio::block_timestamp;
struct eosio_parameters : eosio::blockchain_parameters {
uint64_t max_ram_size = 64ll*1024 * 1024 * 1024;
......@@ -29,21 +31,23 @@ namespace eosiosystem {
uint64_t free_ram()const { return max_ram_size - total_ram_bytes_reserved; }
uint64_t total_ram_bytes_reserved = 0;
eosio::asset total_ram_stake;
int64_t total_ram_stake = 0;
block_timestamp last_producer_schedule_update = 0;
block_timestamp last_producer_schedule_update;
uint64_t last_pervote_bucket_fill = 0;
eosio::asset pervote_bucket;
eosio::asset savings;
checksum160 last_producer_schedule_id;
int64_t pervote_bucket = 0;
int64_t perblock_bucket = 0;
int64_t savings = 0;
uint32_t total_unpaid_blocks = 0; /// all blocks which have been produced but not paid
int64_t total_activated_stake = 0;
checksum160 last_producer_schedule_id;
double total_producer_vote_weight = 0; /// the sum of all producer votes
// explicit serialization macro is not necessary, used here only to improve compilation time
EOSLIB_SERIALIZE_DERIVED( eosio_global_state, eosio_parameters, (total_ram_bytes_reserved)(total_ram_stake)
(last_producer_schedule_update)
(last_pervote_bucket_fill)
(pervote_bucket)(savings)(last_producer_schedule_id)(total_activated_stake) )
(pervote_bucket)(perblock_bucket)(savings)(total_unpaid_blocks)(total_activated_stake)(last_producer_schedule_id)(total_producer_vote_weight) )
};
struct producer_info {
......@@ -51,11 +55,11 @@ namespace eosiosystem {
double total_votes = 0;
eosio::public_key producer_key; /// a packed public key object
std::string url;
uint32_t produced_blocks;
uint32_t unpaid_blocks = 0;
uint64_t last_claim_time = 0;
uint16_t location = 0;
block_timestamp time_became_active = 0;
block_timestamp last_produced_block_time = 0;
block_timestamp time_became_active;
block_timestamp last_produced_block_time;
uint64_t primary_key()const { return owner; }
double by_votes()const { return -total_votes; }
......@@ -63,7 +67,7 @@ namespace eosiosystem {
// explicit serialization macro is not necessary, used here only to improve compilation time
EOSLIB_SERIALIZE( producer_info, (owner)(total_votes)(producer_key)(url)
(produced_blocks)(last_claim_time)(location)
(unpaid_blocks)(last_claim_time)(location)
(time_became_active)(last_produced_block_time) )
};
......@@ -125,7 +129,7 @@ namespace eosiosystem {
~system_contract();
// Actions:
void onblock( uint32_t timestamp_slot, account_name producer );
void onblock( block_timestamp timestamp, account_name producer );
// const block_header& header ); /// only parse first 3 fields of block header
// functions defined in delegate_bandwidth.cpp
......@@ -171,7 +175,7 @@ namespace eosiosystem {
* Reduces quota my bytes and then performs an inline transfer of tokens
* to receiver based upon the average purchase price of the original quota.
*/
void sellram( account_name receiver, uint64_t bytes );
void sellram( account_name receiver, int64_t bytes );
/**
* This action is called after the delegation-period to claim all pending
......@@ -194,13 +198,9 @@ namespace eosiosystem {
// functions defined in producer_pay.cpp
void claimrewards( const account_name& owner );
private:
eosio::asset payment_per_block( double rate, const eosio::asset& token_supply, uint32_t num_blocks );
eosio::asset payment_per_vote( const account_name& owner, double owners_votes, const eosio::asset& pervote_bucket );
eosio::asset supply_growth( double rate, const eosio::asset& token_supply, time seconds );
void setpriv( account_name account, uint8_t ispriv );
private:
void update_elected_producers( block_timestamp timestamp );
// Implementation details:
......
......@@ -6,24 +6,16 @@ namespace eosiosystem {
const int64_t min_daily_tokens = 100;
const double continuous_rate = 0.04879; // 5% annual rate
const double perblock_rate = 0.0025; // 0.25%
const double standby_rate = 0.0075; // 0.75%
const uint32_t blocks_per_year = 52*7*24*2*3600; // half seconds per year
const uint32_t seconds_per_year = 52*7*24*3600;
const uint32_t blocks_per_day = 2 * 24 * 3600;
const uint32_t blocks_per_hour = 2 * 3600;
const uint64_t useconds_per_day = 24 * 3600 * uint64_t(1000000);
eosio::asset system_contract::payment_per_block( double rate, const eosio::asset& token_supply, uint32_t num_blocks ) {
const int64_t payment = static_cast<int64_t>( (rate * double(token_supply.amount) * double(num_blocks)) / double(blocks_per_year) );
return eosio::asset( payment, token_supply.symbol );
}
const double continuous_rate = 0.04879; // 5% annual rate
const double perblock_rate = 0.0025; // 0.25%
const double standby_rate = 0.0075; // 0.75%
const uint32_t blocks_per_year = 52*7*24*2*3600; // half seconds per year
const uint32_t seconds_per_year = 52*7*24*3600;
const uint32_t blocks_per_day = 2 * 24 * 3600;
const uint32_t blocks_per_hour = 2 * 3600;
const uint64_t useconds_per_day = 24 * 3600 * uint64_t(1000000);
const uint64_t useconds_per_year = seconds_per_year*1000000ll;
eosio::asset system_contract::supply_growth( double rate, const eosio::asset& token_supply, time seconds ) {
const int64_t payment = static_cast<int64_t>( (rate * double(token_supply.amount) * double(seconds)) / double(seconds_per_year) );
return eosio::asset( payment, token_supply.symbol );
}
void system_contract::onblock( block_timestamp timestamp, account_name producer ) {
using namespace eosio;
......@@ -37,107 +29,78 @@ namespace eosiosystem {
if( _gstate.last_pervote_bucket_fill == 0 ) /// start the presses
_gstate.last_pervote_bucket_fill = current_time();
/**
* At startup the initial producer may not be one that is registered / elected
* and therefore there may be no producer object for them.
*/
auto prod = _producers.find(producer);
if ( prod != _producers.end() ) {
_gstate.total_unpaid_blocks++;
_producers.modify( prod, 0, [&](auto& p ) {
p.produced_blocks++;
p.unpaid_blocks++;
p.last_produced_block_time = timestamp;
});
}
/// only update block producers once every minute, block_timestamp is in half seconds
if( timestamp - _gstate.last_producer_schedule_update > 120 ) {
if( timestamp.slot - _gstate.last_producer_schedule_update.slot > 120 ) {
update_elected_producers( timestamp );
}
}
eosio::asset system_contract::payment_per_vote( const account_name& owner, double owners_votes, const eosio::asset& pervote_bucket ) {
eosio::asset payment(0, S(4,EOS));
const int64_t min_daily_amount = 100 * 10000;
if ( pervote_bucket.amount < min_daily_amount ) {
return payment;
}
auto idx = _producers.template get_index<N(prototalvote)>();
double total_producer_votes = 0;
double running_payment_amount = 0;
bool to_be_payed = false;
for ( auto itr = idx.cbegin(); itr != idx.cend(); ++itr ) {
if ( !(itr->total_votes > 0) ) {
break;
}
if ( !itr->active() ) {
continue;
}
if ( itr->owner == owner ) {
to_be_payed = true;
}
total_producer_votes += itr->total_votes;
running_payment_amount = (itr->total_votes) * double(pervote_bucket.amount) / total_producer_votes;
if ( running_payment_amount < min_daily_amount ) {
if ( itr->owner == owner ) {
to_be_payed = false;
}
total_producer_votes -= itr->total_votes;
break;
}
}
if ( to_be_payed ) {
payment.amount = static_cast<int64_t>( (double(pervote_bucket.amount) * owners_votes) / total_producer_votes );
}
return payment;
}
using namespace eosio;
void system_contract::claimrewards( const account_name& owner ) {
using namespace eosio;
require_auth(owner);
auto prod = _producers.find( owner );
eosio_assert( prod != _producers.end(), "account name is not in producer list" );
eosio_assert( prod->active(), "producer does not have an active key" );
if( prod->last_claim_time > 0 ) {
eosio_assert(current_time() >= prod->last_claim_time + useconds_per_day, "already claimed rewards within a day");
}
const auto& prod = _producers.get( owner );
eosio_assert( prod.active(), "producer does not have an active key" );
const asset token_supply = token( N(eosio.token)).get_supply(symbol_type(system_token_symbol).name() );
const uint32_t secs_since_last_fill = static_cast<uint32_t>( (current_time() - _gstate.last_pervote_bucket_fill) / 1000000 );
auto ct = current_time();
const asset to_pervote_bucket = supply_growth( standby_rate, token_supply, secs_since_last_fill );
const asset to_savings = supply_growth( continuous_rate - (perblock_rate + standby_rate), token_supply, secs_since_last_fill );
const asset perblock_pay = payment_per_block( perblock_rate, token_supply, prod->produced_blocks );
const asset issue_amount = to_pervote_bucket + to_savings + perblock_pay;
const asset pervote_pay = payment_per_vote( owner, prod->total_votes, to_pervote_bucket + _gstate.pervote_bucket );
eosio_assert( ct - prod.last_claim_time > useconds_per_day, "already claimed rewards within past day" );
if ( perblock_pay.amount + pervote_pay.amount == 0 ) {
_producers.modify( prod, 0, [&](auto& p) {
p.last_claim_time = current_time();
});
return;
const asset token_supply = token( N(eosio.token)).get_supply(symbol_type(system_token_symbol).name() );
const auto usecs_since_last_fill = ct - _gstate.last_pervote_bucket_fill;
if( usecs_since_last_fill > 0 ) {
auto new_tokens = static_cast<int64_t>( (continuous_rate * double(token_supply.amount) * double(usecs_since_last_fill)) / double(useconds_per_year) );
auto to_producers = new_tokens / 5;
auto to_savings = new_tokens - to_producers;
auto to_per_block_pay = to_producers / 4;
auto to_per_vote_pay = to_producers - to_per_block_pay;
INLINE_ACTION_SENDER(eosio::token, issue)( N(eosio.token), {{N(eosio),N(active)}},
{N(eosio), asset(new_tokens), std::string("issue tokens for producer pay and savings")} );
_gstate.pervote_bucket += to_per_vote_pay;
_gstate.perblock_bucket += to_per_block_pay;
_gstate.savings += to_savings;
_gstate.last_pervote_bucket_fill = ct;
}
INLINE_ACTION_SENDER(eosio::token, issue)( N(eosio.token), {{N(eosio),N(active)}},
{N(eosio), issue_amount, std::string("issue tokens for producer pay and savings")} );
_gstate.pervote_bucket += ( to_pervote_bucket - pervote_pay );
_gstate.last_pervote_bucket_fill = current_time();
_gstate.savings += to_savings;
INLINE_ACTION_SENDER(eosio::token, transfer)( N(eosio.token), {N(eosio),N(active)},
{ N(eosio), owner, perblock_pay + pervote_pay, std::string("producer claiming rewards") } );
int64_t producer_per_block_pay = (_gstate.perblock_bucket * prod.unpaid_blocks) / _gstate.total_unpaid_blocks;
int64_t producer_per_vote_pay = int64_t((_gstate.pervote_bucket * prod.total_votes ) / _gstate.total_producer_vote_weight);
if( producer_per_vote_pay < 100'0000 ) {
producer_per_vote_pay = 0;
}
int64_t total_pay = producer_per_block_pay + producer_per_vote_pay;
_producers.modify( prod, 0, [&](auto& p) {
p.last_claim_time = current_time();
p.produced_blocks = 0;
});
_gstate.pervote_bucket -= producer_per_vote_pay;
_gstate.perblock_bucket -= producer_per_block_pay;
_gstate.total_unpaid_blocks -= prod.unpaid_blocks;
_producers.modify( prod, 0, [&](auto& p) {
p.last_claim_time = ct;
p.unpaid_blocks = 0;
});
if( total_pay > 0 ) {
INLINE_ACTION_SENDER(eosio::token, transfer)( N(eosio.token), {N(eosio),N(active)},
{ N(eosio), owner, asset(total_pay), std::string("producer pay") } );
}
}
} //namespace eosiosystem
......@@ -53,7 +53,7 @@ namespace eosiosystem {
_producers.emplace( producer, [&]( producer_info& info ){
info.owner = producer;
info.total_votes = 0;
info.producer_key = producer_key;
info.producer_key = producer_key;
info.url = url;
info.location = location;
});
......@@ -81,15 +81,15 @@ namespace eosiosystem {
for ( auto it = idx.cbegin(); it != idx.cend() && top_producers.size() < 21 && 0 < it->total_votes; ++it ) {
if( !it->active() ) continue;
if ( it->time_became_active == 0 ) {
if ( it->time_became_active.slot == 0 ) {
_producers.modify( *it, 0, [&](auto& p) {
p.time_became_active = block_time;
});
} else if ( block_time > 2 * 21 * 12 + it->time_became_active &&
block_time > it->last_produced_block_time + blocks_per_day ) {
} else if ( block_time.slot > 2 * 21 * 12 + it->time_became_active.slot &&
block_time.slot > it->last_produced_block_time.slot + blocks_per_day ) {
_producers.modify( *it, 0, [&](auto& p) {
p.producer_key = public_key();
p.time_became_active = 0;
p.time_became_active.slot = 0;
});
continue;
......@@ -216,9 +216,8 @@ namespace eosiosystem {
if( pitr != _producers.end() ) {
eosio_assert( pitr->active() || !pd.second.second /* not from new set */, "producer is not currently registered" );
_producers.modify( pitr, 0, [&]( auto& p ) {
print( "orig total_votes: ", p.total_votes, " delta: ", pd.second.first, "\n" );
p.total_votes += pd.second.first;
print( "new total_votes: ", p.total_votes, "\n" );
_gstate.total_producer_vote_weight += pd.second.first;
//eosio_assert( p.total_votes >= 0, "something bad happened" );
});
} else {
......@@ -282,12 +281,13 @@ namespace eosiosystem {
);
propagate_weight_change( proxy );
} else {
auto delta = new_weight - voter.last_vote_weight;
for ( auto acnt : voter.producers ) {
auto& pitr = _producers.get( acnt, "producer not found" ); //data corruption
_producers.modify( pitr, 0, [&]( auto& p ) {
p.total_votes += new_weight - voter.last_vote_weight;
}
);
p.total_votes += delta;
_gstate.total_producer_vote_weight += delta;
});
}
}
}
......
......@@ -14,10 +14,7 @@
"base": "",
"fields": [
{"name":"issuer", "type":"account_name"},
{"name":"maximum_supply", "type":"asset"},
{"name":"can_freeze", "type":"uint8"},
{"name":"can_recall", "type":"uint8"},
{"name":"can_whitelist", "type":"uint8"}
{"name":"maximum_supply", "type":"asset"}
]
},{
"name": "issue",
......@@ -31,9 +28,7 @@
"name": "account",
"base": "",
"fields": [
{"name":"balance", "type":"asset"},
{"name":"frozen", "type":"uint8"},
{"name":"whitelist", "type":"uint8"}
{"name":"balance", "type":"asset"}
]
},{
"name": "currency_stats",
......@@ -41,12 +36,7 @@
"fields": [
{"name":"supply", "type":"asset"},
{"name":"max_supply", "type":"asset"},
{"name":"issuer", "type":"account_name"},
{"name":"can_freeze", "type":"uint8"},
{"name":"can_recall", "type":"uint8"},
{"name":"can_whitelist", "type":"uint8"},
{"name":"is_frozen", "type":"uint8"},
{"name":"enforce_whitelist", "type":"uint8"}
{"name":"issuer", "type":"account_name"}
]
}
],
......
......@@ -8,10 +8,7 @@
namespace eosio {
void token::create( account_name issuer,
asset maximum_supply,
uint8_t issuer_can_freeze,
uint8_t issuer_can_recall,
uint8_t issuer_can_whitelist )
asset maximum_supply )
{
require_auth( _self );
......@@ -28,9 +25,6 @@ void token::create( account_name issuer,
s.supply.symbol = maximum_supply.symbol;
s.max_supply = maximum_supply;
s.issuer = issuer;
s.can_freeze = issuer_can_freeze;
s.can_recall = issuer_can_recall;
s.can_whitelist = issuer_can_whitelist;
});
}
......@@ -94,15 +88,6 @@ void token::sub_balance( account_name owner, asset value, const currency_stats&
const auto& from = from_acnts.get( value.symbol.name() );
eosio_assert( from.balance.amount >= value.amount, "overdrawn balance" );
if( has_auth( owner ) ) {
eosio_assert( !st.can_freeze || !from.frozen, "account is frozen by issuer" );
eosio_assert( !st.can_freeze || !st.is_frozen, "all transfers are frozen by issuer" );
eosio_assert( !st.enforce_whitelist || from.whitelist, "account is not white listed" );
} else if( has_auth( st.issuer ) ) {
eosio_assert( st.can_recall, "issuer may not recall token" );
} else {
eosio_assert( false, "insufficient authority" );
}
if( from.balance.amount == value.amount ) {
from_acnts.erase( from );
......@@ -118,12 +103,10 @@ void token::add_balance( account_name owner, asset value, const currency_stats&
accounts to_acnts( _self, owner );
auto to = to_acnts.find( value.symbol.name() );
if( to == to_acnts.end() ) {
eosio_assert( !st.enforce_whitelist, "can only transfer to white listed accounts" );
to_acnts.emplace( ram_payer, [&]( auto& a ){
a.balance = value;
});
} else {
eosio_assert( !st.enforce_whitelist || to->whitelist, "receiver requires whitelist by issuer" );
to_acnts.modify( to, 0, [&]( auto& a ) {
a.balance += value;
});
......
......@@ -22,11 +22,7 @@ namespace eosio {
token( account_name self ):contract(self){}
void create( account_name issuer,
asset maximum_supply,
uint8_t issuer_can_freeze,
uint8_t issuer_can_recall,
uint8_t issuer_can_whitelist );
asset maximum_supply);
void issue( account_name to, asset quantity, string memo );
......@@ -46,8 +42,6 @@ namespace eosio {
private:
struct account {
asset balance;
bool frozen = false;
bool whitelist = true;
uint64_t primary_key()const { return balance.symbol.name(); }
};
......@@ -56,11 +50,6 @@ namespace eosio {
asset supply;
asset max_supply;
account_name issuer;
bool can_freeze = true;
bool can_recall = true;
bool can_whitelist = true;
bool is_frozen = false;
bool enforce_whitelist = false;
uint64_t primary_key()const { return supply.symbol.name(); }
};
......
......@@ -209,7 +209,7 @@ inline datastream<Stream>& operator>>(datastream<Stream>& ds, bool& d) {
*/
template<typename Stream>
inline datastream<Stream>& operator<<(datastream<Stream>& ds, const checksum256& d) {
ds.write( (const char*)&d, sizeof(d) );
ds.write( (const char*)&d.hash[0], sizeof(d.hash) );
return ds;
}
/**
......@@ -220,7 +220,7 @@ inline datastream<Stream>& operator<<(datastream<Stream>& ds, const checksum256&
*/
template<typename Stream>
inline datastream<Stream>& operator>>(datastream<Stream>& ds, checksum256& d) {
ds.read((char*)&d, sizeof(d) );
ds.read((char*)&d.hash[0], sizeof(d.hash) );
return ds;
}
......@@ -514,25 +514,25 @@ bytes pack( const T& value ) {
template<typename Stream>
inline datastream<Stream>& operator<<(datastream<Stream>& ds, const checksum160& cs) {
ds.write((const char*)&cs, sizeof(cs));
ds.write((const char*)&cs.hash[0], sizeof(cs.hash));
return ds;
}
template<typename Stream>
inline datastream<Stream>& operator>>(datastream<Stream>& ds, checksum160& cs) {
ds.read((char*)&cs, sizeof(cs));
ds.read((char*)&cs.hash[0], sizeof(cs.hash));
return ds;
}
template<typename Stream>
inline datastream<Stream>& operator<<(datastream<Stream>& ds, const checksum512& cs) {
ds.write((const char*)&cs, sizeof(cs));
ds.write((const char*)&cs.hash[0], sizeof(cs.hash));
return ds;
}
template<typename Stream>
inline datastream<Stream>& operator>>(datastream<Stream>& ds, checksum512& cs) {
ds.read((char*)&cs, sizeof(cs));
ds.read((char*)&cs.hash[0], sizeof(cs.hash));
return ds;
}
......
......@@ -24,7 +24,6 @@ typedef uint64_t permission_name;
typedef uint64_t token_name;
typedef uint64_t table_name;
typedef uint32_t time;
typedef uint32_t block_timestamp;
typedef uint64_t scope_name;
typedef uint64_t action_name;
typedef uint16_t region_id;
......
# The Block Producer Agreement
As a Block Producer (BP), I/we promise to:
1. Produce exactly the authorized number of blocks faithfully, accurately, at the appointed time in the rotation
2. Never produce and sign two or more blocks with the same block height or block interval
3. Never censor governance related transactions such as votes or Arbitration related transactions
4. Only add "good" transactions from the transaction pool to the block
5. Make a good faith effort to include as many "good" transactions as possible to the block without undue discrimination
6. Exclude "bad" transactions from the block, and publish why they were excluded
7. Show no favoritism among transactions, ordering them in a FIFO fashion or using some other ordering mechanism that is declared publicly in advance, including the default ordering provided by the unmodified software
8. Refrain from using my/our superior information to "front run" transactions nor enabling anyone else to “front run”
9. Accept as valid any Arbitrator’s order that’s
1. signed by an Arbitrator
2. that the chain shows was assigned to a Case,
3. such that the order affects only the Accounts named in that Case, and
4. the Arbitrator is in good standing with their Arbitration Forum, and
5. the original Transaction that gave rise to the Case names that Arbitration Forum as the venue for dispute resolution
10. Only freeze accounts when authorized to do so by a valid Arbitrator’s order
11. Always file a dispute against myself/ourselves after taking initiative to act on an emergency
12. Provide at least four (4) public endpoints running full nodes (the Minimum Configuration)
13. Not requesting my/our daily Vote Bonus pay on days when I/we don’t have the Minimum Configuration running, and repaying any Vote Bonus income collected while the Minimum Configuration wasn’t running
14. Disclosing all ownership of my/our organization greater than 10%
15. Not sharing more than 10% ownership with another BP
# Article I
No user of this blockchain shall make knowingly false or misleading statements, nor statements that constitute discrimination or harassment, nor profit thereby.
# Article II
The rights of contract and of private property shall be inviolable, therefore no property shall change hands except with the consent of the owner or by a lawful Arbitrator’s order.
# Article III
Each Member agrees to resolve disputes through the blockchain’s default arbitration process, or any other process that the parties to a transaction may mutually agree to in advance.
# Article IV
No Member shall offer nor accept anything of value in exchange for a vote of any type, including for Block Producer candidates, Amendments or Worker Proposals, nor shall any Member unduly influence the vote of another.
# Article V
This EOS Blockchain has no owner, manager or fiduciary. It is governed exclusively under the terms of this Constitution.
# Article VI
No Member nor any Beneficial Interest shall own more than 10% of issued tokens.
# Article VII
Each Member agrees that penalties for violations may include, but are not limited to, fines, account freezing, and reversal of transactions.
# Article VIII
No Member shall serve as a Block Producer who has not agreed in advance to the Block Producer Agreement provided by the Members of this blockchain.
# Article IX
No Arbitrator shall serve except within an Arbitration Forum.
# Article X
No Member shall serve as an Arbitrator who has not
* Agreed in advance to the Arbitrator Agreement provided by the Members,
* Been nominated by at least two other Members, and
* Completed the course of study of, been certified by, and be in good standing with their Forum.
# Article XI
Each Member who makes available a smart contract on this blockchain shall be a Developer. Each Developer shall offer their smart contracts via a license, and each smart contract shall be documented with a Ricardian Contract stating the intent of all parties and naming the Arbitration Forum that will resolve disputes arising from that contract.
# Article XII
Multi-lingual contracts must specify the prevailing language in case of dispute.
# Article XIII
As Developers are able to offer services and provide interaction with the blockchain to non Members via their applications, the Developer assumes all responsibility for guaranteeing that non-Member interaction conforms to this Constitution.
# Article XIV
This Constitution creates no positive rights for or between any Members.
# Article XV
All disputes arising from this Constitution or its related governing documents shall be resolved using the EOS Core Arbitration Forum.
# Article XVI
This Constitution and its subordinate documents the Block Producer Agreement and Arbitrator Agreement shall not be amended except by a vote of the Token Holders with no less than 15% vote participation among eligible tokens and no fewer than 10% more Yes than No vote power, sustained for 30 continuous days within a 120 day period.
# Article XVII
Choice of law for disputes shall be, in order of precedence, this Constitution, the Maxims of Equity, and the laws of Malta.
......@@ -7,7 +7,7 @@
#include <eosio/chain/types.hpp>
#include <eosio/chain/symbol.hpp>
/// eos with 8 digits of precision
/// eos with 4 digits of precision
#define EOS_SYMBOL_VALUE (int64_t(4) | (uint64_t('E') << 8) | (uint64_t('O') << 16) | (uint64_t('S') << 24))
static const eosio::chain::symbol EOS_SYMBOL(EOS_SYMBOL_VALUE);
......
......@@ -1947,11 +1947,14 @@ namespace eosio {
auto port = c->peer_addr.substr( colon + 1);
idump((host)(port));
tcp::resolver::query query( tcp::v4(), host.c_str(), port.c_str() );
connection_wptr weak_conn = c;
// Note: need to add support for IPv6 too
resolver->async_resolve( query,
[c, this]( const boost::system::error_code& err,
[weak_conn, this]( const boost::system::error_code& err,
tcp::resolver::iterator endpoint_itr ){
auto c = weak_conn.lock();
if (!c) return;
if( !err ) {
connect( c, endpoint_itr );
} else {
......@@ -1969,7 +1972,10 @@ namespace eosio {
auto current_endpoint = *endpoint_itr;
++endpoint_itr;
c->connecting = true;
c->socket->async_connect( current_endpoint, [c, endpoint_itr, this] ( const boost::system::error_code& err ) {
connection_wptr weak_conn = c;
c->socket->async_connect( current_endpoint, [weak_conn, endpoint_itr, this] ( const boost::system::error_code& err ) {
auto c = weak_conn.lock();
if (!c) return;
if( !err ) {
start_session( c );
c->send_handshake ();
......@@ -2437,6 +2443,7 @@ namespace eosio {
try {
chain_plug->accept_transaction( msg);
fc_dlog(logger, "chain accepted transaction" );
dispatcher->bcast_transaction(msg);
return;
}
catch( const fc::exception &ex) {
......
......@@ -153,7 +153,7 @@ struct txn_test_gen_plugin_impl {
act.account = N(eosio.token);
act.name = N(create);
act.authorization = vector<permission_level>{{newaccountC,config::active_name}};
act.data = eosio_token_serializer.variant_to_binary("create", fc::json::from_string("{\"issuer\":\"eosio.token\",\"maximum_supply\":\"1000000000.0000 CUR\", \"can_freeze\":0, \"can_recall\":0, \"can_whitelist\":0}}"));
act.data = eosio_token_serializer.variant_to_binary("create", fc::json::from_string("{\"issuer\":\"eosio.token\",\"maximum_supply\":\"1000000000.0000 CUR\"}}"));
trx.actions.push_back(act);
}
{
......
......@@ -918,6 +918,97 @@ struct vote_producers_subcommand {
}
};
struct approve_producer_subcommand {
eosio::name voter;
eosio::name producer_name;
approve_producer_subcommand(CLI::App* actionRoot) {
auto approve_producer = actionRoot->add_subcommand("approve", localized("Add one producer to list of voted producers"));
approve_producer->add_option("voter", voter, localized("The voting account"))->required();
approve_producer->add_option("producer", producer_name, localized("The account to vote for"))->required();
add_standard_transaction_options(approve_producer);
approve_producer->set_callback([this] {
auto result = call(get_table_func, fc::mutable_variant_object("json", true)
("code", name(config::system_account_name).to_string())
("scope", name(config::system_account_name).to_string())
("table", "voters")
("table_key", "owner")
("lower_bound", voter.value)
("limit", 1)
);
auto res = result.as<eosio::chain_apis::read_only::get_table_rows_result>();
if ( res.rows.empty() || res.rows[0]["owner"].as_string() != name(voter).to_string() ) {
std::cerr << "Voter info not found for account " << voter << std::endl;
return;
}
FC_ASSERT( 1 == res.rows.size(), "More than one voter_info for account" );
auto prod_vars = res.rows[0]["producers"].get_array();
vector<eosio::name> prods;
for ( auto& x : prod_vars ) {
prods.push_back( name(x.as_string()) );
}
prods.push_back( producer_name );
std::sort( prods.begin(), prods.end() );
auto it = std::unique( prods.begin(), prods.end() );
if (it != prods.end() ) {
std::cerr << "Producer \"" << producer_name << "\" is already on the list." << std::endl;
return;
}
fc::variant act_payload = fc::mutable_variant_object()
("voter", voter)
("proxy", "")
("producers", prods);
send_actions({create_action({permission_level{voter,config::active_name}}, config::system_account_name, N(voteproducer), act_payload)});
});
}
};
struct unapprove_producer_subcommand {
eosio::name voter;
eosio::name producer_name;
unapprove_producer_subcommand(CLI::App* actionRoot) {
auto approve_producer = actionRoot->add_subcommand("unapprove", localized("Remove one producer from list of voted producers"));
approve_producer->add_option("voter", voter, localized("The voting account"))->required();
approve_producer->add_option("producer", producer_name, localized("The account to remove from voted producers"))->required();
add_standard_transaction_options(approve_producer);
approve_producer->set_callback([this] {
auto result = call(get_table_func, fc::mutable_variant_object("json", true)
("code", name(config::system_account_name).to_string())
("scope", name(config::system_account_name).to_string())
("table", "voters")
("table_key", "owner")
("lower_bound", voter.value)
("limit", 1)
);
auto res = result.as<eosio::chain_apis::read_only::get_table_rows_result>();
if ( res.rows.empty() || res.rows[0]["owner"].as_string() != name(voter).to_string() ) {
std::cerr << "Voter info not found for account " << voter << std::endl;
return;
}
FC_ASSERT( 1 == res.rows.size(), "More than one voter_info for account" );
auto prod_vars = res.rows[0]["producers"].get_array();
vector<eosio::name> prods;
for ( auto& x : prod_vars ) {
prods.push_back( name(x.as_string()) );
}
auto it = std::remove( prods.begin(), prods.end(), producer_name );
if (it == prods.end() ) {
std::cerr << "Cannot remove: producer \"" << producer_name << "\" is not on the list." << std::endl;
return;
}
prods.erase( it, prods.end() ); //should always delete only one element
fc::variant act_payload = fc::mutable_variant_object()
("voter", voter)
("proxy", "")
("producers", prods);
send_actions({create_action({permission_level{voter,config::active_name}}, config::system_account_name, N(voteproducer), act_payload)});
});
}
};
struct list_producers_subcommand {
bool print_json = false;
bool sort_names = false;
......@@ -2339,6 +2430,8 @@ int main( int argc, char** argv ) {
voteProducer->require_subcommand();
auto voteProxy = vote_producer_proxy_subcommand(voteProducer);
auto voteProducers = vote_producers_subcommand(voteProducer);
auto approveProducer = approve_producer_subcommand(voteProducer);
auto unapproveProducer = unapprove_producer_subcommand(voteProducer);
auto listProducers = list_producers_subcommand(system);
......
......@@ -122,7 +122,7 @@
printf "\\tInstalling LCOV.\\n"
if ! cd "${TEMP_DIR}"
then
printf "\\n\\tUnable to enter %s. Exiting now.\\n" "${TEMP_DIR}";
printf "\\n\\tUnable to enter %s. Exiting now.\\n" "${TEMP_DIR}"
exit 1;
fi
if ! git clone "https://github.com/linux-test-project/lcov.git"
......@@ -133,7 +133,7 @@
fi
if ! cd "${TEMP_DIR}/lcov"
then
printf "\\n\\tUnable to enter %s/lcov. Exiting now.\\n" "${TEMP_DIR}";
printf "\\n\\tUnable to enter %s/lcov. Exiting now.\\n" "${TEMP_DIR}"
exit 1;
fi
if ! sudo make install
......
此差异已折叠。
......@@ -410,9 +410,9 @@ mongodconf
printf "\\tExiting now.\\n\\n"
exit 1;
fi
printf "\\n\\tsecp256k1 successfully installed @ /usr/local/lib/libsecp256k1.a.\\n\\n"
printf "\\n\\tsecp256k1 successfully installed @ /usr/local/lib.\\n\\n"
else
printf "\\tsecp256k1 found @ /usr/local/lib/libsecp256k1.a.\\n"
printf "\\tsecp256k1 found @ /usr/local/lib.\\n"
fi
printf "\\n\\tChecking for LLVM with WASM support.\\n"
......
......@@ -101,6 +101,9 @@ try:
cluster.initializeNodes(defproduceraPrvtKey=defproduceraPrvtKey, defproducerbPrvtKey=defproducerbPrvtKey)
killEosInstances=False
Print("Validating system accounts after bootstrap")
cluster.validateAccounts(None)
accounts=testUtils.Cluster.createAccountKeys(3)
if accounts is None:
errorExit("FAILURE - create keys")
......@@ -223,12 +226,31 @@ try:
if node is None:
errorExit("Cluster in bad state, received None node")
Print("Validating accounts before user accounts creation")
cluster.validateAccounts(None)
Print("Create new account %s via %s" % (testeraAccount.name, defproduceraAccount.name))
transId=node.createInitializeAccount(testeraAccount, defproduceraAccount, stakedDeposit=0, waitForTransBlock=False)
if transId is None:
cmdError("%s create account" % (ClientName))
cmdError("%s create account" % (testeraAccount.name))
errorExit("Failed to create account %s" % (testeraAccount.name))
Print("Create new account %s via %s" % (currencyAccount.name, defproducerbAccount.name))
transId=node.createInitializeAccount(currencyAccount, defproducerbAccount, stakedDeposit=5000)
if transId is None:
cmdError("%s create account" % (ClientName))
errorExit("Failed to create account %s" % (currencyAccount.name))
Print("Create new account %s via %s" % (exchangeAccount.name, defproduceraAccount.name))
transId=node.createInitializeAccount(exchangeAccount, defproduceraAccount, waitForTransBlock=True)
if transId is None:
cmdError("%s create account" % (ClientName))
errorExit("Failed to create account %s" % (exchangeAccount.name))
Print("Validating accounts after user accounts creation")
accounts=[testeraAccount, currencyAccount, exchangeAccount]
cluster.validateAccounts(accounts)
Print("Verify account %s" % (testeraAccount))
if not node.verifyAccount(testeraAccount):
errorExit("FAILURE - account creation failed.", raw=True)
......@@ -262,17 +284,9 @@ try:
cmdError("FAILURE - transfer failed")
errorExit("Transfer verification failed. Excepted %s, actual: %s" % (expectedAmount, actualAmount))
Print("Create new account %s via %s" % (currencyAccount.name, defproducerbAccount.name))
transId=node.createInitializeAccount(currencyAccount, defproducerbAccount, stakedDeposit=5000)
if transId is None:
cmdError("%s create account" % (ClientName))
errorExit("Failed to create account %s" % (currencyAccount.name))
Print("Create new account %s via %s" % (exchangeAccount.name, defproduceraAccount.name))
transId=node.createInitializeAccount(exchangeAccount, defproduceraAccount, waitForTransBlock=True)
if transId is None:
cmdError("%s create account" % (ClientName))
errorExit("Failed to create account %s" % (exchangeAccount.name))
Print("Validating accounts after some user trasactions")
accounts=[testeraAccount, currencyAccount, exchangeAccount]
cluster.validateAccounts(accounts)
Print("Locking all wallets.")
if not walletMgr.lockAllWallets():
......@@ -306,7 +320,7 @@ try:
assert(actions)
try:
assert(actions["actions"][0]["action_trace"]["act"]["name"] == "transfer")
except (AssertionError, KeyError) as e:
except (AssertionError, TypeError, KeyError) as _:
Print("Last action validation failed. Actions: %s" % (actions))
raise
......@@ -381,7 +395,7 @@ try:
typeVal= transaction["name"]
amountVal=transaction["data"]["quantity"]
amountVal=int(decimal.Decimal(amountVal.split()[0])*10000)
except (AssertionError, KeyError) as e:
except (TypeError, KeyError) as e:
Print("Transaction validation parsing failed. Transaction: %s" % (transaction))
raise
......@@ -471,7 +485,7 @@ try:
expected="100000.0000 CUR"
actual=amountStr
if actual != expected:
errorExit("FAILURE - get currency1111 balance failed. Recieved response: <%s>" % (res), raw=True)
errorExit("FAILURE - currency1111 balance check failed. Expected: %s, Recieved %s" % (expected, actual), raw=True)
# TBD: "get currency1111 stats is still not working. Enable when ready.
# Print("Verify currency1111 contract has proper total supply of CUR (via get currency1111 stats)")
......@@ -515,6 +529,47 @@ try:
if actual != expected:
errorExit("FAILURE - Wrong currency1111 balance (expected=%s, actual=%s)" % (str(expected), str(actual)), raw=True)
Print("Test for block decoded packed transaction (issue 2932)")
blockId=node.getBlockIdByTransId(transId)
assert(blockId)
block=node.getBlock(blockId)
assert(block)
transactions=None
try:
transactions=block["transactions"]
assert(transactions)
except (AssertionError, TypeError, KeyError) as _:
Print("FAILURE - Failed to parse block. %s" % (block))
raise
myTrans=None
for trans in transactions:
assert(trans)
try:
myTransId=trans["trx"]["id"]
if transId == myTransId:
myTrans=trans["trx"]["transaction"]
assert(myTrans)
break
except (AssertionError, TypeError, KeyError) as _:
Print("FAILURE - Failed to parse block transactions. %s" % (trans))
raise
assert(myTrans)
try:
assert(myTrans["actions"][0]["name"] == "transfer")
assert(myTrans["actions"][0]["account"] == "currency1111")
assert(myTrans["actions"][0]["authorization"][0]["actor"] == "currency1111")
assert(myTrans["actions"][0]["authorization"][0]["permission"] == "active")
assert(myTrans["actions"][0]["data"]["from"] == "currency1111")
assert(myTrans["actions"][0]["data"]["to"] == "defproducera")
assert(myTrans["actions"][0]["data"]["quantity"] == "0.0050 CUR")
assert(myTrans["actions"][0]["data"]["memo"] == "test")
except (AssertionError, TypeError, KeyError) as _:
Print("FAILURE - Failed to parse block transaction. %s" % (myTrans))
raise
Print("Exchange Contract Tests")
Print("upload exchange contract")
......@@ -582,7 +637,7 @@ try:
Print("CurrentBlockNum: %d" % (currentBlockNum))
Print("Request blocks 1-%d" % (currentBlockNum))
for blockNum in range(1, currentBlockNum+1):
block=node.getBlock(blockNum, retry=False, silentErrors=True)
block=node.getBlock(str(blockNum), retry=False, silentErrors=True)
if block is None:
# TBD: Known issue (Issue 2099) that the block containing setprods isn't retrievable.
# Enable errorExit() once that is resolved.
......@@ -605,8 +660,8 @@ try:
# errorExit("mongo get messages by transaction id %s" % (transId))
Print("Request invalid block numbered %d. This will generate an extpected error message." % (currentBlockNum+1000))
block=node.getBlock(currentBlockNum+1000, silentErrors=True, retry=False)
Print("Request invalid block numbered %d. This will generate an expected error message." % (currentBlockNum+1000))
block=node.getBlock(str(currentBlockNum+1000), silentErrors=True, retry=False)
if block is not None:
errorExit("ERROR: Received block where not expected")
else:
......@@ -627,6 +682,10 @@ try:
Print("WARNING: Asserts in var/lib/node_00/stderr.txt")
#errorExit("FAILURE - Assert in var/lib/node_00/stderr.txt")
Print("Validating accounts at end of test")
accounts=[testeraAccount, currencyAccount, exchangeAccount]
cluster.validateAccounts(accounts)
testSuccessful=True
finally:
if testSuccessful:
......
......@@ -278,8 +278,26 @@ class Node(object):
def setWalletEndpointArgs(self, args):
self.endpointArgs="--url http://%s:%d %s" % (self.host, self.port, args)
def validateAccounts(self, accounts):
assert(accounts)
assert(isinstance(accounts, list))
for account in accounts:
assert(account)
assert(isinstance(account, Account))
if Utils.Debug: Utils.Print("Validating account %s" % (account.name))
accountInfo=self.getEosAccount(account.name)
try:
assert(accountInfo)
assert(accountInfo["account_name"] == account.name)
except (AssertionError, TypeError, KeyError) as _:
Utils.Print("account validation failed. account: %s" % (account.name))
raise
# pylint: disable=too-many-branches
def getBlock(self, blockNum, retry=True, silentErrors=False):
"""Given a blockId will return block details."""
assert(isinstance(blockNum, str))
if not self.enableMongo:
cmd="%s %s get block %s" % (Utils.EosClientPath, self.endpointArgs, blockNum)
if Utils.Debug: Utils.Print("cmd: %s" % (cmd))
......@@ -337,15 +355,18 @@ class Node(object):
def doesNodeHaveBlockNum(self, blockNum):
assert isinstance(blockNum, int)
assert (blockNum > 0)
info=self.getInfo(silentErrors=True)
if info is None:
return False
last_irreversible_block_num=int(info["last_irreversible_block_num"])
if blockNum > last_irreversible_block_num:
return False
else:
return True
assert(info)
last_irreversible_block_num=0
try:
last_irreversible_block_num=int(info["last_irreversible_block_num"])
except (TypeError, KeyError) as _:
Utils.Print("Failure in get info parsing. %s" % (info))
raise
return True if blockNum <= last_irreversible_block_num else True
# pylint: disable=too-many-branches
def getTransaction(self, transId, retry=True, silentErrors=False):
......@@ -384,6 +405,68 @@ class Node(object):
return None
def isTransInBlock(self, transId, blockId):
"""Check if transId is within block identified by blockId"""
assert(transId)
assert(isinstance(transId, str))
assert(blockId)
assert(isinstance(blockId, str))
block=self.getBlock(blockId)
transactions=None
try:
transactions=block["transactions"]
except (AssertionError, TypeError, KeyError) as _:
Utils.Print("Failed to parse block. %s" % (block))
raise
if transactions is not None:
for trans in transactions:
assert(trans)
try:
myTransId=trans["trx"]["id"]
if transId == myTransId:
return True
except (TypeError, KeyError) as _:
Utils.Print("Failed to parse block transactions. %s" % (trans))
return False
def getBlockIdByTransId(self, transId):
"""Given a transaction Id (string), will return block id (string) containing the transaction"""
assert(transId)
assert(isinstance(transId, str))
trans=self.getTransaction(transId)
assert(trans)
refBlockNum=None
try:
refBlockNum=trans["trx"]["trx"]["ref_block_num"]
refBlockNum=int(refBlockNum)+1
except (TypeError, ValueError, KeyError) as _:
Utils.Print("transaction parsing failed. Transaction: %s" % (trans))
raise
headBlockNum=self.getIrreversibleBlockNum()
assert(headBlockNum)
try:
headBlockNum=int(headBlockNum)
except(ValueError) as _:
Utils.Print("Info parsing failed. %s" % (headBlockNum))
for blockNum in range(refBlockNum, headBlockNum+1):
if self.isTransInBlock(str(transId), str(blockNum)):
return str(blockNum)
return None
def doesNodeHaveTransId(self, transId):
"""Check if transaction (transId) has been finalized."""
assert(transId)
assert(isinstance(transId, str))
blockId=self.getBlockIdByTransId(transId)
return True if blockId else None
def getTransByBlockId(self, blockId, retry=True, silentErrors=False):
for _ in range(2):
cmd="%s %s" % (Utils.MongoPath, self.mongoEndpointArgs)
......@@ -452,21 +535,6 @@ class Node(object):
return None
def doesNodeHaveTransId(self, transId):
trans=self.getTransaction(transId, silentErrors=True)
if trans is None:
return False
blockNum=None
if not self.enableMongo:
blockNum=int(trans["trx"]["trx"]["ref_block_num"])
else:
blockNum=int(trans["ref_block_num"])
blockNum += 1
if Utils.Debug: Utils.Print("Check if block %d is irreversible." % (blockNum))
return self.doesNodeHaveBlockNum(blockNum)
# Create & initialize account and return creation transactions. Return transaction json object
def createInitializeAccount(self, account, creatorAccount, stakedDeposit=1000, waitForTransBlock=False):
cmd='%s %s system newaccount -j %s %s %s %s --stake-net "100 EOS" --stake-cpu "100 EOS" --buy-ram-EOS "100 EOS"' % (
......@@ -521,6 +589,7 @@ class Node(object):
return trans
def getEosAccount(self, name):
assert(isinstance(name, str))
cmd="%s %s get account -j %s" % (Utils.EosClientPath, self.endpointArgs, name)
if Utils.Debug: Utils.Print("cmd: %s" % (cmd))
try:
......@@ -563,7 +632,7 @@ class Node(object):
assert(trans)
try:
return trans["rows"][0]["balance"]
except (AssertionError, KeyError) as e:
except (TypeError, KeyError) as _:
print("Transaction parsing failed. Transaction: %s" % (trans))
raise
......@@ -694,9 +763,9 @@ class Node(object):
# Gets accounts mapped to key. Returns array
def getAccountsArrByKey(self, key):
trans=self.getAccountsByKey(key)
assert(trans)
assert("account_names" in trans)
trans=self.getAccountsByKey(key)
accounts=trans["account_names"]
return accounts
......@@ -906,6 +975,7 @@ class Node(object):
return False if info is None else True
def getHeadBlockNum(self):
"""returns head block number(string) as returned by cleos get info."""
if not self.enableMongo:
info=self.getInfo()
if info is not None:
......@@ -1330,7 +1400,7 @@ class Cluster(object):
def initializeNodes(self, defproduceraPrvtKey=None, defproducerbPrvtKey=None, onlyBios=False):
port=Cluster.__BiosPort if onlyBios else self.port
host=Cluster.__BiosHost if onlyBios else self.host
node=Node(self.host, self.port, enableMongo=self.enableMongo, mongoHost=self.mongoHost, mongoPort=self.mongoPort, mongoDb=self.mongoDb)
node=Node(host, port, enableMongo=self.enableMongo, mongoHost=self.mongoHost, mongoPort=self.mongoPort, mongoDb=self.mongoDb)
node.setWalletEndpointArgs(self.walletEndpointArgs)
if Utils.Debug: Utils.Print("Node:", node)
......@@ -1595,6 +1665,19 @@ class Cluster(object):
return True
def validateAccounts(self, accounts, testSysAccounts=True):
assert(len(self.nodes) > 0)
node=self.nodes[0]
myAccounts = []
if testSysAccounts:
myAccounts += [self.eosioAccount, self.defproduceraAccount, self.defproducerbAccount]
if accounts:
assert(isinstance(accounts, list))
myAccounts += accounts
node.validateAccounts(myAccounts)
# create account, verify account and return transaction id
def createAccountAndVerify(self, account, creator, stakedDeposit=1000):
assert(len(self.nodes) > 0)
......@@ -1746,7 +1829,9 @@ class Cluster(object):
Utils.Print("Creating accounts: %s " % ", ".join(producerKeys.keys()))
producerKeys.pop(eosioName)
accounts=[]
for name, keys in producerKeys.items():
initx = None
initx = Account(name)
initx.ownerPrivateKey=keys["private"]
initx.ownerPublicKey=keys["public"]
......@@ -1757,10 +1842,14 @@ class Cluster(object):
Utils.Print("ERROR: Failed to create account %s" % (name))
return False
Node.validateTransaction(trans)
accounts.append(initx)
transId=Node.getTransId(trans)
biosNode.waitForTransIdOnNode(transId)
Utils.Print("Validating system accounts within bootstrap")
biosNode.validateAccounts(accounts)
if not onlyBios:
if prodCount == -1:
setProdsFile="setprods.json"
......@@ -1795,6 +1884,7 @@ class Cluster(object):
if Utils.Debug: Utils.Print("setprods: %s" % (setProdsStr))
Utils.Print("Setting producers: %s." % (", ".join(prodNames)))
opts="--permission eosio@active"
# pylint: disable=redefined-variable-type
trans=biosNode.pushMessage("eosio", "setprods", setProdsStr, opts)
if trans is None or not trans[0]:
Utils.Print("ERROR: Failed to set producer %s." % (keys["name"]))
......@@ -1845,6 +1935,8 @@ class Cluster(object):
return False
Node.validateTransaction(trans[1])
transId=Node.getTransId(trans[1])
biosNode.waitForTransIdOnNode(transId)
contract=eosioTokenAccount.name
Utils.Print("push issue action to %s contract" % (contract))
......@@ -1915,6 +2007,7 @@ class Cluster(object):
nodes=[]
pgrepOpts="-fl"
# pylint: disable=deprecated-method
if platform.linux_distribution()[0] in ["Ubuntu", "LinuxMint", "Fedora","CentOS Linux","arch"]:
pgrepOpts="-a"
......
......@@ -96,10 +96,7 @@ public:
void create_currency( name contract, name manager, asset maxsupply, const private_key_type* signer = nullptr ) {
auto act = mutable_variant_object()
("issuer", manager )
("maximum_supply", maxsupply )
("can_freeze", 0)
("can_recall", 0)
("can_whitelist", 0);
("maximum_supply", maxsupply );
base_tester::push_action(contract, N(create), contract, act );
}
......
......@@ -122,9 +122,6 @@ BOOST_AUTO_TEST_CASE( link_delay_direct_test ) { try {
chain.push_action(N(eosio.token), N(create), N(eosio.token), mutable_variant_object()
("issuer", eosio_token)
("maximum_supply", "9000000.0000 CUR")
("can_freeze", 0)
("can_recall", 0)
("can_whitelist", 0)
);
......@@ -281,9 +278,6 @@ BOOST_AUTO_TEST_CASE(delete_auth_test) { try {
chain.push_action(N(eosio.token), N(create), N(eosio.token), mutable_variant_object()
("issuer", "eosio.token" )
("maximum_supply", "9000000.0000 CUR" )
("can_freeze", 0)
("can_recall", 0)
("can_whitelist", 0)
);
// issue to account "eosio.token"
......@@ -404,9 +398,6 @@ BOOST_AUTO_TEST_CASE( link_delay_direct_parent_permission_test ) { try {
chain.push_action(N(eosio.token), N(create), N(eosio.token), mutable_variant_object()
("issuer", eosio_token)
("maximum_supply", "9000000.0000 CUR")
("can_freeze", 0)
("can_recall", 0)
("can_whitelist", 0)
);
chain.push_action(N(eosio.token), name("issue"), N(eosio.token), fc::mutable_variant_object()
......@@ -551,9 +542,6 @@ BOOST_AUTO_TEST_CASE( link_delay_direct_walk_parent_permissions_test ) { try {
chain.push_action(N(eosio.token), N(create), N(eosio.token), mutable_variant_object()
("issuer", eosio_token)
("maximum_supply", "9000000.0000 CUR")
("can_freeze", 0)
("can_recall", 0)
("can_whitelist", 0)
);
chain.push_action(N(eosio.token), name("issue"), N(eosio.token), fc::mutable_variant_object()
......@@ -692,9 +680,6 @@ BOOST_AUTO_TEST_CASE( link_delay_permission_change_test ) { try {
chain.push_action(N(eosio.token), N(create), N(eosio.token), mutable_variant_object()
("issuer", eosio_token )
("maximum_supply", "9000000.0000 CUR" )
("can_freeze", 0)
("can_recall", 0)
("can_whitelist", 0)
);
chain.push_action(N(eosio.token), name("issue"), N(eosio.token), fc::mutable_variant_object()
......@@ -892,9 +877,6 @@ BOOST_AUTO_TEST_CASE( link_delay_permission_change_with_delay_heirarchy_test ) {
chain.push_action(N(eosio.token), N(create), N(eosio.token), mutable_variant_object()
("issuer", eosio_token)
("maximum_supply", "9000000.0000 CUR" )
("can_freeze", 0)
("can_recall", 0)
("can_whitelist", 0)
);
chain.push_action(N(eosio.token), name("issue"), N(eosio.token), fc::mutable_variant_object()
......@@ -1092,9 +1074,6 @@ BOOST_AUTO_TEST_CASE( link_delay_link_change_test ) { try {
chain.push_action(N(eosio.token), N(create), N(eosio.token), mutable_variant_object()
("issuer", eosio_token)
("maximum_supply", "9000000.0000 CUR" )
("can_freeze", 0)
("can_recall", 0)
("can_whitelist", 0)
);
chain.push_action(N(eosio.token), name("issue"), N(eosio.token), fc::mutable_variant_object()
......@@ -1291,9 +1270,6 @@ BOOST_AUTO_TEST_CASE( link_delay_unlink_test ) { try {
chain.push_action(N(eosio.token), N(create), N(eosio.token), mutable_variant_object()
("issuer", eosio_token )
("maximum_supply", "9000000.0000 CUR" )
("can_freeze", 0)
("can_recall", 0)
("can_whitelist", 0)
);
chain.push_action(N(eosio.token), name("issue"), N(eosio.token), fc::mutable_variant_object()
......@@ -1495,9 +1471,6 @@ BOOST_AUTO_TEST_CASE( link_delay_link_change_heirarchy_test ) { try {
chain.push_action(N(eosio.token), N(create), N(eosio.token), mutable_variant_object()
("issuer", eosio_token)
("maximum_supply", "9000000.0000 CUR" )
("can_freeze", 0)
("can_recall", 0)
("can_whitelist", 0)
);
chain.push_action(N(eosio.token), name("issue"), N(eosio.token), fc::mutable_variant_object()
......@@ -1664,9 +1637,6 @@ BOOST_AUTO_TEST_CASE( mindelay_test ) { try {
chain.push_action(N(eosio.token), N(create), N(eosio.token), mutable_variant_object()
("issuer", eosio_token)
("maximum_supply", "9000000.0000 CUR")
("can_freeze", 0)
("can_recall", 0)
("can_whitelist", 0)
);
chain.push_action(N(eosio.token), name("issue"), N(eosio.token), fc::mutable_variant_object()
......@@ -1811,9 +1781,6 @@ BOOST_AUTO_TEST_CASE( canceldelay_test ) { try {
chain.push_action(N(eosio.token), N(create), N(eosio.token), mutable_variant_object()
("issuer", eosio_token)
("maximum_supply", "9000000.0000 CUR")
("can_freeze", 0)
("can_recall", 0)
("can_whitelist", 0)
);
chain.push_action(N(eosio.token), name("issue"), N(eosio.token), fc::mutable_variant_object()
......@@ -2057,9 +2024,6 @@ BOOST_AUTO_TEST_CASE( canceldelay_test2 ) { try {
chain.push_action(N(eosio.token), N(create), N(eosio.token), mutable_variant_object()
("issuer", eosio_token)
("maximum_supply", "9000000.0000 CUR")
("can_freeze", 0)
("can_recall", 0)
("can_whitelist", 0)
);
chain.push_action(N(eosio.token), name("issue"), N(eosio.token), fc::mutable_variant_object()
......@@ -2326,9 +2290,6 @@ BOOST_AUTO_TEST_CASE( max_transaction_delay_execute ) { try {
chain.push_action(N(eosio.token), N(create), N(eosio.token), mutable_variant_object()
("issuer", "eosio.token" )
("maximum_supply", "9000000.0000 CUR" )
("can_freeze", 0)
("can_recall", 0)
("can_whitelist", 0)
);
chain.push_action(N(eosio.token), name("issue"), N(eosio.token), fc::mutable_variant_object()
("to", "tester")
......
......@@ -238,9 +238,6 @@ BOOST_FIXTURE_TEST_CASE( dice_test, dice_tester ) try {
push_action(N(eosio.token), N(create), N(eosio.token), mvo()
("issuer", "eosio.token")
("maximum_supply", "1000000000.0000 EOS")
("can_freeze", "0")
("can_recall", "0")
("can_whitelist", "0")
);
push_action(N(eosio.token), N(issue), N(eosio.token), mvo()
......
此差异已折叠。
......@@ -66,17 +66,11 @@ public:
}
action_result create( account_name issuer,
asset maximum_supply,
uint8_t issuer_can_freeze,
uint8_t issuer_can_recall,
uint8_t issuer_can_whitelist ) {
asset maximum_supply ) {
return push_action( N(eosio.token), N(create), mvo()
( "issuer", issuer)
( "maximum_supply", maximum_supply)
( "can_freeze", issuer_can_freeze)
( "can_recall", issuer_can_recall)
( "can_whitelist", issuer_can_whitelist)
);
}
......@@ -107,17 +101,12 @@ BOOST_AUTO_TEST_SUITE(eosio_token_tests)
BOOST_FIXTURE_TEST_CASE( create_tests, eosio_token_tester ) try {
auto token = create( N(alice), asset::from_string("1000.000 TKN"), false, false, false);
auto token = create( N(alice), asset::from_string("1000.000 TKN"));
auto stats = get_stats("3,TKN");
REQUIRE_MATCHING_OBJECT( stats, mvo()
("supply", "0.000 TKN")
("max_supply", "1000.000 TKN")
("issuer", "alice")
("can_freeze",0)
("can_recall",0)
("can_whitelist",0)
("is_frozen",false)
("enforce_whitelist",false)
);
produce_blocks(1);
......@@ -126,53 +115,43 @@ BOOST_FIXTURE_TEST_CASE( create_tests, eosio_token_tester ) try {
BOOST_FIXTURE_TEST_CASE( create_negative_max_supply, eosio_token_tester ) try {
BOOST_REQUIRE_EQUAL( error( "condition: assertion failed: max-supply must be positive" ),
create( N(alice), asset::from_string("-1000.000 TKN"), false, false, false)
create( N(alice), asset::from_string("-1000.000 TKN"))
);
} FC_LOG_AND_RETHROW()
BOOST_FIXTURE_TEST_CASE( symbol_already_exists, eosio_token_tester ) try {
auto token = create( N(alice), asset::from_string("100 TKN"), true, false, false);
auto token = create( N(alice), asset::from_string("100 TKN"));
auto stats = get_stats("0,TKN");
REQUIRE_MATCHING_OBJECT( stats, mvo()
("supply", "0 TKN")
("max_supply", "100 TKN")
("issuer", "alice")
("can_freeze",1)
("can_recall",0)
("can_whitelist",0)
("is_frozen",false)
("enforce_whitelist",false)
("supply", "0 TKN")
("max_supply", "100 TKN")
("issuer", "alice")
);
produce_blocks(1);
BOOST_REQUIRE_EQUAL( error( "condition: assertion failed: token with symbol already exists" ),
create( N(alice), asset::from_string("100 TKN"), true, false, false)
create( N(alice), asset::from_string("100 TKN"))
);
} FC_LOG_AND_RETHROW()
BOOST_FIXTURE_TEST_CASE( create_max_supply, eosio_token_tester ) try {
auto token = create( N(alice), asset::from_string("4611686018427387903 TKN"), true, false, false);
auto token = create( N(alice), asset::from_string("4611686018427387903 TKN"));
auto stats = get_stats("0,TKN");
REQUIRE_MATCHING_OBJECT( stats, mvo()
("supply", "0 TKN")
("max_supply", "4611686018427387903 TKN")
("issuer", "alice")
("can_freeze",1)
("can_recall",0)
("can_whitelist",0)
("is_frozen",false)
("enforce_whitelist",false)
);
produce_blocks(1);
asset max(10, symbol(SY(0, NKT)));
max.amount = 4611686018427387904;
BOOST_CHECK_EXCEPTION( create( N(alice), max, true, false, false) , asset_type_exception, [](const asset_type_exception& e) {
BOOST_CHECK_EXCEPTION( create( N(alice), max) , asset_type_exception, [](const asset_type_exception& e) {
return expect_assert_message(e, "magnitude of asset amount must be less than 2^62");
});
......@@ -181,17 +160,12 @@ BOOST_FIXTURE_TEST_CASE( create_max_supply, eosio_token_tester ) try {
BOOST_FIXTURE_TEST_CASE( create_max_decimals, eosio_token_tester ) try {
auto token = create( N(alice), asset::from_string("1.000000000000000000 TKN"), true, false, false);
auto token = create( N(alice), asset::from_string("1.000000000000000000 TKN"));
auto stats = get_stats("18,TKN");
REQUIRE_MATCHING_OBJECT( stats, mvo()
("supply", "0.000000000000000000 TKN")
("max_supply", "1.000000000000000000 TKN")
("issuer", "alice")
("can_freeze",1)
("can_recall",0)
("can_whitelist",0)
("is_frozen",false)
("enforce_whitelist",false)
);
produce_blocks(1);
......@@ -199,7 +173,7 @@ BOOST_FIXTURE_TEST_CASE( create_max_decimals, eosio_token_tester ) try {
//1.0000000000000000000 => 0x8ac7230489e80000L
max.amount = 0x8ac7230489e80000L;
BOOST_CHECK_EXCEPTION( create( N(alice), max, true, false, false) , asset_type_exception, [](const asset_type_exception& e) {
BOOST_CHECK_EXCEPTION( create( N(alice), max) , asset_type_exception, [](const asset_type_exception& e) {
return expect_assert_message(e, "magnitude of asset amount must be less than 2^62");
});
......@@ -207,7 +181,7 @@ BOOST_FIXTURE_TEST_CASE( create_max_decimals, eosio_token_tester ) try {
BOOST_FIXTURE_TEST_CASE( issue_tests, eosio_token_tester ) try {
auto token = create( N(alice), asset::from_string("1000.000 TKN"), false, false, false);
auto token = create( N(alice), asset::from_string("1000.000 TKN"));
produce_blocks(1);
issue( N(alice), N(alice), asset::from_string("500.000 TKN"), "hola" );
......@@ -217,18 +191,11 @@ BOOST_FIXTURE_TEST_CASE( issue_tests, eosio_token_tester ) try {
("supply", "500.000 TKN")
("max_supply", "1000.000 TKN")
("issuer", "alice")
("can_freeze",0)
("can_recall",0)
("can_whitelist",0)
("is_frozen",false)
("enforce_whitelist",false)
);
auto alice_balance = get_account(N(alice), "3,TKN");
REQUIRE_MATCHING_OBJECT( alice_balance, mvo()
("balance", "500.000 TKN")
("frozen", 0)
("whitelist", 1)
);
BOOST_REQUIRE_EQUAL( error( "condition: assertion failed: quantity exceeds available supply" ),
......@@ -248,7 +215,7 @@ BOOST_FIXTURE_TEST_CASE( issue_tests, eosio_token_tester ) try {
BOOST_FIXTURE_TEST_CASE( transfer_tests, eosio_token_tester ) try {
auto token = create( N(alice), asset::from_string("1000 CERO"), false, false, false);
auto token = create( N(alice), asset::from_string("1000 CERO"));
produce_blocks(1);
issue( N(alice), N(alice), asset::from_string("1000 CERO"), "hola" );
......@@ -258,18 +225,11 @@ BOOST_FIXTURE_TEST_CASE( transfer_tests, eosio_token_tester ) try {
("supply", "1000 CERO")
("max_supply", "1000 CERO")
("issuer", "alice")
("can_freeze",0)
("can_recall",0)
("can_whitelist",0)
("is_frozen",false)
("enforce_whitelist",false)
);
auto alice_balance = get_account(N(alice), "0,CERO");
REQUIRE_MATCHING_OBJECT( alice_balance, mvo()
("balance", "1000 CERO")
("frozen", 0)
("whitelist", 1)
);
transfer( N(alice), N(bob), asset::from_string("300 CERO"), "hola" );
......
......@@ -4,9 +4,6 @@
#include <eosio/chain/abi_serializer.hpp>
#include <eosio/chain/symbol.hpp>
#include <eosio.token/eosio.token.wast.hpp>
#include <eosio.token/eosio.token.abi.hpp>
#include <exchange/exchange.wast.hpp>
#include <exchange/exchange.abi.hpp>
......@@ -78,7 +75,7 @@ class exchange_tester : public TESTER {
}
asset get_balance(const account_name& account) const {
return get_currency_balance(N(eosio.token), symbol(SY(4,CUR)), account);
return get_currency_balance(N(exchange), symbol(SY(4,CUR)), account);
}
exchange_state get_market_state( account_name exchange, symbol sym ) {
......@@ -145,11 +142,6 @@ class exchange_tester : public TESTER {
FC_ASSERT( false, "unable to find loan balance" );
}
void deploy_currency( account_name ac ) {
create_account( ac );
set_code( ac, eosio_token_wast /*currency_wast*/ );
}
void deploy_exchange( account_name ac ) {
create_account( ac );
set_code( ac, exchange_wast );
......@@ -161,7 +153,7 @@ class exchange_tester : public TESTER {
("maximum_supply", maxsupply )
("can_freeze", 0)
("can_recall", 0)
("can_whitelist", 0)
("can_whitelist", 0)
);
}
......@@ -236,20 +228,19 @@ class exchange_tester : public TESTER {
create_account( N(trader) );
deploy_exchange( N(exchange) );
deploy_currency( N(eosio.token) );
create_currency( N(eosio.token), N(eosio.token), A(1000000.00 USD) );
create_currency( N(eosio.token), N(eosio.token), A(1000000.00 BTC) );
create_currency( N(exchange), N(exchange), A(1000000.00 USD) );
create_currency( N(exchange), N(exchange), A(1000000.00 BTC) );
issue( N(eosio.token), N(eosio.token), N(dan), A(1000.00 USD) );
issue( N(eosio.token), N(eosio.token), N(dan), A(1000.00 BTC) );
issue( N(exchange), N(exchange), N(dan), A(1000.00 USD) );
issue( N(exchange), N(exchange), N(dan), A(1000.00 BTC) );
deposit( N(exchange), N(dan), extended_asset( A(500.00 USD), N(eosio.token) ) );
deposit( N(exchange), N(dan), extended_asset( A(500.00 BTC), N(eosio.token) ) );
deposit( N(exchange), N(dan), extended_asset( A(500.00 USD), N(exchange) ) );
deposit( N(exchange), N(dan), extended_asset( A(500.00 BTC), N(exchange) ) );
create_exchange( N(exchange), N(dan),
extended_asset( A(400.00 USD), N(eosio.token) ),
extended_asset( A(400.00 BTC), N(eosio.token) ),
extended_asset( A(400.00 USD), N(exchange) ),
extended_asset( A(400.00 BTC), N(exchange) ),
A(10000000.00 EXC) );
produce_block();
......@@ -263,9 +254,9 @@ BOOST_AUTO_TEST_SUITE(exchange_tests)
BOOST_AUTO_TEST_CASE( bootstrap ) try {
auto expected = asset::from_string( "1000000.0000 CUR" );
exchange_tester t;
t.create_currency( N(eosio.token), N(eosio.token), expected );
t.issue( N(eosio.token), N(eosio.token), N(eosio.token), expected );
auto actual = t.get_currency_balance(N(eosio.token), expected.get_symbol(), N(eosio.token));
t.create_currency( N(exchange), N(exchange), expected );
t.issue( N(exchange), N(exchange), N(exchange), expected );
auto actual = t.get_currency_balance(N(exchange), expected.get_symbol(), N(exchange));
BOOST_REQUIRE_EQUAL(expected, actual);
} FC_LOG_AND_RETHROW() /// test_api_bootstrap
......@@ -274,38 +265,38 @@ BOOST_AUTO_TEST_CASE( exchange_create ) try {
auto expected = asset::from_string( "1000000.0000 CUR" );
exchange_tester t;
t.issue( N(eosio.token), N(eosio.token), N(trader), A(2000.00 BTC) );
t.issue( N(eosio.token), N(eosio.token), N(trader), A(2000.00 USD) );
t.issue( N(exchange), N(exchange), N(trader), A(2000.00 BTC) );
t.issue( N(exchange), N(exchange), N(trader), A(2000.00 USD) );
t.deposit( N(exchange), N(trader), extended_asset( A(1500.00 USD), N(eosio.token) ) );
t.deposit( N(exchange), N(trader), extended_asset( A(1500.00 BTC), N(eosio.token) ) );
t.deposit( N(exchange), N(trader), extended_asset( A(1500.00 USD), N(exchange) ) );
t.deposit( N(exchange), N(trader), extended_asset( A(1500.00 BTC), N(exchange) ) );
auto trader_ex_usd = t.get_exchange_balance( N(exchange), N(eosio.token), symbol(2,"USD"), N(trader) );
auto trader_ex_btc = t.get_exchange_balance( N(exchange), N(eosio.token), symbol(2,"BTC"), N(trader) );
auto dan_ex_usd = t.get_exchange_balance( N(exchange), N(eosio.token), symbol(2,"USD"), N(dan) );
auto dan_ex_btc = t.get_exchange_balance( N(exchange), N(eosio.token), symbol(2,"BTC"), N(dan) );
auto trader_ex_usd = t.get_exchange_balance( N(exchange), N(exchange), symbol(2,"USD"), N(trader) );
auto trader_ex_btc = t.get_exchange_balance( N(exchange), N(exchange), symbol(2,"BTC"), N(trader) );
auto dan_ex_usd = t.get_exchange_balance( N(exchange), N(exchange), symbol(2,"USD"), N(dan) );
auto dan_ex_btc = t.get_exchange_balance( N(exchange), N(exchange), symbol(2,"BTC"), N(dan) );
auto dan_ex_exc = t.get_exchange_balance( N(exchange), N(exchange), symbol(2,"EXC"), N(dan) );
wdump((dan_ex_exc));
auto result = t.trade( N(exchange), N(trader), symbol(2,"EXC"),
extended_asset( A(10.00 BTC), N(eosio.token) ),
extended_asset( A(0.01 USD), N(eosio.token) ) );
extended_asset( A(10.00 BTC), N(exchange) ),
extended_asset( A(0.01 USD), N(exchange) ) );
for( const auto& at : result->action_traces )
ilog( "${s}", ("s",at.console) );
trader_ex_usd = t.get_exchange_balance( N(exchange), N(eosio.token), symbol(2,"USD"), N(trader) );
trader_ex_btc = t.get_exchange_balance( N(exchange), N(eosio.token), symbol(2,"BTC"), N(trader) );
trader_ex_usd = t.get_exchange_balance( N(exchange), N(exchange), symbol(2,"USD"), N(trader) );
trader_ex_btc = t.get_exchange_balance( N(exchange), N(exchange), symbol(2,"BTC"), N(trader) );
wdump((trader_ex_btc.quantity));
wdump((trader_ex_usd.quantity));
result = t.trade( N(exchange), N(trader), symbol(2,"EXC"),
extended_asset( A(9.75 USD), N(eosio.token) ),
extended_asset( A(0.01 BTC), N(eosio.token) ) );
extended_asset( A(9.75 USD), N(exchange) ),
extended_asset( A(0.01 BTC), N(exchange) ) );
trader_ex_usd = t.get_exchange_balance( N(exchange), N(eosio.token), symbol(2,"USD"), N(trader) );
trader_ex_btc = t.get_exchange_balance( N(exchange), N(eosio.token), symbol(2,"BTC"), N(trader) );
trader_ex_usd = t.get_exchange_balance( N(exchange), N(exchange), symbol(2,"USD"), N(trader) );
trader_ex_btc = t.get_exchange_balance( N(exchange), N(exchange), symbol(2,"BTC"), N(trader) );
for( const auto& at : result->action_traces )
ilog( "${s}", ("s",at.console) );
......@@ -326,19 +317,19 @@ BOOST_AUTO_TEST_CASE( exchange_lend ) try {
exchange_tester t;
t.create_account( N(lender) );
t.issue( N(eosio.token), N(eosio.token), N(lender), A(2000.00 BTC) );
t.issue( N(eosio.token), N(eosio.token), N(lender), A(2000.00 USD) );
t.issue( N(exchange), N(exchange), N(lender), A(2000.00 BTC) );
t.issue( N(exchange), N(exchange), N(lender), A(2000.00 USD) );
t.deposit( N(exchange), N(lender), extended_asset( A(1500.00 USD), N(eosio.token) ) );
t.deposit( N(exchange), N(lender), extended_asset( A(1500.00 BTC), N(eosio.token) ) );
t.deposit( N(exchange), N(lender), extended_asset( A(1500.00 USD), N(exchange) ) );
t.deposit( N(exchange), N(lender), extended_asset( A(1500.00 BTC), N(exchange) ) );
auto lender_ex_usd = t.get_exchange_balance( N(exchange), N(eosio.token), symbol(2,"USD"), N(lender) );
auto lender_ex_btc = t.get_exchange_balance( N(exchange), N(eosio.token), symbol(2,"BTC"), N(lender) );
auto lender_ex_usd = t.get_exchange_balance( N(exchange), N(exchange), symbol(2,"USD"), N(lender) );
auto lender_ex_btc = t.get_exchange_balance( N(exchange), N(exchange), symbol(2,"BTC"), N(lender) );
t.lend( N(exchange), N(lender), extended_asset( A(1000.00 USD), N(eosio.token) ), symbol(2,"EXC") );
t.lend( N(exchange), N(lender), extended_asset( A(1000.00 USD), N(exchange) ), symbol(2,"EXC") );
lender_ex_usd = t.get_exchange_balance( N(exchange), N(eosio.token), symbol(2,"USD"), N(lender) );
lender_ex_btc = t.get_exchange_balance( N(exchange), N(eosio.token), symbol(2,"BTC"), N(lender) );
lender_ex_usd = t.get_exchange_balance( N(exchange), N(exchange), symbol(2,"USD"), N(lender) );
lender_ex_btc = t.get_exchange_balance( N(exchange), N(exchange), symbol(2,"BTC"), N(lender) );
wdump((lender_ex_btc.quantity));
wdump((lender_ex_usd.quantity));
......@@ -351,7 +342,7 @@ BOOST_AUTO_TEST_CASE( exchange_lend ) try {
wdump((t.get_market_state( N(exchange), symbol(2,"EXC") ) ));
t.unlend( N(exchange), N(lender), lentshares, extended_symbol{ symbol(2,"USD"), N(eosio.token)}, symbol(2,"EXC") );
t.unlend( N(exchange), N(lender), lentshares, extended_symbol{ symbol(2,"USD"), N(exchange)}, symbol(2,"EXC") );
lentshares = t.get_lent_shares( N(exchange), symbol(2,"EXC"), N(lender), true );
wdump((lentshares));
......
......@@ -63,9 +63,6 @@ BOOST_AUTO_TEST_CASE( forking ) try {
auto cr = c.push_action( N(eosio.token), N(create), N(eosio.token), mutable_variant_object()
("issuer", "eosio" )
("maximum_supply", "10000000.0000 EOS")
("can_freeze", 0)
("can_recall", 0)
("can_whitelist", 0)
);
wdump((fc::json::to_pretty_string(cr)));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册