提交 9edd5d4b 编写于 作者: B Bucky Kittinger

Merged master

......@@ -20,6 +20,7 @@ matrix:
- libgmp-dev
- libclang-4.0-dev
- python3
- sharutils
- os: osx
osx_image: xcode9.1
before_install:
......@@ -49,7 +50,7 @@ before_install:
cd boost_1_64_0
./bootstrap.sh --prefix=$TRAVIS_BUILD_DIR/ext
echo 'using clang : 4.0 : clang++-4.0 ;' >> project-config.jam
./b2 -d0 -j4 --with-thread --with-date_time --with-system --with-filesystem --with-program_options --with-signals --with-serialization --with-chrono --with-test --with-context --with-locale --with-coroutine toolset=clang link=static install
./b2 -d0 -j4 --with-iostreams --with-thread --with-date_time --with-system --with-filesystem --with-program_options --with-signals --with-serialization --with-chrono --with-test --with-context --with-locale --with-coroutine toolset=clang link=static install
cd $TRAVIS_BUILD_DIR/ext
wget https://cmake.org/files/v3.9/cmake-3.9.0-Linux-x86_64.tar.gz
tar xzf cmake-3.9.0-Linux-x86_64.tar.gz
......@@ -77,7 +78,7 @@ script:
- mkdir build && cd build
- ${CMAKE_DIR}cmake -G Ninja -DWASM_LLVM_CONFIG=$TRAVIS_BUILD_DIR/ext/wasm-compiler/bin/llvm-config -DSecp256k1_ROOT_DIR=$TRAVIS_BUILD_DIR/ext -DBINARYEN_ROOT=$TRAVIS_BUILD_DIR/ext/wasm-compiler -DCMAKE_PREFIX_PATH=$TRAVIS_BUILD_DIR/ext -DCMAKE_BUILD_TYPE=Release -DBUILD_MONGO_DB_PLUGIN=true $EOS_CMAKE_OPTIONS ..
- ninja -j4
- '[ "$TRAVIS_OS_NAME" == "osx" ] || ctest --output-on-failure'
- '[ "$TRAVIS_OS_NAME" == "osx" ] || (export EOSLIB=$TRAVIS_BUILD_DIR/contracts; ctest --output-on-failure)'
- cpack
deploy:
......
......@@ -171,9 +171,7 @@ if(WASM_TOOLCHAIN)
message(STATUS "Using WASM llvm-link => " ${WASM_LLVM_LINK})
add_subdirectory(contracts)
else()
message(STATUS "--------------------------------------------------------------------")
message(STATUS "No WASM compiler could be found ... (skipping building of contracts)")
message(STATUS "--------------------------------------------------------------------")
message( FATAL_ERROR "No WASM compiler cound be found" )
endif()
include(installer)
......
......@@ -138,10 +138,11 @@ macro(add_wast_target target INCLUDE_FOLDERS DESTINATION_FOLDER)
VERBATIM
)
set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${target}.wast)
STRING (REPLACE "." "_" TARGET_VARIABLE "${target}")
add_custom_command(OUTPUT ${DESTINATION_FOLDER}/${target}.wast.hpp
DEPENDS ${DESTINATION_FOLDER}/${target}.wast
COMMAND echo "const char* ${target}_wast = R\"=====(" > ${DESTINATION_FOLDER}/${target}.wast.hpp
COMMAND echo "const char* const ${TARGET_VARIABLE}_wast = R\"=====(" > ${DESTINATION_FOLDER}/${target}.wast.hpp
COMMAND cat ${DESTINATION_FOLDER}/${target}.wast >> ${DESTINATION_FOLDER}/${target}.wast.hpp
COMMAND echo ")=====\";" >> ${DESTINATION_FOLDER}/${target}.wast.hpp
COMMENT "Generating ${target}.wast.hpp"
......@@ -151,7 +152,7 @@ macro(add_wast_target target INCLUDE_FOLDERS DESTINATION_FOLDER)
if (EXISTS ${DESTINATION_FOLDER}/${target}.abi )
add_custom_command(OUTPUT ${DESTINATION_FOLDER}/${target}.abi.hpp
DEPENDS ${DESTINATION_FOLDER}/${target}.abi
COMMAND echo "const char* ${target}_abi = R\"=====(" > ${DESTINATION_FOLDER}/${target}.abi.hpp
COMMAND echo "const char* const ${TARGET_VARIABLE}_abi = R\"=====(" > ${DESTINATION_FOLDER}/${target}.abi.hpp
COMMAND cat ${DESTINATION_FOLDER}/${target}.abi >> ${DESTINATION_FOLDER}/${target}.abi.hpp
COMMAND echo ")=====\";" >> ${DESTINATION_FOLDER}/${target}.abi.hpp
COMMENT "Generating ${target}.abi.hpp"
......
......@@ -31,7 +31,7 @@ RUN wget https://dl.bintray.com/boostorg/release/1.64.0/source/boost_1_64_0.tar.
&& ./bootstrap.sh --prefix=/usr/local \
&& echo 'using clang : 4.0 : clang++-4.0 ;' >> project-config.jam \
&& ./b2 -d0 -j4 --with-thread --with-date_time --with-system --with-filesystem --with-program_options \
--with-signals --with-serialization --with-chrono --with-test --with-context --with-locale --with-coroutine toolset=clang link=static install \
--with-signals --with-serialization --with-chrono --with-test --with-context --with-locale --with-coroutine --with-iostreams toolset=clang link=static install \
&& cd .. && rm -rf boost_1_64_0
RUN wget https://github.com/mongodb/mongo-c-driver/releases/download/1.8.0/mongo-c-driver-1.8.0.tar.gz -O - | tar -xz \
......
......@@ -27,7 +27,7 @@ The public testnet described in the [wiki](https://github.com/EOSIO/eos/wiki/Tes
2. [Setting up a build/development environment](#setup)
1. [Automated build script](#autobuild)
1. [Clean install Ubuntu 16.10 for a local testnet](#autoubuntulocal)
2. [Clean install Ubuntu 16.10 for the public testnet](#autobuntupublic)
2. [Clean install Ubuntu 16.10 for the public testnet](#autoubuntupublic)
3. [MacOS Sierra 10.12.6 for a local testnet](#automaclocal)
4. [MacOS Sierra 10.12.6 for the public testnet](#automacpublic)
3. [Building EOS and running a node](#runanode)
......@@ -61,25 +61,29 @@ The following instructions detail the process of getting the software, building
For Ubuntu 16.10 and MacOS Sierra, there is an automated build script that can install all dependencies and builds EOS.
It is called build.sh with the following inputs.
It is called eosio-build.sh with the following inputs.
- architecture [ubuntu|darwin]
- optional mode [full|build]
The second optional input can be `full` or `build` where `full` implies that it installs dependencies and builds eos. If you omit this input then the build script installs dependencies and then builds eos.
```bash
./build.sh <architecture> <optional mode>
./eosio-build.sh <architecture> <optional mode>
```
Choose whether you will be building for a local testnet or for the public testnet and jump to the appropriate section below. Clone the EOS repository recursively as described and run build.sh located in the root `eos` folder.
Choose whether you will be building for a local testnet or for the public testnet and jump to the appropriate section below. Clone the EOS repository recursively as described and run eosio-build.sh located in the root `eos` folder.
:warning: **As of February 2018, `master` is under heavy development and is not suitable for experimentation.** :warning:
We strongly recommend following the instructions for building the public testnet version for [Ubuntu](#autoubuntupublic) or [Mac OS X](#automacpublic). `master` is in pieces on the garage floor while we rebuild this hotrod. This notice will be removed when `master` is usable again. Your patience is appreciated.
<a name="autoubuntulocal"></a>
#### Clean install Ubuntu 16.10 for a local testnet
#### :no_entry: Clean install Ubuntu 16.10 for a local testnet :no_entry:
```bash
git clone https://github.com/eosio/eos --recursive
cd eos
./build.sh ubuntu
./eosio-build.sh ubuntu
```
Now you can proceed to the next step - [Creating and launching a single-node testnet](#singlenode)
......@@ -92,13 +96,13 @@ git clone https://github.com/eosio/eos --recursive
cd eos
git checkout dawn-2.x
./build.sh ubuntu
./eosio-build.sh ubuntu
```
Now you can proceed to the next step - [Running a node on the public testnet](#publictestnet)
<a name="automaclocal"></a>
#### MacOS Sierra for a local testnet
#### :no_entry: MacOS Sierra for a local testnet :no_entry:
Before running the script make sure you have updated XCode and brew:
......@@ -107,13 +111,13 @@ xcode-select --install
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```
Then clone the EOS repository recursively and run build.sh in the root `eos` folder.
Then clone the EOS repository recursively and run eosio-build.sh in the root `eos` folder.
```bash
git clone https://github.com/eosio/eos --recursive
cd eos
./build.sh darwin
./eosio-build.sh darwin
```
Now you can proceed to the next step - [Creating and launching a single-node testnet](#singlenode)
......@@ -128,14 +132,14 @@ xcode-select --install
ruby -e "$(curl -fsSl https://raw.githubusercontent.com/Homebrew/install/master/install)"
```
Then clone the EOS repository recursively, checkout the branch that is compatible with the public testnet, and run build.sh in the root `eos` folder.
Then clone the EOS repository recursively, checkout the branch that is compatible with the public testnet, and run eosio-build.sh in the root `eos` folder.
```bash
git clone https://github.com/eosio/eos --recursive
cd eos
git checkout dawn-2.x
./build.sh darwin
./eosio-build.sh darwin
```
Now you can proceed to the next step - [Running a node on the public testnet](#publictestnet)
......@@ -184,8 +188,8 @@ EOS comes with a number of programs you can find in `~/eos/build/programs`. They
* eosiod - server-side blockchain node component
* eosioc - command line interface to interact with the blockchain
* eosio-walletd - EOS wallet
* launcher - application for nodes network composing and deployment; [more on launcher](https://github.com/EOSIO/eos/blob/master/testnet.md)
* eosiowd - EOS wallet
* eosio-launcher - application for nodes network composing and deployment; [more on eosio-launcher](https://github.com/EOSIO/eos/blob/master/testnet.md)
<a name="singlenode"></a>
### Creating and launching a single-node testnet
......@@ -425,14 +429,14 @@ As expected, the receiving account **inita** now has a balance of **20** tokens,
<a name="localtestnet"></a>
## Running multi-node local testnet
To run a local testnet you can use a `launcher` application provided in the `~/eos/build/programs/launcher` folder.
To run a local testnet you can use the `eosio-launcher` application provided in the `~/eos/build/programs/eosio-launcher` folder.
For testing purposes you will run two local production nodes talking to each other.
```bash
cd ~/eos/build
cp ../genesis.json ./
./programs/launcher/launcher -p2 --skip-signature
./programs/eosio-launcher/eosio-launcher -p2 --skip-signature
```
This command will generate two data folders for each instance of the node: `tn_data_00` and `tn_data_01`.
......@@ -453,7 +457,7 @@ To confirm the nodes are running, run the following `eosioc` commands:
For each command, you should get a JSON response with blockchain information.
You can read more on launcher and its settings [here](https://github.com/EOSIO/eos/blob/master/testnet.md)
You can read more on eosio-launcher and its settings [here](https://github.com/EOSIO/eos/blob/master/testnet.md)
<a name="publictestnet"></a>
## Running a local node connected to the public testnet
......
......@@ -13,6 +13,7 @@ add_subdirectory(test_api_mem)
#add_subdirectory(simpledb)
#add_subdirectory(storage)
#add_subdirectory(social)
add_subdirectory(noop)
install( DIRECTORY eosiolib DESTINATION include/ )
install( DIRECTORY skeleton DESTINATION share/ )
......@@ -10,8 +10,16 @@
"fields": [
{"name":"from", "type":"account_name"},
{"name":"to", "type":"account_name"},
{"name":"quantity", "type":"uint64"}
{"name":"quantity", "type":"asset"},
{"name":"memo", "type":"string"}
]
},{
"name": "issue",
"base": "",
"fields": [
{"name":"to", "type":"account_name"},
{"name":"quantity", "type":"asset"}
]
},{
"name": "account",
"base": "",
......@@ -19,11 +27,23 @@
{"name":"key", "type":"name"},
{"name":"balance", "type":"uint64"}
]
},{
"name": "nonce",
"base": "",
"fields": [
{"name":"value", "type":"string"}
]
}
],
"actions": [{
"name": "transfer",
"type": "transfer"
},{
"name": "issue",
"type": "issue"
},{
"name": "nonce",
"type": "nonce"
}
],
"tables": [{
......
......@@ -6,6 +6,7 @@
#include <eosiolib/token.hpp>
#include <eosiolib/db.hpp>
#include <eosiolib/reflect.hpp>
#include <eosiolib/print.hpp>
#include <eosiolib/generic_currency.hpp>
#include <eosiolib/datastream.hpp>
......@@ -19,6 +20,34 @@ namespace eosiosystem {
static const account_name system_account = N(eosio.system);
typedef eosio::generic_currency< eosio::token<system_account,S(4,EOS)> > currency;
struct total_bandwidth {
account_name owner;
typename currency::token_type total_net_weight;
typename currency::token_type total_cpu_weight;
};
typedef eosio::table64<SystemAccount, N(totalband), SystemAccount, total_bandwidth> total_bandwidth;
struct delegated_bandwidth {
account_name from;
account_name to;
typename currency::token_type net_weight;
typename currency::token_type cpu_weight;
uint32_t start_pending_net_withdraw = 0;
typename currency::token_type pending_net_withdraw;
uint64_t deferred_net_withdraw_handler = 0;
uint32_t start_pending_cpu_withdraw = 0;
typename currency::token_type pending_cpu_withdraw;
uint64_t deferred_cpu_withdraw_handler = 0;
};
ACTION( SystemAccount, finshundel ) {
account_name from;
account_name to;
};
ACTION( SystemAccount, regproducer ) {
account_name producer_to_register;
......@@ -31,6 +60,35 @@ namespace eosiosystem {
EOSLIB_SERIALIZE( regproxy, (proxy_to_register) );
};
ACTION( SystemAccount, delnetbw ) {
account_name from;
account_name receiver;
typename currency::token_type stake_quantity;
EOSLIB_SERIALIZE( delnetbw, (delegator)(receiver)(stake_quantity) )
};
ACTION( SystemAccount, undelnetbw ) {
account_name from;
account_name receiver;
typename currency::token_type stake_quantity;
EOSLIB_SERIALIZE( delnetbw, (delegator)(receiver)(stake_quantity) )
};
ACTION( SystemAccount, nonce ) {
eosio::string value;
EOSLIB_SERIALIZE( nonce, (value) );
};
static void on( const delnetbw& del ) {
require_auth( del.from );
// require_account( receiver );
currency::inline_transfer( del.from, SystemAccount, del.stake_quantity, "stake bandwidth" );
}
static void on( const regproducer& reg ) {
require_auth( reg.producer_to_register );
}
......@@ -39,16 +97,15 @@ namespace eosiosystem {
require_auth( reg.proxy_to_register );
}
static void on( const nonce& ) {
}
static void apply( account_name code, action_name act ) {
if( !eosio::dispatch<contract,
// typename currency::transfer_memo,
// typename currency::issue,
regproducer,
regproxy
>( code, act) )
{
assert( false, "received unexpected action" );
if( !eosio::dispatch<contract, regproducer, regproxy, nonce>( code, act) ) {
if ( !eosio::dispatch<currency, typename currency::transfer, typename currency::issue>( code, act ) ) {
eosio::print("Unexpected action: ", act, "\n");
assert( false, "received unexpected action");
}
}
} /// apply
};
......
此差异已折叠。
此差异已折叠。
......@@ -74,8 +74,8 @@ namespace eosio {
* Each user stores their balance in the singleton table under the
* scope of their account name.
*/
typedef table64<code, accounts_table_name, account> accounts;
typedef table64<code, stats_table_name, currency_stats> stats;
typedef table64<code, accounts_table_name, code, account> accounts;
typedef table64<code, stats_table_name, code, currency_stats> stats;
static token_type get_balance( account_name owner ) {
return accounts::get_or_create( token_type::symbol, owner ).balance;
......@@ -115,7 +115,7 @@ namespace eosio {
static void apply( account_name c, action_name act) {
eosio::dispatch<generic_currency, transfer_memo, issue>(c,act);
eosio::dispatch<generic_currency, transfer, issue>(c,act);
}
};
......
......@@ -104,7 +104,7 @@ Get information related to an account.
@subsubsection examplegetaccount Example get_account Usage
```
$ curl http://127.0.0.1:8888/v1/chain/get_account -X POST -d '{"name":"inita"}'
$ curl http://127.0.0.1:8888/v1/chain/get_account -X POST -d '{"account_name":"inita"}'
```
@subsubsection examplegetaccountresult Example get_account Result
......
......@@ -11,7 +11,7 @@ namespace eosio {
* @tparam SingletonName - the name of this singlton variable
* @tparam T - the type of the singleton
*/
template<account_name Code, uint64_t SingletonName, typename T>
template<account_name Code, uint64_t SingletonName, account_name BillToAccount, typename T>
class singleton
{
public:
......@@ -19,20 +19,26 @@ namespace eosio {
static bool exists( scope_name scope = Code ) {
uint64_t key = SingletonName;
auto read = load_i64( scope, Code, key, (char*)&key, sizeof(key) );
auto read = load_i64( Code, scope, key, (char*)&key, sizeof(key) );
return read > 0;
}
static T get( scope_name scope = Code ) {
char temp[1024+8];
*reinterpret_cast<uint64_t *>(temp) = SingletonName;
auto read = load_i64( scope, Code, SingletonName, temp, sizeof(temp) );
auto read = load_i64( Code, scope, SingletonName, temp, sizeof(temp) );
assert( read > 0, "singleton does not exist" );
datastream<const char*> ds(temp + sizeof(SingletonName), read);
return unpack<T>( temp + sizeof(SingletonName), read );
}
T result;
unpack( ds, result );
return result;
static T get_or_default( scope_name scope = Code, const T& def = T() ) {
char temp[1024+8];
*reinterpret_cast<uint64_t *>(temp) = SingletonName;
auto read = load_i64( Code, scope, SingletonName, temp, sizeof(temp) );
if ( read < 0 ) {
return def;
}
return unpack<T>( temp + sizeof(SingletonName), read );
}
static T get_or_create( scope_name scope = Code, const T& def = T() ) {
......@@ -40,19 +46,15 @@ namespace eosio {
*reinterpret_cast<uint64_t *>(temp) = SingletonName;
auto read = load_i64( scope, Code, SingletonName, temp, sizeof(temp) );
auto read = load_i64( Code, scope, SingletonName, temp, sizeof(temp) );
if( read < 0 ) {
set( def, scope );
return def;
}
datastream<const char*> ds(temp + sizeof(SingletonName), read);
T result;
ds >> result;
return result;
return unpack<T>( temp + sizeof(SingletonName), read );
}
static void set( const T& value = T(), scope_name scope = Code ) {
static void set( const T& value = T(), scope_name scope = Code, account_name b = BillToAccount ) {
auto size = pack_size( value );
char buf[size+ sizeof(SingletonName)];
......@@ -62,7 +64,12 @@ namespace eosio {
ds << SingletonName;
ds << value;
store_i64( scope, SingletonName, buf, sizeof(buf) );
store_i64( scope, SingletonName, b, buf, sizeof(buf) );
}
static void remove( scope_name scope = Code ) {
uint64_t key = SingletonName;
remove_i64( scope, SingletonName, &key );
}
};
......
......@@ -4,6 +4,7 @@
#include <eosiolib/system.h>
#include <eosiolib/memory.hpp>
#include <eosiolib/print.hpp>
#include <eosiolib/varint.hpp>
namespace eosio {
/**
......
......@@ -8,19 +8,19 @@ namespace eosio {
* @tparam TableName - the name of the table with rows of type T
* @tparam T - a struct where the first 8 bytes are used as primary/unique key
*/
template<uint64_t DefaultScope, uint64_t TableName, typename T>
template<uint64_t DefaultScope, uint64_t TableName, uint64_t BillToAccount, typename T>
class table64
{
public:
static bool exists( uint64_t key, scope_name scope = DefaultScope) {
auto read = load_i64( scope, DefaultScope, TableName, (char*)&key, sizeof(key) );
auto read = load_i64( DefaultScope, scope, TableName, (char*)&key, sizeof(key) );
return read > 0;
}
static T get( uint64_t key, scope_name scope = DefaultScope ) {
char temp[1024];
*reinterpret_cast<uint64_t *>(temp) = key;
auto read = load_i64( scope, DefaultScope , TableName, temp, sizeof(temp) );
auto read = load_i64( DefaultScope, scope , TableName, temp, sizeof(temp) );
assert( read > 0, "key does not exist" );
datastream<const char*> ds(temp, read);
......@@ -33,7 +33,7 @@ namespace eosio {
char temp[1024];
*reinterpret_cast<uint64_t *>(temp) = key;
auto read = load_i64( scope, DefaultScope, TableName, temp, sizeof(temp) );
auto read = load_i64( DefaultScope, scope, TableName, temp, sizeof(temp) );
if( read < 0 ) {
set( def, scope );
return def;
......@@ -60,7 +60,7 @@ namespace eosio {
return result;
}
static void set( const T& value = T(), scope_name scope = DefaultScope ) {
static void set( const T& value = T(), scope_name scope = DefaultScope, uint64_t bta = BillToAccount ) {
auto size = pack_size( value );
char buf[size];
assert( size <= 1024, "singleton too big to store" );
......@@ -68,7 +68,7 @@ namespace eosio {
datastream<char*> ds( buf, size );
ds << value;
store_i64( scope, TableName, buf, ds.tellp() );
store_i64( scope, TableName, bta, buf, ds.tellp() );
}
static void remove( uint64_t key, scope_name scope = DefaultScope ) {
......@@ -77,7 +77,7 @@ namespace eosio {
};
template<uint64_t Code, uint64_t TableName, typename T>
template<uint64_t Code, uint64_t TableName, uint64_t BillToAccount, typename T>
class table_i64i64i64 {
public:
table_i64i64i64( uint64_t scope = Code )
......@@ -93,7 +93,7 @@ namespace eosio {
temp[1] = secondary;
temp[2] = tertiary;
auto read = lower_bound_primary_i64i64i64( Code, _scope, TableName,
auto read = lower_bound_primary_i64i64i64( Code, _scope, TableName,
(char*)temp, sizeof(temp) );
if( read <= 0 ) {
return false;
......@@ -104,27 +104,37 @@ namespace eosio {
return true;
}
bool next_primary( T& result, const T& current ) {
bool primary_upper_bound( T& result,
uint64_t primary = 0,
uint64_t secondary = 0,
uint64_t tertiary = 0 ) {
uint64_t temp[1024/8];
memcpy( temp, (const char*)&current, 3*sizeof(uint64_t) );
auto read = next_primary_i64i64i64( Code, _scope, TableName,
temp[0] = primary;
temp[1] = secondary;
temp[2] = tertiary;
auto read = upper_bound_primary_i64i64i64( Code, _scope, TableName,
(char*)temp, sizeof(temp) );
if( read <= 0 ) {
return false;
}
datastream<const char*> ds( (char*)temp, sizeof(temp) );
ds >> result;
result = unpack<T>( (char*)temp, sizeof(temp) );
return true;
}
void store( const T& value, account_name bill_to ) {
bool next_primary( T& result, const T& current ) {
const uint64_t* keys = reinterpret_cast<const uint64_t*>(&current);
return primary_upper_bound(result, keys[0], keys[1], keys[2]);
}
void store( const T& value, account_name bill_to = BillToAccount ) {
char temp[1024];
datastream<char*> ds(temp, sizeof(temp) );
ds << value;
store_i64i64i64( _scope, TableName, temp, ds.tellp() );
store_i64i64i64( _scope, TableName, bill_to, temp, ds.tellp() );
}
void remove(uint64_t primary_key, uint64_t seconday_key, uint64_t tertiary_key) {
......
......@@ -62,18 +62,12 @@
{"name":"identity", "type":"uint64"},
{"name":"creator", "type":"account_name"}
]
},{
"name": "trustrow",
"base": "",
"fields": [
{"name":"account", "type":"account_name"},
{"name":"trusted", "type":"uint8"}
]
},{
"name": "accountrow",
"base": "",
"fields": [
{"name":"account", "type":"account_name"}
{"name":"singleton_name", "type":"uint64"},
{"name":"identity", "type":"uint64"}
]
}
],
......@@ -110,7 +104,7 @@
"key_types": [ "uint64" ]
},{
"name": "trust",
"type": "trustrow",
"type": "account_name",
"index_type": "i64",
"key_names" : [ "account" ],
"key_types": [ "account_name" ]
......
......@@ -2,6 +2,7 @@
#include <eosiolib/chain.h>
#include <eosiolib/dispatcher.hpp>
#include <eosiolib/singleton.hpp>
#include <eosiolib/table.hpp>
#include <eosiolib/vector.hpp>
#include <eosiolib/string.hpp>
......@@ -10,6 +11,7 @@ namespace identity {
using eosio::action_meta;
using eosio::table_i64i64i64;
using eosio::table64;
using eosio::singleton;
using eosio::string;
using eosio::vector;
......@@ -193,10 +195,10 @@ namespace identity {
}
};
typedef table_i64i64i64<code, N(certs), certrow> certs_table;
typedef table64<code, N(ident), identrow> idents_table;
typedef table64<code, N(account), identity_name> accounts_table;
typedef table64<code, N(trust), trustrow> trust_table;
typedef table_i64i64i64<code, N(certs), code, certrow> certs_table;
typedef table64<code, N(ident), code, identrow> idents_table;
typedef singleton<code, N(account), code, identity_name> accounts_table;
typedef table64<code, N(trust), code, account_name> trust_table;
static identity_name get_claimed_identity( account_name acnt ) {
return accounts_table::get_or_default(acnt, 0);
......@@ -209,13 +211,19 @@ namespace identity {
certs_table certs( ident );
certrow row;
bool ok = certs.primary_lower_bound(row, N(owner), 1, 0);
account_name owner = 0;
while (ok && row.property == N(owner) && row.trusted) {
if (sizeof(account_name) == row.data.size()) {
account_name account = *reinterpret_cast<account_name*>(row.data.data());
if (ident == get_claimed_identity(account)) {
if (is_trusted(row.certifier) ) {
// the certifier is still trusted
return account;
if (!owner || owner == account) {
owner = account;
} else {
//contradiction found: different owners certified for the same identity
return 0;
}
} else if (DeployToAccount == current_receiver()){
//the certifier is no longer trusted, need to unset the flag
row.trusted = 0;
......@@ -227,8 +235,13 @@ namespace identity {
} else {
// bad row - skip it
}
//ok = certs.primary_upper_bound(row, row.property, row.trusted, row.certifier);
ok = certs.next_primary(row, row);
}
if (owner) {
//owner found, no contradictions among certifications flaged as trusted
return owner;
}
// trusted certification not found
// let's see if some of untrusted certifications became trusted
ok = certs.primary_lower_bound(row, N(owner), 0, 0);
......@@ -236,18 +249,25 @@ namespace identity {
if (sizeof(account_name) == row.data.size()) {
account_name account = *reinterpret_cast<account_name*>(row.data.data());
if (ident == get_claimed_identity(account) && is_trusted(row.certifier)) {
// the certifier became trusted, need to set the flag
row.trusted = 1;
certs.store( row, 0 ); //assuming 0 means bill to the same account
return *reinterpret_cast<account_name*>(row.data.data());
if (DeployToAccount == current_receiver()) {
// the certifier became trusted and we have permissions to update the flag
row.trusted = 1;
certs.store( row, 0 ); //assuming 0 means bill to the same account
}
if (!owner || owner == account) {
owner = account;
} else {
//contradiction found: different owners certified for the same identity
return 0;
}
}
} else {
// bad row - skip it
}
//ok = certs.primary_upper_bound(row, row.property, row.trusted, row.certifier);
ok = certs.next_primary(row, row);
}
return 0;
return owner;
}
static identity_name get_identity_for_account( account_name acnt ) {
......@@ -258,10 +278,7 @@ namespace identity {
}
static bool is_trusted_by( account_name trusted, account_name by ) {
trustrow def;
def.trusted = 0;
trustrow row = trust_table::get_or_default( trusted, by, def );
return def.trusted;
return trust_table::exists(trusted, by);
}
static bool is_trusted( account_name acnt ) {
......@@ -283,13 +300,9 @@ namespace identity {
require_recipient( t.trusting );
if( t.trust != 0 ) {
trustrow row{ .account = t.trusting,
.trusted = t.trust };
trust_table::set( row, t.trustor );
trust_table::set( t.trusting, t.trustor );
} else {
trustrow row{ .account = t.trusting,
.trusted = t.trust };
trust_table::remove( row.account, t.trustor );
trust_table::remove( t.trusting, t.trustor );
}
}
......@@ -318,7 +331,7 @@ namespace identity {
row.trusted = is_trusted( cert.certifier );
row.certifier = cert.certifier;
row.confidence = value.confidence;
assert(value.type.get_size() <= 32, "certrow::type shouldn't be longer than 32 bytes");
assert(value.type.get_size() <= 32, "certrow::type should be not longer than 32 bytes");
row.type = value.type;
row.data = value.data;
......@@ -330,17 +343,21 @@ namespace identity {
if (value.property == N(owner)) {
assert(sizeof(account_name) == value.data.size(), "data size doesn't match account_name size");
account_name acnt = *reinterpret_cast<const account_name*>(value.data.data());
accounts_table::set( acnt, cert.identity );
if (cert.certifier == acnt) { //only self-certitication affects accounts_table
accounts_table::set( cert.identity, acnt );
}
}
} else {
//remove both tursted and untrusted because we cannot now if it was trusted back at creation time
//remove both tursted and untrusted because we cannot know if it was trusted back at creation time
certs.remove(value.property, 0, cert.certifier);
certs.remove(value.property, 1, cert.certifier);
//special handling for owner
if (value.property == N(owner)) {
assert(sizeof(account_name) == value.data.size(), "data size doesn't match account_name size");
account_name acnt = *reinterpret_cast<const account_name*>(value.data.data());
accounts_table::remove( acnt, cert.identity );
if (cert.certifier == acnt) { //only self-certitication affects accounts_table
accounts_table::remove( acnt );
}
}
}
}
......
......@@ -49,7 +49,7 @@ namespace identity_test {
}
};
typedef singleton<code, N(result), uint64_t> result_table;
typedef singleton<code, N(result), code, uint64_t> result_table;
static void on( const get_owner_for_identity& c ) {
account_name owner = identity_contract::get_owner_for_identity(c.identity);
......
file(GLOB ABI_FILES "*.abi")
configure_file("${ABI_FILES}" "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY)
add_wast_target(noop "${CMAKE_SOURCE_DIR}/contracts" ${CMAKE_CURRENT_BINARY_DIR})
{
"types": [{
"new_type_name": "account_name",
"type": "name"
}
],
"structs": [{
"name": "anyaction",
"base": "",
"fields": [
{"name":"from", "type":"account_name"},
{"name":"type", "type":"string"},
{"name":"data", "type":"string"}
]
}
],
"actions": [{
"name":"anyaction",
"type":"anyaction"
}
],
"tables": []
}
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#include <noop/noop.hpp>
namespace noop {
extern "C" {
/// The apply method implements the dispatch of events to this contract
void apply( uint64_t code, uint64_t action ) {
eosio::dispatch<noop, noop::anyaction>(code, action);
}
}
}
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#pragma once
#include <eosiolib/eosio.hpp>
#include <eosiolib/dispatcher.hpp>
#include <eosiolib/string.hpp>
using namespace eosio;
namespace noop {
/**
noop contract
All it does is require sender authorization.
Actions: anyaction
*/
class noop {
public:
ACTION(N(noop), anyaction) {
anyaction() { }
anyaction(account_name f, const string& t, const string& d): from(f), type(t), data(d) { }
account_name from;
string type;
string data;
EOSLIB_SERIALIZE(anyaction, (from)(type)(data))
};
static void on(const anyaction& act)
{
require_auth(act.from);
}
};
} /// noop
......@@ -3,12 +3,26 @@
* @copyright defined in eos/LICENSE.txt
*/
#include <proxy/proxy.hpp>
#include <eosiolib/native_currency.hpp>
#include <eosio.system/eosio.system.hpp>
#include <eosiolib/transaction.hpp>
namespace proxy {
using namespace eosio;
namespace configs {
bool get(config &out, const account_name &self) {
auto read = load_i64(self, self, N(config), (char*)&out, sizeof(config));
if (read < 0) {
return false;
}
return true;
}
void store(const config &in, const account_name &self) {
store_i64(self, N(config), self, (const char *)&in, sizeof(config));
}
};
template<typename T>
void apply_transfer(account_name code, const T& transfer) {
config code_config;
......@@ -44,9 +58,10 @@ namespace proxy {
template<size_t ...Args>
void apply_onerror( const deferred_transaction& failed_dtrx ) {
eosio::print("starting onerror\n");
const auto self = current_receiver();
config code_config;
assert(configs::get(code_config, self), "Attempting to use unconfigured proxy");
assert(configs::get(code_config, self), "Attempting use of unconfigured proxy");
auto id = code_config.next_id++;
configs::store(code_config, self);
......@@ -63,12 +78,14 @@ extern "C" {
/// The apply method implements the dispatch of events to this contract
void apply( uint64_t code, uint64_t action ) {
if ( code == N(eosio) ) {
if( action == N(transfer) ) {
apply_transfer(code, unpack_action<native_currency::transfer>());
} else if ( action == N(onerror)) {
if ( code == N(eosio)) {
if (action == N(onerror)) {
apply_onerror(deferred_transaction::from_current_action());
}
} else if ( code == N(eosio.system) ) {
if( action == N(transfer) ) {
apply_transfer(code, unpack_action<eosiosystem::contract<N(eosio.system)>::currency::transfer_memo>());
}
} else if (code == current_receiver() ) {
if ( action == N(setowner)) {
apply_setowner(current_action<set_owner>());
......
......@@ -3,7 +3,6 @@
* @copyright defined in eos/LICENSE.txt
*/
#include <eosiolib/eosio.hpp>
#include <eosiolib/db.hpp>
namespace proxy {
......@@ -22,6 +21,4 @@ namespace proxy {
uint32_t next_id = 0;
};
using configs = eosio::table<N(proxy),N(proxy),N(configs),config,uint64_t>;
} /// namespace proxy
......@@ -15,127 +15,127 @@
"name": "inita",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initb",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initc",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initd",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "inite",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initf",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initg",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "inith",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initi",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initj",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initk",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initl",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initm",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initn",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "inito",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initp",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initq",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initr",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "inits",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initt",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initu",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
}],
"initial_producers": [{
......
......@@ -9,6 +9,7 @@ add_library( eosio_chain
block.cpp
wast_to_wasm.cpp
wasm_interface.cpp
wasm_eosio_constraints.cpp
apply_context.cpp
rate_limiting.cpp
......@@ -22,8 +23,6 @@ add_library( eosio_chain
chain_controller.cpp
contracts/eosio_contract.cpp
contracts/producer_objects.cpp
contracts/staked_balance_objects.cpp
contracts/chain_initializer.cpp
contracts/genesis_state.cpp
contracts/abi_serializer.cpp
......@@ -36,6 +35,7 @@ target_link_libraries( eosio_chain eos_utilities fc chainbase Logging IR WAST WA
target_include_directories( eosio_chain
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_BINARY_DIR}/include"
"${CMAKE_CURRENT_SOURCE_DIR}/../wasm-jit/Include"
"${CMAKE_BINARY_DIR}/contracts"
)
if(MSVC)
......
......@@ -17,6 +17,7 @@ void apply_context::exec_one()
(*native)(*this);
} else {
const auto &a = mutable_controller.get_database().get<account_object, by_name>(receiver);
privileged = a.privileged;
if (a.code.size() > 0) {
// get code from cache
......@@ -101,7 +102,7 @@ void apply_context::exec()
}
for( uint32_t i = 0; i < _inline_actions.size(); ++i ) {
apply_context ncontext( mutable_controller, mutable_db, _inline_actions[i], trx_meta);
apply_context ncontext( mutable_controller, mutable_db, _inline_actions[i], trx_meta, _checktime_limit);
ncontext.exec();
append_results(move(ncontext.results));
}
......@@ -204,22 +205,22 @@ void apply_context::cancel_deferred( uint32_t sender_id ) {
results.canceled_deferred.emplace_back(receiver, sender_id);
}
const contracts::table_id_object* apply_context::find_table( name scope, name code, name table ) {
const contracts::table_id_object* apply_context::find_table( name code, name scope, name table ) {
require_read_lock(code, scope);
return db.find<table_id_object, contracts::by_scope_code_table>(boost::make_tuple(scope, code, table));
return db.find<table_id_object, contracts::by_code_scope_table>(boost::make_tuple(code, scope, table));
}
const contracts::table_id_object& apply_context::find_or_create_table( name scope, name code, name table ) {
const contracts::table_id_object& apply_context::find_or_create_table( name code, name scope, name table ) {
require_read_lock(code, scope);
const auto* existing_tid = db.find<contracts::table_id_object, contracts::by_scope_code_table>(boost::make_tuple(scope, code, table));
const auto* existing_tid = db.find<contracts::table_id_object, contracts::by_code_scope_table>(boost::make_tuple(code, scope, table));
if (existing_tid != nullptr) {
return *existing_tid;
}
require_write_lock(scope);
return mutable_db.create<contracts::table_id_object>([&](contracts::table_id_object &t_id){
t_id.scope = scope;
t_id.code = code;
t_id.scope = scope;
t_id.table = table;
});
}
......@@ -233,21 +234,29 @@ vector<account_name> apply_context::get_active_producers() const {
return accounts;
}
void apply_context::checktime_start() {
_checktime_start = fc::time_point::now();
}
void apply_context::checktime() const {
if ((fc::time_point::now() - _checktime_start).count() > _checktime_limit) {
throw checktime_exceeded();
}
}
const bytes& apply_context::get_packed_transaction() {
if( !trx_meta.packed_trx.size() ) {
if (_cached_trx.empty()) {
auto size = fc::raw::pack_size(trx_meta.trx);
auto size = fc::raw::pack_size(trx_meta.trx());
_cached_trx.resize(size);
fc::datastream<char *> ds(_cached_trx.data(), size);
fc::raw::pack(ds, trx_meta.trx);
fc::raw::pack(ds, trx_meta.trx());
}
return _cached_trx;
}
return trx_meta.packed_trx;
}
} } /// eosio::chain
......@@ -98,7 +98,6 @@ namespace eosio { namespace chain { namespace contracts {
built_in_types.emplace("action_def", pack_unpack<action_def>());
built_in_types.emplace("table_def", pack_unpack<table_def>());
built_in_types.emplace("abi_def", pack_unpack<abi_def>());
built_in_types.emplace("nonce", pack_unpack<nonce>());
}
void abi_serializer::set_abi(const abi_def& abi) {
......
......@@ -3,12 +3,17 @@
* @copyright defined in eos/LICENSE.txt
*/
#include <eosio/chain/contracts/chain_initializer.hpp>
#include <eosio/chain/contracts/objects.hpp>
#include <eosio/chain/contracts/eos_contract.hpp>
#include <eosio/chain/contracts/types.hpp>
#include <eosio/chain/producer_object.hpp>
#include <eosio/chain/permission_object.hpp>
#include <eosio/chain/wast_to_wasm.hpp>
#include <eosio.system/eosio.system.wast.hpp>
#include <eosio.system/eosio.system.abi.hpp>
#include <fc/io/json.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/algorithm/copy.hpp>
......@@ -23,36 +28,25 @@ chain_config chain_initializer::get_chain_start_configuration() {
return genesis.initial_configuration;
}
producer_schedule_type chain_initializer::get_chain_start_producers() {
producer_schedule_type chain_initializer::get_chain_start_producers() {
producer_schedule_type result;
std::transform(genesis.initial_producers.begin(), genesis.initial_producers.end(), result.producers.begin(),
[](const auto& p) { return producer_key{p.owner_name,p.block_signing_key}; });
result.producers.push_back( {config::system_account_name, genesis.initial_key} );
idump((result));
return result;
}
void chain_initializer::register_types(chain_controller& chain, chainbase::database& db) {
// Install the native contract's indexes; we can't do anything until our objects are recognized
db.add_index<staked_balance_multi_index>();
db.add_index<producer_votes_multi_index>();
#define SET_APP_HANDLER( contract, scope, action, nspace ) \
chain._set_apply_handler( #contract, #scope, #action, &BOOST_PP_CAT(contracts::apply_, BOOST_PP_CAT(contract, BOOST_PP_CAT(_,action) ) ) )
SET_APP_HANDLER( eosio, eosio, setproducer, eosio );
SET_APP_HANDLER( eosio, eosio, newaccount, eosio );
SET_APP_HANDLER( eosio, eosio, transfer, eosio );
SET_APP_HANDLER( eosio, eosio, lock, eosio );
SET_APP_HANDLER( eosio, eosio, claim, eosio );
SET_APP_HANDLER( eosio, eosio, unlock, eosio );
SET_APP_HANDLER( eosio, eosio, okproducer, eosio );
SET_APP_HANDLER( eosio, eosio, setproxy, eosio );
SET_APP_HANDLER( eosio, eosio, setcode, eosio );
SET_APP_HANDLER( eosio, eosio, setabi, eosio );
SET_APP_HANDLER( eosio, eosio, updateauth, eosio );
SET_APP_HANDLER( eosio, eosio, deleteauth, eosio );
SET_APP_HANDLER( eosio, eosio, linkauth, eosio );
SET_APP_HANDLER( eosio, eosio, unlinkauth, eosio );
SET_APP_HANDLER( eosio, eosio, nonce, eosio );
SET_APP_HANDLER( eosio, eosio, onerror, eosio );
SET_APP_HANDLER( eosio, eosio, postrecovery, eosio );
SET_APP_HANDLER( eosio, eosio, passrecovery, eosio );
......@@ -66,13 +60,6 @@ abi_def chain_initializer::eos_contract_abi()
eos_abi.types.push_back( type_def{"account_name","name"} );
eos_abi.types.push_back( type_def{"share_type","int64"} );
eos_abi.types.push_back( type_def{"onerror","bytes"} );
eos_abi.actions.push_back( action_def{name("transfer"), "transfer"} );
eos_abi.actions.push_back( action_def{name("lock"), "lock"} );
eos_abi.actions.push_back( action_def{name("unlock"), "unlock"} );
eos_abi.actions.push_back( action_def{name("claim"), "claim"} );
eos_abi.actions.push_back( action_def{name("okproducer"), "okproducer"} );
eos_abi.actions.push_back( action_def{name("setproducer"), "setproducer"} );
eos_abi.actions.push_back( action_def{name("setproxy"), "setproxy"} );
eos_abi.actions.push_back( action_def{name("setcode"), "setcode"} );
eos_abi.actions.push_back( action_def{name("setabi"), "setabi"} );
eos_abi.actions.push_back( action_def{name("linkauth"), "linkauth"} );
......@@ -84,62 +71,9 @@ abi_def chain_initializer::eos_contract_abi()
eos_abi.actions.push_back( action_def{name("passrecovery"), "passrecovery"} );
eos_abi.actions.push_back( action_def{name("vetorecovery"), "vetorecovery"} );
eos_abi.actions.push_back( action_def{name("onerror"), "onerror"} );
eos_abi.actions.push_back( action_def{name("nonce"), "nonce"} );
// ACTION PAYLOADS
eos_abi.structs.emplace_back( struct_def {
"transfer", "", {
{"from", "account_name"},
{"to", "account_name"},
{"amount", "uint64"},
{"memo", "string"},
}
});
eos_abi.structs.emplace_back( struct_def {
"lock", "", {
{"from", "account_name"},
{"to", "account_name"},
{"amount", "share_type"},
}
});
eos_abi.structs.emplace_back( struct_def {
"unlock", "", {
{"account", "account_name"},
{"amount", "share_type"},
}
});
eos_abi.structs.emplace_back( struct_def {
"claim", "", {
{"account", "account_name"},
{"amount", "share_type"},
}
});
eos_abi.structs.emplace_back( struct_def {
"okproducer", "", {
{"voter", "account_name"},
{"producer", "account_name"},
{"approve", "int8"},
}
});
eos_abi.structs.emplace_back( struct_def {
"setproducer", "", {
{"name", "account_name"},
{"key", "public_key"},
{"configuration", "chain_config"},
}
});
eos_abi.structs.emplace_back( struct_def {
"setproxy", "", {
{"stakeholder", "account_name"},
{"proxy", "account_name"},
}
});
eos_abi.structs.emplace_back( struct_def {
"setcode", "", {
......@@ -197,7 +131,6 @@ abi_def chain_initializer::eos_contract_abi()
{"owner", "authority"},
{"active", "authority"},
{"recovery", "authority"},
{"deposit", "asset"},
}
});
......@@ -221,12 +154,6 @@ abi_def chain_initializer::eos_contract_abi()
}
});
eos_abi.structs.emplace_back( struct_def {
"nonce", "", {
{"value", "name"}
}
});
// DATABASE RECORDS
eos_abi.structs.emplace_back( struct_def {
"account", "", {
......@@ -275,57 +202,76 @@ std::vector<action> chain_initializer::prepare_database( chain_controller& chain
std::vector<action> messages_to_process;
/// Create the native contract accounts manually; sadly, we can't run their contracts to make them create themselves
auto create_native_account = [this, &db](account_name name, auto liquid_balance) {
auto create_native_account = [this, &db](account_name name) {
db.create<account_object>([this, &name](account_object& a) {
a.name = name;
a.creation_date = genesis.initial_timestamp;
a.privileged = true;
if( name == config::system_account_name ) {
a.set_abi(eos_contract_abi());
}
});
const auto& owner = db.create<permission_object>([&name](permission_object& p) {
const auto& owner = db.create<permission_object>([&](permission_object& p) {
p.owner = name;
p.name = "owner";
p.auth.threshold = 1;
p.auth.keys.push_back( key_weight{ .key = genesis.initial_key, .weight = 1 } );
});
db.create<permission_object>([&name, &owner](permission_object& p) {
db.create<permission_object>([&](permission_object& p) {
p.owner = name;
p.parent = owner.id;
p.name = "active";
p.auth.threshold = 1;
p.auth.keys.push_back( key_weight{ .key = genesis.initial_key, .weight = 1 } );
});
db.create<bandwidth_usage_object>([&](auto& sb) {
sb.owner = name;
sb.net_weight = -1;
sb.cpu_weight = -1;
sb.db_reserved_capacity = -1;
});
db.create<producer_object>( [&]( auto& pro ) {
pro.owner = config::system_account_name;
pro.signing_key = genesis.initial_key;
});
intialize_eosio_tokens(db, name, liquid_balance);
db.create<staked_balance_object>([&](auto& sb) { sb.owner_name = name; });
db.create<bandwidth_usage_object>([&](auto& sb) { sb.owner = name; });
};
create_native_account(config::system_account_name, config::initial_token_supply);
create_native_account(config::system_account_name);
// Queue up messages which will run contracts to create the initial accounts
auto init_eosio_sytem = genesis_state_type::initial_account_type(name(config::eosio_system_account_name).to_string(), 0, 0, genesis.eosio_system_key, genesis.eosio_system_key);
genesis.initial_accounts.emplace_back(move(init_eosio_sytem));
for (const auto& acct : genesis.initial_accounts) {
action message( {{config::system_account_name, config::active_name}},
newaccount{ config::system_account_name, acct.name,
authority(acct.owner_key),
authority(acct.active_key),
authority(acct.owner_key),
acct.staking_balance});
authority(acct.owner_key)
});
messages_to_process.emplace_back(move(message));
if (acct.liquid_balance > asset(0)) {
message = action( {{config::system_account_name, config::active_name}},
transfer{ .from = config::system_account_name, .to = acct.name,
.amount = acct.liquid_balance.amount, .memo = "Genesis Allocation"});
messages_to_process.emplace_back(move(message));
}
}
// Create initial producers
auto create_producer = boost::adaptors::transformed([config = genesis.initial_configuration](const auto& p) {
return action( {{p.owner_name, config::active_name}},
setproducer(p.owner_name, p.block_signing_key, config));
});
boost::copy(genesis.initial_producers | create_producer, std::back_inserter(messages_to_process));
// Create initial contracts eosio.system
auto wasm = wast_to_wasm(eosio_system_wast);
action eosio_system_setcode({{config::eosio_system_account_name, config::active_name}},
contracts::setcode{
.account = config::eosio_system_account_name,
.vmtype = 0,
.vmversion = 0,
.code = bytes(wasm.begin(), wasm.end())
});
auto abi = fc::json::from_string(eosio_system_abi).template as<contracts::abi_def>();
action eosio_system_setabi({{config::eosio_system_account_name, config::active_name}},
contracts::setabi{
.account = config::eosio_system_account_name,
.abi = abi
});
messages_to_process.emplace_back(move(eosio_system_setcode));
messages_to_process.emplace_back(move(eosio_system_setabi));
// Create special accounts
auto create_special_account = [this, &db](account_name name, const auto& owner, const auto& active) {
......@@ -349,9 +295,7 @@ std::vector<action> chain_initializer::prepare_database( chain_controller& chain
auto empty_authority = authority(0, {}, {});
auto active_producers_authority = authority(config::producers_authority_threshold, {}, {});
for(auto& p : genesis.initial_producers) {
active_producers_authority.accounts.push_back({{p.owner_name, config::active_name}, 1});
}
active_producers_authority.accounts.push_back({{config::system_account_name, config::active_name}, 1});
create_special_account(config::nobody_account_name, empty_authority, empty_authority);
create_special_account(config::producers_account_name, empty_authority, active_producers_authority);
......
......@@ -15,8 +15,6 @@
#include <eosio/chain/permission_object.hpp>
#include <eosio/chain/permission_link_object.hpp>
#include <eosio/chain/global_property_object.hpp>
#include <eosio/chain/contracts/staked_balance_objects.hpp>
#include <eosio/chain/contracts/producer_objects.hpp>
#include <eosio/chain/contracts/types.hpp>
#include <eosio/chain/producer_object.hpp>
......@@ -42,31 +40,16 @@ void intialize_eosio_tokens(chainbase::database& db, const account_name& system_
}
static void modify_eosio_balance( apply_context& context, const account_name& account, share_type amt) {
const auto& t_id = context.find_or_create_table(account, config::system_account_name, N(currency));
const auto& t_id = context.find_or_create_table(config::system_account_name, account, N(currency));
uint64_t key = N(account);
share_type balance = 0;
context.front_record<key_value_index, by_scope_primary>(t_id, &key, (char *)&balance, sizeof(balance));
balance += amt;
context.store_record<key_value_object>(t_id, &key, (const char *)&balance, sizeof(balance));
context.store_record<key_value_object>(t_id, config::system_account_name, &key, (const char *)&balance, sizeof(balance));
}
share_type get_eosio_balance( const chainbase::database& db, const account_name &account ) {
const auto* t_id = db.find<table_id_object, by_scope_code_table>(boost::make_tuple(account, config::system_account_name, N(currency)));
if (!t_id) {
return share_type(0);
}
const auto& idx = db.get_index<key_value_index, by_scope_primary>();
auto itr = idx.lower_bound(boost::make_tuple(t_id->id));
if ( itr == idx.end() || itr->t_id != t_id->id ) {
return share_type(0);
}
FC_ASSERT(itr->value.size() == sizeof(share_type), "Invalid data in EOSIO balance table");
return *reinterpret_cast<const share_type *>(itr->value.data());
}
void validate_authority_precondition( const apply_context& context, const authority& auth ) {
for(const auto& a : auth.accounts) {
......@@ -76,9 +59,7 @@ void validate_authority_precondition( const apply_context& context, const author
}
/**
* This method is called assuming precondition_system_newaccount succeeds and proceeds to
* deduct the balance of the account creator by deposit, this deposit is supposed to be
* credited to the staked balance the new account in the @staked contract.
* This method is called assuming precondition_system_newaccount succeeds a
*/
void apply_eosio_newaccount(apply_context& context) {
auto create = context.act.as<newaccount>();
......@@ -118,104 +99,10 @@ void apply_eosio_newaccount(apply_context& context) {
const auto& owner_permission = create_permission("owner", 0, std::move(create.owner));
create_permission("active", owner_permission.id, std::move(create.active));
share_type creator_balance = get_eosio_balance(context.db, create.creator);
EOS_ASSERT(creator_balance >= create.deposit.amount, action_validate_exception,
"Creator '${c}' has insufficient funds to make account creation deposit of ${a}",
("c", create.creator)("a", create.deposit));
modify_eosio_balance(context, create.creator, -create.deposit.amount);
const auto& sbo = context.mutable_db.create<staked_balance_object>([&]( staked_balance_object& sbo) {
sbo.owner_name = create.name;
sbo.staked_balance = 0;
});
sbo.stake_tokens( create.deposit.amount, context.mutable_db );
db.create<bandwidth_usage_object>([&]( auto& bu ) { bu.owner = create.name; });
} FC_CAPTURE_AND_RETHROW( (create) ) }
/**
*
* @ingroup native_eos
* @defgroup eos_eosio_transfer eosio::eos_transfer
*/
///@{
void apply_eosio_transfer(apply_context& context) {
auto transfer = context.act.as<contracts::transfer>();
try {
EOS_ASSERT(transfer.amount > 0, action_validate_exception, "Must transfer a positive amount");
context.require_write_lock(transfer.to);
context.require_write_lock(transfer.from);
context.require_authorization(transfer.from);
context.require_recipient(transfer.to);
context.require_recipient(transfer.from);
} FC_CAPTURE_AND_RETHROW((transfer))
try {
auto& db = context.mutable_db;
share_type from_balance = get_eosio_balance(db, transfer.from);
EOS_ASSERT(from_balance >= transfer.amount, action_validate_exception, "Insufficient Funds",
("from_balance", from_balance)("transfer.amount",transfer.amount));
modify_eosio_balance(context, transfer.from, - share_type(transfer.amount) );
modify_eosio_balance(context, transfer.to, share_type(transfer.amount) );
} FC_CAPTURE_AND_RETHROW( (transfer) )
}
///@}
/**
* Deduct the balance from the from account.
*/
void apply_eosio_lock(apply_context& context) {
auto lock = context.act.as<contracts::lock>();
EOS_ASSERT(lock.amount > 0, action_validate_exception, "Locked amount must be positive");
context.require_write_lock(lock.to);
context.require_write_lock(lock.from);
context.require_write_lock(config::system_account_name);
context.require_authorization(lock.from);
context.require_recipient(lock.to);
context.require_recipient(lock.from);
share_type locker_balance = get_eosio_balance(context.db, lock.from);
EOS_ASSERT( locker_balance >= lock.amount, action_validate_exception,
"Account ${a} lacks sufficient funds to lock ${amt} EOS", ("a", lock.from)("amt", lock.amount)("available",locker_balance) );
modify_eosio_balance(context, lock.from, -share_type(lock.amount));
const auto& balance = context.db.get<staked_balance_object, by_owner_name>(lock.to);
balance.stake_tokens(lock.amount, context.mutable_db);
}
void apply_eosio_unlock(apply_context& context) {
auto unlock = context.act.as<contracts::unlock>();
context.require_authorization(unlock.account);
EOS_ASSERT(unlock.amount >= 0, action_validate_exception, "Unlock amount cannot be negative");
const auto& balance = context.db.get<staked_balance_object, by_owner_name>(unlock.account);
EOS_ASSERT(balance.staked_balance >= unlock.amount, action_validate_exception,
"Insufficient locked funds to unlock ${a}", ("a", unlock.amount));
balance.begin_unstaking_tokens(unlock.amount, context.mutable_db);
}
void apply_eosio_setcode(apply_context& context) {
auto& db = context.mutable_db;
......@@ -229,6 +116,10 @@ void apply_eosio_setcode(apply_context& context) {
auto code_id = fc::sha256::hash( act.code.data(), act.code.size() );
// TODO: remove this compilation step in favor of validation without compilation
auto& code = context.mutable_controller.get_wasm_cache().checkout(code_id, act.code.data(), act.code.size());
context.mutable_controller.get_wasm_cache().checkin(code_id, code);
const auto& account = db.get<account_object,by_name>(act.account);
// wlog( "set code: ${size}", ("size",act.code.size()));
db.modify( account, [&]( auto& a ) {
......@@ -262,148 +153,6 @@ void apply_eosio_setabi(apply_context& context) {
});
}
void apply_eosio_claim(apply_context& context) {
auto claim = context.act.as<contracts::claim>();
EOS_ASSERT(claim.amount > 0, action_validate_exception, "Claim amount must be positive");
context.require_authorization(claim.account);
auto balance = context.db.find<staked_balance_object, by_owner_name>(claim.account);
EOS_ASSERT(balance != nullptr, action_validate_exception,
"Could not find staked balance for ${name}", ("name", claim.account));
auto balance_release_time = balance->last_unstaking_time + fc::seconds(config::staked_balance_cooldown_sec);
auto now = context.controller.head_block_time();
EOS_ASSERT(now >= balance_release_time, action_validate_exception,
"Cannot claim balance until ${releaseDate}", ("releaseDate", balance_release_time));
EOS_ASSERT(balance->unstaking_balance >= claim.amount, action_validate_exception,
"Cannot claim ${claimAmount} as only ${available} is available for claim",
("claimAmount", claim.amount)("available", balance->unstaking_balance));
const auto& staked_balance = context.db.get<staked_balance_object, by_owner_name>(claim.account);
staked_balance.finish_unstaking_tokens(claim.amount, context.mutable_db);
modify_eosio_balance(context, claim.account, share_type(claim.amount));
}
void apply_eosio_setproducer(apply_context& context) {
auto update = context.act.as<setproducer>();
context.require_authorization(update.name);
EOS_ASSERT(update.name.good(), action_validate_exception, "Producer owner name cannot be empty");
auto& db = context.mutable_db;
auto producer = db.find<producer_object, by_owner>(update.name);
if (producer) {
EOS_ASSERT(producer->signing_key != update.key || producer->configuration != update.configuration,
action_validate_exception, "Producer's new settings may not be identical to old settings");
db.modify(*producer, [&](producer_object& p) {
p.signing_key = update.key;
p.configuration = update.configuration;
});
} else {
db.create<producer_object>([&](producer_object& p) {
p.owner = update.name;
p.signing_key = update.key;
p.configuration = update.configuration;
});
db.create<producer_votes_object>([&](producer_votes_object& pvo) {
pvo.owner_name = update.name;
});
}
}
void apply_eosio_okproducer(apply_context& context) {
auto approve = context.act.as<okproducer>();
EOS_ASSERT(approve.approve == 0 || approve.approve == 1, action_validate_exception,
"Unknown approval value: ${val}; must be either 0 or 1", ("val", approve.approve));
context.require_recipient(approve.voter);
context.require_recipient(approve.producer);
context.require_write_lock(config::system_account_name);
context.require_write_lock(approve.voter);
context.require_authorization(approve.voter);
auto& db = context.mutable_db;
const auto& producer = db.get<producer_votes_object, by_owner_name>(approve.producer);
const auto& voter = db.get<staked_balance_object, by_owner_name>(approve.voter);
EOS_ASSERT(voter.producer_votes.contains<producer_slate>(), action_validate_exception,
"Cannot approve producer; approving account '${name}' proxies its votes to '${proxy}'",
("name", voter.owner_name)("proxy", voter.producer_votes.get<account_name>()));
const auto& slate = voter.producer_votes.get<producer_slate>();
EOS_ASSERT(slate.size < config::max_producer_votes, action_validate_exception,
"Cannot approve producer; approved producer count is already at maximum");
if (approve.approve)
EOS_ASSERT(!slate.contains(producer.owner_name), action_validate_exception,
"Cannot add approval to producer '${name}'; producer is already approved",
("name", producer.owner_name));
else
EOS_ASSERT(slate.contains(producer.owner_name), action_validate_exception,
"Cannot remove approval from producer '${name}'; producer is not approved",
("name", producer.owner_name));
auto total_voting_stake = voter.staked_balance;
// Add/remove votes from producer
db.modify(producer, [approve = approve.approve, total_voting_stake](producer_votes_object& pvo) {
if (approve)
pvo.update_votes(total_voting_stake);
else
pvo.update_votes(-total_voting_stake);
});
// Add/remove producer from voter's approved producer list
db.modify(voter, [&approve, producer = producer.owner_name](staked_balance_object& sbo) {
auto& slate = sbo.producer_votes.get<producer_slate>();
if (approve.approve)
slate.add(producer);
else
slate.remove(producer);
});
}
void apply_eosio_setproxy(apply_context& context) {
auto svp = context.act.as<setproxy>();
FC_ASSERT( !"Not Implemented Yet" );
/*
context.require_authorization( spv.stakeholder );
context.require_recipient(svp.stakeholder);
context.require_recipient(svp.proxy);
auto& db = context.mutable_db;
const auto& proxy = db.get<proxy_vote_object, by_target_name>(context.act.recipient(svp.proxy));
const auto& balance = db.get<staked_balance_object, by_owner_name>(context.act.recipient(svp.stakeholder));
auto proxy = db.find<proxy_vote_object, by_target_name>(context.act.recipient(svp.proxy));
if (svp.proxy != svp.stakeholder) {
// We are enabling proxying to svp.proxy
proxy.add_proxy_source(context.act.recipient(svp.stakeholder), balance.staked_balance, db);
db.modify(balance, [target = proxy.proxy_target](staked_balance_object& sbo) { sbo.producer_votes = target; });
} else {
// We are disabling proxying to balance.producer_votes.get<account_name>()
proxy.remove_proxy_source(context.act.recipient(svp.stakeholder), balance.staked_balance, db);
db.modify(balance, [](staked_balance_object& sbo) { sbo.producer_votes = producer_slate{}; });
}
*/
}
void apply_eosio_updateauth(apply_context& context) {
context.require_write_lock( config::eosio_auth_scope );
......@@ -548,9 +297,6 @@ void apply_eosio_unlinkauth(apply_context& context) {
db.remove(*link);
}
void apply_eosio_nonce(apply_context&) {
/// do nothing
}
void apply_eosio_onerror(apply_context& context) {
assert(context.trx_meta.sender);
......@@ -567,7 +313,7 @@ static const abi_serializer& get_abi_serializer() {
}
static optional<variant> get_pending_recovery(apply_context& context, account_name account ) {
const auto* t_id = context.find_table(account, config::system_account_name, N(recovery));
const auto* t_id = context.find_table(config::system_account_name, account, N(recovery));
if (t_id) {
uint64_t key = account;
int32_t record_size = context.front_record<key_value_index, by_scope_primary>(*t_id, &key, nullptr, 0);
......@@ -588,13 +334,13 @@ static optional<variant> get_pending_recovery(apply_context& context, account_na
static uint32_t get_next_sender_id(apply_context& context) {
context.require_write_lock( config::eosio_auth_scope );
const auto& t_id = context.find_or_create_table(config::eosio_auth_scope, config::system_account_name, N(deferred.seq));
const auto& t_id = context.find_or_create_table(config::system_account_name, config::eosio_auth_scope, N(deferred.seq));
uint64_t key = N(config::eosio_auth_scope);
uint32_t next_serial = 0;
context.front_record<key_value_index, by_scope_primary>(t_id, &key, (char *)&next_serial, sizeof(uint32_t));
uint32_t result = next_serial++;
context.store_record<key_value_object>(t_id, &key, (char *)&next_serial, sizeof(uint32_t));
context.store_record<key_value_object>(t_id, config::system_account_name, &key, (char *)&next_serial, sizeof(uint32_t));
return result;
}
......@@ -681,15 +427,15 @@ void apply_eosio_postrecovery(apply_context& context) {
context.execute_deferred(std::move(dtrx));
const auto& t_id = context.find_or_create_table(account, config::system_account_name, N(recovery));
const auto& t_id = context.find_or_create_table(config::system_account_name, account, N(recovery));
auto data = get_abi_serializer().variant_to_binary("pending_recovery", record_data);
context.store_record<key_value_object>(t_id,&account.value, data.data() + sizeof(uint64_t), data.size() - sizeof(uint64_t));
context.store_record<key_value_object>(t_id, 0, &account.value, data.data() + sizeof(uint64_t), data.size() - sizeof(uint64_t));
context.console_append_formatted("Recovery Started for account ${account} : ${memo}\n", mutable_variant_object()("account", account)("memo", recover_act.memo));
}
static void remove_pending_recovery(apply_context& context, const account_name& account) {
const auto& t_id = context.find_or_create_table(account, config::system_account_name, N(recovery));
const auto& t_id = context.find_or_create_table(config::system_account_name, account, N(recovery));
context.remove_record<key_value_object>(t_id, &account.value);
}
......
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#include <eosio/chain/contracts/producer_objects.hpp>
#include <eosio/chain/contracts/staked_balance_objects.hpp>
#include <eosio/chain/producer_object.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/range/algorithm_ext.hpp>
namespace eosio { namespace chain { namespace contracts {
} } } // namespace eosio::chain::contracts
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#include <eosio/chain/contracts/staked_balance_objects.hpp>
#include <eosio/chain/contracts/producer_objects.hpp>
#include <eosio/chain/global_property_object.hpp>
#include <boost/range/algorithm/for_each.hpp>
namespace eosio { namespace chain { namespace contracts {
void staked_balance_object::stake_tokens(share_type new_stake, chainbase::database& db) const {
// Update the staked balance
db.modify(*this, [&new_stake](staked_balance_object& sbo) {
sbo.staked_balance += new_stake;
});
db.modify( db.get<dynamic_global_property_object>(), [&]( auto& dgpo ){
dgpo.total_staked_tokens += new_stake;
});
propagate_votes(new_stake, db);
}
void staked_balance_object::begin_unstaking_tokens(share_type amount, chainbase::database& db) const {
// Remember there might be stake left over from a previous, uncompleted unstaking in unstaking_balance
auto delta_stake = unstaking_balance - amount;
// Update actual stake balance and invariants around it
stake_tokens(delta_stake, db);
// Update stats for unstaking process
db.modify(*this, [&amount, &db](staked_balance_object& sbo) {
sbo.unstaking_balance = amount;
sbo.last_unstaking_time = db.get(dynamic_global_property_object::id_type()).time;
});
}
void staked_balance_object::finish_unstaking_tokens(share_type amount, chainbase::database& db) const {
db.modify(*this, [&amount](staked_balance_object& sbo) {
sbo.unstaking_balance -= amount;
});
db.modify( db.get<dynamic_global_property_object>(), [&]( auto& dgpo ){
dgpo.total_staked_tokens -= amount;
});
}
void staked_balance_object::propagate_votes(share_type staked_delta, chainbase::database& db) const {
if (producer_votes.contains<producer_slate>())
// This account votes for producers directly; update their stakes
boost::for_each(producer_votes.get<producer_slate>().range(), [&db, &staked_delta](const account_name& name) {
db.modify(db.get<producer_votes_object, by_owner_name>(name), [&db, &staked_delta](producer_votes_object& pvo) {
pvo.update_votes(staked_delta);
});
});
else {
}
}
} } } // namespace eosio::chain::contracts
......@@ -13,8 +13,8 @@ fc::variant_object get_config()
{
fc::mutable_variant_object result;
result["block_interval_ms"] = config::block_interval_ms;
result["producer_count"] = config::producer_count;
// result["block_interval_ms"] = config::block_interval_ms;
// result["producer_count"] = config::producer_count;
/// TODO: add extra config parms
return result;
}
......
......@@ -19,6 +19,9 @@ namespace eosio { namespace chain {
account_name name;
uint8_t vm_type = 0;
uint8_t vm_version = 0;
bool privileged = false;
bool frozen = false;
time_point_sec last_code_update;
digest_type code_version;
block_timestamp_type creation_date;
......
......@@ -39,34 +39,34 @@ struct asset
uint8_t decimals()const;
string symbol_name()const;
int64_t precision()const;
const symbol& symbol() const { return sym; }
const symbol& get_symbol() const { return sym; }
static asset from_string(const string& from);
string to_string()const;
asset& operator += (const asset& o)
{
FC_ASSERT(symbol() == o.symbol());
FC_ASSERT(get_symbol() == o.get_symbol());
amount += o.amount;
return *this;
}
asset& operator -= (const asset& o)
{
FC_ASSERT(symbol() == o.symbol());
FC_ASSERT(get_symbol() == o.get_symbol());
amount -= o.amount;
return *this;
}
asset operator -()const { return asset(-amount, symbol()); }
asset operator -()const { return asset(-amount, get_symbol()); }
friend bool operator == (const asset& a, const asset& b)
{
return std::tie(a.symbol(), a.amount) == std::tie(b.symbol(), b.amount);
return std::tie(a.get_symbol(), a.amount) == std::tie(b.get_symbol(), b.amount);
}
friend bool operator < (const asset& a, const asset& b)
{
FC_ASSERT(a.symbol() == b.symbol());
return std::tie(a.amount,a.symbol()) < std::tie(b.amount,b.symbol());
FC_ASSERT(a.get_symbol() == b.get_symbol());
return std::tie(a.amount,a.get_symbol()) < std::tie(b.amount,b.get_symbol());
}
friend bool operator <= (const asset& a, const asset& b) { return (a == b) || (a < b); }
friend bool operator != (const asset& a, const asset& b) { return !(a == b); }
......@@ -74,13 +74,13 @@ struct asset
friend bool operator >= (const asset& a, const asset& b) { return !(a < b); }
friend asset operator - (const asset& a, const asset& b) {
FC_ASSERT(a.symbol() == b.symbol());
return asset(a.amount - b.amount, a.symbol());
FC_ASSERT(a.get_symbol() == b.get_symbol());
return asset(a.amount - b.amount, a.get_symbol());
}
friend asset operator + (const asset& a, const asset& b) {
FC_ASSERT(a.symbol() == b.symbol());
return asset(a.amount + b.amount, a.symbol());
FC_ASSERT(a.get_symbol() == b.get_symbol());
return asset(a.amount + b.amount, a.get_symbol());
}
friend std::ostream& operator << (std::ostream& out, const asset& a) { return out << a.to_string(); }
......
......@@ -50,7 +50,7 @@ namespace eosio { namespace chain {
skip_output_check = 1 << 13, ///< used to skip checks for outputs in block exactly matching those created from apply
pushed_transaction = 1 << 14, ///< used to indicate that the origination of the call was from a push_transaction, to determine time allotment
created_block = 1 << 15, ///< used to indicate that the origination of the call was for creating a block, to determine time allotment
received_block = 1 << 16, ///< used to indicate that the origination of the call was for a received block, to determine time allotment
received_block = 1 << 16, ///< used to indicate that the origination of the call was for a received block, to determine time allotment
genesis_setup = 1 << 17, ///< used to indicate that the origination of the call was for a genesis transaction
skip_missed_block_penalty = 1 << 18, ///< used to indicate that missed blocks shouldn't count against producers (used in long unit tests)
};
......@@ -121,6 +121,8 @@ namespace eosio { namespace chain {
* @return True if the controller is now applying a block; false otherwise
*/
bool is_applying_block()const { return _currently_applying_block; }
bool is_start_of_round( block_num_type n )const;
uint32_t blocks_per_round()const;
chain_id_type get_chain_id()const { return chain_id_type(); } /// TODO: make this hash of constitution
......@@ -292,10 +294,17 @@ namespace eosio { namespace chain {
)const;
void set_txn_execution_times(uint32_t create_block_txn_execution_time, uint32_t rcvd_block_txn_execution_time, uint32_t txn_execution_time);
static const uint32_t default_received_block_transaction_execution_time_ms;
static const uint32_t default_transaction_execution_time_ms;
static const uint32_t default_create_block_transaction_execution_time_ms;
private:
const apply_handler* find_apply_handler( account_name contract, scope_name scope, action_name act )const;
uint32_t txn_execution_time() const;
friend class contracts::chain_initializer;
friend class apply_context;
......@@ -321,7 +330,7 @@ namespace eosio { namespace chain {
void _initialize_chain(contracts::chain_initializer& starter);
producer_schedule_type _calculate_producer_schedule()const;
const producer_schedule_type& _head_producer_schedule()const;
const shared_producer_schedule_type& _head_producer_schedule()const;
void replay();
......@@ -432,6 +441,10 @@ namespace eosio { namespace chain {
map< account_name, map<handler_key, apply_handler> > _apply_handlers;
wasm_cache _wasm_cache;
uint32_t _create_block_txn_execution_time;
uint32_t _rcvd_block_txn_execution_time;
uint32_t _txn_execution_time;
};
} }
......@@ -13,12 +13,12 @@ typedef __uint128_t uint128_t;
const static auto default_block_log_dir = "block_log";
const static auto default_shared_memory_dir = "shared_mem";
const static auto default_shared_memory_size = 1024*1024*1024ll;
const static int producer_count = 21;
const static uint64_t system_account_name = N(eosio);
const static uint64_t nobody_account_name = N(nobody);
const static uint64_t anybody_account_name = N(anybody);
const static uint64_t producers_account_name = N(producers);
const static uint64_t eosio_system_account_name = N(eosio.system);
const static uint64_t eosio_auth_scope = N(eosio.auth);
const static uint64_t eosio_all_scope = N(eosio.all);
......@@ -71,13 +71,13 @@ const static uint16_t max_recursion_depth = 6;
/**
* The number of sequential blocks produced by a single producer
*/
const static int producer_repititions = 6;
const static int producer_repititions = 12;
/**
* The number of blocks produced per round is based upon all producers having a chance
* to produce all of their consecutive blocks.
*/
const static int blocks_per_round = producer_count * producer_repititions;
//const static int blocks_per_round = producer_count * producer_repititions;
const static int irreversible_threshold_percent= 70 * percent_1;
const static int max_producer_votes = 30;
......
......@@ -18,12 +18,13 @@ namespace eosio { namespace chain { namespace contracts {
OBJECT_CTOR(table_id_object)
id_type id;
scope_name scope;
account_name code;
scope_name scope;
table_name table;
uint32_t count = 0; /// the number of elements in the table
};
struct by_scope_code_table;
struct by_code_scope_table;
using table_id_multi_index = chainbase::shared_multi_index_container<
table_id_object,
......@@ -31,10 +32,10 @@ namespace eosio { namespace chain { namespace contracts {
ordered_unique<tag<by_id>,
member<table_id_object, table_id_object::id_type, &table_id_object::id>
>,
ordered_unique<tag<by_scope_code_table>,
ordered_unique<tag<by_code_scope_table>,
composite_key< table_id_object,
member<table_id_object, scope_name, &table_id_object::scope>,
member<table_id_object, account_name, &table_id_object::code>,
member<table_id_object, scope_name, &table_id_object::scope>,
member<table_id_object, table_name, &table_id_object::table>
>
>
......@@ -47,6 +48,7 @@ namespace eosio { namespace chain { namespace contracts {
struct by_scope_secondary;
struct by_scope_tertiary;
struct key_value_object : public chainbase::object<key_value_object_type, key_value_object> {
OBJECT_CTOR(key_value_object, (value))
......@@ -57,6 +59,7 @@ namespace eosio { namespace chain { namespace contracts {
table_id t_id;
uint64_t primary_key;
shared_string value;
account_name payer = 0;
};
using key_value_index = chainbase::shared_multi_index_container<
......@@ -73,6 +76,90 @@ namespace eosio { namespace chain { namespace contracts {
>
>;
struct by_primary;
struct by_secondary;
template<typename SecondaryKey, uint64_t ObjectTypeId>
struct secondary_index
{
struct index_object : public chainbase::object<ObjectTypeId,index_object> {
OBJECT_CTOR(index_object)
typedef SecondaryKey secondary_key_type;
typename chainbase::object<ObjectTypeId,index_object>::id_type id;
table_id t_id;
uint64_t primary_key;
SecondaryKey secondary_key;
account_name payer;
};
typedef chainbase::shared_multi_index_container<
index_object,
indexed_by<
ordered_unique<tag<by_id>, member<index_object, typename index_object::id_type, &index_object::id>>,
ordered_unique<tag<by_primary>,
composite_key< index_object,
member<index_object, table_id, &index_object::t_id>,
member<index_object, uint64_t, &index_object::primary_key>
>,
composite_key_compare< std::less<table_id>, std::less<uint64_t> >
>,
ordered_unique<tag<by_secondary>,
composite_key< index_object,
member<index_object, SecondaryKey, &index_object::secondary_key>,
member<index_object, uint64_t, &index_object::primary_key>
>
>
>
> index_index;
};
typedef secondary_index<uint64_t,index64_object_type>::index_object index64_object;
typedef secondary_index<uint64_t,index64_object_type>::index_index index64_index;
typedef secondary_index<uint128_t,index128_object_type>::index_object index128_object;
typedef secondary_index<uint128_t,index128_object_type>::index_index index128_index;
/*
struct index64_object : public chainbase::object<index64_object_type, index64_object> {
OBJECT_CTOR(index64_object)
typedef uint64_t key_type;
static const int number_of_keys = 1;
id_type id;
table_id t_id;
uint64_t primary_key;
uint64_t secondary_key;
account_name payer;
};
using index64_index = chainbase::shared_multi_index_container<
index64_object,
indexed_by<
ordered_unique<tag<by_id>, member<index64_object, index64_object::id_type, &index64_object::id>>,
ordered_unique<tag<by_primary>,
composite_key< index64_object,
member<index64_object, table_id, &index64_object::t_id>,
member<index64_object, uint64_t, &index64_object::primary_key>
>,
composite_key_compare< std::less<table_id>, std::less<uint64_t> >
>,
ordered_unique<tag<by_secondary>,
composite_key< index64_object,
member<index64_object, uint64_t, &index64_object::secondary_key>,
member<index64_object, uint64_t, &index64_object::primary_key>
>
>
>
>;
*/
struct shared_string_less {
bool operator()( const char* a, const char* b )const {
return less(a, b);
......@@ -103,6 +190,7 @@ namespace eosio { namespace chain { namespace contracts {
table_id t_id;
shared_string primary_key;
shared_string value;
account_name payer;
};
using keystr_value_index = chainbase::shared_multi_index_container<
......@@ -130,6 +218,7 @@ namespace eosio { namespace chain { namespace contracts {
uint128_t primary_key;
uint128_t secondary_key;
shared_string value;
account_name payer;
};
using key128x128_value_index = chainbase::shared_multi_index_container<
......@@ -155,6 +244,45 @@ namespace eosio { namespace chain { namespace contracts {
>
>;
struct key64x64_value_object : public chainbase::object<key64x64_value_object_type, key64x64_value_object> {
OBJECT_CTOR(key64x64_value_object, (value))
typedef uint64_t key_type;
static const int number_of_keys = 2;
id_type id;
table_id t_id;
uint64_t primary_key;
uint64_t secondary_key;
shared_string value;
account_name payer;
};
using key64x64_value_index = chainbase::shared_multi_index_container<
key64x64_value_object,
indexed_by<
ordered_unique<tag<by_id>, member<key64x64_value_object, key64x64_value_object::id_type, &key64x64_value_object::id>>,
ordered_unique<tag<by_scope_primary>,
composite_key< key64x64_value_object,
member<key64x64_value_object, table_id, &key64x64_value_object::t_id>,
member<key64x64_value_object, uint64_t, &key64x64_value_object::primary_key>,
member<key64x64_value_object, uint64_t, &key64x64_value_object::secondary_key>
>,
composite_key_compare< std::less<table_id>,std::less<uint64_t>,std::less<uint64_t> >
>,
ordered_unique<tag<by_scope_secondary>,
composite_key< key64x64_value_object,
member<key64x64_value_object, table_id, &key64x64_value_object::t_id>,
member<key64x64_value_object, uint64_t, &key64x64_value_object::secondary_key>,
member<key64x64_value_object, typename key64x64_value_object::id_type, &key64x64_value_object::id>
>,
composite_key_compare< std::less<table_id>,std::less<uint64_t>,std::less<typename key64x64_value_object::id_type> >
>
>
>;
struct key64x64x64_value_object : public chainbase::object<key64x64x64_value_object_type, key64x64x64_value_object> {
OBJECT_CTOR(key64x64x64_value_object, (value))
......@@ -167,6 +295,7 @@ namespace eosio { namespace chain { namespace contracts {
uint64_t secondary_key;
uint64_t tertiary_key;
shared_string value;
account_name payer;
};
using key64x64x64_value_index = chainbase::shared_multi_index_container<
......@@ -208,10 +337,15 @@ CHAINBASE_SET_INDEX_TYPE(eosio::chain::contracts::table_id_object, eosio::chain:
CHAINBASE_SET_INDEX_TYPE(eosio::chain::contracts::key_value_object, eosio::chain::contracts::key_value_index)
CHAINBASE_SET_INDEX_TYPE(eosio::chain::contracts::keystr_value_object, eosio::chain::contracts::keystr_value_index)
CHAINBASE_SET_INDEX_TYPE(eosio::chain::contracts::key128x128_value_object, eosio::chain::contracts::key128x128_value_index)
CHAINBASE_SET_INDEX_TYPE(eosio::chain::contracts::key64x64_value_object, eosio::chain::contracts::key64x64_value_index)
CHAINBASE_SET_INDEX_TYPE(eosio::chain::contracts::key64x64x64_value_object, eosio::chain::contracts::key64x64x64_value_index)
FC_REFLECT(eosio::chain::contracts::table_id_object, (id)(scope)(code)(table) )
FC_REFLECT(eosio::chain::contracts::key_value_object, (id)(t_id)(primary_key)(value) )
FC_REFLECT(eosio::chain::contracts::keystr_value_object, (id)(t_id)(primary_key)(value) )
FC_REFLECT(eosio::chain::contracts::key128x128_value_object, (id)(t_id)(primary_key)(secondary_key)(value) )
FC_REFLECT(eosio::chain::contracts::key64x64x64_value_object, (id)(t_id)(primary_key)(secondary_key)(tertiary_key)(value) )
CHAINBASE_SET_INDEX_TYPE(eosio::chain::contracts::index64_object, eosio::chain::contracts::index64_index)
CHAINBASE_SET_INDEX_TYPE(eosio::chain::contracts::index128_object, eosio::chain::contracts::index128_index)
FC_REFLECT(eosio::chain::contracts::table_id_object, (id)(code)(scope)(table) )
FC_REFLECT(eosio::chain::contracts::key_value_object, (id)(t_id)(primary_key)(value)(payer) )
FC_REFLECT(eosio::chain::contracts::keystr_value_object, (id)(t_id)(primary_key)(value)(payer) )
FC_REFLECT(eosio::chain::contracts::key128x128_value_object, (id)(t_id)(primary_key)(secondary_key)(value)(payer) )
FC_REFLECT(eosio::chain::contracts::key64x64_value_object, (id)(t_id)(primary_key)(secondary_key)(value)(payer) )
FC_REFLECT(eosio::chain::contracts::key64x64x64_value_object, (id)(t_id)(primary_key)(secondary_key)(tertiary_key)(value)(payer) )
......@@ -25,23 +25,10 @@ namespace eosio { namespace chain { namespace contracts {
void apply_eosio_passrecovery(apply_context&);
void apply_eosio_vetorecovery(apply_context&);
void apply_eosio_transfer(apply_context& context);
void apply_eosio_lock(apply_context& context);
void apply_eosio_claim(apply_context&);
void apply_eosio_unlock(apply_context&);
void apply_eosio_okproducer(apply_context&);
void apply_eosio_setproducer(apply_context&);
void apply_eosio_setproxy(apply_context&);
void apply_eosio_setcode(apply_context&);
void apply_eosio_setabi(apply_context&);
void apply_eosio_nonce(apply_context&);
void apply_eosio_onerror(apply_context&);
///@} end action handlers
share_type get_eosio_balance( const chainbase::database& db, const account_name& account );
} } } /// namespace eosio::contracts
......@@ -61,6 +61,9 @@ struct genesis_state_type {
};
time_point initial_timestamp;
public_key_type initial_key;
public_key_type eosio_system_key;
vector<initial_account_type> initial_accounts;
vector<initial_producer_type> initial_producers;
......@@ -85,5 +88,5 @@ FC_REFLECT(eosio::chain::contracts::genesis_state_type::initial_account_type,
FC_REFLECT(eosio::chain::contracts::genesis_state_type::initial_producer_type, (owner_name)(block_signing_key))
FC_REFLECT(eosio::chain::contracts::genesis_state_type,
(initial_timestamp)(initial_configuration)(initial_accounts)
(initial_timestamp)(initial_key)(initial_configuration)(initial_accounts)
(initial_producers)(initial_chain_id))
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#pragma once
/// @file This file #include's all database objects/indices used by the C++ native contract implementation
#include <eosio/chain/contracts/staked_balance_objects.hpp>
#include <eosio/chain/contracts/producer_objects.hpp>
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#pragma once
#include <eosio/chain/config.hpp>
#include <eosio/chain/types.hpp>
#include <eosio/chain/multi_index_includes.hpp>
#include <eosio/utilities/exception_macros.hpp>
#include <chainbase/chainbase.hpp>
#include <boost/multi_index/mem_fun.hpp>
namespace eosio { namespace chain { namespace contracts {
FC_DECLARE_EXCEPTION(producer_race_overflow_exception, 10000000, "Producer Virtual Race time has overflowed");
/**
* @brief The producer_votes_object class tracks all votes for and by the block producers
*
* This class tracks the voting for block producers, as well as the virtual time 'race' to select the runner-up block
* producer.
*
* This class also tracks the votes cast by block producers on various chain configuration options and key documents.
*/
class producer_votes_object : public chainbase::object<producer_votes_object_type, producer_votes_object> {
OBJECT_CTOR(producer_votes_object)
id_type id;
account_name owner_name;
share_type votes = 0;
/**
* @brief Update the tally of votes for the producer
* @param delta_votes The change in votes since the last update
*/
void update_votes(share_type delta_votes) {
votes += delta_votes;
}
};
using boost::multi_index::const_mem_fun;
/// Index producers by their owner's name
struct by_owner_name;
/// Index producers by projected race finishing time, from soonest to latest
struct by_projected_race_finish_time;
/// Index producers by votes, from greatest to least
struct by_votes;
using producer_votes_multi_index = chainbase::shared_multi_index_container<
producer_votes_object,
indexed_by<
ordered_unique< tag<by_id>,
member<producer_votes_object, producer_votes_object::id_type, &producer_votes_object::id>
>,
ordered_unique< tag<by_owner_name>,
member<producer_votes_object, account_name, &producer_votes_object::owner_name>
>,
ordered_unique< tag<by_votes>,
composite_key<producer_votes_object,
member<producer_votes_object, share_type, &producer_votes_object::votes>,
member<producer_votes_object, producer_votes_object::id_type, &producer_votes_object::id>
>,
composite_key_compare< std::greater<share_type>,std::less<producer_votes_object::id_type> >
>
>
>;
/// Index proxies by the proxy target account name
struct by_target_name;
} } } // namespace eosio::chain::contracts
CHAINBASE_SET_INDEX_TYPE(eosio::chain::contracts::producer_votes_object, eosio::chain::contracts::producer_votes_multi_index)
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#pragma once
#include <eosio/chain/types.hpp>
#include <eosio/chain/config.hpp>
#include <eosio/chain/multi_index_includes.hpp>
#include <chainbase/chainbase.hpp>
#include <fc/static_variant.hpp>
namespace eosio { namespace chain { namespace contracts {
/**
* @brief The producer_slate struct stores a list of producers voted on by an account
*/
struct producer_slate {
std::array<account_name, config::max_producer_votes> votes;
size_t size = 0;
void add(account_name producer) {
votes[size++] = producer;
std::inplace_merge(votes.begin(), votes.begin() + size - 1, votes.begin() + size);
}
void remove(account_name producer) {
auto itr = std::remove(votes.begin(), votes.begin() + size, producer);
size = std::distance(votes.begin(), itr);
}
bool contains(account_name producer) const {
return std::binary_search(votes.begin(), votes.begin() + size, producer);
}
auto range() { return boost::make_iterator_range_n(votes.begin(), size); }
auto range() const { return boost::make_iterator_range_n(votes.begin(), size); }
};
/**
* @brief The staked_balance_object class tracks the staked balance (voting balance) for accounts
*/
class staked_balance_object : public chainbase::object<staked_balance_object_type, staked_balance_object> {
OBJECT_CTOR(staked_balance_object)
id_type id;
account_name owner_name;
share_type staked_balance = 0;
share_type unstaking_balance = 0;
time_point last_unstaking_time = time_point::maximum();
uint128_t staked_balance_percent = 0;
/// The account's vote on producers. This may either be a list of approved producers, or an account to proxy vote to
fc::static_variant<producer_slate, account_name> producer_votes = producer_slate{};
/**
* @brief Add the provided stake to this balance, maintaining invariants
* @param new_stake The new stake to add to the balance
* @param db Read-write reference to the database
*
* This method will update this object with the new stake, while maintaining invariants around the stake balance,
* such as by updating vote tallies
*/
void stake_tokens(share_type new_stake, chainbase::database& db) const;
/**
* @brief Begin unstaking the specified amount of stake, maintaining invariants
* @param amount The amount of stake to begin unstaking
* @param db Read-write reference to the database
*
* This method will update this object's balances while maintaining invariants around the stake balances, such as by
* updating vote tallies
*/
void begin_unstaking_tokens(share_type amount, chainbase::database& db) const;
/**
* @brief Finish unstaking the specified amount of stake
* @param amount The amount of stake to finish unstaking
* @param db Read-write reference to the database
*
* This method will update this object's balances. There aren't really any invariants to maintain on this call, as
* the tokens are already unstaked and removed from vote tallies, but it is provided for completeness' sake.
*/
void finish_unstaking_tokens(share_type amount, chainbase::database& db) const;
/**
* @brief Propagate the specified change in stake to the producer votes or the proxy
* @param staked_delta The change in stake
* @param db Read-write reference to the database
*
* This method will apply the provided delta in voting stake to the next stage in the producer voting pipeline,
* whether that be the producers in the slate, or the account the votes are proxied to.
*
* This method will *not* update this object in any way. It will not adjust @ref staked_balance, etc
*/
void propagate_votes(share_type staked_delta, chainbase::database& db) const;
};
struct by_owner_name;
using staked_balance_multi_index = chainbase::shared_multi_index_container<
staked_balance_object,
indexed_by<
ordered_unique<tag<by_id>,
member<staked_balance_object, staked_balance_object::id_type, &staked_balance_object::id>
>,
ordered_unique<tag<by_owner_name>,
member<staked_balance_object, account_name, &staked_balance_object::owner_name>
>
>
>;
} } } // namespace eosio::chain::contracts
CHAINBASE_SET_INDEX_TYPE(eosio::chain::contracts::staked_balance_object, eosio::chain::contracts::staked_balance_multi_index)
......@@ -103,83 +103,12 @@ struct abi_def {
vector<table_def> tables;
};
struct transfer {
account_name from;
account_name to;
uint64 amount;
string memo;
static account_name get_account() {
return config::system_account_name;
}
static name get_name() {
return N(transfer);
}
};
struct lock {
lock() = default;
lock(const account_name& from, const account_name& to, const share_type& amount)
:from(from), to(to), amount(amount)
{}
account_name from;
account_name to;
share_type amount;
static account_name get_account() {
return config::system_account_name;
}
static action_name get_name() {
return N(lock);
}
};
struct unlock {
unlock() = default;
unlock(const account_name& account, const share_type& amount)
:account(account), amount(amount)
{}
account_name account;
share_type amount;
static account_name get_account() {
return config::system_account_name;
}
static action_name get_name() {
return N(unlock);
}
};
struct claim {
claim() = default;
claim(const account_name& account, const share_type& amount)
:account(account), amount(amount)
{}
account_name account;
share_type amount;
static account_name get_account() {
return config::system_account_name;
}
static action_name get_name() {
return N(claim);
}
};
struct newaccount {
account_name creator;
account_name name;
authority owner;
authority active;
authority recovery;
asset deposit;
static account_name get_account() {
return config::system_account_name;
......@@ -218,61 +147,6 @@ struct setabi {
}
};
struct setproducer {
setproducer() = default;
setproducer(const account_name& name, const public_key_type& key, const chain_config& configuration)
:name(name), key(key), configuration(configuration)
{}
account_name name;
public_key_type key;
chain_config configuration;
static account_name get_account() {
return config::system_account_name;
}
static action_name get_name() {
return N(setproducer);
}
};
struct okproducer {
okproducer() = default;
okproducer(const account_name& voter, const account_name& producer, const int8_t& approve)
:voter(voter), producer(producer), approve(approve)
{}
account_name voter;
account_name producer;
int8_t approve;
static account_name get_account() {
return config::system_account_name;
}
static action_name get_name() {
return N(okproducer);
}
};
struct setproxy {
setproxy() = default;
setproxy(const account_name& stakeholder, const account_name& proxy)
:stakeholder(stakeholder), proxy(proxy)
{}
account_name stakeholder;
account_name proxy;
static account_name get_account() {
return config::system_account_name;
}
static action_name get_name() {
return N(setproxy);
}
};
struct updateauth {
account_name account;
......@@ -397,18 +271,6 @@ struct vetorecovery {
}
};
using nonce_type = name;
struct nonce {
nonce_type value;
static account_name get_account() {
return config::system_account_name;
}
static action_name get_name() {
return N(nonce);
}
};
} } } /// namespace eosio::chain::contracts
......@@ -418,16 +280,10 @@ FC_REFLECT( eosio::chain::contracts::struct_def , (name)(b
FC_REFLECT( eosio::chain::contracts::action_def , (name)(type) )
FC_REFLECT( eosio::chain::contracts::table_def , (name)(index_type)(key_names)(key_types)(type) )
FC_REFLECT( eosio::chain::contracts::abi_def , (types)(structs)(actions)(tables) )
FC_REFLECT( eosio::chain::contracts::transfer , (from)(to)(amount)(memo) )
FC_REFLECT( eosio::chain::contracts::lock , (from)(to)(amount) )
FC_REFLECT( eosio::chain::contracts::unlock , (account)(amount) )
FC_REFLECT( eosio::chain::contracts::claim , (account)(amount) )
FC_REFLECT( eosio::chain::contracts::newaccount , (creator)(name)(owner)(active)(recovery)(deposit) )
FC_REFLECT( eosio::chain::contracts::newaccount , (creator)(name)(owner)(active)(recovery) )
FC_REFLECT( eosio::chain::contracts::setcode , (account)(vmtype)(vmversion)(code) ) //abi
FC_REFLECT( eosio::chain::contracts::setabi , (account)(abi) )
FC_REFLECT( eosio::chain::contracts::setproducer , (name)(key)(configuration) )
FC_REFLECT( eosio::chain::contracts::okproducer , (voter)(producer)(approve) )
FC_REFLECT( eosio::chain::contracts::setproxy , (stakeholder)(proxy) )
FC_REFLECT( eosio::chain::contracts::updateauth , (account)(permission)(parent)(data) )
FC_REFLECT( eosio::chain::contracts::deleteauth , (account)(permission) )
FC_REFLECT( eosio::chain::contracts::linkauth , (account)(code)(type)(requirement) )
......@@ -435,5 +291,4 @@ FC_REFLECT( eosio::chain::contracts::unlinkauth , (account
FC_REFLECT( eosio::chain::contracts::postrecovery , (account)(data)(memo) )
FC_REFLECT( eosio::chain::contracts::passrecovery , (account) )
FC_REFLECT( eosio::chain::contracts::vetorecovery , (account) )
FC_REFLECT( eosio::chain::contracts::nonce , (value) )
......@@ -20,6 +20,7 @@ namespace eosio { namespace chain {
FC_DECLARE_DERIVED_EXCEPTION( unlinkable_block_exception, eosio::chain::chain_exception, 3090000, "unlinkable block" )
FC_DECLARE_DERIVED_EXCEPTION( black_swan_exception, eosio::chain::chain_exception, 3100000, "black swan" )
FC_DECLARE_DERIVED_EXCEPTION( unknown_block_exception, eosio::chain::chain_exception, 3110000, "unknown block" )
FC_DECLARE_DERIVED_EXCEPTION( chain_type_exception, eosio::chain::chain_exception, 3120000, "chain type exception" )
FC_DECLARE_DERIVED_EXCEPTION( block_tx_output_exception, eosio::chain::block_validate_exception, 3020001, "transaction outputs in block do not match transaction outputs from applying block" )
FC_DECLARE_DERIVED_EXCEPTION( block_concurrency_exception, eosio::chain::block_validate_exception, 3020002, "block does not guarantee concurrent exection without conflicts" )
......@@ -52,6 +53,13 @@ namespace eosio { namespace chain {
FC_DECLARE_DERIVED_EXCEPTION( pop_empty_chain, eosio::chain::undo_database_exception, 3070001, "there are no blocks to pop" )
FC_DECLARE_DERIVED_EXCEPTION( name_type_exception, eosio::chain::chain_type_exception, 3120001, "Invalid name" )
FC_DECLARE_DERIVED_EXCEPTION( public_key_type_exception, eosio::chain::chain_type_exception, 3120002, "Invalid public key" )
FC_DECLARE_DERIVED_EXCEPTION( authority_type_exception, eosio::chain::chain_type_exception, 3120003, "Invalid authority" )
FC_DECLARE_DERIVED_EXCEPTION( action_type_exception, eosio::chain::chain_type_exception, 3120004, "Invalid action" )
FC_DECLARE_DERIVED_EXCEPTION( transaction_type_exception, eosio::chain::chain_type_exception, 3120005, "Invalid transaction" )
FC_DECLARE_DERIVED_EXCEPTION( abi_type_exception, eosio::chain::chain_type_exception, 3120006, "Invalid ABI" )
#define EOS_RECODE_EXC( cause_type, effect_type ) \
catch( const cause_type& e ) \
......
......@@ -18,6 +18,14 @@
namespace eosio { namespace chain {
struct blocknum_producer_schedule {
blocknum_producer_schedule( allocator<char> a )
:second(a){}
block_num_type first;
shared_producer_schedule_type second;
};
/**
* @class global_property_object
* @brief Maintains global state information (committee_member list, current fees)
......@@ -28,18 +36,19 @@ namespace eosio { namespace chain {
*/
class global_property_object : public chainbase::object<global_property_object_type, global_property_object>
{
OBJECT_CTOR(global_property_object, (pending_active_producers) )
OBJECT_CTOR(global_property_object, (active_producers)(new_active_producers)(pending_active_producers) )
id_type id;
chain_config configuration;
producer_schedule_type active_producers;
shared_producer_schedule_type active_producers;
shared_producer_schedule_type new_active_producers;
/** every block that has change in producer schedule gets inserted into this list, this includes
* all blocks that see a change in producer signing keys or vote order.
*
* TODO: consider moving this to a more effeicent datatype
*/
shared_vector< pair<block_num_type, producer_schedule_type> > pending_active_producers;
shared_vector< blocknum_producer_schedule > pending_active_producers;
};
......@@ -63,7 +72,10 @@ namespace eosio { namespace chain {
time_point time;
account_name current_producer;
share_type total_staked_tokens;
uint64_t total_net_weight = 1;
uint64_t total_cpu_weight = 1;
uint64_t total_db_capacity = 1024*1024*1024ull*1024ull;
uint64_t total_db_reserved = 0;
/**
* The current absolute slot number. Equal to the total
......
#pragma once
#include <eosio/chain/config.hpp>
#include <eosio/chain/types.hpp>
#include <chainbase/chainbase.hpp>
namespace eosio { namespace chain {
......@@ -23,13 +24,39 @@ namespace eosio { namespace chain {
*/
struct producer_schedule_type {
uint32_t version = 0; ///< sequentially incrementing version number
fc::array<producer_key,config::producer_count> producers;
vector<producer_key> producers;
};
struct shared_producer_schedule_type {
shared_producer_schedule_type( chainbase::allocator<char> alloc )
:producers(alloc){}
shared_producer_schedule_type& operator=( const producer_schedule_type& a ) {
version = a.version;
producers.clear();
producers.reserve( a.producers.size() );
for( const auto& p : a.producers )
producers.push_back(p);
return *this;
}
operator producer_schedule_type()const {
producer_schedule_type result;
result.producers.reserve(producers.size());
for( const auto& p : producers )
result.producers.push_back(p);
return result;
}
uint32_t version = 0; ///< sequentially incrementing version number
shared_vector<producer_key> producers;
};
inline bool operator == ( const producer_schedule_type& a, const producer_schedule_type& b )
{
if( a.version != b.version ) return false;
if ( a.producers.size() != b.producers.size() ) return false;
for( uint32_t i = 0; i < a.producers.size(); ++i )
if( a.producers[i] != b.producers[i] ) return false;
return true;
......
......@@ -55,6 +55,10 @@ namespace eosio { namespace chain {
id_type id;
account_name owner;
uint64_t net_weight = 0;
uint64_t cpu_weight = 0;
uint64_t db_reserved_capacity = 0; /// bytes
average_accumulator<config::bandwidth_average_window_ms> bytes;
average_accumulator<config::compute_average_window_ms> acts; ///< tracks a logical number of actions processed
......
......@@ -8,54 +8,62 @@
namespace eosio { namespace chain {
struct transaction_metadata {
class transaction_metadata {
// transaction_metadata( const transaction& t )
// :trx(t)
// ,id(trx.id()) {}
transaction_metadata( const transaction& t, const time_point& published, const account_name& sender, uint32_t sender_id, const char* raw_data, size_t raw_size )
:trx(t)
,id(trx.id())
,published(published)
,sender(sender),sender_id(sender_id),raw_data(raw_data),raw_size(raw_size)
{}
transaction_metadata( const packed_transaction& t, chain_id_type chainid, const time_point& published );
transaction_metadata( transaction_metadata && ) = default;
transaction_metadata& operator= (transaction_metadata &&) = default;
// things for packed_transaction
optional<bytes> raw_trx;
optional<transaction> decompressed_trx;
// things for signed/packed transactions
optional<flat_set<public_key_type>> signing_keys;
const transaction& trx;
transaction_id_type id;
uint32_t region_id = 0;
uint32_t cycle_index = 0;
uint32_t shard_index = 0;
uint32_t bandwidth_usage = 0;
time_point published;
// things for processing deferred transactions
optional<account_name> sender;
uint32_t sender_id = 0;
// packed form to pass to contracts if needed
const char* raw_data = nullptr;
size_t raw_size = 0;
vector<char> packed_trx;
// scopes available to this transaction if we are applying a block
optional<const vector<shard_lock>*> allowed_read_locks;
optional<const vector<shard_lock>*> allowed_write_locks;
static digest_type calculate_transaction_merkle_root( const vector<transaction_metadata>& metas );
public:
transaction_metadata( const transaction& t, const time_point& published, const account_name& sender, uint32_t sender_id, const char* raw_data, size_t raw_size )
:id(t.id())
,published(published)
,sender(sender),sender_id(sender_id),raw_data(raw_data),raw_size(raw_size),_trx(&t)
{}
transaction_metadata( const packed_transaction& t, chain_id_type chainid, const time_point& published );
transaction_metadata( transaction_metadata && ) = default;
transaction_metadata& operator= (transaction_metadata &&) = default;
// things for packed_transaction
optional<bytes> raw_trx;
optional<transaction> decompressed_trx;
// things for signed/packed transactions
optional<flat_set<public_key_type>> signing_keys;
transaction_id_type id;
uint32_t region_id = 0;
uint32_t cycle_index = 0;
uint32_t shard_index = 0;
uint32_t bandwidth_usage = 0;
time_point published;
// things for processing deferred transactions
optional<account_name> sender;
uint32_t sender_id = 0;
// packed form to pass to contracts if needed
const char* raw_data = nullptr;
size_t raw_size = 0;
vector<char> packed_trx;
// scopes available to this transaction if we are applying a block
optional<const vector<shard_lock>*> allowed_read_locks;
optional<const vector<shard_lock>*> allowed_write_locks;
const transaction& trx() const{
if (decompressed_trx) {
return *decompressed_trx;
} else {
return *_trx;
}
}
static digest_type calculate_transaction_merkle_root( const vector<transaction_metadata>& metas );
private:
const transaction* _trx;
};
} } // eosio::chain
......
......@@ -120,6 +120,9 @@ namespace eosio { namespace chain {
action_code_object_type,
key_value_object_type,
key128x128_value_object_type,
key64x64_value_object_type,
index64_object_type,
index128_object_type,
action_permission_object_type,
global_property_object_type,
dynamic_global_property_object_type,
......@@ -172,6 +175,9 @@ FC_REFLECT_ENUM(eosio::chain::object_type,
(action_code_object_type)
(key_value_object_type)
(key128x128_value_object_type)
(key64x64_value_object_type)
(index64_object_type)
(index128_object_type)
(action_permission_object_type)
(global_property_object_type)
(dynamic_global_property_object_type)
......
#pragma once
namespace IR {
struct Module;
};
namespace eosio { namespace chain {
//Throws if something in the module violates
void validate_eosio_wasm_constraints(const IR::Module& m);
}}
......@@ -28,8 +28,8 @@ struct wasm_cache::entry {
struct wasm_context {
wasm_context(wasm_cache::entry &code, apply_context& ctx) : code(code), context(ctx)
{
//initialize to minimum bytes and limit this to 32 bit space
sbrk_bytes = (1 << IR::numBytesPerPageLog2) > UINT32_MAX ? UINT32_MAX : 1 << IR::numBytesPerPageLog2;
MemoryInstance* default_mem = Runtime::getDefaultMemory(code.instance);
sbrk_bytes = default_mem ? Runtime::getMemoryNumPages(default_mem) << IR::numBytesPerPageLog2 : 0;
}
wasm_cache::entry& code;
apply_context& context;
......
......@@ -2,15 +2,16 @@
#include <fc/variant.hpp>
#include <boost/algorithm/string.hpp>
#include <fc/exception/exception.hpp>
#include <eosio/chain/exceptions.hpp>
namespace eosio { namespace chain {
void name::set( const char* str ) {
try {
const auto len = strnlen(str,14);
FC_ASSERT( len <= 13 );
EOS_ASSERT( len <= 13, name_type_exception, "Name is longer than 13 characters (${name}) ", ("name",string(str)) );
value = string_to_name(str);
FC_ASSERT( to_string() == string(str), "name not properly normalized", ("name",string(str))("normalized",to_string()) );
EOS_ASSERT( to_string() == string(str), name_type_exception, "Name not properly normalized (name: ${name}, normalized: ${normalized}) ", ("name",string(str))("normalized",to_string()) );
}FC_CAPTURE_AND_RETHROW( (str) ) }
name::operator string()const {
......
......@@ -7,7 +7,6 @@ namespace eosio { namespace chain {
transaction_metadata::transaction_metadata( const packed_transaction& t, chain_id_type chainid, const time_point& published )
:raw_trx(t.get_raw_transaction())
,decompressed_trx(fc::raw::unpack<transaction>(*raw_trx))
,trx(*decompressed_trx)
,id(decompressed_trx->id())
,bandwidth_usage( (uint32_t)fc::raw::pack_size(t) )
,published(published)
......@@ -19,8 +18,9 @@ digest_type transaction_metadata::calculate_transaction_merkle_root( const vecto
vector<digest_type> ids;
ids.reserve(metas.size());
for( const auto& t : metas )
ids.emplace_back( t.id );
for( const auto& t : metas ) {
ids.emplace_back(t.id);
}
return merkle( std::move(ids) );
}
......
此差异已折叠。
此差异已折叠。
......@@ -102,6 +102,11 @@ namespace fc
*/
std::string to_string( log_level ll = log_level::info )const;
/**
* Generates a user-friendly error report.
*/
std::string top_message( )const;
/**
* Throw this exception as its most derived type.
*
......
此差异已折叠。
file(GLOB HEADERS "include/eosio/tester/*.hpp")
file(GLOB HEADERS "include/eosio/testing/*.hpp")
## SORT .cpp by most likely to change / break compile
add_library( eosio_testing
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册