Updates from BitShares FC #22

Closed
nathanielhourt wants to merge 693 commits from dapp-support into latest-fc
141 changed files with 411 additions and 6330 deletions
Showing only changes of commit 7f93f265c7 - Show all commits

View file

@ -31,7 +31,6 @@ script:
- set -o pipefail
- tests/run-parallel-tests.sh tests/all_tests
- "tests/api 2>&1 | grep -vE 'callback result 9|remote_calc->add. 4, 5 .: 9|set callback|] \\.$'"
- tests/bip_lock 2>&1 | cat
- tests/hmac_test 2>&1 | cat
- tests/ecc_test README.md 2>&1 | cat
- tests/log_test 2>&1 | cat

View file

@ -24,7 +24,6 @@ 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)
@ -37,17 +36,6 @@ SET(BOOST_COMPONENTS)
LIST(APPEND BOOST_COMPONENTS thread date_time filesystem system program_options chrono unit_test_framework context iostreams regex)
SET( Boost_USE_STATIC_LIBS ON CACHE STRING "ON or OFF" )
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 )
# Configure secp256k1-zkp
if ( MSVC )
# autoconf won't work here, hard code the defines
@ -233,17 +221,12 @@ set( fc_sources
src/io/sstream.cpp
src/io/json.cpp
src/io/varint.cpp
src/io/console.cpp
src/filesystem.cpp
src/interprocess/signals.cpp
src/interprocess/file_mapping.cpp
src/interprocess/mmap_struct.cpp
src/interprocess/file_mutex.cpp
src/rpc/cli.cpp
src/rpc/http_api.cpp
src/rpc/json_connection.cpp
src/rpc/state.cpp
src/rpc/bstate.cpp
src/rpc/websocket_api.cpp
src/log/log_message.cpp
src/log/logger.cpp
@ -257,7 +240,6 @@ set( fc_sources
src/crypto/aes.cpp
src/crypto/crc.cpp
src/crypto/city.cpp
src/crypto/base36.cpp
src/crypto/base58.cpp
src/crypto/base64.cpp
src/crypto/bigint.cpp
@ -268,10 +250,9 @@ set( fc_sources
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/elliptic_impl_priv.cpp
src/crypto/elliptic_secp256k1.cpp
src/crypto/rand.cpp
src/network/tcp_socket.cpp
src/network/udp_socket.cpp
@ -401,7 +382,7 @@ target_include_directories(fc
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} ${PLATFORM_SPECIFIC_LIBS} ${RPCRT4} ${CMAKE_DL_LIBS} ${rt_library} ${editline_libraries} ${ECC_LIB} )
target_link_libraries( fc PUBLIC ${LINK_USR_LOCAL_LIB} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES} ${PLATFORM_SPECIFIC_LIBS} ${RPCRT4} ${CMAKE_DL_LIBS} ${rt_library} ${editline_libraries} secp256k1 )
if(MSVC)
set_source_files_properties( src/network/http/websocket.cpp PROPERTIES COMPILE_FLAGS "/bigobj" )

View file

@ -31,12 +31,6 @@
</Expand>
</Type>
<Type Name="fc::string">
<DisplayString>{my}</DisplayString>
<Expand>
<ExpandedItem>my</ExpandedItem>
</Expand>
</Type>
<Type Name="fc::optional&lt;*&gt;">
<DisplayString Condition="!_valid">invalid</DisplayString>
@ -54,4 +48,4 @@
</Expand>
</Type>
</AutoVisualizer>
</AutoVisualizer>

View file

@ -1,65 +0,0 @@
#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

View file

@ -1,14 +0,0 @@
#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; }
};
}

View file

@ -1,7 +0,0 @@
#pragma once
#include <boost/any.hpp>
namespace fc {
// TODO: define this without using boost
typedef boost::any any;
}

View file

@ -1,7 +1,7 @@
#pragma once
#include <fc/thread/future.hpp>
#include <fc/any.hpp>
#include <functional>
#include <boost/any.hpp>
#include <boost/config.hpp>
// ms visual c++ (as of 2013) doesn't accept the standard syntax for calling a
@ -75,7 +75,7 @@ namespace fc {
api( const T& p )
:_vtable( std::make_shared<vtable_type>() )
{
_data = std::make_shared<fc::any>(p);
_data = std::make_shared<boost::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;
@ -95,7 +95,7 @@ namespace fc {
protected:
std::shared_ptr<vtable_type> _vtable;
std::shared_ptr<fc::any> _data;
std::shared_ptr<boost::any> _data;
};
} // namespace fc

View file

@ -112,7 +112,7 @@ namespace fc {
std::vector<char> ve = v.as< std::vector<char> >( 1 );
if( ve.size() )
{
memcpy(&bi, ve.data(), fc::min<size_t>(ve.size(),sizeof(bi)) );
memcpy(&bi, ve.data(), std::min<size_t>(ve.size(),sizeof(bi)) );
}
else
memset( &bi, char(0), sizeof(bi) );

View file

@ -282,7 +282,7 @@ namespace asio {
{
public:
istream( std::shared_ptr<AsyncReadStream> str )
:_stream( fc::move(str) ){}
:_stream( std::move(str) ){}
virtual size_t readsome( char* buf, size_t len )
{
@ -302,7 +302,7 @@ namespace asio {
{
public:
ostream( std::shared_ptr<AsyncWriteStream> str )
:_stream( fc::move(str) ){}
:_stream( std::move(str) ){}
virtual size_t writesome( const char* buf, size_t len )
{

View file

@ -1,10 +1,10 @@
#pragma once
#include <fc/string.hpp>
#include <string>
namespace fc
{
string zlib_compress(const string& in);
std::string zlib_compress(const std::string& in);
} // namespace fc

View file

@ -1,14 +0,0 @@
#pragma once
#include <fc/config.hpp>
#include <deque>
namespace fc {
namespace raw {
template<typename Stream, typename T>
void pack( Stream& s, const std::deque<T>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename T>
void unpack( Stream& s, std::deque<T>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
}
} // namespace fc

View file

@ -1,10 +0,0 @@
#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 );
}

View file

@ -1,5 +1,5 @@
#pragma once
#include <fc/string.hpp>
#include <string>
#include <vector>
namespace fc {

View file

@ -1,7 +1,7 @@
#pragma once
#include <stdint.h>
#include <fc/string.hpp>
#include <fc/vector.hpp>
#include <string>
#include <vector>
struct bignum_st;
typedef bignum_st BIGNUM;
@ -55,7 +55,7 @@ namespace fc {
bigint operator--(int);
bigint& operator--();
operator fc::string()const;
operator std::string()const;
// returns bignum as bigendian bytes
operator std::vector<char>()const;

View file

@ -1,178 +0,0 @@
////////////////////////////////////////////////////////////////////////////
///
// 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

View file

@ -153,9 +153,9 @@ namespace fc {
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 );
std::string str() const;
std::string to_base58() const { return str(); }
static extended_public_key from_base58( const std::string& base58 );
private:
sha256 c;
@ -177,10 +177,10 @@ namespace fc {
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 );
std::string str() const;
std::string to_base58() const { return str(); }
static extended_private_key from_base58( const std::string& base58 );
static extended_private_key generate_master( const std::string& seed );
static extended_private_key generate_master( const char* seed, uint32_t seed_len );
private:

View file

@ -1,15 +1,15 @@
#pragma once
#include <fc/string.hpp>
#include <fc/utility.hpp>
#include <stdint.h>
#include <string>
#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 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 );
size_t from_hex( const std::string& hex_str, char* out_data, size_t out_data_len );
}

View file

@ -1,117 +0,0 @@
#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, uint32_t _max_depth=FC_PACK_MAX_DEPTH )
{
FC_ASSERT( _max_depth > 0 );
bytes ser;
fc::raw::unpack( s, ser, _max_depth - 1 );
pk = fc::public_key( ser );
}
template<typename Stream>
void pack( Stream& s, const fc::public_key& pk, uint32_t _max_depth=FC_PACK_MAX_DEPTH )
{
FC_ASSERT( _max_depth > 0 );
fc::raw::pack( s, pk.serialize(), _max_depth - 1 );
}
template<typename Stream>
void unpack( Stream& s, fc::private_key& pk, uint32_t _max_depth=FC_PACK_MAX_DEPTH )
{
FC_ASSERT( _max_depth > 0 );
bytes ser;
fc::raw::unpack( s, ser, _max_depth - 1 );
pk = fc::private_key( ser );
}
template<typename Stream>
void pack( Stream& s, const fc::private_key& pk, uint32_t _max_depth=FC_PACK_MAX_DEPTH )
{
FC_ASSERT( _max_depth > 0 );
fc::raw::pack( s, pk.serialize(), _max_depth - 1 );
}
}
class variant;
void to_variant( const public_key& bi, variant& v, uint32_t max_depth = 1 );
void from_variant( const variant& v, public_key& bi, uint32_t max_depth = 1 );
void to_variant( const private_key& bi, variant& v, uint32_t max_depth = 1 );
void from_variant( const variant& v, private_key& bi, uint32_t max_depth = 1 );
} // fc

View file

@ -1,8 +1,8 @@
#pragma once
#include <fc/fwd.hpp>
#include <fc/string.hpp>
#include <functional>
#include <string>
namespace fc{
@ -10,16 +10,16 @@ class sha1
{
public:
sha1();
explicit sha1( const string& hex_str );
explicit sha1( const std::string& hex_str );
string str()const;
operator string()const;
std::string str()const;
operator std::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& );
static sha1 hash( const std::string& );
template<typename T>
static sha1 hash( const T& t )

View file

@ -2,7 +2,6 @@
#include <unordered_map>
#include <fc/fwd.hpp>
#include <fc/io/raw_fwd.hpp>
#include <fc/string.hpp>
namespace fc
{

View file

@ -1,6 +1,5 @@
#pragma once
#include <fc/fwd.hpp>
#include <fc/string.hpp>
#include <fc/platform_independence.hpp>
#include <fc/io/raw_fwd.hpp>

View file

@ -1,6 +1,5 @@
#pragma once
#include <fc/fwd.hpp>
#include <fc/string.hpp>
namespace fc
{

View file

@ -240,9 +240,9 @@ namespace fc
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 ){}\
:BASE( std::move(m), CODE, BOOST_PP_STRINGIZE(TYPE), WHAT ){}\
TYPE( fc::log_messages msgs ) \
:BASE( fc::move( msgs ), CODE, BOOST_PP_STRINGIZE(TYPE), WHAT ) {} \
:BASE( std::move( msgs ), CODE, BOOST_PP_STRINGIZE(TYPE), WHAT ) {} \
TYPE( const TYPE& c ) \
:BASE(c){} \
TYPE( const BASE& c ) \

View file

@ -2,7 +2,6 @@
#include <utility>
#include <memory>
#include <fc/string.hpp>
#include <fc/reflect/typename.hpp>
#include <fc/optional.hpp>
#include <fc/fwd.hpp>
@ -228,37 +227,5 @@ namespace fc {
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
}

View file

@ -1,143 +0,0 @@
#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(){}
fixed_string( const fixed_string& c ):data(c.data){}
fixed_string( const std::string& str ) {
if( str.size() <= sizeof(data) )
memcpy( (char*)&data, str.c_str(), str.size() );
else {
memcpy( (char*)&data, str.c_str(), sizeof(data) );
}
}
fixed_string( const char* str ) {
auto l = strlen(str);
if( l <= 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) ) {
data = Storage();
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;
}
//private:
Storage data;
};
namespace raw
{
template<typename Stream, typename Storage>
inline void pack( Stream& s, const fc::fixed_string<Storage>& u, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) {
FC_ASSERT( _max_depth > 0 );
unsigned_int size = u.size();
pack( s, size, _max_depth - 1 );
s.write( (const char*)&u.data, size );
}
template<typename Stream, typename Storage>
inline void unpack( Stream& s, fc::fixed_string<Storage>& u, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) {
FC_ASSERT( _max_depth > 0 );
unsigned_int size;
fc::raw::unpack( s, size, _max_depth - 1 );
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 );
} else {
s.read( (char*)&u.data, size.value );
}
}
}
}
}
#include <fc/variant.hpp>
namespace fc {
template<typename Storage>
void to_variant( const fixed_string<Storage>& s, variant& v, uint32_t max_depth = 1 ) {
v = std::string(s);
}
template<typename Storage>
void from_variant( const variant& v, fixed_string<Storage>& s, uint32_t max_depth = 1 ) {
s = v.as_string();
}
}

View file

@ -1,5 +1,4 @@
#pragma once
#include <fc/aligned.hpp>
namespace fc {
@ -37,7 +36,7 @@ class fwd {
~fwd();
private:
aligned<S,Align> _store;
alignas(Align) char _store[S];
};

View file

@ -3,31 +3,33 @@
#include <fc/utility.hpp>
#include <fc/fwd.hpp>
#include <new>
#include <type_traits>
#include <utility>
namespace fc {
namespace detail {
template<typename A, typename U>
struct add {
typedef decltype( *((A*)0) + *((typename fc::remove_reference<U>::type*)0) ) type;
typedef decltype( *((A*)0) + *((typename std::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;
typedef decltype( *((A*)0) += *((typename std::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;
typedef decltype( *((A*)0) - *((typename std::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;
typedef decltype( *((A*)0) -= *((typename std::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;
typedef decltype( *((A*)0) << *((typename std::remove_reference<U>::type*)0) ) type;
};
template<typename A, typename U>
struct extract_op {
@ -91,7 +93,7 @@ namespace fc {
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) );
new (this) T( std::move(*f) );
}
@ -124,7 +126,7 @@ namespace fc {
template<typename T,unsigned int S, typename A>
T& fwd<T,S,A>::operator = ( fwd<T,S,A>&& u ) {
return **this = fc::move(*u);
return **this = std::move(*u);
}
template<typename T,unsigned int S, typename A>
T& fwd<T,S,A>::operator = ( const fwd<T,S,A>& u ) {

View file

@ -1,108 +0,0 @@
#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/exception/exception.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, uint32_t max_depth ) {
FC_ASSERT( max_depth > 0, "Recursion depth exceeded!" );
--max_depth;
std::vector<variant> vars(t.size());
for( size_t i = 0; i < t.size(); ++i ) {
to_variant( t[i], vars[i], max_depth );
}
v = std::move(vars);
}
template<typename T, typename... A>
void from_variant( const fc::variant& v, bip::deque< T, A... >& d, uint32_t max_depth ) {
FC_ASSERT( max_depth > 0, "Recursion depth exceeded!" );
--max_depth;
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], max_depth );
}
}
template<typename K, typename V, typename... T >
void to_variant( const bip::map< K, V, T... >& var, fc::variant& vo, uint32_t max_depth ) {
FC_ASSERT( max_depth > 0, "Recursion depth exceeded!" );
--max_depth;
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, max_depth );
vo = vars;
}
template<typename... T >
void to_variant( const bip::vector< T... >& t, fc::variant& v, uint32_t max_depth ) {
FC_ASSERT( max_depth > 0, "Recursion depth exceeded!" );
--max_depth;
std::vector<variant> vars(t.size());
for( size_t i = 0; i < t.size(); ++i ) {
to_variant( t[i], vars[i], max_depth );
}
v = std::move(vars);
}
template<typename T, typename... A>
void from_variant( const fc::variant& v, bip::vector< T, A... >& d, uint32_t max_depth ) {
FC_ASSERT( max_depth > 0, "Recursion depth exceeded!" );
--max_depth;
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], max_depth );
}
}
template<typename... T >
void to_variant( const bip::set< T... >& t, fc::variant& v, uint32_t max_depth ) {
FC_ASSERT( max_depth > 0, "Recursion depth exceeded!" );
--max_depth;
std::vector<variant> vars;
vars.reserve(t.size());
for( const auto& item : t ) {
vars.emplace_back( variant( item, max_depth ) );
}
v = std::move(vars);
}
template<typename... A>
void to_variant( const bip::vector<char, A...>& t, fc::variant& v, uint32_t max_depth = 1 )
{
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, uint32_t max_depth = 1 )
{
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() );
}
}
}

View file

@ -1,6 +1,7 @@
#pragma once
#include <fc/fwd.hpp>
#include <fc/utility.hpp>
#include <cstdint>
#include <cstdlib>
namespace boost {
namespace interprocess {
@ -24,7 +25,7 @@ namespace fc {
#ifdef _WIN64
fc::fwd<boost::interprocess::file_mapping,0x38> my;
#else
fc::fwd<boost::interprocess::file_mapping,0x24> my;
fc::fwd<boost::interprocess::file_mapping,0x28> my;
#endif
};

View file

@ -1,44 +0,0 @@
#pragma once
#include <fc/time.hpp>
#include <fc/thread/spin_yield_lock.hpp>
#include <memory>
namespace fc {
class microseconds;
class time_point;
class path;
struct context;
namespace detail { class file_mutex_impl; }
/**
* The purpose of this class is to support synchronization of
* processes, threads, and coop-threads.
*
* Before grabbing the lock for a thread or coop, a file_mutex will first
* grab a process-level lock. After grabbing the process level lock, it will
* synchronize in the same way as a local process lock.
*/
class file_mutex {
public:
file_mutex( const fc::path& filename );
~file_mutex();
bool try_lock();
bool try_lock_for( const microseconds& rel_time );
bool try_lock_until( const time_point& abs_time );
void lock();
void unlock();
void lock_shared();
void unlock_shared();
bool try_lock_shared();
int readers()const;
private:
std::unique_ptr<detail::file_mutex_impl> my;
};
} // namespace fc

View file

@ -1,67 +0,0 @@
#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

View file

@ -1,59 +0,0 @@
#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;
};
}

View file

@ -1,37 +0,0 @@
#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

View file

@ -1,8 +0,0 @@
#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

View file

@ -1,81 +0,0 @@
#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;
};
}

View file

@ -1,7 +1,6 @@
#pragma once
#include <fc/utility.hpp>
#include <fc/string.hpp>
#include <memory>
#include <string>
namespace fc {
@ -61,7 +60,7 @@ namespace fc {
class iostream : public virtual ostream, public virtual istream {};
fc::istream& getline( fc::istream&, fc::string&, char delim = '\n' );
fc::istream& getline( fc::istream&, std::string&, char delim = '\n' );
template<size_t N>
ostream& operator<<( ostream& o, char (&array)[N] )
@ -72,7 +71,7 @@ namespace fc {
ostream& operator<<( ostream& o, char );
ostream& operator<<( ostream& o, const char* v );
ostream& operator<<( ostream& o, const std::string& v );
ostream& operator<<( ostream& o, const fc::string& v );
ostream& operator<<( ostream& o, const std::string& v );
ostream& operator<<( ostream& o, const double& v );
ostream& operator<<( ostream& o, const float& v );
ostream& operator<<( ostream& o, const int64_t& v );
@ -88,7 +87,7 @@ namespace fc {
#endif
istream& operator>>( istream& o, std::string& v );
istream& operator>>( istream& o, fc::string& v );
istream& operator>>( istream& o, std::string& v );
istream& operator>>( istream& o, char& v );
istream& operator>>( istream& o, double& v );
istream& operator>>( istream& o, float& v );

View file

@ -33,7 +33,7 @@ namespace fc
legacy_generator = 1
};
static ostream& to_stream( ostream& out, const fc::string& );
static ostream& to_stream( ostream& out, const std::string& );
static ostream& to_stream( ostream& out, const variant& v, output_formatting format = stringify_large_ints_and_doubles, uint32_t max_depth = DEFAULT_MAX_RECURSION_DEPTH );
static ostream& to_stream( ostream& out, const variants& v, output_formatting format = stringify_large_ints_and_doubles, uint32_t max_depth = DEFAULT_MAX_RECURSION_DEPTH );
static ostream& to_stream( ostream& out, const variant_object& v, output_formatting format = stringify_large_ints_and_doubles, uint32_t max_depth = DEFAULT_MAX_RECURSION_DEPTH );

View file

@ -10,7 +10,6 @@
#include <fc/io/fstream.hpp>
#include <fc/io/sstream.hpp>
#include <fc/log/logger.hpp>
#include <fc/string.hpp>
//#include <utfcpp/utf8.h>
#include <iostream>
#include <fstream>
@ -24,7 +23,7 @@ namespace fc { namespace json_relaxed
variant variant_from_stream( T& in, uint32_t max_depth );
template<typename T>
fc::string tokenFromStream( T& in )
std::string tokenFromStream( T& in )
{
fc::stringstream token;
try
@ -81,7 +80,7 @@ namespace fc { namespace json_relaxed
}
template<typename T, bool strict, bool allow_escape>
fc::string quoteStringFromStream( T& in )
std::string quoteStringFromStream( T& in )
{
fc::stringstream token;
try
@ -107,11 +106,11 @@ namespace fc { namespace json_relaxed
try
{
if( in.peek() != q )
return fc::string();
return std::string();
}
catch( const fc::eof_exception& e )
{
return fc::string();
return std::string();
}
// triple quote processing
@ -186,7 +185,7 @@ namespace fc { namespace json_relaxed
}
template<typename T, bool strict>
fc::string stringFromStream( T& in )
std::string stringFromStream( T& in )
{
try
{
@ -294,7 +293,7 @@ namespace fc { namespace json_relaxed
};
template<uint8_t base>
fc::variant parseInt( const fc::string& token, size_t start )
fc::variant parseInt( const std::string& token, size_t start )
{
static const CharValueTable ctbl;
static const uint64_t INT64_MAX_PLUS_ONE = static_cast<uint64_t>(INT64_MAX) + 1;
@ -336,7 +335,7 @@ namespace fc { namespace json_relaxed
}
template<bool strict, uint8_t base>
fc::variant maybeParseInt( const fc::string& token, size_t start )
fc::variant maybeParseInt( const std::string& token, size_t start )
{
try
{
@ -352,7 +351,7 @@ namespace fc { namespace json_relaxed
}
template<bool strict>
fc::variant parseNumberOrStr( const fc::string& token )
fc::variant parseNumberOrStr( const std::string& token )
{ try {
//ilog( (token) );
size_t i = 0, n = token.length();
@ -588,7 +587,7 @@ namespace fc { namespace json_relaxed
template<typename T, bool strict>
variant numberFromStream( T& in )
{ try {
fc::string token = tokenFromStream(in);
std::string token = tokenFromStream(in);
variant result = json_relaxed::parseNumberOrStr<strict>( token );
if( strict && !(result.is_int64() || result.is_uint64() || result.is_double()) )
FC_THROW_EXCEPTION( parse_error_exception, "expected: number" );
@ -598,7 +597,7 @@ namespace fc { namespace json_relaxed
template<typename T, bool strict>
variant wordFromStream( T& in )
{
fc::string token = tokenFromStream(in);
std::string token = tokenFromStream(in);
FC_ASSERT( token.length() > 0 );

View file

@ -50,7 +50,7 @@ namespace fc {
fc::raw::unpack( s, what, _max_depth );
fc::raw::unpack( s, msgs, _max_depth );
e = fc::exception( fc::move(msgs), code, name, what );
e = fc::exception( std::move(msgs), code, name, what );
}
template<typename Stream>
@ -206,7 +206,7 @@ namespace fc {
template<typename Stream> inline void pack( Stream& s, const char* v, uint32_t _max_depth )
{
FC_ASSERT( _max_depth > 0 );
fc::raw::pack( s, fc::string(v), _max_depth - 1 );
fc::raw::pack( s, std::string(v), _max_depth - 1 );
}
template<typename Stream, typename T>
@ -270,18 +270,18 @@ namespace fc {
}
// fc::string
template<typename Stream> inline void pack( Stream& s, const fc::string& v, uint32_t _max_depth ) {
template<typename Stream> inline void pack( Stream& s, const std::string& v, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
fc::raw::pack( s, unsigned_int(v.size()), _max_depth - 1 );
if( v.size() ) s.write( v.c_str(), v.size() );
}
template<typename Stream> inline void unpack( Stream& s, fc::string& v, uint32_t _max_depth ) {
template<typename Stream> inline void unpack( Stream& s, std::string& v, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
std::vector<char> tmp; fc::raw::unpack( s, tmp, _max_depth - 1 );
if( tmp.size() )
v = fc::string( tmp.data(), tmp.data()+tmp.size() );
else v = fc::string();
v = std::string( tmp.data(), tmp.data()+tmp.size() );
else v = std::string();
}
// bool

View file

@ -1,7 +1,6 @@
#pragma once
#include <fc/config.hpp>
#include <fc/container/flat_fwd.hpp>
#include <fc/container/deque_fwd.hpp>
#include <fc/io/varint.hpp>
#include <fc/array.hpp>
#include <fc/safe.hpp>
@ -31,15 +30,11 @@ namespace fc {
namespace ip { class endpoint; }
namespace ecc { class public_key; class private_key; }
template<typename Storage> class fixed_string;
namespace raw {
template<typename T>
inline size_t pack_size( const T& v );
template<typename Stream, typename Storage> inline void pack( Stream& s, const fc::fixed_string<Storage>& u, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename Storage> inline void unpack( Stream& s, fc::fixed_string<Storage>& u, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename IntType, typename EnumType>
inline void pack( Stream& s, const fc::enum_type<IntType,EnumType>& tp, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename IntType, typename EnumType>
@ -58,8 +53,8 @@ namespace fc {
//template<typename Stream, typename T> inline void pack( Stream& s, const flat_set<T>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
//template<typename Stream, typename T> inline void unpack( Stream& s, flat_set<T>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
//template<typename Stream, typename T> inline void pack( Stream& s, const std::deque<T>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
//template<typename Stream, typename T> inline void unpack( Stream& s, std::deque<T>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename T> inline void pack( Stream& s, const std::deque<T>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename T> inline void unpack( Stream& s, std::deque<T>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename K, typename V> inline void pack( Stream& s, const std::unordered_map<K,V>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename K, typename V> inline void unpack( Stream& s, std::unordered_map<K,V>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH );

View file

@ -1,24 +0,0 @@
#pragma once
#include <fc/io/raw.hpp>
#include <fc/interprocess/file_mapping.hpp>
#include <fc/filesystem.hpp>
#include <fc/exception/exception.hpp>
namespace fc
{
namespace raw
{
template<typename T>
void unpack_file( const fc::path& filename, T& obj )
{
try {
fc::file_mapping fmap( filename.generic_string().c_str(), fc::read_only);
fc::mapped_region mapr( fmap, fc::read_only, 0, fc::file_size(filename) );
auto cs = (const char*)mapr.get_address();
fc::datastream<const char*> ds( cs, mapr.get_size() );
fc::raw::unpack(ds,obj);
} FC_RETHROW_EXCEPTIONS( info, "unpacking file ${file}", ("file",filename) );
}
}
}

View file

@ -100,23 +100,23 @@ namespace fc { namespace raw {
}
case variant::string_type:
{
fc::string val;
std::string val;
raw::unpack( s, val, _max_depth );
v = fc::move(val);
v = std::move(val);
return;
}
case variant::array_type:
{
variants val;
raw::unpack( s, val, _max_depth );
v = fc::move(val);
v = std::move(val);
return;
}
case variant::object_type:
{
variant_object val;
raw::unpack( s, val, _max_depth );
v = fc::move(val);
v = std::move(val);
return;
}
default:
@ -148,13 +148,13 @@ namespace fc { namespace raw {
mvo.reserve( std::min( vs.value, static_cast<uint64_t>(FC_MAX_PREALLOC_SIZE) ) );
for( uint32_t i = 0; i < vs.value; ++i )
{
fc::string key;
std::string key;
fc::variant value;
fc::raw::unpack( s, key, _max_depth );
fc::raw::unpack( s, value, _max_depth );
mvo.set( fc::move(key), fc::move(value) );
mvo.set( std::move(key), std::move(value) );
}
v = fc::move(mvo);
v = std::move(mvo);
}
} } // fc::raw

View file

@ -7,12 +7,12 @@ namespace fc {
class stringstream : virtual public iostream {
public:
stringstream();
stringstream( fc::string& s);
stringstream( const fc::string& s);
stringstream( std::string& s);
stringstream( const std::string& s);
~stringstream();
fc::string str();
void str(const fc::string& s);
std::string str();
void str(const std::string& s);
void clear();

View file

@ -1,6 +1,6 @@
#pragma once
#include <fc/shared_ptr.hpp>
#include <fc/string.hpp>
#include <string>
namespace fc {
class appender;
@ -30,13 +30,13 @@ namespace fc {
typedef fc::shared_ptr<appender> ptr;
template<typename T>
static bool register_appender(const fc::string& type) {
static bool register_appender(const std::string& type) {
return register_appender( type, new detail::appender_factory_impl<T>() );
}
static appender::ptr create( const fc::string& name, const fc::string& type, const variant& args );
static appender::ptr get( const fc::string& name );
static bool register_appender( const fc::string& type, const appender_factory::ptr& f );
static appender::ptr create( const std::string& name, const std::string& type, const variant& args );
static appender::ptr get( const std::string& name );
static bool register_appender( const std::string& type, const appender_factory::ptr& f );
virtual void log( const log_message& m ) = 0;
};

View file

@ -40,7 +40,7 @@ namespace fc
:format( "${timestamp} ${thread_name} ${context} ${file}:${line} ${method} ${level}] ${message}" ),
stream(console_appender::stream::std_error),max_object_depth(FC_MAX_LOG_OBJECT_DEPTH),flush(true){}
fc::string format;
std::string format;
console_appender::stream::type stream;
std::vector<level_color> level_colors;
uint32_t max_object_depth;

View file

@ -12,7 +12,7 @@ class file_appender : public appender {
struct config {
config( const fc::path& p = "log.txt" );
fc::string format;
std::string format;
fc::path filename;
bool flush = true;
bool rotate = false;

View file

@ -8,6 +8,7 @@
#include <fc/variant_object.hpp>
#include <fc/shared_ptr.hpp>
#include <memory>
#include <string>
namespace fc
{
@ -65,19 +66,19 @@ namespace fc
explicit log_context( const variant& v, uint32_t max_depth );
variant to_variant( uint32_t max_depth )const;
string get_file()const;
std::string get_file()const;
uint64_t get_line_number()const;
string get_method()const;
string get_thread_name()const;
string get_task_name()const;
string get_host_name()const;
std::string get_method()const;
std::string get_thread_name()const;
std::string get_task_name()const;
std::string get_host_name()const;
time_point get_timestamp()const;
log_level get_log_level()const;
string get_context()const;
std::string get_context()const;
void append_context( const fc::string& c );
void append_context( const std::string& c );
string to_string()const;
std::string to_string()const;
private:
std::shared_ptr<detail::log_context_impl> my;
};
@ -116,10 +117,10 @@ namespace fc
log_message( const variant& v, uint32_t max_depth );
variant to_variant(uint32_t max_depth)const;
string get_message()const;
std::string get_message()const;
log_context get_context()const;
string get_format()const;
std::string get_format()const;
variant_object get_data()const;
private:

View file

@ -1,6 +1,5 @@
#pragma once
#include <fc/config.hpp>
#include <fc/string.hpp>
#include <fc/time.hpp>
#include <fc/shared_ptr.hpp>
#include <fc/log/log_message.hpp>
@ -23,7 +22,7 @@ namespace fc
class logger
{
public:
static logger get( const fc::string& name = "default");
static logger get( const std::string& name = "default");
logger();
logger( const string& name, const logger& parent = nullptr );
@ -41,8 +40,8 @@ namespace fc
logger& set_parent( const logger& l );
logger get_parent()const;
void set_name( const fc::string& n );
const fc::string& name()const;
void set_name( const std::string& n );
const std::string& name()const;
void add_appender( const fc::shared_ptr<appender>& a );
std::vector<fc::shared_ptr<appender> > get_appenders()const;

View file

@ -9,7 +9,7 @@ namespace fc {
variant args = variant()) :
name(name),
type(type),
args(fc::move(args)),
args(std::move(args)),
enabled(true)
{}
string name;
@ -19,7 +19,7 @@ namespace fc {
};
struct logger_config {
logger_config(const fc::string& name = ""):name(name),enabled(true),additivity(false){}
logger_config(const std::string& name = ""):name(name),enabled(true),additivity(false){}
string name;
ostring parent;
/// if not set, then parents level is used.

View file

@ -1,26 +0,0 @@
#pragma once
#include <fc/tuple.hpp>
#include <fc/function.hpp>
namespace fc {
template<typename R>
std::function<R, fc::tuple<> > make_fused( const std::function<R>& f ) {
return [=]( fc::tuple<> ){ return f(); };
}
template<typename R,typename A>
std::function<R(fc::tuple<A>) > make_fused( const std::function<R(A)>& f ) {
return [f]( fc::tuple<A> t){ return f(t.a); };
}
template<typename R,typename A,typename B>
std::function<R(fc::tuple<A,B>) > make_fused( const std::function<R(A,B)>& f ) {
return [f]( fc::tuple<A,B> t){ return f(t.a,t.b); };
}
template<typename R,typename A,typename B,typename C>
std::function<R(fc::tuple<A,B,C>) > make_fused( const std::function<R(A,B,C)>& f ) {
return [f]( fc::tuple<A,B,C> t){ return f(t.a,t.b,t.c); };
}
template<typename R,typename A,typename B,typename C,typename D>
std::function<R(fc::tuple<A,B,C,D>) > make_fused( const std::function<R(A,B,C,D)>& f ) {
return [f]( fc::tuple<A,B,C> t){ return f(t.a,t.b,t.c,t.d); };
}
}

View file

@ -1,7 +1,7 @@
#pragma once
#include <fc/vector.hpp>
#include <fc/string.hpp>
#include <memory>
#include <string>
#include <vector>
namespace fc {
namespace ip { class endpoint; }
@ -11,11 +11,11 @@ namespace fc {
struct header
{
header( fc::string k, fc::string v )
:key(fc::move(k)),val(fc::move(v)){}
header( std::string k, std::string v )
:key(std::move(k)),val(std::move(v)){}
header(){}
fc::string key;
fc::string val;
std::string key;
std::string val;
};
typedef std::vector<header> headers;
@ -39,16 +39,16 @@ namespace fc {
struct request
{
fc::string get_header( const fc::string& key )const;
fc::string remote_endpoint;
fc::string method;
fc::string domain;
fc::string path;
std::string get_header( const std::string& key )const;
std::string remote_endpoint;
std::string method;
std::string domain;
std::string path;
std::vector<header> headers;
std::vector<char> body;
};
std::vector<header> parse_urlencoded_params( const fc::string& f );
std::vector<header> parse_urlencoded_params( const std::string& f );
/**
* Connections have reference semantics, all copies refer to the same
@ -61,7 +61,7 @@ namespace fc {
~connection();
// used for clients
void connect_to( const fc::ip::endpoint& ep );
http::reply request( const fc::string& method, const fc::string& url, const fc::string& body = std::string(), const headers& = headers());
http::reply request( const std::string& method, const std::string& url, const std::string& body = std::string(), const headers& = headers());
// used for servers
fc::tcp_socket& get_socket()const;

View file

@ -35,7 +35,7 @@ namespace fc { namespace http {
response& operator=(const response& );
response& operator=( response&& );
void add_header( const fc::string& key, const fc::string& val )const;
void add_header( const std::string& key, const std::string& val )const;
void set_status( const http::reply::status_code& s )const;
void set_length( uint64_t s )const;

View file

@ -2,7 +2,7 @@
#include <functional>
#include <memory>
#include <string>
#include <fc/any.hpp>
#include <boost/any.hpp>
#include <fc/network/ip.hpp>
#include <fc/signals.hpp>
@ -26,14 +26,14 @@ namespace fc { namespace http {
void on_message_handler( const std::function<void(const std::string&)>& h ) { _on_message = h; }
void on_http_handler( const std::function<std::string(const std::string&)>& h ) { _on_http = h; }
void set_session_data( fc::any d ){ _session_data = std::move(d); }
fc::any& get_session_data() { return _session_data; }
void set_session_data( boost::any d ){ _session_data = std::move(d); }
boost::any& get_session_data() { return _session_data; }
virtual std::string get_request_header(const std::string& key) = 0;
fc::signal<void()> closed;
private:
fc::any _session_data;
boost::any _session_data;
std::function<void(const std::string&)> _on_message;
std::function<string(const std::string&)> _on_http;
};

View file

@ -1,5 +1,4 @@
#pragma once
#include <fc/string.hpp>
#include <fc/crypto/sha1.hpp>
#include <fc/io/raw_fwd.hpp>
#include <fc/crypto/city.hpp>
@ -11,10 +10,10 @@ namespace fc {
class address {
public:
address( uint32_t _ip = 0 );
address( const fc::string& s );
address( const std::string& s );
address& operator=( const fc::string& s );
operator fc::string()const;
address& operator=( const std::string& s );
operator std::string()const;
operator uint32_t()const;
friend bool operator==( const address& a, const address& b );

View file

@ -1,5 +1,4 @@
#pragma once
#include <fc/vector.hpp>
#include <fc/network/ip.hpp>
namespace fc

View file

@ -1,5 +1,4 @@
#pragma once
#include <fc/utility.hpp>
#include <fc/fwd.hpp>
#include <fc/io/iostream.hpp>
#include <fc/time.hpp>
@ -52,7 +51,7 @@ namespace fc {
friend class tcp_server;
class impl;
#ifdef _WIN64
fc::fwd<impl,0x81> my;
fc::fwd<impl,0x88> my;
#else
fc::fwd<impl,0x54> my;
#endif

View file

@ -1,5 +1,4 @@
#pragma once
#include <fc/utility.hpp>
#include <fc/shared_ptr.hpp>
#include <memory>

View file

@ -1,5 +1,4 @@
#pragma once
#include <fc/string.hpp>
#include <fc/optional.hpp>
#include <stdint.h>
#include <fc/filesystem.hpp>
@ -8,7 +7,7 @@
namespace fc {
typedef fc::optional<fc::string> ostring;
typedef fc::optional<std::string> ostring;
typedef fc::optional<fc::path> opath;
typedef fc::optional<fc::variant_object> ovariant_object;

View file

@ -1,14 +0,0 @@
#pragma once
namespace fc
{
class noncopyable
{
public:
noncopyable(){}
private:
noncopyable( const noncopyable& ) = delete;
noncopyable& operator=( const noncopyable& ) = delete;
};
}

View file

@ -1,6 +1,7 @@
#pragma once
#include <fc/utility.hpp>
#include <assert.h>
#include <utility>
namespace fc {
@ -43,7 +44,7 @@ namespace fc {
optional( optional&& o )
:_valid(false)
{
if( o._valid ) new (ptr()) T( fc::move(*o) );
if( o._valid ) new (ptr()) T( std::move(*o) );
_valid = o._valid;
o.reset();
}
@ -71,7 +72,7 @@ namespace fc {
optional( optional<U>&& o )
:_valid(false)
{
if( o._valid ) new (ptr()) T( fc::move(*o) );
if( o._valid ) new (ptr()) T( std::move(*o) );
_valid = o._valid;
o.reset();
}
@ -156,10 +157,10 @@ namespace fc {
{
if( _valid && o._valid )
{
ref() = fc::move(*o);
ref() = std::move(*o);
o.reset();
} else if ( !_valid && o._valid ) {
*this = fc::move(*o);
*this = std::move(*o);
} else if (_valid) {
reset();
}
@ -173,10 +174,10 @@ namespace fc {
{
if( _valid && o._valid )
{
ref() = fc::move(*o);
ref() = std::move(*o);
o.reset();
} else if ( !_valid && o._valid ) {
*this = fc::move(*o);
*this = std::move(*o);
} else if (_valid) {
reset();
}

View file

@ -6,6 +6,7 @@
*
*/
#include <fc/string.hpp>
#include <fc/utility.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
@ -126,7 +127,7 @@ void fc::reflector<TYPE>::visit( const Visitor& v ) { \
#define FC_REFLECT_ENUM_TO_STRING( r, enum_type, elem ) \
case enum_type::elem: return BOOST_PP_STRINGIZE(elem);
#define FC_REFLECT_ENUM_TO_FC_STRING( r, enum_type, elem ) \
case enum_type::elem: return fc::string(BOOST_PP_STRINGIZE(elem));
case enum_type::elem: return std::string(BOOST_PP_STRINGIZE(elem));
#define FC_REFLECT_ENUM_FROM_STRING( r, enum_type, elem ) \
if( strcmp( s, BOOST_PP_STRINGIZE(elem) ) == 0 ) return enum_type::elem;
@ -149,13 +150,13 @@ template<> struct reflector<ENUM> { \
static const char* to_string(int64_t i) { \
return to_string(ENUM(i)); \
} \
static fc::string to_fc_string(ENUM elem) { \
static std::string to_fc_string(ENUM elem) { \
switch( elem ) { \
BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_ENUM_TO_FC_STRING, ENUM, FIELDS ) \
} \
return fc::to_string(int64_t(elem)); \
} \
static fc::string to_fc_string(int64_t i) { \
static std::string to_fc_string(int64_t i) { \
return to_fc_string(ENUM(i)); \
} \
static ENUM from_int(int64_t i) { \

View file

@ -3,13 +3,12 @@
#include <deque>
#include <map>
#include <set>
#include <string>
#include <vector>
#include <fc/string.hpp>
#include <fc/optional.hpp>
#include <fc/container/flat_fwd.hpp>
#include <fc/container/deque_fwd.hpp>
namespace fc {
class value;
@ -30,8 +29,8 @@ namespace fc {
template<> struct get_typename<bool> { static const char* name() { return "bool"; } };
template<> struct get_typename<char> { static const char* name() { return "char"; } };
template<> struct get_typename<void> { static const char* name() { return "char"; } };
template<> struct get_typename<string> { static const char* name() { return "string"; } };
template<> struct get_typename<value> { static const char* name() { return "value"; } };
template<> struct get_typename<std::string> { static const char* name() { return "string"; } };
template<> struct get_typename<fc::exception> { static const char* name() { return "fc::exception"; } };
template<> struct get_typename<std::vector<char>> { static const char* name() { return "std::vector<char>"; } };
template<typename T> struct get_typename<std::vector<T>>

View file

@ -71,7 +71,7 @@ namespace fc
{
mutable_variant_object mvo;
fc::reflector<T>::visit( to_variant_visitor<T>( mvo, v, max_depth ) );
vo = fc::move(mvo);
vo = std::move(mvo);
}
template<typename T>
static inline void from_variant( const fc::variant& v, T& o, uint32_t max_depth )

View file

@ -2,7 +2,7 @@
#include <fc/variant.hpp>
#include <fc/optional.hpp>
#include <fc/api.hpp>
#include <fc/any.hpp>
#include <boost/any.hpp>
#include <memory>
#include <vector>
#include <functional>
@ -208,7 +208,7 @@ namespace fc {
std::weak_ptr<fc::api_connection> _api_connection;
fc::any _api;
boost::any _api;
std::map< std::string, uint32_t > _by_name;
std::vector< std::function<variant(const variants&)> > _methods;
}; // class generic_api

View file

@ -1,532 +0,0 @@
#pragma once
#include <fc/variant.hpp>
#include <fc/io/raw.hpp>
#include <fc/optional.hpp>
#include <fc/api.hpp>
#include <fc/any.hpp>
#include <memory>
#include <vector>
#include <functional>
#include <utility>
#include <fc/signals.hpp>
//#include <fc/rpc/json_connection.hpp>
namespace fc {
class binary_api_connection;
namespace detail {
template<typename Signature>
class callback_functor
{
public:
typedef typename std::function<Signature>::result_type result_type;
callback_functor( std::weak_ptr< fc::binary_api_connection > con, uint64_t id )
:_callback_id(id),_binary_api_connection(con){}
template<typename... Args>
result_type operator()( Args... args )const;
private:
uint64_t _callback_id;
std::weak_ptr< fc::binary_api_connection > _binary_api_connection;
};
template<typename R, typename Arg0, typename ... Args>
std::function<R(Args...)> bind_first_arg( const std::function<R(Arg0,Args...)>& f, Arg0 a0 )
{
return [=]( Args... args ) { return f( a0, args... ); };
}
template<typename R>
R call_generic( const std::function<R()>& f, variants::const_iterator a0, variants::const_iterator e )
{
return f();
}
template<typename R, typename Arg0, typename ... Args>
R call_generic( const std::function<R(Arg0,Args...)>& f, variants::const_iterator a0, variants::const_iterator e )
{
FC_ASSERT( a0 != e );
return call_generic<R,Args...>( bind_first_arg<R,Arg0,Args...>( f, a0->as< typename std::decay<Arg0>::type >() ), a0+1, e );
}
template<typename R, typename ... Args>
std::function<variant(const fc::variants&)> to_generic( const std::function<R(Args...)>& f )
{
return [=]( const variants& args ) {
return variant( call_generic( f, args.begin(), args.end() ) );
};
}
template<typename ... Args>
std::function<variant(const fc::variants&)> to_generic( const std::function<void(Args...)>& f )
{
return [=]( const variants& args ) {
call_generic( f, args.begin(), args.end() );
return variant();
};
}
/**
* If api<T> is returned from a remote method, the API is eagerly bound to api<T> of
* the correct type in api_visitor::from_variant(). This binding [1] needs a reference
* to the binary_api_connection, which is made available to from_variant() as a parameter.
*
* However, in the case of a remote method which returns api_base which can subsequently
* be cast by the caller with as<T>, we need to keep track of the connection because
* the binding is done later (when the client code actually calls as<T>).
*
* [1] The binding actually happens in get_remote_api().
*/
class any_api : public api_base
{
public:
any_api( api_id_type api_id, const std::shared_ptr<fc::binary_api_connection>& con )
: _api_id(api_id), _binary_api_connection(con) {}
virtual uint64_t get_handle()const override
{ return _api_id; }
virtual api_id_type register_api( binary_api_connection& conn )const override
{ FC_ASSERT( false ); return api_id_type(); }
api_id_type _api_id;
std::weak_ptr<fc::binary_api_connection> _binary_api_connection;
};
} // namespace detail
class generic_api
{
public:
template<typename Api>
generic_api( const Api& a, const std::shared_ptr<fc::binary_api_connection>& c );
generic_api( const generic_api& cpy ) = delete;
vector<char> call( const string& name, const vector<char>& args )
{
auto itr = _by_name.find(name);
FC_ASSERT( itr != _by_name.end(), "no method with name '${name}'", ("name",name)("api",_by_name) );
return call( itr->second, args );
}
vector<char> call( uint32_t method_id, const vector<char>& args )
{
FC_ASSERT( method_id < _methods.size() );
return _methods[method_id](args);
}
std::weak_ptr< fc::binary_api_connection > get_connection()
{
return _binary_api_connection;
}
std::vector<std::string> get_method_names()const
{
std::vector<std::string> result;
result.reserve( _by_name.size() );
for( auto& m : _by_name ) result.push_back(m.first);
return result;
}
private:
friend struct api_visitor;
template<typename R, typename Arg0, typename ... Args>
std::function<R(Args...)> bind_first_arg( const std::function<R(Arg0,Args...)>& f, Arg0 a0 )const
{
return [=]( Args... args ) { return f( a0, args... ); };
}
template<typename R>
R call_generic( const std::function<R()>& f, datastream<const char*>& ds )const
{
return f();
}
template<typename R, typename Signature, typename ... Args>
R call_generic( const std::function<R(std::function<Signature>,Args...)>& f, datastream<const char*>& ds )
{
uint64_t callback_id = 0;
fc::raw::unpack( ds, callback_id );
detail::callback_functor<Signature> arg0( get_connection(), callback_id );
return call_generic<R,Args...>( this->bind_first_arg<R,std::function<Signature>,Args...>( f, std::function<Signature>(arg0) ), ds );
}
template<typename R, typename Signature, typename ... Args>
R call_generic( const std::function<R(const std::function<Signature>&,Args...)>& f, fc::datastream<const char*>& ds )
{
uint64_t callback_id = 0;
fc::raw::unpack( ds, callback_id );
detail::callback_functor<Signature> arg0( get_connection(), callback_id );
return call_generic<R,Args...>( this->bind_first_arg<R,const std::function<Signature>&,Args...>( f, arg0 ), ds );
}
template<typename R, typename Arg0, typename ... Args>
R call_generic( const std::function<R(Arg0,Args...)>& f, fc::datastream<const char*>& ds )
{
std::decay<Arg0>::type a0;
fc::raw::unpack( ds, a0 );
return call_generic<R,Args...>( this->bind_first_arg<R,Arg0,Args...>( f, a0 ), ds );
}
struct api_visitor
{
api_visitor( generic_api& a, const std::weak_ptr<fc::binary_api_connection>& s ):api(a),_api_con(s){ }
template<typename Interface, typename Adaptor, typename ... Args>
std::function<variant(const fc::variants&)> to_generic( const std::function<api<Interface,Adaptor>(Args...)>& f )const;
template<typename Interface, typename Adaptor, typename ... Args>
std::function<variant(const fc::variants&)> to_generic( const std::function<fc::optional<api<Interface,Adaptor>>(Args...)>& f )const;
template<typename ... Args>
std::function<variant(const fc::variants&)> to_generic( const std::function<fc::api_ptr(Args...)>& f )const;
template<typename R, typename ... Args>
std::function<variant(const fc::variants&)> to_generic( const std::function<R(Args...)>& f )const;
template<typename ... Args>
std::function<variant(const fc::variants&)> to_generic( const std::function<void(Args...)>& f )const;
template<typename Result, typename... Args>
void operator()( const char* name, std::function<Result(Args...)>& memb )const {
api._methods.emplace_back( to_generic( memb ) );
api._by_name[name] = api._methods.size() - 1;
}
generic_api& api;
const std::weak_ptr<fc::binary_api_connection>& _api_con;
};
std::weak_ptr<fc::binary_api_connection> _binary_api_connection;
fc::any _api;
std::map< std::string, uint32_t > _by_name;
std::vector< std::function<vector<char>(const vector<char>&)> > _methods;
}; // class generic_api
class binary_api_connection : public std::enable_shared_from_this<fc::binary_api_connection>
{
public:
typedef std::vector<char> params_type;
typedef std::vector<char> result_type;
binary_api_connection(){}
virtual ~binary_api_connection(){};
template<typename T>
api<T> get_remote_api( api_id_type api_id = 0 )
{
api<T> result;
result->visit( api_visitor( api_id, this->shared_from_this() ) );
return result;
}
/** makes calls to the remote server */
virtual result_type send_call( api_id_type api_id, string method_name, params_type args = params_type() ) = 0;
virtual result_type send_callback( uint64_t callback_id, params_type args = params_type() ) = 0;
virtual void send_notice( uint64_t callback_id, params_type args = params_type() ) = 0;
result_type receive_call( api_id_type api_id, const string& method_name, const params_type& args = params_type() )const
{
FC_ASSERT( _local_apis.size() > api_id );
return _local_apis[api_id]->call( method_name, args );
}
result_type receive_callback( uint64_t callback_id, const params_type& args = params_type() )const
{
FC_ASSERT( _local_callbacks.size() > callback_id );
return _local_callbacks[callback_id]( args );
}
void receive_notice( uint64_t callback_id, const params_type& args = params_type() )const
{
FC_ASSERT( _local_callbacks.size() > callback_id );
_local_callbacks[callback_id]( args );
}
template<typename Interface>
api_id_type register_api( const Interface& a )
{
auto handle = a.get_handle();
auto itr = _handle_to_id.find(handle);
if( itr != _handle_to_id.end() ) return itr->second;
_local_apis.push_back( std::unique_ptr<generic_api>( new generic_api(a, shared_from_this() ) ) );
_handle_to_id[handle] = _local_apis.size() - 1;
return _local_apis.size() - 1;
}
template<typename Signature>
uint64_t register_callback( const std::function<Signature>& cb )
{
_local_callbacks.push_back( detail::to_generic( cb ) );
return _local_callbacks.size() - 1;
}
std::vector<std::string> get_method_names( api_id_type local_api_id = 0 )const { return _local_apis[local_api_id]->get_method_names(); }
fc::signal<void()> closed;
private:
std::vector< std::unique_ptr<generic_api> > _local_apis;
std::map< uint64_t, api_id_type > _handle_to_id;
std::vector< std::function<variant(const variants&)> > _local_callbacks;
struct api_visitor
{
uint32_t _api_id;
std::shared_ptr<fc::binary_api_connection> _connection;
api_visitor( uint32_t api_id, std::shared_ptr<fc::binary_api_connection> con )
:_api_id(api_id),_connection(std::move(con))
{
}
api_visitor() = delete;
template<typename Result>
static Result from_vector( const vector<char>& v, Result*, const std::shared_ptr<fc::binary_api_connection>& )
{
return fc::raw::unpack<Result>( v );
}
template<typename ResultInterface>
static fc::api<ResultInterface> from_vector( const vector<char>& v,
fc::api<ResultInterface>* /*used for template deduction*/,
const std::shared_ptr<fc::binary_api_connection>& con
)
{
return con->get_remote_api<ResultInterface>( fc::raw::unpack<uint64_t>( v ) );
}
static fc::api_ptr from_vector(
const vector<char>& v,
fc::api_ptr* /* used for template deduction */,
const std::shared_ptr<fc::binary_api_connection>& con
)
{
return fc::api_ptr( new detail::any_api( fc::raw::unpack<uint64_t>(v), con ) );
}
template<typename T>
static result_type convert_callbacks( const std::shared_ptr<fc::binary_api_connection>&, const T& v )
{
return fc::raw::pack(v);
}
template<typename Signature>
static result_type convert_callbacks( const std::shared_ptr<fc::binary_api_connection>& con, const std::function<Signature>& v )
{
return con->register_callback( v );
}
template<typename Result, typename... Args>
void operator()( const char* name, std::function<Result(Args...)>& memb )const
{
auto con = _connection;
auto api_id = _api_id;
memb = [con,api_id,name]( Args... args ) {
auto var_result = con->send_call( api_id, name, { convert_callbacks(con,args)...} );
return from_vector( var_result, (Result*)nullptr, con );
};
}
template<typename... Args>
void operator()( const char* name, std::function<void(Args...)>& memb )const
{
auto con = _connection;
auto api_id = _api_id;
memb = [con,api_id,name]( Args... args ) {
con->send_call( api_id, name, { convert_callbacks(con,args)...} );
};
}
};
};
class local_binary_api_connection : public binary_api_connection
{
public:
/** makes calls to the remote server */
virtual result_type send_call( api_id_type api_id, string method_name, params_type args = params_type() ) override
{
FC_ASSERT( _remote_connection );
return _remote_connection->receive_call( api_id, method_name, std::move(args) );
}
virtual result_type send_callback( uint64_t callback_id, params_type args = params_type() ) override
{
FC_ASSERT( _remote_connection );
return _remote_connection->receive_callback( callback_id, args );
}
virtual void send_notice( uint64_t callback_id, params_type args = params_type() ) override
{
FC_ASSERT( _remote_connection );
_remote_connection->receive_notice( callback_id, args );
}
void set_remote_connection( const std::shared_ptr<fc::binary_api_connection>& rc )
{
FC_ASSERT( !_remote_connection );
FC_ASSERT( rc != this->shared_from_this() );
_remote_connection = rc;
}
const std::shared_ptr<fc::binary_api_connection>& remote_connection()const { return _remote_connection; }
std::shared_ptr<fc::binary_api_connection> _remote_connection;
};
template<typename Api>
generic_api::generic_api( const Api& a, const std::shared_ptr<fc::binary_api_connection>& c )
:_binary_api_connection(c),_api(a)
{
boost::any_cast<const Api&>(a)->visit( api_visitor( *this, c ) );
}
template<typename Interface, typename Adaptor, typename ... Args>
std::function<result_type(const params_type&)> generic_api::api_visitor::to_generic(
const std::function<fc::api<Interface,Adaptor>(Args...)>& f )const
{
auto api_con = _api_con;
auto gapi = &api;
return [=]( const params_type& args ) {
auto con = api_con.lock();
FC_ASSERT( con, "not connected" );
fc::raw::datastream<const char*> ds( args.data(), args.size() );
auto api_result = gapi->call_generic( f, args );
return con->register_api( api_result );
};
}
template<typename Interface, typename Adaptor, typename ... Args>
std::function<result_type(const params_type&)> generic_api::api_visitor::to_generic(
const std::function<fc::optional<fc::api<Interface,Adaptor>>(Args...)>& f )const
{
auto api_con = _api_con;
auto gapi = &api;
return [=]( const params_type& args )-> fc::variant {
auto con = api_con.lock();
FC_ASSERT( con, "not connected" );
fc::raw::datastream<const char*> ds( args.data(), args.size() );
auto api_result = gapi->call_generic( f, ds );
if( api_result )
return con->register_api( *api_result );
return result_type();
};
}
template<typename ... Args>
std::function<result_type(const params_type&)> generic_api::api_visitor::to_generic(
const std::function<fc::api_ptr(Args...)>& f )const
{
auto api_con = _api_con;
auto gapi = &api;
return [=]( const variants& args ) -> fc::variant {
auto con = api_con.lock();
FC_ASSERT( con, "not connected" );
fc::raw::datastream<const char*> ds( args.data(), args.size() );
auto api_result = gapi->call_generic( f, ds );
if( !api_result )
return result_type();
return api_result->register_api( *con );
};
}
template<typename R, typename ... Args>
std::function<result_type(const params_type&)> generic_api::api_visitor::to_generic( const std::function<R(Args...)>& f )const
{
generic_api* gapi = &api;
return [f,gapi]( const params_type& args ) {
fc::raw::datastream<const char*> ds( args.data(), args.size() );
return fc::raw::pack(gapi->call_generic( f, ds ));
};
}
template<typename ... Args>
std::function<result_type(const params_type&)> generic_api::api_visitor::to_generic( const std::function<void(Args...)>& f )const
{
generic_api* gapi = &api;
return [f,gapi]( const params_type& args ) {
fc::raw::datastream<const char*> ds( args.data(), args.size() );
gapi->call_generic( f, ds );
return result_type();
};
}
/**
* It is slightly unclean tight coupling to have this method in the api class.
* It breaks encapsulation by requiring an api class method to have a pointer
* to an binary_api_connection. The reason this is necessary is we have a goal of being
* able to call register_api() on an api<T> through its base class api_base. But
* register_api() must know the template parameters!
*
* The only reasonable way to achieve the goal is to implement register_api()
* as a method in api<T> (which obviously knows the template parameter T),
* then make the implementation accessible through the base class (by making
* it a pure virtual method in the base class which is overridden by the subclass's
* implementation).
*/
template< typename Interface, typename Transform >
api_id_type api< Interface, Transform >::register_api( binary_api_connection& conn )const
{
return conn.register_api( *this );
}
template< typename T >
api<T> api_base::as()
{
// TODO: this method should probably be const (if it is not too hard)
api<T>* maybe_requested_type = dynamic_cast< api<T>* >(this);
if( maybe_requested_type != nullptr )
return *maybe_requested_type;
detail::any_api* maybe_any = dynamic_cast< detail::any_api* >(this);
FC_ASSERT( maybe_any != nullptr );
std::shared_ptr< binary_api_connection > api_conn = maybe_any->_binary_api_connection.lock();
FC_ASSERT( api_conn );
return api_conn->get_remote_api<T>( maybe_any->_api_id );
}
namespace detail {
template<typename Signature>
template<typename... Args>
typename callback_functor<Signature>::result_type callback_functor<Signature>::operator()( Args... args )const
{
std::shared_ptr< fc::binary_api_connection > locked = _binary_api_connection.lock();
// TODO: make new exception type for this instead of recycling eof_exception
if( !locked )
throw fc::eof_exception();
/// TODO------------->>> pack args...
locked->send_callback( _callback_id, fc::raw::pack( args... ) ).template as< result_type >();
}
template<typename... Args>
class callback_functor<void(Args...)>
{
public:
typedef void result_type;
callback_functor( std::weak_ptr< fc::binary_api_connection > con, uint64_t id )
:_callback_id(id),_binary_api_connection(con){}
void operator()( Args... args )const
{
std::shared_ptr< fc::binary_api_connection > locked = _binary_api_connection.lock();
// TODO: make new exception type for this instead of recycling eof_exception
if( !locked )
throw fc::eof_exception();
locked->send_notice( _callback_id, fc::variants{ args... } );
}
private:
uint64_t _callback_id;
std::weak_ptr< fc::binary_api_connection > _binary_api_connection;
};
} // namespace detail
} // fc

View file

@ -1,58 +0,0 @@
#pragma once
#include <fc/variant.hpp>
#include <functional>
#include <fc/thread/future.hpp>
#include <fc/rpc/state.hpp>
namespace fc { namespace rpc {
typedef std::vector<char> params_type;
typedef std::vector<char> result_type;
struct brequest
{
optional<uint64_t> id;
std::string method;
params_type params;
};
struct bresponse
{
bresponse(){}
bresponse( int64_t i, result_type r ):id(i),result(r){}
bresponse( int64_t i, error_object r ):id(i),error(r){}
int64_t id = 0;
optional<result_type> result;
optional<error_object> error;
};
/** binary RPC state */
class bstate
{
public:
typedef std::function<result_type(const params_type&)> method;
~bstate();
void add_method( const fc::string& name, method m );
void remove_method( const fc::string& name );
result_type local_call( const string& method_name, const params_type& args );
void handle_reply( const bresponse& response );
brequest start_remote_call( const string& method_name, params_type args );
result_type wait_for_response( uint64_t request_id );
void close();
void on_unhandled( const std::function<result_type(const string&,const params_type&)>& unhandled );
private:
uint64_t _next_id = 1;
std::unordered_map<uint64_t, fc::promise<result_type>::ptr> _awaiting;
std::unordered_map<std::string, method> _methods;
std::function<result_type(const string&,const params_type&)> _unhandled;
};
} } // namespace fc::rpc
FC_REFLECT( fc::rpc::brequest, (id)(method)(params) );
FC_REFLECT( fc::rpc::bresponse, (id)(result)(error) )

View file

@ -28,7 +28,7 @@ namespace fc { namespace rpc {
void wait();
void format_result( const string& method, std::function<string(variant,const variants&)> formatter);
virtual void getline( const fc::string& prompt, fc::string& line );
virtual void getline( const std::string& prompt, std::string& line );
void set_prompt( const string& prompt );

View file

@ -1,318 +0,0 @@
#pragma once
#include <fc/io/buffered_iostream.hpp>
#include <fc/variant_object.hpp>
#include <fc/thread/future.hpp>
#include <fc/log/logger.hpp>
#include <functional>
namespace fc { namespace rpc {
namespace detail { class json_connection_impl; }
/**
* @brief Implements JSON-RPC 2.0 over a set of io streams
*
* Each JSON RPC message is expected to be on its own line, violators
* will be prosecuted to the fullest extent of the law.
*/
class json_connection
{
public:
typedef std::function<variant(const variants&)> method;
typedef std::function<variant(const variant_object&)> named_param_method;
json_connection( fc::buffered_istream_ptr in, fc::buffered_ostream_ptr out, uint32_t max_depth );
~json_connection();
/**
* Starts processing messages from input
*/
future<void> exec();
bool is_open();
void close();
void set_on_disconnected_callback(std::function<void(fc::exception_ptr)> callback);
logger get_logger()const;
void set_logger( const logger& l );
/**
* @name server interface
*
* Adding methods to the interface allows the remote side
* to call them.
*/
///@{
void add_method( const fc::string& name, method );
void add_named_param_method( const fc::string& name, named_param_method );
void remove_method( const fc::string& name );
//@}
/**
* @name client interface
*/
///@{
void notice( const fc::string& method );
void notice( const fc::string& method, const variants& args );
void notice( const fc::string& method, const variant_object& named_args );
/// args will be handled as named params
future<variant> async_call( const fc::string& method,
const variant_object& args );
future<variant> async_call( const fc::string& method, mutable_variant_object args );
/// Sending in an array of variants will be handled as positional arguments
future<variant> async_call( const fc::string& method,
const variants& args );
future<variant> async_call( const fc::string& method );
future<variant> async_call( const fc::string& method,
const variant& a1 );
future<variant> async_call( const fc::string& method,
const variant& a1,
const variant& a2 );
future<variant> async_call( const fc::string& method,
const variant& a1,
const variant& a2,
const variant& a3 );
future<variant> async_call( const fc::string& method,
const variant& a1,
const variant& a2,
const variant& a3,
const variant& a4 );
future<variant> async_call( const fc::string& method,
const variant& a1,
const variant& a2,
const variant& a3,
const variant& a4,
const variant& a5 );
future<variant> async_call( const fc::string& method,
const variant& a1,
const variant& a2,
const variant& a3,
const variant& a4,
const variant& a5,
const variant& a6 );
future<variant> async_call( const fc::string& method,
const variant& a1,
const variant& a2,
const variant& a3,
const variant& a4,
const variant& a5,
const variant& a6,
const variant& a7
);
future<variant> async_call( const fc::string& method,
const variant& a1,
const variant& a2,
const variant& a3,
const variant& a4,
const variant& a5,
const variant& a6,
const variant& a7,
const variant& a8
);
future<variant> async_call( const fc::string& method,
const variant& a1,
const variant& a2,
const variant& a3,
const variant& a4,
const variant& a5,
const variant& a6,
const variant& a7,
const variant& a8,
const variant& a9
);
future<variant> async_call( const fc::string& method,
const variant& a1,
const variant& a2,
const variant& a3,
const variant& a4,
const variant& a5,
const variant& a6,
const variant& a7,
const variant& a8,
const variant& a9,
const variant& a10
);
template<typename Result>
Result call( const fc::string& method,
const variants& args,
microseconds timeout = microseconds::maximum())
{
return async_call( method, args ).wait(timeout).as<Result>();
}
template<typename Result>
Result call( const fc::string& method,
const variant& a1,
const variant& a2,
const variant& a3,
microseconds timeout = microseconds::maximum())
{
return async_call( method, a1, a2, a3 ).wait(timeout).as<Result>();
}
template<typename Result>
Result call( const fc::string& method,
const variant& a1,
const variant& a2,
const variant& a3,
const variant& a4,
microseconds timeout = microseconds::maximum())
{
return async_call( method, a1, a2, a3, a4).wait(timeout).as<Result>();
}
template<typename Result>
Result call( const fc::string& method,
const variant& a1,
const variant& a2,
const variant& a3,
const variant& a4,
const variant& a5,
microseconds timeout = microseconds::maximum())
{
return async_call( method, a1, a2, a3, a4, a5).wait(timeout).as<Result>();
}
template<typename Result>
Result call( const fc::string& method,
const variant& a1,
const variant& a2,
const variant& a3,
const variant& a4,
const variant& a5,
const variant& a6,
microseconds timeout = microseconds::maximum())
{
return async_call( method, a1, a2, a3, a4, a5, a6).wait(timeout).as<Result>();
}
template<typename Result>
Result call( const fc::string& method,
const variant& a1,
const variant& a2,
const variant& a3,
const variant& a4,
const variant& a5,
const variant& a6,
const variant& a7,
microseconds timeout = microseconds::maximum())
{
return async_call( method, a1, a2, a3, a4, a5, a6, a7).wait(timeout).as<Result>();
}
template<typename Result>
Result call( const fc::string& method,
const variant& a1,
const variant& a2,
const variant& a3,
const variant& a4,
const variant& a5,
const variant& a6,
const variant& a7,
const variant& a8,
microseconds timeout = microseconds::maximum())
{
return async_call( method, a1, a2, a3, a4, a5, a6, a7, a8).wait(timeout).as<Result>();
}
template<typename Result>
Result call( const fc::string& method,
const variant& a1,
const variant& a2,
const variant& a3,
const variant& a4,
const variant& a5,
const variant& a6,
const variant& a7,
const variant& a8,
const variant& a9,
microseconds timeout = microseconds::maximum())
{
return async_call( method, a1, a2, a3, a4, a5, a6, a7, a8, a9).wait(timeout).as<Result>();
}
template<typename Result>
Result call( const fc::string& method,
const variant& a1,
const variant& a2,
const variant& a3,
const variant& a4,
const variant& a5,
const variant& a6,
const variant& a7,
const variant& a8,
const variant& a9,
const variant& a10,
microseconds timeout = microseconds::maximum())
{
return async_call( method, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10).wait(timeout).as<Result>();
}
template<typename Result>
Result call( const fc::string& method,
const variant& a1,
const variant& a2,
microseconds timeout = microseconds::maximum())
{
return async_call( method, a1, a2 ).wait(timeout).as<Result>();
}
template<typename Result>
Result call( const fc::string& method,
const variant& a1,
microseconds timeout = microseconds::maximum())
{
return async_call( method, a1 ).wait(timeout).as<Result>();
}
template<typename Result>
Result call( const fc::string& method,
variant_object a1,
microseconds timeout = microseconds::maximum())
{
return async_call( method, fc::move(a1) ).wait(timeout).as<Result>();
}
template<typename Result>
Result call( const fc::string& method,
mutable_variant_object a1,
microseconds timeout = microseconds::maximum())
{
return async_call( method, variant_object( fc::move(a1) ) ).wait(timeout).as<Result>();
}
template<typename Result>
Result call( const fc::string& method, microseconds timeout = microseconds::maximum() )
{
return async_call( method ).wait(timeout).as<Result>();
}
/// Sending in a variant_object will be issued as named parameters
variant call( const fc::string& method, const variant_object& named_args );
///@}
protected:
const uint32_t _max_conversion_depth; // for nested structures, json, variant etc.
private:
std::unique_ptr<detail::json_connection_impl> my;
};
typedef std::shared_ptr<json_connection> json_connection_ptr;
}} // fc::rpc

View file

@ -26,7 +26,7 @@ namespace fc { namespace rpc {
response( int64_t i, fc::variant r, string j ):id(i),jsonrpc(j),result(r){}
response( int64_t i, error_object r, string j ):id(i),jsonrpc(j),error(r){}
int64_t id = 0;
optional<fc::string> jsonrpc;
optional<std::string> jsonrpc;
optional<fc::variant> result;
optional<error_object> error;
};
@ -37,8 +37,8 @@ namespace fc { namespace rpc {
typedef std::function<variant(const variants&)> method;
~state();
void add_method( const fc::string& name, method m );
void remove_method( const fc::string& name );
void add_method( const std::string& name, method m );
void remove_method( const std::string& name );
variant local_call( const string& method_name, const variants& args );
void handle_reply( const response& response );

View file

@ -1,140 +0,0 @@
#pragma once
#include <fc/io/buffered_iostream.hpp>
#include <fc/variant_object.hpp>
#include <fc/thread/future.hpp>
#include <fc/log/logger.hpp>
#include <functional>
namespace fc { namespace rpc {
namespace detail { class variant_connection_impl; }
/**
* @brief Implements JSON-RPC 2.0 over a set of io streams
*
* Each JSON RPC message is expected to be on its own line, violators
* will be prosecuted to the fullest extent of the law.
*/
class variant_connection
{
public:
typedef std::function<variant(const variants&)> method;
typedef std::function<variant(const variant_object&)> named_param_method;
variant_connection( fc::variant_stream::ptr in, fc::variant_stream::ptr out );
~variant_connection();
/**
* Starts processing messages from input
*/
future<void> exec();
logger get_logger()const;
void set_logger( const logger& l );
/**
* @name server interface
*
* Adding methods to the interface allows the remote side
* to call them.
*/
///@{
void add_method( const fc::string& name, method );
void add_named_param_method( const fc::string& name, named_param_method );
void remove_method( const fc::string& name );
//@}
/**
* @name client interface
*/
///@{
void notice( const fc::string& method );
void notice( const fc::string& method, const variants& args );
void notice( const fc::string& method, const variant_object& named_args );
/// args will be handled as named params
future<variant> async_call( const fc::string& method,
const variant_object& args );
future<variant> async_call( const fc::string& method, mutable_variant_object args );
/// Sending in an array of variants will be handled as positional arguments
future<variant> async_call( const fc::string& method,
const variants& args );
future<variant> async_call( const fc::string& method );
future<variant> async_call( const fc::string& method,
const variant& a1 );
future<variant> async_call( const fc::string& method,
const variant& a1,
const variant& a2 );
future<variant> async_call( const fc::string& method,
const variant& a1,
const variant& a2,
const variant& a3 );
template<typename Result>
Result call( const fc::string& method,
const variant& a1,
const variant& a2,
const variant& a3,
microseconds timeout = microseconds::maximum())
{
return async_call( method, a1, a2, a3 ).wait(timeout).as<Result>();
}
template<typename Result>
Result call( const fc::string& method,
const variant& a1,
const variant& a2,
microseconds timeout = microseconds::maximum())
{
return async_call( method, a1, a2 ).wait(timeout).as<Result>();
}
template<typename Result>
Result call( const fc::string& method,
const variant& a1,
microseconds timeout = microseconds::maximum())
{
return async_call( method, a1 ).wait(timeout).as<Result>();
}
template<typename Result>
Result call( const fc::string& method,
variant_object a1,
microseconds timeout = microseconds::maximum())
{
return async_call( method, fc::move(a1) ).wait(timeout).as<Result>();
}
template<typename Result>
Result call( const fc::string& method,
mutable_variant_object a1,
microseconds timeout = microseconds::maximum())
{
return async_call( method, variant_object( fc::move(a1) ) ).wait(timeout).as<Result>();
}
template<typename Result>
Result call( const fc::string& method, microseconds timeout = microseconds::maximum() )
{
return async_call( method ).wait(timeout).as<Result>();
}
/// Sending in a variant_object will be issued as named parameters
variant call( const fc::string& method, const variant_object& named_args );
///@}
private:
std::unique_ptr<detail::variant_connection_impl> my;
};
typedef std::shared_ptr<variant_connection> variant_connection_ptr;
}} // fc::rpc

View file

@ -1,36 +0,0 @@
#pragma once
namespace fc
{
/**
* Thread-safe, circular buffer for passing variants
* between threads.
*/
class variant_stream
{
public:
variant_stream( size_t s );
~variant_stream();
/** producer api */
int64_t free(); // number of spaces available
int64_t claim( int64_t num );
int64_t publish( int64_t pos );
int64_t wait_free(); // wait for free space
// producer/consumer api
variant& get( int64_t pos );
/** consumer api */
int64_t begin(); // returns the first index ready to be read
int64_t end(); // returns the first index that cannot be read
int64_t wait(); // wait for variants to be posted
private:
std::vector<variant> _variants;
uint64_t _read_pos;
uint64_t _write_pos;
};
}

View file

@ -1,32 +0,0 @@
#pragma once
namespace fc {
template<typename Callback>
class scoped_exit {
public:
template<typename C>
scoped_exit( C&& c ):callback( std::forward<C>(c) ){}
scoped_exit( scoped_exit&& mv ):callback( std::move( mv.callback ) ){}
~scoped_exit() {
try { callback(); } catch( ... ) {}
}
scoped_exit& operator = ( scoped_exit&& mv ) {
callback = std::move(mv);
return *this;
}
private:
scoped_exit( const scoped_exit& );
scoped_exit& operator=( const scoped_exit& );
Callback callback;
};
template<typename Callback>
scoped_exit<Callback> make_scoped_exit( Callback&& c ) {
return scoped_exit<Callback>( std::forward<Callback>(c) );
}
}

View file

@ -1,5 +1,7 @@
#pragma once
#include <fc/utility.hpp>
#include <cstdint>
#include <utility>
namespace fc {
@ -62,7 +64,7 @@ namespace fc {
return *this;
}
shared_ptr& operator=(shared_ptr&& p ) {
fc_swap(_ptr,p._ptr);
std::swap(_ptr,p._ptr);
return *this;
}
T& operator* ()const { return *_ptr; }

View file

@ -1,130 +0,0 @@
#pragma once
#include <functional>
#include <memory>
#include <fc/vector.hpp>
#include <fc/log/logger.hpp>
#include <fc/thread/mutex.hpp>
#include <fc/thread/unique_lock.hpp>
#ifdef emit
#undef emit
#endif
namespace fc {
template<typename Signature>
class signal {
private:
typedef std::function<Signature> func_type;
typedef std::vector<std::shared_ptr<func_type>> list_type;
public:
typedef void* connection_id_type;
template<typename Functor>
connection_id_type connect( Functor&& f ) {
fc::unique_lock<fc::mutex> lock(_mutex);
//auto c = new std::function<Signature>( fc::forward<Functor>(f) );
_handlers.push_back( std::make_shared<func_type>(f) );
return reinterpret_cast<connection_id_type>(_handlers.back().get());
}
#ifdef WIN32
template<typename Arg>
void emit( Arg&& arg ) {
list_type handlers = getHandlers();
for( size_t i = 0; i < handlers.size(); ++i ) {
(*handlers[i])( fc::forward<Arg>(arg) );
}
}
void operator()() {
list_type handlers = getHandlers();
for( size_t i = 0; i < handlers.size(); ++i ) {
(*handlers[i])();
}
}
template<typename Arg>
void operator()( Arg&& arg ) {
list_type handlers = getHandlers();
for( size_t i = 0; i < handlers.size(); ++i ) {
(*handlers[i])( fc::forward<Arg>(arg) );
}
}
template<typename Arg,typename Arg2>
void emit( Arg&& arg, Arg2&& arg2 ) {
list_type handlers = getHandlers();
for( size_t i = 0; i < handlers.size(); ++i ) {
(*handlers[i])( fc::forward<Arg>(arg), fc::forward<Arg2>(arg2) );
}
}
template<typename Arg, typename Arg2>
void operator()( Arg&& arg, Arg2&& arg2 ) {
list_type handlers = getHandlers();
for( size_t i = 0; i < handlers.size(); ++i ) {
(*handlers[i])( fc::forward<Arg>(arg), fc::forward<Arg2>(arg2) );
}
}
template<typename Arg, typename Arg2, typename Arg3>
void emit( Arg&& arg, Arg2&& arg2, Arg3&& arg3 ) {
list_type handlers = getHandlers();
for( size_t i = 0; i < handlers.size(); ++i ) {
(*handlers[i])( fc::forward<Arg>(arg), fc::forward<Arg2>(arg2), fc::forward<Arg3>(arg3) );
}
}
template<typename Arg, typename Arg2, typename Arg3>
void operator()( Arg&& arg, Arg2&& arg2, Arg3&& arg3 ) {
list_type handlers = getHandlers();
for( size_t i = 0; i < handlers.size(); ++i ) {
(*handlers[i])( fc::forward<Arg>(arg), fc::forward<Arg2>(arg2), fc::forward<Arg3>(arg3) );
}
}
#else
template<typename... Args>
void emit( Args&&... args ) {
list_type handlers = getHandlers();
for( size_t i = 0; i < handlers.size(); ++i ) {
(*handlers[i])( fc::forward<Args>(args)... );
}
}
template<typename... Args>
void operator()( Args&&... args ) {
list_type handlers = getHandlers();
for( size_t i = 0; i < handlers.size(); ++i ) {
(*handlers[i])( fc::forward<Args>(args)... );
}
}
#endif
void disconnect( connection_id_type cid ) {
fc::unique_lock<fc::mutex> lock(_mutex);
auto itr = _handlers.begin();
while( itr != _handlers.end() ) {
if( reinterpret_cast<connection_id_type>(itr->get()) == cid ) {
_handlers.erase(itr);
}
++itr;
}
}
signal()
{
_handlers.reserve(4);
}
//~signal()
//{
// for( auto itr = _handlers.begin(); itr != _handlers.end(); ++itr )
// {
// delete *itr;
// }
// _handlers.clear();
//}
private:
fc::mutex _mutex;
list_type _handlers;
list_type getHandlers()
{
fc::unique_lock<fc::mutex> lock(_mutex);
list_type handlers(_handlers);
return handlers;
}
};
}

View file

@ -1,154 +1,32 @@
#pragma once
#include <fc/utility.hpp>
#include <fc/fwd.hpp>
#include <fc/optional.hpp>
#ifndef USE_FC_STRING
#include <string>
namespace fc
{
typedef std::string string;
using std::string;
int64_t to_int64( const fc::string& );
uint64_t to_uint64( const fc::string& );
double to_double( const fc::string& );
fc::string to_string( double );
fc::string to_string( uint64_t );
fc::string to_string( int64_t );
fc::string to_string( uint16_t );
int64_t to_int64( const std::string& );
uint64_t to_uint64( const std::string& );
double to_double( const std::string& );
std::string to_string( double );
std::string to_string( uint64_t );
std::string to_string( int64_t );
std::string to_string( uint16_t );
std::string to_pretty_string( int64_t );
inline fc::string to_string( int32_t v ) { return to_string( int64_t(v) ); }
inline fc::string to_string( uint32_t v ){ return to_string( uint64_t(v) ); }
inline std::string to_string( int32_t v ) { return to_string( int64_t(v) ); }
inline std::string to_string( uint32_t v ){ return to_string( uint64_t(v) ); }
#ifdef __APPLE__
inline fc::string to_string( size_t s) { return to_string(uint64_t(s)); }
inline std::string to_string( size_t s) { return to_string(uint64_t(s)); }
#endif
typedef fc::optional<fc::string> ostring;
typedef fc::optional<std::string> ostring;
class variant_object;
fc::string format_string( const fc::string&, const variant_object&, uint32_t max_object_depth = 200 );
fc::string trim( const fc::string& );
fc::string to_lower( const fc::string& );
std::string format_string( const std::string&, const variant_object&, uint32_t max_object_depth = 200 );
std::string trim( const std::string& );
std::string to_lower( const std::string& );
string trim_and_normalize_spaces( const string& s );
uint64_t parse_size( const string& s );
}
#else
/**
* There is debate about whether doing this is 'standard conforming', but
* it works everywhere and enables the purpose of this library which is to
* accelerate compiles while maintaining compatability.
*/
namespace std {
template<class Char>
struct char_traits;
template<class T>
class allocator;
template<class Char, class Traits, class Allocator>
class basic_string;
typedef basic_string<char, char_traits<char>, allocator<char> > string;
}
namespace fc {
/**
* @brief wrapper on std::string
*
* Including <string> results in 4000 lines of code
* that must be included to build your header. This
* class hides all of those details while maintaining
* compatability with std::string. Using fc::string
* instead of std::string can accelerate compile times
* 10x.
*
* The implementation of this class is std::string, this header simply
* accelerates compile times. fc::string is automatically convertable to / from
* std::string.
*/
class string {
public:
typedef char* iterator;
typedef const char* const_iterator;
enum { npos = size_t(-1) };
// static const size_t npos;// = -1;
string();
string( const std::string& s );
string( std::string&& s );
string( const string& c );
string( string&& c );
string( const char* c );
string( const char* c, int s );
string( const_iterator b, const_iterator e );
~string();
operator std::string&();
operator const std::string&()const;
iterator begin();
iterator end();
const_iterator begin()const;
const_iterator end()const;
char& operator[](size_t idx);
const char& operator[](size_t idx)const;
string& operator =( const string& c );
string& operator =( string&& c );
void reserve( size_t );
size_t size()const;
size_t find( char c, size_t pos = 0 )const;
size_t find(const fc::string& str, size_t pos = 0) const;
size_t find(const char* s, size_t pos = 0) const;
size_t rfind( char c, size_t pos = npos )const;
size_t rfind( const char* c, size_t pos = npos )const;
size_t rfind( const fc::string& c, size_t pos = npos )const;
size_t find_first_of (const fc::string& str, size_t pos = 0) const;
size_t find_first_of (const char* s, size_t pos = 0) const;
string& replace(size_t pos, size_t len, const fc::string& str);
string& replace(size_t pos, size_t len, const char* s);
void resize( size_t s );
void clear();
const char* c_str()const;
char* data();
bool operator == ( const char* s )const;
bool operator == ( const string& s )const;
bool operator != ( const string& s )const;
friend bool operator < ( const string& a, const string& b );
string& operator+=( const string& s );
string& operator+=( char c );
friend string operator + ( const string&, const string& );
friend string operator + ( const string&, char c );
fc::string substr( size_t start, size_t len = fc::string::npos )const;
private:
fc::fwd<std::string,32> my;
};
int64_t to_int64( const fc::string& );
uint64_t to_uint64( const fc::string& );
double to_double( const fc::string& );
fc::string to_string( double );
fc::string to_string( uint64_t );
fc::string to_string( int64_t );
typedef fc::optional<fc::string> ostring;
class variant_object;
fc::string format_string( const fc::string&, const variant_object& );
} // namespace fc
#endif

View file

@ -1,5 +1,4 @@
#pragma once
#include <fc/utility.hpp>
#include <fc/time.hpp>
#include <fc/shared_ptr.hpp>
#include <fc/exception/exception.hpp>
@ -35,7 +34,7 @@ namespace fc {
template<typename Functor, typename T>
class completion_handler_impl : public completion_handler {
public:
completion_handler_impl( Functor&& f ):_func(fc::move(f)){}
completion_handler_impl( Functor&& f ):_func(std::move(f)){}
completion_handler_impl( const Functor& f ):_func(f){}
virtual void on_complete( const void* v, const fc::exception_ptr& e ) {
@ -47,7 +46,7 @@ namespace fc {
template<typename Functor>
class completion_handler_impl<Functor,void> : public completion_handler {
public:
completion_handler_impl( Functor&& f ):_func(fc::move(f)){}
completion_handler_impl( Functor&& f ):_func(std::move(f)){}
completion_handler_impl( const Functor& f ):_func(f){}
virtual void on_complete( const void* v, const fc::exception_ptr& e ) {
_func(e);
@ -110,7 +109,7 @@ namespace fc {
typedef fc::shared_ptr< promise<T> > ptr;
promise( const char* desc FC_TASK_NAME_DEFAULT_ARG):promise_base(desc){}
promise( const T& val ){ set_value(val); }
promise( T&& val ){ set_value(fc::move(val) ); }
promise( T&& val ){ set_value(std::move(val) ); }
const T& wait(const microseconds& timeout = microseconds::maximum() ){
this->_wait( timeout );
@ -127,7 +126,7 @@ namespace fc {
}
void set_value( T&& v ) {
result = fc::move(v);
result = std::move(v);
_set_value(&*result);
}
@ -186,12 +185,12 @@ namespace fc {
class future {
public:
future( const fc::shared_ptr<promise<T>>& p ):m_prom(p){}
future( fc::shared_ptr<promise<T>>&& p ):m_prom(fc::move(p)){}
future( fc::shared_ptr<promise<T>>&& p ):m_prom(std::move(p)){}
future(const future<T>& f ) : m_prom(f.m_prom){}
future(){}
future& operator=(future<T>&& f ) {
fc_swap(m_prom,f.m_prom);
std::swap(m_prom,f.m_prom);
return *this;
}
@ -259,12 +258,12 @@ namespace fc {
class future<void> {
public:
future( const fc::shared_ptr<promise<void>>& p ):m_prom(p){}
future( fc::shared_ptr<promise<void>>&& p ):m_prom(fc::move(p)){}
future( fc::shared_ptr<promise<void>>&& p ):m_prom(std::move(p)){}
future(const future<void>& f ) : m_prom(f.m_prom){}
future(){}
future& operator=(future<void>&& f ) {
fc_swap(m_prom,f.m_prom);
std::swap(m_prom,f.m_prom);
return *this;
}

View file

@ -1,7 +1,6 @@
#pragma once
#include <fc/thread/future.hpp>
#include <fc/thread/priority.hpp>
#include <fc/aligned.hpp>
#include <fc/fwd.hpp>
namespace fc {
@ -103,7 +102,7 @@ namespace fc {
}
virtual void cancel(const char* reason FC_CANCELATION_REASON_DEFAULT_ARG) override { task_base::cancel(reason); }
aligned<FunctorSize> _functor;
alignas(double) char _functor[FunctorSize];
private:
~task(){}
};
@ -123,7 +122,7 @@ namespace fc {
}
virtual void cancel(const char* reason FC_CANCELATION_REASON_DEFAULT_ARG) override { task_base::cancel(reason); }
aligned<FunctorSize> _functor;
alignas(double) char _functor[FunctorSize];
private:
~task(){}
};

View file

@ -3,8 +3,6 @@
#define FC_CONTEXT_STACK_SIZE (2048*1024)
#include <fc/thread/task.hpp>
#include <fc/vector.hpp>
#include <fc/string.hpp>
namespace fc {
class time_point;
@ -75,7 +73,7 @@ namespace fc {
* @note debug info is more useful if you provide a description for your
* async tasks and promises.
*/
void debug( const fc::string& d );
void debug( const std::string& d );
/**
@ -146,7 +144,7 @@ namespace fc {
std::vector<fc::promise_base::ptr> proms(2);
proms[0] = fc::static_pointer_cast<fc::promise_base>(f1.m_prom);
proms[1] = fc::static_pointer_cast<fc::promise_base>(f2.m_prom);
return wait_any_until(fc::move(proms), fc::time_point::now()+timeout_us );
return wait_any_until(std::move(proms), fc::time_point::now()+timeout_us );
}
private:
thread( class thread_d* ); // parameter is ignored, will create a new thread_d

View file

@ -1,76 +0,0 @@
#pragma once
#include <fc/thread/future.hpp>
#include <fc/thread/spin_yield_lock.hpp>
#include <fc/thread/unique_lock.hpp>
#include <deque>
namespace fc
{
/**
* A thread-safe, fiber-aware condition variable that
* can be used to signal/wait on a certain condition between
* threads.
*/
template<typename T=void_t>
class wait_condition
{
public:
wait_condition(const char* name) : _name(name) {}
void wait( const microseconds& timeout = microseconds::maximum() )
{
typename fc::promise<T>::ptr p = new fc::promise<T>(_name);
{ synchronized( _prom_lock )
_promises.push_back( p );
}
p->wait(timeout);
}
template<typename LockType>
T wait( LockType& l, const microseconds& timeout = microseconds::maximum() )
{
typename fc::promise<T>::ptr p( new fc::promise<T>(_name));
{ synchronized( _prom_lock )
_promises.push_back( p );
}
l.unlock();
struct relocker {
LockType& _lock;
relocker(LockType& l) : _lock(l) {}
~relocker() { _lock.lock(); }
} lock_on_exit(l);
return p->wait(timeout);
}
void notify_one( const T& t=T())
{
typename fc::promise<void_t>::ptr prom;
{ synchronized( _prom_lock )
if( _promises.size() )
{
prom = _promises.front();
_promises.pop_front();
}
}
if( prom && prom->retain_count() > 1 )
prom->set_value(t);
}
void notify_all(const T& t=T())
{
std::deque<typename fc::promise<T>::ptr> all;
{ synchronized( _prom_lock )
std::swap(all, _promises);
}
for( auto itr = all.begin(); itr != all.end(); ++itr )
{
if( (*itr)->retain_count() > 1 )
(*itr)->set_value(t);
}
}
private:
fc::spin_yield_lock _prom_lock;
std::deque<typename fc::promise<T>::ptr> _promises;
const char *const _name;
};
}

View file

@ -1,6 +1,6 @@
#pragma once
#include <stdint.h>
#include <fc/string.hpp>
#include <string>
#include <fc/optional.hpp>
#ifdef _MSC_VER
@ -48,8 +48,8 @@ namespace fc {
static time_point maximum() { return time_point( microseconds::maximum() ); }
static time_point min() { return time_point(); }
operator fc::string()const;
static time_point from_iso_string( const fc::string& s );
operator std::string()const;
static time_point from_iso_string( const std::string& s );
const microseconds& time_since_epoch()const { return elapsed; }
uint32_t sec_since_epoch()const { return elapsed.count() / 1000000; }
@ -112,11 +112,11 @@ namespace fc {
friend microseconds operator - ( const time_point_sec& t, const time_point_sec& m ) { return time_point(t) - time_point(m); }
friend microseconds operator - ( const time_point& t, const time_point_sec& m ) { return time_point(t) - time_point(m); }
fc::string to_non_delimited_iso_string()const;
fc::string to_iso_string()const;
std::string to_non_delimited_iso_string()const;
std::string to_iso_string()const;
operator fc::string()const;
static time_point_sec from_iso_string( const fc::string& s );
operator std::string()const;
static time_point_sec from_iso_string( const std::string& s );
private:
uint32_t utc_seconds;
@ -127,12 +127,12 @@ namespace fc {
/** return a human-readable approximate time, relative to now()
* e.g., "4 hours ago", "2 months ago", etc.
*/
string get_approximate_relative_time_string(const time_point_sec& event_time,
const time_point_sec& relative_to_time = fc::time_point::now(),
const std::string& ago = " ago");
string get_approximate_relative_time_string(const time_point& event_time,
const time_point& relative_to_time = fc::time_point::now(),
const std::string& ago = " ago");
std::string get_approximate_relative_time_string(const time_point_sec& event_time,
const time_point_sec& relative_to_time = fc::time_point::now(),
const std::string& ago = " ago");
std::string get_approximate_relative_time_string(const time_point& event_time,
const time_point& relative_to_time = fc::time_point::now(),
const std::string& ago = " ago");
}
#include <fc/reflect/reflect.hpp>

View file

@ -1,136 +0,0 @@
#pragma once
#include <fc/utility.hpp>
#include <boost/preprocessor/repeat.hpp>
#include <boost/preprocessor/repeat_from_to.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/facilities/empty.hpp>
#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
namespace fc {
/**
* Provides a fast-compiling tuple that doesn't use fancy meta-programming
* techniques. It is limited to 4 parameters which is sufficient for most
* methods argument lists which is the primary use case for this tuple. Methods
* that require more than 4 parameters are probably better served by defining
* a struct.
*
* The members of the tuple are easily visited with a simple visitor functor
* of the form:
* @code
* struct visitor {
* template<typename MemberType>
* void operator()( MemberType& m );
*
* template<typename MemberType>
* void operator()( const MemberType& m );
* };
* @endcode
template<typename A=void, typename B=void,typename C=void, typename D=void>
struct tuple {
tuple(){}
enum size_enum { size = 4 };
template<typename AA, typename BB, typename CC, typename DD>
tuple( AA&& aa, BB&& bb, CC&& cc, DD&& dd )
:a( fc::forward<AA>(aa) ),
b( fc::forward<BB>(bb) ),
c( fc::forward<CC>(cc) ),
d( fc::forward<DD>(dd) )
{}
template<typename V>
void visit( V&& v ) { v(a); v(b); v(c); v(d); }
template<typename V>
void visit( V&& v )const { v(a); v(b); v(c); v(d); }
A a;
B b;
C c;
D d;
};
*/
template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(9, typename A, void)> struct tuple{};
template<>
struct tuple<> {
enum size_enum { size = 0 };
template<typename V>
void visit( V&& v)const{};
};
template<typename Functor>
auto call_fused( Functor f, const tuple<>& t ) -> decltype( f( ) ) {
return f();
}
inline tuple<> make_tuple(){ return tuple<>(); }
template<typename T>
struct is_tuple {
typedef fc::false_type type;
};
#define RREF_PARAMS(z,n,data) BOOST_PP_CAT(AA,n)&& BOOST_PP_CAT(p,n)
#define ILIST_PARAMS(z,n,data) BOOST_PP_CAT(a,n)( fc::forward<BOOST_PP_CAT(AA,n)>( BOOST_PP_CAT(p,n) ) )
#define ILIST_PARAMS_COPY(z,n,data) BOOST_PP_CAT(a,n)( t.BOOST_PP_CAT(a,n) )
#define VISIT_PARAMS(z,n,data) v(BOOST_PP_CAT(a,n));
#define LIST_MEMBERS_ON(z,n,data) data.BOOST_PP_CAT(a,n)
#define DEDUCE_MEMBERS(z,n,data) typename fc::deduce<BOOST_PP_CAT(AA,n)>::type
#define FORWARD_PARAMS(z,n,data) fc::forward<BOOST_PP_CAT(AA,n)>(BOOST_PP_CAT(p,n))
#define MEM_PARAMS(z,n,data) BOOST_PP_CAT(A,n) BOOST_PP_CAT(a,n);
#define TUPLE(z,n,unused) \
template<BOOST_PP_ENUM_PARAMS( n, typename A)> \
struct tuple<BOOST_PP_ENUM_PARAMS(n,A)> { \
enum size_enum { size = n }; \
template<BOOST_PP_ENUM_PARAMS( n, typename AA)> \
explicit tuple( BOOST_PP_ENUM(n, RREF_PARAMS, unused ) )BOOST_PP_IF(n,:,BOOST_PP_EMPTY())BOOST_PP_ENUM( n, ILIST_PARAMS,unused){} \
tuple( const tuple& t )BOOST_PP_IF(n,:,BOOST_PP_EMPTY())BOOST_PP_ENUM( n, ILIST_PARAMS_COPY,unused){} \
tuple( tuple&& t )BOOST_PP_IF(n,:,BOOST_PP_EMPTY())BOOST_PP_ENUM( n, ILIST_PARAMS_COPY,unused){} \
tuple(){}\
template<typename V>\
void visit( V&& v ) { BOOST_PP_REPEAT(n,VISIT_PARAMS,a) }\
template<typename V>\
void visit( V&& v )const { BOOST_PP_REPEAT(n,VISIT_PARAMS,a) }\
BOOST_PP_REPEAT(n,MEM_PARAMS,a) \
}; \
template<BOOST_PP_ENUM_PARAMS( n, typename AA)> \
tuple<BOOST_PP_ENUM_PARAMS(n,AA)> make_tuple( BOOST_PP_ENUM( n, RREF_PARAMS, unused) ) { \
return tuple<BOOST_PP_ENUM_PARAMS(n,AA)>( BOOST_PP_ENUM( n, FORWARD_PARAMS,unused ) ); \
} \
template<typename Functor, BOOST_PP_ENUM_PARAMS(n,typename AA)> \
auto call_fused( Functor f, tuple<BOOST_PP_ENUM_PARAMS(n,AA)>& t ) \
-> decltype( f( BOOST_PP_ENUM( n, LIST_MEMBERS_ON, t) ) ) { \
return f( BOOST_PP_ENUM( n, LIST_MEMBERS_ON, t) ); \
} \
template<typename Functor, BOOST_PP_ENUM_PARAMS(n,typename AA)> \
auto call_fused( Functor f, const tuple<BOOST_PP_ENUM_PARAMS(n,AA)>& t ) \
-> decltype( f( BOOST_PP_ENUM( n, LIST_MEMBERS_ON, t) ) ) { \
return f( BOOST_PP_ENUM( n, LIST_MEMBERS_ON, t) ); \
} \
template<BOOST_PP_ENUM_PARAMS( n, typename AA)> \
struct is_tuple<fc::tuple<BOOST_PP_ENUM_PARAMS(n,AA)> > { \
typedef fc::true_type type; \
}; \
template<BOOST_PP_ENUM_PARAMS( n, typename AA)> \
struct deduce<fc::tuple<BOOST_PP_ENUM_PARAMS(n,AA)> > { \
typedef fc::tuple<BOOST_PP_ENUM( n, DEDUCE_MEMBERS,unused)> type; \
};
BOOST_PP_REPEAT_FROM_TO( 1, 5, TUPLE, unused )
#undef FORWARD_PARAMS
#undef DEDUCE_MEMBERS
#undef RREF_PARAMS
#undef LIST_MEMBERS_ON
#undef ILIST_PARAMS
#undef ILIST_PARAMS_COPY
#undef VISIT_PARAMS
#undef MEM_PARAMS
#undef TUPLE
}

View file

@ -1,60 +0,0 @@
#pragma once
#include <fc/utility.hpp>
#include <memory>
namespace fc
{
template<typename T>
class unique_ptr
{
public:
typedef T* pointer;
explicit unique_ptr( pointer t = nullptr ):_p(t){}
unique_ptr( unique_ptr&& m )
:_p(m._p){ m._p = nullptr; }
~unique_ptr() { delete _p; }
operator bool()const { return _p != nullptr; }
friend bool operator==(const unique_ptr& p, nullptr_t)
{
return p._p == nullptr;
}
friend bool operator!=(const unique_ptr& p, nullptr_t)
{
return p._p != nullptr;
}
unique_ptr& operator=( nullptr_t )
{
delete _p; _p = nullptr;
}
unique_ptr& operator=( unique_ptr&& o )
{
fc_swap( _p, o._p );
return *this;
}
pointer operator->()const { return _p; }
T& operator*()const { return *_p; }
void reset( pointer v )
{
delete _p; _p = v;
}
pointer release()
{
auto tmp = _p;
_p = nullptr;
return tmp;
}
private:
pointer _p;
};
}

View file

@ -19,19 +19,12 @@ namespace fc {
using std::size_t;
typedef decltype(nullptr) nullptr_t;
template<typename T> struct remove_reference { typedef T type; };
template<typename T> struct remove_reference<T&> { typedef T type; };
template<typename T> struct remove_reference<T&&> { typedef T type; };
template<typename T> struct deduce { typedef T type; };
template<typename T> struct deduce<T&> { typedef T type; };
template<typename T> struct deduce<const T&> { typedef T type; };
template<typename T> struct deduce<T&&> { typedef T type; };
template<typename T> struct deduce<const T&&>{ typedef T type; };
template<typename T>
typename fc::remove_reference<T>::type&& move( T&& t ) { return static_cast<typename fc::remove_reference<T>::type&&>(t); }
template<typename T, typename U>
inline T&& forward( U&& u ) { return static_cast<T&&>(u); }
@ -45,21 +38,4 @@ namespace fc {
template<typename T>
struct is_class { typedef decltype(detail::is_class_helper<T>(0)) type; enum value_enum { value = type::value }; };
#ifdef min
#undef min
#endif
template<typename T>
const T& min( const T& a, const T& b ) { return a < b ? a: b; }
}
// outside of namespace fc becuase of VC++ conflict with std::swap
template<typename T>
void fc_swap( T& a, T& b ) {
T tmp = fc::move(a);
a = fc::move(b);
b = fc::move(tmp);
}
#define LLCONST(constant) static_cast<int64_t>(constant##ll)
#define ULLCONST(constant) static_cast<uint64_t>(constant##ull)

View file

@ -11,8 +11,6 @@
#include <string.h> // memset
#include <fc/optional.hpp>
#include <fc/string.hpp>
#include <fc/container/deque_fwd.hpp>
#include <fc/container/flat_fwd.hpp>
#include <boost/multi_index_container_fwd.hpp>
@ -217,7 +215,7 @@ namespace fc
variant( double val, uint32_t max_depth = 1 );
variant( bool val, uint32_t max_depth = 1 );
variant( blob val, uint32_t max_depth = 1 );
variant( fc::string val, uint32_t max_depth = 1 );
variant( std::string val, uint32_t max_depth = 1 );
variant( variant_object, uint32_t max_depth = 1 );
variant( mutable_variant_object, uint32_t max_depth = 1 );
variant( variants, uint32_t max_depth = 1 );
@ -238,7 +236,7 @@ namespace fc
virtual void handle( const uint64_t& v )const = 0;
virtual void handle( const double& v )const = 0;
virtual void handle( const bool& v )const = 0;
virtual void handle( const string& v )const = 0;
virtual void handle( const std::string& v )const = 0;
virtual void handle( const variant_object& v)const = 0;
virtual void handle( const variants& v)const = 0;
};
@ -277,10 +275,10 @@ namespace fc
/** Convert's double, ints, bools, etc to a string
* @throw if get_type() == array_type | get_type() == object_type
*/
string as_string()const;
std::string as_string()const;
/// @pre get_type() == string_type
const string& get_string()const;
const std::string& get_string()const;
/// @throw if get_type() != array_type | null_type
variants& get_array();
@ -357,7 +355,7 @@ namespace fc
typedef optional<variant> ovariant;
/** @ingroup Serializable */
void from_variant( const variant& var, string& vo, uint32_t max_depth = 1 );
void from_variant( const variant& var, std::string& vo, uint32_t max_depth = 1 );
/** @ingroup Serializable */
void from_variant( const variant& var, variants& vo, uint32_t max_depth );
void from_variant( const variant& var, variant& vo, uint32_t max_depth );

View file

@ -1,7 +1,6 @@
#pragma once
#include <fc/variant.hpp>
#include <fc/shared_ptr.hpp>
#include <fc/unique_ptr.hpp>
namespace fc
{

View file

@ -1,2 +0,0 @@
#pragma once
#include <vector>

View file

@ -1,11 +0,0 @@
#ifndef _FC_VECTOR_FWD_HPP_
#define _FC_VECTOR_FWD_HPP_
#if 0
#include <fc/vector.hpp>
#else
namespace fc {
template<typename T> class vector;
};
#endif
#endif // _FC_VECTOR_FWD_HPP_

View file

@ -1,13 +0,0 @@
#pragma once
#include <fc/vector.hpp>
#include <fc/thread/thread.hpp>
namespace fc {
template<typename T1, typename T2>
int wait_any( fc::future<T1>& f1, fc::future<T2>& f2, const microseconds& timeout_us = microseconds::max() ) {
fc::vector<promise_base::ptr> p(2);
p[0] = static_pointer_cast<promise_base*>(f1.promise());
p[1] = static_pointer_cast<promise_base*>(f2.promise());
return wait( fc::move(p), timeout_us );
}
}

View file

@ -4,11 +4,11 @@
namespace fc
{
string zlib_compress(const string& in)
std::string zlib_compress(const std::string& in)
{
size_t compressed_message_length;
char* compressed_message = (char*)tdefl_compress_mem_to_heap(in.c_str(), in.size(), &compressed_message_length, TDEFL_WRITE_ZLIB_HEADER | TDEFL_DEFAULT_MAX_PROBES);
string result(compressed_message, compressed_message_length);
std::string result(compressed_message, compressed_message_length);
free(compressed_message);
return result;
}

View file

@ -1,85 +0,0 @@
#include <memory>
#include <fc/crypto/bigint.hpp>
#include <fc/io/sstream.hpp>
#include <fc/log/logger.hpp>
namespace fc
{
fc::string to_base36( const char* data, size_t len )
{
if( len == 0 ) return fc::string();
const char* src = data;
int src_len = len;
std::unique_ptr<char[]> buffer(new char[len+1]);
if (*data & 0x80) {
buffer[0] = 0;
memcpy( buffer.get() + 1, data, len );
src = buffer.get();
src_len++;
}
fc::bigint value( src, src_len );
auto base36 = "0123456789abcdefghijklmnopqrstuvwxyz";
std::vector<char> out( static_cast<size_t>(len * 1.6) + 2 );
int pos = out.size() - 1;
out[pos] = '\0';
fc::bigint _36(36);
do {
if( value ) {
--pos;
out[pos] = base36[(value % _36).to_int64()];
}
} while (value /= _36);
while (len-- > 0 && *data++ == 0) {
out[--pos] = '0';
}
return &out[pos]; //fc::string( &out[pos], out.size() - pos);
}
fc::string to_base36( const std::vector<char>& vec )
{
return to_base36( (const char*)vec.data(), vec.size() );
}
std::vector<char> from_base36( const fc::string& b36 )
{
if ( b36.empty() ) {
std::vector<char> empty;
return empty;
}
fc::bigint value;
fc::bigint pos = 0;
fc::bigint _36(36);
for( auto itr = b36.rbegin(); itr != b36.rend(); ++itr )
{
if( *itr >= '0' && *itr <= '9' )
value = value + _36.exp(pos) * fc::bigint(*itr - '0');
else if( *itr >= 'a' && *itr <= 'z' )
value = value + (_36.exp(pos) * fc::bigint(10+*itr - 'a'));
else if( *itr >= 'A' && *itr <= 'Z' )
value = value + (_36.exp(pos) * fc::bigint(10+*itr - 'A'));
else
{
wlog("unknown '${char}'", ("char",fc::string(&*itr,1)) );
}
++pos;
}
std::vector<char> bytes = value;
int leading_zeros = 0, len = bytes.size();
const char *in = b36.c_str();
while (*in++ == '0') { leading_zeros++; }
char* first = bytes.data();
while (len > 0 && *first == 0) { first++; len--; }
std::vector<char> result;
result.resize(leading_zeros + len, 0);
if (len)
{
memcpy( result.data() + leading_zeros, first, len );
}
return result;
}
}

View file

@ -22,7 +22,6 @@
#include <string.h>
#include <fc/log/logger.hpp>
#include <fc/string.hpp>
#include <fc/exception/exception.hpp>
#include <stdexcept>

View file

@ -1,5 +1,4 @@
#include <fc/crypto/bigint.hpp>
#include <fc/utility.hpp>
#include <openssl/bn.h>
#include <fc/variant.hpp>
#include <fc/crypto/base64.hpp>
@ -145,7 +144,7 @@ namespace fc {
BN_CTX* ctx = BN_CTX_new();
bigint tmp;
BN_div( tmp.n, NULL, n, a.n, ctx );
fc_swap( tmp.n, n );
std::swap( tmp.n, n );
BN_CTX_free(ctx);
return tmp;
}
@ -190,7 +189,7 @@ namespace fc {
bigint& bigint::operator = ( bigint&& a ) {
if( &a == this )
return *this;
fc_swap( a.n, n );
std::swap( a.n, n );
return *this;
}
bigint& bigint::operator = ( const bigint& a ) {
@ -199,7 +198,7 @@ namespace fc {
BN_copy( n, a.n );
return *this;
}
bigint::operator fc::string()const {
bigint::operator std::string()const {
return BN_bn2dec(n);
}

View file

@ -1,624 +0,0 @@
////////////////////////////////////////////////////////////////////////////
///
// BlowFish.cpp
//
// Implementation of Bruce Schneier's BLOWFISH algorithm from "Applied
// Cryptography", Second Edition.
#include <cstring>
#include <fc/crypto/blowfish.hpp>
#include <fc/exception/exception.hpp>
namespace fc {
//Extract low order byte
inline unsigned char Byte(unsigned int ui)
{
return (unsigned char)(ui & 0xff);
}
//Function F
inline unsigned int blowfish::F(unsigned int ui)
{
return ((m_auiS[0][Byte(ui>>24)] + m_auiS[1][Byte(ui>>16)]) ^ m_auiS[2][Byte(ui>>8)]) + m_auiS[3][Byte(ui)];
}
//Initialization with a fixed string which consists of the hexadecimal digits of PI (less the initial 3)
//P-array, 18 32-bit subkeys
const unsigned int blowfish::scm_auiInitP[18] = {
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
0x9216d5d9, 0x8979fb1b
};
//Four 32-bit S-boxes with 256 entries each
const unsigned int blowfish::scm_auiInitS[4][256] = {
//0
{0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a},
//1
{0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7},
//2
{0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0},
//3
{0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6}
};
//Constructor - Initialize the P and S boxes for a given Key
blowfish::blowfish()
{}
void blowfish::start(unsigned char* ucKey, uint64_t keysize, const sblock& roChain)
{
m_oChain0 = roChain;
m_oChain = roChain;
if(keysize<1)
FC_THROW_EXCEPTION( exception, "invalid key length" );
//Check the Key - the key length should be between 1 and 56 bytes
if(keysize>56)
keysize = 56;
unsigned char aucLocalKey[56];
unsigned int i, j;
memcpy(aucLocalKey, ucKey, static_cast<size_t>(keysize));
//Reflexive Initialization of the Blowfish.
//Generating the Subkeys from the Key flood P and S boxes with PI
memcpy(m_auiP, scm_auiInitP, sizeof m_auiP);
memcpy(m_auiS, scm_auiInitS, sizeof m_auiS);
//Load P boxes with key bytes
const unsigned char* p = aucLocalKey;
unsigned int x=0;
//Repeatedly cycle through the key bits until the entire P array has been XORed with key bits
uint32_t iCount = 0;
for(i=0; i<18; i++)
{
x=0;
for(int n=4; n--; )
{
//int iVal = (int)(*p);
x <<= 8;
x |= *(p++);
iCount++;
if(iCount == keysize)
{
//All bytes used, so recycle bytes
iCount = 0;
p = aucLocalKey;
}
}
m_auiP[i] ^= x;
}
//Reflect P and S boxes through the evolving Blowfish
sblock block(0UL,0UL); //all-zero block
for(i=0; i<18; )
encrypt(block), m_auiP[i++] = block.m_uil, m_auiP[i++] = block.m_uir;
for(j=0; j<4; j++)
for(int k=0; k<256; )
encrypt(block), m_auiS[j][k++] = block.m_uil, m_auiS[j][k++] = block.m_uir;
}
//Sixteen Round Encipher of Block
void blowfish::encrypt(sblock& block)
{
unsigned int uiLeft = block.m_uil;
unsigned int uiRight = block.m_uir;
uiLeft ^= m_auiP[0];
uiRight ^= F(uiLeft)^m_auiP[1]; uiLeft ^= F(uiRight)^m_auiP[2];
uiRight ^= F(uiLeft)^m_auiP[3]; uiLeft ^= F(uiRight)^m_auiP[4];
uiRight ^= F(uiLeft)^m_auiP[5]; uiLeft ^= F(uiRight)^m_auiP[6];
uiRight ^= F(uiLeft)^m_auiP[7]; uiLeft ^= F(uiRight)^m_auiP[8];
uiRight ^= F(uiLeft)^m_auiP[9]; uiLeft ^= F(uiRight)^m_auiP[10];
uiRight ^= F(uiLeft)^m_auiP[11]; uiLeft ^= F(uiRight)^m_auiP[12];
uiRight ^= F(uiLeft)^m_auiP[13]; uiLeft ^= F(uiRight)^m_auiP[14];
uiRight ^= F(uiLeft)^m_auiP[15]; uiLeft ^= F(uiRight)^m_auiP[16];
uiRight ^= m_auiP[17];
block.m_uil = uiRight;
block.m_uir = uiLeft;
}
//Sixteen Round Decipher of sblock
void blowfish::decrypt(sblock& block)
{
unsigned int uiLeft = block.m_uil;
unsigned int uiRight = block.m_uir;
uiLeft ^= m_auiP[17];
uiRight ^= F(uiLeft)^m_auiP[16]; uiLeft ^= F(uiRight)^m_auiP[15];
uiRight ^= F(uiLeft)^m_auiP[14]; uiLeft ^= F(uiRight)^m_auiP[13];
uiRight ^= F(uiLeft)^m_auiP[12]; uiLeft ^= F(uiRight)^m_auiP[11];
uiRight ^= F(uiLeft)^m_auiP[10]; uiLeft ^= F(uiRight)^m_auiP[9];
uiRight ^= F(uiLeft)^m_auiP[8]; uiLeft ^= F(uiRight)^m_auiP[7];
uiRight ^= F(uiLeft)^m_auiP[6]; uiLeft ^= F(uiRight)^m_auiP[5];
uiRight ^= F(uiLeft)^m_auiP[4]; uiLeft ^= F(uiRight)^m_auiP[3];
uiRight ^= F(uiLeft)^m_auiP[2]; uiLeft ^= F(uiRight)^m_auiP[1];
uiRight ^= m_auiP[0];
block.m_uil = uiRight;
block.m_uir = uiLeft;
}
//Semi-Portable Byte Shuffling
inline void BytesToBlock(unsigned char const* p, sblock& b)
{
unsigned int y;
//Left
b.m_uil = 0;
y = *p++;
y <<= 24;
b.m_uil |= y;
y = *p++;
y <<= 16;
b.m_uil |= y;
y = *p++;
y <<= 8;
b.m_uil |= y;
y = *p++;
b.m_uil |= y;
//Right
b.m_uir = 0;
y = *p++;
y <<= 24;
b.m_uir |= y;
y = *p++;
y <<= 16;
b.m_uir |= y;
y = *p++;
y <<= 8;
b.m_uir |= y;
y = *p++;
b.m_uir |= y;
}
inline void BlockToBytes(sblock const& b, unsigned char* p)
{
unsigned int y;
//Right
y = b.m_uir;
*--p = Byte(y);
y = b.m_uir >> 8;
*--p = Byte(y);
y = b.m_uir >> 16;
*--p = Byte(y);
y = b.m_uir >> 24;
*--p = Byte(y);
//Left
y = b.m_uil;
*--p = Byte(y);
y = b.m_uil >> 8;
*--p = Byte(y);
y = b.m_uil >> 16;
*--p = Byte(y);
y = b.m_uil >> 24;
*--p = Byte(y);
}
//encrypt Buffer in Place
//Returns false if n is multiple of 8
void blowfish::encrypt(unsigned char* buf, uint64_t n, int iMode)
{
//Check the buffer's length - should be > 0 and multiple of 8
if((n==0)||(n%8!=0))
FC_THROW_EXCEPTION( exception, "invalid buffer length ${n}, not multiple of 8", ("n", n) );
sblock work;
if(iMode == CBC) //CBC mode, using the Chain
{
sblock chain(m_oChain);
for(; n >= 8; n -= 8)
{
BytesToBlock(buf, work);
work ^= chain;
encrypt(work);
chain = work;
BlockToBytes(work, buf+=8);
}
}
else if(iMode == CFB) //CFB mode, using the Chain
{
sblock chain(m_oChain);
for(; n >= 8; n -= 8)
{
encrypt(chain);
BytesToBlock(buf, work);
work ^= chain;
chain = work;
BlockToBytes(work, buf+=8);
}
}
else //ECB mode, not using the Chain
{
for(; n >= 8; n -= 8)
{
BytesToBlock(buf, work);
encrypt(work);
BlockToBytes(work, buf+=8);
}
}
}
//decrypt Buffer in Place
//Returns false if n is multiple of 8
void blowfish::decrypt(unsigned char* buf, uint64_t n, int iMode)
{
//Check the buffer's length - should be > 0 and multiple of 8
if((n==0)||(n%8!=0))
FC_THROW_EXCEPTION( exception, "invalid buffer length ${n}, not multiple of 8", ("n", n) );
sblock work;
if(iMode == CBC) //CBC mode, using the Chain
{
sblock crypt, chain(m_oChain);
for(; n >= 8; n -= 8)
{
BytesToBlock(buf, work);
crypt = work;
decrypt(work);
work ^= chain;
chain = crypt;
BlockToBytes(work, buf+=8);
}
}
else if(iMode == CFB) //CFB mode, using the Chain, not using decrypt()
{
sblock crypt, chain(m_oChain);
for(; n >= 8; n -= 8)
{
BytesToBlock(buf, work);
encrypt(chain);
crypt = work;
work ^= chain;
chain = crypt;
BlockToBytes(work, buf+=8);
}
}
else //ECB mode, not using the Chain
{
for(; n >= 8; n -= 8)
{
BytesToBlock(buf, work);
decrypt(work);
BlockToBytes(work, buf+=8);
}
}
}
//encrypt from Input Buffer to Output Buffer
//Returns false if n is multiple of 8
void blowfish::encrypt(const unsigned char* in, unsigned char* out, uint64_t n, int iMode)
{
//Check the buffer's length - should be > 0 and multiple of 8
if((n==0)||(n%8!=0))
FC_THROW_EXCEPTION( exception, "invalid buffer length ${n}, not multiple of 8", ("n", n) );
sblock work;
if(iMode == CBC) //CBC mode, using the Chain
{
sblock chain(m_oChain);
for(; n >= 8; n -= 8, in += 8)
{
BytesToBlock(in, work);
work ^= chain;
encrypt(work);
chain = work;
BlockToBytes(work, out+=8);
}
}
else if(iMode == CFB) //CFB mode, using the Chain
{
sblock chain(m_oChain);
for(; n >= 8; n -= 8, in += 8)
{
encrypt(chain);
BytesToBlock(in, work);
work ^= chain;
chain = work;
BlockToBytes(work, out+=8);
}
}
else //ECB mode, not using the Chain
{
for(; n >= 8; n -= 8, in += 8)
{
BytesToBlock(in, work);
encrypt(work);
BlockToBytes(work, out+=8);
}
}
}
//decrypt from Input Buffer to Output Buffer
//Returns false if n is multiple of 8
void blowfish::decrypt(const unsigned char* in, unsigned char* out, uint64_t n, int iMode)
{
//Check the buffer's length - should be > 0 and multiple of 8
if((n==0)||(n%8!=0))
FC_THROW_EXCEPTION( exception, "invalid buffer length ${n}, not multiple of 8", ("n", n) );
sblock work;
if(iMode == CBC) //CBC mode, using the Chain
{
sblock crypt, chain(m_oChain);
for(; n >= 8; n -= 8, in += 8)
{
BytesToBlock(in, work);
crypt = work;
decrypt(work);
work ^= chain;
chain = crypt;
BlockToBytes(work, out+=8);
}
}
else if(iMode == CFB) //CFB mode, using the Chain, not using decrypt()
{
sblock crypt, chain(m_oChain);
for(; n >= 8; n -= 8, in += 8)
{
BytesToBlock(in, work);
encrypt(chain);
crypt = work;
work ^= chain;
chain = crypt;
BlockToBytes(work, out+=8);
}
}
else //ECB mode, not using the Chain
{
for(; n >= 8; n -= 8, in += 8)
{
BytesToBlock(in, work);
decrypt(work);
BlockToBytes(work, out+=8);
}
}
}
} // namespace fc

View file

@ -229,7 +229,7 @@ namespace fc { namespace ecc {
return private_key( k );
}
static fc::string _to_base58( const extended_key_data& key )
static std::string _to_base58( const extended_key_data& key )
{
size_t buf_len = key.size() + 4;
char *buffer = (char*)alloca(buf_len);
@ -239,7 +239,7 @@ namespace fc { namespace ecc {
return fc::to_base58( buffer, buf_len );
}
static void _parse_extended_data( unsigned char* buffer, fc::string base58 )
static void _parse_extended_data( unsigned char* buffer, std::string base58 )
{
memset( buffer, 0, 78 );
std::vector<char> decoded = fc::from_base58( base58 );
@ -276,12 +276,12 @@ namespace fc { namespace ecc {
return from_base58( _to_base58( data ) );
}
fc::string extended_public_key::str() const
std::string extended_public_key::str() const
{
return _to_base58( serialize_extended() );
}
extended_public_key extended_public_key::from_base58( const fc::string& base58 )
extended_public_key extended_public_key::from_base58( const std::string& base58 )
{
unsigned char buffer[78];
unsigned char* ptr = buffer;
@ -344,12 +344,12 @@ namespace fc { namespace ecc {
return from_base58( _to_base58( data ) );
}
fc::string extended_private_key::str() const
std::string extended_private_key::str() const
{
return _to_base58( serialize_extended() );
}
extended_private_key extended_private_key::from_base58( const fc::string& base58 )
extended_private_key extended_private_key::from_base58( const std::string& base58 )
{
unsigned char buffer[78];
unsigned char* ptr = buffer;
@ -366,7 +366,7 @@ namespace fc { namespace ecc {
return extended_private_key( private_key::regenerate(key), chain, cn, fp, d );
}
extended_private_key extended_private_key::generate_master( const fc::string& seed )
extended_private_key extended_private_key::generate_master( const std::string& seed )
{
return generate_master( seed.c_str(), seed.size() );
}

View file

@ -1,358 +0,0 @@
#include <fc/fwd_impl.hpp>
#include <boost/config.hpp>
#include "_elliptic_impl_pub.hpp"
/* used by mixed + openssl */
namespace fc { namespace ecc {
namespace detail {
public_key_impl::public_key_impl() BOOST_NOEXCEPT
{
_init_lib();
}
public_key_impl::public_key_impl( const public_key_impl& cpy ) BOOST_NOEXCEPT
{
_init_lib();
*this = cpy;
}
public_key_impl::public_key_impl( public_key_impl&& cpy ) BOOST_NOEXCEPT
{
_init_lib();
*this = cpy;
}
public_key_impl::~public_key_impl() BOOST_NOEXCEPT
{
free_key();
}
public_key_impl& public_key_impl::operator=( const public_key_impl& pk ) BOOST_NOEXCEPT
{
if (pk._key == nullptr)
{
free_key();
} else if ( _key == nullptr ) {
_key = EC_KEY_dup( pk._key );
} else {
EC_KEY_copy( _key, pk._key );
}
return *this;
}
public_key_impl& public_key_impl::operator=( public_key_impl&& pk ) BOOST_NOEXCEPT
{
if ( this != &pk ) {
free_key();
_key = pk._key;
pk._key = nullptr;
}
return *this;
}
void public_key_impl::free_key() BOOST_NOEXCEPT
{
if( _key != nullptr )
{
EC_KEY_free(_key);
_key = nullptr;
}
}
// Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields
// recid selects which key is recovered
// if check is non-zero, additional checks are performed
int public_key_impl::ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig,
const unsigned char *msg,
int msglen, int recid, int check)
{
if (!eckey) FC_THROW_EXCEPTION( exception, "null key" );
int ret = 0;
BN_CTX *ctx = NULL;
BIGNUM *x = NULL;
BIGNUM *e = NULL;
BIGNUM *order = NULL;
BIGNUM *sor = NULL;
BIGNUM *eor = NULL;
BIGNUM *field = NULL;
EC_POINT *R = NULL;
EC_POINT *O = NULL;
EC_POINT *Q = NULL;
BIGNUM *rr = NULL;
BIGNUM *zero = NULL;
int n = 0;
int i = recid / 2;
const EC_GROUP *group = EC_KEY_get0_group(eckey);
if ((ctx = BN_CTX_new()) == NULL) { ret = -1; goto err; }
BN_CTX_start(ctx);
order = BN_CTX_get(ctx);
if (!EC_GROUP_get_order(group, order, ctx)) { ret = -2; goto err; }
x = BN_CTX_get(ctx);
if (!BN_copy(x, order)) { ret=-1; goto err; }
if (!BN_mul_word(x, i)) { ret=-1; goto err; }
if (!BN_add(x, x, ecsig->r)) { ret=-1; goto err; }
field = BN_CTX_get(ctx);
if (!EC_GROUP_get_curve_GFp(group, field, NULL, NULL, ctx)) { ret=-2; goto err; }
if (BN_cmp(x, field) >= 0) { ret=0; goto err; }
if ((R = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
if (!EC_POINT_set_compressed_coordinates_GFp(group, R, x, recid % 2, ctx)) { ret=0; goto err; }
if (check)
{
if ((O = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
if (!EC_POINT_mul(group, O, NULL, R, order, ctx)) { ret=-2; goto err; }
if (!EC_POINT_is_at_infinity(group, O)) { ret = 0; goto err; }
}
if ((Q = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
n = EC_GROUP_get_degree(group);
e = BN_CTX_get(ctx);
if (!BN_bin2bn(msg, msglen, e)) { ret=-1; goto err; }
if (8*msglen > n) BN_rshift(e, e, 8-(n & 7));
zero = BN_CTX_get(ctx);
if (!BN_zero(zero)) { ret=-1; goto err; }
if (!BN_mod_sub(e, zero, e, order, ctx)) { ret=-1; goto err; }
rr = BN_CTX_get(ctx);
if (!BN_mod_inverse(rr, ecsig->r, order, ctx)) { ret=-1; goto err; }
sor = BN_CTX_get(ctx);
if (!BN_mod_mul(sor, ecsig->s, rr, order, ctx)) { ret=-1; goto err; }
eor = BN_CTX_get(ctx);
if (!BN_mod_mul(eor, e, rr, order, ctx)) { ret=-1; goto err; }
if (!EC_POINT_mul(group, Q, eor, R, sor, ctx)) { ret=-2; goto err; }
if (!EC_KEY_set_public_key(eckey, Q)) { ret=-2; goto err; }
ret = 1;
err:
if (ctx) {
BN_CTX_end(ctx);
BN_CTX_free(ctx);
}
if (R != NULL) EC_POINT_free(R);
if (O != NULL) EC_POINT_free(O);
if (Q != NULL) EC_POINT_free(Q);
return ret;
}
}
public_key::public_key() {}
public_key::public_key( const public_key& pk ) : my( pk.my ) {}
public_key::public_key( public_key&& pk ) : my( std::move( pk.my ) ) {}
public_key::~public_key() {}
public_key& public_key::operator=( public_key&& pk )
{
my = std::move(pk.my);
return *this;
}
public_key& public_key::operator=( const public_key& pk )
{
my = pk.my;
return *this;
}
bool public_key::valid()const
{
return my->_key != nullptr;
}
/* WARNING! This implementation is broken, it is actually equivalent to
* public_key::add()!
*/
// public_key public_key::mult( const fc::sha256& digest ) const
// {
// // get point from this public key
// const EC_POINT* master_pub = EC_KEY_get0_public_key( my->_key );
// ec_group group(EC_GROUP_new_by_curve_name(NID_secp256k1));
//
// ssl_bignum z;
// BN_bin2bn((unsigned char*)&digest, sizeof(digest), z);
//
// // multiply by digest
// ssl_bignum one;
// BN_one(one);
// bn_ctx ctx(BN_CTX_new());
//
// ec_point result(EC_POINT_new(group));
// EC_POINT_mul(group, result, z, master_pub, one, ctx);
//
// public_key rtn;
// rtn.my->_key = EC_KEY_new_by_curve_name( NID_secp256k1 );
// EC_KEY_set_public_key(rtn.my->_key,result);
//
// return rtn;
// }
public_key public_key::add( const fc::sha256& digest )const
{
try {
ec_group group(EC_GROUP_new_by_curve_name(NID_secp256k1));
bn_ctx ctx(BN_CTX_new());
fc::bigint digest_bi( (char*)&digest, sizeof(digest) );
ssl_bignum order;
EC_GROUP_get_order(group, order, ctx);
if( digest_bi > fc::bigint(order) )
{
FC_THROW_EXCEPTION( exception, "digest > group order" );
}
public_key digest_key = private_key::regenerate(digest).get_public_key();
const EC_POINT* digest_point = EC_KEY_get0_public_key( digest_key.my->_key );
// get point from this public key
const EC_POINT* master_pub = EC_KEY_get0_public_key( my->_key );
// ssl_bignum z;
// BN_bin2bn((unsigned char*)&digest, sizeof(digest), z);
// multiply by digest
// ssl_bignum one;
// BN_one(one);
ec_point result(EC_POINT_new(group));
EC_POINT_add(group, result, digest_point, master_pub, ctx);
if (EC_POINT_is_at_infinity(group, result))
{
FC_THROW_EXCEPTION( exception, "point at infinity" );
}
public_key rtn;
rtn.my->_key = EC_KEY_new_by_curve_name( NID_secp256k1 );
EC_KEY_set_public_key(rtn.my->_key,result);
return rtn;
} FC_RETHROW_EXCEPTIONS( debug, "digest: ${digest}", ("digest",digest) );
}
std::string public_key::to_base58() const
{
public_key_data key = serialize();
return to_base58( key );
}
// signature private_key::sign( const fc::sha256& digest )const
// {
// unsigned int buf_len = ECDSA_size(my->_key);
//// fprintf( stderr, "%d %d\n", buf_len, sizeof(sha256) );
// signature sig;
// assert( buf_len == sizeof(sig) );
//
// if( !ECDSA_sign( 0,
// (const unsigned char*)&digest, sizeof(digest),
// (unsigned char*)&sig, &buf_len, my->_key ) )
// {
// FC_THROW_EXCEPTION( exception, "signing error" );
// }
//
//
// return sig;
// }
// bool public_key::verify( const fc::sha256& digest, const fc::ecc::signature& sig )
// {
// return 1 == ECDSA_verify( 0, (unsigned char*)&digest, sizeof(digest), (unsigned char*)&sig, sizeof(sig), my->_key );
// }
public_key_data public_key::serialize()const
{
public_key_data dat;
if( !my->_key ) return dat;
EC_KEY_set_conv_form( my->_key, POINT_CONVERSION_COMPRESSED );
/*size_t nbytes = i2o_ECPublicKey( my->_key, nullptr ); */
/*assert( nbytes == 33 )*/
char* front = &dat.data[0];
i2o_ECPublicKey( my->_key, (unsigned char**)&front ); // FIXME: questionable memory handling
return dat;
/*
EC_POINT* pub = EC_KEY_get0_public_key( my->_key );
EC_GROUP* group = EC_KEY_get0_group( my->_key );
EC_POINT_get_affine_coordinates_GFp( group, pub, self.my->_pub_x.get(), self.my->_pub_y.get(), nullptr );
*/
}
public_key_point_data public_key::serialize_ecc_point()const
{
public_key_point_data dat;
if( !my->_key ) return dat;
EC_KEY_set_conv_form( my->_key, POINT_CONVERSION_UNCOMPRESSED );
char* front = &dat.data[0];
i2o_ECPublicKey( my->_key, (unsigned char**)&front ); // FIXME: questionable memory handling
return dat;
}
public_key::public_key( const public_key_point_data& dat )
{
const char* front = &dat.data[0];
if( *front == 0 ){}
else
{
my->_key = EC_KEY_new_by_curve_name( NID_secp256k1 );
my->_key = o2i_ECPublicKey( &my->_key, (const unsigned char**)&front, sizeof(dat) );
if( !my->_key )
{
FC_THROW_EXCEPTION( exception, "error decoding public key", ("s", ERR_error_string( ERR_get_error(), nullptr) ) );
}
}
}
public_key::public_key( const public_key_data& dat )
{
const char* front = &dat.data[0];
if( *front == 0 ){}
else
{
my->_key = EC_KEY_new_by_curve_name( NID_secp256k1 );
my->_key = o2i_ECPublicKey( &my->_key, (const unsigned char**)&front, sizeof(public_key_data) );
if( !my->_key )
{
FC_THROW_EXCEPTION( exception, "error decoding public key", ("s", ERR_error_string( ERR_get_error(), nullptr) ) );
}
}
}
// bool private_key::verify( const fc::sha256& digest, const fc::ecc::signature& sig )
// {
// return 1 == ECDSA_verify( 0, (unsigned char*)&digest, sizeof(digest), (unsigned char*)&sig, sizeof(sig), my->_key );
// }
public_key::public_key( const compact_signature& c, const fc::sha256& digest, bool check_canonical )
{
int nV = c.data[0];
if (nV<27 || nV>=35)
FC_THROW_EXCEPTION( exception, "unable to reconstruct public key from signature" );
ECDSA_SIG *sig = ECDSA_SIG_new();
BN_bin2bn(&c.data[1],32,sig->r);
BN_bin2bn(&c.data[33],32,sig->s);
if( check_canonical )
{
FC_ASSERT( is_canonical( c ), "signature is not canonical" );
}
my->_key = EC_KEY_new_by_curve_name(NID_secp256k1);
if (nV >= 31)
{
EC_KEY_set_conv_form( my->_key, POINT_CONVERSION_COMPRESSED );
nV -= 4;
// fprintf( stderr, "compressed\n" );
}
if (detail::public_key_impl::ECDSA_SIG_recover_key_GFp(my->_key, sig, (unsigned char*)&digest, sizeof(digest), nV - 27, 0) == 1)
{
ECDSA_SIG_free(sig);
return;
}
ECDSA_SIG_free(sig);
FC_THROW_EXCEPTION( exception, "unable to reconstruct public key from signature" );
}
}}

View file

@ -1,40 +0,0 @@
#include <fc/crypto/elliptic.hpp>
#include <fc/crypto/base58.hpp>
#include <fc/crypto/openssl.hpp>
#include <fc/fwd_impl.hpp>
#include <fc/exception/exception.hpp>
#include <fc/log/logger.hpp>
#include <assert.h>
#include <secp256k1.h>
#include "_elliptic_impl_priv.hpp"
#include "_elliptic_impl_pub.hpp"
namespace fc { namespace ecc {
namespace detail
{
const secp256k1_context_t* _get_context() {
static secp256k1_context_t* ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN);
return ctx;
}
void _init_lib() {
static const secp256k1_context_t* ctx = _get_context();
static int init_o = init_openssl();
}
}
static const private_key_secret empty_priv;
fc::sha512 private_key::get_shared_secret( const public_key& other )const
{
FC_ASSERT( my->_key != empty_priv );
FC_ASSERT( other.my->_key != nullptr );
public_key_data pub(other.serialize());
FC_ASSERT( secp256k1_ec_pubkey_tweak_mul( detail::_get_context(), (unsigned char*) pub.begin(), pub.size(), (unsigned char*) my->_key.data() ) );
return fc::sha512::hash( pub.begin() + 1, pub.size() - 1 );
}
} }

View file

@ -1,261 +0,0 @@
#include <fc/crypto/elliptic.hpp>
#include <fc/crypto/base58.hpp>
#include <fc/crypto/openssl.hpp>
#include <fc/fwd_impl.hpp>
#include <fc/exception/exception.hpp>
#include <fc/log/logger.hpp>
#include <assert.h>
#include "_elliptic_impl_pub.hpp"
namespace fc { namespace ecc {
namespace detail
{
void _init_lib() {
static int init_o = init_openssl();
}
class private_key_impl
{
public:
private_key_impl() BOOST_NOEXCEPT
{
_init_lib();
}
private_key_impl( const private_key_impl& cpy ) BOOST_NOEXCEPT
{
_init_lib();
*this = cpy;
}
private_key_impl( private_key_impl&& cpy ) BOOST_NOEXCEPT
{
_init_lib();
*this = cpy;
}
~private_key_impl() BOOST_NOEXCEPT
{
free_key();
}
private_key_impl& operator=( const private_key_impl& pk ) BOOST_NOEXCEPT
{
if (pk._key == nullptr)
{
free_key();
} else if ( _key == nullptr ) {
_key = EC_KEY_dup( pk._key );
} else {
EC_KEY_copy( _key, pk._key );
}
return *this;
}
private_key_impl& operator=( private_key_impl&& pk ) BOOST_NOEXCEPT
{
if ( this != &pk ) {
free_key();
_key = pk._key;
pk._key = nullptr;
}
return *this;
}
EC_KEY* _key = nullptr;
private:
void free_key() BOOST_NOEXCEPT
{
if( _key != nullptr )
{
EC_KEY_free(_key);
_key = nullptr;
}
}
};
}
private_key::private_key() {}
private_key::private_key( const private_key& pk ) : my( pk.my ) {}
private_key::private_key( private_key&& pk ) : my( std::move( pk.my ) ) {}
private_key::~private_key() {}
private_key& private_key::operator=( private_key&& pk )
{
my = std::move(pk.my);
return *this;
}
private_key& private_key::operator=( const private_key& pk )
{
my = pk.my;
return *this;
}
static void * ecies_key_derivation(const void *input, size_t ilen, void *output, size_t *olen)
{
if (*olen < SHA512_DIGEST_LENGTH) {
return NULL;
}
*olen = SHA512_DIGEST_LENGTH;
return (void*)SHA512((const unsigned char*)input, ilen, (unsigned char*)output);
}
int static inline EC_KEY_regenerate_key(EC_KEY *eckey, const BIGNUM *priv_key)
{
int ok = 0;
BN_CTX *ctx = NULL;
EC_POINT *pub_key = NULL;
if (!eckey) return 0;
const EC_GROUP *group = EC_KEY_get0_group(eckey);
if ((ctx = BN_CTX_new()) == NULL)
goto err;
pub_key = EC_POINT_new(group);
if (pub_key == NULL)
goto err;
if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
goto err;
EC_KEY_set_private_key(eckey,priv_key);
EC_KEY_set_public_key(eckey,pub_key);
ok = 1;
err:
if (pub_key) EC_POINT_free(pub_key);
if (ctx != NULL) BN_CTX_free(ctx);
return(ok);
}
private_key private_key::regenerate( const fc::sha256& secret )
{
private_key self;
self.my->_key = EC_KEY_new_by_curve_name( NID_secp256k1 );
if( !self.my->_key ) FC_THROW_EXCEPTION( exception, "Unable to generate EC key" );
ssl_bignum bn;
BN_bin2bn( (const unsigned char*)&secret, 32, bn );
if( !EC_KEY_regenerate_key(self.my->_key,bn) )
{
FC_THROW_EXCEPTION( exception, "unable to regenerate key" );
}
return self;
}
fc::sha256 private_key::get_secret()const
{
return get_secret( my->_key );
}
private_key::private_key( EC_KEY* k )
{
my->_key = k;
}
public_key private_key::get_public_key()const
{
public_key pub;
pub.my->_key = EC_KEY_new_by_curve_name( NID_secp256k1 );
EC_KEY_set_public_key( pub.my->_key, EC_KEY_get0_public_key( my->_key ) );
return pub;
}
fc::sha512 private_key::get_shared_secret( const public_key& other )const
{
FC_ASSERT( my->_key != nullptr );
FC_ASSERT( other.my->_key != nullptr );
fc::sha512 buf;
ECDH_compute_key( (unsigned char*)&buf, sizeof(buf), EC_KEY_get0_public_key(other.my->_key), my->_key, ecies_key_derivation );
return buf;
}
compact_signature private_key::sign_compact( const fc::sha256& digest )const
{
try {
FC_ASSERT( my->_key != nullptr );
auto my_pub_key = get_public_key().serialize(); // just for good measure
//ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&digest, sizeof(digest), my->_key);
public_key_data key_data;
while( true )
{
ecdsa_sig sig = ECDSA_do_sign((unsigned char*)&digest, sizeof(digest), my->_key);
if (sig==nullptr)
FC_THROW_EXCEPTION( exception, "Unable to sign" );
compact_signature csig;
// memset( csig.data, 0, sizeof(csig) );
int nBitsR = BN_num_bits(sig->r);
int nBitsS = BN_num_bits(sig->s);
if (nBitsR <= 256 && nBitsS <= 256)
{
int nRecId = -1;
EC_KEY* key = EC_KEY_new_by_curve_name( NID_secp256k1 );
FC_ASSERT( key );
EC_KEY_set_conv_form( key, POINT_CONVERSION_COMPRESSED );
for (int i=0; i<4; i++)
{
if (detail::public_key_impl::ECDSA_SIG_recover_key_GFp(key, sig, (unsigned char*)&digest, sizeof(digest), i, 1) == 1)
{
unsigned char* buffer = (unsigned char*) key_data.begin();
i2o_ECPublicKey( key, &buffer ); // FIXME: questionable memory handling
if ( key_data == my_pub_key )
{
nRecId = i;
break;
}
}
}
EC_KEY_free( key );
if (nRecId == -1)
{
FC_THROW_EXCEPTION( exception, "unable to construct recoverable key");
}
unsigned char* result = nullptr;
auto bytes = i2d_ECDSA_SIG( sig, &result );
auto lenR = result[3];
auto lenS = result[5+lenR];
//idump( (result[0])(result[1])(result[2])(result[3])(result[3+lenR])(result[4+lenR])(bytes)(lenR)(lenS) );
if( lenR != 32 ) { free(result); continue; }
if( lenS != 32 ) { free(result); continue; }
//idump( (33-(nBitsR+7)/8) );
//idump( (65-(nBitsS+7)/8) );
//idump( (sizeof(csig) ) );
memcpy( &csig.data[1], &result[4], lenR );
memcpy( &csig.data[33], &result[6+lenR], lenS );
//idump( (csig.data[33]) );
//idump( (csig.data[1]) );
free(result);
//idump( (nRecId) );
csig.data[0] = nRecId+27+4;//(fCompressedPubKey ? 4 : 0);
/*
idump( (csig) );
auto rlen = BN_bn2bin(sig->r,&csig.data[33-(nBitsR+7)/8]);
auto slen = BN_bn2bin(sig->s,&csig.data[65-(nBitsS+7)/8]);
idump( (rlen)(slen) );
*/
}
return csig;
} // while true
} FC_RETHROW_EXCEPTIONS( warn, "sign ${digest}", ("digest", digest)("private_key",*this) );
}
} }

View file

@ -10,7 +10,7 @@ namespace fc {
return c - 'a' + 10;
if( c >= 'A' && c <= 'F' )
return c - 'A' + 10;
FC_THROW_EXCEPTION( exception, "Invalid hex character '${c}'", ("c", fc::string(&c,1) ) );
FC_THROW_EXCEPTION( exception, "Invalid hex character '${c}'", ("c", std::string(&c,1) ) );
return 0;
}
@ -24,8 +24,8 @@ namespace fc {
return r;
}
size_t from_hex( const fc::string& hex_str, char* out_data, size_t out_data_len ) {
fc::string::const_iterator i = hex_str.begin();
size_t from_hex( const std::string& hex_str, char* out_data, size_t out_data_len ) {
std::string::const_iterator i = hex_str.begin();
uint8_t* out_pos = (uint8_t*)out_data;
uint8_t* out_end = out_pos + out_data_len;
while( i != hex_str.end() && out_end != out_pos ) {

View file

@ -1,365 +0,0 @@
#include <fc/crypto/pke.hpp>
#include <openssl/rsa.h>
#include <openssl/rand.h>
#include <openssl/sha.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <assert.h>
#include <fc/crypto/base64.hpp>
#include <fc/io/sstream.hpp>
#include <fc/io/stdio.hpp>
#include <fc/exception/exception.hpp>
#include <fc/variant.hpp>
namespace fc {
namespace detail {
class pke_impl
{
public:
pke_impl():rsa(nullptr){}
~pke_impl()
{
if( rsa != nullptr )
RSA_free(rsa);
}
RSA* rsa;
};
} // detail
public_key::operator bool()const { return !!my; }
private_key::operator bool()const { return !!my; }
public_key::public_key()
{}
public_key::public_key( const bytes& d )
:my( std::make_shared<detail::pke_impl>() )
{
string pem = "-----BEGIN RSA PUBLIC KEY-----\n";
auto b64 = fc::base64_encode( (const unsigned char*)d.data(), d.size() );
for( size_t i = 0; i < b64.size(); i += 64 )
pem += b64.substr( i, 64 ) + "\n";
pem += "-----END RSA PUBLIC KEY-----\n";
// fc::cerr<<pem;
BIO* mem = (BIO*)BIO_new_mem_buf( (void*)pem.c_str(), pem.size() );
my->rsa = PEM_read_bio_RSAPublicKey(mem, NULL, NULL, NULL );
BIO_free(mem);
}
public_key::public_key( const public_key& k )
:my(k.my)
{
}
public_key::public_key( public_key&& k )
:my(std::move(k.my))
{
}
public_key::~public_key() { }
public_key& public_key::operator=(const public_key& p )
{
my = p.my; return *this;
}
public_key& public_key::operator=( public_key&& p )
{
my = std::move(p.my); return *this;
}
bool public_key::verify( const sha1& digest, const array<char,2048/8>& sig )const
{
return 0 != RSA_verify( NID_sha1, (const uint8_t*)&digest, 20,
(uint8_t*)&sig, 2048/8, my->rsa );
}
bool public_key::verify( const sha1& digest, const signature& sig )const
{
static_assert( sig.size() == 2048/8, "Invalid signature size" );
return 0 != RSA_verify( NID_sha1, (const uint8_t*)&digest, 20,
(uint8_t*)sig.data(), 2048/8, my->rsa );
}
bool public_key::verify( const sha256& digest, const signature& sig )const
{
static_assert( sig.size() == 2048/8, "Invalid signature size" );
return 0 != RSA_verify( NID_sha256, (const uint8_t*)&digest, 32,
(uint8_t*)sig.data(), 2048/8, my->rsa );
}
bytes public_key::encrypt( const char* b, size_t l )const
{
FC_ASSERT( my && my->rsa );
bytes out( RSA_size(my->rsa) ); //, char(0) );
int rtn = RSA_public_encrypt( l,
(unsigned char*)b,
(unsigned char*)out.data(),
my->rsa, RSA_PKCS1_OAEP_PADDING );
if( rtn >= 0 ) {
out.resize(rtn);
return out;
}
FC_THROW_EXCEPTION( exception, "openssl: ${message}", ("message",fc::string(ERR_error_string( ERR_get_error(),NULL))) );
}
bytes public_key::encrypt( const bytes& in )const
{
FC_ASSERT( my && my->rsa );
bytes out( RSA_size(my->rsa) ); //, char(0) );
int rtn = RSA_public_encrypt( in.size(),
(unsigned char*)in.data(),
(unsigned char*)out.data(),
my->rsa, RSA_PKCS1_OAEP_PADDING );
fc::cerr<<"rtn: "<<rtn<<"\n";
if( rtn >= 0 ) {
out.resize(rtn);
return out;
}
FC_THROW_EXCEPTION( exception, "openssl: ${message}", ("message",fc::string(ERR_error_string( ERR_get_error(),NULL))) );
}
bytes public_key::decrypt( const bytes& in )const
{
FC_ASSERT( my && my->rsa );
bytes out( RSA_size(my->rsa) );//, char(0) );
int rtn = RSA_public_decrypt( in.size(),
(unsigned char*)in.data(),
(unsigned char*)out.data(),
my->rsa, RSA_PKCS1_OAEP_PADDING );
if( rtn >= 0 ) {
out.resize(rtn);
return out;
}
FC_THROW_EXCEPTION( exception, "openssl: ${message}", ("message",fc::string(ERR_error_string( ERR_get_error(),NULL))) );
}
bytes public_key::serialize()const
{
bytes ba;
if( !my ) { return ba; }
BIO *mem = BIO_new(BIO_s_mem());
int e = PEM_write_bio_RSAPublicKey( mem, my->rsa );
if( e != 1 )
{
BIO_free(mem);
FC_THROW_EXCEPTION( exception, "openssl: ${message}", ("message",fc::string(ERR_error_string( ERR_get_error(),NULL))) );
}
char* dat;
uint32_t l = BIO_get_mem_data( mem, &dat );
fc::stringstream ss( string( dat, l ) );
fc::stringstream key;
fc::string tmp;
fc::getline( ss, tmp );
fc::getline( ss, tmp );
while( tmp.size() && tmp[0] != '-' )
{
key << tmp;
fc::getline( ss, tmp );
}
auto str = key.str();
str = fc::base64_decode( str );
ba = bytes( str.begin(), str.end() );
BIO_free(mem);
return ba;
}
private_key::private_key()
{
}
private_key::private_key( const bytes& d )
:my( std::make_shared<detail::pke_impl>() )
{
string pem = "-----BEGIN RSA PRIVATE KEY-----\n";
auto b64 = fc::base64_encode( (const unsigned char*)d.data(), d.size() );
for( size_t i = 0; i < b64.size(); i += 64 )
pem += b64.substr( i, 64 ) + "\n";
pem += "-----END RSA PRIVATE KEY-----\n";
// fc::cerr<<pem;
BIO* mem = (BIO*)BIO_new_mem_buf( (void*)pem.c_str(), pem.size() );
my->rsa = PEM_read_bio_RSAPrivateKey(mem, NULL, NULL, NULL );
BIO_free(mem);
FC_ASSERT( my->rsa, "read private key" );
}
private_key::private_key( const private_key& k )
:my(k.my)
{
}
private_key::private_key( private_key&& k )
:my(std::move(k.my) )
{
}
private_key::~private_key() { }
private_key& private_key::operator=(const private_key& p )
{
my = p.my; return *this;
}
private_key& private_key::operator=(private_key&& p )
{
my = std::move(p.my); return *this;
}
void private_key::sign( const sha1& digest, array<char,2048/8>& sig )const
{
FC_ASSERT( (size_t(RSA_size(my->rsa)) <= sizeof(sig)), "Invalid RSA size" );
uint32_t slen = 0;
if( 1 != RSA_sign( NID_sha1, (uint8_t*)&digest,
20, (unsigned char*)&sig, &slen, my->rsa ) )
{
FC_THROW_EXCEPTION( exception, "rsa sign failed with ${message}", ("message",fc::string(ERR_error_string( ERR_get_error(),NULL))) );
}
}
signature private_key::sign( const sha1& digest )const
{
if( !my ) FC_THROW_EXCEPTION( assert_exception, "!null" );
signature sig;
sig.resize( RSA_size(my->rsa) );
uint32_t slen = 0;
if( 1 != RSA_sign( NID_sha1, (uint8_t*)digest.data(),
20, (unsigned char*)sig.data(), &slen, my->rsa ) )
{
FC_THROW_EXCEPTION( exception, "rsa sign failed with ${message}", ("message",fc::string(ERR_error_string( ERR_get_error(),NULL))) );
}
return sig;
}
signature private_key::sign( const sha256& digest )const
{
if( !my ) FC_THROW_EXCEPTION( assert_exception, "!null" );
signature sig;
sig.resize( RSA_size(my->rsa) );
uint32_t slen = 0;
if( 1 != RSA_sign( NID_sha256, (uint8_t*)digest.data(),
32, (unsigned char*)sig.data(), &slen, my->rsa ) )
{
FC_THROW_EXCEPTION( exception, "rsa sign failed with ${message}", ("message",fc::string(ERR_error_string( ERR_get_error(),NULL))) );
}
return sig;
}
bytes private_key::encrypt( const bytes& in )const
{
if( !my ) FC_THROW_EXCEPTION( assert_exception, "!null" );
bytes out;
out.resize( RSA_size(my->rsa) );
int rtn = RSA_private_encrypt( in.size(),
(unsigned char*)in.data(),
(unsigned char*)out.data(),
my->rsa, RSA_PKCS1_OAEP_PADDING );
if( rtn >= 0 ) {
out.resize(rtn);
return out;
}
FC_THROW_EXCEPTION( exception, "encrypt failed" );
}
bytes private_key::decrypt( const char* in, size_t l )const
{
if( !my ) FC_THROW_EXCEPTION( assert_exception, "!null" );
bytes out;
out.resize( RSA_size(my->rsa) );
int rtn = RSA_private_decrypt( l,
(unsigned char*)in,
(unsigned char*)out.data(),
my->rsa, RSA_PKCS1_OAEP_PADDING );
if( rtn >= 0 ) {
out.resize(rtn);
return out;
}
FC_THROW_EXCEPTION( exception, "decrypt failed" );
}
bytes private_key::decrypt( const bytes& in )const
{
if( !my ) FC_THROW_EXCEPTION( assert_exception, "!null" );
bytes out;
out.resize( RSA_size(my->rsa) );
int rtn = RSA_private_decrypt( in.size(),
(unsigned char*)in.data(),
(unsigned char*)out.data(),
my->rsa, RSA_PKCS1_OAEP_PADDING );
if( rtn >= 0 ) {
out.resize(rtn);
return out;
}
FC_THROW_EXCEPTION( exception, "decrypt failed" );
}
bytes private_key::serialize()const
{
bytes ba;
if( !my ) { return ba; }
BIO *mem = BIO_new(BIO_s_mem());
int e = PEM_write_bio_RSAPrivateKey( mem, my->rsa, NULL, NULL, 0, NULL, NULL );
if( e != 1 )
{
BIO_free(mem);
FC_THROW_EXCEPTION( exception, "Error writing private key, ${message}", ("message",fc::string(ERR_error_string( ERR_get_error(),NULL))) );
}
char* dat;
uint32_t l = BIO_get_mem_data( mem, &dat );
// return bytes( dat, dat + l );
stringstream ss( string( dat, l ) );
stringstream key;
string tmp;
fc::getline( ss, tmp );
fc::getline( ss, tmp );
while( tmp.size() && tmp[0] != '-' )
{
key << tmp;
fc::getline( ss, tmp );
}
auto str = key.str();
str = fc::base64_decode( str );
ba = bytes( str.begin(), str.end() );
// ba = bytes( dat, dat + l );
BIO_free(mem);
return ba;
}
void generate_key_pair( public_key& pub, private_key& priv )
{
static bool init = true;
if( init ) { ERR_load_crypto_strings(); init = false; }
pub.my = std::make_shared<detail::pke_impl>();
priv.my = pub.my;
pub.my->rsa = RSA_generate_key( 2048, 65537, NULL, NULL );
}
/** encodes the big int as base64 string, or a number */
void to_variant( const public_key& bi, variant& v, uint32_t max_depth )
{
v = bi.serialize();
}
/** decodes the big int as base64 string, or a number */
void from_variant( const variant& v, public_key& bi, uint32_t max_depth )
{
bi = public_key( v.as<std::vector<char> >(max_depth) );
}
/** encodes the big int as base64 string, or a number */
void to_variant( const private_key& bi, variant& v, uint32_t max_depth )
{
v = bi.serialize();
}
/** decodes the big int as base64 string, or a number */
void from_variant( const variant& v, private_key& bi, uint32_t max_depth )
{
bi = private_key( v.as<std::vector<char> >(max_depth) );
}
} // fc

View file

@ -108,7 +108,7 @@ bool operator == ( const ripemd160& h1, const ripemd160& h2 ) {
std::vector<char> ve = v.as< std::vector<char> >( max_depth );
memset( &bi, char(0), sizeof(bi) );
if( ve.size() )
memcpy( &bi, ve.data(), fc::min<size_t>(ve.size(),sizeof(bi)) );
memcpy( &bi, ve.data(), std::min<size_t>(ve.size(),sizeof(bi)) );
}
} // fc

Some files were not shown because too many files have changed in this diff Show more