Skip to content

Commit efaee38

Browse files
committed
Refactor eosio.bios to use new contract structure
- fix bootseq tests - related to #1614 and #1752 - new dispatch_inline helper - define producer_schedule_type - implement eosio.token as a independent contract in new contract style
1 parent 9384262 commit efaee38

19 files changed

+417
-161
lines changed

contracts/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ add_subdirectory(eosiolib)
88
add_subdirectory(musl)
99
add_subdirectory(libc++)
1010
add_subdirectory(simple.token)
11+
add_subdirectory(eosio.token)
1112
add_subdirectory(multi_index_test)
1213
add_subdirectory(eosio.system)
1314
add_subdirectory(identity)

contracts/eosio.bios/eosio.bios.abi

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
{"name":"cpu_weight", "type":"int64"}
1111
]
1212
},{
13-
"name": "set_priv",
13+
"name": "setpriv",
1414
"base": "",
1515
"fields": [
1616
{"name":"account", "type":"account_name"},
@@ -56,8 +56,8 @@
5656
"name": "setglimits",
5757
"type": "set_global_limits"
5858
},{
59-
"name": "setprivileged",
60-
"type": "set_priv"
59+
"name": "setpriv",
60+
"type": "setpriv"
6161
},{
6262
"name": "setprods",
6363
"type": "set_producers"

contracts/eosio.bios/eosio.bios.cpp

Lines changed: 2 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -1,113 +1,3 @@
1-
/**
2-
* @file
3-
* @copyright defined in eos/LICENSE.txt
4-
*/
1+
#include <eosio.bios/eosio.bios.hpp>
52

6-
#include <eosiolib/action.hpp>
7-
#include <eosiolib/chain.h>
8-
#include <eosiolib/types.hpp>
9-
#include <eosiolib/serialize.hpp>
10-
#include <eosiolib/system.h>
11-
#include <eosiolib/privileged.h>
12-
13-
using namespace eosio;
14-
15-
namespace eosiobios {
16-
template<uint64_t Val>
17-
struct dispatchable {
18-
constexpr static uint64_t action_name = Val;
19-
};
20-
21-
struct set_account_limits : dispatchable<N(setalimits)> {
22-
account_name account;
23-
uint64_t ram_bytes = 0;
24-
uint64_t net_weight = 0;
25-
uint64_t cpu_weight = 0;
26-
27-
static void process(const set_account_limits& act) {
28-
set_resource_limits(act.account, act.ram_bytes, act.net_weight, act.cpu_weight, 0);
29-
}
30-
31-
EOSLIB_SERIALIZE( set_account_limits, (account)(ram_bytes)(net_weight)(cpu_weight) )
32-
};
33-
34-
struct set_priv : dispatchable<N(setprivileged)> {
35-
account_name account;
36-
bool is_priv;
37-
38-
static void process(const set_priv& priv) {
39-
set_privileged(priv.account, priv.is_priv);
40-
}
41-
42-
EOSLIB_SERIALIZE( set_priv, (account)(is_priv) )
43-
};
44-
45-
46-
struct set_global_limits : dispatchable<N(setglimits)> {
47-
int64_t cpu_usec_per_period;
48-
49-
static void process(const set_global_limits& ) {
50-
// TODO: support this
51-
}
52-
53-
EOSLIB_SERIALIZE( set_global_limits, (cpu_usec_per_period) )
54-
};
55-
56-
struct producer_key {
57-
account_name account;
58-
std::string public_key;
59-
60-
EOSLIB_SERIALIZE( producer_key, (account) ) //(public_key) )
61-
};
62-
63-
struct set_producers : dispatchable<N(setprods)> {
64-
static void process(const set_producers&) {
65-
char buffer[action_data_size()];
66-
read_action_data( buffer, sizeof(buffer) );
67-
set_active_producers(buffer, sizeof(buffer));
68-
}
69-
};
70-
71-
struct require_auth : dispatchable<N(reqauth)> {
72-
account_name from;
73-
74-
static void process(const require_auth& r) {
75-
::require_auth(r.from);
76-
}
77-
};
78-
79-
template<typename ...Ts>
80-
struct dispatcher_impl;
81-
82-
template<typename T>
83-
struct dispatcher_impl<T> {
84-
static bool dispatch(uint64_t action) {
85-
if (action == T::action_name) {
86-
T::process(current_action_data<T>());
87-
return true;
88-
}
89-
90-
return false;
91-
}
92-
};
93-
94-
template<typename T, typename ...Rem>
95-
struct dispatcher_impl<T, Rem...> {
96-
static bool dispatch(uint64_t action) {
97-
return dispatcher_impl<T>::dispatch(action) || dispatcher_impl<Rem...>::dispatch(action);
98-
}
99-
};
100-
101-
using dispatcher = dispatcher_impl<set_account_limits, set_priv, set_producers, require_auth>;
102-
};
103-
104-
extern "C" {
105-
106-
/// The apply method implements the dispatch of events to this contract
107-
void apply( uint64_t code, uint64_t act ) {
108-
if (code == current_receiver()) {
109-
eosiobios::dispatcher::dispatch(act);
110-
}
111-
}
112-
113-
} // extern "C"
3+
EOSIO_ABI( eosio::bios, (setpriv)(setalimits)(setglimits)(setprods)(reqauth) )

contracts/eosio.bios/eosio.bios.hpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#include <eosiolib/eosio.hpp>
2+
#include <eosiolib/privileged.h>
3+
#include <eosiolib/producer_schedule.hpp>
4+
5+
namespace eosio {
6+
7+
class bios : public contract {
8+
public:
9+
bios( action_name self ):contract(self){}
10+
11+
void setpriv( account_name account, uint8_t ispriv ) {
12+
require_auth( _self );
13+
set_privileged( account, ispriv );
14+
}
15+
16+
void setalimits( account_name account, uint64_t ram_bytes, uint64_t net_weight, uint64_t cpu_weight ) {
17+
require_auth( _self );
18+
set_resource_limits( account, ram_bytes, net_weight, cpu_weight, 0 );
19+
}
20+
21+
void setglimits( uint64_t ram, uint64_t net, uint64_t cpu ) {
22+
require_auth( _self );
23+
}
24+
25+
void setprods( producer_schedule sch ) {
26+
char buffer[action_data_size()];
27+
read_action_data( buffer, sizeof(buffer) );
28+
set_active_producers(buffer, sizeof(buffer));
29+
}
30+
31+
void reqauth( action_name from ) {
32+
require_auth( from );
33+
}
34+
35+
private:
36+
};
37+
38+
} /// namespace eosio

contracts/eosio.token/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
file(GLOB ABI_FILES "*.abi")
2+
configure_file("${ABI_FILES}" "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY)
3+
4+
add_wast_executable(TARGET eosio.token
5+
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
6+
LIBRARIES libc++ libc eosiolib
7+
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
8+
)

contracts/eosio.token/eosio.token.abi

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
{
2+
"types": [{
3+
"new_type_name": "account_name",
4+
"type": "name"
5+
}
6+
],
7+
"structs": [{
8+
"name": "transfer",
9+
"base": "",
10+
"fields": [
11+
{"name":"from", "type":"account_name"},
12+
{"name":"to", "type":"account_name"},
13+
{"name":"quantity", "type":"asset"},
14+
{"name":"memo", "type":"string"}
15+
]
16+
},{
17+
"name": "create",
18+
"base": "",
19+
"fields": [
20+
{"name":"issuer", "type":"account_name"},
21+
{"name":"maximum_supply", "type":"asset"},
22+
{"name":"can_freeze", "type":"uint8"},
23+
{"name":"can_recall", "type":"uint8"},
24+
{"name":"can_whitelist", "type":"uint8"}
25+
]
26+
},{
27+
"name": "issue",
28+
"base": "",
29+
"fields": [
30+
{"name":"to", "type":"account_name"},
31+
{"name":"quantity", "type":"asset"},
32+
{"name":"memo", "type":"string"}
33+
]
34+
},{
35+
"name": "account",
36+
"base": "",
37+
"fields": [
38+
{"name":"currency", "type":"uint64"},
39+
{"name":"balance", "type":"uint64"}
40+
]
41+
},{
42+
"name": "currency_stats",
43+
"base": "",
44+
"fields": [
45+
{"name":"currency", "type":"uint64"},
46+
{"name":"supply", "type":"uint64"}
47+
]
48+
}
49+
],
50+
"actions": [{
51+
"name": "transfer",
52+
"type": "transfer"
53+
},{
54+
"name": "issue",
55+
"type": "issue"
56+
}, {
57+
"name": "create",
58+
"type": "create"
59+
}
60+
61+
],
62+
"tables": [{
63+
"name": "account",
64+
"type": "account",
65+
"index_type": "i64",
66+
"key_names" : ["currency"],
67+
"key_types" : ["uint64"]
68+
},{
69+
"name": "stat",
70+
"type": "currency_stats",
71+
"index_type": "i64",
72+
"key_names" : ["currency"],
73+
"key_types" : ["uint64"]
74+
}
75+
]
76+
}

contracts/eosio.token/eosio.token.cpp

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/**
2+
* @file
3+
* @copyright defined in eos/LICENSE.txt
4+
*/
5+
6+
#include <eosio.token/eosio.token.hpp>
7+
8+
namespace eosio {
9+
10+
void token::create( account_name issuer,
11+
asset maximum_supply,
12+
uint8_t issuer_can_freeze,
13+
uint8_t issuer_can_recall,
14+
uint8_t issuer_can_whitelist )
15+
{
16+
require_auth( _self );
17+
18+
auto sym = maximum_supply.symbol;
19+
eosio_assert( sym.is_valid(), "invalid symbol name" );
20+
21+
stats statstable( _self, sym.name() );
22+
auto existing = statstable.find( sym.name() );
23+
eosio_assert( existing == statstable.end(), "token with symbol already exists" );
24+
25+
statstable.emplace( _self, [&]( auto& s ) {
26+
s.supply.symbol = maximum_supply.symbol;
27+
s.max_supply = maximum_supply;
28+
s.issuer = issuer;
29+
s.can_freeze = issuer_can_freeze;
30+
s.can_recall = issuer_can_recall;
31+
s.can_whitelist = issuer_can_whitelist;
32+
});
33+
}
34+
35+
36+
void token::issue( account_name to, asset quantity, string memo )
37+
{
38+
print( "issue" );
39+
auto sym = quantity.symbol.name();
40+
stats statstable( _self, sym );
41+
const auto& st = statstable.get( sym );
42+
43+
require_auth( st.issuer );
44+
eosio_assert( quantity.is_valid(), "invalid quantity" );
45+
eosio_assert( quantity.amount > 0, "must issue positive quantity" );
46+
47+
statstable.modify( st, 0, [&]( auto& s ) {
48+
s.supply.amount += quantity.amount;
49+
});
50+
51+
add_balance( st.issuer, quantity, st, st.issuer );
52+
53+
if( to != st.issuer )
54+
{
55+
dispatch_inline( permission_level{st.issuer,N(active)}, _self, N(transfer), &token::transfer, { st.issuer, to, quantity, memo } );
56+
}
57+
}
58+
59+
void token::transfer( account_name from,
60+
account_name to,
61+
asset quantity,
62+
string /*memo*/ )
63+
{
64+
print( "transfer" );
65+
require_auth( from );
66+
auto sym = quantity.symbol.name();
67+
stats statstable( _self, sym );
68+
const auto& st = statstable.get( sym );
69+
70+
require_recipient( from );
71+
require_recipient( to );
72+
73+
eosio_assert( quantity.is_valid(), "invalid quantity" );
74+
eosio_assert( quantity.amount > 0, "must transfer positive quantity" );
75+
76+
sub_balance( from, quantity, st );
77+
add_balance( to, quantity, st, from );
78+
}
79+
80+
81+
void token::sub_balance( account_name owner, asset value, const currency_stats& st ) {
82+
accounts from_acnts( _self, owner );
83+
84+
const auto& from = from_acnts.get( value.symbol );
85+
eosio_assert( from.balance.amount >= value.amount, "overdrawn balance" );
86+
87+
if( has_auth( owner ) ) {
88+
eosio_assert( !st.can_freeze || !from.frozen, "account is frozen by issuer" );
89+
eosio_assert( !st.can_freeze || !st.is_frozen, "all transfers are frozen by issuer" );
90+
eosio_assert( !st.enforce_whitelist || from.whitelist, "account is not white listed" );
91+
} else if( has_auth( st.issuer ) ) {
92+
eosio_assert( st.can_recall, "issuer may not recall token" );
93+
} else {
94+
eosio_assert( false, "insufficient authority" );
95+
}
96+
97+
from_acnts.modify( from, owner, [&]( auto& a ) {
98+
a.balance.amount -= value.amount;
99+
});
100+
}
101+
102+
void token::add_balance( account_name owner, asset value, const currency_stats& st, account_name ram_payer )
103+
{
104+
accounts to_acnts( _self, owner );
105+
auto to = to_acnts.find( value.symbol );
106+
if( to == to_acnts.end() ) {
107+
eosio_assert( !st.enforce_whitelist, "can only transfer to white listed accounts" );
108+
to_acnts.emplace( ram_payer, [&]( auto& a ){
109+
a.balance = value;
110+
});
111+
} else {
112+
eosio_assert( !st.enforce_whitelist || to->whitelist, "receiver requires whitelist by issuer" );
113+
to_acnts.modify( to, 0, [&]( auto& a ) {
114+
a.balance.amount += value.amount;
115+
});
116+
}
117+
}
118+
119+
} /// namespace eosio
120+
121+
EOSIO_ABI( eosio::token, (create)(issue)(transfer) )

0 commit comments

Comments
 (0)