提交 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"]
path = libraries/fc
url = https://github.com/bitshares/bitshares-fc.git
url = https://github.com/eosio/fc.git
ignore = dirty
[submodule "libraries/chainbase"]
path = libraries/chainbase
......
add_subdirectory( fc )
add_subdirectory( chainbase )
add_subdirectory( wren )
#add_subdirectory( types )
add_subdirectory( types )
add_subdirectory( deterministic_openssl_rand )
add_subdirectory( chain )
add_subdirectory( egenesis )
......
......@@ -5,7 +5,6 @@ add_library( eos_chain
database.cpp
fork_database.cpp
types.cpp
transaction.cpp
block.cpp
......@@ -18,7 +17,7 @@ add_library( eos_chain
${PROTOCOL_HEADERS}
)
target_link_libraries( eos_chain fc chainbase )
target_link_libraries( eos_chain fc chainbase eos_types )
target_include_directories( eos_chain
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
const account_name* previous_notify_account = nullptr;
for(const auto& current_notify_account : msg.notify) {
get_account(current_notify_account);
if(previous_notify_account)
if(previous_notify_account) {
EOS_ASSERT(current_notify_account < *previous_notify_account, message_validate_exception,
"Message notify accounts out of order. Possibly a bug in the wallet?");
}
EOS_ASSERT(current_notify_account != msg.sender, message_validate_exception,
"Message sender is listed in accounts to notify. Possibly a bug in the wallet?");
EOS_ASSERT(current_notify_account != msg.recipient, message_validate_exception,
......@@ -745,7 +747,7 @@ void database::init_genesis(const genesis_state_type& genesis_state)
create<account_object>([&acct](account_object& a) {
a.name = acct.name.c_str();
a.balance = acct.balance;
idump((acct.name)(a.balance));
// idump((acct.name)(a.balance));
// a.active_key = acct.active_key;
// a.owner_key = acct.owner_key;
});
......
......@@ -51,9 +51,9 @@ namespace eos { namespace chain {
return *this;
}
uint32_t threshold = 0;
shared_vector<PermissionLevel> accounts;
shared_vector<KeyPermission> keys;
UInt32 threshold = 0;
shared_vector<AccountPermissionWeight> accounts;
shared_vector<KeyPermissionWeight> keys;
};
class account_object : public chainbase::object<account_object_type, account_object>
......@@ -61,11 +61,11 @@ namespace eos { namespace chain {
OBJECT_CTOR(account_object)
id_type id;
account_name name;
uint64_t balance = 0;
uint64_t votes = 0;
uint64_t converting_votes = 0;
time_point_sec last_vote_conversion;
AccountName name;
Asset balance;
UInt64 votes = 0;
UInt64 converting_votes = 0;
Time last_vote_conversion;
};
struct by_name;
......@@ -73,7 +73,7 @@ namespace eos { namespace chain {
account_object,
indexed_by<
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
#include <eos/chain/types.hpp>
#include <eos/types/generated.hpp>
namespace eos {
inline bool operator < ( const AccountPermission& a, const AccountPermission& b ) {
return std::tie( a.account, a.permission ) < std::tie( b.account, b.permission );
}
namespace eos { namespace chain {
struct PermissionLevel {
account_name account;
permission_name level;
uint16_t weight;
};
struct KeyPermission {
public_key_type key;
uint16_t weight;
};
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;
/**
* Makes sure all keys are unique and sorted and all account permissions are unique and sorted
*/
inline bool validate( eos::Authority& auth ) {
const KeyPermissionWeight* prev = nullptr;
for( const auto& k : auth.keys ) {
if( !prev ) prev = &k;
else if( prev->key < k.key ) return false;
}
set<account_name> referenced_accounts() const {
set<account_name> results;
std::transform(accounts.begin(), accounts.end(), std::inserter(results, results.begin()),
[](const PermissionLevel& p) { return p.account; });
return results;
const AccountPermissionWeight* pa = nullptr;
for( const auto& a : auth.accounts ) {
if( !pa ) pa = &a;
else if( pa->permission < a.permission ) return false;
}
};
} } // eos::chain
return true;
}
}
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 {
active_key(active_key == public_key_type()? owner_key : active_key)
{}
string name;
uint64_t balance = 0;
Asset balance;
public_key_type owner_key;
public_key_type active_key;
};
......
......@@ -94,7 +94,6 @@ namespace eos { namespace chain {
/// Calculate the digest used for signature validation
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);
bool verify_reference_block(const block_id_type& reference_block)const;
};
......
......@@ -26,9 +26,6 @@
#include <fc/io/varint.hpp>
#include <fc/io/enum_type.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/safe.hpp>
#include <fc/container/flat.hpp>
......@@ -39,6 +36,10 @@
#include <fc/smart_ref_fwd.hpp>
#include <fc/crypto/ripemd160.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 <vector>
......@@ -105,12 +106,14 @@ namespace eos { namespace chain {
using private_key_type = fc::ecc::private_key;
using chain_id_type = fc::sha256;
typedef fc::fixed_string<> account_name;
typedef fc::fixed_string<> permission_name;
typedef fc::fixed_string<> message_type;
//using account_name = std::string;
//using message_type = std::string;
//using permission_name = std::string;
using eos::AccountName;
using account_name = eos::AccountName;
using eos::PermissionName;
using permission_name = eos::PermissionName;
using message_name = eos::TypeName;
using message_type = message_name;
/**
* List all object types from all namespaces here so they can
......@@ -150,40 +153,11 @@ namespace eos { namespace chain {
using signature_type = fc::ecc::compact_signature;
using weight_type = uint16_t;
struct public_key_type
{
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 );
};
using public_key_type = eos::PublicKey;
} } // 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::producer_id_type, (_id))
......
......@@ -62,10 +62,6 @@ signature_type eos::chain::signed_transaction::sign(const private_key_type& key,
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) {
ref_block_num = fc::endian_reverse_u32(reference_block._hash[0]);
ref_block_prefix = reference_block._hash[1];
......
Subproject commit 1f41494f360a1800fc967d647631cf64fdc549ee
Subproject commit cadc521fe41282487e047cc3030b2eb8231202c2
......@@ -10,7 +10,8 @@ set(SOURCES node.cpp
add_library( eos_net ${SOURCES} ${HEADERS} )
target_link_libraries( eos_net
PUBLIC fc chainbase appbase )
PUBLIC fc chainbase appbase eos_types)
target_include_directories( eos_net
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include"
PRIVATE "${CMAKE_SOURCE_DIR}/libraries/chain/include"
......
#include <eos/types/Asset.hpp>
#include <boost/rational.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <fc/reflect/variant.hpp>
namespace EOS {
namespace eos {
typedef boost::multiprecision::int128_t int128_t;
uint8_t Asset::decimals()const {
......@@ -14,7 +15,7 @@ namespace EOS {
a[0] = d;
}
std::string Asset::symbol_name()const {
String Asset::symbol_name()const {
auto a = (const char*)&symbol;
assert( a[7] == 0 );
return &a[1];
......@@ -32,21 +33,21 @@ namespace EOS {
return table[ decimals() ];
}
string Asset::toString()const {
string result = fc::to_string(amount.value / precision());
String Asset::toString()const {
String result = fc::to_string( static_cast<int64_t>(amount) / precision());
if( decimals() )
{
auto fract = amount.value % precision();
auto fract = static_cast<int64_t>(amount) % precision();
result += "." + fc::to_string(precision() + fract).erase(0,1);
}
return result + " " + symbol_name();
}
Asset Asset::fromString( const string& from )
Asset Asset::fromString( const String& from )
{
try
{
string s = fc::trim( from );
String s = fc::trim( from );
auto space_pos = s.find( " " );
auto dot_pos = s.find( "." );
......@@ -57,15 +58,15 @@ namespace EOS {
auto intpart = s.substr( 0, dot_pos );
result.amount = fc::to_int64(intpart);
std::string fractpart;
if( dot_pos != std::string::npos )
String fractpart;
if( dot_pos != String::npos )
{
auto fractpart = "1" + s.substr( dot_pos + 1, space_pos - dot_pos - 1 );
result.set_decimals( fractpart.size() - 1 );
result.amount.value *= result.precision();
result.amount.value += fc::to_int64(fractpart);
result.amount.value -= result.precision();
result.amount *= Int64(result.precision());
result.amount += Int64(fc::to_int64(fractpart));
result.amount -= Int64(result.precision());
}
auto symbol = s.substr( space_pos + 1 );
......@@ -82,8 +83,8 @@ namespace EOS {
if( std::tie( a.base.symbol, a.quote.symbol ) != std::tie( b.base.symbol, b.quote.symbol ) )
return false;
const auto amult = uint128_t( b.quote.amount.value ) * a.base.amount.value;
const auto bmult = uint128_t( a.quote.amount.value ) * b.base.amount.value;
const auto amult = UInt128( b.quote.amount ) * UInt128(a.base.amount);
const auto bmult = UInt128( a.quote.amount ) * UInt128(b.base.amount);
return amult == bmult;
}
......@@ -95,8 +96,8 @@ namespace EOS {
if( a.quote.symbol < b.quote.symbol ) return true;
if( a.quote.symbol > b.quote.symbol ) return false;
const auto amult = uint128_t( b.quote.amount.value ) * a.base.amount.value;
const auto bmult = uint128_t( a.quote.amount.value ) * b.base.amount.value;
const auto amult = UInt128( b.quote.amount ) * UInt128(a.base.amount);
const auto bmult = UInt128( a.quote.amount ) * UInt128(b.base.amount);
return amult < bmult;
}
......@@ -125,17 +126,16 @@ namespace EOS {
{
if( a.symbol_name() == b.base.symbol_name() )
{
FC_ASSERT( b.base.amount.value > 0 );
uint128_t result = (uint128_t(a.amount.value) * b.quote.amount.value)/b.base.amount.value;
FC_ASSERT( result.hi == 0 );
return Asset( result.to_uint64(), b.quote.symbol );
FC_ASSERT( static_cast<int64_t>(b.base.amount) > 0 );
auto result = (UInt128(a.amount) * UInt128(b.quote.amount))/UInt128(b.base.amount);
return Asset( Int64(result), b.quote.symbol );
}
else if( a.symbol_name() == b.quote.symbol_name() )
{
FC_ASSERT( b.quote.amount.value > 0 );
uint128_t result = (uint128_t(a.amount.value) * b.base.amount.value)/b.quote.amount.value;
FC_ASSERT( result.hi == 0 );
return Asset( result.to_uint64(), b.base.symbol );
FC_ASSERT( static_cast<int64_t>(b.quote.amount) > 0 );
auto result = (UInt128(a.amount) *UInt128(b.base.amount))/UInt128(b.quote.amount);
return Asset( Int64(result), b.base.symbol );
}
FC_THROW_EXCEPTION( fc::assert_exception, "invalid Asset * Price", ("Asset",a)("Price",b) );
}
......@@ -146,8 +146,8 @@ namespace EOS {
return Price{ 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::min( SymbolType base, SymbolType quote ) { return Asset( 1, base ) / Asset( EOS_MAX_SHARE_SUPPLY, quote); }
Price Price::max( AssetSymbol base, AssetSymbol quote ) { return Asset( ShareType(EOS_MAX_SHARE_SUPPLY), base ) / Asset( ShareType(1), 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(); }
......@@ -159,4 +159,4 @@ namespace EOS {
} FC_CAPTURE_AND_RETHROW( (base)(quote) ) }
} // EOS
} // eos
file(GLOB HEADERS "include/eos/types/*.hpp")
add_library( eos_types
Asset.cpp
PublicKey.cpp
TypeParser.cpp
native.cpp
)
......@@ -10,13 +12,10 @@ target_link_libraries( eos_types fc )
add_executable( type_generator type_generator.cpp )
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
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
add_custom_command( OUTPUT 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 )
add_library( eos_generated_types generated.cpp )
target_link_libraries( eos_generated_types eos_types )
add_executable( types_test test.cpp )
target_link_libraries( types_test fc eos_generated_types ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} )
add_executable( types_test test.cpp include/eos/types/generated.hpp )
target_link_libraries( types_test eos_types fc ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} )
/*
* 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 <eos/types/PublicKey.hpp>
#include <fc/crypto/base58.hpp>
#include <fc/crypto/ripemd160.hpp>
#include <fc/exception/exception.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 ) {};
public_key_type::public_key_type(const fc::ecc::public_key& pubkey)
PublicKey::PublicKey(const fc::ecc::public_key& 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()
// to make public_key_type API more similar to address API
std::string prefix( config::KeyPrefix );
// to make PublicKey API more similar to address API
std::string prefix( KEY_PREFIX );
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<binary_key>(bin);
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);
}
public_key_type::operator fc::ecc::public_key_data() const
PublicKey::operator fc::ecc::public_key_data() const
{
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);
};
public_key_type::operator std::string() const
PublicKey::operator std::string() const
{
binary_key k;
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 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();
}
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;
}
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;
}
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;
};
} } // eos::chain
} // eos
namespace fc
{
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);
}
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
......@@ -2,7 +2,7 @@
#include <boost/algorithm/string.hpp>
#include <iostream>
namespace EOS {
namespace eos {
void AbstractSymbolTable::parse( std::istream& in ) {
vector<string> line_tokens;
......@@ -13,7 +13,7 @@ namespace EOS {
FC_ASSERT( current.fields.size() > 0, "A struct must specify at least one field" );
this->addType( current );
current.fields.clear();
current.base.clear();
current.base = TypeName();
in_struct = false;
};
......@@ -57,4 +57,4 @@ namespace EOS {
}
}
} // namespace EOS
} // namespace eos
#pragma once
#include <fc/exception/exception.hpp>
#include <string>
#include <eos/types/ints.hpp>
#include <eos/types/native.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) )
/// 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
#define EOS_MAX_SHARE_SUPPLY int64_t(1000000000000000ll)
namespace EOS {
typedef uint64_t AssetSymbol;
typedef Int64 ShareType;
using std::string;
namespace eos {
using AssetSymbol = uint64_t;
using ShareType = Int64;
struct Asset
{
......@@ -27,17 +21,15 @@ namespace EOS {
ShareType amount;
AssetSymbol symbol;
double to_real()const {
return static_cast<double>(amount) / precision();
}
double to_real()const { return static_cast<double>(amount) / precision(); }
uint8_t decimals()const;
std::string symbol_name()const;
String symbol_name()const;
int64_t precision()const;
void set_decimals(uint8_t d);
static Asset fromString( const string& from );
string toString()const;
static Asset fromString( const String& from );
String toString()const;
Asset& operator += ( const Asset& o )
{
......@@ -63,45 +55,33 @@ namespace EOS {
FC_ASSERT( a.symbol == b.symbol );
return std::tie(a.amount,a.symbol) < std::tie(b.amount,b.symbol);
}
friend bool operator <= ( const Asset& a, const Asset& b )
{
return (a == b) || (a < b);
}
friend bool operator <= ( const Asset& a, const Asset& b ) { return (a == b) || (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 ) { 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 bool operator >= ( const Asset& a, const Asset& b )
{
return !(a < b);
}
friend Asset operator - ( const Asset& a, const Asset& b )
{
friend Asset operator - ( const Asset& a, const Asset& b ) {
FC_ASSERT( a.symbol == b.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 );
return Asset( a.amount + b.amount, a.symbol );
}
friend std::ostream& operator << ( std::ostream& out, const Asset& a ) { return out << a.toString(); }
};
struct Price
{
Price(const Asset& base = Asset(), const Asset quote = Asset())
: base(base),quote(quote){}
Asset base;
Asset quote;
Price(const Asset& base = Asset(), const Asset quote = Asset())
:base(base),quote(quote){}
static Price max(AssetSymbol base, AssetSymbol quote );
static Price min(AssetSymbol base, AssetSymbol quote );
......@@ -127,40 +107,13 @@ namespace EOS {
bool operator != ( const Price& a, const Price& b );
Asset operator * ( const Asset& a, const Price& b );
inline fc::variant toVariant( const Asset& v ) { return v.toString(); }
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 eos
namespace fc {
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 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() ); }
}
FC_REFLECT( EOS::Asset, (amount)(symbol) )
FC_REFLECT( EOS::Price, (base)(quote) )
FC_REFLECT( eos::Asset, (amount)(symbol) )
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 @@
#include <eos/types/native.hpp>
namespace EOS {
namespace eos {
using std::map;
using std::set;
using std::string;
......@@ -39,7 +39,7 @@ namespace EOS {
class SimpleSymbolTable : public AbstractSymbolTable {
public:
SimpleSymbolTable():
known( { "FixedString16", "FixedString32",
known( { "Field", "Struct", "Asset", "FixedString16", "FixedString32",
"UInt8", "UInt16", "UInt32", "UInt64",
"UInt128", "Checksum", "UInt256", "UInt512",
"Int8", "Int16", "Int32", "Int64",
......@@ -65,16 +65,17 @@ namespace EOS {
order.push_back(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 );
if( name.size() > 2 && name.back() == ']' ) {
FC_ASSERT( name[name.size()-2] == '[' );
return isKnownType( name.substr( 0, name.size()-2 ) );
}
return known.find(name) != known.end() ||
typedefs.find(name) != typedefs.end() ||
structs.find(name) != structs.end();
} FC_CAPTURE_AND_RETHROW( (name) ) }
return known.find(n) != known.end() ||
typedefs.find(n) != typedefs.end() ||
structs.find(n) != structs.end();
} FC_CAPTURE_AND_RETHROW( (n) ) }
virtual Struct getType( TypeName name )const override {
name = resolveTypedef( name );
......@@ -105,8 +106,6 @@ namespace EOS {
};
} // namespace EOS
} // namespace eos
FC_REFLECT( EOS::Field, (name)(type) )
FC_REFLECT( EOS::Struct, (name)(base)(fields) )
FC_REFLECT( EOS::SimpleSymbolTable, (typedefs)(structs) )
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
#include <eos/types/ints.hpp>
#include <eos/types/Asset.hpp>
#include <vector>
#include <array>
#include <string>
#include <functional>
#include <boost/multiprecision/cpp_int.hpp>
#include <fc/variant.hpp>
#include <fc/crypto/base64.hpp>
#include <fc/crypto/hex.hpp>
#include <fc/crypto/elliptic.hpp>
#include <fc/crypto/ripemd160.hpp>
#include <fc/crypto/sha256.hpp>
#include <fc/io/datastream.hpp>
namespace EOS {
using std::vector;
using std::array;
using std::string;
template<size_t Size=16>
struct FixedString {
array<uint64_t,Size/8> value;
static_assert( sizeof(value) == Size, "unexpected padding" );
FixedString(){ memset( &value, 0, sizeof(value) ); }
FixedString( const std::string& str ) {
memset( &value, 0, sizeof(value) );
if( str.size() <= Size )
memcpy( (char*)&value, str.c_str(), str.size() );
else {
memcpy( (char*)&value, str.c_str(), Size );
}
}
operator std::string()const {
const char* self = (const char*)&value;
return std::string( self, self + size() );
}
uint32_t size()const {
if( *(((const char*)&value)+ - 1) )
return sizeof(value);
return strnlen( (const char*)&value, Size );
}
friend bool operator == ( const FixedString& a, const FixedString& b ) {
return a.value == b.value;
}
friend bool operator < ( const FixedString& a, const FixedString& b ) {
return a.value < b.value;
}
friend bool operator == ( const FixedString& a, const char* b ) {
const char* self = (const char*)&a.value;
return 0 == strncmp( self, b, Size );
}
};
typedef FixedString<16> FixedString16;
typedef FixedString<32> FixedString32;
typedef string TypeName;
typedef string FieldName;
#include <fc/time.hpp>
#include <fc/fixed_string.hpp>
#include <fc/reflect/reflect.hpp>
namespace eos {
using namespace boost::multiprecision;
template<typename... T>
using Vector = std::vector<T...>;
template<typename... T>
using Array = std::array<T...>;
using String = std::string;
using Time = fc::time_point_sec;
using Signature = fc::ecc::compact_signature;
using Checksum = fc::sha256;
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<>;
using TypeName = FixedString32;
using Bytes = Vector<char>;
template<size_t Size>
using UInt = number<cpp_int_backend<Size, Size, unsigned_magnitude, unchecked, void> >;
template<size_t Size>
using Int = number<cpp_int_backend<Size, Size, signed_magnitude, unchecked, void> >;
using UInt8 = UInt<8>;
using UInt16 = UInt<16>;
using UInt32 = UInt<32>;
using UInt64 = UInt<64>;
using UInt128 = boost::multiprecision::uint128_t;
using UInt256 = boost::multiprecision::uint256_t;
using Int8 = int8_t;//Int<8>; these types are different sizes than native...
using Int16 = int16_t; //Int<16>;
using Int32 = int32_t; //Int<32>;
using Int64 = int64_t; //Int<64>;
using Int128 = boost::multiprecision::int128_t;
using Int256 = boost::multiprecision::int256_t;
struct Field {
FieldName name;
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 {
TypeName name;
TypeName base;
vector<Field> fields;
Vector<Field> fields;
};
struct Bytes {
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); }
using Fields = Vector<Field>;
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);
};
struct GetStruct{};
template<typename Stream>
inline void toBinary( Stream& stream, const FixedString32& v ) {
stream.write( (const char*)&v.value, sizeof(v.value) );
template<> struct GetStruct<Field> {
static const Struct& type() {
static Struct result = { "Field ", "", {
{"name", "FieldName"},
{"type", "TypeNmae"}
}
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> void fromVariant( vector<T>& data, const fc::variant& v );
template<typename Stream, typename T> void toBinary( Stream& s, const vector<T>& a );
template<typename Stream, typename T> void fromBinary( Stream& s, vector<T>& a );
template<typename Stream>
void toBinary( Stream& s, const Bytes& 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, Bytes& data ) {
uint32_t len = 0;
s.read( (char*)&len, sizeof(len) );
data.resize(len);
if( len ) {
s.read( data.data(), data.size() );
}
}
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 ) {
if( !data.size() ) return "";
return fc::base64_encode( data.data(), data.size() );
};
return result;
}
inline void fromVariant( Bytes& data, const fc::variant& v ) {
auto decoded = fc::base64_decode( v.get_string() );
data.value.resize( decoded.size() );
memcpy( data.value.data(), decoded.c_str(), decoded.size() );
};
template<> struct GetStruct<Struct> {
static const Struct& type() {
static Struct result = { "Struct ", "", {
{"name", "TypeName"},
{"base", "TypeName"},
{"fields", "Field[]"}
}
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) );
};
return result;
}
};
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 );
/// TODO: make sure this works with FC raw
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 T>
T as( const vector<char>& data ) {
fc::datastream<const char*> ds(data.data(), data.size() );
T result;
EOS::fromBinary( ds, result );
return result;
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
FC_REFLECT( EOS::PublicKey::BinaryKey, (check)(data) )
FC_REFLECT( EOS::PublicKey, (key_data) )
} // namespace eos
namespace fc {
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 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 to_variant( const std::vector<eos::Field>& c, fc::variant& v );
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 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 @@
#include <fc/crypto/base58.hpp>
#include <fc/crypto/ripemd160.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 {
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() );
for( const auto& f : c ) {
mvo.set( f.name, f.type );
mvo.set( f.name, eos::String(f.type) );
}
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();
fields.reserve( obj.size() );
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() );
for( const auto& item : c ) {
......@@ -89,7 +30,7 @@ namespace fc {
}
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();
structs.clear();
for( const auto& f : obj ) {
......
#include <eos/types/native.hpp>
#include <fc/log/logger.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/native_impl.hpp>
#include <fc/io/datastream.hpp>
int main( int argc, char** argv ) {
try {
EOS::Message m;
m.from = EOS::AccountName( "ned" );
m.to = EOS::AccountName( "dan" );
eos::Message m;
m.sender = eos::AccountName( "ned" );
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;
EOS::toBinary( ps, m );
eos::toBinary( ps, m );
idump((ps.tellp()));
std::vector<char> data(ps.tellp());
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());
EOS::fromBinary( ds2, m2 );
eos::fromBinary( ds2, m2 );
wdump( (EOS::toVariant(m2) ) );
wdump( (eos::toVariant(m2) ) );
*/
} catch ( const fc::exception& e ) {
elog( "${e}", ("e", e.to_detail_string() ) );
......
......@@ -60,7 +60,7 @@ string call_type_constructor( const string& type ) {
return "Vector[" + getWrenType(type) + "]";
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;
ss << "class " << s.name;
......@@ -98,16 +98,15 @@ string generate_wren( const EOS::Struct& s, EOS::SimpleSymbolTable& symbols ) {
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 )
}
void generate_hpp( EOS::SimpleSymbolTable& ss, const char* outfile ) {
void generate_hpp( eos::SimpleSymbolTable& ss, const char* outfile ) {
wdump((outfile));
std::ofstream out(outfile);
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 ) {
if( ss.typedefs.find( s ) != ss.typedefs.end() ) {
const auto& td = ss.typedefs[s];
......@@ -123,33 +122,26 @@ void generate_hpp( EOS::SimpleSymbolTable& ss, const char* outfile ) {
for( const auto& f : st.fields ) {
string type = f.type;
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 << " };\n\n";
out << " fc::variant toVariant( const " << s << "& t ); \n";
out << " void fromVariant( " << s << "& t, const fc::variant& v ); \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";
out << " template<> struct GetStruct<"<< s <<"> { \n";
out << " static const Struct& type() { \n";
out << " static Struct result = { \"" << s << " \", \"" << st.base <<"\", {\n";
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 ) {
if( ss.typedefs.find( s ) != ss.typedefs.end() ) {
......@@ -158,9 +150,9 @@ void generate_hpp( EOS::SimpleSymbolTable& ss, const char* outfile ) {
const auto& st = ss.structs[s];
if( st.base.size() ) {
out << "FC_REFLECT_DERIVED( EOS::" << s << ", (EOS::" << st.base <<"), ";
out << "FC_REFLECT_DERIVED( eos::" << s << ", (eos::" << st.base <<"), ";
} else {
out << "FC_REFLECT( EOS::" << s << ", ";
out << "FC_REFLECT( eos::" << std::setw(33) << s << ", ";
}
for( const auto& f : st.fields ) {
out <<"("<<f.name<<")";
......@@ -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() )
return st.fields.size() + count_fields( ss, ss.getType( st.base ) );
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 ) {
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]);
EOS::SimpleSymbolTable ss;
eos::SimpleSymbolTable ss;
ss.parse(in);
auto as_json = fc::json::to_pretty_string( ss );
std:: cerr << as_json << "\n";
generate_hpp( ss, argv[4] );
generate_hpp( ss, argv[2] );
/*
generate_cpp( ss, argv[2], argv[3] );
/*
auto w = generate_wren( ss.getType( "Message" ), ss );
std::cerr << w <<"\n";
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 FixedString16 PermissionName
typedef FixedString16 MessageType
typedef UInt32 AccountPermissionWeight
typedef UInt32 GeneratedTransactionID
typedef FixedString32 MessageName
typedef FixedString32 TypeName
# import account type as localtype
......@@ -22,18 +9,24 @@ struct Message
sender AccountName # testing
recipient AccountName
notify AccountName[]
type MessageType
type TypeName
data Bytes
struct AccountPermission
account AccountName
permission PermissionName
struct AccountPermissionWeight
permission AccountPermission
weight UInt16
struct Transaction
ref_block_num UInt16
ref_block_prefix UInt32
expiration Time
tapos UInt32
messages Message[]
permissions AccountPermission[]
authorization AccountPermission[]
struct SignedTransaction inherits Transaction
signatures Signature[]
......@@ -47,41 +40,43 @@ struct Authority
keys KeyPermissionWeight[]
accounts AccountPermissionWeight[]
struct Transfer
from AccountName # may not be the message.sender if message.sender has delegated authority by from
to AccountName
amount Asset
memo String
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
from AccountName
to AccountName
amount UInt64
memo String
deposit Asset
struct CreateProducer
account AccountName
name AccountName
key PublicKey
struct VoteOnProducer
account AccountName
# implies message.sender account
struct ApproveProducer
producer AccountName
weight Int8
approve Int8 # 0 or 1
struct SetProducerVoteProxy
account AccountName
# implies message.sender account
struct SetVoteProxy
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
read_write::push_block_results read_write::push_block(const read_write::push_block_params& 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) {
db.push_transaction(params);
return read_write::push_transaction_results();
}
} // namespace chain_apis
......
......@@ -8,21 +8,6 @@
namespace eos {
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.
......@@ -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 @@
#include <eos/chain/account_object.hpp>
#include <eos/chain/exceptions.hpp>
#include <eos/types/native.hpp>
#include <eos/types/generated.hpp>
namespace eos {
using namespace chain;
/************************************************************
*
* Transfer Handlers
*
***********************************************************/
void Transfer_validate(chain::message_validate_context& context) {
auto transfer = context.msg.as<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) {
const auto& db = context.db;
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));
}
void Transfer_apply(chain::apply_context& context) {
auto& db = context.mutable_db;
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);
db.modify(from, [&](account_object& a) {
a.balance -= transfer.amount;
......@@ -28,39 +42,62 @@ void Transfer_apply(chain::apply_context& context) {
db.modify(to, [&](account_object& a) {
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) {
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) {
const auto& db = context.db;
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,
"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);
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())
db.get_account(account);
for (const auto& account : create.active.referenced_accounts())
db.get_account(account);
Authority_validate_preconditions( create.owner, context );
Authority_validate_preconditions( create.active, context );
Authority_validate_preconditions( create.recovery, context );
}
void CreateAccount_apply(chain::apply_context& context) {
auto& db = context.mutable_db;
auto create = context.msg.as<CreateAccount>();
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) {
a.name = create.new_account;
a.balance = create.initial_balance;
a.name = create.name;
a.balance = create.deposit;
});
const auto& owner_permission = db.create<permission_object>([&create, &new_account](permission_object& p) {
p.name = "owner";
......@@ -75,6 +112,7 @@ void CreateAccount_apply(chain::apply_context& context) {
p.auth = std::move(create.active);
});
}
///@} Create Account Handlers
class native_system_contract_plugin_impl {
public:
......
......@@ -68,21 +68,36 @@ BOOST_FIXTURE_TEST_CASE(transfer, testing_fixture)
BOOST_REQUIRE_THROW(db.push_transaction(trx), transaction_exception); // no messages
trx.messages.resize(1);
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].recipient = "sys";
trx.messages[0].type = "Undefined";
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].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"
wlog( "." );
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);
wlog( "." );
BOOST_CHECK_EQUAL(db.get_account("init1").balance, 100000 - 100);
BOOST_CHECK_EQUAL(db.get_account("init2").balance, 100000 + 100);
BOOST_CHECK_EQUAL(db.get_account("init1").balance, Asset(100000 - 100));
BOOST_CHECK_EQUAL(db.get_account("init2").balance, Asset(100000 + 100));
db.produce_blocks(1);
BOOST_REQUIRE_THROW(db.push_transaction(trx), transaction_exception); // not unique
......@@ -97,7 +112,7 @@ BOOST_FIXTURE_TEST_CASE(create_account, testing_fixture)
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"));
public_key_type joe_public_key = joe_private_key.get_public_key();
......@@ -105,17 +120,17 @@ BOOST_FIXTURE_TEST_CASE(create_account, testing_fixture)
signed_transaction trx;
trx.messages.resize(1);
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].recipient = "sys";
trx.messages[0].type = "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);
const auto& joe_account = db.get_account("joe");
BOOST_CHECK_EQUAL(joe_account.balance, 1000);
BOOST_CHECK_EQUAL(init1_account.balance, 100000 - 1000);
BOOST_CHECK_EQUAL(joe_account.balance, Asset(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"));
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.
先完成此消息的编辑!
想要评论请 注册