提交 e3d777f1 编写于 作者: B Bill Hamilton

Merge branch 'eosio_build' into eosio_build_amzn

Merging latest changes from eosio_build branch
......@@ -9,3 +9,11 @@
[submodule "programs/snapshot"]
path = programs/snapshot
url = https://github.com/EOSIO/genesis.git
[submodule "contracts/musl/upstream"]
path = contracts/musl/upstream
url = https://github.com/EOSIO/musl.git
branch = eosio
[submodule "contracts/libc++/upstream"]
path = contracts/libc++/upstream
url = https://github.com/EOSIO/libcxx.git
branch = eosio
......@@ -78,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:
......
......@@ -58,15 +58,22 @@ if( NOT ("${WASM_CLANG}" STREQUAL "" OR "${WASM_LLC}" STREQUAL "" OR "${WASM_LLV
set(WASM_TOOLCHAIN TRUE)
endif()
macro(add_wast_target target INCLUDE_FOLDERS DESTINATION_FOLDER)
macro(compile_wast)
cmake_parse_arguments(ARG "" "TARGET" "SOURCE_FILES;INCLUDE_FOLDERS" ${ARGN})
set(target ${ARG_TARGET})
# NOTE: Setting SOURCE_FILE and looping over it to avoid cmake issue with compilation ${target}.bc's rule colliding with
# linking ${target}.bc's rule
set(SOURCE_FILE ${target}.cpp)
# linking ${target}.bc's rule
if ("${ARG_SOURCE_FILES}" STREQUAL "")
set(SOURCE_FILES ${target}.cpp)
else()
set(SOURCE_FILES ${ARG_SOURCE_FILES})
endif()
set(outfiles "")
foreach(srcfile ${SOURCE_FILE})
foreach(srcfile ${SOURCE_FILES})
get_filename_component(outfile ${srcfile} NAME)
get_filename_component(extension ${srcfile} EXT)
get_filename_component(infile ${srcfile} ABSOLUTE)
# -ffreestanding
......@@ -89,12 +96,17 @@ macro(add_wast_target target INCLUDE_FOLDERS DESTINATION_FOLDER)
# -fno-exceptions
# Disable the generation of extra code needed to propagate exceptions
if ("${extension}" STREQUAL ".c")
set(STDFLAG -D_XOPEN_SOURCE=700)
else()
set(STDFLAG "--std=c++14")
endif()
set(WASM_COMMAND ${WASM_CLANG} -emit-llvm -O3 --std=c++14 --target=wasm32 -ffreestanding
-nostdlib -fno-threadsafe-statics -fno-rtti -fno-exceptions
set(WASM_COMMAND ${WASM_CLANG} -emit-llvm -O3 ${STDFLAG} --target=wasm32 -ffreestanding
-nostdlib -nostdlibinc -fno-threadsafe-statics -fno-rtti -fno-exceptions
-c ${infile} -o ${outfile}.bc
)
foreach(folder ${INCLUDE_FOLDERS})
foreach(folder ${ARG_INCLUDE_FOLDERS})
list(APPEND WASM_COMMAND -I ${folder})
endforeach()
......@@ -111,18 +123,51 @@ macro(add_wast_target target INCLUDE_FOLDERS DESTINATION_FOLDER)
endforeach(srcfile)
add_custom_command(OUTPUT ${target}.bc
set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${target}.bc)
endmacro(compile_wast)
macro(add_wast_library)
cmake_parse_arguments(ARG "" "TARGET;DESTINATION_FOLDER" "SOURCE_FILES;INCLUDE_FOLDERS" ${ARGN})
set(target ${ARG_TARGET})
compile_wast(TARGET ${ARG_TARGET} SOURCE_FILES ${ARG_SOURCE_FILES} INCLUDE_FOLDERS ${ARG_INCLUDE_FOLDERS})
get_filename_component("${ARG_TARGET}_BC_FILENAME" "${ARG_DESTINATION_FOLDER}/${ARG_TARGET}.bc" ABSOLUTE CACHE)
add_custom_target(${target} ALL DEPENDS ${${ARG_TARGET}_BC_FILENAME})
add_custom_command(OUTPUT ${${ARG_TARGET}_BC_FILENAME}
DEPENDS ${outfiles}
COMMAND ${WASM_LLVM_LINK} -o ${target}.bc ${outfiles}
COMMENT "Linking LLVM bitcode ${target}.bc"
COMMAND ${WASM_LLVM_LINK} -o ${${ARG_TARGET}_BC_FILENAME} ${outfiles}
COMMENT "Linking LLVM bitcode library ${target}.bc"
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
VERBATIM
)
endmacro(add_wast_library)
macro(add_wast_executable)
cmake_parse_arguments(ARG "" "TARGET;DESTINATION_FOLDER" "SOURCE_FILES;INCLUDE_FOLDERS;LIBRARIES" ${ARGN})
set(target ${ARG_TARGET})
set(DESTINATION_FOLDER ${ARG_DESTINATION_FOLDER})
compile_wast(TARGET ${ARG_TARGET} SOURCE_FILES ${ARG_SOURCE_FILES} INCLUDE_FOLDERS ${ARG_INCLUDE_FOLDERS})
foreach(lib ${ARG_LIBRARIES})
list(APPEND LIBRARIES ${${lib}_BC_FILENAME})
endforeach()
add_custom_command(OUTPUT ${target}.bc
DEPENDS ${outfiles} ${ARG_LIBRARIES} ${LIBRARIES}
COMMAND ${WASM_LLVM_LINK} -only-needed -o ${target}.bc ${outfiles} ${LIBRARIES}
COMMENT "Linking LLVM bitcode executable ${target}.bc"
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
VERBATIM
)
set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${target}.bc)
add_custom_command(OUTPUT ${target}.s
DEPENDS ${target}.bc
COMMAND ${WASM_LLC} -asm-verbose=false -o ${target}.s ${target}.bc
COMMAND ${WASM_LLC} -thread-model=single -asm-verbose=false -o ${target}.s ${target}.bc
COMMENT "Generating textual assembly ${target}.s"
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
VERBATIM
......@@ -132,7 +177,6 @@ macro(add_wast_target target INCLUDE_FOLDERS DESTINATION_FOLDER)
add_custom_command(OUTPUT ${DESTINATION_FOLDER}/${target}.wast
DEPENDS ${target}.s
COMMAND ${BINARYEN_BIN}/s2wasm -o ${DESTINATION_FOLDER}/${target}.wast -s 4096 ${target}.s
COMMENT "Generating WAST ${target}.wast"
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
VERBATIM
......@@ -149,7 +193,7 @@ macro(add_wast_target target INCLUDE_FOLDERS DESTINATION_FOLDER)
VERBATIM
)
if (EXISTS ${DESTINATION_FOLDER}/${target}.abi )
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${target}.abi )
add_custom_command(OUTPUT ${DESTINATION_FOLDER}/${target}.abi.hpp
DEPENDS ${DESTINATION_FOLDER}/${target}.abi
COMMAND echo "const char* const ${TARGET_VARIABLE}_abi = R\"=====(" > ${DESTINATION_FOLDER}/${target}.abi.hpp
......@@ -163,13 +207,12 @@ macro(add_wast_target target INCLUDE_FOLDERS DESTINATION_FOLDER)
else()
endif()
add_custom_target(${target} ALL DEPENDS ${DESTINATION_FOLDER}/${target}.wast.hpp ${extra_target_dependency})
set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${DESTINATION_FOLDER}/${target}.wast.hpp)
set_property(TARGET ${target} PROPERTY INCLUDE_DIRECTORIES ${INCLUDE_FOLDERS})
set_property(TARGET ${target} PROPERTY INCLUDE_DIRECTORIES ${ARG_INCLUDE_FOLDERS})
set(extra_target_dependency)
endmacro(add_wast_target)
endmacro(add_wast_executable)
......@@ -26,6 +26,7 @@ EOS.IO currently supports the following operating systems:
5. [Developer Telegram Group](https://t.me/joinchat/EaEnSUPktgfoI-XPfMYtcQ)
6. [White Paper](https://github.com/EOSIO/Documentation/blob/master/TechnicalWhitePaper.md)
7. [Roadmap](https://github.com/EOSIO/Documentation/blob/master/Roadmap.md)
8. [Wiki](https://github.com/EOSIO/eos/wiki)
# Table of contents
......@@ -40,6 +41,7 @@ EOS.IO currently supports the following operating systems:
1. [Getting the code](#getcode)
2. [Building from source code](#build)
3. [Creating and launching a single-node testnet](#singlenode)
4. [Next steps](#nextsteps)
4. [Example Currency Contract Walkthrough](#smartcontracts)
1. [Example Contracts](#smartcontractexample)
2. [Setting up a wallet and importing account key](#walletimport)
......@@ -77,7 +79,7 @@ We are working on supporting Centos, Amazon Linux & Red Hat in future releases.
It is called eosio_build.sh
```bash
cd ~/eos
cd eos
./eosio_build.sh
```
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.
......@@ -87,7 +89,7 @@ Choose whether you will be building for a local testnet or for the public testne
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 Linux (Ubuntu & Fedora) for a local testnet
#### :no_entry: Clean install Linux (Ubuntu & Fedora) for a local testnet :no_entry:
```bash
git clone https://github.com/eosio/eos --recursive
......@@ -96,6 +98,12 @@ cd eos
./eosio_build.sh
```
For ease of contract development, one further step is required:
```bash
sudo make install
```
Now you can proceed to the next step - [Creating and launching a single-node testnet](#singlenode)
<a name="autoubuntupublic"></a>
......@@ -105,14 +113,21 @@ Now you can proceed to the next step - [Creating and launching a single-node tes
git clone https://github.com/eosio/eos --recursive
cd eos
git checkout dawn-2.x
git checkout DAWN-2018-01-25
./eosio_build.sh
```
For ease of contract development, one further step is required:
```bash
sudo make install
```
Now you can proceed to the next step - [Running a node on the public testnet](#publictestnet)
<a name="automaclocal"></a>
#### MacOS for a local testnet
#### :no_entry: MacOS for a local testnet :no_entry:
Before running the script make sure you have installed/updated XCode. Note: The build script
will install homebrew if it is not already installed on you system. [Homebrew Website](https://brew.sh)
......@@ -126,6 +141,12 @@ cd eos
./eosio_build.sh
```
For ease of contract development, one further step is required:
```bash
make install
```
Now you can proceed to the next step - [Creating and launching a single-node testnet](#singlenode)
<a name="automacpublic"></a>
......@@ -140,10 +161,17 @@ Then clone the EOS repository recursively, checkout the branch that is compatibl
git clone https://github.com/eosio/eos --recursive
cd eos
git checkout dawn-2.x
git checkout DAWN-2018-01-25
./eosio_build.sh
```
For ease of contract development, one further step is required:
```bash
make install
```
Now you can proceed to the next step - [Running a node on the public testnet](#publictestnet)
<a name="runanode"></a>
......@@ -247,6 +275,10 @@ When running `eosiod` you should get log messages similar to below. It means the
1578001ms thread-0 producer_plugin.cpp:207 block_production_loo ] initc generated block #2 @ 2017-09-04T04:26:18 with 0 trxs 0 pending
...
```
<a name="nextsteps"></a>
### Next Steps
Further documentation is available in the [wiki](https://github.com/EOSIO/eos/wiki). Wiki pages include detailed reference documentation for all programs and tools and the database schema and API. The wiki also includes a section describing smart contract development. A simple walkthrough of the "currency" contract follows.
<a name="smartcontracts"></a>
## Example "Currency" Contract Walkthrough
......@@ -529,7 +561,7 @@ Dependencies:
* Clang 4.0.0
* CMake 3.5.1
* Boost 1.64
* Boost 1.66
* OpenSSL
* LLVM 4.0
* [secp256k1-zkp (Cryptonomex branch)](https://github.com/cryptonomex/secp256k1-zkp.git)
......@@ -550,14 +582,14 @@ sudo apt-get install clang-4.0 lldb-4.0 libclang-4.0-dev cmake make \
autoconf libtool git
```
Install Boost 1.64:
Install Boost 1.66:
```bash
cd ~
wget -c 'https://sourceforge.net/projects/boost/files/boost/1.64.0/boost_1_64_0.tar.bz2/download' -O boost_1.64.0.tar.bz2
tar xjf boost_1.64.0.tar.bz2
cd boost_1_64_0/
echo "export BOOST_ROOT=$HOME/boost_1_64_0" >> ~/.bash_profile
wget -c 'https://sourceforge.net/projects/boost/files/boost/1.64.0/boost_1_66_0.tar.bz2/download' -O boost_1.64.0.tar.bz2
tar xjf boost_1.66.0.tar.bz2
cd boost_1_66_0/
echo "export BOOST_ROOT=$HOME/boost_1_66_0" >> ~/.bash_profile
source ~/.bash_profile
./bootstrap.sh "--prefix=$BOOST_ROOT"
./b2 install
......@@ -687,14 +719,14 @@ cd ..
mkdir build
cd build
cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX=.. -DLLVM_TARGETS_TO_BUILD= -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=WebAssembly -DCMAKE_BUILD_TYPE=Release ../
make -j4 install
make -j$( nproc ) install
```
Add `WASM_LLVM_CONFIG` and `LLVM_DIR` to your `.bash_profile`:
```bash
echo "export WASM_LLVM_CONFIG=~/wasm-compiler/llvm/bin/llvm-config" >> ~/.bash_profile
echo "export LLVM_DIR=/usr/local/Cellar/llvm/4.0.1/lib/cmake/llvm" >> ~/.bash_profile
echo "export LLVM_DIR=/usr/local/Cellar/llvm@4/4.0.1/lib/cmake/llvm/" >> ~/.bash_profile
source ~/.bash_profile
```
......@@ -718,7 +750,7 @@ Install Boost 1.66:
cd ~
curl -L https://dl.bintray.com/boostorg/release/1.66.0/source/boost_1_66_0.tar.bz2 > boost_1.66.0.tar.bz2
tar xf boost_1.66.0.tar.bz2
echo "export BOOST_ROOT=$HOME/boost_1_64_0" >> ~/.bash_profile
echo "export BOOST_ROOT=$HOME/boost_1_66_0" >> ~/.bash_profile
source ~/.bash_profile
cd boost_1_66_0/
./bootstrap.sh "--prefix=$BOOST_ROOT"
......@@ -774,7 +806,7 @@ Add `WASM_LLVM_CONFIG` and `LLVM_DIR` to your `.bash_profile`:
```bash
echo "export WASM_LLVM_CONFIG=~/wasm-compiler/llvm/bin/llvm-config" >> ~/.bash_profile
echo "export LLVM_DIR=/usr/local/Cellar/llvm/4.0.1/lib/cmake/llvm" >> ~/.bash_profile
echo "export LLVM_DIR=~/wasm-compiler/lib/cmake/llvm" >> ~/.bash_profile
source ~/.bash_profile
```
Your environment is set up. Now you can <a href="#runanode">build EOS and run a node</a>.
set(STANDARD_INCLUDE_FOLDERS ${CMAKE_SOURCE_DIR}/contracts ${CMAKE_SOURCE_DIR}/contracts/libc++/upstream/include ${CMAKE_SOURCE_DIR}/contracts/musl/upstream/include)
add_subdirectory(eosiolib)
add_subdirectory(musl)
add_subdirectory(libc++)
add_subdirectory(eosio.system)
add_subdirectory(identity)
add_subdirectory(currency)
add_subdirectory(stltest)
#add_subdirectory(bancor)
#add_subdirectory(eosio.system)
add_subdirectory(asserter)
#add_subdirectory(exchange)
#add_subdirectory(infinite)
add_subdirectory(infinite)
add_subdirectory(proxy)
add_subdirectory(test_api)
#add_subdirectory(simpledb)
#add_subdirectory(storage)
#add_subdirectory(social)
add_subdirectory(test.system)
add_subdirectory(noop)
install( DIRECTORY eosiolib DESTINATION include/ )
......
file(GLOB ABI_FILES "*.abi")
configure_file("${ABI_FILES}" "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY)
add_wast_target(asserter "${CMAKE_SOURCE_DIR}/contracts" ${CMAKE_CURRENT_BINARY_DIR})
add_wast_executable(TARGET asserter
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
LIBRARIES eosiolib
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
......@@ -29,9 +29,9 @@ extern "C" {
}
// maybe assert?
assert(def->condition, def->message);
eos_assert(def->condition, def->message);
} else if( action == N(provereset) ) {
assert(global_variable == 45, "Global Variable Initialized poorly");
eos_assert(global_variable == 45, "Global Variable Initialized poorly");
global_variable = 100;
}
}
......
file(GLOB ABI_FILES "*.abi")
configure_file("${ABI_FILES}" "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY)
add_wast_target(bancor "${CMAKE_SOURCE_DIR}/contracts" ${CMAKE_CURRENT_BINARY_DIR})
add_wast_executable(TARGET bancor
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
LIBRARIES eosiolib
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
......@@ -82,7 +82,7 @@ namespace bancor {
save_and_send( trans.from, state, output, args.min_return );
}
else {
assert( false, "invalid to currency" );
eos_assert( false, "invalid to currency" );
}
}
......@@ -118,7 +118,7 @@ namespace bancor {
template<typename CurrencyType>
static void start_convert( const typename CurrencyType::transfer_memo& trans ) {
auto args = unpack<converter_args>( trans.memo );
assert( args.to_currency_type != trans.quantity.token_type(), "cannot convert to self" );
eos_assert( args.to_currency_type != trans.quantity.token_type(), "cannot convert to self" );
auto state = read_converter_state();
on_convert( trans, args, state );
......@@ -148,7 +148,7 @@ namespace bancor {
if( trans.to == converter_account ) {
start_convert( trans );
} else {
assert( trans.from == converter_account,
eos_assert( trans.from == converter_account,
"received unexpected notification of transfer" );
}
}
......@@ -159,7 +159,7 @@ namespace bancor {
converter_currency::issue,
first_currency::transfer,
second_currency::transfer ) {
assert( false, "received unexpected action" );
eos_assert( false, "received unexpected action" );
}
}
}; /// converter_contract
......
file(GLOB ABI_FILES "*.abi")
configure_file("${ABI_FILES}" "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY)
add_wast_target(currency "${CMAKE_SOURCE_DIR}/contracts" ${CMAKE_CURRENT_BINARY_DIR})
add_wast_executable(TARGET currency
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
LIBRARIES eosiolib
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
......@@ -6,8 +6,8 @@
namespace dice {
void apply_offer( const offer_bet& offer ) {
assert( offer.amount > 0, "insufficient bet" );
assert( !hasOffer( offer.commitment ), "offer with this commitment already exist" );
eos_assert( offer.amount > 0, "insufficient bet" );
eos_assert( !hasOffer( offer.commitment ), "offer with this commitment already exist" );
require_auth( offer.player );
auto acnt = get_account( offer.player );
......
file(GLOB ABI_FILES "*.abi")
configure_file("${ABI_FILES}" "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY)
add_wast_target(eosio.system "${CMAKE_SOURCE_DIR}/contracts" ${CMAKE_CURRENT_BINARY_DIR})
add_wast_executable(TARGET eosio.system
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
LIBRARIES eosiolib
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
{
"types": [{
"new_type_name": "account_name",
"type": "name"
}
],
"types": [],
"structs": [{
"name": "transfer",
"base": "",
......
......@@ -11,6 +11,6 @@ extern "C" {
/// The apply method implements the dispatch of events to this contract
void apply( uint64_t code, uint64_t act ) {
eosiosystem::contract<N(eosio.system)>::apply( code, act );
eosiosystem::contract<N(eosio)>::apply( code, act );
}
}
......@@ -17,7 +17,7 @@ namespace eosiosystem {
template<account_name SystemAccount>
class contract {
public:
static const account_name system_account = N(eosio.system);
static const account_name system_account = SystemAccount;
typedef eosio::generic_currency< eosio::token<system_account,S(4,EOS)> > currency;
struct total_bandwidth {
......@@ -103,8 +103,8 @@ namespace eosiosystem {
static void apply( account_name code, action_name act ) {
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");
eosio::print("Unexpected action: ", eosio::name(act), "\n");
eos_assert( false, "received unexpected action");
}
}
} /// apply
......
add_wast_library(TARGET eosiolib
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
......@@ -61,8 +61,8 @@ extern "C" {
* account_name code = current_receiver();
* print(Name(code)); // Output: eos
*
* assert(Name(current_receiver()) === "eos", "This action expects to be received by eos"); // Do nothing
* assert(Name(current_receiver()) === "inita", "This action expects to be received by inita"); // Throws exception and roll back transfer transaction
* eos_assert(Name(current_receiver()) === "eos", "This action expects to be received by eos"); // Do nothing
* eos_assert(Name(current_receiver()) === "inita", "This action expects to be received by inita"); // Throws exception and roll back transfer transaction
*
* print(now()); // Output: timestamp of last accepted block
*
......
......@@ -40,7 +40,7 @@ namespace eosio {
T current_action() {
T value;
auto read = read_action( &value, sizeof(value) );
assert( read >= sizeof(value), "action shorter than expected" );
eos_assert( read >= sizeof(value), "action shorter than expected" );
return value;
}
......
......@@ -51,7 +51,7 @@
if( action == N(transfer) )
currency::apply_currency_transfer( current_action< currency::transfer >() );
} else {
assert( false, "rejecting unexpected event" );
eos_assert( false, "rejecting unexpected event" );
}
}
}
......
......@@ -10,14 +10,14 @@ extern "C" {
*
* checksum calc_hash;
* sha256( data, length, &calc_hash );
* assert( calc_hash == hash, "invalid hash" );
* eos_assert( calc_hash == hash, "invalid hash" );
*
* This method is optimized to a NO-OP when in fast evaluation mode
*/
void assert_sha256( char* data, uint32_t length, const checksum* hash );
void eos_assert_sha256( char* data, uint32_t length, const checksum* hash );
/**
* Calculates sha256( data,length) and stores result in memory pointed to by hash
*/
void sha256( char* data, uint32_t length, checksum* hash );
}
\ No newline at end of file
}
......@@ -33,7 +33,7 @@ class datastream {
* @param s the number of bytes to read
*/
inline bool read( char* d, size_t s ) {
assert( size_t(_end - _pos) >= (size_t)s, "read" );
eos_assert( size_t(_end - _pos) >= (size_t)s, "read" );
memcpy( d, _pos, s );
_pos += s;
return true;
......@@ -46,7 +46,7 @@ class datastream {
* @param s The number of bytes to write
*/
inline bool write( const char* d, size_t s ) {
assert( _end - _pos >= (int32_t)s, "write" );
eos_assert( _end - _pos >= (int32_t)s, "write" );
memcpy( _pos, d, s );
_pos += s;
return true;
......@@ -58,7 +58,7 @@ class datastream {
* @param c byte to write
*/
inline bool put(char c) {
assert( _pos < _end, "put" );
eos_assert( _pos < _end, "put" );
*_pos = c;
++_pos;
return true;
......@@ -72,7 +72,7 @@ class datastream {
inline bool get( unsigned char& c ) { return get( *(char*)&c ); }
inline bool get( char& c )
{
assert( _pos < _end, "get" );
eos_assert( _pos < _end, "get" );
c = *_pos;
++_pos;
return true;
......@@ -428,5 +428,3 @@ bytes pack( const T& value ) {
}
......@@ -388,7 +388,7 @@ struct table {
* @return true if successful store.
*/
static bool store( const Record& r, uint64_t s = scope, uint64_t b = bta ) {
assert( impl::store( s, table_n, b, &r, sizeof(r) ), "error storing record" );
eos_assert( impl::store( s, table_n, b, &r, sizeof(r) ), "error storing record" );
return true;
}
......@@ -401,7 +401,7 @@ struct table {
* @return true if successful update.
*/
static bool update( const Record& r, uint64_t s = scope, uint64_t b = bta ) {
assert( impl::update( s, table_n, b, &r, sizeof(r) ), "error updating record" );
eos_assert( impl::update( s, table_n, b, &r, sizeof(r) ), "error updating record" );
return true;
}
......
#include "memory.hpp"
namespace eosio {
using ::memset;
using ::memcpy;
/**
* @defgroup memorycppapi Memory C++ API
* @brief Defines common memory functions
* @ingroup memoryapi
*
* @{
*/
class memory_manager // NOTE: Should never allocate another instance of memory_manager
{
friend void* ::malloc(size_t size);
friend void* ::calloc(size_t count, size_t size);
friend void* ::realloc(void* ptr, size_t size);
friend void ::free(void* ptr);
public:
memory_manager()
// NOTE: it appears that WASM has an issue with initialization lists if the object is globally allocated,
// and seems to just initialize members to 0
: _heaps_actual_size(0)
, _active_heap(0)
, _active_free_heap(0)
{
}
private:
class memory;
memory* next_active_heap()
{
memory* const current_memory = _available_heaps + _active_heap;
// make sure we will not exceed the 1M limit (needs to match wasm_interface.cpp _max_memory)
auto remaining = 1024 * 1024 - reinterpret_cast<int32_t>(sbrk(0));
if (remaining <= 0)
{
// ensure that any remaining unallocated memory gets cleaned up
current_memory->cleanup_remaining();
++_active_heap;
_heaps_actual_size = _active_heap;
return nullptr;
}
const uint32_t new_heap_size = remaining > _new_heap_size ? _new_heap_size : remaining;
char* new_memory_start = static_cast<char*>(sbrk(new_heap_size));
// if we can expand the current memory, keep working with it
if (current_memory->expand_memory(new_memory_start, new_heap_size))
return current_memory;
// ensure that any remaining unallocated memory gets cleaned up
current_memory->cleanup_remaining();
++_active_heap;
memory* const next = _available_heaps + _active_heap;
next->init(new_memory_start, new_heap_size);
return next;
}
void* malloc(uint32_t size)
{
if (size == 0)
return nullptr;
// see Note on ctor
if (_heaps_actual_size == 0)
_heaps_actual_size = _heaps_size;
adjust_to_mem_block(size);
// first pass of loop never has to initialize the slot in _available_heap
uint32_t needs_init = 0;
char* buffer = nullptr;
memory* current = nullptr;
// need to make sure
if (_active_heap < _heaps_actual_size)
{
memory* const start_heap = &_available_heaps[_active_heap];
// only heap 0 won't be initialized already
if(_active_heap == 0 && !start_heap->is_init())
{
start_heap->init(_initial_heap, _initial_heap_size);
}
current = start_heap;
}
while (current != nullptr)
{
buffer = current->malloc(size);
// done if we have a buffer
if (buffer != nullptr)
break;
current = next_active_heap();
}
if (buffer == nullptr)
{
const uint32_t end_free_heap = _active_free_heap;
do
{
buffer = _available_heaps[_active_free_heap].malloc_from_freed(size);
if (buffer != nullptr)
break;
if (++_active_free_heap == _heaps_actual_size)
_active_free_heap = 0;
} while (_active_free_heap != end_free_heap);
}
return buffer;
}
void* realloc(void* ptr, uint32_t size)
{
if (size == 0)
{
free(ptr);
return nullptr;
}
const uint32_t REMOVE = size;
adjust_to_mem_block(size);
char* realloc_ptr = nullptr;
uint32_t orig_ptr_size = 0;
if (ptr != nullptr)
{
char* const char_ptr = static_cast<char*>(ptr);
for (memory* realloc_heap = _available_heaps; realloc_heap < _available_heaps + _heaps_actual_size && realloc_heap->is_init(); ++realloc_heap)
{
if (realloc_heap->is_in_heap(char_ptr))
{
realloc_ptr = realloc_heap->realloc_in_place(char_ptr, size, &orig_ptr_size);
if (realloc_ptr != nullptr)
return realloc_ptr;
else
break;
}
}
}
char* new_alloc = static_cast<char*>(malloc(size));
if (new_alloc == nullptr)
return nullptr;
const uint32_t copy_size = (size < orig_ptr_size) ? size : orig_ptr_size;
if (copy_size > 0)
{
memcpy(new_alloc, ptr, copy_size);
free (ptr);
}
return new_alloc;
}
void free(void* ptr)
{
if (ptr == nullptr)
return;
char* const char_ptr = static_cast<char*>(ptr);
for (memory* free_heap = _available_heaps; free_heap < _available_heaps + _heaps_actual_size && free_heap->is_init(); ++free_heap)
{
if (free_heap->is_in_heap(char_ptr))
{
free_heap->free(char_ptr);
break;
}
}
}
void adjust_to_mem_block(uint32_t& size)
{
const uint32_t remainder = (size + _size_marker) & _rem_mem_block_mask;
if (remainder > 0)
{
size += _mem_block - remainder;
}
}
class memory
{
public:
memory()
: _heap_size(0)
, _heap(nullptr)
, _offset(0)
{
}
void init(char* const mem_heap, uint32_t size)
{
_heap_size = size;
_heap = mem_heap;
memset(_heap, 0, _heap_size);
}
uint32_t is_init() const
{
return _heap != nullptr;
}
uint32_t is_in_heap(const char* const ptr) const
{
const char* const end_of_buffer = _heap + _heap_size;
const char* const first_ptr_of_buffer = _heap + _size_marker;
return ptr >= first_ptr_of_buffer && ptr < end_of_buffer;
}
uint32_t is_capacity_remaining() const
{
return _offset + _size_marker < _heap_size;
}
char* malloc(uint32_t size)
{
uint32_t used_up_size = _offset + size + _size_marker;
if (used_up_size > _heap_size)
{
return nullptr;
}
buffer_ptr new_buff(&_heap[_offset + _size_marker], size, _heap + _heap_size);
_offset += size + _size_marker;
new_buff.mark_alloc();
return new_buff.ptr();
}
char* malloc_from_freed(uint32_t size)
{
eos_assert(_offset == _heap_size, "malloc_from_freed was designed to only be called after _heap was completely allocated");
char* current = _heap + _size_marker;
while (current != nullptr)
{
buffer_ptr current_buffer(current, _heap + _heap_size);
if (!current_buffer.is_alloc())
{
// done if we have enough contiguous memory
if (current_buffer.merge_contiguous(size))
{
current_buffer.mark_alloc();
return current;
}
}
current = current_buffer.next_ptr();
}
// failed to find any free memory
return nullptr;
}
char* realloc_in_place(char* const ptr, uint32_t size, uint32_t* orig_ptr_size)
{
const char* const end_of_buffer = _heap + _heap_size;
buffer_ptr orig_buffer(ptr, end_of_buffer);
*orig_ptr_size = orig_buffer.size();
// is the passed in pointer valid
char* const orig_buffer_end = orig_buffer.end();
if (orig_buffer_end > end_of_buffer)
{
*orig_ptr_size = 0;
return nullptr;
}
if (ptr > end_of_buffer - size)
{
// cannot resize in place
return nullptr;
}
const int32_t diff = size - *orig_ptr_size;
if (diff < 0)
{
// use a buffer_ptr to allocate the memory to free
char* const new_ptr = ptr + size + _size_marker;
buffer_ptr excess_to_free(new_ptr, -diff, _heap + _heap_size);
excess_to_free.mark_free();
return ptr;
}
// if ptr was the last allocated buffer, we can expand
else if (orig_buffer_end == &_heap[_offset])
{
orig_buffer.size(size);
_offset += diff;
return ptr;
}
if (-diff == 0)
return ptr;
if (!orig_buffer.merge_contiguous_if_available(size))
// could not resize in place
return nullptr;
orig_buffer.mark_alloc();
return ptr;
}
void free(char* ptr)
{
buffer_ptr to_free(ptr, _heap + _heap_size);
to_free.mark_free();
}
void cleanup_remaining()
{
if (_offset == _heap_size)
return;
// take the remaining memory and act like it was allocated
const uint32_t size = _heap_size - _offset - _size_marker;
buffer_ptr new_buff(&_heap[_offset + _size_marker], size, _heap + _heap_size);
_offset = _heap_size;
new_buff.mark_free();
}
bool expand_memory(char* exp_mem, uint32_t size)
{
if (_heap + _heap_size != exp_mem)
return false;
_heap_size += size;
return true;
}
private:
class buffer_ptr
{
public:
buffer_ptr(void* ptr, const char* const heap_end)
: _ptr(static_cast<char*>(ptr))
, _size(*reinterpret_cast<uint32_t*>(static_cast<char*>(ptr) - _size_marker) & ~_alloc_memory_mask)
, _heap_end(heap_end)
{
}
buffer_ptr(void* ptr, uint32_t buff_size, const char* const heap_end)
: _ptr(static_cast<char*>(ptr))
, _heap_end(heap_end)
{
size(buff_size);
}
uint32_t size() const
{
return _size;
}
char* next_ptr() const
{
char* const next = end() + _size_marker;
if (next >= _heap_end)
return nullptr;
return next;
}
void size(uint32_t val)
{
// keep the same state (allocated or free) as was set before
const uint32_t memory_state = *reinterpret_cast<uint32_t*>(_ptr - _size_marker) & _alloc_memory_mask;
*reinterpret_cast<uint32_t*>(_ptr - _size_marker) = val | memory_state;
_size = val;
}
char* end() const
{
return _ptr + _size;
}
char* ptr() const
{
return _ptr;
}
void mark_alloc()
{
*reinterpret_cast<uint32_t*>(_ptr - _size_marker) |= _alloc_memory_mask;
}
void mark_free()
{
*reinterpret_cast<uint32_t*>(_ptr - _size_marker) &= ~_alloc_memory_mask;
}
bool is_alloc() const
{
return *reinterpret_cast<const uint32_t*>(_ptr - _size_marker) & _alloc_memory_mask;
}
bool merge_contiguous_if_available(uint32_t needed_size)
{
return merge_contiguous(needed_size, true);
}
bool merge_contiguous(uint32_t needed_size)
{
return merge_contiguous(needed_size, false);
}
private:
bool merge_contiguous(uint32_t needed_size, bool all_or_nothing)
{
// do not bother if there isn't contiguious space to allocate
if (all_or_nothing && _heap_end - _ptr < needed_size)
return false;
uint32_t possible_size = _size;
while (possible_size < needed_size && (_ptr + possible_size < _heap_end))
{
const uint32_t next_mem_flag_size = *reinterpret_cast<const uint32_t*>(_ptr + possible_size);
// if ALLOCed then done with contiguous free memory
if (next_mem_flag_size & _alloc_memory_mask)
break;
possible_size += (next_mem_flag_size & ~_alloc_memory_mask) + _size_marker;
}
if (all_or_nothing && possible_size < needed_size)
return false;
// combine
const uint32_t new_size = possible_size < needed_size ? possible_size : needed_size;
size(new_size);
if (possible_size > needed_size)
{
const uint32_t freed_size = possible_size - needed_size - _size_marker;
buffer_ptr freed_remainder(_ptr + needed_size + _size_marker, freed_size, _heap_end);
freed_remainder.mark_free();
}
return new_size == needed_size;
}
char* _ptr;
uint32_t _size;
const char* const _heap_end;
};
uint32_t _heap_size;
char* _heap;
uint32_t _offset;
};
static const uint32_t _size_marker = sizeof(uint32_t);
// allocate memory in 8 char blocks
static const uint32_t _mem_block = 8;
static const uint32_t _rem_mem_block_mask = _mem_block - 1;
static const uint32_t _initial_heap_size = 8192;//32768;
static const uint32_t _new_heap_size = 65536;
// if sbrk is not called outside of this file, then this is the max times we can call it
static const uint32_t _heaps_size = 16;
char _initial_heap[_initial_heap_size];
memory _available_heaps[_heaps_size];
uint32_t _heaps_actual_size;
uint32_t _active_heap;
uint32_t _active_free_heap;
static const uint32_t _alloc_memory_mask = 1 << 31;
};
memory_manager memory_heap;
}
extern "C" {
void* __dso_handle = 0;
void* malloc(size_t size)
{
return eosio::memory_heap.malloc(size);
}
void* calloc(size_t count, size_t size)
{
return eosio::memory_heap.malloc(count*size);
}
void* realloc(void* ptr, size_t size)
{
return eosio::memory_heap.realloc(ptr, size);
}
void free(void* ptr)
{
return eosio::memory_heap.free(ptr);
}
}
......@@ -41,7 +41,7 @@ namespace eosio {
template<typename DataStream>
friend DataStream& operator >> ( DataStream& ds, transfer& t ){
ds >> t.from >> t.to >> t.quantity;
assert( t.quantity.symbol== token_type::symbol, "unexpected asset type" );
eos_assert( t.quantity.symbol== token_type::symbol, "unexpected asset type" );
return ds;
}
};
......
......@@ -34,4 +34,4 @@ Welcome to the EOS.IO Documentation
- @ref transactionapi - Define API for sending transactions and inline messages
- @ref types - Specifies typedefs and aliases
\ No newline at end of file
......@@ -102,7 +102,7 @@ namespace eosio {
}
explicit operator uint64_t()const {
assert( !(value >> 64), "cast to 64 bit loss of precision" );
eos_assert( !(value >> 64), "cast to 64 bit loss of precision" );
return uint64_t(value);
}
......
......@@ -4,89 +4,5 @@
*/
#pragma once
#include <string.h>
#include <eosiolib/types.h>
/**
* @defgroup memoryapi Memory API
* @brief Defines common memory functions
* @ingroup contractdev
*/
extern "C" {
/**
* @defgroup memorycapi Memory C API
* @brief Defines common memory functions
* @ingroup memoryapi
*
* @{
*/
/**
* Allocate page(s) of memory to accommodate the
* requested number of bytes.
* @brief Allocate page memory
* @param num_bytes Number of bytes to add.
*
* @return void pointer to the previous end of allocated bytes
*
* Example:
* @code
* // allocate a whole new page, the returned offset is the pointer to the
* // newly allocated page
* char* new_page = static_cast<char*>(sbrk(65536));
* memset(new_page, 0, 65536);
* @endcode
*/
void* sbrk( uint32_t num_bytes );
/**
* Copy a block of memory from source to destination.
* @brief Copy a block of memory from source to destination.
* @param destination Pointer to the destination to copy to.
* @param source Pointer to the source for copy from.
* @param num Number of bytes to copy.
*
* @return the destination pointer
*
* Example:
* @code
* char dest[6] = { 0 };
* char source[6] = { 'H', 'e', 'l', 'l', 'o', '\0' };
* memcpy(dest, source, 6 * sizeof(char));
* prints(dest); // Output: Hello
* @endcode
*/
void* memcpy( void* destination, const void* source, uint32_t num );
/**
* Compare block of memory from source to destination.
* @brief Copy a block of memory from source to destination.
* @param ptr1 Pointer to first data to compare
* @param ptr2 Pointer to second data to compare
* @param num Number of bytes to compare.
*
* @return the destination pointer
*
*/
int32_t memcmp( void* ptr1, const void* ptr2, uint32_t num );
/**
* Fill block of memory.
* @brief Fill a block of memory with the provided value.
* @param ptr Pointer to memory to fill.
* @param value Value to set (it is passed as an int but converted to unsigned char).
* @param num Number of bytes to be set to the value.
*
* @return the destination pointer
*
* Example:
* @code
* char ptr[6] = { 'H', 'e', 'l', 'l', 'o', '\0' };
* memset(ptr, 'y', 6 * sizeof(char));
* prints(ptr); // Output: yyyyyy
* @endcode
*/
void* memset( void* ptr, uint32_t value, uint32_t num );
/// @}
} // extern "C"
......@@ -7,528 +7,16 @@
#include <eosiolib/memory.h>
#include <eosiolib/print.hpp>
namespace eosio {
#include <unistd.h>
using ::memset;
using ::memcpy;
extern "C" {
/**
* @defgroup memorycppapi Memory C++ API
* @brief Defines common memory functions
* @ingroup memoryapi
*
* @{
*/
void* malloc(size_t size);
class memory_manager // NOTE: Should never allocate another instance of memory_manager
{
friend void* malloc(uint32_t size);
friend void* realloc(void* ptr, uint32_t size);
friend void free(void* ptr);
public:
memory_manager()
// NOTE: it appears that WASM has an issue with initialization lists if the object is globally allocated,
// and seems to just initialize members to 0
: _heaps_actual_size(0)
, _active_heap(0)
, _active_free_heap(0)
{
}
void* calloc(size_t count, size_t size);
private:
class memory;
void* realloc(void* ptr, size_t size);
memory* next_active_heap()
{
memory* const current_memory = _available_heaps + _active_heap;
void free(void* ptr);
// make sure we will not exceed the 1M limit (needs to match wasm_interface.cpp _max_memory)
auto remaining = 1024 * 1024 - reinterpret_cast<int32_t>(sbrk(0));
if (remaining <= 0)
{
// ensure that any remaining unallocated memory gets cleaned up
current_memory->cleanup_remaining();
++_active_heap;
_heaps_actual_size = _active_heap;
return nullptr;
}
const uint32_t new_heap_size = remaining > _new_heap_size ? _new_heap_size : remaining;
char* new_memory_start = static_cast<char*>(sbrk(new_heap_size));
// if we can expand the current memory, keep working with it
if (current_memory->expand_memory(new_memory_start, new_heap_size))
return current_memory;
// ensure that any remaining unallocated memory gets cleaned up
current_memory->cleanup_remaining();
++_active_heap;
memory* const next = _available_heaps + _active_heap;
next->init(new_memory_start, new_heap_size);
return next;
}
void* malloc(uint32_t size)
{
if (size == 0)
return nullptr;
// see Note on ctor
if (_heaps_actual_size == 0)
_heaps_actual_size = _heaps_size;
adjust_to_mem_block(size);
// first pass of loop never has to initialize the slot in _available_heap
uint32_t needs_init = 0;
char* buffer = nullptr;
memory* current = nullptr;
// need to make sure
if (_active_heap < _heaps_actual_size)
{
memory* const start_heap = &_available_heaps[_active_heap];
// only heap 0 won't be initialized already
if(_active_heap == 0 && !start_heap->is_init())
{
start_heap->init(_initial_heap, _initial_heap_size);
}
current = start_heap;
}
while (current != nullptr)
{
buffer = current->malloc(size);
// done if we have a buffer
if (buffer != nullptr)
break;
current = next_active_heap();
}
if (buffer == nullptr)
{
const uint32_t end_free_heap = _active_free_heap;
do
{
buffer = _available_heaps[_active_free_heap].malloc_from_freed(size);
if (buffer != nullptr)
break;
if (++_active_free_heap == _heaps_actual_size)
_active_free_heap = 0;
} while (_active_free_heap != end_free_heap);
}
return buffer;
}
void* realloc(void* ptr, uint32_t size)
{
if (size == 0)
{
free(ptr);
return nullptr;
}
const uint32_t REMOVE = size;
adjust_to_mem_block(size);
char* realloc_ptr = nullptr;
uint32_t orig_ptr_size = 0;
if (ptr != nullptr)
{
char* const char_ptr = static_cast<char*>(ptr);
for (memory* realloc_heap = _available_heaps; realloc_heap < _available_heaps + _heaps_actual_size && realloc_heap->is_init(); ++realloc_heap)
{
if (realloc_heap->is_in_heap(char_ptr))
{
realloc_ptr = realloc_heap->realloc_in_place(char_ptr, size, &orig_ptr_size);
if (realloc_ptr != nullptr)
return realloc_ptr;
else
break;
}
}
}
char* new_alloc = static_cast<char*>(malloc(size));
if (new_alloc == nullptr)
return nullptr;
const uint32_t copy_size = (size < orig_ptr_size) ? size : orig_ptr_size;
if (copy_size > 0)
{
memcpy(new_alloc, ptr, copy_size);
free (ptr);
}
return new_alloc;
}
void free(void* ptr)
{
if (ptr == nullptr)
return;
char* const char_ptr = static_cast<char*>(ptr);
for (memory* free_heap = _available_heaps; free_heap < _available_heaps + _heaps_actual_size && free_heap->is_init(); ++free_heap)
{
if (free_heap->is_in_heap(char_ptr))
{
free_heap->free(char_ptr);
break;
}
}
}
void adjust_to_mem_block(uint32_t& size)
{
const uint32_t remainder = (size + _size_marker) & _rem_mem_block_mask;
if (remainder > 0)
{
size += _mem_block - remainder;
}
}
class memory
{
public:
memory()
: _heap_size(0)
, _heap(nullptr)
, _offset(0)
{
}
void init(char* const mem_heap, uint32_t size)
{
_heap_size = size;
_heap = mem_heap;
memset(_heap, 0, _heap_size);
}
uint32_t is_init() const
{
return _heap != nullptr;
}
uint32_t is_in_heap(const char* const ptr) const
{
const char* const end_of_buffer = _heap + _heap_size;
const char* const first_ptr_of_buffer = _heap + _size_marker;
return ptr >= first_ptr_of_buffer && ptr < end_of_buffer;
}
uint32_t is_capacity_remaining() const
{
return _offset + _size_marker < _heap_size;
}
char* malloc(uint32_t size)
{
uint32_t used_up_size = _offset + size + _size_marker;
if (used_up_size > _heap_size)
{
return nullptr;
}
buffer_ptr new_buff(&_heap[_offset + _size_marker], size, _heap + _heap_size);
_offset += size + _size_marker;
new_buff.mark_alloc();
return new_buff.ptr();
}
char* malloc_from_freed(uint32_t size)
{
assert(_offset == _heap_size, "malloc_from_freed was designed to only be called after _heap was completely allocated");
char* current = _heap + _size_marker;
while (current != nullptr)
{
buffer_ptr current_buffer(current, _heap + _heap_size);
if (!current_buffer.is_alloc())
{
// done if we have enough contiguous memory
if (current_buffer.merge_contiguous(size))
{
current_buffer.mark_alloc();
return current;
}
}
current = current_buffer.next_ptr();
}
// failed to find any free memory
return nullptr;
}
char* realloc_in_place(char* const ptr, uint32_t size, uint32_t* orig_ptr_size)
{
const char* const end_of_buffer = _heap + _heap_size;
buffer_ptr orig_buffer(ptr, end_of_buffer);
*orig_ptr_size = orig_buffer.size();
// is the passed in pointer valid
char* const orig_buffer_end = orig_buffer.end();
if (orig_buffer_end > end_of_buffer)
{
*orig_ptr_size = 0;
return nullptr;
}
if (ptr > end_of_buffer - size)
{
// cannot resize in place
return nullptr;
}
const int32_t diff = size - *orig_ptr_size;
if (diff < 0)
{
// use a buffer_ptr to allocate the memory to free
char* const new_ptr = ptr + size + _size_marker;
buffer_ptr excess_to_free(new_ptr, -diff, _heap + _heap_size);
excess_to_free.mark_free();
return ptr;
}
// if ptr was the last allocated buffer, we can expand
else if (orig_buffer_end == &_heap[_offset])
{
orig_buffer.size(size);
_offset += diff;
return ptr;
}
if (-diff == 0)
return ptr;
if (!orig_buffer.merge_contiguous_if_available(size))
// could not resize in place
return nullptr;
orig_buffer.mark_alloc();
return ptr;
}
void free(char* ptr)
{
buffer_ptr to_free(ptr, _heap + _heap_size);
to_free.mark_free();
}
void cleanup_remaining()
{
if (_offset == _heap_size)
return;
// take the remaining memory and act like it was allocated
const uint32_t size = _heap_size - _offset - _size_marker;
buffer_ptr new_buff(&_heap[_offset + _size_marker], size, _heap + _heap_size);
_offset = _heap_size;
new_buff.mark_free();
}
bool expand_memory(char* exp_mem, uint32_t size)
{
if (_heap + _heap_size != exp_mem)
return false;
_heap_size += size;
return true;
}
private:
class buffer_ptr
{
public:
buffer_ptr(void* ptr, const char* const heap_end)
: _ptr(static_cast<char*>(ptr))
, _size(*reinterpret_cast<uint32_t*>(static_cast<char*>(ptr) - _size_marker) & ~_alloc_memory_mask)
, _heap_end(heap_end)
{
}
buffer_ptr(void* ptr, uint32_t buff_size, const char* const heap_end)
: _ptr(static_cast<char*>(ptr))
, _heap_end(heap_end)
{
size(buff_size);
}
uint32_t size() const
{
return _size;
}
char* next_ptr() const
{
char* const next = end() + _size_marker;
if (next >= _heap_end)
return nullptr;
return next;
}
void size(uint32_t val)
{
// keep the same state (allocated or free) as was set before
const uint32_t memory_state = *reinterpret_cast<uint32_t*>(_ptr - _size_marker) & _alloc_memory_mask;
*reinterpret_cast<uint32_t*>(_ptr - _size_marker) = val | memory_state;
_size = val;
}
char* end() const
{
return _ptr + _size;
}
char* ptr() const
{
return _ptr;
}
void mark_alloc()
{
*reinterpret_cast<uint32_t*>(_ptr - _size_marker) |= _alloc_memory_mask;
}
void mark_free()
{
*reinterpret_cast<uint32_t*>(_ptr - _size_marker) &= ~_alloc_memory_mask;
}
bool is_alloc() const
{
return *reinterpret_cast<const uint32_t*>(_ptr - _size_marker) & _alloc_memory_mask;
}
bool merge_contiguous_if_available(uint32_t needed_size)
{
return merge_contiguous(needed_size, true);
}
bool merge_contiguous(uint32_t needed_size)
{
return merge_contiguous(needed_size, false);
}
private:
bool merge_contiguous(uint32_t needed_size, bool all_or_nothing)
{
// do not bother if there isn't contiguious space to allocate
if (all_or_nothing && _heap_end - _ptr < needed_size)
return false;
uint32_t possible_size = _size;
while (possible_size < needed_size && (_ptr + possible_size < _heap_end))
{
const uint32_t next_mem_flag_size = *reinterpret_cast<const uint32_t*>(_ptr + possible_size);
// if ALLOCed then done with contiguous free memory
if (next_mem_flag_size & _alloc_memory_mask)
break;
possible_size += (next_mem_flag_size & ~_alloc_memory_mask) + _size_marker;
}
if (all_or_nothing && possible_size < needed_size)
return false;
// combine
const uint32_t new_size = possible_size < needed_size ? possible_size : needed_size;
size(new_size);
if (possible_size > needed_size)
{
const uint32_t freed_size = possible_size - needed_size - _size_marker;
buffer_ptr freed_remainder(_ptr + needed_size + _size_marker, freed_size, _heap_end);
freed_remainder.mark_free();
}
return new_size == needed_size;
}
char* _ptr;
uint32_t _size;
const char* const _heap_end;
};
uint32_t _heap_size;
char* _heap;
uint32_t _offset;
};
static const uint32_t _size_marker = sizeof(uint32_t);
// allocate memory in 8 char blocks
static const uint32_t _mem_block = 8;
static const uint32_t _rem_mem_block_mask = _mem_block - 1;
static const uint32_t _initial_heap_size = 8192;//32768;
static const uint32_t _new_heap_size = 65536;
// if sbrk is not called outside of this file, then this is the max times we can call it
static const uint32_t _heaps_size = 16;
char _initial_heap[_initial_heap_size];
memory _available_heaps[_heaps_size];
uint32_t _heaps_actual_size;
uint32_t _active_heap;
uint32_t _active_free_heap;
static const uint32_t _alloc_memory_mask = 1 << 31;
} memory_heap;
/**
* Allocate a block of memory.
* @brief Allocate a block of memory.
* @param size Size of memory block
*
* Example:
* @code
* uint64_t* int_buffer = malloc(500 * sizeof(uint64_t));
* @endcode
*/
inline void* malloc(uint32_t size)
{
return memory_heap.malloc(size);
}
/**
* Allocate a block of memory.
* @brief Allocate a block of memory.
* @param size Size of memory block
*
* Example:
* @code
* uint64_t* int_buffer = malloc(500 * sizeof(uint64_t));
* ...
* uint64_t* bigger_int_buffer = realloc(int_buffer, 600 * sizeof(uint64_t));
* @endcode
*/
inline void* realloc(void* ptr, uint32_t size)
{
return memory_heap.realloc(ptr, size);
}
/**
* Free a block of memory.
* @brief Free a block of memory.
* @param ptr Pointer to memory block to free.
*
* Example:
* @code
* uint64_t* int_buffer = malloc(500 * sizeof(uint64_t));
* ...
* free(int_buffer);
* @endcode
*/
inline void free(void* ptr)
{
return memory_heap.free(ptr);
}
/// @} /// mathcppapi
}
......@@ -4,7 +4,11 @@
*/
#pragma once
#include <eosiolib/types.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup consoleapi Console API
* @brief Enables applications to log/print text messages
......@@ -98,4 +102,6 @@ extern "C" {
*/
void printhex( void* data, uint32_t datalen );
/// @}
#ifdef __cplusplus
}
#endif
......@@ -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) );
assert( read > 0, "singleton does not exist" );
datastream<const char*> ds(temp + sizeof(SingletonName), read);
auto read = load_i64( Code, scope, SingletonName, temp, sizeof(temp) );
eos_assert( read > 0, "singleton does not exist" );
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,23 +46,19 @@ 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, account_name b = BillToAccount ) {
auto size = pack_size( value );
char buf[size+ sizeof(SingletonName)];
assert( sizeof(buf) <= 1024 + 8, "singleton too big to store" );
eos_assert( sizeof(buf) <= 1024 + 8, "singleton too big to store" );
datastream<char*> ds( buf, size + sizeof(SingletonName) );
ds << SingletonName;
......@@ -64,6 +66,11 @@ namespace eosio {
store_i64( scope, SingletonName, b, buf, sizeof(buf) );
}
static void remove( scope_name scope = Code ) {
uint64_t key = SingletonName;
remove_i64( scope, SingletonName, &key );
}
};
} /// namespace eosio
#pragma once
// forward declarations, to be filled in by the compiler, for placement new.
extern "C" {
void* operator new(size_t, void*);
void* operator new[](size_t, void*);
}
// compatibility for things declared by the c++ standard libraries that compilers replace
namespace std {
// forward declaration of initializer_list
template<class E> class initializer_list {
public:
using value_type = E;
using reference = const E&;
using const_reference = const E&;
using size_type = size_t;
using iterator = const E*;
using const_iterator = const E*;
constexpr initializer_list() noexcept;
constexpr size_t size() const noexcept {
return _len;
}
constexpr const E* begin() const noexcept {
return _iter;
}
constexpr const E* end() const noexcept {
return _iter + _len;
}
private:
iterator _iter;
size_type _len;
constexpr initializer_list(const_iterator array, size_type len)
:_iter(array),_len(len)
{}
};
// initializer list range access
template<class E> constexpr const E* begin(initializer_list<E> il) noexcept;
template<class E> constexpr const E* end(initializer_list<E> il) noexcept;
}
\ No newline at end of file
#include <initializer_list>
#include <iterator>
#include <memory>
......@@ -4,6 +4,7 @@
#include <eosiolib/system.h>
#include <eosiolib/memory.hpp>
#include <eosiolib/print.hpp>
#include <eosiolib/varint.hpp>
namespace eosio {
/**
......@@ -197,12 +198,12 @@ namespace eosio {
* @return substring of the current string
*/
string substr(size_t offset, size_t substr_size, bool copy) {
assert((offset < size) && (offset + substr_size < size), "out of bound");
eos_assert((offset < size) && (offset + substr_size < size), "out of bound");
return string(data + offset, substr_size, copy);
}
char operator [] (const size_t index) {
assert(index < size, "index out of bound");
eos_assert(index < size, "index out of bound");
return *(data + index);
}
......@@ -237,7 +238,7 @@ namespace eosio {
}
string& operator += (const string& str){
assert((size + str.size > size) && (size + str.size > str.size), "overflow");
eos_assert((size + str.size > size) && (size + str.size > str.size), "overflow");
char* new_data;
size_t new_size;
......
......@@ -29,7 +29,7 @@ extern "C" {
* @param cstr - a null terminated action to explain the reason for failure
*/
void assert( uint32_t test, const char* cstr );
void eos_assert( uint32_t test, const char* cstr );
/**
* Returns the time in seconds from 1970 of the last accepted block (not the block including this action)
......@@ -37,7 +37,27 @@ extern "C" {
* @return time in seconds from 1970 of the last accepted block
*/
time now();
///@ } systemcapi
/**
* @defgroup privilegedapi Privileged API
* @ingroup systemapi
* @brief Defines an API for accessing configuration of the chain that can only be done by privileged accounts
*/
/**
* @defgroup privilegedcapi Privileged C API
* @ingroup privilegedapi
* @brief Define C Privileged API
*
* @{
*/
void set_resource_limits( account_name account, int64_t ram_bytes, int64_t net_weight, int64_t cpu_weight, int64_t ignored);
void set_active_producers( char *producer_data, size_t producer_data_size );
///@ } privilegedcapi
}
......@@ -21,7 +21,7 @@ namespace eosio {
char temp[1024];
*reinterpret_cast<uint64_t *>(temp) = key;
auto read = load_i64( DefaultScope, scope , TableName, temp, sizeof(temp) );
assert( read > 0, "key does not exist" );
eos_assert( read > 0, "key does not exist" );
datastream<const char*> ds(temp, read);
T result;
......@@ -63,7 +63,7 @@ namespace eosio {
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" );
eos_assert( size <= 1024, "singleton too big to store" );
datastream<char*> ds( buf, size );
ds << value;
......@@ -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,21 +104,31 @@ 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;
}
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) );
......
......@@ -41,7 +41,7 @@ namespace eosio {
operator asset()const { return asset( quantity, Symbol ); }
token( const asset& a ):quantity(a.amount) {
assert( a.symbol == Symbol, "attempt to construct token from asset with different symbol" );
eos_assert( a.symbol == Symbol, "attempt to construct token from asset with different symbol" );
}
/**
......@@ -65,7 +65,7 @@ namespace eosio {
* @return this token after subtraction
*/
token& operator-=( const token& a ) {
assert( quantity >= a.quantity, "integer underflow subtracting token balance" );
eos_assert( quantity >= a.quantity, "integer underflow subtracting token balance" );
quantity -= a.quantity;
return *this;
}
......@@ -78,7 +78,7 @@ namespace eosio {
* @return this token after addition
*/
token& operator+=( const token& a ) {
assert( quantity + a.quantity >= a.quantity, "integer overflow adding token balance" );
eos_assert( quantity + a.quantity >= a.quantity, "integer overflow adding token balance" );
quantity += a.quantity;
return *this;
}
......@@ -258,8 +258,8 @@ namespace eosio {
* @param quote - quote token
*/
price( BaseToken base, QuoteToken quote ) {
assert( base >= BaseToken(1ul), "invalid price" );
assert( quote >= QuoteToken(1ul), "invalid price" );
eos_assert( base >= BaseToken(1ul), "invalid price" );
eos_assert( quote >= QuoteToken(1ul), "invalid price" );
base_per_quote = base.quantity;
base_per_quote *= precision;
......
......@@ -4,7 +4,12 @@
*/
#pragma once
#include <stdint.h>
#include <wchar.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup types Builtin Types
......@@ -14,24 +19,10 @@ extern "C" {
* @{
*/
typedef unsigned __int128 uint128_t;
typedef unsigned long long uint64_t;
typedef unsigned long uint32_t;
typedef unsigned short uint16_t;
typedef unsigned char uint8_t;
typedef __int128 int128_t;
typedef long long int64_t;
typedef long int32_t;
typedef short int16_t;
typedef char int8_t;
struct uint256 {
uint64_t words[4];
};
typedef unsigned int size_t;
typedef uint64_t account_name;
typedef uint64_t permission_name;
typedef uint64_t token_name;
......@@ -60,22 +51,24 @@ struct checksum {
struct fixed_string16 {
uint8_t len;
char str[16];
char str[16];
};
typedef fixed_string16 field_name;
typedef struct fixed_string16 field_name;
struct fixed_string32 {
uint8_t len;
char str[32];
char str[32];
};
typedef fixed_string32 type_name;
typedef struct fixed_string32 type_name;
struct account_permission {
account_name account;
permission_name permission;
};
#ifdef __cplusplus
} /// extern "C"
#endif
/// @}
......@@ -126,4 +126,4 @@ struct signed_int {
}
};
/// @}
\ No newline at end of file
/// @}
file(GLOB ABI_FILES "*.abi")
add_wast_target(exchange "${CMAKE_SOURCE_DIR}/contracts" ${CMAKE_CURRENT_BINARY_DIR})
add_wast_executable(TARGET exchange
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
LIBRARIES eosiolib
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
configure_file("${ABI_FILES}" "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY)
add_dependencies( exchange currency )
......@@ -75,7 +75,7 @@ void apply_currency_transfer( const currency::transfer& transfer ) {
mod_account.currency_balance -= transfer.quantity;
});
} else {
assert( false, "notified on transfer that is not relevant to this exchange" );
eos_assert( false, "notified on transfer that is not relevant to this exchange" );
}
}
......@@ -95,7 +95,7 @@ void apply_eos_transfer( const eosio::transfer& transfer ) {
mod_account.eos_balance -= transfer.quantity;
});
} else {
assert( false, "notified on transfer that is not relevant to this exchange" );
eos_assert( false, "notified on transfer that is not relevant to this exchange" );
}
}
......@@ -132,13 +132,13 @@ void apply_exchange_buy( buy_order order ) {
bid& exchange_bid = order;
require_auth( exchange_bid.buyer.name );
assert( exchange_bid.quantity > eosio::tokens(0), "invalid quantity" );
assert( exchange_bid.expiration > now(), "order expired" );
eos_assert( exchange_bid.quantity > eosio::tokens(0), "invalid quantity" );
eos_assert( exchange_bid.expiration > now(), "order expired" );
print( name(exchange_bid.buyer.name), " created bid for ", order.quantity, " currency at price: ", order.at_price, "\n" );
bid existing_bid;
assert( !bids_by_id::get( exchange_bid.buyer, existing_bid ), "order with this id already exists" );
eos_assert( !bids_by_id::get( exchange_bid.buyer, existing_bid ), "order with this id already exists" );
print( __FILE__, __LINE__, "\n" );
auto buyer_account = get_account( exchange_bid.buyer.name );
......@@ -147,7 +147,7 @@ void apply_exchange_buy( buy_order order ) {
ask lowest_ask;
if( !asks_by_price::front( lowest_ask ) ) {
print( "\n No asks found, saving buyer account and storing bid\n" );
assert( !order.fill_or_kill, "order not completely filled" );
eos_assert( !order.fill_or_kill, "order not completely filled" );
bids::store( exchange_bid );
buyer_account.open_orders++;
save( buyer_account );
......@@ -183,7 +183,7 @@ void apply_exchange_buy( buy_order order ) {
print( "saving buyer's account\n" );
if( exchange_bid.quantity ) {
print( exchange_bid.quantity, " eos left over" );
assert( !order.fill_or_kill, "order not completely filled" );
eos_assert( !order.fill_or_kill, "order not completely filled" );
bids::store( exchange_bid );
return;
}
......@@ -195,14 +195,14 @@ void apply_exchange_sell( sell_order order ) {
ask& exchange_ask = order;
require_auth( exchange_ask.seller.name );
assert( exchange_ask.quantity > currency_tokens(0), "invalid quantity" );
assert( exchange_ask.expiration > now(), "order expired" );
eos_assert( exchange_ask.quantity > currency_tokens(0), "invalid quantity" );
eos_assert( exchange_ask.expiration > now(), "order expired" );
print( "\n\n", name(exchange_ask.seller.name), " created sell for ", order.quantity,
" currency at price: ", order.at_price, "\n");
ask existing_ask;
assert( !asks_by_id::get( exchange_ask.seller, existing_ask ), "order with this id already exists" );
eos_assert( !asks_by_id::get( exchange_ask.seller, existing_ask ), "order with this id already exists" );
auto seller_account = get_account( exchange_ask.seller.name );
seller_account.currency_balance -= exchange_ask.quantity;
......@@ -210,7 +210,7 @@ void apply_exchange_sell( sell_order order ) {
bid highest_bid;
if( !bids_by_price::back( highest_bid ) ) {
assert( !order.fill_or_kill, "order not completely filled" );
eos_assert( !order.fill_or_kill, "order not completely filled" );
print( "\n No bids found, saving seller account and storing ask\n" );
asks::store( exchange_ask );
seller_account.open_orders++;
......@@ -241,7 +241,7 @@ void apply_exchange_sell( sell_order order ) {
if( exchange_ask.quantity && !order.fill_or_kill ) seller_account.open_orders++;
save( seller_account );
if( exchange_ask.quantity ) {
assert( !order.fill_or_kill, "order not completely filled" );
eos_assert( !order.fill_or_kill, "order not completely filled" );
print( "saving ask\n" );
asks::store( exchange_ask );
return;
......@@ -254,7 +254,7 @@ void apply_exchange_cancel_buy( order_id order ) {
require_auth( order.name );
bid bid_to_cancel;
assert( bids_by_id::get( order, bid_to_cancel ), "bid with this id does not exists" );
eos_assert( bids_by_id::get( order, bid_to_cancel ), "bid with this id does not exists" );
auto buyer_account = get_account( order.name );
buyer_account.eos_balance += bid_to_cancel.quantity;
......@@ -270,7 +270,7 @@ void apply_exchange_cancel_sell( order_id order ) {
require_auth( order.name );
ask ask_to_cancel;
assert( asks_by_id::get( order, ask_to_cancel ), "ask with this id does not exists" );
eos_assert( asks_by_id::get( order, ask_to_cancel ), "ask with this id does not exists" );
auto seller_account = get_account( order.name );
seller_account.currency_balance += ask_to_cancel.quantity;
......@@ -307,7 +307,7 @@ extern "C" {
apply_exchange_cancel_sell( current_action<exchange::order_id>() );
break;
default:
assert( false, "unknown action" );
eos_assert( false, "unknown action" );
}
}
else if( code == N(currency) ) {
......
file(GLOB ABI_FILES "*.abi")
configure_file("${ABI_FILES}" "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY)
add_wast_target(identity "${CMAKE_SOURCE_DIR}/contracts" ${CMAKE_CURRENT_BINARY_DIR})
add_wast_executable(TARGET identity
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
LIBRARIES eosiolib
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
add_subdirectory(test)
......@@ -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;
......@@ -195,8 +197,8 @@ namespace identity {
typedef table_i64i64i64<code, N(certs), code, certrow> certs_table;
typedef table64<code, N(ident), code, identrow> idents_table;
typedef table64<code, N(account), code, identity_name> accounts_table;
typedef table64<code, N(trust), code, trustrow> trust_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,20 +300,16 @@ 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 );
}
}
static void on( const create& c ) {
require_auth( c.creator );
assert( !idents_table::exists( c.identity ), "identity already exists" );
assert( c.identity != 0, "identity=0 is not allowed" );
eos_assert( !idents_table::exists( c.identity ), "identity already exists" );
eos_assert( c.identity != 0, "identity=0 is not allowed" );
idents_table::set( identrow{ .identity = c.identity,
.creator = c.creator } );
}
......@@ -306,7 +319,7 @@ namespace identity {
if( cert.bill_storage_to != cert.certifier )
require_auth( cert.bill_storage_to );
assert( idents_table::exists( cert.identity ), "identity does not exist" );
eos_assert( idents_table::exists( cert.identity ), "identity does not exist" );
/// the table exists in the scope of the identity
certs_table certs( cert.identity );
......@@ -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");
eos_assert(value.type.get_size() <= 32, "certrow::type should be not longer than 32 bytes");
row.type = value.type;
row.data = value.data;
......@@ -328,19 +341,23 @@ namespace identity {
//special handling for owner
if (value.property == N(owner)) {
assert(sizeof(account_name) == value.data.size(), "data size doesn't match account_name size");
eos_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");
eos_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 );
}
}
}
}
......
set(ABI_FILES "identity_test.abi")
configure_file("${ABI_FILES}" "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY)
add_wast_target(identity_test "${CMAKE_SOURCE_DIR}/contracts" ${CMAKE_CURRENT_BINARY_DIR})
add_wast_executable(TARGET identity_test
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
LIBRARIES eosiolib
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
add_wast_target(infinite "${CMAKE_SOURCE_DIR}/contracts" ${CMAKE_CURRENT_BINARY_DIR})
add_wast_executable(TARGET infinite
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
LIBRARIES eosiolib
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
......@@ -2,50 +2,15 @@
* @file
* @copyright defined in eos/LICENSE.txt
*/
#include <infinite/infinite.hpp> /// defines transfer struct (abi)
namespace infinite {
using namespace eosio;
/// When storing accounts, check for empty balance and remove account
void store_account( account_name account_to_store, const account& a ) {
if( a.is_empty() ) {
/// value, scope
accounts::remove( a, account_to_store );
} else {
/// value, scope
accounts::store( a, account_to_store );
}
}
void apply_currency_transfer( const infinite::transfer& transfer ) {
require_recipient( transfer.to, transfer.from );
require_auth( transfer.from );
auto from = get_account( transfer.from );
auto to = get_account( transfer.to );
while (from.balance > infinite::currency_tokens())
{
from.balance -= transfer.quantity; /// token subtraction has underflow assertion
to.balance += transfer.quantity; /// token addition has overflow assertion
}
store_account( transfer.from, from );
store_account( transfer.to, to );
}
} // namespace infinite
using namespace infinite;
#include <eosiolib/print.hpp> /// defines transfer struct (abi)
extern "C" {
/// The apply method implements the dispatch of events to this contract
void apply( uint64_t code, uint64_t action ) {
if( code == N(currency) ) {
if( action == N(transfer) )
infinite::apply_currency_transfer( current_action< infinite::transfer >() );
/// The apply method just prints forever
void apply( uint64_t, uint64_t ) {
int idx = 0;
while(true) {
eosio::print(idx++);
}
}
}
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#include <eosiolib/eos.hpp>
#include <eosiolib/token.hpp>
#include <eosiolib/db.hpp>
namespace infinite {
typedef eosio::token<uint64_t,N(currency)> currency_tokens;
/**
* transfer requires that the sender and receiver be the first two
* accounts notified and that the sender has provided authorization.
*/
struct transfer {
account_name from;
account_name to;
currency_tokens quantity;
};
/**
* @brief row in account table stored within each scope
*/
struct account {
account( currency_tokens b = currency_tokens() ):balance(b){}
/**
* The key is constant because there is only one record per scope/currency/accounts
*/
const uint64_t key = N(account);
currency_tokens balance;
bool is_empty()const { return balance.quantity == 0; }
};
static_assert( sizeof(account) == sizeof(uint64_t)+sizeof(currency_tokens), "unexpected packing" );
using accounts = eosio::table<N(currency),N(currency),N(account),account,uint64_t>;
/**
* accounts information for owner is stored:
*
* owner/infinite/account/account -> account
*
* This API is made available for 3rd parties wanting read access to
* the users balance. If the account doesn't exist a default constructed
* account will be returned.
*/
inline account get_account( account_name owner ) {
account owned_account;
/// scope, record
accounts::get( owned_account, owner );
return owned_account;
}
} /// namespace infinite
SET(SRC_FILENAMES algorithm.cpp any.cpp bind.cpp condition_variable.cpp exception.cpp functional.cpp
future.cpp ios.cpp iostream.cpp locale.cpp memory.cpp mutex.cpp new.cpp optional.cpp
regex.cpp shared_mutex.cpp stdexcept.cpp string.cpp strstream.cpp system_error.cpp
thread.cpp typeinfo.cpp utility.cpp valarray.cpp variant.cpp vector.cpp)
SET(SRC_FILES "")
FOREACH(FN ${SRC_FILENAMES})
LIST(APPEND SRC_FILES "upstream/src/${FN}")
ENDFOREACH(FN)
add_wast_library(TARGET libc++
SOURCE_FILES "${SRC_FILES}"
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
Subproject commit 35a26f82dae8b292290815ae6ede8f849ce7806f
file(GLOB CRYPT_SOURCES "upstream/src/crypt/*.c")
file(GLOB CTYPE_SOURCES "upstream/src/ctype/*.c")
file(GLOB ENV_SOURCES "upstream/src/env/*.c")
file(GLOB ERRNO_SOURCES "upstream/src/errno/*.c")
file(GLOB EXIT_SOURCES "upstream/src/exit/*.c")
file(GLOB LOCALE_SOURCES "upstream/src/locale/*.c")
file(GLOB MBYTE_SOURCES "upstream/src/multibyte/*.c")
file(GLOB SEARCH_SOURCES "upstream/src/search/*.c")
file(GLOB STDIO_SOURCES "upstream/src/stdio/*.c")
file(GLOB STDLIB_SOURCES "upstream/src/stdlib/*.c")
file(GLOB STRING_SOURCES "upstream/src/string/*.c")
file(GLOB TIME_SOURCES "upstream/src/time/*.c")
file(GLOB THREAD_SOURCES "upstream/src/thread/*.c") #only for __lock __unlock
file(GLOB INTERNAL_SOURCES upstream/src/internal/intscan.c upstream/src/internal/shgetc.c upstream/src/internal/libc.c)
add_wast_library(TARGET libc
SOURCE_FILES ${CRYPT_SOURCES} ${CTYPE_SOURCES} ${ENV_SOURCES} ${ERRNO_SOURCES} ${EXIT_SOURCES} ${INTERNAL_SOURCES} ${LOCALE_SOURCES} ${MBYTE_SOURCES}
${SEARCH_SOURCES} ${STDIO_SOURCES} ${STDLIB_SOURCES} ${STRING_SOURCES} ${TIME_SOURCES} ${THREAD_SOURCES}
INCLUDE_FOLDERS ${CMAKE_SOURCE_DIR}/contracts/musl/upstream/include ${CMAKE_SOURCE_DIR}/contracts/musl/upstream/src/internal ${CMAKE_SOURCE_DIR}/contracts/musl/upstream/arch/eos ${CMAKE_SOURCE_DIR}/contracts/
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
Subproject commit 29098b1f3044e7a9e2c1152028dba08885ea04f9
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})
add_wast_executable(TARGET noop
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
LIBRARIES eosiolib
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
file(GLOB ABI_FILES "*.abi")
configure_file("${ABI_FILES}" "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY)
add_wast_target(proxy "${CMAKE_SOURCE_DIR}/contracts" ${CMAKE_CURRENT_BINARY_DIR})
add_wast_executable(TARGET proxy
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
LIBRARIES eosiolib
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
......@@ -5,20 +5,35 @@
#include <proxy/proxy.hpp>
#include <eosio.system/eosio.system.hpp>
#include <eosiolib/transaction.hpp>
#include <currency/currency.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;
const auto self = current_receiver();
auto get_res = configs::get(code_config, self);
assert(get_res, "Attempting to use unconfigured proxy");
eos_assert(get_res, "Attempting to use unconfigured proxy");
if (transfer.from == self) {
assert(transfer.to == code_config.owner, "proxy may only pay its owner" );
eos_assert(transfer.to == code_config.owner, "proxy may only pay its owner" );
} else {
assert(transfer.to == self, "proxy is not involved in this transfer");
eos_assert(transfer.to == self, "proxy is not involved in this transfer");
T new_transfer = T(transfer);
new_transfer.from = self;
new_transfer.to = code_config.owner;
......@@ -47,7 +62,7 @@ namespace proxy {
eosio::print("starting onerror\n");
const auto self = current_receiver();
config code_config;
assert(configs::get(code_config, self), "Attempting use of unconfigured proxy");
eos_assert(configs::get(code_config, self), "Attempting use of unconfigured proxy");
auto id = code_config.next_id++;
configs::store(code_config, self);
......@@ -67,10 +82,12 @@ extern "C" {
if ( code == N(eosio)) {
if (action == N(onerror)) {
apply_onerror(deferred_transaction::from_current_action());
} if( action == N(transfer) ) {
apply_transfer(code, unpack_action<eosiosystem::contract<N(eosio.system)>::currency::transfer_memo>());
}
} else if ( code == N(eosio.system) ) {
} else if ( code == N(currency) ) {
if( action == N(transfer) ) {
apply_transfer(code, unpack_action<eosiosystem::contract<N(eosio.system)>::currency::transfer_memo>());
apply_transfer(code, unpack_action<currency::contract::transfer_memo>());
}
} else if (code == current_receiver() ) {
if ( action == N(setowner)) {
......
......@@ -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),N(proxy),config,uint64_t>;
} /// namespace proxy
file(GLOB ABI_FILES "*.abi")
add_wast_target(simpledb "${CMAKE_SOURCE_DIR}/contracts" ${CMAKE_CURRENT_BINARY_DIR})
add_wast_executable(TARGET simpledb
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
LIBRARIES eosiolib
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
configure_file("${ABI_FILES}" "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY)
......@@ -54,7 +54,7 @@ extern "C" {
auto bytes = eosio::raw::pack(tmp);
store_i64i64i64( N(simpledb), N(record3), bytes.data, bytes.len);
} else {
assert(0, "unknown message");
eos_assert(0, "unknown message");
}
}
}
......
......@@ -83,7 +83,7 @@ namespace eosio {
Type current_message_ex() {
uint32_t size = action_size();
char* data = (char *)eosio::malloc(size);
assert(data && read_action(data, size) == size, "error reading message");
eos_assert(data && read_action(data, size) == size, "error reading message");
Type value;
eosio::raw::unpack(data, size, value);
eosio::free(data);
......
add_wast_target(social "${CMAKE_SOURCE_DIR}/contracts" ${CMAKE_CURRENT_BINARY_DIR})
\ No newline at end of file
add_wast_executable(TARGET social
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
LIBRARIES eosiolib
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
......@@ -62,7 +62,7 @@ void apply_social_post() {
const auto& post = current_action<post_action>();
require_auth( post.author );
assert( current_context() == post.author, "cannot call from any other context" );
eos_assert( current_context() == post.author, "cannot call from any other context" );
static post_record& existing;
if( !Db::get( post.postid, existing ) )
......@@ -84,8 +84,8 @@ void apply_social_vote() {
if( context == vote.author ) {
static post_record post;
assert( Db::get( vote.postid, post ) > 0, "unable to find post" );
assert( now() - post.created < days(7), "cannot vote after 7 days" );
eos_assert( Db::get( vote.postid, post ) > 0, "unable to find post" );
eos_assert( now() - post.created < days(7), "cannot vote after 7 days" );
post.votes += vote.vote_power;
Db::store( vote.postid, post );
}
......@@ -95,13 +95,13 @@ void apply_social_vote() {
auto abs_vote = abs(vote.vote_power);
vote_account.vote_power = min( vote_account.social_power,
vote_account.vote_power + (vote_account.social_power * (now()-last_vote)) / days(7));
assert( abs_vote <= vote_account.vote_power, "insufficient vote power" );
eos_assert( abs_vote <= vote_account.vote_power, "insufficient vote power" );
post.votes += vote.vote_power;
vote_account.vote_power -= abs_vote;
vote_account.last_vote = now();
Db::store( "account", vote_account );
} else {
assert( false, "invalid context for execution of this vote" );
eos_assert( false, "invalid context for execution of this vote" );
}
}
#file(GLOB ABI_FILES "*.abi")
set(ABI_FILES "stltest.abi")
add_wast_executable(TARGET stltest
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
LIBRARIES libc++ libc eosiolib
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
configure_file("${ABI_FILES}" "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY)
{
"types": [{
"new_type_name": "my_account_name",
"type": "name"
}
],
"structs": [{
"name": "message",
"base": "",
"fields": [
{"name":"from", "type":"my_account_name"},
{"name":"to", "type":"my_account_name"},
{"name": "message", "type":"string" }
]
},{
"name": "messages_count",
"base": "",
"fields": [
{"name": "user", "type": "my_account_name"},
{"name": "count", "type": "uint32"}
]
}
],
"actions": [{
"name": "message",
"type": "message"
}
],
"tables": [{
"name": "msgsent",
"type": "messages_count",
"index_type": "i64",
"key_names" : ["user"],
"key_types" : ["my_account_name"]
},{
"name": "msgreceived",
"type": "messages_count",
"index_type": "i64",
"key_names" : ["user"],
"key_types" : ["my_account_name"]
}
]
}
\ No newline at end of file
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#include <stltest/stltest.hpp> /// defines transfer struct (abi)
// include entire libc
#include <alloca.h>
#include <ar.h>
#include <assert.h>
#include <byteswap.h>
#include <cpio.h>
#include <crypt.h>
#include <ctype.h>
#include <elf.h>
#include <endian.h>
#include <errno.h>
#include <features.h>
#include <fnmatch.h>
#include <inttypes.h>
#include <iso646.h>
#include <limits.h>
#include <locale.h>
#include <malloc.h>
#include <math.h>
#include <memory.h>
#include <monetary.h>
#include <mqueue.h>
#include <regex.h>
#include <search.h>
#include <stdalign.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdc-predef.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdnoreturn.h>
#include <string.h>
#include <strings.h>
#include <stropts.h>
#include <sysexits.h>
#include <tar.h>
#include <uchar.h>
#include <unistd.h>
#include <values.h>
#include <wchar.h>
#include <wctype.h>
#include <wordexp.h>
//include entire libstdc++
#include<algorithm>
#include<any>
#include<array>
#include<bitset>
#include<cassert>
//include<ccomplex>
#include<cctype>
#include<cerrno>
//include<cfenv>
#include<cfloat>
//include<chrono>
#include<cinttypes>
#include<ciso646>
#include<climits>
#include<clocale>
#include<cmath>
#include<codecvt>
//include<complex>
#include<condition_variable>
//include<csetjmp>
//include<csignal>
#include<cstdarg>
#include<cstdbool>
#include<cstddef>
#include<cstdint>
#include<cstdio>
#include<cstdlib>
#include<cstring>
//include<ctgmath>
#include<ctime>
#include<cwchar>
#include<cwctype>
#include<deque>
#include<exception>
#include<forward_list>
//include<fstream>
#include<functional>
//include<future>
#include<initializer_list>
#include<iomanip>
#include<ios>
#include<iosfwd>
#include<iostream>
#include<istream>
#include<iterator>
#include<limits>
#include<list>
#include<locale>
#include<map>
#include<memory>
#include<mutex>
#include<new>
#include<numeric>
#include<optional>
#include<ostream>
#include<queue>
//include<random>
#include<ratio>
#include<regex>
#include<scoped_allocator>
#include<set>
//include<shared_mutex>
#include<sstream>
#include<stack>
#include<stdexcept>
#include<streambuf>
#include<string>
#include<string_view>
#include<strstream>
#include<system_error>
//include<thread>
#include<tuple>
#include<type_traits>
#include<typeindex>
#include<typeinfo>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<valarray>
#include<variant>
#include<vector>
/*
#include <array>
#include <vector>
#include <stack>
#include <queue>
#include <deque>
#include <list>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <string>
#include <stdexcept>
*/
//include <eosiolib/eos.hpp>
#include <eosiolib/token.hpp>
#include <eosiolib/string.hpp>
#include <eosiolib/dispatcher.hpp>
using namespace eosio;
/*
namespace std {
extern ios_base __start_std_streams;
}
*/
namespace stltest {
struct MSTR {
MSTR() : x(7891) {
prints("ATTENTION! S::S() called\n");
}
int x;
~MSTR() {
prints("~MSTR");
}
};
/*
std::string s = "abcdef";
eosio::string s2 = "abcdef";;
MSTR global;
*/
class contract {
public:
typedef eosio::token<N(mycurrency),S(4,MYCUR)> token_type;
static const uint64_t code = token_type::code;
static const uint64_t symbol = token_type::symbol;
static const uint64_t sent_table_name = N(sent);
static const uint64_t received_table_name = N(received);
struct message {
account_name from;
account_name to;
//string msg;
static uint64_t get_account() { return current_receiver(); }
static uint64_t get_name() { return N(message); }
template<typename DataStream>
friend DataStream& operator << ( DataStream& ds, const message& m ){
return ds << m.from << m.to;// << m.msg;
}
template<typename DataStream>
friend DataStream& operator >> ( DataStream& ds, message& m ){
return ds >> m.from >> m.to;// >> m.msg;
}
};
static void on(const message& msg) {
/* manual initialization of global variable
new(&std::__start_std_streams)std::ios_base::Init;
*/
/*
std::ostringstream osm;
osm << "abcdef";
std::string s = osm.str();
prints_l(s.data(), s.size());
*/
/*
prints("STD string: "); prints(s.c_str());
prints("\nEOS string: "); prints_l(s2.get_data(), s2.get_size());
*/
prints("STL test start\n");
void* ptr = malloc(10);
free(ptr);
std::array<uint32_t, 10> arr;
arr.fill(3);
arr[0] = 0;
std::vector<uint32_t> v;
v.push_back(0);
std::stack<char> stack;
stack.push('J');
stack.pop();
std::queue<unsigned int> q;
q.push(0);
std::deque<long> dq;
dq.push_front(0.0f);
std::list<uint32_t> l;
l.push_back(0);
std::string s = "abcdef";
s.append(1, 'g');
std::map<int, long> m;
m.emplace(0, 1);
auto mit = m.lower_bound(2);
std::set<long> st;
st.insert(0);
st.erase(st.begin());
st.count(0);
//std::unordered_map<int, string> hm;
//hm[0] = "abc";
//std::unordered_set<int> hs;
//hs.insert(0);
sort(dq.begin(), dq.end());
auto lit = find_if(l.begin(), l.end(), [](uint32_t f) { return f < 10; });
prints("STL test done.\n");
//std::cout << "STL test done." << std::endl;
}
static void apply( account_name c, action_name act) {
eosio::dispatch<stltest::contract, message>(c,act);
}
};
} /// namespace eosio
extern "C" {
/// The apply method implements the dispatch of events to this contract
void apply( uint64_t code, uint64_t action ) {
stltest::contract::apply( code, action );
}
}
#pragma once
\ No newline at end of file
file(GLOB ABI_FILES "*.abi")
add_wast_target(storage "${CMAKE_SOURCE_DIR}/contracts" ${CMAKE_CURRENT_BINARY_DIR})
configure_file("${ABI_FILES}" "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY)
add_wast_executable(TARGET storage
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
LIBRARIES eosiolib
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
......@@ -121,10 +121,10 @@ extern "C" {
auto len = read_action( tmp, 1025 );
TOKEN_NAME::apply_storage_rejectstore( tmp, len );
} else {
assert(0, "unknown message");
eos_assert(0, "unknown message");
}
} else {
assert(0, "unknown code");
eos_assert(0, "unknown code");
}
}
}
file(GLOB ABI_FILES "*.abi")
configure_file("${ABI_FILES}" "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY)
add_wast_executable(TARGET test.system
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
LIBRARIES eosiolib
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
{
"types": [],
"structs": [{
"name": "set_account_limits",
"base": "",
"fields": [
{"name":"account", "type":"account_name"},
{"name":"ram_bytes", "type":"int64"},
{"name":"net_weight", "type":"int64"},
{"name":"cpu_weight", "type":"int64"}
]
},{
"name": "set_global_limits",
"base": "",
"fields": [
{"name":"cpu_usec_per_period", "type":"int64"},
]
},{
"name": "producer_key",
"base": "",
"fields": [
{"name":"account", "type":"account_name"},
{"name":"public_key", "type":"string"}
]
},{
"name": "set_producers",
"base": "",
"fields": [
{"name":"version", "type":"uint32"},
{"name":"producer", "type":"producer_key[]"}
]
},{
"name": "require_auth",
"base": "",
"fields": [
{"name":"from", "type":"account_name"},
]
},{
"name": "nonce",
"base": "",
"fields": [
{"name":"value", "type":"string"}
]
}],
"actions": [{
"name": "setalimits",
"type": "set_account_limits"
},{
"name": "setglimits",
"type": "set_global_limits"
},{
"name": "setprods",
"type": "set_producers"
},{
"name": "reqauth",
"type": "require_auth"
},{
"name": "nonce",
"type": "nonce"
}
],
"tables": []
}
\ No newline at end of file
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#include <eosiolib/action.hpp>
#include <eosiolib/types.hpp>
#include <eosiolib/serialize.hpp>
#include <eosiolib/string.hpp>
#include <eosiolib/system.h>
using namespace eosio;
namespace testsystem {
template<uint64_t Val>
struct dispatchable {
constexpr static uint64_t action_name = Val;
};
struct set_account_limits : dispatchable<N(setalimits)> {
account_name account;
int64_t ram_bytes;
int64_t net_weight;
int64_t cpu_weight;
static void process(const set_account_limits& act) {
set_resource_limits(act.account, act.ram_bytes, act.net_weight, act.cpu_weight, 0);
}
EOSLIB_SERIALIZE( set_account_limits, (account)(ram_bytes)(net_weight)(cpu_weight) );
};
struct set_global_limits : dispatchable<N(setglimits)> {
int64_t cpu_usec_per_period;
static void process(const set_global_limits& act) {
// TODO: support this
}
EOSLIB_SERIALIZE( set_global_limits, (cpu_usec_per_period) );
};
struct producer_key {
account_name account;
string public_key;
EOSLIB_SERIALIZE( producer_key, (account)(public_key) );
};
struct set_producers : dispatchable<N(setprods)> {
uint32_t version;
vector<producer_key> producers;
static void process(const set_producers&) {
char buffer[action_size()];
read_action( buffer, sizeof(buffer) );
set_active_producers(buffer, sizeof(buffer));
}
EOSLIB_SERIALIZE( set_producers, (version)(producers) );
};
struct require_auth : dispatchable<N(reqauth)> {
account_name from;
static void process(const require_auth& r) {
::require_auth(r.from);
}
};
template<typename ...Ts>
struct dispatcher_impl;
template<typename T>
struct dispatcher_impl<T> {
static bool dispatch(uint64_t action) {
if (action == T::action_name) {
T::process(current_action<T>());
return true;
}
return false;
}
};
template<typename T, typename ...Rem>
struct dispatcher_impl<T, Rem...> {
static bool dispatch(uint64_t action) {
return dispatcher_impl<T>::dispatch(action) || dispatcher_impl<Rem...>::dispatch(action);
}
};
using dispatcher = dispatcher_impl<set_account_limits, set_global_limits, set_producers, require_auth>;
};
extern "C" {
/// The apply method implements the dispatch of events to this contract
void apply( uint64_t code, uint64_t act ) {
if (code == current_receiver()) {
testsystem::dispatcher::dispatch(act);
}
}
} // extern "C"
add_wast_target(test_api "${CMAKE_SOURCE_DIR}/contracts" ${CMAKE_CURRENT_BINARY_DIR})
add_wast_executable(TARGET test_api
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
LIBRARIES eosiolib
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
......@@ -11,26 +11,26 @@ void test_action::read_action_normal() {
char buffer[100];
uint32_t total = 0;
assert( current_receiver() == N(testapi), "current_receiver() == N(testapi)" );
eos_assert( current_receiver() == N(testapi), "current_receiver() == N(testapi)" );
assert(action_size() == sizeof(dummy_action), "action_size() == sizeof(dummy_action)");
eos_assert(action_size() == sizeof(dummy_action), "action_size() == sizeof(dummy_action)");
total = read_action(buffer, 30);
assert(total == sizeof(dummy_action) , "read_action(30)" );
eos_assert(total == sizeof(dummy_action) , "read_action(30)" );
total = read_action(buffer, 100);
assert(total == sizeof(dummy_action) , "read_action(100)" );
eos_assert(total == sizeof(dummy_action) , "read_action(100)" );
total = read_action(buffer, 5);
assert(total == 5 , "read_action(5)" );
eos_assert(total == 5 , "read_action(5)" );
total = read_action(buffer, sizeof(dummy_action) );
assert(total == sizeof(dummy_action), "read_action(sizeof(dummy_action))" );
eos_assert(total == sizeof(dummy_action), "read_action(sizeof(dummy_action))" );
dummy_action *dummy13 = reinterpret_cast<dummy_action *>(buffer);
assert(dummy13->a == DUMMY_MESSAGE_DEFAULT_A, "dummy13->a == DUMMY_MESSAGE_DEFAULT_A");
assert(dummy13->b == DUMMY_MESSAGE_DEFAULT_B, "dummy13->b == DUMMY_MESSAGE_DEFAULT_B");
assert(dummy13->c == DUMMY_MESSAGE_DEFAULT_C, "dummy13->c == DUMMY_MESSAGE_DEFAULT_C");
eos_assert(dummy13->a == DUMMY_MESSAGE_DEFAULT_A, "dummy13->a == DUMMY_MESSAGE_DEFAULT_A");
eos_assert(dummy13->b == DUMMY_MESSAGE_DEFAULT_B, "dummy13->b == DUMMY_MESSAGE_DEFAULT_B");
eos_assert(dummy13->c == DUMMY_MESSAGE_DEFAULT_C, "dummy13->c == DUMMY_MESSAGE_DEFAULT_C");
}
......@@ -61,11 +61,11 @@ void test_action::read_action_to_64k() {
//}
void test_action::assert_false() {
assert(false, "test_action::assert_false");
eos_assert(false, "test_action::assert_false");
}
void test_action::assert_true() {
assert(true, "test_action::assert_true");
eos_assert(true, "test_action::assert_true");
}
//unsigned int test_action::now() {
......
......@@ -154,7 +154,7 @@ extern "C" {
// WASM_TEST_HANDLER(test_account, test_balance_acc1);
//
//unhandled test call
assert(false, "Unknown Test");
eos_assert(false, "Unknown Test");
}
}
......@@ -89,12 +89,12 @@ namespace tic_tac_toe {
*/
void apply_create(const create& c) {
require_auth(c.host);
assert(c.challenger != c.host, "challenger shouldn't be the same as host");
eos_assert(c.challenger != c.host, "challenger shouldn't be the same as host");
// Check if game already exists
game existing_game;
bool game_exists = Games::get(c.challenger, existing_game, c.host);
assert(game_exists == false, "game already exists");
eos_assert(game_exists == false, "game already exists");
game game_to_create(c.challenger, c.host);
Games::store(game_to_create, c.host);
......@@ -110,10 +110,10 @@ namespace tic_tac_toe {
// Check if game exists
game game_to_restart;
bool game_exists = Games::get(r.challenger, game_to_restart, r.host);
assert(game_exists == true, "game doesn't exist!");
eos_assert(game_exists == true, "game doesn't exist!");
// Check if this game belongs to the action sender
assert(r.by == game_to_restart.host || r.by == game_to_restart.challenger, "this is not your game!");
eos_assert(r.by == game_to_restart.host || r.by == game_to_restart.challenger, "this is not your game!");
// Reset game
game_to_restart.reset_game();
......@@ -131,7 +131,7 @@ namespace tic_tac_toe {
// Check if game exists
game game_to_close;
bool game_exists = Games::get(c.challenger, game_to_close, c.host);
assert(game_exists == true, "game doesn't exist!");
eos_assert(game_exists == true, "game doesn't exist!");
Games::remove(game_to_close, game_to_close.host);
}
......@@ -146,18 +146,18 @@ namespace tic_tac_toe {
// Check if game exists
game game_to_move;
bool game_exists = Games::get(m.challenger, game_to_move, m.host);
assert(game_exists == true, "game doesn't exist!");
eos_assert(game_exists == true, "game doesn't exist!");
// Check if this game hasn't ended yet
assert(game_to_move.winner == N(none), "the game has ended!");
eos_assert(game_to_move.winner == N(none), "the game has ended!");
// Check if this game belongs to the action sender
assert(m.by == game_to_move.host || m.by == game_to_move.challenger, "this is not your game!");
eos_assert(m.by == game_to_move.host || m.by == game_to_move.challenger, "this is not your game!");
// Check if this is the action sender's turn
assert(m.by == game_to_move.turn, "it's not your turn yet!");
eos_assert(m.by == game_to_move.turn, "it's not your turn yet!");
// Check if user makes a valid movement
assert(is_valid_movement(m.mvt, game_to_move), "not a valid movement!");
eos_assert(is_valid_movement(m.mvt, game_to_move), "not a valid movement!");
// Fill the cell, 1 for host, 2 for challenger
bool is_movement_by_host = m.by == game_to_move.host;
......
#!/usr/bin/env bash
##########################################################################
# This is EOS bootstrapper script for Linux and OS X.
# This file was downloaded from https://github.com/EOSIO/eos
# Feel free to change this file to fit your needs.
##########################################################################
VERSION=1.0
ulimit -u
# Define directories.
WORK_DIR=$PWD
BUILD_DIR=${WORK_DIR}/build
TEMP_DIR=/tmp
# Target architectures
ARCH=$1
TARGET_ARCHS="ubuntu darwin"
# Check ARCH
if [[ $# > 2 ]]; then
echo ""
echo "Error: too many arguments"
exit 1
fi
if [[ $# < 1 ]]; then
echo ""
echo "Usage: bash build.sh TARGET [full|build]"
echo ""
echo "Targets: $TARGET_ARCHS"
exit 1
fi
if [[ $ARCH =~ [[:space:]] || ! $TARGET_ARCHS =~ (^|[[:space:]])$ARCH([[:space:]]|$) ]]; then
echo ""
echo ">>> WRONG ARCHITECTURE \"$ARCH\""
exit 1
fi
if [ -z "$2" ]; then
INSTALL_DEPS=1
else
if [ "$2" == "full" ]; then
INSTALL_DEPS=1
elif [ "$2" == "build" ]; then
INSTALL_DEPS=0
else
echo ">>> WRONG mode use full or build"
exit 1
fi
fi
echo ""
echo ">>> ARCHITECTURE \"$ARCH\""
if [ $ARCH == "ubuntu" ]; then
BOOST_ROOT=${HOME}/opt/boost_1_64_0
BINARYEN_BIN=${HOME}/opt/binaryen/bin
OPENSSL_ROOT_DIR=/usr/local/opt/openssl
OPENSSL_LIBRARIES=/usr/local/opt/openssl/lib
WASM_LLVM_CONFIG=${HOME}/opt/wasm/bin/llvm-config
fi
if [ $ARCH == "darwin" ]; then
OPENSSL_ROOT_DIR=/usr/local/opt/openssl
OPENSSL_LIBRARIES=/usr/local/opt/openssl/lib
BINARYEN_BIN=/usr/local/binaryen/bin/
WASM_LLVM_CONFIG=/usr/local/wasm/bin/llvm-config
fi
# Debug flags
COMPILE_EOS=1
COMPILE_CONTRACTS=1
# Define default arguments.
CMAKE_BUILD_TYPE=RelWithDebugInfo
# Install dependencies
if [ ${INSTALL_DEPS} == "1" ]; then
echo ">> Install dependencies"
. ${WORK_DIR}/scripts/install_dependencies.sh
fi
# Create the build dir
cd ${WORK_DIR}
mkdir -p ${BUILD_DIR}
cd ${BUILD_DIR}
CXX_COMPILER=clang++-4.0
C_COMPILER=clang-4.0
if [ $ARCH == "darwin" ]; then
CXX_COMPILER=clang++
C_COMPILER=clang
fi
# Build EOS
cmake -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_CXX_COMPILER=${CXX_COMPILER} -DCMAKE_C_COMPILER=${C_COMPILER} -DWASM_LLVM_CONFIG=${WASM_LLVM_CONFIG} -DBINARYEN_BIN=${BINARYEN_BIN} -DOPENSSL_ROOT_DIR=${OPENSSL_ROOT_DIR} -DOPENSSL_LIBRARIES=${OPENSSL_LIBRARIES} ..
make -j4
......@@ -63,13 +63,6 @@
CXX_COMPILER=clang++-4.0
C_COMPILER=clang-4.0
;;
"Red Hat Enterprise Linux Server")
printf "\n\tRed Hat Linux is Unsupported at this time.\nCheck back soon. Exiting now.\n\n"
exit 1
FILE=${WORK_DIR}/scripts/eosio_build_rhel.sh
CXX_COMPILER=clang++
C_COMPILER=clang
;;
"Fedora")
FILE=${WORK_DIR}/scripts/eosio_build_fedora.sh
CXX_COMPILER=g++
......
{
"initial_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"initial_timestamp": "2017-03-30T12:00:00",
"initial_parameters": {
"maintenance_interval": 86400,
......@@ -11,196 +12,5 @@
"immutable_parameters": {
"min_producer_count": 21
},
"initial_accounts": [{
"name": "inita",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initb",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initc",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initd",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "inite",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initf",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initg",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "inith",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initi",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initj",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initk",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initl",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initm",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initn",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "inito",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initp",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initq",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initr",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "inits",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initt",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initu",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
}],
"initial_producers": [{
"owner_name": "inita",
"block_signing_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV"
},{
"owner_name": "initb",
"block_signing_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV"
},{
"owner_name": "initc",
"block_signing_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV"
},{
"owner_name": "initd",
"block_signing_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV"
},{
"owner_name": "inite",
"block_signing_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV"
},{
"owner_name": "initf",
"block_signing_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV"
},{
"owner_name": "initg",
"block_signing_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV"
},{
"owner_name": "inith",
"block_signing_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV"
},{
"owner_name": "initi",
"block_signing_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV"
},{
"owner_name": "initj",
"block_signing_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV"
},{
"owner_name": "initk",
"block_signing_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV"
},{
"owner_name": "initl",
"block_signing_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV"
},{
"owner_name": "initm",
"block_signing_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV"
},{
"owner_name": "initn",
"block_signing_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV"
},{
"owner_name": "inito",
"block_signing_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV"
},{
"owner_name": "initp",
"block_signing_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV"
},{
"owner_name": "initq",
"block_signing_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV"
},{
"owner_name": "initr",
"block_signing_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV"
},{
"owner_name": "inits",
"block_signing_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV"
},{
"owner_name": "initt",
"block_signing_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV"
},{
"owner_name": "initu",
"block_signing_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV"
}],
"initial_chain_id": "0000000000000000000000000000000000000000000000000000000000000000"
}
Subproject commit d8e24895d5d3d019d5083ccafc9e290bdc96a32c
Subproject commit a0cf75ad7c39137ebf03b0f3b0b4e5b7f731296b
......@@ -29,13 +29,12 @@ add_library( eosio_chain
${HEADERS}
transaction_metadata.cpp)
transaction_metadata.cpp)
target_link_libraries( eosio_chain eos_utilities fc chainbase Logging IR WAST WASM Runtime )
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)
......
......@@ -102,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, _checktime_limit);
apply_context ncontext( mutable_controller, mutable_db, _inline_actions[i], trx_meta);
ncontext.exec();
append_results(move(ncontext.results));
}
......@@ -234,12 +234,8 @@ 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) {
void apply_context::checktime(uint32_t instruction_count) const {
if (trx_meta.processing_deadline && fc::time_point::now() > (*trx_meta.processing_deadline)) {
throw checktime_exceeded();
}
}
......@@ -259,4 +255,65 @@ const bytes& apply_context::get_packed_transaction() {
return trx_meta.packed_trx;
}
const char* to_string(contracts::table_key_type key_type) {
switch(key_type) {
case contracts::type_unassigned:
return "unassigned";
case contracts::type_i64:
return "i64";
case contracts::type_str:
return "str";
case contracts::type_i128i128:
return "i128i128";
case contracts::type_i64i64:
return "i64i64";
case contracts::type_i64i64i64:
return "i64i64i64";
default:
return "<unkown table_key_type>";
}
}
void apply_context::validate_table_key( const table_id_object& t_id, contracts::table_key_type key_type ) {
FC_ASSERT( t_id.key_type == contracts::table_key_type::type_unassigned || key_type == t_id.key_type,
"Table entry for ${code}-${scope}-${table} uses key type ${act_type} should have had type of ${exp_type}",
("code",t_id.code)("scope",t_id.scope)("table",t_id.table)("act_type",to_string(t_id.key_type))("exp_type", to_string(key_type)) );
}
void apply_context::validate_or_add_table_key( const table_id_object& t_id, contracts::table_key_type key_type ) {
if (t_id.key_type == contracts::table_key_type::type_unassigned)
mutable_db.modify( t_id, [&key_type]( auto& o) {
o.key_type = key_type;
});
else
FC_ASSERT( key_type == t_id.key_type,
"Table entry for ${code}-${scope}-${table} uses key type ${act_type} should have had type of ${exp_type}",
("code",t_id.code)("scope",t_id.scope)("table",t_id.table)("act_type",to_string(t_id.key_type))("exp_type", to_string(key_type)) );
}
template<>
contracts::table_key_type apply_context::get_key_type<contracts::key_value_object>() {
return contracts::table_key_type::type_i64;
}
template<>
contracts::table_key_type apply_context::get_key_type<contracts::keystr_value_object>() {
return contracts::table_key_type::type_str;
}
template<>
contracts::table_key_type apply_context::get_key_type<contracts::key128x128_value_object>() {
return contracts::table_key_type::type_i128i128;
}
template<>
contracts::table_key_type apply_context::get_key_type<contracts::key64x64_value_object>() {
return contracts::table_key_type::type_i64i64;
}
template<>
contracts::table_key_type apply_context::get_key_type<contracts::key64x64x64_value_object>() {
return contracts::table_key_type::type_i64i64i64;
}
} } /// eosio::chain
......@@ -39,16 +39,6 @@
namespace eosio { namespace chain {
#ifdef NDEBUG
const uint32_t chain_controller::default_received_block_transaction_execution_time_ms = 12;
const uint32_t chain_controller::default_transaction_execution_time_ms = 3;
const uint32_t chain_controller::default_create_block_transaction_execution_time_ms = 3;
#else
const uint32_t chain_controller::default_received_block_transaction_execution_time_ms = 72;
const uint32_t chain_controller::default_transaction_execution_time_ms = 18;
const uint32_t chain_controller::default_create_block_transaction_execution_time_ms = 18;
#endif
bool chain_controller::is_start_of_round( block_num_type block_num )const {
return 0 == (block_num % blocks_per_round());
}
......@@ -62,9 +52,7 @@ chain_controller::chain_controller( const chain_controller::controller_config& c
(cfg.read_only ? database::read_only : database::read_write),
cfg.shared_memory_size),
_block_log(cfg.block_log_dir),
_create_block_txn_execution_time(default_create_block_transaction_execution_time_ms * 1000),
_rcvd_block_txn_execution_time(default_received_block_transaction_execution_time_ms * 1000),
_txn_execution_time(default_transaction_execution_time_ms * 1000)
_limits(cfg.limits)
{
_initialize_indexes();
......@@ -293,6 +281,10 @@ static void record_locks_for_data_access(const vector<action_trace>& action_trac
transaction_trace chain_controller::_push_transaction( transaction_metadata&& data )
{
if (_limits.max_push_transaction_us.count() > 0) {
data.processing_deadline = fc::time_point::now() + _limits.max_push_transaction_us;
}
const transaction& trx = data.trx();
// If this is the first transaction pushed after applying a block, start a new undo session.
// This allows us to quickly rewind to the clean state of the head block, in case a new block arrives.
......@@ -586,6 +578,11 @@ static void validate_shard_locks(const vector<shard_lock>& locks, const string&
void chain_controller::__apply_block(const signed_block& next_block)
{ try {
optional<fc::time_point> processing_deadline;
if (!_currently_replaying_blocks && _limits.max_push_block_us.count() > 0) {
processing_deadline = fc::time_point::now() + _limits.max_push_block_us;
}
uint32_t skip = _skip_flags;
/*
......@@ -677,6 +674,7 @@ void chain_controller::__apply_block(const signed_block& next_block)
mtrx->shard_index = shard_index;
mtrx->allowed_read_locks.emplace(&shard.read_locks);
mtrx->allowed_write_locks.emplace(&shard.write_locks);
mtrx->processing_deadline = processing_deadline;
s_trace.transaction_traces.emplace_back(_apply_transaction(*mtrx));
record_locks_for_data_access(s_trace.transaction_traces.back().action_traces, used_read_locks, used_write_locks);
......@@ -713,7 +711,7 @@ void chain_controller::__apply_block(const signed_block& next_block)
FC_ASSERT(next_block.action_mroot == next_block_trace.calculate_action_merkle_root());
FC_ASSERT( transaction_metadata::calculate_transaction_merkle_root(input_metas) == next_block.transaction_mroot, "merkle root does not match" );
_finalize_block( next_block_trace );
_finalize_block( next_block_trace );
} FC_CAPTURE_AND_RETHROW( (next_block.block_num()) ) }
flat_set<public_key_type> chain_controller::get_required_keys(const transaction& trx,
......@@ -1041,8 +1039,15 @@ void chain_controller::_initialize_indexes() {
_db.add_index<permission_usage_index>();
_db.add_index<permission_link_index>();
_db.add_index<action_permission_index>();
_db.add_index<contracts::table_id_multi_index>();
_db.add_index<contracts::key_value_index>();
_db.add_index<contracts::index64_index>();
_db.add_index<contracts::index128_index>();
_db.add_index<contracts::keystr_value_index>();
_db.add_index<contracts::key128x128_value_index>();
_db.add_index<contracts::key64x64_value_index>();
......@@ -1087,37 +1092,9 @@ void chain_controller::_initialize_chain(contracts::chain_initializer& starter)
for (int i = 0; i < 0x10000; i++)
_db.create<block_summary_object>([&](block_summary_object&) {});
auto acts = starter.prepare_database(*this, _db);
// create a block for our genesis transaction to send to applied_irreversible_block below
signed_block block{};
block.producer = config::system_account_name;
block_trace btrace{block};
btrace.region_traces.emplace_back();
auto& rtrace = btrace.region_traces.back();
rtrace.cycle_traces.emplace_back();
auto& ctrace = rtrace.cycle_traces.back();
ctrace.shard_traces.emplace_back();
auto& strace = ctrace.shard_traces.back();
signed_transaction genesis_setup_transaction; // not actually signed, signature checking is skipped
genesis_setup_transaction.actions = move(acts);
block.input_transactions.emplace_back(genesis_setup_transaction);
ilog( "applying genesis transaction" );
with_skip_flags(skip_scope_check | skip_transaction_signatures | skip_authority_check | received_block | genesis_setup,
[&](){
transaction_metadata tmeta( packed_transaction(genesis_setup_transaction), chain_id_type(), initial_timestamp );
transaction_trace ttrace = __apply_transaction( tmeta );
strace.append(ttrace);
});
// TODO: Should we write this genesis block instead of faking it on startup?
strace.calculate_root();
applied_block(btrace);
applied_irreversible_block(block);
starter.prepare_database(*this, _db);
ilog( "done applying genesis transaction" );
ilog( "done initializing chain" );
});
}
} FC_CAPTURE_AND_RETHROW() }
......@@ -1290,7 +1267,12 @@ void chain_controller::update_last_irreversible_block()
return a->last_confirmed_block_num < b->last_confirmed_block_num;
});
uint32_t new_last_irreversible_block_num = producer_objs[offset]->last_confirmed_block_num - 1;
uint32_t new_last_irreversible_block_num = producer_objs[offset]->last_confirmed_block_num;
// TODO: right now the code cannot handle the head block being irreversible for reasons that are purely
// implementation details. We can and should remove this special case once the rest of the logic is fixed.
if (producer_objs.size() == 1) {
new_last_irreversible_block_num -= 1;
}
if (new_last_irreversible_block_num > dpo.last_irreversible_block_num) {
......@@ -1425,7 +1407,7 @@ static void log_handled_exceptions(const transaction& trx) {
transaction_trace chain_controller::__apply_transaction( transaction_metadata& meta ) {
transaction_trace result(meta.id);
for (const auto &act : meta.trx().actions) {
apply_context context(*this, _db, act, meta, txn_execution_time());
apply_context context(*this, _db, act, meta);
context.exec();
fc::move_append(result.action_traces, std::move(context.results.applied_actions));
fc::move_append(result.deferred_transactions, std::move(context.results.generated_transactions));
......@@ -1478,7 +1460,7 @@ transaction_trace chain_controller::_apply_error( transaction_metadata& meta ) {
try {
auto temp_session = _db.start_undo_session(true);
apply_context context(*this, _db, etrx.actions.front(), meta, txn_execution_time());
apply_context context(*this, _db, etrx.actions.front(), meta);
context.exec();
fc::move_append(result.action_traces, std::move(context.results.applied_actions));
fc::move_append(result.deferred_transactions, std::move(context.results.generated_transactions));
......@@ -1642,20 +1624,4 @@ const apply_handler* chain_controller::find_apply_handler( account_name receiver
return nullptr;
}
void chain_controller::set_txn_execution_times(uint32_t create_block_txn_execution_time, uint32_t rcvd_block_txn_execution_time, uint32_t txn_execution_time)
{
_create_block_txn_execution_time = create_block_txn_execution_time;
_rcvd_block_txn_execution_time = rcvd_block_txn_execution_time;
_txn_execution_time = txn_execution_time;
}
uint32_t chain_controller::txn_execution_time() const
{
return _skip_flags & received_block
? _rcvd_block_txn_execution_time
: (_skip_flags && created_block
? _create_block_txn_execution_time
: _txn_execution_time);
}
} } /// eosio::chain
......@@ -3,6 +3,7 @@
* @copyright defined in eos/LICENSE.txt
*/
#include <eosio/chain/contracts/abi_serializer.hpp>
#include <eosio/chain/contracts/chain_initializer.hpp>
#include <eosio/chain/contracts/types.hpp>
#include <eosio/chain/authority.hpp>
#include <eosio/chain/chain_config.hpp>
......@@ -129,6 +130,17 @@ namespace eosio { namespace chain { namespace contracts {
FC_ASSERT( actions.size() == abi.actions.size() );
FC_ASSERT( tables.size() == abi.tables.size() );
}
void abi_serializer::append_system_abi(account_name account, abi_def& abi) {
if ( account == eosio::chain::config::system_account_name ) {
abi_def eos_abi = chain_initializer::eos_contract_abi();
abi.actions.insert(abi.actions.end(), eos_abi.actions.cbegin(), eos_abi.actions.cend());
abi.structs.insert(abi.structs.end(), eos_abi.structs.cbegin(), eos_abi.structs.cend());
abi.tables.insert(abi.tables.end(), eos_abi.tables.cbegin(), eos_abi.tables.cend());
abi.types.insert(abi.types.end(), eos_abi.types.cbegin(), eos_abi.types.cend());
}
}
bool abi_serializer::is_builtin_type(const type_name& type)const {
return built_in_types.find(type) != built_in_types.end();
......
......@@ -8,10 +8,6 @@
#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>
......@@ -155,12 +151,6 @@ abi_def chain_initializer::eos_contract_abi()
});
// DATABASE RECORDS
eos_abi.structs.emplace_back( struct_def {
"account", "", {
{"key", "name"},
{"balance", "uint64"},
}
});
eos_abi.structs.emplace_back( struct_def {
"pending_recovery", "", {
......@@ -171,15 +161,6 @@ abi_def chain_initializer::eos_contract_abi()
}
});
eos_abi.tables.emplace_back( table_def {
"currency", "i64", {
"key"
}, {
"name"
},
"account"
});
eos_abi.tables.emplace_back( table_def {
"recovery", "i64", {
"account",
......@@ -193,14 +174,8 @@ abi_def chain_initializer::eos_contract_abi()
return eos_abi;
}
// forward declared method from eosio contract
void intialize_eosio_tokens(chainbase::database& db, const account_name& system_account, share_type initial_tokens);
std::vector<action> chain_initializer::prepare_database( chain_controller& chain,
void chain_initializer::prepare_database( chain_controller& chain,
chainbase::database& db) {
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) {
db.create<account_object>([this, &name](account_object& a) {
......@@ -209,7 +184,7 @@ std::vector<action> chain_initializer::prepare_database( chain_controller& chain
a.privileged = true;
if( name == config::system_account_name ) {
a.set_abi(eos_contract_abi());
a.set_abi(abi_def());
}
});
const auto& owner = db.create<permission_object>([&](permission_object& p) {
......@@ -239,40 +214,6 @@ std::vector<action> chain_initializer::prepare_database( chain_controller& chain
};
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)
});
messages_to_process.emplace_back(move(message));
}
// 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) {
db.create<account_object>([this, &name](account_object& a) {
......@@ -299,8 +240,6 @@ std::vector<action> chain_initializer::prepare_database( chain_controller& chain
create_special_account(config::nobody_account_name, empty_authority, empty_authority);
create_special_account(config::producers_account_name, empty_authority, active_producers_authority);
return messages_to_process;
}
} } } // namespace eosio::chain::contracts
......@@ -116,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 ) {
......
......@@ -17,7 +17,6 @@ namespace eosio { namespace chain {
*/
struct chain_config {
share_type producer_pay;
uint32_t target_block_size;
uint32_t max_block_size;
......@@ -46,7 +45,6 @@ inline bool operator!=(const chain_config& a, const chain_config& b) { return !(
} } // namespace eosio::chain
FC_REFLECT(eosio::chain::chain_config,
(producer_pay)
(target_block_size)
(max_block_size)
(target_block_acts_per_scope)
......
......@@ -62,6 +62,11 @@ namespace eosio { namespace chain {
*/
class chain_controller : public boost::noncopyable {
public:
struct runtime_limits {
fc::microseconds max_push_block_us = fc::microseconds(-1);
fc::microseconds max_push_transaction_us = fc::microseconds(-1);
};
struct controller_config {
path block_log_dir = config::default_block_log_dir;
path shared_memory_dir = config::default_shared_memory_dir;
......@@ -69,6 +74,7 @@ namespace eosio { namespace chain {
bool read_only = false;
std::vector<signal<void(const signed_block&)>::slot_type> applied_irreversible_block_callbacks;
contracts::genesis_state_type genesis;
runtime_limits limits;
};
chain_controller( const controller_config& cfg );
......@@ -294,18 +300,9 @@ 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;
......@@ -442,9 +439,7 @@ namespace eosio { namespace chain {
wasm_cache _wasm_cache;
uint32_t _create_block_txn_execution_time;
uint32_t _rcvd_block_txn_execution_time;
uint32_t _txn_execution_time;
runtime_limits _limits;
};
} }
......@@ -18,7 +18,6 @@ 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);
......@@ -63,9 +62,6 @@ const static uint32_t default_max_gen_trx_count = 16; ///< the number of
const static uint32_t producers_authority_threshold = 14;
const static uint32_t rate_limiting_precision = 1000*1000;
const static share_type default_elected_pay = asset(100).amount;
const static share_type default_min_eos_balance = asset(100).amount;
const static uint16_t max_recursion_depth = 6;
/**
......@@ -80,9 +76,7 @@ const static int producer_repititions = 12;
//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;
const static auto staked_balance_cooldown_sec = fc::days(3).to_seconds();
} } } // namespace eosio::chain::config
template<typename Number>
......
......@@ -5,6 +5,7 @@
#pragma once
#include <eosio/chain/contracts/types.hpp>
#include <eosio/chain/transaction.hpp>
#include <eosio/chain/block.hpp>
#include <fc/variant_object.hpp>
......@@ -72,11 +73,12 @@ struct abi_serializer {
}
template<typename Vec>
static bool to_abi(const Vec& abi_vec, abi_def& abi)
static bool to_abi(account_name account, const Vec& abi_vec, abi_def& abi)
{
if( !is_empty_abi(abi_vec) ) { /// 4 == packsize of empty Abi
if( !is_empty_abi(abi_vec) || account == eosio::chain::config::system_account_name ) { /// 4 == packsize of empty Abi
fc::datastream<const char*> ds( abi_vec.data(), abi_vec.size() );
fc::raw::unpack( ds, abi );
append_system_abi(account, abi);
return true;
}
return false;
......@@ -84,6 +86,7 @@ struct abi_serializer {
private:
void binary_to_variant(const type_name& type, fc::datastream<const char*>& stream, fc::mutable_variant_object& obj)const;
static void append_system_abi(account_name account, abi_def& abi);
};
namespace impl {
......@@ -97,7 +100,10 @@ namespace impl {
std::is_same<T, packed_transaction>::value ||
std::is_same<T, action>::value ||
std::is_same<T, transaction_trace>::value ||
std::is_same<T, action_trace>::value;
std::is_same<T, action_trace>::value ||
std::is_same<T, shard_summary>::value ||
std::is_same<T, region_summary>::value ||
std::is_base_of<signed_block_summary, T>:: value;
}
/**
......
......@@ -22,8 +22,7 @@ namespace eosio { namespace chain { namespace contracts {
void register_types(chain::chain_controller& chain, chainbase::database& db);
std::vector<action> prepare_database(chain::chain_controller& chain, chainbase::database& db);
void prepare_database(chain::chain_controller& chain, chainbase::database& db);
static abi_def eos_contract_abi();
......
......@@ -16,34 +16,7 @@
namespace eosio { namespace chain { namespace contracts {
struct genesis_state_type {
struct initial_account_type {
initial_account_type(const string& name = string(),
uint64_t staking_bal = 0,
uint64_t liquid_bal = 0,
const public_key_type& owner_key = public_key_type(),
const public_key_type& active_key = public_key_type())
: name(name), staking_balance(staking_bal), liquid_balance(liquid_bal),
owner_key(owner_key),
active_key(active_key == public_key_type()? owner_key : active_key)
{}
string name;
asset staking_balance;
asset liquid_balance;
public_key_type owner_key;
public_key_type active_key;
};
struct initial_producer_type {
initial_producer_type(const string& name = string(),
const public_key_type& signing_key = public_key_type())
: owner_name(name), block_signing_key(signing_key)
{}
/// Must correspond to one of the initial accounts
string owner_name;
public_key_type block_signing_key;
};
chain_config initial_configuration = {
.producer_pay = config::default_elected_pay,
.target_block_size = config::default_target_block_size,
.max_block_size = config::default_max_block_size,
.target_block_acts_per_scope = config::default_target_block_acts_per_scope,
......@@ -62,10 +35,6 @@ 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;
/**
* Temporary, will be moved elsewhere.
......@@ -82,11 +51,6 @@ struct genesis_state_type {
} } } // namespace eosio::contracts
FC_REFLECT(eosio::chain::contracts::genesis_state_type::initial_account_type,
(name)(staking_balance)(liquid_balance)(owner_key)(active_key))
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_key)(initial_configuration)(initial_accounts)
(initial_producers)(initial_chain_id))
(initial_timestamp)(initial_key)(initial_configuration)(initial_chain_id))
......@@ -103,22 +103,6 @@ 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 newaccount {
account_name creator;
account_name name;
......
......@@ -33,6 +33,7 @@ namespace eosio { namespace chain {
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);
......@@ -55,6 +56,7 @@ namespace eosio { namespace chain {
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;
......
......@@ -61,6 +61,9 @@ class transaction_metadata {
}
}
// limits
optional<time_point> processing_deadline;
static digest_type calculate_transaction_merkle_root( const vector<transaction_metadata>& metas );
private:
const transaction* _trx;
......
......@@ -121,6 +121,8 @@ namespace eosio { namespace chain {
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,
......@@ -174,6 +176,8 @@ FC_REFLECT_ENUM(eosio::chain::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)
......
......@@ -6,6 +6,14 @@ namespace IR {
namespace eosio { namespace chain {
namespace wasm_constraints {
//Be aware that some of these are required to be a multiple of some internal number
constexpr unsigned maximum_linear_memory = 1024*1024; //bytes
constexpr unsigned maximum_mutable_globals = 1024; //bytes
constexpr unsigned maximum_table_elements = 1024; //elements
constexpr unsigned maximum_linear_memory_init = 64*1024; //bytes
}
//Throws if something in the module violates
void validate_eosio_wasm_constraints(const IR::Module& m);
......
......@@ -89,7 +89,7 @@ struct array_ptr {
static T* validated_ptr (wasm_interface& wasm, U32 ptr, size_t length) {
auto mem = getDefaultMemory(intrinsics_accessor::get_context(wasm).code.instance);
if(!mem || ptr + length >= IR::numBytesPerPage*Runtime::getMemoryNumPages(mem))
if(!mem || ptr + length > IR::numBytesPerPage*Runtime::getMemoryNumPages(mem))
Runtime::causeException(Exception::Cause::accessViolation);
return (T*)(getMemoryBaseAddress(mem) + ptr);
......
......@@ -29,7 +29,7 @@ struct eosio_constraints_visitor : public nop_opcode_visitor {
// an 8 byte data type, that's fine. There will be enough of a guard on the end
// of 1MiB where it's not a problem
void fail_large_offset(U32 offset) {
if(offset >= 1024*1024)
if(offset >= wasm_constraints::maximum_linear_memory)
FC_THROW_EXCEPTION(wasm_execution_error, "Smart contract used an invalid large memory store/load offset");
}
void i32_load (LoadOrStoreImm<2> imm) override { fail_large_offset(imm.offset); }
......@@ -65,18 +65,18 @@ struct eosio_constraints_visitor : public nop_opcode_visitor {
};
void validate_eosio_wasm_constraints(const Module& m) {
if(m.memories.defs.size() && m.memories.defs[0].type.size.min > 16)
FC_THROW_EXCEPTION(wasm_execution_error, "Smart contract initial memory size must be less than or equal to 1MiB");
if(m.memories.defs.size() && m.memories.defs[0].type.size.min > wasm_constraints::maximum_linear_memory/(64*1024))
FC_THROW_EXCEPTION(wasm_execution_error, "Smart contract initial memory size must be less than or equal to ${k}KiB", ("k", wasm_constraints::maximum_linear_memory/1024));
for(const DataSegment& ds : m.dataSegments) {
if(ds.baseOffset.type != InitializerExpression::Type::i32_const)
FC_THROW_EXCEPTION(wasm_execution_error, "Smart contract has unexpected memory base offset type");
if(static_cast<uint32_t>(ds.baseOffset.i32) + ds.data.size() > 64*1024)
FC_THROW_EXCEPTION(wasm_execution_error, "Smart contract data segments must lie in first 64KiB");
if(static_cast<uint32_t>(ds.baseOffset.i32) + ds.data.size() > wasm_constraints::maximum_linear_memory_init)
FC_THROW_EXCEPTION(wasm_execution_error, "Smart contract data segments must lie in first ${k}KiB", ("k", wasm_constraints::maximum_linear_memory_init/1024));
}
if(m.tables.defs.size() && m.tables.defs[0].type.size.min > 1024)
FC_THROW_EXCEPTION(wasm_execution_error, "Smart contract table limited to 1024 elements");
if(m.tables.defs.size() && m.tables.defs[0].type.size.min > wasm_constraints::maximum_table_elements)
FC_THROW_EXCEPTION(wasm_execution_error, "Smart contract table limited to ${t} elements", ("t", wasm_constraints::maximum_table_elements));
unsigned mutable_globals_total_size = 0;
for(const GlobalDef& global_def : m.globals.defs) {
......@@ -94,8 +94,8 @@ void validate_eosio_wasm_constraints(const Module& m) {
mutable_globals_total_size += 4;
}
}
if(mutable_globals_total_size > 1024)
FC_THROW_EXCEPTION(wasm_execution_error, "Smart contract has more than 1KiB of mutable globals");
if(mutable_globals_total_size > wasm_constraints::maximum_mutable_globals)
FC_THROW_EXCEPTION(wasm_execution_error, "Smart contract has more than ${k} bytes of mutable globals", ("k", wasm_constraints::maximum_mutable_globals));
//Some of the OperatorDecoderStream users inside of WAVM track the control stack and quit parsing from
// OperatorDecoderStream when the control stack is empty (since that would indicate unreachable code).
......
此差异已折叠。
......@@ -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.
*
......
......@@ -54,11 +54,12 @@ namespace fc {
const T& min( const T& a, const T& b ) { return a < b ? a: b; }
constexpr size_t const_strlen(const char* str) {
if (*str == '\0') {
return 0;
size_t res = 0;
while (*str != '\0') {
++res;
++str;
}
return 1 + const_strlen(str+1);
return res;
}
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册