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

Removing Dependencies on Old Boost

- remove BTS P2P code which depended on fc threads which depended on
deprecated boost::context API

- remove fc submodule and making fc part of eos repository
上级 b4fb074e
[submodule "libraries/fc"]
path = libraries/fc
url = https://github.com/eosio/fc.git
ignore = dirty
[submodule "libraries/chainbase"]
path = libraries/chainbase
url = https://github.com/eosio/chainbase
......
......@@ -5,6 +5,5 @@ add_subdirectory( types )
add_subdirectory( deterministic_openssl_rand )
add_subdirectory( chain )
add_subdirectory( egenesis )
add_subdirectory( net )
add_subdirectory( utilities )
add_subdirectory( appbase )
......@@ -39,7 +39,6 @@
#include <fc/smart_ref_impl.hpp>
#include <fc/uint128.hpp>
#include <fc/crypto/digest.hpp>
#include <fc/io/fstream.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/range/adaptor/transformed.hpp>
......
......@@ -33,7 +33,8 @@
#include <chainbase/chainbase.hpp>
#include <fc/scoped_exit.hpp>
#include <fc/signals.hpp>
#include <boost/signals2/signal.hpp>
#include <eos/chain/protocol.hpp>
......@@ -45,6 +46,7 @@ namespace eos { namespace chain {
class chain_controller;
using database = chainbase::database;
using boost::signals2::signal;
class message_validate_context {
public:
......@@ -102,13 +104,13 @@ namespace eos { namespace chain {
* the write lock and may be in an "inconstant state" until after it is
* released.
*/
fc::signal<void(const signed_block&)> applied_block;
signal<void(const signed_block&)> applied_block;
/**
* This signal is emitted any time a new transaction is added to the pending
* block state.
*/
fc::signal<void(const SignedTransaction&)> on_pending_transaction;
signal<void(const SignedTransaction&)> on_pending_transaction;
template<typename T>
void register_type( AccountName scope ) {
......
......@@ -24,11 +24,9 @@
#include <fc/crypto/elliptic.hpp>
#include <fc/crypto/sha256.hpp>
#include <fc/time.hpp>
#include <fc/thread/thread.hpp>
#include <iostream>
#include <algorithm>
#include <fc/crypto/sha512.hpp>
//#include <eos/blockchain/config.hpp>
#include <cstdio>
#include <cstdlib>
......
......@@ -30,9 +30,9 @@
#include <boost/algorithm/string.hpp>
#include <fc/filesystem.hpp>
#include <fc/io/fstream.hpp>
#include <fc/smart_ref_impl.hpp> // required for gcc in release mode
#include <fc/string.hpp>
#include <fc/io/fstream.hpp>
#include <fc/io/json.hpp>
#include <eos/chain/genesis_state.hpp>
#include <eos/chain/types.hpp>
......@@ -276,7 +276,7 @@ int main( int argc, char** argv )
read_file_contents( fc::path( src ), tmpl );
std::string out_str = fc::format_string( tmpl, template_context );
fc::path dest_filename = fc::path( dest );
fc::ofstream outfile( dest_filename );
std::ofstream outfile( dest_filename.generic_string().c_str() );
outfile.write( out_str.c_str(), out_str.size() );
outfile.close();
}
......
Subproject commit 7d5ddb1fabe2524a881bc88af4e9020c9d06fbd5
# Setup module path to make visible used CMake extensions
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/GitVersionGen")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules")
INCLUDE(GetPrerequisites)
INCLUDE( VersionMacros )
INCLUDE( SetupTargetMacros )
INCLUDE(GetGitRevisionDescription)
get_git_head_revision(GIT_REFSPEC FC_GIT_REVISION_SHA)
get_git_unix_timestamp(FC_GIT_REVISION_UNIX_TIMESTAMP)
SET( DEFAULT_HEADER_INSTALL_DIR include/\${target} )
SET( DEFAULT_LIBRARY_INSTALL_DIR lib/ )
SET( DEFAULT_EXECUTABLE_INSTALL_DIR bin/ )
SET( CMAKE_DEBUG_POSTFIX _debug )
SET( BUILD_SHARED_LIBS NO )
SET( ECC_IMPL secp256k1 CACHE STRING "secp256k1 or openssl or mixed" )
set(platformBitness 32)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(platformBitness 64)
endif()
SET (ORIGINAL_LIB_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
IF( ECC_IMPL STREQUAL openssl )
SET( ECC_REST src/crypto/elliptic_impl_pub.cpp )
ELSE( ECC_IMPL STREQUAL openssl )
SET( ECC_LIB secp256k1 )
IF( ECC_IMPL STREQUAL mixed )
SET( ECC_REST src/crypto/elliptic_impl_priv.cpp src/crypto/elliptic_impl_pub.cpp )
ELSE( ECC_IMPL STREQUAL mixed )
SET( ECC_REST src/crypto/elliptic_impl_priv.cpp )
ENDIF( ECC_IMPL STREQUAL mixed )
ENDIF( ECC_IMPL STREQUAL openssl )
MESSAGE(STATUS "Configuring fc to build on Unix/Apple")
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".a;.so")
IF(NOT APPLE)
# Linux or other unix
SET(rt_library rt )
SET(pthread_library pthread)
ENDIF(NOT APPLE)
IF(NOT "$ENV{OPENSSL_ROOT_DIR}" STREQUAL "")
set(OPENSSL_ROOT_DIR $ENV{OPENSSL_ROOT_DIR} )
set(OPENSSL_INCLUDE_DIR ${OPENSSL_ROOT_DIR}/include)
message(STATUS "Setting up OpenSSL root and include vars to ${OPENSSL_ROOT_DIR}, ${OPENSSL_INCLUDE_DIR}")
ENDIF()
find_package(OpenSSL REQUIRED)
set( CMAKE_FIND_LIBRARY_SUFFIXES ${ORIGINAL_LIB_SUFFIXES} )
set( fc_sources
src/uint128.cpp
src/real128.cpp
src/variant.cpp
src/exception.cpp
src/variant_object.cpp
src/string.cpp
src/shared_ptr.cpp
src/time.cpp
src/utf8.cpp
src/io/datastream.cpp
src/io/json.cpp
src/io/varint.cpp
src/io/fstream.cpp
src/filesystem.cpp
src/interprocess/file_mapping.cpp
src/interprocess/mmap_struct.cpp
src/log/log_message.cpp
src/log/logger.cpp
src/log/appender.cpp
src/log/console_appender.cpp
src/log/logger_config.cpp
src/crypto/_digest_common.cpp
src/crypto/openssl.cpp
src/crypto/aes.cpp
src/crypto/crc.cpp
src/crypto/city.cpp
src/crypto/base32.cpp
src/crypto/base36.cpp
src/crypto/base58.cpp
src/crypto/base64.cpp
src/crypto/bigint.cpp
src/crypto/hex.cpp
src/crypto/sha1.cpp
src/crypto/ripemd160.cpp
src/crypto/sha256.cpp
src/crypto/sha224.cpp
src/crypto/sha512.cpp
src/crypto/dh.cpp
src/crypto/blowfish.cpp
src/crypto/elliptic_common.cpp
${ECC_REST}
src/crypto/elliptic_${ECC_IMPL}.cpp
src/crypto/rand.cpp
src/network/ip.cpp
src/network/url.cpp
src/compress/smaz.cpp
src/compress/zlib.cpp
vendor/cyoencode-1.0.2/src/CyoDecode.c
vendor/cyoencode-1.0.2/src/CyoEncode.c
)
file( GLOB_RECURSE fc_headers ${CMAKE_CURRENT_SOURCE_DIR} *.hpp *.h )
set( sources
${fc_sources}
)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/git_revision.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/git_revision.cpp" @ONLY)
list(APPEND sources "${CMAKE_CURRENT_BINARY_DIR}/git_revision.cpp")
list(APPEND sources ${fc_headers})
setup_library( fc SOURCES ${sources} LIBRARY_TYPE STATIC DONT_INSTALL_LIBRARY )
IF(APPLE)
# As of 10.10 yosemite, the OpenSSL static libraries shipped with os x have a dependency
# on zlib, so any time you link in openssl you also need to link zlib. . We really want to detect whether openssl was configured with the --no-zlib
# option or not when it was built, but that's difficult to do in practice, so we
# just always try to link it in on mac.
find_package( ZLIB REQUIRED )
ELSE(APPLE)
find_package( ZLIB )
ENDIF(APPLE)
if( ZLIB_FOUND )
MESSAGE( STATUS "zlib found" )
add_definitions( -DHAS_ZLIB )
else()
MESSAGE( STATUS "zlib not found" )
set( ZLIB_LIBRARIES "" )
endif( ZLIB_FOUND )
find_package( BZip2 )
if( BZIP2_FOUND )
MESSAGE( STATUS "bzip2 found" )
add_definitions( -DHAS_BZIP2 )
else()
MESSAGE( STATUS "bzip2 not found" )
set( BZIP2_LIBRARIES "" )
endif( BZIP2_FOUND )
# This will become unnecessary once we update to websocketpp which fixes upstream issue #395
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWEBSOCKETPP_STRICT_MASKING")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBOOST_ASIO_HAS_STD_CHRONO")
target_include_directories(fc
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include
${Boost_INCLUDE_DIR}
${OPENSSL_INCLUDE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/vendor/websocketpp
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/vendor/boost_1.51/include
${CMAKE_CURRENT_SOURCE_DIR}/vendor/cyoencode-1.0.2/src
)
IF(NOT WIN32)
set(LINK_USR_LOCAL_LIB -L/usr/local/lib)
ENDIF()
target_link_libraries( fc PUBLIC ${LINK_USR_LOCAL_LIB} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES} ${BZIP2_LIBRARIES} ${PLATFORM_SPECIFIC_LIBS} ${RPCRT4} ${CMAKE_DL_LIBS} ${rt_library} ${readline_libraries} ${ECC_LIB} )
SET(OPENSSL_CONF_TARGET )
IF(DEFINED CMAKE_RUNTIME_OUTPUT_DIRECTORY)
SET (OPENSSL_CONF_TARGET ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
ELSE()
SET (OPENSSL_CONF_TARGET ${CMAKE_CURRENT_BINARY_DIR})
ENDIF()
#pragma once
#include <fc/api.hpp>
#include <fc/thread/thread.hpp>
namespace fc {
namespace detail {
struct actor_member {
#if 1 // BOOST_NO_VARIADIC_TEMPLATES
#define RPC_MEMBER_FUNCTOR(z,n,IS_CONST) \
template<typename R, typename C, typename P BOOST_PP_ENUM_TRAILING_PARAMS( n, typename A)> \
static std::function<fc::future<R>( BOOST_PP_ENUM_PARAMS(n,A) ) > \
functor( P p, R (C::*mem_func)(BOOST_PP_ENUM_PARAMS(n,A)) IS_CONST, fc::thread* c = 0) { \
return [=](BOOST_PP_ENUM_BINARY_PARAMS(n,A,a))->fc::future<R>{ \
return c->async( [=](){ return (p->*mem_func)(BOOST_PP_ENUM_PARAMS(n,a)); } ); }; \
}
BOOST_PP_REPEAT( 8, RPC_MEMBER_FUNCTOR, const )
BOOST_PP_REPEAT( 8, RPC_MEMBER_FUNCTOR, BOOST_PP_EMPTY() )
#undef RPC_MEMBER_FUNCTOR
#else // g++ has a bug that prevents lambdas and varidic templates from working together (G++ Bug 41933)
template<typename R, typename C, typename P, typename... Args>
static std::function<fc::future<R>(Args...)> functor( P&& p, R (C::*mem_func)(Args...), fc::thread* c ) {
return [=](Args... args)->fc::future<R>{ c->async( [=]()->R { return p->*mem_func( fc::forward<Args>(args)... ); } ) };
}
template<typename R, typename C, typename P, typename... Args>
static std::function<fc::future<R>(Args...)> functor( P&& p, R (C::*mem_func)(Args...)const, fc::thread* c ){
return [=](Args... args)->fc::future<R>{ c->async( [=]()->R { return p->*mem_func( fc::forward<Args>(args)... ); } ) };
}
#endif
};
template<typename ThisPtr>
struct actor_vtable_visitor {
template<typename U>
actor_vtable_visitor( fc::thread* t, U&& u ):_thread(t),_this( fc::forward<U>(u) ){}
template<typename Function, typename MemberPtr>
void operator()( const char* name, Function& memb, MemberPtr m )const {
memb = actor_member::functor( _this, m, _thread );
}
fc::thread* _thread;
ThisPtr _this;
};
}
/**
* Posts all method calls to another thread and
* returns a future.
*/
template<typename Interface>
class actor : public api<Interface, detail::actor_member> {
public:
actor(){}
template<typename InterfaceType>
actor( InterfaceType* p, fc::thread* t = &fc::thread::current() )
{
this->_vtable.reset(new detail::vtable<Interface,detail::actor_member>() );
this->_vtable->template visit<InterfaceType>( detail::actor_vtable_visitor<InterfaceType*>(t, p) );
}
};
} // namespace fc
#pragma once
namespace fc {
template<unsigned int S, typename T=double>
struct aligned {
union {
T _align;
char _data[S];
} _store;
operator char*() { return _store._data; }
operator const char*()const { return _store._data; }
};
}
#pragma once
#include <boost/any.hpp>
namespace fc {
// TODO: define this without using boost
typedef boost::any any;
}
#pragma once
#include <fc/thread/future.hpp>
#include <fc/any.hpp>
#include <functional>
#include <boost/config.hpp>
// ms visual c++ (as of 2013) doesn't accept the standard syntax for calling a
// templated member function (foo->template bar();)
#ifdef _MSC_VER
# define FC_CALL_MEMBER_TEMPLATE_KEYWORD
#else
# define FC_CALL_MEMBER_TEMPLATE_KEYWORD template
#endif
namespace fc {
struct identity_member {
template<typename R, typename C, typename P, typename... Args>
static std::function<R(Args...)> functor( P&& p, R (C::*mem_func)(Args...) );
template<typename R, typename C, typename P, typename... Args>
static std::function<R(Args...)> functor( P&& p, R (C::*mem_func)(Args...)const );
};
template< typename Interface, typename Transform >
struct vtable : public std::enable_shared_from_this<vtable<Interface,Transform>>
{ private: vtable(); };
template<typename OtherType>
struct vtable_copy_visitor {
typedef OtherType other_type;
vtable_copy_visitor( OtherType& s):_source( s ){}
template<typename R, typename MemberPtr, typename... Args>
void operator()( const char* name, std::function<R(Args...)>& memb, MemberPtr m )const {
OtherType* src = &_source;
memb = [src,m]( Args... args ){ return (src->*m)(args...); };
}
OtherType& _source;
};
template<typename Interface, typename Transform >
class api;
class api_connection;
typedef uint32_t api_id_type;
class api_base
{
public:
api_base() {}
virtual ~api_base() {}
virtual uint64_t get_handle()const = 0;
virtual api_id_type register_api( api_connection& conn )const = 0;
// defined in api_connection.hpp
template< typename T >
api<T, identity_member> as();
};
typedef std::shared_ptr< api_base > api_ptr;
class api_connection;
template<typename Interface, typename Transform = identity_member >
class api : public api_base {
public:
typedef vtable<Interface,Transform> vtable_type;
api():_vtable( std::make_shared<vtable_type>() ) {}
/** T is anything with pointer semantics */
template<typename T >
api( const T& p )
:_vtable( std::make_shared<vtable_type>() )
{
_data = std::make_shared<fc::any>(p);
T& ptr = boost::any_cast<T&>(*_data);
auto& pointed_at = *ptr;
typedef typename std::remove_reference<decltype(pointed_at)>::type source_vtable_type;
_vtable->FC_CALL_MEMBER_TEMPLATE_KEYWORD visit_other( vtable_copy_visitor<source_vtable_type>(pointed_at) );
}
api( const api& cpy ):_vtable(cpy._vtable),_data(cpy._data) {}
virtual ~api() {}
friend bool operator == ( const api& a, const api& b ) { return a._data == b._data && a._vtable == b._vtable; }
friend bool operator != ( const api& a, const api& b ) { return !(a._data == b._data && a._vtable == b._vtable); }
virtual uint64_t get_handle()const override { return uint64_t(_data.get()); }
virtual api_id_type register_api( api_connection& conn )const override; // defined in api_connection.hpp
vtable_type& operator*()const { FC_ASSERT( _vtable ); return *_vtable; }
vtable_type* operator->()const { FC_ASSERT( _vtable ); return _vtable.get(); }
protected:
std::shared_ptr<vtable_type> _vtable;
std::shared_ptr<fc::any> _data;
};
} // namespace fc
#include <boost/preprocessor/repeat.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#include <boost/preprocessor/facilities/empty.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/stringize.hpp>
#define FC_API_VTABLE_DEFINE_MEMBER( r, data, elem ) \
decltype(Transform::functor( (data*)nullptr, &data::elem)) elem;
#define FC_API_VTABLE_DEFINE_VISIT_OTHER( r, data, elem ) \
{ typedef typename Visitor::other_type OtherType; \
v( BOOST_PP_STRINGIZE(elem), elem, &OtherType::elem ); }
#define FC_API_VTABLE_DEFINE_VISIT( r, data, elem ) \
v( BOOST_PP_STRINGIZE(elem), elem );
#define FC_API( CLASS, METHODS ) \
namespace fc { \
template<typename Transform> \
struct vtable<CLASS,Transform> : public std::enable_shared_from_this<vtable<CLASS,Transform>> { \
BOOST_PP_SEQ_FOR_EACH( FC_API_VTABLE_DEFINE_MEMBER, CLASS, METHODS ) \
template<typename Visitor> \
void visit_other( Visitor&& v ){ \
BOOST_PP_SEQ_FOR_EACH( FC_API_VTABLE_DEFINE_VISIT_OTHER, CLASS, METHODS ) \
} \
template<typename Visitor> \
void visit( Visitor&& v ){ \
BOOST_PP_SEQ_FOR_EACH( FC_API_VTABLE_DEFINE_VISIT, CLASS, METHODS ) \
} \
}; \
}
#pragma once
#include <fc/crypto/base64.hpp>
#include <fc/variant.hpp>
#include <fc/reflect/reflect.hpp>
namespace fc {
/**
* Provides a fixed size array that is easier for templates to specialize
* against or overload than T[N].
*/
template<typename T, size_t N>
class array {
public:
/**
* Checked indexing (when in debug build) that also simplifies dereferencing
* when you have an array<T,N>*.
*/
///@{
T& at( size_t pos ) { assert( pos < N); return data[pos]; }
const T& at( size_t pos )const { assert( pos < N); return data[pos]; }
///@}
T& operator[]( size_t pos ) { assert( pos < N); return data[pos]; }
const T& operator[]( size_t pos )const { assert( pos < N); return data[pos]; }
const T* begin()const { return &data[0]; }
const T* end()const { return &data[N]; }
T* begin() { return &data[0]; }
T* end() { return &data[N]; }
size_t size()const { return N; }
T data[N];
};
/** provided for default 0 init */
template<size_t N>
class array<unsigned char,N>
{
public:
typedef unsigned char T;
array(){ memset( data, 0, sizeof(data) ); }
/**
* Checked indexing (when in debug build) that also simplifies dereferencing
* when you have an array<T,N>*.
*/
///@{
T& at( size_t pos ) { assert( pos < N); return data[pos]; }
const T& at( size_t pos )const { assert( pos < N); return data[pos]; }
///@}
T* begin() { return &data[0]; }
const T* begin()const { return &data[0]; }
const T* end()const { return &data[N]; }
size_t size()const { return N; }
T data[N];
};
/** provided for default 0 init */
template<size_t N>
class array<char,N>
{
public:
typedef char T;
array(){ memset( data, 0, sizeof(data) ); }
/**
* Checked indexing (when in debug build) that also simplifies dereferencing
* when you have an array<T,N>*.
*/
///@{
T& at( size_t pos ) { assert( pos < N); return data[pos]; }
const T& at( size_t pos )const { assert( pos < N); return data[pos]; }
///@}
T* begin() { return &data[0]; }
const T* begin()const { return &data[0]; }
const T* end()const { return &data[N]; }
size_t size()const { return N; }
T data[N];
};
template<typename T, size_t N>
bool operator == ( const array<T,N>& a, const array<T,N>& b )
{ return 0 == memcmp( a.data, b.data, N*sizeof(T) ); }
template<typename T, size_t N>
bool operator < ( const array<T,N>& a, const array<T,N>& b )
{ return memcmp( a.data, b.data, N*sizeof(T) ) < 0 ; }
template<typename T, size_t N>
bool operator > ( const array<T,N>& a, const array<T,N>& b )
{ return memcmp( a.data, b.data, N*sizeof(T) ) > 0 ; }
template<typename T, size_t N>
bool operator != ( const array<T,N>& a, const array<T,N>& b )
{ return 0 != memcmp( a.data, b.data, N*sizeof(T) ); }
template<typename T, size_t N>
void to_variant( const array<T,N>& bi, variant& v )
{
v = std::vector<char>( (const char*)&bi, ((const char*)&bi) + sizeof(bi) );
}
template<typename T, size_t N>
void from_variant( const variant& v, array<T,N>& bi )
{
std::vector<char> ve = v.as< std::vector<char> >();
if( ve.size() )
{
memcpy(&bi, ve.data(), fc::min<size_t>(ve.size(),sizeof(bi)) );
}
else
memset( &bi, char(0), sizeof(bi) );
}
template<typename T,size_t N> struct get_typename< fc::array<T,N> >
{
static const char* name()
{
static std::string _name = std::string("fc::array<")+std::string(fc::get_typename<T>::name())+","+ fc::to_string(N) + ">";
return _name.c_str();
}
};
}
#include <unordered_map>
#include <fc/crypto/city.hpp>
namespace std
{
template<typename T, size_t N>
struct hash<fc::array<T,N> >
{
size_t operator()( const fc::array<T,N>& e )const
{
return fc::city_hash_size_t( (char*)&e, sizeof(e) );
}
};
}
#pragma once
#include <stdint.h>
namespace fc {
inline uint64_t endian_reverse_u64( uint64_t x )
{
return (((x >> 0x38) & 0xFF) )
| (((x >> 0x30) & 0xFF) << 0x08)
| (((x >> 0x28) & 0xFF) << 0x10)
| (((x >> 0x20) & 0xFF) << 0x18)
| (((x >> 0x18) & 0xFF) << 0x20)
| (((x >> 0x10) & 0xFF) << 0x28)
| (((x >> 0x08) & 0xFF) << 0x30)
| (((x ) & 0xFF) << 0x38)
;
}
inline uint32_t endian_reverse_u32( uint32_t x )
{
return (((x >> 0x18) & 0xFF) )
| (((x >> 0x10) & 0xFF) << 0x08)
| (((x >> 0x08) & 0xFF) << 0x10)
| (((x ) & 0xFF) << 0x18)
;
}
} // namespace fc
此差异已折叠。
#pragma once
#include <string>
namespace fc {
std::string smaz_compress( const std::string& in );
std::string smaz_decompress( const std::string& compressed );
} // namespace fc
#pragma once
#include <fc/string.hpp>
namespace fc
{
string zlib_compress(const string& in);
} // namespace fc
#pragma once
#include <deque>
#include <fc/io/raw.hpp>
namespace fc {
namespace raw {
} // namespace raw
} // namespace fc
#pragma once
#include <deque>
namespace fc {
namespace raw {
template<typename Stream, typename T>
void pack( Stream& s, const std::deque<T>& value );
template<typename Stream, typename T>
void unpack( Stream& s, std::deque<T>& value );
}
} // namespace fc
#pragma once
#include <fc/variant.hpp>
#include <fc/container/flat_fwd.hpp>
#include <boost/container/flat_map.hpp>
#include <boost/container/flat_set.hpp>
#include <fc/io/raw_fwd.hpp>
namespace fc {
namespace raw {
template<typename Stream, typename T>
inline void pack( Stream& s, const flat_set<T>& value ) {
pack( s, unsigned_int((uint32_t)value.size()) );
auto itr = value.begin();
auto end = value.end();
while( itr != end ) {
fc::raw::pack( s, *itr );
++itr;
}
}
template<typename Stream, typename T>
inline void unpack( Stream& s, flat_set<T>& value ) {
unsigned_int size; unpack( s, size );
value.clear();
FC_ASSERT( size.value*sizeof(T) < MAX_ARRAY_ALLOC_SIZE );
value.reserve(size.value);
for( uint32_t i = 0; i < size.value; ++i )
{
T tmp;
fc::raw::unpack( s, tmp );
value.insert( std::move(tmp) );
}
}
template<typename Stream, typename K, typename... V>
inline void pack( Stream& s, const flat_map<K,V...>& value ) {
pack( s, unsigned_int((uint32_t)value.size()) );
auto itr = value.begin();
auto end = value.end();
while( itr != end ) {
fc::raw::pack( s, *itr );
++itr;
}
}
template<typename Stream, typename K, typename V, typename... A>
inline void unpack( Stream& s, flat_map<K,V,A...>& value )
{
unsigned_int size; unpack( s, size );
value.clear();
FC_ASSERT( size.value*(sizeof(K)+sizeof(V)) < MAX_ARRAY_ALLOC_SIZE );
value.reserve(size.value);
for( uint32_t i = 0; i < size.value; ++i )
{
std::pair<K,V> tmp;
fc::raw::unpack( s, tmp );
value.insert( std::move(tmp) );
}
}
template<typename Stream, typename T, typename A>
void pack( Stream& s, const bip::vector<T,A>& value ) {
pack( s, unsigned_int((uint32_t)value.size()) );
if( !std::is_fundamental<T>::value ) {
auto itr = value.begin();
auto end = value.end();
while( itr != end ) {
fc::raw::pack( s, *itr );
++itr;
}
} else {
s.write( (const char*)value.data(), value.size() );
}
}
template<typename Stream, typename T, typename A>
void unpack( Stream& s, bip::vector<T,A>& value ) {
unsigned_int size;
unpack( s, size );
value.resize( size );
if( !std::is_fundamental<T>::value ) {
for( auto& item : value )
unpack( s, item );
} else {
s.read( (char*)value.data(), value.size() );
}
}
} // namespace raw
template<typename T>
void to_variant( const flat_set<T>& var, variant& vo )
{
std::vector<variant> vars(var.size());
size_t i = 0;
for( auto itr = var.begin(); itr != var.end(); ++itr, ++i )
vars[i] = variant(*itr);
vo = vars;
}
template<typename T>
void from_variant( const variant& var, flat_set<T>& vo )
{
const variants& vars = var.get_array();
vo.clear();
vo.reserve( vars.size() );
for( auto itr = vars.begin(); itr != vars.end(); ++itr )
vo.insert( itr->as<T>() );
}
template<typename K, typename... T>
void to_variant( const flat_map<K, T...>& var, variant& vo )
{
std::vector< variant > vars(var.size());
size_t i = 0;
for( auto itr = var.begin(); itr != var.end(); ++itr, ++i )
vars[i] = fc::variant(*itr);
vo = vars;
}
template<typename K, typename T, typename... A>
void from_variant( const variant& var, flat_map<K, T, A...>& vo )
{
const variants& vars = var.get_array();
vo.clear();
for( auto itr = vars.begin(); itr != vars.end(); ++itr )
vo.insert( itr->as< std::pair<K,T> >() );
}
}
#pragma once
#include <boost/container/flat_map.hpp>
#include <boost/container/flat_set.hpp>
#include <boost/interprocess/containers/vector.hpp>
namespace fc {
using boost::container::flat_map;
using boost::container::flat_set;
namespace bip = boost::interprocess;
namespace raw {
template<typename Stream, typename T>
void pack( Stream& s, const flat_set<T>& value );
template<typename Stream, typename T>
void unpack( Stream& s, flat_set<T>& value );
template<typename Stream, typename K, typename... V>
void pack( Stream& s, const flat_map<K,V...>& value );
template<typename Stream, typename K, typename... V>
void unpack( Stream& s, flat_map<K,V...>& value ) ;
template<typename Stream, typename T, typename A>
void pack( Stream& s, const bip::vector<T,A>& value );
template<typename Stream, typename T, typename A>
void unpack( Stream& s, bip::vector<T,A>& value );
} // namespace raw
} // fc
#pragma once
#include <fc/crypto/sha512.hpp>
#include <fc/crypto/sha256.hpp>
#include <fc/uint128.hpp>
#include <fc/fwd.hpp>
#include <vector>
namespace fc {
class path;
class aes_encoder
{
public:
aes_encoder();
~aes_encoder();
void init( const fc::sha256& key, const fc::uint128& init_value );
uint32_t encode( const char* plaintxt, uint32_t len, char* ciphertxt );
// uint32_t final_encode( char* ciphertxt );
private:
struct impl;
fc::fwd<impl,96> my;
};
class aes_decoder
{
public:
aes_decoder();
~aes_decoder();
void init( const fc::sha256& key, const fc::uint128& init_value );
uint32_t decode( const char* ciphertxt, uint32_t len, char* plaintext );
// uint32_t final_decode( char* plaintext );
private:
struct impl;
fc::fwd<impl,96> my;
};
unsigned aes_encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key,
unsigned char *iv, unsigned char *ciphertext);
unsigned aes_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key,
unsigned char *iv, unsigned char *plaintext);
unsigned aes_cfb_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key,
unsigned char *iv, unsigned char *plaintext);
std::vector<char> aes_encrypt( const fc::sha512& key, const std::vector<char>& plain_text );
std::vector<char> aes_decrypt( const fc::sha512& key, const std::vector<char>& cipher_text );
/** encrypts plain_text and then includes a checksum that enables us to verify the integrety of
* the file / key prior to decryption.
*/
void aes_save( const fc::path& file, const fc::sha512& key, std::vector<char> plain_text );
/**
* recovers the plain_text saved via aes_save()
*/
std::vector<char> aes_load( const fc::path& file, const fc::sha512& key );
} // namespace fc
#pragma once
#include <fc/vector.hpp>
#include <fc/string.hpp>
namespace fc
{
std::vector<char> from_base32( const fc::string& b32 );
fc::string to_base32( const std::vector<char>& vec );
fc::string to_base32( const char* data, size_t len );
}
#pragma once
#include <fc/vector.hpp>
#include <fc/string.hpp>
namespace fc
{
std::vector<char> from_base36( const fc::string& b36 );
fc::string to_base36( const std::vector<char>& vec );
fc::string to_base36( const char* data, size_t len );
}
#pragma once
#include <fc/string.hpp>
#include <vector>
namespace fc {
std::string to_base58( const char* d, size_t s );
std::string to_base58( const std::vector<char>& data );
std::vector<char> from_base58( const std::string& base58_str );
size_t from_base58( const std::string& base58_str, char* out_data, size_t out_data_len );
}
#pragma once
#include <string>
namespace fc {
std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len);
inline std::string base64_encode(char const* bytes_to_encode, unsigned int in_len) { return base64_encode( (unsigned char const*)bytes_to_encode, in_len); }
std::string base64_encode( const std::string& enc );
std::string base64_decode( const std::string& encoded_string);
} // namespace fc
#pragma once
#include <stdint.h>
#include <fc/string.hpp>
#include <fc/vector.hpp>
struct bignum_st;
typedef bignum_st BIGNUM;
namespace fc {
class bigint {
public:
bigint( const std::vector<char>& bige );
bigint( const char* bige, uint32_t l );
bigint(uint64_t value);
bigint( );
bigint( const bigint& c );
bigint( bigint&& c );
explicit bigint( BIGNUM* n );
~bigint();
bigint& operator = ( const bigint& a );
bigint& operator = ( bigint&& a );
explicit operator bool()const;
bool is_negative()const;
int64_t to_int64()const;
int64_t log2()const;
bigint exp( const bigint& c )const;
static bigint random( uint32_t bits, int t, int );
bool operator < ( const bigint& c )const;
bool operator > ( const bigint& c )const;
bool operator >= ( const bigint& c )const;
bool operator == ( const bigint& c )const;
bool operator != ( const bigint& c )const;
bigint operator + ( const bigint& a )const;
bigint operator * ( const bigint& a )const;
bigint operator / ( const bigint& a )const;
bigint operator % ( const bigint& a )const;
bigint operator /= ( const bigint& a );
bigint operator *= ( const bigint& a );
bigint& operator += ( const bigint& a );
bigint& operator -= ( const bigint& a );
bigint& operator <<= ( uint32_t i );
bigint& operator >>= ( uint32_t i );
bigint operator - ( const bigint& a )const;
bigint operator++(int);
bigint& operator++();
bigint operator--(int);
bigint& operator--();
operator fc::string()const;
// returns bignum as bigendian bytes
operator std::vector<char>()const;
BIGNUM* dup()const;
BIGNUM* get()const { return n; }
private:
BIGNUM* n;
};
class variant;
/** encodes the big int as base64 string, or a number */
void to_variant( const bigint& bi, variant& v );
/** decodes the big int as base64 string, or a number */
void from_variant( const variant& v, bigint& bi );
} // namespace fc
////////////////////////////////////////////////////////////////////////////
///
// Blowfish.h Header File
//
// BLOWFISH ENCRYPTION ALGORITHM
//
// encryption and decryption of Byte Strings using the Blowfish encryption Algorithm.
// Blowfish is a block cipher that encrypts data in 8-byte blocks. The algorithm consists
// of two parts: a key-expansion part and a data-ancryption part. Key expansion converts a
// variable key of at least 1 and at most 56 bytes into several subkey arrays totaling
// 4168 bytes. Blowfish has 16 rounds. Each round consists of a key-dependent permutation,
// and a key and data-dependent substitution. All operations are XORs and additions on 32-bit words.
// The only additional operations are four indexed array data lookups per round.
// Blowfish uses a large number of subkeys. These keys must be precomputed before any data
// encryption or decryption. The P-array consists of 18 32-bit subkeys: P0, P1,...,P17.
// There are also four 32-bit S-boxes with 256 entries each: S0,0, S0,1,...,S0,255;
// S1,0, S1,1,...,S1,255; S2,0, S2,1,...,S2,255; S3,0, S3,1,...,S3,255;
//
// The Electronic Code Book (ECB), Cipher Block Chaining (CBC) and Cipher Feedback modes
// are used:
//
// In ECB mode if the same block is encrypted twice with the same key, the resulting
// ciphertext blocks are the same.
//
// In CBC Mode a ciphertext block is obtained by first xoring the
// plaintext block with the previous ciphertext block, and encrypting the resulting value.
//
// In CFB mode a ciphertext block is obtained by encrypting the previous ciphertext block
// and xoring the resulting value with the plaintext
//
// The previous ciphertext block is usually stored in an Initialization Vector (IV).
// An Initialization Vector of zero is commonly used for the first block, though other
// arrangements are also in use.
/*
http://www.counterpane.com/vectors.txt
Test vectors by Eric Young. These tests all assume Blowfish with 16
rounds.
All data is shown as a hex string with 012345 loading as
data[0]=0x01;
data[1]=0x23;
data[2]=0x45;
ecb test data (taken from the DES validation tests)
key bytes clear bytes cipher bytes
0000000000000000 0000000000000000 4EF997456198DD78
FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF 51866FD5B85ECB8A
3000000000000000 1000000000000001 7D856F9A613063F2 ???
1111111111111111 1111111111111111 2466DD878B963C9D
0123456789ABCDEF 1111111111111111 61F9C3802281B096
1111111111111111 0123456789ABCDEF 7D0CC630AFDA1EC7
0000000000000000 0000000000000000 4EF997456198DD78
FEDCBA9876543210 0123456789ABCDEF 0ACEAB0FC6A0A28D
7CA110454A1A6E57 01A1D6D039776742 59C68245EB05282B
0131D9619DC1376E 5CD54CA83DEF57DA B1B8CC0B250F09A0
07A1133E4A0B2686 0248D43806F67172 1730E5778BEA1DA4
3849674C2602319E 51454B582DDF440A A25E7856CF2651EB
04B915BA43FEB5B6 42FD443059577FA2 353882B109CE8F1A
0113B970FD34F2CE 059B5E0851CF143A 48F4D0884C379918
0170F175468FB5E6 0756D8E0774761D2 432193B78951FC98
43297FAD38E373FE 762514B829BF486A 13F04154D69D1AE5
07A7137045DA2A16 3BDD119049372802 2EEDDA93FFD39C79
04689104C2FD3B2F 26955F6835AF609A D887E0393C2DA6E3
37D06BB516CB7546 164D5E404F275232 5F99D04F5B163969
1F08260D1AC2465E 6B056E18759F5CCA 4A057A3B24D3977B
584023641ABA6176 004BD6EF09176062 452031C1E4FADA8E
025816164629B007 480D39006EE762F2 7555AE39F59B87BD
49793EBC79B3258F 437540C8698F3CFA 53C55F9CB49FC019
4FB05E1515AB73A7 072D43A077075292 7A8E7BFA937E89A3
49E95D6D4CA229BF 02FE55778117F12A CF9C5D7A4986ADB5
018310DC409B26D6 1D9D5C5018F728C2 D1ABB290658BC778
1C587F1C13924FEF 305532286D6F295A 55CB3774D13EF201
0101010101010101 0123456789ABCDEF FA34EC4847B268B2
1F1F1F1F0E0E0E0E 0123456789ABCDEF A790795108EA3CAE
E0FEE0FEF1FEF1FE 0123456789ABCDEF C39E072D9FAC631D
0000000000000000 FFFFFFFFFFFFFFFF 014933E0CDAFF6E4
FFFFFFFFFFFFFFFF 0000000000000000 F21E9A77B71C49BC
0123456789ABCDEF 0000000000000000 245946885754369A
FEDCBA9876543210 FFFFFFFFFFFFFFFF 6B5C5A9C5D9E0A5A
set_key test data
data[8]= FEDCBA9876543210
c=F9AD597C49DB005E k[ 1]=F0
c=E91D21C1D961A6D6 k[ 2]=F0E1
c=E9C2B70A1BC65CF3 k[ 3]=F0E1D2
c=BE1E639408640F05 k[ 4]=F0E1D2C3
c=B39E44481BDB1E6E k[ 5]=F0E1D2C3B4
c=9457AA83B1928C0D k[ 6]=F0E1D2C3B4A5
c=8BB77032F960629D k[ 7]=F0E1D2C3B4A596
c=E87A244E2CC85E82 k[ 8]=F0E1D2C3B4A59687
c=15750E7A4F4EC577 k[ 9]=F0E1D2C3B4A5968778
c=122BA70B3AB64AE0 k[10]=F0E1D2C3B4A596877869
c=3A833C9AFFC537F6 k[11]=F0E1D2C3B4A5968778695A
c=9409DA87A90F6BF2 k[12]=F0E1D2C3B4A5968778695A4B
c=884F80625060B8B4 k[13]=F0E1D2C3B4A5968778695A4B3C
c=1F85031C19E11968 k[14]=F0E1D2C3B4A5968778695A4B3C2D
c=79D9373A714CA34F k[15]=F0E1D2C3B4A5968778695A4B3C2D1E ???
c=93142887EE3BE15C k[16]=F0E1D2C3B4A5968778695A4B3C2D1E0F
c=03429E838CE2D14B k[17]=F0E1D2C3B4A5968778695A4B3C2D1E0F00
c=A4299E27469FF67B k[18]=F0E1D2C3B4A5968778695A4B3C2D1E0F0011
c=AFD5AED1C1BC96A8 k[19]=F0E1D2C3B4A5968778695A4B3C2D1E0F001122
c=10851C0E3858DA9F k[20]=F0E1D2C3B4A5968778695A4B3C2D1E0F00112233
c=E6F51ED79B9DB21F k[21]=F0E1D2C3B4A5968778695A4B3C2D1E0F0011223344
c=64A6E14AFD36B46F k[22]=F0E1D2C3B4A5968778695A4B3C2D1E0F001122334455
c=80C7D7D45A5479AD k[23]=F0E1D2C3B4A5968778695A4B3C2D1E0F00112233445566
c=05044B62FA52D080 k[24]=F0E1D2C3B4A5968778695A4B3C2D1E0F0011223344556677
chaining mode test data
key[16] = 0123456789ABCDEFF0E1D2C3B4A59687
iv[8] = FEDCBA9876543210
data[29] = "7654321 Now is the time for " (includes trailing '\0')
data[29] = 37363534333231204E6F77206973207468652074696D6520666F722000
cbc cipher text
cipher[32]= 6B77B4D63006DEE605B156E27403979358DEB9E7154616D959F1652BD5FF92CC
cfb64 cipher text cipher[29]=
E73214A2822139CAF26ECF6D2EB9E76E3DA3DE04D1517200519D57A6C3
ofb64 cipher text cipher[29]=
E73214A2822139CA62B343CC5B65587310DD908D0C241B2263C2CF80DA
*/
#pragma once
#include <stdint.h>
namespace fc {
//Block Structure
struct sblock
{
//Constructors
sblock(unsigned int l=0, unsigned int r=0) : m_uil(l), m_uir(r) {}
//Copy Constructor
sblock(const sblock& roBlock) : m_uil(roBlock.m_uil), m_uir(roBlock.m_uir) {}
sblock& operator^=(sblock& b) { m_uil ^= b.m_uil; m_uir ^= b.m_uir; return *this; }
unsigned int m_uil, m_uir;
};
class blowfish
{
public:
enum { ECB=0, CBC=1, CFB=2 };
//Constructor - Initialize the P and S boxes for a given Key
blowfish();
void start(unsigned char* ucKey, uint64_t n, const sblock& roChain = sblock(0UL,0UL));
//Resetting the chaining block
void reset_chain() { m_oChain = m_oChain0; }
// encrypt/decrypt Buffer in Place
void encrypt(unsigned char* buf, uint64_t n, int iMode=CFB);
void decrypt(unsigned char* buf, uint64_t n, int iMode=CFB);
// encrypt/decrypt from Input Buffer to Output Buffer
void encrypt(const unsigned char* in, unsigned char* out, uint64_t n, int iMode=CFB);
void decrypt(const unsigned char* in, unsigned char* out, uint64_t n, int iMode=CFB);
//Private Functions
private:
unsigned int F(unsigned int ui);
void encrypt(sblock&);
void decrypt(sblock&);
private:
//The Initialization Vector, by default {0, 0}
sblock m_oChain0;
sblock m_oChain;
unsigned int m_auiP[18];
unsigned int m_auiS[4][256];
static const unsigned int scm_auiInitP[18];
static const unsigned int scm_auiInitS[4][256];
};
} // namespace fc
// Copyright (c) 2011 Google, Inc.
//
// 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.
//
// CityHash, by Geoff Pike and Jyrki Alakuijala
//
// This file provides a few functions for hashing strings. On x86-64
// hardware in 2011, CityHash64() is faster than other high-quality
// hash functions, such as Murmur. This is largely due to higher
// instruction-level parallelism. CityHash64() and CityHash128() also perform
// well on hash-quality tests.
//
// CityHash128() is optimized for relatively long strings and returns
// a 128-bit hash. For strings more than about 2000 bytes it can be
// faster than CityHash64().
//
// Functions in the CityHash family are not suitable for cryptography.
//
// WARNING: This code has not been tested on big-endian platforms!
// It is known to work well on little-endian platforms that have a small penalty
// for unaligned reads, such as current Intel and AMD moderate-to-high-end CPUs.
//
// By the way, for some hash functions, given strings a and b, the hash
// of a+b is easily derived from the hashes of a and b. This property
// doesn't hold for any hash functions in this file.
#pragma once
#include <stdlib.h> // for size_t.
#include <stdint.h>
#include <utility>
namespace fc {
template<typename T, size_t N>
class array;
class uint128;
// Hash function for a byte array.
uint64_t city_hash64(const char *buf, size_t len);
uint32_t city_hash32(const char *buf, size_t len);
#if SIZE_MAX > UINT32_MAX
inline size_t city_hash_size_t(const char *buf, size_t len) { return city_hash64(buf, len); }
#else
inline size_t city_hash_size_t(const char *buf, size_t len) { return city_hash32(buf, len); }
#endif
// Hash function for a byte array.
uint128 city_hash128(const char *s, size_t len);
// Hash function for a byte array.
uint64_t city_hash_crc_64(const char *buf, size_t len);
// Hash function for a byte array.
uint128 city_hash_crc_128(const char *s, size_t len);
array<uint64_t,4> city_hash_crc_256(const char *s, size_t len);
} // namespace fc
#pragma once
#include <fc/crypto/openssl.hpp>
#include <vector>
#include <stdint.h>
namespace fc {
struct diffie_hellman {
diffie_hellman():valid(0),g(5){ fc::init_openssl(); }
bool generate_params( int s, uint8_t g );
bool generate_pub_key();
bool compute_shared_key( const char* buf, uint32_t s );
bool compute_shared_key( const std::vector<char>& pubk);
bool validate();
std::vector<char> p;
std::vector<char> pub_key;
std::vector<char> priv_key;
std::vector<char> shared_key;
bool valid;
uint8_t g;
};
} // namespace fc
#pragma once
#include <fc/io/raw.hpp>
#include <fc/reflect/reflect.hpp>
#include <fc/crypto/sha256.hpp>
namespace fc {
template<typename T>
fc::sha256 digest( const T& value )
{
fc::sha256::encoder enc;
fc::raw::pack( enc, value );
return enc.result();
}
}
#pragma once
#include <fc/crypto/bigint.hpp>
#include <fc/crypto/openssl.hpp>
#include <fc/crypto/sha256.hpp>
#include <fc/crypto/sha512.hpp>
#include <fc/fwd.hpp>
#include <fc/array.hpp>
#include <fc/io/raw_fwd.hpp>
namespace fc {
namespace ecc {
namespace detail
{
class public_key_impl;
class private_key_impl;
}
typedef fc::sha256 blind_factor_type;
typedef fc::array<char,33> commitment_type;
typedef fc::array<char,33> public_key_data;
typedef fc::sha256 private_key_secret;
typedef fc::array<char,65> public_key_point_data; ///< the full non-compressed version of the ECC point
typedef fc::array<char,72> signature;
typedef fc::array<unsigned char,65> compact_signature;
typedef std::vector<char> range_proof_type;
typedef fc::array<char,78> extended_key_data;
typedef fc::sha256 blinded_hash;
typedef fc::sha256 blind_signature;
/**
* @class public_key
* @brief contains only the public point of an elliptic curve key.
*/
class public_key
{
public:
public_key();
public_key(const public_key& k);
~public_key();
// bool verify( const fc::sha256& digest, const signature& sig );
public_key_data serialize()const;
public_key_point_data serialize_ecc_point()const;
operator public_key_data()const { return serialize(); }
public_key( const public_key_data& v );
public_key( const public_key_point_data& v );
public_key( const compact_signature& c, const fc::sha256& digest, bool check_canonical = true );
public_key child( const fc::sha256& offset )const;
bool valid()const;
/** Computes new pubkey = generator * offset + old pubkey ?! */
// public_key mult( const fc::sha256& offset )const;
/** Computes new pubkey = regenerate(offset).pubkey + old pubkey
* = offset * G + 1 * old pubkey ?! */
public_key add( const fc::sha256& offset )const;
public_key( public_key&& pk );
public_key& operator=( public_key&& pk );
public_key& operator=( const public_key& pk );
inline friend bool operator==( const public_key& a, const public_key& b )
{
return a.serialize() == b.serialize();
}
inline friend bool operator!=( const public_key& a, const public_key& b )
{
return a.serialize() != b.serialize();
}
/// Allows to convert current public key object into base58 number.
std::string to_base58() const;
static std::string to_base58( const public_key_data &key );
static public_key from_base58( const std::string& b58 );
unsigned int fingerprint() const;
private:
friend class private_key;
static public_key from_key_data( const public_key_data& v );
static bool is_canonical( const compact_signature& c );
fc::fwd<detail::public_key_impl,33> my;
};
/**
* @class private_key
* @brief an elliptic curve private key.
*/
class private_key
{
public:
private_key();
private_key( private_key&& pk );
private_key( const private_key& pk );
~private_key();
private_key& operator=( private_key&& pk );
private_key& operator=( const private_key& pk );
static private_key generate();
static private_key regenerate( const fc::sha256& secret );
private_key child( const fc::sha256& offset )const;
/**
* This method of generation enables creating a new private key in a deterministic manner relative to
* an initial seed. A public_key created from the seed can be multiplied by the offset to calculate
* the new public key without having to know the private key.
*/
static private_key generate_from_seed( const fc::sha256& seed, const fc::sha256& offset = fc::sha256() );
private_key_secret get_secret()const; // get the private key secret
operator private_key_secret ()const { return get_secret(); }
/**
* Given a public key, calculatse a 512 bit shared secret between that
* key and this private key.
*/
fc::sha512 get_shared_secret( const public_key& pub )const;
// signature sign( const fc::sha256& digest )const;
compact_signature sign_compact( const fc::sha256& digest, bool require_canonical = true )const;
// bool verify( const fc::sha256& digest, const signature& sig );
public_key get_public_key()const;
inline friend bool operator==( const private_key& a, const private_key& b )
{
return a.get_secret() == b.get_secret();
}
inline friend bool operator!=( const private_key& a, const private_key& b )
{
return a.get_secret() != b.get_secret();
}
inline friend bool operator<( const private_key& a, const private_key& b )
{
return a.get_secret() < b.get_secret();
}
unsigned int fingerprint() const { return get_public_key().fingerprint(); }
private:
private_key( EC_KEY* k );
static fc::sha256 get_secret( const EC_KEY * const k );
fc::fwd<detail::private_key_impl,32> my;
};
class extended_public_key : public public_key
{
public:
extended_public_key( const public_key& k, const sha256& c,
int child = 0, int parent_fp = 0, uint8_t depth = 0 );
extended_public_key derive_child( int i ) const;
extended_public_key derive_normal_child( int i ) const;
extended_key_data serialize_extended() const;
static extended_public_key deserialize( const extended_key_data& data );
fc::string str() const;
fc::string to_base58() const { return str(); }
static extended_public_key from_base58( const fc::string& base58 );
public_key generate_p( int i ) const;
public_key generate_q( int i ) const;
private:
sha256 c;
int child_num, parent_fp;
uint8_t depth;
};
class extended_private_key : public private_key
{
public:
extended_private_key( const private_key& k, const sha256& c,
int child = 0, int parent_fp = 0, uint8_t depth = 0 );
extended_public_key get_extended_public_key()const;
extended_private_key derive_child( int i ) const;
extended_private_key derive_normal_child( int i ) const;
extended_private_key derive_hardened_child( int i ) const;
extended_key_data serialize_extended() const;
static extended_private_key deserialize( const extended_key_data& data );
fc::string str() const;
fc::string to_base58() const { return str(); }
static extended_private_key from_base58( const fc::string& base58 );
static extended_private_key generate_master( const fc::string& seed );
static extended_private_key generate_master( const char* seed, uint32_t seed_len );
// Oleg Andreev's blind signature scheme,
// see http://blog.oleganza.com/post/77474860538/blind-signatures
public_key blind_public_key( const extended_public_key& bob, int i ) const;
blinded_hash blind_hash( const fc::sha256& hash, int i ) const;
blind_signature blind_sign( const blinded_hash& hash, int i ) const;
// WARNING! This may produce non-canonical signatures!
compact_signature unblind_signature( const extended_public_key& bob,
const blind_signature& sig,
const fc::sha256& hash, int i ) const;
private:
extended_private_key private_derive_rest( const fc::sha512& hash,
int num ) const;
private_key generate_a( int i ) const;
private_key generate_b( int i ) const;
private_key generate_c( int i ) const;
private_key generate_d( int i ) const;
private_key_secret compute_p( int i ) const;
private_key_secret compute_q( int i, const private_key_secret& p ) const;
sha256 c;
int child_num, parent_fp;
uint8_t depth;
};
struct range_proof_info
{
int exp;
int mantissa;
uint64_t min_value;
uint64_t max_value;
};
commitment_type blind( const blind_factor_type& blind, uint64_t value );
blind_factor_type blind_sum( const std::vector<blind_factor_type>& blinds, uint32_t non_neg );
/** verifies taht commnits + neg_commits + excess == 0 */
bool verify_sum( const std::vector<commitment_type>& commits, const std::vector<commitment_type>& neg_commits, int64_t excess );
bool verify_range( uint64_t& min_val, uint64_t& max_val, const commitment_type& commit, const range_proof_type& proof );
range_proof_type range_proof_sign( uint64_t min_value,
const commitment_type& commit,
const blind_factor_type& commit_blind,
const blind_factor_type& nonce,
int8_t base10_exp,
uint8_t min_bits,
uint64_t actual_value
);
bool verify_range_proof_rewind( blind_factor_type& blind_out,
uint64_t& value_out,
string& message_out,
const blind_factor_type& nonce,
uint64_t& min_val,
uint64_t& max_val,
commitment_type commit,
const range_proof_type& proof );
range_proof_info range_get_info( const range_proof_type& proof );
} // namespace ecc
void to_variant( const ecc::private_key& var, variant& vo );
void from_variant( const variant& var, ecc::private_key& vo );
void to_variant( const ecc::public_key& var, variant& vo );
void from_variant( const variant& var, ecc::public_key& vo );
namespace raw
{
template<typename Stream>
void unpack( Stream& s, fc::ecc::public_key& pk)
{
ecc::public_key_data ser;
fc::raw::unpack(s,ser);
pk = fc::ecc::public_key( ser );
}
template<typename Stream>
void pack( Stream& s, const fc::ecc::public_key& pk)
{
fc::raw::pack( s, pk.serialize() );
}
template<typename Stream>
void unpack( Stream& s, fc::ecc::private_key& pk)
{
fc::sha256 sec;
unpack( s, sec );
pk = ecc::private_key::regenerate(sec);
}
template<typename Stream>
void pack( Stream& s, const fc::ecc::private_key& pk)
{
fc::raw::pack( s, pk.get_secret() );
}
} // namespace raw
} // namespace fc
#include <fc/reflect/reflect.hpp>
FC_REFLECT_TYPENAME( fc::ecc::private_key )
FC_REFLECT_TYPENAME( fc::ecc::public_key )
FC_REFLECT( fc::ecc::range_proof_info, (exp)(mantissa)(min_value)(max_value) )
#pragma once
#include <fc/crypto/sha256.hpp>
#include <fc/vector.hpp>
namespace fc { namespace equihash {
struct proof
{
uint32_t n;
uint32_t k;
sha256 seed;
std::vector< uint32_t > inputs;
bool is_valid() const;
static proof hash( uint32_t n, uint32_t k, sha256 seed );
};
} } // fc
FC_REFLECT( fc::equihash::proof, (n)(k)(seed)(inputs) )
#pragma once
#include <fc/string.hpp>
#include <fc/utility.hpp>
#include <vector>
namespace fc {
uint8_t from_hex( char c );
fc::string to_hex( const char* d, uint32_t s );
std::string to_hex( const std::vector<char>& data );
/**
* @return the number of bytes decoded
*/
size_t from_hex( const fc::string& hex_str, char* out_data, size_t out_data_len );
}
/*
* File: hmac.hpp
* Author: Peter Conrad
*
* Created on 1. Juli 2015, 21:48
*/
#ifndef HMAC_HPP
#define HMAC_HPP
#include <fc/crypto/sha224.hpp>
#include <fc/crypto/sha256.hpp>
#include <fc/crypto/sha512.hpp>
namespace fc {
template<typename H>
class hmac
{
public:
hmac() {}
H digest( const char* c, uint32_t c_len, const char* d, uint32_t d_len )
{
encoder.reset();
add_key(c, c_len, 0x36);
encoder.write( d, d_len );
H intermediate = encoder.result();
encoder.reset();
add_key(c, c_len, 0x5c);
encoder.write( intermediate.data(), intermediate.data_size() );
return encoder.result();
}
private:
void add_key( const char* c, const uint32_t c_len, char pad )
{
if ( c_len > internal_block_size() )
{
H hash = H::hash( c, c_len );
add_key( hash.data(), hash.data_size(), pad );
}
else
for (unsigned int i = 0; i < internal_block_size(); i++ )
{
encoder.put( pad ^ ((i < c_len) ? *c++ : 0) );
}
}
unsigned int internal_block_size() const;
H dummy;
typename H::encoder encoder;
};
typedef hmac<fc::sha224> hmac_sha224;
typedef hmac<fc::sha256> hmac_sha256;
typedef hmac<fc::sha512> hmac_sha512;
}
#endif /* HMAC_HPP */
#pragma once
#include <openssl/ec.h>
#include <openssl/crypto.h>
#include <openssl/evp.h>
#include <openssl/conf.h>
#include <openssl/err.h>
#include <openssl/ecdsa.h>
#include <openssl/ecdh.h>
#include <openssl/sha.h>
#include <openssl/obj_mac.h>
/**
* @file openssl.hpp
* Provides common utility calls for wrapping openssl c api.
*/
namespace fc
{
class path;
template <typename ssl_type>
struct ssl_wrapper
{
ssl_wrapper(ssl_type* obj):obj(obj) {}
operator ssl_type*() { return obj; }
operator const ssl_type*() const { return obj; }
ssl_type* operator->() { return obj; }
const ssl_type* operator->() const { return obj; }
ssl_type* obj;
};
#define SSL_TYPE(name, ssl_type, free_func) \
struct name : public ssl_wrapper<ssl_type> \
{ \
name(ssl_type* obj=nullptr) \
: ssl_wrapper(obj) {} \
~name() \
{ \
if( obj != nullptr ) \
free_func(obj); \
} \
};
SSL_TYPE(ec_group, EC_GROUP, EC_GROUP_free)
SSL_TYPE(ec_point, EC_POINT, EC_POINT_free)
SSL_TYPE(ecdsa_sig, ECDSA_SIG, ECDSA_SIG_free)
SSL_TYPE(bn_ctx, BN_CTX, BN_CTX_free)
SSL_TYPE(evp_cipher_ctx, EVP_CIPHER_CTX, EVP_CIPHER_CTX_free )
/** allocates a bignum by default.. */
struct ssl_bignum : public ssl_wrapper<BIGNUM>
{
ssl_bignum() : ssl_wrapper(BN_new()) {}
~ssl_bignum() { BN_free(obj); }
};
/** Allows to explicitly specify OpenSSL configuration file path to be loaded at OpenSSL library init.
If not set OpenSSL will try to load the conf. file (openssl.cnf) from the path it was
configured with what caused serious Keyhotee startup bugs on some Win7, Win8 machines.
\warning to be effective this method should be used before any part using OpenSSL, especially
before init_openssl call
*/
void store_configuration_path(const path& filePath);
int init_openssl();
} // namespace fc
#pragma once
#include <memory>
#include <vector>
#include <fc/crypto/sha1.hpp>
#include <fc/crypto/sha256.hpp>
#include <fc/io/raw_fwd.hpp>
#include <fc/array.hpp>
namespace fc {
namespace detail { class pke_impl; }
class private_key;
class public_key;
void generate_key_pair( public_key&, private_key& );
typedef std::vector<char> bytes;
typedef bytes signature;
class public_key
{
public:
public_key();
explicit public_key( const bytes& d );
public_key( const public_key& k );
public_key( public_key&& k );
~public_key();
operator bool()const;
public_key& operator=(const public_key& p );
public_key& operator=(public_key&& p );
bool verify( const sha1& digest, const array<char,2048/8>& sig )const;
bool verify( const sha1& digest, const signature& sig )const;
bool verify( const sha256& digest, const signature& sig )const;
bytes encrypt( const char* data, size_t len )const;
bytes encrypt( const bytes& )const;
bytes decrypt( const bytes& )const;
bytes serialize()const;
friend void generate_key_pair( public_key&, private_key& );
private:
std::shared_ptr<detail::pke_impl> my;
};
class private_key
{
public:
private_key();
explicit private_key( const bytes& d );
private_key( const private_key& k );
private_key( private_key&& k );
~private_key();
operator bool()const;
private_key& operator=(const private_key& p );
private_key& operator=(private_key&& p );
void sign( const sha1& digest, array<char,2048/8>& sig )const;
signature sign( const sha1& digest )const;
signature sign( const sha256& digest )const;
bytes decrypt( const char* bytes, size_t len )const;
bytes decrypt( const bytes& )const;
bytes encrypt( const bytes& )const;
bytes serialize()const;
friend void generate_key_pair( public_key&, private_key& );
private:
std::shared_ptr<detail::pke_impl> my;
};
bool operator==( const private_key& a, const private_key& b );
namespace raw
{
template<typename Stream>
void unpack( Stream& s, fc::public_key& pk)
{
bytes ser;
fc::raw::unpack(s,ser);
pk = fc::public_key( ser );
}
template<typename Stream>
void pack( Stream& s, const fc::public_key& pk)
{
fc::raw::pack( s, pk.serialize() );
}
template<typename Stream>
void unpack( Stream& s, fc::private_key& pk)
{
bytes ser;
fc::raw::unpack(s,ser);
pk = fc::private_key( ser );
}
template<typename Stream>
void pack( Stream& s, const fc::private_key& pk)
{
fc::raw::pack( s, pk.serialize() );
}
}
class variant;
void to_variant( const public_key& bi, variant& v );
void from_variant( const variant& v, public_key& bi );
void to_variant( const private_key& bi, variant& v );
void from_variant( const variant& v, private_key& bi );
} // fc
#pragma once
namespace fc {
/* provides access to the OpenSSL random number generator */
void rand_bytes(char* buf, int count);
void rand_pseudo_bytes(char* buf, int count);
} // namespace fc
#pragma once
#include <fc/fwd.hpp>
#include <fc/io/raw_fwd.hpp>
#include <fc/reflect/typename.hpp>
namespace fc{
class sha512;
class sha256;
class ripemd160
{
public:
ripemd160();
explicit ripemd160( const string& hex_str );
string str()const;
explicit operator string()const;
char* data()const;
size_t data_size()const { return 160/8; }
static ripemd160 hash( const fc::sha512& h );
static ripemd160 hash( const fc::sha256& h );
static ripemd160 hash( const char* d, uint32_t dlen );
static ripemd160 hash( const string& );
template<typename T>
static ripemd160 hash( const T& t )
{
ripemd160::encoder e;
fc::raw::pack(e,t);
return e.result();
}
class encoder
{
public:
encoder();
~encoder();
void write( const char* d, uint32_t dlen );
void put( char c ) { write( &c, 1 ); }
void reset();
ripemd160 result();
private:
struct impl;
fc::fwd<impl,96> my;
};
template<typename T>
inline friend T& operator<<( T& ds, const ripemd160& ep ) {
ds.write( ep.data(), sizeof(ep) );
return ds;
}
template<typename T>
inline friend T& operator>>( T& ds, ripemd160& ep ) {
ds.read( ep.data(), sizeof(ep) );
return ds;
}
friend ripemd160 operator << ( const ripemd160& h1, uint32_t i );
friend bool operator == ( const ripemd160& h1, const ripemd160& h2 );
friend bool operator != ( const ripemd160& h1, const ripemd160& h2 );
friend ripemd160 operator ^ ( const ripemd160& h1, const ripemd160& h2 );
friend bool operator >= ( const ripemd160& h1, const ripemd160& h2 );
friend bool operator > ( const ripemd160& h1, const ripemd160& h2 );
friend bool operator < ( const ripemd160& h1, const ripemd160& h2 );
uint32_t _hash[5];
};
class variant;
void to_variant( const ripemd160& bi, variant& v );
void from_variant( const variant& v, ripemd160& bi );
typedef ripemd160 uint160_t;
typedef ripemd160 uint160;
template<> struct get_typename<uint160_t> { static const char* name() { return "uint160_t"; } };
} // namespace fc
namespace std
{
template<>
struct hash<fc::ripemd160>
{
size_t operator()( const fc::ripemd160& s )const
{
return *((size_t*)&s);
}
};
}
#pragma once
#include <fc/fwd.hpp>
#include <fc/string.hpp>
namespace fc{
class sha1
{
public:
sha1();
explicit sha1( const string& hex_str );
string str()const;
operator string()const;
char* data()const;
size_t data_size()const { return 20; }
static sha1 hash( const char* d, uint32_t dlen );
static sha1 hash( const string& );
template<typename T>
static sha1 hash( const T& t )
{
sha1::encoder e;
e << t;
return e.result();
}
class encoder
{
public:
encoder();
~encoder();
void write( const char* d, uint32_t dlen );
void put( char c ) { write( &c, 1 ); }
void reset();
sha1 result();
private:
struct impl;
fc::fwd<impl,96> my;
};
template<typename T>
inline friend T& operator<<( T& ds, const sha1& ep ) {
ds.write( ep.data(), sizeof(ep) );
return ds;
}
template<typename T>
inline friend T& operator>>( T& ds, sha1& ep ) {
ds.read( ep.data(), sizeof(ep) );
return ds;
}
friend sha1 operator << ( const sha1& h1, uint32_t i );
friend bool operator == ( const sha1& h1, const sha1& h2 );
friend bool operator != ( const sha1& h1, const sha1& h2 );
friend sha1 operator ^ ( const sha1& h1, const sha1& h2 );
friend bool operator >= ( const sha1& h1, const sha1& h2 );
friend bool operator > ( const sha1& h1, const sha1& h2 );
friend bool operator < ( const sha1& h1, const sha1& h2 );
uint32_t _hash[5];
};
class variant;
void to_variant( const sha1& bi, variant& v );
void from_variant( const variant& v, sha1& bi );
} // namespace fc
namespace std
{
template<>
struct hash<fc::sha1>
{
size_t operator()( const fc::sha1& s )const
{
return *((size_t*)&s);
}
};
}
#pragma once
#include <unordered_map>
#include <fc/fwd.hpp>
#include <fc/io/raw_fwd.hpp>
#include <fc/string.hpp>
namespace fc
{
class sha224
{
public:
sha224();
explicit sha224( const string& hex_str );
string str()const;
operator string()const;
char* data()const;
size_t data_size()const { return 224 / 8; }
static sha224 hash( const char* d, uint32_t dlen );
static sha224 hash( const string& );
template<typename T>
static sha224 hash( const T& t )
{
sha224::encoder e;
fc::raw::pack(e,t);
return e.result();
}
class encoder
{
public:
encoder();
~encoder();
void write( const char* d, uint32_t dlen );
void put( char c ) { write( &c, 1 ); }
void reset();
sha224 result();
private:
struct impl;
fc::fwd<impl,112> my;
};
template<typename T>
inline friend T& operator<<( T& ds, const sha224& ep ) {
static_assert( sizeof(ep) == (8*3+4), "sha224 size mismatch" );
ds.write( ep.data(), sizeof(ep) );
return ds;
}
template<typename T>
inline friend T& operator>>( T& ds, sha224& ep ) {
ds.read( ep.data(), sizeof(ep) );
return ds;
}
friend sha224 operator << ( const sha224& h1, uint32_t i );
friend bool operator == ( const sha224& h1, const sha224& h2 );
friend bool operator != ( const sha224& h1, const sha224& h2 );
friend sha224 operator ^ ( const sha224& h1, const sha224& h2 );
friend bool operator >= ( const sha224& h1, const sha224& h2 );
friend bool operator > ( const sha224& h1, const sha224& h2 );
friend bool operator < ( const sha224& h1, const sha224& h2 );
friend std::size_t hash_value( const sha224& v ) { return uint64_t(v._hash[1])<<32 | v._hash[2]; }
uint32_t _hash[7];
};
class variant;
void to_variant( const sha224& bi, variant& v );
void from_variant( const variant& v, sha224& bi );
} // fc
namespace std
{
template<>
struct hash<fc::sha224>
{
size_t operator()( const fc::sha224& s )const
{
return *((size_t*)&s);
}
};
}
#include <fc/reflect/reflect.hpp>
FC_REFLECT_TYPENAME( fc::sha224 )
#pragma once
#include <fc/fwd.hpp>
#include <fc/string.hpp>
#include <fc/platform_independence.hpp>
#include <fc/io/raw_fwd.hpp>
namespace fc
{
class sha256
{
public:
sha256();
explicit sha256( const string& hex_str );
explicit sha256( const char *data, size_t size );
string str()const;
operator string()const;
char* data()const;
size_t data_size()const { return 256 / 8; }
static sha256 hash( const char* d, uint32_t dlen );
static sha256 hash( const string& );
static sha256 hash( const sha256& );
template<typename T>
static sha256 hash( const T& t )
{
sha256::encoder e;
fc::raw::pack(e,t);
return e.result();
}
class encoder
{
public:
encoder();
~encoder();
void write( const char* d, uint32_t dlen );
void put( char c ) { write( &c, 1 ); }
void reset();
sha256 result();
private:
struct impl;
fc::fwd<impl,112> my;
};
template<typename T>
inline friend T& operator<<( T& ds, const sha256& ep ) {
ds.write( ep.data(), sizeof(ep) );
return ds;
}
template<typename T>
inline friend T& operator>>( T& ds, sha256& ep ) {
ds.read( ep.data(), sizeof(ep) );
return ds;
}
friend sha256 operator << ( const sha256& h1, uint32_t i );
friend sha256 operator >> ( const sha256& h1, uint32_t i );
friend bool operator == ( const sha256& h1, const sha256& h2 );
friend bool operator != ( const sha256& h1, const sha256& h2 );
friend sha256 operator ^ ( const sha256& h1, const sha256& h2 );
friend bool operator >= ( const sha256& h1, const sha256& h2 );
friend bool operator > ( const sha256& h1, const sha256& h2 );
friend bool operator < ( const sha256& h1, const sha256& h2 );
uint32_t pop_count()const
{
return (uint32_t)(__builtin_popcountll(_hash[0]) +
__builtin_popcountll(_hash[1]) +
__builtin_popcountll(_hash[2]) +
__builtin_popcountll(_hash[3]));
}
/**
* Count leading zero bits
*/
uint16_t clz()const;
/**
* Approximate (log_2(x) + 1) * 2**24.
*
* Detailed specs:
* - Return 0 when x == 0.
* - High 8 bits of result simply counts nonzero bits.
* - Low 24 bits of result are the 24 bits of input immediately after the most significant 1 in the input.
* - If above would require reading beyond the end of the input, zeros are used instead.
*/
uint32_t approx_log_32()const;
void set_to_inverse_approx_log_32( uint32_t x );
static double inverse_approx_log_32_double( uint32_t x );
uint64_t _hash[4];
};
typedef sha256 uint256;
class variant;
void to_variant( const sha256& bi, variant& v );
void from_variant( const variant& v, sha256& bi );
uint64_t hash64(const char* buf, size_t len);
} // fc
namespace std
{
template<>
struct hash<fc::sha256>
{
size_t operator()( const fc::sha256& s )const
{
return *((size_t*)&s);
}
};
}
namespace boost
{
template<>
struct hash<fc::sha256>
{
size_t operator()( const fc::sha256& s )const
{
return s._hash[3];//*((size_t*)&s);
}
};
}
#include <fc/reflect/reflect.hpp>
FC_REFLECT_TYPENAME( fc::sha256 )
#pragma once
#include <fc/fwd.hpp>
#include <fc/string.hpp>
namespace fc
{
class sha512
{
public:
sha512();
explicit sha512( const string& hex_str );
string str()const;
operator string()const;
char* data()const;
size_t data_size()const { return 512 / 8; }
static sha512 hash( const char* d, uint32_t dlen );
static sha512 hash( const string& );
template<typename T>
static sha512 hash( const T& t )
{
sha512::encoder e;
e << t;
return e.result();
}
class encoder
{
public:
encoder();
~encoder();
void write( const char* d, uint32_t dlen );
void put( char c ) { write( &c, 1 ); }
void reset();
sha512 result();
private:
struct impl;
fc::fwd<impl,216> my;
};
template<typename T>
inline friend T& operator<<( T& ds, const sha512& ep ) {
ds.write( ep.data(), sizeof(ep) );
return ds;
}
template<typename T>
inline friend T& operator>>( T& ds, sha512& ep ) {
ds.read( ep.data(), sizeof(ep) );
return ds;
}
friend sha512 operator << ( const sha512& h1, uint32_t i );
friend bool operator == ( const sha512& h1, const sha512& h2 );
friend bool operator != ( const sha512& h1, const sha512& h2 );
friend sha512 operator ^ ( const sha512& h1, const sha512& h2 );
friend bool operator >= ( const sha512& h1, const sha512& h2 );
friend bool operator > ( const sha512& h1, const sha512& h2 );
friend bool operator < ( const sha512& h1, const sha512& h2 );
uint64_t _hash[8];
};
typedef fc::sha512 uint512;
class variant;
void to_variant( const sha512& bi, variant& v );
void from_variant( const variant& v, sha512& bi );
} // fc
#include <fc/reflect/reflect.hpp>
FC_REFLECT_TYPENAME( fc::sha512 )
#pragma once
/**
* @file exception.hpp
* @brief Defines exception's used by fc
*/
#include <fc/log/logger.hpp>
#include <fc/optional.hpp>
#include <exception>
#include <functional>
#include <unordered_map>
namespace fc
{
namespace detail { class exception_impl; }
enum exception_code
{
/** for exceptions we threw that don't have an assigned code */
unspecified_exception_code = 0,
unhandled_exception_code = 1, ///< for unhandled 3rd party exceptions
timeout_exception_code = 2, ///< timeout exceptions
file_not_found_exception_code = 3,
parse_error_exception_code = 4,
invalid_arg_exception_code = 5,
key_not_found_exception_code = 6,
bad_cast_exception_code = 7,
out_of_range_exception_code = 8,
canceled_exception_code = 9,
assert_exception_code = 10,
eof_exception_code = 11,
std_exception_code = 13,
invalid_operation_exception_code = 14,
unknown_host_exception_code = 15,
null_optional_code = 16,
udt_error_code = 17,
aes_error_code = 18,
overflow_code = 19,
underflow_code = 20,
divide_by_zero_code = 21
};
/**
* @brief Used to generate a useful error report when an exception is thrown.
* @ingroup serializable
*
* At each level in the stack where the exception is caught and rethrown a
* new log_message is added to the exception.
*
* exception's are designed to be serialized to a variant and
* deserialized from an variant.
*
* @see FC_THROW_EXCEPTION
* @see FC_RETHROW_EXCEPTION
* @see FC_RETHROW_EXCEPTIONS
*/
class exception
{
public:
enum code_enum
{
code_value = unspecified_exception_code
};
exception( int64_t code = unspecified_exception_code,
const std::string& name_value = "exception",
const std::string& what_value = "unspecified");
exception( log_message&&, int64_t code = unspecified_exception_code,
const std::string& name_value = "exception",
const std::string& what_value = "unspecified");
exception( log_messages&&, int64_t code = unspecified_exception_code,
const std::string& name_value = "exception",
const std::string& what_value = "unspecified");
exception( const log_messages&,
int64_t code = unspecified_exception_code,
const std::string& name_value = "exception",
const std::string& what_value = "unspecified");
exception( const exception& e );
exception( exception&& e );
virtual ~exception();
const char* name()const throw();
int64_t code()const throw();
virtual const char* what()const throw();
/**
* @return a reference to log messages that have
* been added to this log.
*/
const log_messages& get_log()const;
void append_log( log_message m );
/**
* Generates a detailed string including file, line, method,
* and other information that is generally only useful for
* developers.
*/
std::string to_detail_string( log_level ll = log_level::all )const;
/**
* Generates a user-friendly error report.
*/
std::string to_string( log_level ll = log_level::info )const;
/**
* Throw this exception as its most derived type.
*
* @note does not return.
*/
virtual NO_RETURN void dynamic_rethrow_exception()const;
/**
* This is equivalent to:
* @code
* try { throwAsDynamic_exception(); }
* catch( ... ) { return std::current_exception(); }
* @endcode
*/
virtual std::shared_ptr<exception> dynamic_copy_exception()const;
friend void to_variant( const exception& e, variant& v );
friend void from_variant( const variant& e, exception& ll );
exception& operator=( const exception& copy );
exception& operator=( exception&& copy );
protected:
std::unique_ptr<detail::exception_impl> my;
};
void to_variant( const exception& e, variant& v );
void from_variant( const variant& e, exception& ll );
typedef std::shared_ptr<exception> exception_ptr;
typedef optional<exception> oexception;
/**
* @brief re-thrown whenever an unhandled exception is caught.
* @ingroup serializable
* Any exceptions thrown by 3rd party libraries that are not
* caught get wrapped in an unhandled_exception exception.
*
* The original exception is captured as a std::exception_ptr
* which may be rethrown. The std::exception_ptr does not
* propgate across process boundaries.
*/
class unhandled_exception : public exception
{
public:
enum code_enum {
code_value = unhandled_exception_code,
};
unhandled_exception( log_message&& m, std::exception_ptr e = std::current_exception() );
unhandled_exception( log_messages );
unhandled_exception( const exception& );
std::exception_ptr get_inner_exception()const;
virtual NO_RETURN void dynamic_rethrow_exception()const;
virtual std::shared_ptr<exception> dynamic_copy_exception()const;
private:
std::exception_ptr _inner;
};
template<typename T>
fc::exception_ptr copy_exception( T&& e )
{
#if defined(_MSC_VER) && (_MSC_VER < 1700)
return std::make_shared<unhandled_exception>( log_message(),
std::copy_exception(fc::forward<T>(e)) );
#else
return std::make_shared<unhandled_exception>( log_message(),
std::make_exception_ptr(fc::forward<T>(e)) );
#endif
}
class exception_factory
{
public:
struct base_exception_builder
{
virtual NO_RETURN void rethrow( const exception& e )const = 0;
};
template<typename T>
struct exception_builder : public base_exception_builder
{
virtual NO_RETURN void rethrow( const exception& e )const override
{
throw T( e );
}
};
template<typename T>
void register_exception()
{
static exception_builder<T> builder;
auto itr = _registered_exceptions.find( T::code_value );
assert( itr == _registered_exceptions.end() );
(void)itr; // in release builds this hides warnings
_registered_exceptions[T::code_value] = &builder;
}
void NO_RETURN rethrow( const exception& e )const;
static exception_factory& instance()
{
static exception_factory once;
return once;
}
private:
std::unordered_map<int64_t,base_exception_builder*> _registered_exceptions;
};
#define FC_REGISTER_EXCEPTION(r, unused, base) \
fc::exception_factory::instance().register_exception<base>();
#define FC_REGISTER_EXCEPTIONS( SEQ )\
\
static bool exception_init = []()->bool{ \
BOOST_PP_SEQ_FOR_EACH( FC_REGISTER_EXCEPTION, v, SEQ ) \
return true; \
}(); \
#define FC_DECLARE_DERIVED_EXCEPTION( TYPE, BASE, CODE, WHAT ) \
class TYPE : public BASE \
{ \
public: \
enum code_enum { \
code_value = CODE, \
}; \
explicit TYPE( int64_t code, const std::string& name_value, const std::string& what_value ) \
:BASE( code, name_value, what_value ){} \
explicit TYPE( fc::log_message&& m, int64_t code, const std::string& name_value, const std::string& what_value ) \
:BASE( std::move(m), code, name_value, what_value ){} \
explicit TYPE( fc::log_messages&& m, int64_t code, const std::string& name_value, const std::string& what_value )\
:BASE( std::move(m), code, name_value, what_value ){}\
explicit TYPE( const fc::log_messages& m, int64_t code, const std::string& name_value, const std::string& what_value )\
:BASE( m, code, name_value, what_value ){}\
TYPE( const std::string& what_value, const fc::log_messages& m ) \
:BASE( m, CODE, BOOST_PP_STRINGIZE(TYPE), what_value ){} \
TYPE( fc::log_message&& m ) \
:BASE( fc::move(m), CODE, BOOST_PP_STRINGIZE(TYPE), WHAT ){}\
TYPE( fc::log_messages msgs ) \
:BASE( fc::move( msgs ), CODE, BOOST_PP_STRINGIZE(TYPE), WHAT ) {} \
TYPE( const TYPE& c ) \
:BASE(c){} \
TYPE( const BASE& c ) \
:BASE(c){} \
TYPE():BASE(CODE, BOOST_PP_STRINGIZE(TYPE), WHAT){}\
\
virtual std::shared_ptr<fc::exception> dynamic_copy_exception()const\
{ return std::make_shared<TYPE>( *this ); } \
virtual NO_RETURN void dynamic_rethrow_exception()const \
{ if( code() == CODE ) throw *this;\
else fc::exception::dynamic_rethrow_exception(); \
} \
};
#define FC_DECLARE_EXCEPTION( TYPE, CODE, WHAT ) \
FC_DECLARE_DERIVED_EXCEPTION( TYPE, fc::exception, CODE, WHAT )
FC_DECLARE_EXCEPTION( timeout_exception, timeout_exception_code, "Timeout" );
FC_DECLARE_EXCEPTION( file_not_found_exception, file_not_found_exception_code, "File Not Found" );
/**
* @brief report's parse errors
*/
FC_DECLARE_EXCEPTION( parse_error_exception, parse_error_exception_code, "Parse Error" );
FC_DECLARE_EXCEPTION( invalid_arg_exception, invalid_arg_exception_code, "Invalid Argument" );
/**
* @brief reports when a key, guid, or other item is not found.
*/
FC_DECLARE_EXCEPTION( key_not_found_exception, key_not_found_exception_code, "Key Not Found" );
FC_DECLARE_EXCEPTION( bad_cast_exception, bad_cast_exception_code, "Bad Cast" );
FC_DECLARE_EXCEPTION( out_of_range_exception, out_of_range_exception_code, "Out of Range" );
/** @brief if an operation is unsupported or not valid this may be thrown */
FC_DECLARE_EXCEPTION( invalid_operation_exception,
invalid_operation_exception_code,
"Invalid Operation" );
/** @brief if an host name can not be resolved this may be thrown */
FC_DECLARE_EXCEPTION( unknown_host_exception,
unknown_host_exception_code,
"Unknown Host" );
/**
* @brief used to report a canceled Operation
*/
FC_DECLARE_EXCEPTION( canceled_exception, canceled_exception_code, "Canceled" );
/**
* @brief used inplace of assert() to report violations of pre conditions.
*/
FC_DECLARE_EXCEPTION( assert_exception, assert_exception_code, "Assert Exception" );
FC_DECLARE_EXCEPTION( eof_exception, eof_exception_code, "End Of File" );
FC_DECLARE_EXCEPTION( null_optional, null_optional_code, "null optional" );
FC_DECLARE_EXCEPTION( udt_exception, udt_error_code, "UDT error" );
FC_DECLARE_EXCEPTION( aes_exception, aes_error_code, "AES error" );
FC_DECLARE_EXCEPTION( overflow_exception, overflow_code, "Integer Overflow" );
FC_DECLARE_EXCEPTION( underflow_exception, underflow_code, "Integer Underflow" );
FC_DECLARE_EXCEPTION( divide_by_zero_exception, divide_by_zero_code, "Integer Divide By Zero" );
std::string except_str();
void record_assert_trip(
const char* filename,
uint32_t lineno,
const char* expr
);
extern bool enable_record_assert_trip;
} // namespace fc
#if __APPLE__
#define LIKELY(x) __builtin_expect((long)!!(x), 1L)
#define UNLIKELY(x) __builtin_expect((long)!!(x), 0L)
#else
#define LIKELY(x) (x)
#define UNLIKELY(x) (x)
#endif
/**
*@brief: Workaround for varying preprocessing behavior between MSVC and gcc
*/
#define FC_EXPAND_MACRO( x ) x
/**
* @brief Checks a condition and throws an assert_exception if the test is FALSE
*/
#define FC_ASSERT( TEST, ... ) \
FC_EXPAND_MACRO( \
FC_MULTILINE_MACRO_BEGIN \
if( UNLIKELY(!(TEST)) ) \
{ \
if( fc::enable_record_assert_trip ) \
fc::record_assert_trip( __FILE__, __LINE__, #TEST ); \
FC_THROW_EXCEPTION( fc::assert_exception, #TEST ": " __VA_ARGS__ ); \
} \
FC_MULTILINE_MACRO_END \
)
#define FC_CAPTURE_AND_THROW( EXCEPTION_TYPE, ... ) \
FC_MULTILINE_MACRO_BEGIN \
throw EXCEPTION_TYPE( FC_LOG_MESSAGE( error, "", FC_FORMAT_ARG_PARAMS(__VA_ARGS__) ) ); \
FC_MULTILINE_MACRO_END
//#define FC_THROW( FORMAT, ... )
// FC_INDIRECT_EXPAND workas around a bug in Visual C++ variadic macro processing that prevents it
// from separating __VA_ARGS__ into separate tokens
#define FC_INDIRECT_EXPAND(MACRO, ARGS) MACRO ARGS
#define FC_THROW( ... ) \
FC_MULTILINE_MACRO_BEGIN \
throw fc::exception( FC_INDIRECT_EXPAND(FC_LOG_MESSAGE, ( error, __VA_ARGS__ )) ); \
FC_MULTILINE_MACRO_END
#define FC_EXCEPTION( EXCEPTION_TYPE, FORMAT, ... ) \
EXCEPTION_TYPE( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) )
/**
* @def FC_THROW_EXCEPTION( EXCEPTION, FORMAT, ... )
* @param EXCEPTION a class in the Phoenix::Athena::API namespace that inherits
* @param format - a const char* string with "${keys}"
*/
#define FC_THROW_EXCEPTION( EXCEPTION, FORMAT, ... ) \
FC_MULTILINE_MACRO_BEGIN \
throw EXCEPTION( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) ); \
FC_MULTILINE_MACRO_END
/**
* @def FC_RETHROW_EXCEPTION(ER,LOG_LEVEL,FORMAT,...)
* @brief Appends a log_message to the exception ER and rethrows it.
*/
#define FC_RETHROW_EXCEPTION( ER, LOG_LEVEL, FORMAT, ... ) \
FC_MULTILINE_MACRO_BEGIN \
ER.append_log( FC_LOG_MESSAGE( LOG_LEVEL, FORMAT, __VA_ARGS__ ) ); \
throw; \
FC_MULTILINE_MACRO_END
#define FC_LOG_AND_RETHROW( ) \
catch( fc::exception& er ) { \
wlog( "${details}", ("details",er.to_detail_string()) ); \
FC_RETHROW_EXCEPTION( er, warn, "rethrow" ); \
} catch( const std::exception& e ) { \
fc::exception fce( \
FC_LOG_MESSAGE( warn, "rethrow ${what}: ", ("what",e.what())), \
fc::std_exception_code,\
typeid(e).name(), \
e.what() ) ; \
wlog( "${details}", ("details",fce.to_detail_string()) ); \
throw fce;\
} catch( ... ) { \
fc::unhandled_exception e( \
FC_LOG_MESSAGE( warn, "rethrow"), \
std::current_exception() ); \
wlog( "${details}", ("details",e.to_detail_string()) ); \
throw e; \
}
#define FC_CAPTURE_LOG_AND_RETHROW( ... ) \
catch( fc::exception& er ) { \
wlog( "${details}", ("details",er.to_detail_string()) ); \
wdump( __VA_ARGS__ ); \
FC_RETHROW_EXCEPTION( er, warn, "rethrow", FC_FORMAT_ARG_PARAMS(__VA_ARGS__) ); \
} catch( const std::exception& e ) { \
fc::exception fce( \
FC_LOG_MESSAGE( warn, "rethrow ${what}: ", FC_FORMAT_ARG_PARAMS( __VA_ARGS__ )("what",e.what())), \
fc::std_exception_code,\
typeid(e).name(), \
e.what() ) ; \
wlog( "${details}", ("details",fce.to_detail_string()) ); \
wdump( __VA_ARGS__ ); \
throw fce;\
} catch( ... ) { \
fc::unhandled_exception e( \
FC_LOG_MESSAGE( warn, "rethrow", FC_FORMAT_ARG_PARAMS( __VA_ARGS__) ), \
std::current_exception() ); \
wlog( "${details}", ("details",e.to_detail_string()) ); \
wdump( __VA_ARGS__ ); \
throw e; \
}
#define FC_CAPTURE_AND_LOG( ... ) \
catch( fc::exception& er ) { \
wlog( "${details}", ("details",er.to_detail_string()) ); \
wdump( __VA_ARGS__ ); \
} catch( const std::exception& e ) { \
fc::exception fce( \
FC_LOG_MESSAGE( warn, "rethrow ${what}: ",FC_FORMAT_ARG_PARAMS( __VA_ARGS__ )("what",e.what()) ), \
fc::std_exception_code,\
typeid(e).name(), \
e.what() ) ; \
wlog( "${details}", ("details",fce.to_detail_string()) ); \
wdump( __VA_ARGS__ ); \
} catch( ... ) { \
fc::unhandled_exception e( \
FC_LOG_MESSAGE( warn, "rethrow", FC_FORMAT_ARG_PARAMS( __VA_ARGS__) ), \
std::current_exception() ); \
wlog( "${details}", ("details",e.to_detail_string()) ); \
wdump( __VA_ARGS__ ); \
}
/**
* @def FC_RETHROW_EXCEPTIONS(LOG_LEVEL,FORMAT,...)
* @brief Catchs all exception's, std::exceptions, and ... and rethrows them after
* appending the provided log message.
*/
#define FC_RETHROW_EXCEPTIONS( LOG_LEVEL, FORMAT, ... ) \
catch( fc::exception& er ) { \
FC_RETHROW_EXCEPTION( er, LOG_LEVEL, FORMAT, __VA_ARGS__ ); \
} catch( const std::exception& e ) { \
fc::exception fce( \
FC_LOG_MESSAGE( LOG_LEVEL, "${what}: " FORMAT,__VA_ARGS__("what",e.what())), \
fc::std_exception_code,\
typeid(e).name(), \
e.what() ) ; throw fce;\
} catch( ... ) { \
throw fc::unhandled_exception( \
FC_LOG_MESSAGE( LOG_LEVEL, FORMAT,__VA_ARGS__), \
std::current_exception() ); \
}
#define FC_CAPTURE_AND_RETHROW( ... ) \
catch( fc::exception& er ) { \
FC_RETHROW_EXCEPTION( er, warn, "", FC_FORMAT_ARG_PARAMS(__VA_ARGS__) ); \
} catch( const std::exception& e ) { \
fc::exception fce( \
FC_LOG_MESSAGE( warn, "${what}: ",FC_FORMAT_ARG_PARAMS(__VA_ARGS__)("what",e.what())), \
fc::std_exception_code,\
typeid(e).name(), \
e.what() ) ; throw fce;\
} catch( ... ) { \
throw fc::unhandled_exception( \
FC_LOG_MESSAGE( warn, "",FC_FORMAT_ARG_PARAMS(__VA_ARGS__)), \
std::current_exception() ); \
}
#pragma once
#include <utility>
#include <memory>
#include <fc/string.hpp>
#include <fc/reflect/typename.hpp>
#include <fc/optional.hpp>
#include <fc/fwd.hpp>
namespace boost {
namespace filesystem {
class path;
class directory_iterator;
class recursive_directory_iterator;
}
}
namespace fc {
/**
* @brief wraps boost::filesystem::path to provide platform independent path manipulation.
*
* Most calls are simply a passthrough to boost::filesystem::path, however exceptions are
* wrapped in an fc::error_report and the additional helper method fc::path::windows_string(),
* can be used to calculate paths intended for systems different than the host.
*
* @note Serializes to a fc::value() as the result of generic_string()
*/
class path {
public:
path();
~path();
path( const boost::filesystem::path& );
path( const std::string& p );
/// Constructor to build path using unicode native characters.
path(const std::wstring& p);
path( const char* );
path( const path& p );
path( path&& p );
path& operator =( const path& );
path& operator =( path&& );
path& operator /=( const fc::path& );
friend path operator /( const fc::path& p, const fc::path& );
friend bool operator ==( const fc::path& p, const fc::path& );
friend bool operator !=( const fc::path& p, const fc::path& );
friend bool operator < ( const fc::path& p, const fc::path& );
operator boost::filesystem::path& ();
operator const boost::filesystem::path& ()const;
void replace_extension( const fc::path& e );
fc::path stem()const;
fc::path extension()const;
fc::path filename()const;
fc::path parent_path()const;
std::string string()const;
std::string generic_string()const;
/** On windows, returns a path where all path separators are '\' suitable for displaying
* to users. On other platforms, it does the same as generic_string()
*/
std::string preferred_string() const;
std::wstring wstring() const;
std::wstring generic_wstring() const;
std::wstring preferred_wstring() const;
/** Retrieves native string path representation and next converts it into
ANSI UTF-8 representation.
It is needed since not all parts of fc library accept unicode paths
(fc::file_mapping).
*/
std::string to_native_ansi_path() const;
/**
* @brief replaces '/' with '\' in the result of generic_string()
*
* @note not part of boost::filesystem::path
*/
std::string windows_string()const;
bool is_relative()const;
bool is_absolute()const;
static char separator_char;
private:
#ifdef _WIN64
fwd<boost::filesystem::path,40> _p;
#else
fwd<boost::filesystem::path,32> _p;
#endif
};
namespace detail
{
class path_wrapper
{
public:
path_wrapper(path p) :
_path(p)
{
}
const path* operator->() const
{
return &_path;
}
private:
path _path;
};
}
class directory_iterator {
public:
directory_iterator( const fc::path& p );
directory_iterator();
~directory_iterator();
fc::path operator*()const;
detail::path_wrapper operator->() const;
directory_iterator& operator++(int);
directory_iterator& operator++();
friend bool operator==( const directory_iterator&, const directory_iterator& );
friend bool operator!=( const directory_iterator&, const directory_iterator& );
private:
fwd<boost::filesystem::directory_iterator,16> _p;
};
class recursive_directory_iterator {
public:
recursive_directory_iterator( const fc::path& p );
recursive_directory_iterator();
~recursive_directory_iterator();
fc::path operator*()const;
recursive_directory_iterator& operator++(int);
recursive_directory_iterator& operator++();
void pop();
int level();
friend bool operator==( const recursive_directory_iterator&, const recursive_directory_iterator& );
friend bool operator!=( const recursive_directory_iterator&, const recursive_directory_iterator& );
private:
fwd<boost::filesystem::recursive_directory_iterator,16> _p;
};
bool exists( const path& p );
bool is_directory( const path& p );
bool is_regular_file( const path& p );
void create_directories( const path& p );
void remove_all( const path& p );
path absolute( const path& p );
path make_relative(const path& from, const path& to);
path canonical( const path& p );
uint64_t file_size( const path& p );
uint64_t directory_size( const path& p );
bool remove( const path& p );
void copy( const path& from, const path& to );
void rename( const path& from, const path& to );
void resize_file( const path& file, size_t s );
// setuid, setgid not implemented.
// translates octal permission like 0755 to S_ stuff defined in sys/stat.h
// no-op on Windows.
void chmod( const path& p, int perm );
void create_hard_link( const path& from, const path& to );
path unique_path();
path temp_directory_path();
/** @return the home directory on Linux and OS X and the Profile directory on Windows */
const path& home_path();
/** @return the home_path() on Linux, home_path()/Library/Application Support/ on OS X,
* and APPDATA on windows
*/
const path& app_path();
/** @return application executable path */
const fc::path& current_path();
class variant;
void to_variant( const fc::path&, fc::variant& );
void from_variant( const fc::variant& , fc::path& );
template<> struct get_typename<path> { static const char* name() { return "path"; } };
/**
* Class which creates a temporary directory inside an existing temporary directory.
*/
class temp_file_base
{
public:
inline ~temp_file_base() { remove(); }
inline operator bool() const { return _path.valid(); }
inline bool operator!() const { return !_path; }
const fc::path& path() const;
void remove();
void release();
protected:
typedef fc::optional<fc::path> path_t;
inline temp_file_base(const path_t& path) : _path(path) {}
inline temp_file_base(path_t&& path) : _path(std::move(path)) {}
path_t _path;
};
/**
* Class which creates a temporary directory inside an existing temporary directory.
*/
class temp_file : public temp_file_base
{
public:
temp_file(temp_file&& other);
temp_file& operator=(temp_file&& other);
temp_file(const fc::path& tempFolder = fc::temp_directory_path(), bool create = false);
};
/**
* Class which creates a temporary directory inside an existing temporary directory.
*/
class temp_directory : public temp_file_base
{
public:
temp_directory(temp_directory&& other);
temp_directory& operator=(temp_directory&& other);
temp_directory(const fc::path& tempFolder = fc::temp_directory_path());
};
#if !defined(__APPLE__)
// this code is known to work on linux and windows. It may work correctly on mac,
// or it may need slight tweaks or extra includes. It's disabled now to avoid giving
// a false sense of security.
# define FC_HAS_SIMPLE_FILE_LOCK
#endif
#ifdef FC_HAS_SIMPLE_FILE_LOCK
/** simple class which only allows one process to open any given file.
* approximate usage:
* int main() {
* fc::simple_file_lock instance_lock("~/.my_app/.lock");
* if (!instance_lock.try_lock()) {
* elog("my_app is already running");
* return 1;
* }
* // do stuff here, file will be unlocked when instance_lock goes out of scope
* }
*/
class simple_lock_file
{
public:
simple_lock_file(const path& lock_file_path);
~simple_lock_file();
bool try_lock();
void unlock();
private:
class impl;
std::unique_ptr<impl> my;
};
#endif // FC_HAS_SIMPLE_FILE_LOCK
}
#pragma once
#include <fc/io/raw_fwd.hpp>
namespace fc {
/**
* This class is designed to offer in-place memory allocation of a string up to Length equal to
* sizeof(Storage).
*
* The string will serialize the same way as std::string for variant and raw formats
* The string will sort according to the comparison operators defined for Storage, this enables effecient
* sorting.
*/
template<typename Storage = std::pair<uint64_t,uint64_t> >
class fixed_string {
public:
fixed_string(){
memset( (char*)&data, 0, sizeof(data) );
}
fixed_string( const fixed_string& c ):data(c.data){}
fixed_string( const std::string& str ) {
if( str.size() < sizeof(data) ) {
memset( (char*)&data, 0, sizeof(data) );
memcpy( (char*)&data, str.c_str(), str.size() );
} else {
memcpy( (char*)&data, str.c_str(), sizeof(data) );
}
}
fixed_string( const char* str ) {
memset( (char*)&data, 0, sizeof(data) );
auto l = strlen(str);
if( l < sizeof(data) ) {
memset( (char*)&data, 0, sizeof(data) );
memcpy( (char*)&data, str, l );
}
else {
memcpy( (char*)&data, str, sizeof(data) );
}
}
operator std::string()const {
const char* self = (const char*)&data;
return std::string( self, self + size() );
}
uint32_t size()const {
if( *(((const char*)&data)+sizeof(data) - 1) )
return sizeof(data);
return strnlen( (const char*)&data, sizeof(data) );
}
uint32_t length()const { return size(); }
fixed_string& operator=( const fixed_string& str ) {
data = str.data;
return *this;
}
fixed_string& operator=( const char* str ) {
return *this = fixed_string(str);
}
fixed_string& operator=( const std::string& str ) {
if( str.size() < sizeof(data) ) {
memset( (char*)&data, 0, sizeof(data) );
memcpy( (char*)&data, str.c_str(), str.size() );
}
else {
memcpy( (char*)&data, str.c_str(), sizeof(data) );
}
return *this;
}
friend std::string operator + ( const fixed_string& a, const std::string& b ) {
return std::string(a) + b;
}
friend std::string operator + ( const std::string& a, const fixed_string& b ) {
return a + std::string(b);
}
friend bool operator < ( const fixed_string& a, const fixed_string& b ) {
return a.data < b.data;
}
friend bool operator <= ( const fixed_string& a, const fixed_string& b ) {
return a.data <= b.data;
}
friend bool operator > ( const fixed_string& a, const fixed_string& b ) {
return a.data > b.data;
}
friend bool operator >= ( const fixed_string& a, const fixed_string& b ) {
return a.data >= b.data;
}
friend bool operator == ( const fixed_string& a, const fixed_string& b ) {
return a.data == b.data;
}
friend bool operator != ( const fixed_string& a, const fixed_string& b ) {
return a.data != b.data;
}
friend std::ostream& operator << ( std::ostream& out, const fixed_string& str ) {
return out << std::string(str);
}
//private:
Storage data;
};
namespace raw
{
template<typename Stream, typename Storage>
inline void pack( Stream& s, const fc::fixed_string<Storage>& u ) {
unsigned_int size = u.size();
pack( s, size );
s.write( (const char*)&u.data, size );
}
template<typename Stream, typename Storage>
inline void unpack( Stream& s, fc::fixed_string<Storage>& u ) {
unsigned_int size;
fc::raw::unpack( s, size );
if( size.value > 0 ) {
if( size.value > sizeof(Storage) ) {
s.read( (char*)&u.data, sizeof(Storage) );
char buf[1024];
size_t left = size.value - sizeof(Storage);
while( left >= 1024 )
{
s.read( buf, 1024 );
left -= 1024;
}
s.read( buf, left );
/*
s.seekp( s.tellp() + (size.value - sizeof(Storage)) );
char tmp;
size.value -= sizeof(storage);
while( size.value ){ s.read( &tmp, 1 ); --size.value; }
*/
// s.skip( size.value - sizeof(Storage) );
} else {
s.read( (char*)&u.data, size.value );
}
}
}
/*
template<typename Stream, typename... Args>
inline void pack( Stream& s, const boost::multiprecision::number<Args...>& d ) {
s.write( (const char*)&d, sizeof(d) );
}
template<typename Stream, typename... Args>
inline void unpack( Stream& s, boost::multiprecision::number<Args...>& u ) {
s.read( (const char*)&u, sizeof(u) );
}
*/
}
}
#include <fc/variant.hpp>
namespace fc {
template<typename Storage>
void to_variant( const fixed_string<Storage>& s, variant& v ) {
v = std::string(s);
}
template<typename Storage>
void from_variant( const variant& v, fixed_string<Storage>& s ) {
s = v.as_string();
}
}
#pragma once
#include <fc/aligned.hpp>
namespace fc {
/**
* @brief Used to forward declare value types.
*
*/
template<typename T,unsigned int S, typename Align=double>
class fwd {
public:
template<typename U> fwd( U&& u );
template<typename U, typename V> fwd( U&& u, V&& v );
template<typename U, typename V, typename X, typename Y> fwd( U&& u, V&& v, X&&, Y&& );
fwd();
fwd( const fwd& f );
fwd( fwd&& f );
operator const T&()const;
operator T&();
T& operator*();
const T& operator*()const;
const T* operator->()const;
T* operator->();
bool operator !()const;
template<typename U>
T& operator = ( U&& u );
T& operator = ( fwd&& u );
T& operator = ( const fwd& u );
~fwd();
private:
aligned<S,Align> _store;
};
} // namespace fc
#pragma once
#include <fc/utility.hpp>
#include <fc/fwd.hpp>
#include <new>
namespace fc {
namespace detail {
template<typename A, typename U>
struct add {
typedef decltype( *((A*)0) + *((typename fc::remove_reference<U>::type*)0) ) type;
};
template<typename A, typename U>
struct add_eq {
typedef decltype( *((A*)0) += *((typename fc::remove_reference<U>::type*)0) ) type;
};
template<typename A, typename U>
struct sub {
typedef decltype( *((A*)0) - *((typename fc::remove_reference<U>::type*)0) ) type;
};
template<typename A, typename U>
struct sub_eq {
typedef decltype( *((A*)0) -= *((typename fc::remove_reference<U>::type*)0) ) type;
};
template<typename A, typename U>
struct insert_op {
typedef decltype( *((A*)0) << *((typename fc::remove_reference<U>::type*)0) ) type;
};
template<typename A, typename U>
struct extract_op {
A* a;
U* u;
typedef decltype( *a >> *u ) type;
};
}
template<typename T, unsigned int S, typename U, typename A>
auto operator + ( const fwd<T,S,A>& x, U&& u ) -> typename detail::add<T,U>::type { return *x+fc::forward<U>(u); }
template<typename T, unsigned int S, typename U, typename A>
auto operator - ( const fwd<T,S,A>& x, U&& u ) -> typename detail::sub<T,U>::type { return *x-fc::forward<U>(u); }
template<typename T, unsigned int S, typename U, typename A>
auto operator << ( U& u, const fwd<T,S,A>& f ) -> typename detail::insert_op<U,T>::type { return u << *f; }
template<typename T, unsigned int S, typename U, typename A>
auto operator >> ( U& u, fwd<T,S,A>& f ) -> typename detail::extract_op<U,T>::type { return u >> *f; }
template<typename T, unsigned int S, typename A>
bool fwd<T,S,A>::operator !()const { return !(**this); }
template<uint64_t RequiredSize, uint64_t ProvidedSize>
void check_size() { static_assert( (ProvidedSize >= RequiredSize), "Failed to reserve enough space in fc::fwd<T,S>" ); }
template<typename T,unsigned int S,typename A>
template<typename U>
fwd<T,S,A>::fwd( U&& u ) {
check_size<sizeof(T),sizeof(_store)>();
new (this) T( fc::forward<U>(u) );
}
template<typename T,unsigned int S,typename A>
template<typename U,typename V>
fwd<T,S,A>::fwd( U&& u, V&& v ) {
check_size<sizeof(T),sizeof(_store)>();
new (this) T( fc::forward<U>(u), fc::forward<V>(v) );
}
template<typename T,unsigned int S,typename A>
template<typename U,typename V,typename X,typename Y>
fwd<T,S,A>::fwd( U&& u, V&& v, X&& x, Y&& y ) {
check_size<sizeof(T),sizeof(_store)>();
new (this) T( fc::forward<U>(u), fc::forward<V>(v), fc::forward<X>(x), fc::forward<Y>(y) );
}
template<typename T,unsigned int S,typename A>
fwd<T,S,A>::fwd() {
check_size<sizeof(T),sizeof(_store)>();
new (this) T;
}
template<typename T,unsigned int S,typename A>
fwd<T,S,A>::fwd( const fwd<T,S,A>& f ){
check_size<sizeof(T),sizeof(_store)>();
new (this) T( *f );
}
template<typename T,unsigned int S,typename A>
fwd<T,S,A>::fwd( fwd<T,S,A>&& f ){
check_size<sizeof(T),sizeof(_store)>();
new (this) T( fc::move(*f) );
}
template<typename T,unsigned int S, typename A>
fwd<T,S,A>::operator T&() { return *(( T*)this); }
template<typename T,unsigned int S, typename A>
fwd<T,S,A>::operator const T&()const { return *((const T*)this); }
template<typename T,unsigned int S, typename A>
T& fwd<T,S,A>::operator*() { return *((T*)this); }
template<typename T,unsigned int S, typename A>
const T& fwd<T,S,A>::operator*()const { return *((const T*)this); }
template<typename T,unsigned int S, typename A>
const T* fwd<T,S,A>::operator->()const { return ((const T*)this); }
template<typename T,unsigned int S, typename A>
T* fwd<T,S,A>::operator->(){ return ((T*)this); }
template<typename T,unsigned int S, typename A>
fwd<T,S,A>::~fwd() {
((T*)this)->~T();
}
template<typename T,unsigned int S, typename A>
template<typename U>
T& fwd<T,S,A>::operator = ( U&& u ) {
return **this = fc::forward<U>(u);
}
template<typename T,unsigned int S, typename A>
T& fwd<T,S,A>::operator = ( fwd<T,S,A>&& u ) {
return **this = fc::move(*u);
}
template<typename T,unsigned int S, typename A>
T& fwd<T,S,A>::operator = ( const fwd<T,S,A>& u ) {
return **this = *u;
}
} // namespace fc
#pragma once
#include <stdint.h>
namespace fc {
extern const char* const git_revision_sha;
extern const uint32_t git_revision_unix_timestamp;
} // end namespace fc
#pragma once
#include <fc/variant.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/containers/map.hpp>
#include <boost/interprocess/containers/flat_map.hpp>
#include <boost/interprocess/containers/set.hpp>
#include <boost/interprocess/containers/deque.hpp>
#include <fc/crypto/hex.hpp>
#include <fc/io/raw_fwd.hpp>
namespace fc {
namespace bip = boost::interprocess;
template<typename... T >
void to_variant( const bip::deque< T... >& t, fc::variant& v ) {
std::vector<variant> vars(t.size());
for( size_t i = 0; i < t.size(); ++i ) {
vars[i] = t[i];
}
v = std::move(vars);
}
template<typename T, typename... A>
void from_variant( const fc::variant& v, bip::deque< T, A... >& d ) {
const variants& vars = v.get_array();
d.clear();
d.resize( vars.size() );
for( uint32_t i = 0; i < vars.size(); ++i ) {
from_variant( vars[i], d[i] );
}
}
//bip::map == boost::map
template<typename K, typename V, typename... T >
void to_variant( const bip::map< K, V, T... >& var, fc::variant& vo ) {
std::vector< variant > vars(var.size());
size_t i = 0;
for( auto itr = var.begin(); itr != var.end(); ++itr, ++i )
vars[i] = fc::variant(*itr);
vo = vars;
}
/*
template<typename K, typename V, typename... A>
void from_variant( const variant& var, bip::map<K, V, A...>& vo )
{
const variants& vars = var.get_array();
vo.clear();
for( auto itr = vars.begin(); itr != vars.end(); ++itr )
vo.insert( itr->as< std::pair<K,V> >() ); Not safe for interprocess. Needs allocator
}
*/
template<typename... T >
void to_variant( const bip::vector< T... >& t, fc::variant& v ) {
std::vector<variant> vars(t.size());
for( size_t i = 0; i < t.size(); ++i ) {
vars[i] = t[i];
}
v = std::move(vars);
}
template<typename T, typename... A>
void from_variant( const fc::variant& v, bip::vector< T, A... >& d ) {
const variants& vars = v.get_array();
d.clear();
d.resize( vars.size() );
for( uint32_t i = 0; i < vars.size(); ++i ) {
from_variant( vars[i], d[i] );
}
}
template<typename... T >
void to_variant( const bip::set< T... >& t, fc::variant& v ) {
std::vector<variant> vars;
vars.reserve(t.size());
for( const auto& item : t ) {
vars.emplace_back( item );
}
v = std::move(vars);
}
/*
template<typename T, typename... A>
void from_variant( const fc::variant& v, bip::set< T, A... >& d ) {
const variants& vars = v.get_array();
d.clear();
d.reserve( vars.size() );
for( uint32_t i = 0; i < vars.size(); ++i ) {
from_variant( vars[i], d[i] ); Not safe for interprocess. Needs allocator
}
}
*/
template<typename... A>
void to_variant( const bip::vector<char, A...>& t, fc::variant& v )
{
if( t.size() )
v = variant(fc::to_hex(t.data(), t.size()));
else
v = "";
}
template<typename... A>
void from_variant( const fc::variant& v, bip::vector<char, A...>& d )
{
auto str = v.as_string();
d.resize( str.size() / 2 );
if( d.size() )
{
size_t r = fc::from_hex( str, d.data(), d.size() );
FC_ASSERT( r == d.size() );
}
// std::string b64 = base64_decode( var.as_string() );
// vo = std::vector<char>( b64.c_str(), b64.c_str() + b64.size() );
}
namespace raw {
namespace bip = boost::interprocess;
template<typename Stream, typename T, typename... A>
inline void pack( Stream& s, const bip::vector<T,A...>& value ) {
pack( s, unsigned_int((uint32_t)value.size()) );
auto itr = value.begin();
auto end = value.end();
while( itr != end ) {
fc::raw::pack( s, *itr );
++itr;
}
}
template<typename Stream, typename T, typename... A>
inline void unpack( Stream& s, bip::vector<T,A...>& value ) {
unsigned_int size;
unpack( s, size );
value.clear(); value.resize(size);
for( auto& item : value )
fc::raw::unpack( s, item );
}
}
}
#pragma once
#include <fc/fwd.hpp>
#include <fc/utility.hpp>
namespace boost {
namespace interprocess {
class file_mapping;
class mapped_region;
}
}
namespace fc {
enum mode_t {
read_only,
write_only,
read_write
};
class file_mapping {
public:
file_mapping( const char* file, mode_t );
~file_mapping();
private:
friend class mapped_region;
#ifdef _WIN64
fc::fwd<boost::interprocess::file_mapping,0x38> my;
#else
fc::fwd<boost::interprocess::file_mapping,0x24> my;
#endif
};
class mapped_region {
public:
mapped_region( const file_mapping& fm, mode_t m, uint64_t start, size_t size );
mapped_region( const file_mapping& fm, mode_t m );
~mapped_region();
void flush();
void* get_address()const;
size_t get_size()const;
private:
fc::fwd<boost::interprocess::mapped_region,40> my;
};
}
#pragma once
#include <fc/thread/future.hpp>
#include <fc/io/buffered_iostream.hpp>
#include <vector>
#include <fc/string.hpp>
#include <fc/filesystem.hpp>
namespace fc
{
/**
* @brief abstract interface for interacting with external processes
*
* At the very least we have ssh::process and direct child processes, and
* there may be other processes that need to implement this protocol.
*/
class iprocess
{
public:
enum exec_opts {
open_none = 0,
open_stdin = 0x01,
open_stdout = 0x02,
open_stderr = 0x04,
open_all = open_stdin|open_stdout|open_stderr,
suppress_console = 0x08
};
virtual ~iprocess(){}
/**
*
* @return *this
*/
virtual iprocess& exec( const path& exe, std::vector<std::string> args,
const path& work_dir = path(), int opts = open_all ) = 0;
/**
* @return blocks until the process exits
*/
virtual int result(const microseconds& timeout = microseconds::maximum()) = 0;
/**
* Forcefully kills the process.
*/
virtual void kill() = 0;
/**
* @brief returns a stream that writes to the process' stdin
*/
virtual buffered_ostream_ptr in_stream() = 0;
/**
* @brief returns a stream that reads from the process' stdout
*/
virtual buffered_istream_ptr out_stream() = 0;
/**
* @brief returns a stream that reads from the process' stderr
*/
virtual buffered_istream_ptr err_stream() = 0;
};
typedef std::shared_ptr<iprocess> iprocess_ptr;
} // namespace fc
#pragma once
#include <fc/interprocess/file_mapping.hpp>
#include <memory>
namespace fc
{
class path;
namespace detail
{
/**
* Base class used to hide common implementation details.
*/
class mmap_struct_base
{
public:
size_t size()const;
void flush();
protected:
void open( const fc::path& file, size_t s, bool create );
std::unique_ptr<fc::file_mapping> _file_mapping;
std::unique_ptr<fc::mapped_region> _mapped_region;
};
};
/**
* @class mmap_struct
* @brief A struct that has been mapped from a file.
*
* @note T must be POD
*/
template<typename T>
class mmap_struct : public detail::mmap_struct_base
{
public:
mmap_struct():_mapped_struct(nullptr){}
/**
* Create the file if it does not exist or is of the wrong size if create is true, then maps
* the file to memory.
*
* @throw an exception if the file does not exist or is the wrong size and create is false
*/
void open( const fc::path& file, bool create = false )
{
detail::mmap_struct_base::open( file, sizeof(T), create );
_mapped_struct = (T*)_mapped_region->get_address();
}
T* operator->() { return _mapped_struct; }
const T* operator->()const { return _mapped_struct; }
T& operator*() { return *_mapped_struct; }
const T& operator*()const { return *_mapped_struct; }
private:
T* _mapped_struct;
};
}
#pragma once
#include <fc/interprocess/iprocess.hpp>
namespace fc {
fc::path find_executable_in_path( const fc::string name );
/**
* @brief start and manage an local process
* @note this class implements reference semantics.
*/
class process : public iprocess
{
public:
process();
~process();
virtual iprocess& exec( const fc::path& exe,
std::vector<std::string> args,
const fc::path& work_dir = fc::path(),
int opts = open_all );
virtual int result(const microseconds& timeout = microseconds::maximum());
virtual void kill();
virtual fc::buffered_ostream_ptr in_stream();
virtual fc::buffered_istream_ptr out_stream();
virtual fc::buffered_istream_ptr err_stream();
class impl;
private:
std::unique_ptr<impl> my;
};
typedef std::shared_ptr<process> process_ptr;
} // namespace fc
#pragma once
#include <fc/io/iostream.hpp>
namespace fc
{
namespace detail
{
class buffered_istream_impl;
class buffered_ostream_impl;
}
/**
* @brief Reads data from an unbuffered stream
* and enables peek functionality.
*/
class buffered_istream : public virtual istream
{
public:
buffered_istream( istream_ptr is );
buffered_istream( buffered_istream&& o );
buffered_istream& operator=( buffered_istream&& i );
virtual ~buffered_istream();
/** read at least 1 byte or throw, if no data is available
* this method should block cooperatively until data is
* available or fc::eof_exception is thrown.
*
* @pre len > 0
* @pre buf != nullptr
* @throws fc::eof if at least 1 byte cannot be read
**/
virtual std::size_t readsome( char* buf, std::size_t len );
virtual size_t readsome( const std::shared_ptr<char>& buf, size_t len, size_t offset );
/**
* This method may block until at least 1 character is
* available.
*/
virtual char peek() const;
private:
std::unique_ptr<detail::buffered_istream_impl> my;
};
typedef std::shared_ptr<buffered_istream> buffered_istream_ptr;
/**
*
*/
class buffered_ostream : public virtual ostream
{
public:
buffered_ostream( ostream_ptr o, size_t bufsize = 4096 );
buffered_ostream( buffered_ostream&& m );
~buffered_ostream();
buffered_ostream& operator=( buffered_ostream&& m );
/**
* This method will return immediately unless the buffer
* is full, in which case it will flush which may block.
*/
virtual size_t writesome( const char* buf, size_t len );
virtual size_t writesome( const std::shared_ptr<const char>& buf, size_t len, size_t offset );
virtual void close();
virtual void flush();
private:
std::unique_ptr<detail::buffered_ostream_impl> my;
};
typedef std::shared_ptr<buffered_ostream> buffered_ostream_ptr;
}
#pragma once
namespace fc
{
/** enables / disables echoing of console input, useful for
* entering passwords on the console.
*/
void set_console_echo( bool enable_echo );
} // namespace fc
#pragma once
#include <fc/utility.hpp>
#include <string.h>
#include <stdint.h>
#include <boost/multiprecision/cpp_int.hpp>
namespace fc {
namespace detail
{
NO_RETURN void throw_datastream_range_error( const char* file, size_t len, int64_t over );
}
/**
* The purpose of this datastream is to provide a fast, effecient, means
* of calculating the amount of data "about to be written" and then
* writing it. This means having two modes of operation, "test run" where
* you call the entire pack sequence calculating the size, and then
* actually packing it after doing a single allocation.
*/
template<typename T>
class datastream {
public:
datastream( T start, size_t s )
:_start(start),_pos(start),_end(start+s){};
inline void skip( size_t s ){ _pos += s; }
inline bool read( char* d, size_t s ) {
if( size_t(_end - _pos) >= (size_t)s ) {
memcpy( d, _pos, s );
_pos += s;
return true;
}
detail::throw_datastream_range_error( "read", _end-_start, int64_t(-((_end-_pos) - 1)));
}
inline bool write( const char* d, size_t s ) {
if( _end - _pos >= (int32_t)s ) {
memcpy( _pos, d, s );
_pos += s;
return true;
}
detail::throw_datastream_range_error( "write", _end-_start, int64_t(-((_end-_pos) - 1)));
}
inline bool put(char c) {
if( _pos < _end ) {
*_pos = c;
++_pos;
return true;
}
detail::throw_datastream_range_error( "put", _end-_start, int64_t(-((_end-_pos) - 1)));
}
inline bool get( unsigned char& c ) { return get( *(char*)&c ); }
inline bool get( char& c )
{
if( _pos < _end ) {
c = *_pos;
++_pos;
return true;
}
detail::throw_datastream_range_error( "get", _end-_start, int64_t(-((_end-_pos) - 1)));
}
T pos()const { return _pos; }
inline bool valid()const { return _pos <= _end && _pos >= _start; }
inline bool seekp(size_t p) { _pos = _start + p; return _pos <= _end; }
inline size_t tellp()const { return _pos - _start; }
inline size_t remaining()const { return _end - _pos; }
private:
T _start;
T _pos;
T _end;
};
template<>
class datastream<size_t> {
public:
datastream( size_t init_size = 0):_size(init_size){};
inline bool skip( size_t s ) { _size += s; return true; }
inline bool write( const char* ,size_t s ) { _size += s; return true; }
inline bool put(char ) { ++_size; return true; }
inline bool valid()const { return true; }
inline bool seekp(size_t p) { _size = p; return true; }
inline size_t tellp()const { return _size; }
inline size_t remaining()const { return 0; }
private:
size_t _size;
};
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const int32_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, int32_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const uint32_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, uint32_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const int64_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, int64_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const uint64_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, uint64_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const int16_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, int16_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const uint16_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, uint16_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const int8_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, int8_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const uint8_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, uint8_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
/*
template<typename ST, typename T>
inline datastream<ST>& operator<<(datastream<ST>& ds, const boost::multiprecision::number<T>& n) {
unsigned char data[(std::numeric_limits<decltype(n)>::digits+1)/8];
ds.read( (char*)data, sizeof(data) );
boost::multiprecision::import_bits( n, data, data + sizeof(data), 1 );
}
template<typename ST, typename T>
inline datastream<ST>& operator>>(datastream<ST>& ds, boost::multiprecision::number<T>& n) {
unsigned char data[(std::numeric_limits<decltype(n)>::digits+1)/8];
boost::multiprecision::export_bits( n, data, 1 );
ds.write( (const char*)data, sizeof(data) );
}
*/
} // namespace fc
#pragma once
#include <fc/reflect/reflect.hpp>
#include <fc/io/raw_fwd.hpp>
#include <fc/variant.hpp>
namespace fc
{
template<typename IntType, typename EnumType>
class enum_type
{
public:
enum_type( EnumType t )
:value(t){}
enum_type( IntType t )
:value( (EnumType)t ){}
enum_type(){}
explicit operator IntType()const { return static_cast<IntType>(value); }
operator EnumType()const { return value; }
operator std::string()const { return fc::reflector<EnumType>::to_string(value); }
enum_type& operator=( IntType i ) { value = (EnumType)i; return *this;}
enum_type& operator=( EnumType i ) { value = i; return *this;}
bool operator<( EnumType i ) const { return value < i; }
bool operator>( EnumType i ) const { return value < i; }
bool operator<(const enum_type& e) const { return value < e.value;}
bool operator>(const enum_type& e) const { return value > e.value;}
bool operator<=(const enum_type& e) const { return value <= e.value;}
bool operator>=(const enum_type& e) const { return value >= e.value;}
friend bool operator==( const enum_type& e, IntType i ){ return e.value == (EnumType)i;}
friend bool operator==( const enum_type& e, EnumType i ){ return e.value == i; }
friend bool operator==( const enum_type& e, const enum_type& i ){ return e.value == i.value; }
friend bool operator==( IntType i, const enum_type& e){ return e.value == (EnumType)i; }
friend bool operator==( EnumType i, const enum_type& e ){ return e.value == i; }
friend bool operator!=( const enum_type& e, IntType i ){ return e.value != (EnumType)i;}
friend bool operator!=( const enum_type& e, EnumType i ){ return e.value != i; }
friend bool operator!=( const enum_type& e, const enum_type& i ){ return e.value != i.value; }
EnumType value;
};
template<typename IntType, typename EnumType>
void to_variant( const enum_type<IntType,EnumType>& var, variant& vo )
{
vo = (EnumType)var.value;
}
template<typename IntType, typename EnumType>
void from_variant( const variant& var, enum_type<IntType,EnumType>& vo )
{
vo.value = var.as<EnumType>();
}
/** serializes like an IntType */
namespace raw
{
template<typename Stream, typename IntType, typename EnumType>
inline void pack( Stream& s, const fc::enum_type<IntType,EnumType>& tp )
{
fc::raw::pack( s, static_cast<IntType>(tp) );
}
template<typename Stream, typename IntType, typename EnumType>
inline void unpack( Stream& s, fc::enum_type<IntType,EnumType>& tp )
{
IntType t;
fc::raw::unpack( s, t );
tp = t;
}
}
}
#include <fc/filesystem.hpp>
#include <string>
namespace fc {
/**
* Grab the full contents of a file into a string object.
* NB reading a full file into memory is a poor choice
* if the file may be very large.
*/
void read_file_contents( const fc::path& filename, std::string& result );
}
#pragma once
#include <fc/io/iostream.hpp>
#include <fc/exception/exception.hpp>
namespace fc
{
/**
* Records the size, but discards the data.
*/
class size_stream : public virtual fc::ostream
{
public:
size_stream( size_t s = 0):_size(s){}
size_t size()const { return _size; }
size_t seek( size_t pos ) { return _size = pos; }
virtual size_t writesome( const char* /*ignored buf*/, size_t len )
{
_size += len;
return len;
}
virtual void close(){}
virtual void flush(){}
private:
size_t _size;
};
class iobuffer : public virtual fc::iostream
{
public:
iobuffer( size_t s )
:_data(s){}
size_t size()const { return _data.size(); }
size_t pos()const { return _pos; }
size_t seek( size_t pos )
{
return _pos = std::min<size_t>(_data.size(),pos);
}
virtual size_t readsome( char* buf, size_t len )
{
auto avail = std::min<size_t>( _data.size()-_pos, len );
if( avail == 0 ) throw fc::eof_exception();
memcpy( buf, _data.data()+_pos, avail );
_pos += avail;
return avail;
}
/**
* This method may block until at least 1 character is
* available.
*/
char peek()const
{
if( _pos == _data.size() ) throw fc::eof_exception();
return _data[_pos];
}
virtual size_t writesome( const char* buf, size_t len )
{
auto avail = std::max<size_t>( _data.size(), _pos + len );
_data.resize(avail);
memcpy( _data.data()+_pos, buf, len );
_pos += avail;
return avail;
}
char* data() { return _data.data(); }
virtual void close(){}
virtual void flush(){}
private:
std::vector<char> _data;
size_t _pos;
};
}
#pragma once
#include <fc/variant.hpp>
#include <fc/filesystem.hpp>
namespace fc
{
using std::ostream;
/**
* Provides interface for json serialization.
*
* json strings are always UTF8
*/
class json
{
public:
enum parse_type
{
legacy_parser = 0,
strict_parser = 1,
relaxed_parser = 2,
legacy_parser_with_string_doubles = 3
};
enum output_formatting
{
stringify_large_ints_and_doubles = 0,
legacy_generator = 1
};
static ostream& to_stream( ostream& out, const fc::string&);
static ostream& to_stream( ostream& out, const variant& v, output_formatting format = stringify_large_ints_and_doubles );
static ostream& to_stream( ostream& out, const variants& v, output_formatting format = stringify_large_ints_and_doubles );
static ostream& to_stream( ostream& out, const variant_object& v, output_formatting format = stringify_large_ints_and_doubles );
static variant from_string( const string& utf8_str, parse_type ptype = legacy_parser );
static variants variants_from_string( const string& utf8_str, parse_type ptype = legacy_parser );
static string to_string( const variant& v, output_formatting format = stringify_large_ints_and_doubles );
static string to_pretty_string( const variant& v, output_formatting format = stringify_large_ints_and_doubles );
static bool is_valid( const std::string& json_str, parse_type ptype = legacy_parser );
template<typename T>
static void save_to_file( const T& v, const fc::path& fi, bool pretty = true, output_formatting format = stringify_large_ints_and_doubles )
{
save_to_file( variant(v), fi, pretty, format );
}
static void save_to_file( const variant& v, const fc::path& fi, bool pretty = true, output_formatting format = stringify_large_ints_and_doubles );
static variant from_file( const fc::path& p, parse_type ptype = legacy_parser );
template<typename T>
static T from_file( const fc::path& p, parse_type ptype = legacy_parser )
{
return json::from_file(p, ptype).as<T>();
}
template<typename T>
static string to_string( const T& v, output_formatting format = stringify_large_ints_and_doubles )
{
return to_string( variant(v), format );
}
template<typename T>
static string to_pretty_string( const T& v, output_formatting format = stringify_large_ints_and_doubles )
{
return to_pretty_string( variant(v), format );
}
template<typename T>
static void save_to_file( const T& v, const std::string& p, bool pretty = true, output_formatting format = stringify_large_ints_and_doubles )
{
save_to_file( variant(v), fc::path(p), pretty );
}
};
} // fc
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
#pragma once
namespace fc
{
class noncopyable
{
public:
noncopyable(){}
private:
noncopyable( const noncopyable& ) = delete;
noncopyable& operator=( const noncopyable& ) = delete;
};
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册