提交 bdc2a324 编写于 作者: D Daniel Larimer

Moving type definition over to code generation

- update fc to use EOS local repository on github
- add type library in to build process
上级 2dcb6c45
[submodule "libraries/fc"] [submodule "libraries/fc"]
path = libraries/fc path = libraries/fc
url = https://github.com/bitshares/bitshares-fc.git url = https://github.com/eosio/fc.git
ignore = dirty ignore = dirty
[submodule "libraries/chainbase"] [submodule "libraries/chainbase"]
path = libraries/chainbase path = libraries/chainbase
......
add_subdirectory( fc ) add_subdirectory( fc )
add_subdirectory( chainbase ) add_subdirectory( chainbase )
add_subdirectory( wren ) add_subdirectory( wren )
#add_subdirectory( types ) add_subdirectory( types )
add_subdirectory( deterministic_openssl_rand ) add_subdirectory( deterministic_openssl_rand )
add_subdirectory( chain ) add_subdirectory( chain )
add_subdirectory( egenesis ) add_subdirectory( egenesis )
......
...@@ -5,7 +5,6 @@ add_library( eos_chain ...@@ -5,7 +5,6 @@ add_library( eos_chain
database.cpp database.cpp
fork_database.cpp fork_database.cpp
types.cpp
transaction.cpp transaction.cpp
block.cpp block.cpp
...@@ -18,7 +17,7 @@ add_library( eos_chain ...@@ -18,7 +17,7 @@ add_library( eos_chain
${PROTOCOL_HEADERS} ${PROTOCOL_HEADERS}
) )
target_link_libraries( eos_chain fc chainbase ) target_link_libraries( eos_chain fc chainbase eos_types )
target_include_directories( eos_chain target_include_directories( eos_chain
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_BINARY_DIR}/include" ) PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_BINARY_DIR}/include" )
......
...@@ -513,9 +513,11 @@ void database::validate_referenced_accounts(const signed_transaction& trx)const ...@@ -513,9 +513,11 @@ void database::validate_referenced_accounts(const signed_transaction& trx)const
const account_name* previous_notify_account = nullptr; const account_name* previous_notify_account = nullptr;
for(const auto& current_notify_account : msg.notify) { for(const auto& current_notify_account : msg.notify) {
get_account(current_notify_account); get_account(current_notify_account);
if(previous_notify_account) if(previous_notify_account) {
EOS_ASSERT(current_notify_account < *previous_notify_account, message_validate_exception, EOS_ASSERT(current_notify_account < *previous_notify_account, message_validate_exception,
"Message notify accounts out of order. Possibly a bug in the wallet?"); "Message notify accounts out of order. Possibly a bug in the wallet?");
}
EOS_ASSERT(current_notify_account != msg.sender, message_validate_exception, EOS_ASSERT(current_notify_account != msg.sender, message_validate_exception,
"Message sender is listed in accounts to notify. Possibly a bug in the wallet?"); "Message sender is listed in accounts to notify. Possibly a bug in the wallet?");
EOS_ASSERT(current_notify_account != msg.recipient, message_validate_exception, EOS_ASSERT(current_notify_account != msg.recipient, message_validate_exception,
...@@ -745,7 +747,7 @@ void database::init_genesis(const genesis_state_type& genesis_state) ...@@ -745,7 +747,7 @@ void database::init_genesis(const genesis_state_type& genesis_state)
create<account_object>([&acct](account_object& a) { create<account_object>([&acct](account_object& a) {
a.name = acct.name.c_str(); a.name = acct.name.c_str();
a.balance = acct.balance; a.balance = acct.balance;
idump((acct.name)(a.balance)); // idump((acct.name)(a.balance));
// a.active_key = acct.active_key; // a.active_key = acct.active_key;
// a.owner_key = acct.owner_key; // a.owner_key = acct.owner_key;
}); });
......
...@@ -51,9 +51,9 @@ namespace eos { namespace chain { ...@@ -51,9 +51,9 @@ namespace eos { namespace chain {
return *this; return *this;
} }
uint32_t threshold = 0; UInt32 threshold = 0;
shared_vector<PermissionLevel> accounts; shared_vector<AccountPermissionWeight> accounts;
shared_vector<KeyPermission> keys; shared_vector<KeyPermissionWeight> keys;
}; };
class account_object : public chainbase::object<account_object_type, account_object> class account_object : public chainbase::object<account_object_type, account_object>
...@@ -61,11 +61,11 @@ namespace eos { namespace chain { ...@@ -61,11 +61,11 @@ namespace eos { namespace chain {
OBJECT_CTOR(account_object) OBJECT_CTOR(account_object)
id_type id; id_type id;
account_name name; AccountName name;
uint64_t balance = 0; Asset balance;
uint64_t votes = 0; UInt64 votes = 0;
uint64_t converting_votes = 0; UInt64 converting_votes = 0;
time_point_sec last_vote_conversion; Time last_vote_conversion;
}; };
struct by_name; struct by_name;
...@@ -73,7 +73,7 @@ namespace eos { namespace chain { ...@@ -73,7 +73,7 @@ namespace eos { namespace chain {
account_object, account_object,
indexed_by< indexed_by<
ordered_unique<tag<by_id>, member<account_object, account_object::id_type, &account_object::id>>, ordered_unique<tag<by_id>, member<account_object, account_object::id_type, &account_object::id>>,
ordered_unique<tag<by_name>, member<account_object, account_name, &account_object::name>> ordered_unique<tag<by_name>, member<account_object, AccountName, &account_object::name>>
> >
>; >;
......
#pragma once #pragma once
#include <eos/chain/types.hpp> #include <eos/chain/types.hpp>
#include <eos/types/generated.hpp>
namespace eos { namespace chain { namespace eos {
inline bool operator < ( const AccountPermission& a, const AccountPermission& b ) {
struct PermissionLevel { return std::tie( a.account, a.permission ) < std::tie( b.account, b.permission );
account_name account; }
permission_name level;
uint16_t weight; /**
}; * Makes sure all keys are unique and sorted and all account permissions are unique and sorted
*/
struct KeyPermission { inline bool validate( eos::Authority& auth ) {
public_key_type key; const KeyPermissionWeight* prev = nullptr;
uint16_t weight; for( const auto& k : auth.keys ) {
}; if( !prev ) prev = &k;
else if( prev->key < k.key ) return false;
struct Authority {
uint32_t threshold = 0;
vector<PermissionLevel> accounts;
vector<KeyPermission> keys;
bool validate() const {
if (threshold == 0)
return false;
uint32_t score = 0;
for (const auto& p : accounts)
score += p.weight;
for (const auto& p : keys)
score += p.weight;
return score >= threshold;
} }
set<account_name> referenced_accounts() const { const AccountPermissionWeight* pa = nullptr;
set<account_name> results; for( const auto& a : auth.accounts ) {
std::transform(accounts.begin(), accounts.end(), std::inserter(results, results.begin()), if( !pa ) pa = &a;
[](const PermissionLevel& p) { return p.account; }); else if( pa->permission < a.permission ) return false;
return results;
} }
}; return true;
}
} } // eos::chain }
FC_REFLECT(eos::chain::PermissionLevel, (account)(level)(weight))
FC_REFLECT(eos::chain::KeyPermission, (key)(weight))
FC_REFLECT(eos::chain::Authority, (threshold)(accounts)(keys))
...@@ -47,7 +47,7 @@ struct genesis_state_type { ...@@ -47,7 +47,7 @@ struct genesis_state_type {
active_key(active_key == public_key_type()? owner_key : active_key) active_key(active_key == public_key_type()? owner_key : active_key)
{} {}
string name; string name;
uint64_t balance = 0; Asset balance;
public_key_type owner_key; public_key_type owner_key;
public_key_type active_key; public_key_type active_key;
}; };
......
...@@ -94,7 +94,6 @@ namespace eos { namespace chain { ...@@ -94,7 +94,6 @@ namespace eos { namespace chain {
/// Calculate the digest used for signature validation /// Calculate the digest used for signature validation
digest_type sig_digest(const chain_id_type& chain_id)const; digest_type sig_digest(const chain_id_type& chain_id)const;
void set_expiration(fc::time_point_sec expiration_time);
void set_reference_block(const block_id_type& reference_block); void set_reference_block(const block_id_type& reference_block);
bool verify_reference_block(const block_id_type& reference_block)const; bool verify_reference_block(const block_id_type& reference_block)const;
}; };
......
...@@ -26,9 +26,6 @@ ...@@ -26,9 +26,6 @@
#include <fc/io/varint.hpp> #include <fc/io/varint.hpp>
#include <fc/io/enum_type.hpp> #include <fc/io/enum_type.hpp>
#include <fc/crypto/sha224.hpp> #include <fc/crypto/sha224.hpp>
#include <fc/crypto/elliptic.hpp>
#include <fc/reflect/reflect.hpp>
#include <fc/reflect/variant.hpp>
#include <fc/optional.hpp> #include <fc/optional.hpp>
#include <fc/safe.hpp> #include <fc/safe.hpp>
#include <fc/container/flat.hpp> #include <fc/container/flat.hpp>
...@@ -39,6 +36,10 @@ ...@@ -39,6 +36,10 @@
#include <fc/smart_ref_fwd.hpp> #include <fc/smart_ref_fwd.hpp>
#include <fc/crypto/ripemd160.hpp> #include <fc/crypto/ripemd160.hpp>
#include <fc/fixed_string.hpp> #include <fc/fixed_string.hpp>
#include <eos/types/native.hpp>
#include <eos/types/PublicKey.hpp>
#include <eos/types/Asset.hpp>
#include <eos/types/generated.hpp>
#include <memory> #include <memory>
#include <vector> #include <vector>
...@@ -105,12 +106,14 @@ namespace eos { namespace chain { ...@@ -105,12 +106,14 @@ namespace eos { namespace chain {
using private_key_type = fc::ecc::private_key; using private_key_type = fc::ecc::private_key;
using chain_id_type = fc::sha256; using chain_id_type = fc::sha256;
typedef fc::fixed_string<> account_name;
typedef fc::fixed_string<> permission_name; using eos::AccountName;
typedef fc::fixed_string<> message_type; using account_name = eos::AccountName;
//using account_name = std::string; using eos::PermissionName;
//using message_type = std::string; using permission_name = eos::PermissionName;
//using permission_name = std::string; using message_name = eos::TypeName;
using message_type = message_name;
/** /**
* List all object types from all namespaces here so they can * List all object types from all namespaces here so they can
...@@ -150,40 +153,11 @@ namespace eos { namespace chain { ...@@ -150,40 +153,11 @@ namespace eos { namespace chain {
using signature_type = fc::ecc::compact_signature; using signature_type = fc::ecc::compact_signature;
using weight_type = uint16_t; using weight_type = uint16_t;
struct public_key_type using public_key_type = eos::PublicKey;
{
struct binary_key
{
binary_key() {}
uint32_t check = 0;
fc::ecc::public_key_data data;
};
fc::ecc::public_key_data key_data;
public_key_type();
public_key_type( const fc::ecc::public_key_data& data );
public_key_type( const fc::ecc::public_key& pubkey );
explicit public_key_type( const std::string& base58str );
operator fc::ecc::public_key_data() const;
operator fc::ecc::public_key() const;
explicit operator std::string() const;
friend bool operator == ( const public_key_type& p1, const fc::ecc::public_key& p2);
friend bool operator == ( const public_key_type& p1, const public_key_type& p2);
friend bool operator != ( const public_key_type& p1, const public_key_type& p2);
friend bool operator < ( const public_key_type& p1, const public_key_type& p2);
bool is_valid_v1( const std::string& base58str );
};
} } // eos::chain } } // eos::chain
namespace fc
{
void to_variant( const eos::chain::public_key_type& var, fc::variant& vo );
void from_variant( const fc::variant& var, eos::chain::public_key_type& vo );
}
FC_REFLECT( eos::chain::public_key_type, (key_data) )
FC_REFLECT( eos::chain::public_key_type::binary_key, (data)(check) )
FC_REFLECT(eos::chain::account_id_type, (_id)) FC_REFLECT(eos::chain::account_id_type, (_id))
FC_REFLECT(eos::chain::producer_id_type, (_id)) FC_REFLECT(eos::chain::producer_id_type, (_id))
......
...@@ -62,10 +62,6 @@ signature_type eos::chain::signed_transaction::sign(const private_key_type& key, ...@@ -62,10 +62,6 @@ signature_type eos::chain::signed_transaction::sign(const private_key_type& key,
return key.sign_compact(enc.result()); return key.sign_compact(enc.result());
} }
void transaction::set_expiration( fc::time_point_sec expiration_time ) {
expiration = expiration_time;
}
void transaction::set_reference_block(const block_id_type& reference_block) { void transaction::set_reference_block(const block_id_type& reference_block) {
ref_block_num = fc::endian_reverse_u32(reference_block._hash[0]); ref_block_num = fc::endian_reverse_u32(reference_block._hash[0]);
ref_block_prefix = reference_block._hash[1]; ref_block_prefix = reference_block._hash[1];
......
Subproject commit 1f41494f360a1800fc967d647631cf64fdc549ee Subproject commit cadc521fe41282487e047cc3030b2eb8231202c2
...@@ -10,7 +10,8 @@ set(SOURCES node.cpp ...@@ -10,7 +10,8 @@ set(SOURCES node.cpp
add_library( eos_net ${SOURCES} ${HEADERS} ) add_library( eos_net ${SOURCES} ${HEADERS} )
target_link_libraries( eos_net target_link_libraries( eos_net
PUBLIC fc chainbase appbase ) PUBLIC fc chainbase appbase eos_types)
target_include_directories( eos_net target_include_directories( eos_net
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include"
PRIVATE "${CMAKE_SOURCE_DIR}/libraries/chain/include" PRIVATE "${CMAKE_SOURCE_DIR}/libraries/chain/include"
......
#include <eos/types/Asset.hpp> #include <eos/types/Asset.hpp>
#include <boost/rational.hpp> #include <boost/rational.hpp>
#include <boost/multiprecision/cpp_int.hpp> #include <boost/multiprecision/cpp_int.hpp>
#include <fc/reflect/variant.hpp>
namespace EOS { namespace eos {
typedef boost::multiprecision::int128_t int128_t; typedef boost::multiprecision::int128_t int128_t;
uint8_t Asset::decimals()const { uint8_t Asset::decimals()const {
...@@ -14,7 +15,7 @@ namespace EOS { ...@@ -14,7 +15,7 @@ namespace EOS {
a[0] = d; a[0] = d;
} }
std::string Asset::symbol_name()const { String Asset::symbol_name()const {
auto a = (const char*)&symbol; auto a = (const char*)&symbol;
assert( a[7] == 0 ); assert( a[7] == 0 );
return &a[1]; return &a[1];
...@@ -32,21 +33,21 @@ namespace EOS { ...@@ -32,21 +33,21 @@ namespace EOS {
return table[ decimals() ]; return table[ decimals() ];
} }
string Asset::toString()const { String Asset::toString()const {
string result = fc::to_string(amount.value / precision()); String result = fc::to_string( static_cast<int64_t>(amount) / precision());
if( decimals() ) if( decimals() )
{ {
auto fract = amount.value % precision(); auto fract = static_cast<int64_t>(amount) % precision();
result += "." + fc::to_string(precision() + fract).erase(0,1); result += "." + fc::to_string(precision() + fract).erase(0,1);
} }
return result + " " + symbol_name(); return result + " " + symbol_name();
} }
Asset Asset::fromString( const string& from ) Asset Asset::fromString( const String& from )
{ {
try try
{ {
string s = fc::trim( from ); String s = fc::trim( from );
auto space_pos = s.find( " " ); auto space_pos = s.find( " " );
auto dot_pos = s.find( "." ); auto dot_pos = s.find( "." );
...@@ -57,15 +58,15 @@ namespace EOS { ...@@ -57,15 +58,15 @@ namespace EOS {
auto intpart = s.substr( 0, dot_pos ); auto intpart = s.substr( 0, dot_pos );
result.amount = fc::to_int64(intpart); result.amount = fc::to_int64(intpart);
std::string fractpart; String fractpart;
if( dot_pos != std::string::npos ) if( dot_pos != String::npos )
{ {
auto fractpart = "1" + s.substr( dot_pos + 1, space_pos - dot_pos - 1 ); auto fractpart = "1" + s.substr( dot_pos + 1, space_pos - dot_pos - 1 );
result.set_decimals( fractpart.size() - 1 ); result.set_decimals( fractpart.size() - 1 );
result.amount.value *= result.precision(); result.amount *= Int64(result.precision());
result.amount.value += fc::to_int64(fractpart); result.amount += Int64(fc::to_int64(fractpart));
result.amount.value -= result.precision(); result.amount -= Int64(result.precision());
} }
auto symbol = s.substr( space_pos + 1 ); auto symbol = s.substr( space_pos + 1 );
...@@ -82,8 +83,8 @@ namespace EOS { ...@@ -82,8 +83,8 @@ namespace EOS {
if( std::tie( a.base.symbol, a.quote.symbol ) != std::tie( b.base.symbol, b.quote.symbol ) ) if( std::tie( a.base.symbol, a.quote.symbol ) != std::tie( b.base.symbol, b.quote.symbol ) )
return false; return false;
const auto amult = uint128_t( b.quote.amount.value ) * a.base.amount.value; const auto amult = UInt128( b.quote.amount ) * UInt128(a.base.amount);
const auto bmult = uint128_t( a.quote.amount.value ) * b.base.amount.value; const auto bmult = UInt128( a.quote.amount ) * UInt128(b.base.amount);
return amult == bmult; return amult == bmult;
} }
...@@ -95,8 +96,8 @@ namespace EOS { ...@@ -95,8 +96,8 @@ namespace EOS {
if( a.quote.symbol < b.quote.symbol ) return true; if( a.quote.symbol < b.quote.symbol ) return true;
if( a.quote.symbol > b.quote.symbol ) return false; if( a.quote.symbol > b.quote.symbol ) return false;
const auto amult = uint128_t( b.quote.amount.value ) * a.base.amount.value; const auto amult = UInt128( b.quote.amount ) * UInt128(a.base.amount);
const auto bmult = uint128_t( a.quote.amount.value ) * b.base.amount.value; const auto bmult = UInt128( a.quote.amount ) * UInt128(b.base.amount);
return amult < bmult; return amult < bmult;
} }
...@@ -125,17 +126,16 @@ namespace EOS { ...@@ -125,17 +126,16 @@ namespace EOS {
{ {
if( a.symbol_name() == b.base.symbol_name() ) if( a.symbol_name() == b.base.symbol_name() )
{ {
FC_ASSERT( b.base.amount.value > 0 ); FC_ASSERT( static_cast<int64_t>(b.base.amount) > 0 );
uint128_t result = (uint128_t(a.amount.value) * b.quote.amount.value)/b.base.amount.value; auto result = (UInt128(a.amount) * UInt128(b.quote.amount))/UInt128(b.base.amount);
FC_ASSERT( result.hi == 0 ); return Asset( Int64(result), b.quote.symbol );
return Asset( result.to_uint64(), b.quote.symbol );
} }
else if( a.symbol_name() == b.quote.symbol_name() ) else if( a.symbol_name() == b.quote.symbol_name() )
{ {
FC_ASSERT( b.quote.amount.value > 0 ); FC_ASSERT( static_cast<int64_t>(b.quote.amount) > 0 );
uint128_t result = (uint128_t(a.amount.value) * b.base.amount.value)/b.quote.amount.value; auto result = (UInt128(a.amount) *UInt128(b.base.amount))/UInt128(b.quote.amount);
FC_ASSERT( result.hi == 0 ); return Asset( Int64(result), b.base.symbol );
return Asset( result.to_uint64(), b.base.symbol );
} }
FC_THROW_EXCEPTION( fc::assert_exception, "invalid Asset * Price", ("Asset",a)("Price",b) ); FC_THROW_EXCEPTION( fc::assert_exception, "invalid Asset * Price", ("Asset",a)("Price",b) );
} }
...@@ -146,8 +146,8 @@ namespace EOS { ...@@ -146,8 +146,8 @@ namespace EOS {
return Price{ base, quote }; return Price{ base, quote };
} FC_CAPTURE_AND_RETHROW( (base)(quote) ) } } FC_CAPTURE_AND_RETHROW( (base)(quote) ) }
Price Price::max( SymbolType base, SymbolType quote ) { return Asset( ShareType(EOS_MAX_SHARE_SUPPLY), base ) / Asset( ShareType(1), quote); } Price Price::max( AssetSymbol base, AssetSymbol quote ) { return Asset( ShareType(EOS_MAX_SHARE_SUPPLY), base ) / Asset( ShareType(1), quote); }
Price Price::min( SymbolType base, SymbolType quote ) { return Asset( 1, base ) / Asset( EOS_MAX_SHARE_SUPPLY, quote); } Price Price::min( AssetSymbol base, AssetSymbol quote ) { return Asset( 1, base ) / Asset( EOS_MAX_SHARE_SUPPLY, quote); }
bool Price::is_null() const { return *this == Price(); } bool Price::is_null() const { return *this == Price(); }
...@@ -159,4 +159,4 @@ namespace EOS { ...@@ -159,4 +159,4 @@ namespace EOS {
} FC_CAPTURE_AND_RETHROW( (base)(quote) ) } } FC_CAPTURE_AND_RETHROW( (base)(quote) ) }
} // EOS } // eos
file(GLOB HEADERS "include/eos/types/*.hpp") file(GLOB HEADERS "include/eos/types/*.hpp")
add_library( eos_types add_library( eos_types
Asset.cpp
PublicKey.cpp
TypeParser.cpp TypeParser.cpp
native.cpp native.cpp
) )
...@@ -10,13 +12,10 @@ target_link_libraries( eos_types fc ) ...@@ -10,13 +12,10 @@ target_link_libraries( eos_types fc )
add_executable( type_generator type_generator.cpp ) add_executable( type_generator type_generator.cpp )
target_link_libraries( type_generator fc eos_types ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} ) target_link_libraries( type_generator fc eos_types ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} )
add_custom_command( OUTPUT generated.cpp include/eos/types/generated.hpp add_custom_command( OUTPUT include/eos/types/generated.hpp
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/type_generator ${CMAKE_CURRENT_SOURCE_DIR}/types.eos generated.cpp generated.hpp ${CMAKE_CURRENT_SOURCE_DIR}/include/eos/types/generated.hpp COMMAND ${CMAKE_CURRENT_BINARY_DIR}/type_generator ${CMAKE_CURRENT_SOURCE_DIR}/types.eos ${CMAKE_CURRENT_SOURCE_DIR}/include/eos/types/generated.hpp
DEPENDS types.eos type_generator ) DEPENDS types.eos type_generator )
add_library( eos_generated_types generated.cpp ) add_executable( types_test test.cpp include/eos/types/generated.hpp )
target_link_libraries( eos_generated_types eos_types ) target_link_libraries( types_test eos_types fc ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} )
add_executable( types_test test.cpp )
target_link_libraries( types_test fc eos_generated_types ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} )
/* #include <eos/types/PublicKey.hpp>
* Copyright (c) 2017, Respective Authors.
*
* The MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <eos/chain/config.hpp>
#include <eos/chain/types.hpp>
#include <fc/crypto/base58.hpp> #include <fc/crypto/base58.hpp>
#include <fc/crypto/ripemd160.hpp> #include <fc/crypto/ripemd160.hpp>
#include <fc/exception/exception.hpp> #include <fc/exception/exception.hpp>
#include <fc/io/raw.hpp> #include <fc/io/raw.hpp>
namespace eos { namespace chain { #define KEY_PREFIX "EOS"
namespace eos {
public_key_type::public_key_type():key_data(){}; PublicKey::PublicKey():key_data(){};
public_key_type::public_key_type(const fc::ecc::public_key_data& data) PublicKey::PublicKey(const fc::ecc::public_key_data& data)
:key_data( data ) {}; :key_data( data ) {};
public_key_type::public_key_type(const fc::ecc::public_key& pubkey) PublicKey::PublicKey(const fc::ecc::public_key& pubkey)
:key_data( pubkey ) {}; :key_data( pubkey ) {};
public_key_type::public_key_type(const std::string& base58str) PublicKey::PublicKey(const std::string& base58str)
{ {
// TODO: Refactor syntactic checks into static is_valid() // TODO: Refactor syntactic checks into static is_valid()
// to make public_key_type API more similar to address API // to make PublicKey API more similar to address API
std::string prefix( config::KeyPrefix ); std::string prefix( KEY_PREFIX );
const size_t prefix_len = prefix.size(); const size_t prefix_len = prefix.size();
FC_ASSERT(base58str.size() > prefix_len); FC_ASSERT(base58str.size() > prefix_len);
FC_ASSERT(base58str.substr(0, prefix_len) == prefix , "", ("base58str", base58str)); FC_ASSERT(base58str.substr(0, prefix_len) == prefix , "", ("base58str", base58str));
auto bin = fc::from_base58(base58str.substr(prefix_len)); auto bin = fc::from_base58(base58str.substr(prefix_len));
auto bin_key = fc::raw::unpack<binary_key>(bin); auto bin_key = fc::raw::unpack<BinaryKey>(bin);
key_data = bin_key.data; key_data = bin_key.data;
FC_ASSERT(fc::ripemd160::hash(key_data.data, key_data.size())._hash[0] == bin_key.check); FC_ASSERT(fc::ripemd160::hash(key_data.data, key_data.size())._hash[0] == bin_key.check);
} }
public_key_type::operator fc::ecc::public_key_data() const PublicKey::operator fc::ecc::public_key_data() const
{ {
return key_data; return key_data;
}; };
public_key_type::operator fc::ecc::public_key() const PublicKey::operator fc::ecc::public_key() const
{ {
return fc::ecc::public_key(key_data); return fc::ecc::public_key(key_data);
}; };
public_key_type::operator std::string() const PublicKey::operator std::string() const
{ {
binary_key k; BinaryKey k;
k.data = key_data; k.data = key_data;
k.check = fc::ripemd160::hash( k.data.data, k.data.size() )._hash[0]; k.check = fc::ripemd160::hash( k.data.data, k.data.size() )._hash[0];
auto data = fc::raw::pack( k ); auto data = fc::raw::pack( k );
return config::KeyPrefix + fc::to_base58( data.data(), data.size() ); return KEY_PREFIX + fc::to_base58( data.data(), data.size() );
} }
bool operator == (const public_key_type& p1, const fc::ecc::public_key& p2) bool operator == (const PublicKey& p1, const fc::ecc::public_key& p2)
{ {
return p1.key_data == p2.serialize(); return p1.key_data == p2.serialize();
} }
bool operator == (const public_key_type& p1, const public_key_type& p2) bool operator == (const PublicKey& p1, const PublicKey& p2)
{ {
return p1.key_data == p2.key_data; return p1.key_data == p2.key_data;
} }
bool operator != (const public_key_type& p1, const public_key_type& p2) bool operator != (const PublicKey& p1, const PublicKey& p2)
{ {
return p1.key_data != p2.key_data; return p1.key_data != p2.key_data;
} }
bool operator <(const public_key_type& p1, const public_key_type& p2) bool operator <(const PublicKey& p1, const PublicKey& p2)
{ {
return p1.key_data < p2.key_data; return p1.key_data < p2.key_data;
}; };
} } // eos::chain } // eos
namespace fc namespace fc
{ {
using namespace std; using namespace std;
void to_variant(const eos::chain::public_key_type& var, fc::variant& vo) void to_variant(const eos::PublicKey& var, fc::variant& vo)
{ {
vo = std::string(var); vo = std::string(var);
} }
void from_variant(const fc::variant& var, eos::chain::public_key_type& vo) void from_variant(const fc::variant& var, eos::PublicKey& vo)
{ {
vo = eos::chain::public_key_type(var.as_string()); vo = eos::PublicKey(var.as_string());
} }
} // fc } // fc
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <iostream> #include <iostream>
namespace EOS { namespace eos {
void AbstractSymbolTable::parse( std::istream& in ) { void AbstractSymbolTable::parse( std::istream& in ) {
vector<string> line_tokens; vector<string> line_tokens;
...@@ -13,7 +13,7 @@ namespace EOS { ...@@ -13,7 +13,7 @@ namespace EOS {
FC_ASSERT( current.fields.size() > 0, "A struct must specify at least one field" ); FC_ASSERT( current.fields.size() > 0, "A struct must specify at least one field" );
this->addType( current ); this->addType( current );
current.fields.clear(); current.fields.clear();
current.base.clear(); current.base = TypeName();
in_struct = false; in_struct = false;
}; };
...@@ -57,4 +57,4 @@ namespace EOS { ...@@ -57,4 +57,4 @@ namespace EOS {
} }
} }
} // namespace EOS } // namespace eos
#pragma once #pragma once
#include <fc/exception/exception.hpp> #include <fc/exception/exception.hpp>
#include <string> #include <eos/types/native.hpp>
#include <eos/types/ints.hpp>
/// EOS with 8 digits of precision /// eos with 8 digits of precision
#define EOS_SYMBOL (uint64_t(8) | (uint64_t('E') << 8) | (uint64_t('O') << 16) | (uint64_t('S') << 24) ) #define EOS_SYMBOL (uint64_t(8) | (uint64_t('E') << 8) | (uint64_t('O') << 16) | (uint64_t('S') << 24) )
/// VOTE with 8 digits of precision
#define VOTE_SYMBOL (uint64_t(8) | (uint64_t('V') << 8) | (uint64_t('O') << 16) | (uint64_t('T') << 24) | (uint64_t('E') << 32) )
/// Defined to be largest power of 10 that fits in 53 bits of precision /// Defined to be largest power of 10 that fits in 53 bits of precision
#define EOS_MAX_SHARE_SUPPLY int64_t(1000000000000000ll) #define EOS_MAX_SHARE_SUPPLY int64_t(1000000000000000ll)
namespace EOS { namespace eos {
typedef uint64_t AssetSymbol;
typedef Int64 ShareType;
using std::string;
using AssetSymbol = uint64_t;
using ShareType = Int64;
struct Asset struct Asset
{ {
...@@ -27,17 +21,15 @@ namespace EOS { ...@@ -27,17 +21,15 @@ namespace EOS {
ShareType amount; ShareType amount;
AssetSymbol symbol; AssetSymbol symbol;
double to_real()const { double to_real()const { return static_cast<double>(amount) / precision(); }
return static_cast<double>(amount) / precision();
}
uint8_t decimals()const; uint8_t decimals()const;
std::string symbol_name()const; String symbol_name()const;
int64_t precision()const; int64_t precision()const;
void set_decimals(uint8_t d); void set_decimals(uint8_t d);
static Asset fromString( const string& from ); static Asset fromString( const String& from );
string toString()const; String toString()const;
Asset& operator += ( const Asset& o ) Asset& operator += ( const Asset& o )
{ {
...@@ -63,45 +55,33 @@ namespace EOS { ...@@ -63,45 +55,33 @@ namespace EOS {
FC_ASSERT( a.symbol == b.symbol ); FC_ASSERT( a.symbol == b.symbol );
return std::tie(a.amount,a.symbol) < std::tie(b.amount,b.symbol); return std::tie(a.amount,a.symbol) < std::tie(b.amount,b.symbol);
} }
friend bool operator <= ( const Asset& a, const Asset& b ) friend bool operator <= ( const Asset& a, const Asset& b ) { return (a == b) || (a < b); }
{ friend bool operator != ( const Asset& a, const Asset& b ) { return !(a == b); }
return (a == b) || (a < b); friend bool operator > ( const Asset& a, const Asset& b ) { return !(a <= b); }
} friend bool operator >= ( const Asset& a, const Asset& b ) { return !(a < b); }
friend bool operator != ( const Asset& a, const Asset& b ) friend Asset operator - ( const Asset& a, const Asset& b ) {
{
return !(a == b);
}
friend bool operator > ( const Asset& a, const Asset& b )
{
return !(a <= b);
}
friend bool operator >= ( const Asset& a, const Asset& b )
{
return !(a < b);
}
friend Asset operator - ( const Asset& a, const Asset& b )
{
FC_ASSERT( a.symbol == b.symbol ); FC_ASSERT( a.symbol == b.symbol );
return Asset( a.amount - b.amount, a.symbol ); return Asset( a.amount - b.amount, a.symbol );
} }
friend Asset operator + ( const Asset& a, const Asset& b )
{ friend Asset operator + ( const Asset& a, const Asset& b ) {
FC_ASSERT( a.symbol == b.symbol ); FC_ASSERT( a.symbol == b.symbol );
return Asset( a.amount + b.amount, a.symbol ); return Asset( a.amount + b.amount, a.symbol );
} }
friend std::ostream& operator << ( std::ostream& out, const Asset& a ) { return out << a.toString(); }
}; };
struct Price struct Price
{ {
Price(const Asset& base = Asset(), const Asset quote = Asset())
: base(base),quote(quote){}
Asset base; Asset base;
Asset quote; Asset quote;
Price(const Asset& base = Asset(), const Asset quote = Asset())
:base(base),quote(quote){}
static Price max(AssetSymbol base, AssetSymbol quote ); static Price max(AssetSymbol base, AssetSymbol quote );
static Price min(AssetSymbol base, AssetSymbol quote ); static Price min(AssetSymbol base, AssetSymbol quote );
...@@ -127,40 +107,13 @@ namespace EOS { ...@@ -127,40 +107,13 @@ namespace EOS {
bool operator != ( const Price& a, const Price& b ); bool operator != ( const Price& a, const Price& b );
Asset operator * ( const Asset& a, const Price& b ); Asset operator * ( const Asset& a, const Price& b );
inline fc::variant toVariant( const Asset& v ) { return v.toString(); } } // namespace eos
inline void fromVariant( Asset& v, const fc::variant& var ) { v = Asset::fromString( var.get_string() ); }
template<typename Stream>
void toBinary( Stream& stream, const Asset& t ) {
EOS::toBinary( stream, t.amount );
EOS::toBinary( stream, t.symbol );
}
template<typename Stream>
void fromBinary( Stream& stream, Asset& t ) {
EOS::fromBinary( stream, t.amount );
EOS::fromBinary( stream, t.symbol );
}
template<typename Stream>
void toBinary( Stream& stream, const Price& t ) {
EOS::toBinary( stream, t.base );
EOS::toBinary( stream, t.quote );
}
template<typename Stream>
void fromBinary( Stream& stream, Price& t ) {
EOS::fromBinary( stream, t.base );
EOS::fromBinary( stream, t.quote );
}
} // namespace EOS
namespace fc { namespace fc {
inline void to_variant( const EOS::Asset& var, fc::variant& vo ) { vo = var.toString(); } inline void to_variant( const eos::Asset& var, fc::variant& vo ) { vo = var.toString(); }
inline void from_variant( const fc::variant& var, EOS::Asset& vo ) { vo = EOS::Asset::fromString( var.get_string() ); } inline void from_variant( const fc::variant& var, eos::Asset& vo ) { vo = eos::Asset::fromString( var.get_string() ); }
} }
FC_REFLECT( EOS::Asset, (amount)(symbol) ) FC_REFLECT( eos::Asset, (amount)(symbol) )
FC_REFLECT( EOS::Price, (base)(quote) ) FC_REFLECT( eos::Price, (base)(quote) )
#pragma once
#include <fc/crypto/elliptic.hpp>
#include <fc/reflect/reflect.hpp>
#include <fc/reflect/variant.hpp>
namespace eos {
struct PublicKey
{
struct BinaryKey
{
BinaryKey() {}
uint32_t check = 0;
fc::ecc::public_key_data data;
};
fc::ecc::public_key_data key_data;
PublicKey();
PublicKey( const fc::ecc::public_key_data& data );
PublicKey( const fc::ecc::public_key& pubkey );
explicit PublicKey( const std::string& base58str );
operator fc::ecc::public_key_data() const;
operator fc::ecc::public_key() const;
explicit operator std::string() const;
friend bool operator == ( const PublicKey& p1, const fc::ecc::public_key& p2);
friend bool operator == ( const PublicKey& p1, const PublicKey& p2);
friend bool operator != ( const PublicKey& p1, const PublicKey& p2);
friend bool operator < ( const PublicKey& p1, const PublicKey& p2);
bool is_valid_v1( const std::string& base58str );
};
}
namespace fc
{
void to_variant( const eos::PublicKey& var, fc::variant& vo );
void from_variant( const fc::variant& var, eos::PublicKey& vo );
}
FC_REFLECT( eos::PublicKey, (key_data) )
FC_REFLECT( eos::PublicKey::BinaryKey, (data)(check) )
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
#include <eos/types/native.hpp> #include <eos/types/native.hpp>
namespace EOS { namespace eos {
using std::map; using std::map;
using std::set; using std::set;
using std::string; using std::string;
...@@ -39,7 +39,7 @@ namespace EOS { ...@@ -39,7 +39,7 @@ namespace EOS {
class SimpleSymbolTable : public AbstractSymbolTable { class SimpleSymbolTable : public AbstractSymbolTable {
public: public:
SimpleSymbolTable(): SimpleSymbolTable():
known( { "FixedString16", "FixedString32", known( { "Field", "Struct", "Asset", "FixedString16", "FixedString32",
"UInt8", "UInt16", "UInt32", "UInt64", "UInt8", "UInt16", "UInt32", "UInt64",
"UInt128", "Checksum", "UInt256", "UInt512", "UInt128", "Checksum", "UInt256", "UInt512",
"Int8", "Int16", "Int32", "Int64", "Int8", "Int16", "Int32", "Int64",
...@@ -65,16 +65,17 @@ namespace EOS { ...@@ -65,16 +65,17 @@ namespace EOS {
order.push_back(to); order.push_back(to);
} FC_CAPTURE_AND_RETHROW( (from)(to) ) } } FC_CAPTURE_AND_RETHROW( (from)(to) ) }
virtual bool isKnownType( const TypeName& name ) override { try { virtual bool isKnownType( const TypeName& n ) override { try {
String name(n);
FC_ASSERT( name.size() > 0 ); FC_ASSERT( name.size() > 0 );
if( name.size() > 2 && name.back() == ']' ) { if( name.size() > 2 && name.back() == ']' ) {
FC_ASSERT( name[name.size()-2] == '[' ); FC_ASSERT( name[name.size()-2] == '[' );
return isKnownType( name.substr( 0, name.size()-2 ) ); return isKnownType( name.substr( 0, name.size()-2 ) );
} }
return known.find(name) != known.end() || return known.find(n) != known.end() ||
typedefs.find(name) != typedefs.end() || typedefs.find(n) != typedefs.end() ||
structs.find(name) != structs.end(); structs.find(n) != structs.end();
} FC_CAPTURE_AND_RETHROW( (name) ) } } FC_CAPTURE_AND_RETHROW( (n) ) }
virtual Struct getType( TypeName name )const override { virtual Struct getType( TypeName name )const override {
name = resolveTypedef( name ); name = resolveTypedef( name );
...@@ -105,8 +106,6 @@ namespace EOS { ...@@ -105,8 +106,6 @@ namespace EOS {
}; };
} // namespace EOS } // namespace eos
FC_REFLECT( EOS::Field, (name)(type) ) FC_REFLECT( eos::SimpleSymbolTable, (typedefs)(structs) )
FC_REFLECT( EOS::Struct, (name)(base)(fields) )
FC_REFLECT( EOS::SimpleSymbolTable, (typedefs)(structs) )
#pragma once
#include <boost/multiprecision/cpp_int.hpp>
#include <fc/log/logger.hpp>
namespace EOS {
using namespace boost::multiprecision;
typedef number<cpp_int_backend<8, 8, unsigned_magnitude, unchecked, void> > UInt8;
typedef number<cpp_int_backend<16, 16, unsigned_magnitude, unchecked, void> > UInt16;
typedef number<cpp_int_backend<32, 32, unsigned_magnitude, unchecked, void> > UInt32;
typedef number<cpp_int_backend<64, 64, unsigned_magnitude, unchecked, void> > UInt64;
typedef boost::multiprecision::uint128_t UInt128;
typedef boost::multiprecision::uint256_t UInt256;
typedef number<cpp_int_backend<8, 8, signed_magnitude, unchecked, void> > Int8;
typedef number<cpp_int_backend<16, 16, signed_magnitude, unchecked, void> > Int16;
typedef number<cpp_int_backend<32, 32, signed_magnitude, unchecked, void> > Int32;
typedef number<cpp_int_backend<64, 64, signed_magnitude, unchecked, void> > Int64;
typedef boost::multiprecision::int128_t Int128;
typedef boost::multiprecision::int256_t Int256;
template<typename Stream, typename Number>
void fromBinary( Stream& st, boost::multiprecision::number<Number>& value ) {
unsigned char data[(std::numeric_limits<decltype(value)>::digits+1)/8];
st.read( (char*)data, sizeof(data) );
boost::multiprecision::import_bits( value, data, data + sizeof(data), 1 );
}
template<typename Stream, typename Number>
void toBinary( Stream& st, const boost::multiprecision::number<Number>& value ) {
unsigned char data[(std::numeric_limits<decltype(value)>::digits+1)/8];
boost::multiprecision::export_bits( value, data, 1 );
st.write( (const char*)data, sizeof(data) );
}
} // namespace EOS
#pragma once #pragma once
#include <eos/types/ints.hpp>
#include <eos/types/Asset.hpp>
#include <vector> #include <vector>
#include <array> #include <array>
#include <string> #include <string>
#include <functional> #include <functional>
#include <boost/multiprecision/cpp_int.hpp>
#include <fc/variant.hpp> #include <fc/variant.hpp>
#include <fc/crypto/base64.hpp> #include <fc/crypto/base64.hpp>
#include <fc/crypto/hex.hpp> #include <fc/crypto/hex.hpp>
#include <fc/crypto/elliptic.hpp> #include <fc/crypto/elliptic.hpp>
#include <fc/crypto/ripemd160.hpp> #include <fc/crypto/sha256.hpp>
#include <fc/io/datastream.hpp> #include <fc/io/datastream.hpp>
#include <fc/time.hpp>
namespace EOS { #include <fc/fixed_string.hpp>
using std::vector;
using std::array; #include <fc/reflect/reflect.hpp>
using std::string;
namespace eos {
using namespace boost::multiprecision;
template<size_t Size=16>
struct FixedString { template<typename... T>
array<uint64_t,Size/8> value; using Vector = std::vector<T...>;
static_assert( sizeof(value) == Size, "unexpected padding" );
template<typename... T>
FixedString(){ memset( &value, 0, sizeof(value) ); } using Array = std::array<T...>;
FixedString( const std::string& str ) {
memset( &value, 0, sizeof(value) ); using String = std::string;
if( str.size() <= Size ) using Time = fc::time_point_sec;
memcpy( (char*)&value, str.c_str(), str.size() ); using Signature = fc::ecc::compact_signature;
else { using Checksum = fc::sha256;
memcpy( (char*)&value, str.c_str(), Size ); using FieldName = fc::fixed_string<>;
} using FixedString32 = fc::fixed_string<std::tuple<uint64_t,uint64_t,uint64_t,uint64_t>>;
} using FixedString16 = fc::fixed_string<>;
operator std::string()const { using TypeName = FixedString32;
const char* self = (const char*)&value; using Bytes = Vector<char>;
return std::string( self, self + size() );
} template<size_t Size>
using UInt = number<cpp_int_backend<Size, Size, unsigned_magnitude, unchecked, void> >;
uint32_t size()const { template<size_t Size>
if( *(((const char*)&value)+ - 1) ) using Int = number<cpp_int_backend<Size, Size, signed_magnitude, unchecked, void> >;
return sizeof(value);
return strnlen( (const char*)&value, Size ); using UInt8 = UInt<8>;
} using UInt16 = UInt<16>;
using UInt32 = UInt<32>;
friend bool operator == ( const FixedString& a, const FixedString& b ) { using UInt64 = UInt<64>;
return a.value == b.value; using UInt128 = boost::multiprecision::uint128_t;
} using UInt256 = boost::multiprecision::uint256_t;
friend bool operator < ( const FixedString& a, const FixedString& b ) { using Int8 = int8_t;//Int<8>; these types are different sizes than native...
return a.value < b.value; using Int16 = int16_t; //Int<16>;
} using Int32 = int32_t; //Int<32>;
friend bool operator == ( const FixedString& a, const char* b ) { using Int64 = int64_t; //Int<64>;
const char* self = (const char*)&a.value; using Int128 = boost::multiprecision::int128_t;
return 0 == strncmp( self, b, Size ); using Int256 = boost::multiprecision::int256_t;
}
};
typedef FixedString<16> FixedString16;
typedef FixedString<32> FixedString32;
typedef string TypeName;
typedef string FieldName;
struct Field { struct Field {
FieldName name; FieldName name;
TypeName type; TypeName type;
}; };
typedef fc::time_point_sec Time;
typedef fc::ecc::compact_signature Signature;
typedef string String;
typedef fc::sha256 Checksum;
typedef fc::ripemd160 BlockID;
typedef fc::ripemd160 TransactionID;
struct Struct { struct Struct {
TypeName name; TypeName name;
TypeName base; TypeName base;
vector<Field> fields; Vector<Field> fields;
}; };
struct Bytes { using Fields = Vector<Field>;
uint32_t size()const { return value.size(); }
const char* data()const { return value.data(); }
char* data() { return value.data(); }
void resize( uint32_t size ) { value.resize(size); }
template<typename T>
T as()const;
vector<char> value;
};
struct PublicKey
{
struct BinaryKey
{
BinaryKey() {}
uint32_t check = 0;
fc::ecc::public_key_data data;
};
fc::ecc::public_key_data key_data;
PublicKey();
PublicKey( const fc::ecc::public_key_data& data );
PublicKey( const fc::ecc::public_key& pubkey );
explicit PublicKey( const std::string& base58str );
operator fc::ecc::public_key_data() const;
operator fc::ecc::public_key() const;
explicit operator std::string() const;
friend bool operator == ( const PublicKey& p1, const fc::ecc::public_key& p2);
friend bool operator == ( const PublicKey& p1, const PublicKey& p2);
friend bool operator < ( const PublicKey& p1, const PublicKey& p2) { return p1.key_data < p2.key_data; }
friend bool operator != ( const PublicKey& p1, const PublicKey& p2);
};
template<typename Stream>
inline void toBinary( Stream& stream, const FixedString32& v ) {
stream.write( (const char*)&v.value, sizeof(v.value) );
}
template<typename Stream>
inline void fromBinary( Stream& stream, FixedString32& v ) {
stream.read( (char*)&v.value, sizeof(v.value) );
}
template<typename Stream>
inline void fromBinary( Stream& stream, FixedString16& v ) {
stream.read( (char*)&v.value, sizeof(v.value) );
}
template<typename Stream>
inline void toBinary( Stream& stream, const FixedString16& v ) {
stream.write( (const char*)&v.value, sizeof(v.value) );
}
template<typename Stream>
inline void toBinary( Stream& stream, const Signature& v ) {
stream.write( (const char*)&v, sizeof(v) );
}
template<typename Stream>
inline void fromBinary( Stream& stream, Signature& v ) {
stream.read( (char*)&v, sizeof(v) );
}
inline fc::variant toVariant( const Int8& v ) { return static_cast<int8_t>(v); }
inline fc::variant toVariant( const Int16& v ) { return static_cast<int16_t>(v); }
inline fc::variant toVariant( const Int32& v ) { return static_cast<int32_t>(v); }
inline fc::variant toVariant( const Int64& v ) { return static_cast<int64_t>(v); }
inline fc::variant toVariant( const UInt8& v ) { return static_cast<uint8_t>(v); }
inline fc::variant toVariant( const UInt16& v ) { return static_cast<uint16_t>(v); }
inline fc::variant toVariant( const UInt32& v ) { return static_cast<uint32_t>(v); }
inline fc::variant toVariant( const UInt64& v ) { return static_cast<uint64_t>(v); }
inline fc::variant toVariant( const FixedString16& v ) { return std::string(v); }
inline fc::variant toVariant( const FixedString32& v ) { return std::string(v); }
inline fc::variant toVariant( const PublicKey& v ) { return std::string(v); }
inline fc::variant toVariant( const String& v ) { return v; }
inline fc::variant toVariant( const Time& v ) { return fc::variant(v); }
inline fc::variant toVariant( const Checksum& v ) { return fc::to_hex( (const char*)&v, sizeof(v) ); }
inline fc::variant toVariant( const Signature& v ) { return fc::to_hex( (const char*)&v, sizeof(v) ); }
inline void fromVariant( Int8& v, const fc::variant& var ) { v = static_cast<int8_t>(var.as_int64()); }
inline void fromVariant( Int16& v, const fc::variant& var ) { v = static_cast<int16_t>(var.as_int64()); }
inline void fromVariant( Int32& v, const fc::variant& var ) { v = static_cast<int32_t>(var.as_int64()); }
inline void fromVariant( Int64& v, const fc::variant& var ) { v = static_cast<int64_t>(var.as_int64()); }
inline void fromVariant( UInt8& v, const fc::variant& var ) { v = static_cast<uint8_t>(var.as_uint64()); }
inline void fromVariant( UInt16& v, const fc::variant& var ) { v = static_cast<uint16_t>(var.as_uint64()); }
inline void fromVariant( UInt32& v, const fc::variant& var ) { v = static_cast<uint32_t>(var.as_uint64()); }
inline void fromVariant( UInt64& v, const fc::variant& var ) { v = static_cast<uint64_t>(var.as_uint64()); }
inline void fromVariant( FixedString16& v, const fc::variant& var ) { v = FixedString16( var.as_string() ); }
inline void fromVariant( FixedString32& v, const fc::variant& var ) { v = FixedString32( var.as_string() ); }
inline void fromVariant( String& v, const fc::variant& var ) { v = var.as_string(); }
inline void fromVariant( Time& v, const fc::variant& var ) { v = var.as<Time>(); }
inline void fromVariant( PublicKey& v, const fc::variant& var ) { v = PublicKey( var.as_string() ); }
inline void fromVariant( Checksum& v, const fc::variant& var ) { fc::from_hex( var.as_string(), (char*)&v, sizeof(v)); }
inline void fromVariant( Signature& v, const fc::variant& var ) { fc::from_hex( var.as_string(), (char*)&v, sizeof(v)); }
template<typename T> fc::variant toVariant( const vector<T>& a ); template<typename T>
template<typename T> void fromVariant( vector<T>& data, const fc::variant& v ); struct GetStruct{};
template<typename Stream, typename T> void toBinary( Stream& s, const vector<T>& a ); template<> struct GetStruct<Field> {
template<typename Stream, typename T> void fromBinary( Stream& s, vector<T>& a ); static const Struct& type() {
static Struct result = { "Field ", "", {
template<typename Stream> {"name", "FieldName"},
void toBinary( Stream& s, const Bytes& data ) { {"type", "TypeNmae"}
uint32_t len = data.size(); }
s.write( (const char*)&len, sizeof(len) ); };
if( len ) s.write( data.data(), data.size() ); return result;
} }
};
template<typename Stream> template<> struct GetStruct<Struct> {
void fromBinary( Stream& s, Bytes& data ) { static const Struct& type() {
uint32_t len = 0; static Struct result = { "Struct ", "", {
s.read( (char*)&len, sizeof(len) ); {"name", "TypeName"},
data.resize(len); {"base", "TypeName"},
if( len ) { {"fields", "Field[]"}
s.read( data.data(), data.size() ); }
} };
} return result;
}
template<typename Stream> };
void toBinary( Stream& s, const String& data ) {
uint32_t len = data.size();
s.write( (const char*)&len, sizeof(len) );
if( len ) s.write( data.data(), data.size() );
}
template<typename Stream>
void fromBinary( Stream& s, String& data ) {
uint32_t len = 0;
s.read( (char*)&len, sizeof(len) );
data.resize(len);
if( len ) {
s.read( const_cast<char*>(data.data()), data.size() );
}
}
inline fc::variant toVariant( const Bytes& data ) { /// TODO: make sure this works with FC raw
if( !data.size() ) return ""; template<typename Stream, typename Number>
return fc::base64_encode( data.data(), data.size() ); void fromBinary( Stream& st, boost::multiprecision::number<Number>& value ) {
unsigned char data[(std::numeric_limits<decltype(value)>::digits+1)/8];
st.read( (char*)data, sizeof(data) );
boost::multiprecision::import_bits( value, data, data + sizeof(data), 1 );
} }
template<typename Stream, typename Number>
inline void fromVariant( Bytes& data, const fc::variant& v ) { void toBinary( Stream& st, const boost::multiprecision::number<Number>& value ) {
auto decoded = fc::base64_decode( v.get_string() ); unsigned char data[(std::numeric_limits<decltype(value)>::digits+1)/8];
data.value.resize( decoded.size() ); boost::multiprecision::export_bits( value, data, 1 );
memcpy( data.value.data(), decoded.c_str(), decoded.size() ); st.write( (const char*)data, sizeof(data) );
} }
inline fc::variant toVariant( const Field& t ) {
fc::mutable_variant_object mvo;
mvo.reserve( 2 );
mvo["name"] = EOS::toVariant( t.name );
mvo["type"] = EOS::toVariant( t.type );
return fc::variant( std::move(mvo) );
}
template<typename Stream>
void toBinary( Stream& stream, const Field& t ) {
EOS::toBinary( stream, t.name );
EOS::toBinary( stream, t.type );
}
template<typename Stream>
void fromBinary( Stream& stream, Field& t ) {
EOS::fromBinary( stream, t.name );
EOS::fromBinary( stream, t.type );
}
template<typename T>
T as( const vector<char>& data ) {
fc::datastream<const char*> ds(data.data(), data.size() );
T result;
EOS::fromBinary( ds, result );
return result;
}
} // namespace EOS } // namespace eos
FC_REFLECT( EOS::PublicKey::BinaryKey, (check)(data) )
FC_REFLECT( EOS::PublicKey, (key_data) )
namespace fc { namespace fc {
void to_variant( const std::vector<EOS::Field>& c, fc::variant& v ); void to_variant( const std::vector<eos::Field>& c, fc::variant& v );
void from_variant( const fc::variant& v, std::vector<EOS::Field>& check ); void from_variant( const fc::variant& v, std::vector<eos::Field>& check );
void to_variant( const std::map<std::string,EOS::Struct>& c, fc::variant& v ); void to_variant( const std::map<std::string,eos::Struct>& c, fc::variant& v );
void from_variant( const fc::variant& v, std::map<std::string,EOS::Struct>& check ); void from_variant( const fc::variant& v, std::map<std::string,eos::Struct>& check );
} }
FC_REFLECT( eos::Field, (name)(type) )
FC_REFLECT( eos::Struct, (name)(base)(fields) )
...@@ -2,83 +2,24 @@ ...@@ -2,83 +2,24 @@
#include <fc/crypto/base58.hpp> #include <fc/crypto/base58.hpp>
#include <fc/crypto/ripemd160.hpp> #include <fc/crypto/ripemd160.hpp>
#include <fc/io/raw.hpp> #include <fc/io/raw.hpp>
#include <fc/fixed_string.hpp>
#include <fc/reflect/variant.hpp>
namespace EOS {
PublicKey::PublicKey():key_data(){};
PublicKey::PublicKey( const fc::ecc::public_key_data& data )
:key_data( data ) {};
PublicKey::PublicKey( const fc::ecc::public_key& pubkey )
:key_data( pubkey ) {};
PublicKey::PublicKey( const std::string& base58str )
{
// TODO: Refactor syntactic checks into static is_valid()
// to make PublicKey API more similar to address API
std::string prefix( "EOS" );
const size_t prefix_len = prefix.size();
FC_ASSERT( base58str.size() > prefix_len );
FC_ASSERT( base58str.substr( 0, prefix_len ) == prefix , "", ("base58str", base58str) );
auto bin = fc::from_base58( base58str.substr( prefix_len ) );
auto bin_key = fc::raw::unpack<BinaryKey>(bin);
key_data = bin_key.data;
FC_ASSERT( fc::ripemd160::hash( key_data.data, key_data.size() )._hash[0] == bin_key.check );
};
PublicKey::operator fc::ecc::public_key_data() const
{
return key_data;
};
PublicKey::operator fc::ecc::public_key() const
{
return fc::ecc::public_key( key_data );
};
PublicKey::operator std::string() const
{
BinaryKey k;
k.data = key_data;
k.check = fc::ripemd160::hash( k.data.data, k.data.size() )._hash[0];
auto data = fc::raw::pack( k );
return "EOS" + fc::to_base58( data.data(), data.size() );
}
bool operator == ( const PublicKey& p1, const fc::ecc::public_key& p2)
{
return p1.key_data == p2.serialize();
}
bool operator == ( const PublicKey& p1, const PublicKey& p2)
{
return p1.key_data == p2.key_data;
}
bool operator != ( const PublicKey& p1, const PublicKey& p2)
{
return p1.key_data != p2.key_data;
}
}
namespace fc { namespace fc {
void to_variant( const std::vector<EOS::Field>& c, fc::variant& v ) { void to_variant( const std::vector<eos::Field>& c, fc::variant& v ) {
fc::mutable_variant_object mvo; mvo.reserve( c.size() ); fc::mutable_variant_object mvo; mvo.reserve( c.size() );
for( const auto& f : c ) { for( const auto& f : c ) {
mvo.set( f.name, f.type ); mvo.set( f.name, eos::String(f.type) );
} }
v = std::move(mvo); v = std::move(mvo);
} }
void from_variant( const fc::variant& v, std::vector<EOS::Field>& fields ) { void from_variant( const fc::variant& v, std::vector<eos::Field>& fields ) {
const auto& obj = v.get_object(); const auto& obj = v.get_object();
fields.reserve( obj.size() ); fields.reserve( obj.size() );
for( const auto& f : obj ) for( const auto& f : obj )
fields.emplace_back( EOS::Field{ f.key(), f.value().get_string() } ); fields.emplace_back( eos::Field{ f.key(), f.value().get_string() } );
} }
void to_variant( const std::map<std::string,EOS::Struct>& c, fc::variant& v ) void to_variant( const std::map<std::string,eos::Struct>& c, fc::variant& v )
{ {
fc::mutable_variant_object mvo; mvo.reserve( c.size() ); fc::mutable_variant_object mvo; mvo.reserve( c.size() );
for( const auto& item : c ) { for( const auto& item : c ) {
...@@ -89,7 +30,7 @@ namespace fc { ...@@ -89,7 +30,7 @@ namespace fc {
} }
v = std::move(mvo); v = std::move(mvo);
} }
void from_variant( const fc::variant& v, std::map<std::string,EOS::Struct>& structs ) { void from_variant( const fc::variant& v, std::map<std::string,eos::Struct>& structs ) {
const auto& obj = v.get_object(); const auto& obj = v.get_object();
structs.clear(); structs.clear();
for( const auto& f : obj ) { for( const auto& f : obj ) {
......
#include <eos/types/native.hpp>
#include <fc/log/logger.hpp> #include <fc/log/logger.hpp>
#include <fc/exception/exception.hpp> #include <fc/exception/exception.hpp>
#include <eos/types/native.hpp>
#include <eos/types/Asset.hpp>
#include <eos/types/PublicKey.hpp>
#include <eos/types/generated.hpp> #include <eos/types/generated.hpp>
#include <eos/types/native_impl.hpp>
#include <fc/io/datastream.hpp> #include <fc/io/datastream.hpp>
int main( int argc, char** argv ) { int main( int argc, char** argv ) {
try { try {
EOS::Message m; eos::Message m;
m.from = EOS::AccountName( "ned" ); m.sender = eos::AccountName( "ned" );
m.to = EOS::AccountName( "dan" ); m.recipient = eos::AccountName( "dan" );
idump( (m) );
eos::Transfer t;
t.from = m.sender;
t.to = "other";
idump( (EOS::toVariant(m) ) ); idump( (t) );
/*
fc::datastream<size_t> ps; fc::datastream<size_t> ps;
EOS::toBinary( ps, m ); eos::toBinary( ps, m );
idump((ps.tellp())); idump((ps.tellp()));
std::vector<char> data(ps.tellp()); std::vector<char> data(ps.tellp());
fc::datastream<char*> ds( data.data(), data.size()); fc::datastream<char*> ds( data.data(), data.size());
EOS::toBinary( ds, m ); eos::toBinary( ds, m );
EOS::Message m2; eos::Message m2;
fc::datastream<const char*> ds2( data.data(), data.size()); fc::datastream<const char*> ds2( data.data(), data.size());
EOS::fromBinary( ds2, m2 ); eos::fromBinary( ds2, m2 );
wdump( (EOS::toVariant(m2) ) ); wdump( (eos::toVariant(m2) ) );
*/
} catch ( const fc::exception& e ) { } catch ( const fc::exception& e ) {
elog( "${e}", ("e", e.to_detail_string() ) ); elog( "${e}", ("e", e.to_detail_string() ) );
......
...@@ -60,7 +60,7 @@ string call_type_constructor( const string& type ) { ...@@ -60,7 +60,7 @@ string call_type_constructor( const string& type ) {
return "Vector[" + getWrenType(type) + "]"; return "Vector[" + getWrenType(type) + "]";
return getWrenType(type) + ".new()"; return getWrenType(type) + ".new()";
} }
string generate_wren( const EOS::Struct& s, EOS::SimpleSymbolTable& symbols ) { string generate_wren( const eos::Struct& s, eos::SimpleSymbolTable& symbols ) {
std::stringstream ss; std::stringstream ss;
ss << "class " << s.name; ss << "class " << s.name;
...@@ -98,16 +98,15 @@ string generate_wren( const EOS::Struct& s, EOS::SimpleSymbolTable& symbols ) { ...@@ -98,16 +98,15 @@ string generate_wren( const EOS::Struct& s, EOS::SimpleSymbolTable& symbols ) {
return ss.str(); return ss.str();
} }
void generate_wren( EOS::SimpleSymbolTable& ss, const char* outfile ) { void generate_wren( eos::SimpleSymbolTable& ss, const char* outfile ) {
//for( const auto& s : ss.order ) //for( const auto& s : ss.order )
} }
void generate_hpp( EOS::SimpleSymbolTable& ss, const char* outfile ) { void generate_hpp( eos::SimpleSymbolTable& ss, const char* outfile ) {
wdump((outfile)); wdump((outfile));
std::ofstream out(outfile); std::ofstream out(outfile);
out << "#pragma once\n"; out << "#pragma once\n";
out << "#include <eos/types/native.hpp>\n"; out << "namespace eos { \n";
out << "namespace EOS { \n";
for( const auto& s : ss.order ) { for( const auto& s : ss.order ) {
if( ss.typedefs.find( s ) != ss.typedefs.end() ) { if( ss.typedefs.find( s ) != ss.typedefs.end() ) {
const auto& td = ss.typedefs[s]; const auto& td = ss.typedefs[s];
...@@ -123,33 +122,26 @@ void generate_hpp( EOS::SimpleSymbolTable& ss, const char* outfile ) { ...@@ -123,33 +122,26 @@ void generate_hpp( EOS::SimpleSymbolTable& ss, const char* outfile ) {
for( const auto& f : st.fields ) { for( const auto& f : st.fields ) {
string type = f.type; string type = f.type;
if( type.back() == ']' ) if( type.back() == ']' )
type = "vector<" + type.substr(0,type.size()-2) + ">"; type = "Vector<" + type.substr(0,type.size()-2) + ">";
out <<" " << std::left << std::setw(32) << type << " " << f.name<<";\n"; out <<" " << std::left << std::setw(32) << type << " " << f.name<<";\n";
} }
out << " };\n\n"; out << " };\n\n";
out << " fc::variant toVariant( const " << s << "& t ); \n"; out << " template<> struct GetStruct<"<< s <<"> { \n";
out << " void fromVariant( " << s << "& t, const fc::variant& v ); \n"; out << " static const Struct& type() { \n";
out << " static Struct result = { \"" << s << " \", \"" << st.base <<"\", {\n";
out << " template<typename Stream>\n";
out << " void toBinary( Stream& stream, const " << s << "& t ) { \n";
if( st.base.size() )
out << " EOS::toBinary( stream, static_cast<const " << st.base<<"&>(t) );\n";
for( const auto& f : st.fields ) {
out << " EOS::toBinary( stream, t."<< f.name << " );\n";
}
out << " }\n\n";
out << " template<typename Stream>\n";
out << " void fromBinary( Stream& stream, " << s << "& t ) { \n";
if( st.base.size() )
out << " EOS::fromBinary( stream, static_cast<" << st.base<<"&>(t) );\n";
for( const auto& f : st.fields ) { for( const auto& f : st.fields ) {
out << " EOS::fromBinary( stream, t."<< f.name << " );\n"; out << " {\"" << f.name <<"\", \"" << f.type <<"\"},\n";
} }
out << " }\n\n"; out << " }\n";
out << " };\n";
out << " return result;\n";
out << " }\n";
out << " };\n\n";
} }
out << "} // namespace EOS \n";
out << "} // namespace eos \n";
for( const auto& s : ss.order ) { for( const auto& s : ss.order ) {
if( ss.typedefs.find( s ) != ss.typedefs.end() ) { if( ss.typedefs.find( s ) != ss.typedefs.end() ) {
...@@ -158,9 +150,9 @@ void generate_hpp( EOS::SimpleSymbolTable& ss, const char* outfile ) { ...@@ -158,9 +150,9 @@ void generate_hpp( EOS::SimpleSymbolTable& ss, const char* outfile ) {
const auto& st = ss.structs[s]; const auto& st = ss.structs[s];
if( st.base.size() ) { if( st.base.size() ) {
out << "FC_REFLECT_DERIVED( EOS::" << s << ", (EOS::" << st.base <<"), "; out << "FC_REFLECT_DERIVED( eos::" << s << ", (eos::" << st.base <<"), ";
} else { } else {
out << "FC_REFLECT( EOS::" << s << ", "; out << "FC_REFLECT( eos::" << std::setw(33) << s << ", ";
} }
for( const auto& f : st.fields ) { for( const auto& f : st.fields ) {
out <<"("<<f.name<<")"; out <<"("<<f.name<<")";
...@@ -170,76 +162,27 @@ void generate_hpp( EOS::SimpleSymbolTable& ss, const char* outfile ) { ...@@ -170,76 +162,27 @@ void generate_hpp( EOS::SimpleSymbolTable& ss, const char* outfile ) {
} }
int count_fields( EOS::SimpleSymbolTable& ss, const EOS::Struct& st ) { int count_fields( eos::SimpleSymbolTable& ss, const eos::Struct& st ) {
if( st.base.size() ) if( st.base.size() )
return st.fields.size() + count_fields( ss, ss.getType( st.base ) ); return st.fields.size() + count_fields( ss, ss.getType( st.base ) );
return st.fields.size(); return st.fields.size();
} }
void add_fields( EOS::SimpleSymbolTable& ss, std::ofstream& out, const EOS::Struct& st ) {
if( st.base.size() ) {
add_fields( ss, out, ss.getType( st.base ) );
}
for( const auto& f : st.fields ) {
out << " mvo[\""<<f.name<<"\"] = EOS::toVariant( t."<<f.name<<" );\n";
}
}
void generate_cpp( EOS::SimpleSymbolTable& ss, const char* outfile, const char* hpp ) {
edump((hpp)(outfile));
std::ofstream out(outfile);
out << "#include <eos/types/native.hpp>\n";
out << "#include <eos/types/" << hpp <<">\n";
out << "#include <eos/types/native_impl.hpp>\n";
out << "namespace EOS { \n";
for( const auto& s : ss.order ) {
if( ss.typedefs.find( s ) != ss.typedefs.end() ) {
continue;
}
}
for( const auto& s : ss.order ) {
if( ss.typedefs.find( s ) != ss.typedefs.end() ) { continue; }
const auto& st = ss.structs[s];
out << " fc::variant toVariant( const " << s << "& t ) { \n";
out << " fc::mutable_variant_object mvo; \n";
out << " mvo.reserve( " << count_fields(ss, st) <<" ); \n";
add_fields( ss, out, st );
out << " return fc::variant( std::move(mvo) ); \n";
out << " }\n\n";
out << " void fromVariant( " << s << "& t, const fc::variant& v ) { \n";
out << " const fc::variant_object& mvo = v.get_object(); \n";
for( const auto& f : st.fields ) {
out << " { auto itr = mvo.find( \"" << f.name <<"\" );\n";
out << " if( itr != mvo.end() ) \n";
out << " EOS::fromVariant( t." << f.name << ", itr->value() );}\n";
}
out << " }\n\n";
}
out << "} // namespace EOS \n";
out.close();
}
int main( int argc, char** argv ) { int main( int argc, char** argv ) {
try { try {
FC_ASSERT( argc > 4, "Usage: ${program} input out.cpp out.hpp path/to/out.hpp", ("program",string(argv[0])) ); FC_ASSERT( argc > 2, "Usage: ${program} input path/to/out.hpp", ("program",string(argv[0])) );
std::ifstream in(argv[1]); std::ifstream in(argv[1]);
EOS::SimpleSymbolTable ss; eos::SimpleSymbolTable ss;
ss.parse(in); ss.parse(in);
auto as_json = fc::json::to_pretty_string( ss ); auto as_json = fc::json::to_pretty_string( ss );
std:: cerr << as_json << "\n"; std:: cerr << as_json << "\n";
generate_hpp( ss, argv[4] ); generate_hpp( ss, argv[2] );
/*
generate_cpp( ss, argv[2], argv[3] ); generate_cpp( ss, argv[2], argv[3] );
/*
auto w = generate_wren( ss.getType( "Message" ), ss ); auto w = generate_wren( ss.getType( "Message" ), ss );
std::cerr << w <<"\n"; std::cerr << w <<"\n";
w = generate_wren( ss.getType( "Transfer" ), ss ); w = generate_wren( ss.getType( "Transfer" ), ss );
......
#// Built In Types
#Vector[Type]
#String
#Bytes
#Time
#Signature
#PublicKey
#FixedString16,32 // names, types
#FixedBytes16,28,32,64 // signatures, hashes, keys
#UInt8,16,32,64,128,224,256,512
#Int8,16,32,64,128,224,256,512
typedef FixedString32 AccountName typedef FixedString32 AccountName
typedef FixedString16 PermissionName typedef FixedString16 PermissionName
typedef FixedString16 MessageType typedef FixedString32 MessageName
typedef UInt32 AccountPermissionWeight typedef FixedString32 TypeName
typedef UInt32 GeneratedTransactionID
# import account type as localtype # import account type as localtype
struct Message struct Message
sender AccountName # testing sender AccountName # testing
recipient AccountName recipient AccountName
notify AccountName[] notify AccountName[]
type MessageType type TypeName
data Bytes data Bytes
struct AccountPermission struct AccountPermission
account AccountName account AccountName
permission PermissionName permission PermissionName
struct AccountPermissionWeight
permission AccountPermission
weight UInt16
struct Transaction struct Transaction
expiration Time ref_block_num UInt16
tapos UInt32 ref_block_prefix UInt32
messages Message[] expiration Time
permissions AccountPermission[] tapos UInt32
messages Message[]
authorization AccountPermission[]
struct SignedTransaction inherits Transaction struct SignedTransaction inherits Transaction
signatures Signature[] signatures Signature[]
struct KeyPermissionWeight struct KeyPermissionWeight
key PublicKey key PublicKey
weight UInt16 weight UInt16
struct Authority struct Authority
threshold UInt32 threshold UInt32
keys KeyPermissionWeight[] keys KeyPermissionWeight[]
accounts AccountPermissionWeight[] accounts AccountPermissionWeight[]
struct CreateAccount
creator AccountName
name AccountName
owner Authority
active Authority
recovery Authority
struct UpdatePermission
account AccountName
permission PermissionName
parent PermissionName
authority Authority
struct DeletePermission
account AccountName
permission PermissionName
struct Transfer struct Transfer
from AccountName from AccountName # may not be the message.sender if message.sender has delegated authority by from
to AccountName to AccountName
amount UInt64 amount Asset
memo String memo String
struct CreateAccount
creator AccountName
name AccountName
owner Authority
active Authority
recovery Authority
deposit Asset
struct CreateProducer struct CreateProducer
account AccountName name AccountName
key PublicKey key PublicKey
struct VoteOnProducer # implies message.sender account
account AccountName struct ApproveProducer
producer AccountName producer AccountName
weight Int8 approve Int8 # 0 or 1
struct SetProducerVoteProxy # implies message.sender account
account AccountName struct SetVoteProxy
proxy AccountName proxy AccountName
struct DefineStruct
scope AccountName
definition Struct
struct UpdatePermission
account AccountName
permission PermissionName
parent PermissionName
authority Authority
struct DeletePermission
account AccountName
permission PermissionName
...@@ -175,10 +175,12 @@ read_only::get_block_results read_only::get_block(const read_only::get_block_par ...@@ -175,10 +175,12 @@ read_only::get_block_results read_only::get_block(const read_only::get_block_par
read_write::push_block_results read_write::push_block(const read_write::push_block_params& params) { read_write::push_block_results read_write::push_block(const read_write::push_block_params& params) {
db.push_block(params); db.push_block(params);
return read_write::push_block_results();
} }
read_write::push_transaction_results read_write::push_transaction(const read_write::push_transaction_params& params) { read_write::push_transaction_results read_write::push_transaction(const read_write::push_transaction_params& params) {
db.push_transaction(params); db.push_transaction(params);
return read_write::push_transaction_results();
} }
} // namespace chain_apis } // namespace chain_apis
......
...@@ -8,21 +8,6 @@ ...@@ -8,21 +8,6 @@
namespace eos { namespace eos {
using namespace appbase; using namespace appbase;
using chain::account_name;
using chain::Authority;
struct Transfer {
account_name to;
uint64_t amount = 0;
string memo;
};
struct CreateAccount {
account_name new_account;
Authority owner;
Authority active;
uint64_t initial_balance = 0;
};
/** /**
* @brief This class is a native C++ implementation of the system contract. * @brief This class is a native C++ implementation of the system contract.
...@@ -54,5 +39,3 @@ private: ...@@ -54,5 +39,3 @@ private:
} }
FC_REFLECT(eos::Transfer, (to)(amount)(memo))
FC_REFLECT(eos::CreateAccount, (new_account)(owner)(active)(initial_balance))
...@@ -2,25 +2,39 @@ ...@@ -2,25 +2,39 @@
#include <eos/chain/account_object.hpp> #include <eos/chain/account_object.hpp>
#include <eos/chain/exceptions.hpp> #include <eos/chain/exceptions.hpp>
#include <eos/types/native.hpp>
#include <eos/types/generated.hpp>
namespace eos { namespace eos {
using namespace chain; using namespace chain;
/************************************************************
*
* Transfer Handlers
*
***********************************************************/
void Transfer_validate(chain::message_validate_context& context) { void Transfer_validate(chain::message_validate_context& context) {
auto transfer = context.msg.as<Transfer>(); auto transfer = context.msg.as<Transfer>();
EOS_ASSERT(context.msg.has_notify(transfer.to), message_validate_exception, "Must notify recipient of transfer"); try {
EOS_ASSERT(transfer.amount > Asset(0), message_validate_exception, "Must transfer a positive amount");
EOS_ASSERT(context.msg.has_notify(transfer.to), message_validate_exception, "Must notify recipient of transfer");
} FC_CAPTURE_AND_RETHROW( (transfer) )
} }
void Transfer_validate_preconditions(chain::precondition_validate_context& context) { void Transfer_validate_preconditions(chain::precondition_validate_context& context) {
const auto& db = context.db; const auto& db = context.db;
auto transfer = context.msg.as<Transfer>(); auto transfer = context.msg.as<Transfer>();
const auto& from = db.get_account(context.msg.sender);
EOS_ASSERT(from.balance >= transfer.amount, message_precondition_exception, "Insufficient Funds", db.get_account(transfer.to); ///< make sure this exists
const auto& from = db.get_account(transfer.from);
EOS_ASSERT(from.balance >= transfer.amount.amount, message_precondition_exception, "Insufficient Funds",
("from.balance",from.balance)("transfer.amount",transfer.amount)); ("from.balance",from.balance)("transfer.amount",transfer.amount));
} }
void Transfer_apply(chain::apply_context& context) { void Transfer_apply(chain::apply_context& context) {
auto& db = context.mutable_db; auto& db = context.mutable_db;
auto transfer = context.msg.as<Transfer>(); auto transfer = context.msg.as<Transfer>();
const auto& from = db.get_account(context.msg.sender); idump((transfer));
const auto& from = db.get_account(transfer.from);
const auto& to = db.get_account(transfer.to); const auto& to = db.get_account(transfer.to);
db.modify(from, [&](account_object& a) { db.modify(from, [&](account_object& a) {
a.balance -= transfer.amount; a.balance -= transfer.amount;
...@@ -28,39 +42,62 @@ void Transfer_apply(chain::apply_context& context) { ...@@ -28,39 +42,62 @@ void Transfer_apply(chain::apply_context& context) {
db.modify(to, [&](account_object& a) { db.modify(to, [&](account_object& a) {
a.balance += transfer.amount; a.balance += transfer.amount;
}); });
idump((from));
idump((to));
}
/************************************************************
*
* Create Account Handlers
*
***********************************************************/
///@{
void Authority_validate_preconditions( const Authority& auth, chain::precondition_validate_context& context ) {
for( const auto& a : auth.accounts )
context.db.get<account_object,by_name>( a.permission.account );
} }
void CreateAccount_validate(chain::message_validate_context& context) { void CreateAccount_validate(chain::message_validate_context& context) {
auto create = context.msg.as<CreateAccount>(); auto create = context.msg.as<CreateAccount>();
EOS_ASSERT(create.owner.validate(), message_validate_exception, "Invalid owner authority");
EOS_ASSERT(create.active.validate(), message_validate_exception, "Invalid active authority"); EOS_ASSERT( validate(create.owner), message_validate_exception, "Invalid owner authority");
EOS_ASSERT( validate(create.active), message_validate_exception, "Invalid active authority");
EOS_ASSERT( validate(create.recovery), message_validate_exception, "Invalid recovery authority");
} }
void CreateAccount_validate_preconditions(chain::precondition_validate_context& context) { void CreateAccount_validate_preconditions(chain::precondition_validate_context& context) {
const auto& db = context.db; const auto& db = context.db;
auto create = context.msg.as<CreateAccount>(); auto create = context.msg.as<CreateAccount>();
auto existing_account = db.find<account_object, by_name>(create.new_account); db.get_account(create.creator); ///< make sure it exists
auto existing_account = db.find<account_object, by_name>(create.name);
EOS_ASSERT(existing_account == nullptr, message_precondition_exception, EOS_ASSERT(existing_account == nullptr, message_precondition_exception,
"Cannot create account named ${name}, as that name is already taken", "Cannot create account named ${name}, as that name is already taken",
("name", create.new_account)); ("name", create.name));
const auto& creator = db.get_account(context.msg.sender); const auto& creator = db.get_account(context.msg.sender);
EOS_ASSERT(creator.balance >= create.initial_balance, message_precondition_exception, "Insufficient Funds"); EOS_ASSERT(creator.balance >= create.deposit, message_precondition_exception, "Insufficient Funds");
#warning TODO: make sure creation deposit is greater than min account balance
for (const auto& account : create.owner.referenced_accounts()) Authority_validate_preconditions( create.owner, context );
db.get_account(account); Authority_validate_preconditions( create.active, context );
for (const auto& account : create.active.referenced_accounts()) Authority_validate_preconditions( create.recovery, context );
db.get_account(account);
} }
void CreateAccount_apply(chain::apply_context& context) { void CreateAccount_apply(chain::apply_context& context) {
auto& db = context.mutable_db; auto& db = context.mutable_db;
auto create = context.msg.as<CreateAccount>(); auto create = context.msg.as<CreateAccount>();
db.modify(db.get_account(context.msg.sender), [&create](account_object& a) { db.modify(db.get_account(context.msg.sender), [&create](account_object& a) {
a.balance -= create.initial_balance; a.balance -= create.deposit;
}); });
const auto& new_account = db.create<account_object>([&create](account_object& a) { const auto& new_account = db.create<account_object>([&create](account_object& a) {
a.name = create.new_account; a.name = create.name;
a.balance = create.initial_balance; a.balance = create.deposit;
}); });
const auto& owner_permission = db.create<permission_object>([&create, &new_account](permission_object& p) { const auto& owner_permission = db.create<permission_object>([&create, &new_account](permission_object& p) {
p.name = "owner"; p.name = "owner";
...@@ -75,6 +112,7 @@ void CreateAccount_apply(chain::apply_context& context) { ...@@ -75,6 +112,7 @@ void CreateAccount_apply(chain::apply_context& context) {
p.auth = std::move(create.active); p.auth = std::move(create.active);
}); });
} }
///@} Create Account Handlers
class native_system_contract_plugin_impl { class native_system_contract_plugin_impl {
public: public:
......
...@@ -68,21 +68,36 @@ BOOST_FIXTURE_TEST_CASE(transfer, testing_fixture) ...@@ -68,21 +68,36 @@ BOOST_FIXTURE_TEST_CASE(transfer, testing_fixture)
BOOST_REQUIRE_THROW(db.push_transaction(trx), transaction_exception); // no messages BOOST_REQUIRE_THROW(db.push_transaction(trx), transaction_exception); // no messages
trx.messages.resize(1); trx.messages.resize(1);
trx.set_reference_block(db.head_block_id()); trx.set_reference_block(db.head_block_id());
trx.set_expiration(db.head_block_time() + 100); trx.expiration = db.head_block_time() + 100;
trx.messages[0].sender = "init1"; trx.messages[0].sender = "init1";
trx.messages[0].recipient = "sys"; trx.messages[0].recipient = "sys";
trx.messages[0].type = "Undefined"; trx.messages[0].type = "Undefined";
BOOST_REQUIRE_THROW( db.push_transaction(trx), message_validate_exception ); // "Type Undefined is not defined" BOOST_REQUIRE_THROW( db.push_transaction(trx), message_validate_exception ); // "Type Undefined is not defined"
Transfer trans = { "init1", "init2", Asset(100), "transfer 100" };
edump((trans));
UInt64 value(5);
auto packed = fc::raw::pack(value);
auto unpacked = fc::raw::unpack<UInt64>(packed);
BOOST_CHECK_EQUAL( value, unpacked );
trx.messages[0].type = "Transfer"; trx.messages[0].type = "Transfer";
trx.messages[0].set("Transfer", Transfer{ "init2", 100, "memo" }); trx.messages[0].set("Transfer", trans );
auto unpack_trans = trx.messages[0].as<Transfer>();
edump((unpack_trans));
wlog( "." );
BOOST_REQUIRE_THROW(db.push_transaction(trx), message_validate_exception); // "fail to notify receiver, init2" BOOST_REQUIRE_THROW(db.push_transaction(trx), message_validate_exception); // "fail to notify receiver, init2"
wlog( "." );
trx.messages[0].notify = {"init2"}; trx.messages[0].notify = {"init2"};
trx.messages[0].set("Transfer", Transfer{ "init2", 100, "memo" }); trx.messages[0].set("Transfer", trans );
wlog( "." );
db.push_transaction(trx); db.push_transaction(trx);
wlog( "." );
BOOST_CHECK_EQUAL(db.get_account("init1").balance, 100000 - 100); BOOST_CHECK_EQUAL(db.get_account("init1").balance, Asset(100000 - 100));
BOOST_CHECK_EQUAL(db.get_account("init2").balance, 100000 + 100); BOOST_CHECK_EQUAL(db.get_account("init2").balance, Asset(100000 + 100));
db.produce_blocks(1); db.produce_blocks(1);
BOOST_REQUIRE_THROW(db.push_transaction(trx), transaction_exception); // not unique BOOST_REQUIRE_THROW(db.push_transaction(trx), transaction_exception); // not unique
...@@ -97,7 +112,7 @@ BOOST_FIXTURE_TEST_CASE(create_account, testing_fixture) ...@@ -97,7 +112,7 @@ BOOST_FIXTURE_TEST_CASE(create_account, testing_fixture)
const auto& init1_account = db.get_account("init1"); const auto& init1_account = db.get_account("init1");
BOOST_CHECK_EQUAL(init1_account.balance, 100000); BOOST_CHECK_EQUAL(init1_account.balance, Asset(100000));
auto joe_private_key = fc::ecc::private_key::regenerate(fc::sha256::hash("joe")); auto joe_private_key = fc::ecc::private_key::regenerate(fc::sha256::hash("joe"));
public_key_type joe_public_key = joe_private_key.get_public_key(); public_key_type joe_public_key = joe_private_key.get_public_key();
...@@ -105,17 +120,17 @@ BOOST_FIXTURE_TEST_CASE(create_account, testing_fixture) ...@@ -105,17 +120,17 @@ BOOST_FIXTURE_TEST_CASE(create_account, testing_fixture)
signed_transaction trx; signed_transaction trx;
trx.messages.resize(1); trx.messages.resize(1);
trx.set_reference_block(db.head_block_id()); trx.set_reference_block(db.head_block_id());
trx.set_expiration(db.head_block_time() + 100); trx.expiration = db.head_block_time() + 100;
trx.messages[0].sender = "init1"; trx.messages[0].sender = "init1";
trx.messages[0].recipient = "sys"; trx.messages[0].recipient = "sys";
trx.messages[0].type = "CreateAccount"; trx.messages[0].type = "CreateAccount";
trx.messages[0].set("CreateAccount", trx.messages[0].set("CreateAccount",
CreateAccount{"joe", {1, {}, {{joe_public_key, 1}}}, {1, {}, {{joe_public_key, 1}}}, 1000}); CreateAccount{"init1", "joe", {1, {{joe_public_key, 1}}, {}}, {1, {{joe_public_key, 1}}, {}}, {}, Asset(1000)});
db.push_transaction(trx); db.push_transaction(trx);
const auto& joe_account = db.get_account("joe"); const auto& joe_account = db.get_account("joe");
BOOST_CHECK_EQUAL(joe_account.balance, 1000); BOOST_CHECK_EQUAL(joe_account.balance, Asset(1000));
BOOST_CHECK_EQUAL(init1_account.balance, 100000 - 1000); BOOST_CHECK_EQUAL(init1_account.balance, Asset(100000 - 1000));
const auto& joe_owner_authority = db.get<permission_object, by_owner>(boost::make_tuple(joe_account.id, "owner")); const auto& joe_owner_authority = db.get<permission_object, by_owner>(boost::make_tuple(joe_account.id, "owner"));
BOOST_CHECK_EQUAL(joe_owner_authority.auth.threshold, 1); BOOST_CHECK_EQUAL(joe_owner_authority.auth.threshold, 1);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册