mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Merge branch 'master' of github.com:jedmccaleb/NewCoin
This commit is contained in:
@@ -20,7 +20,7 @@ Application* theApp = NULL;
|
||||
DatabaseCon::DatabaseCon(const std::string& name, const char *initStrings[], int initCount)
|
||||
{
|
||||
std::string path=strprintf("%s%s", theConfig.DATA_DIR.c_str(), name.c_str());
|
||||
mDatabase=new SqliteDatabase(path.c_str());
|
||||
mDatabase = new SqliteDatabase(path.c_str());
|
||||
mDatabase->connect();
|
||||
for(int i = 0; i < initCount; ++i)
|
||||
mDatabase->executeSQL(initStrings[i], true);
|
||||
@@ -35,15 +35,16 @@ DatabaseCon::~DatabaseCon()
|
||||
Application::Application() :
|
||||
mUNL(mIOService),
|
||||
mNetOps(mIOService, &mMasterLedger), mNodeCache(16384, 600),
|
||||
mTxnDB(NULL), mLedgerDB(NULL), mWalletDB(NULL), mHashNodeDB(NULL), mNetNodeDB(NULL),
|
||||
mTxnDB(NULL), mAcctTxnDB(NULL), mLedgerDB(NULL), mWalletDB(NULL), mHashNodeDB(NULL), mNetNodeDB(NULL),
|
||||
mConnectionPool(mIOService), mPeerDoor(NULL), mRPCDoor(NULL)
|
||||
{
|
||||
RAND_bytes(mNonce256.begin(), mNonce256.size());
|
||||
RAND_bytes(reinterpret_cast<unsigned char *>(&mNonceST), sizeof(mNonceST));
|
||||
}
|
||||
|
||||
extern const char *TxnDBInit[], *LedgerDBInit[], *WalletDBInit[], *HashNodeDBInit[], *NetNodeDBInit[];
|
||||
extern int TxnDBCount, LedgerDBCount, WalletDBCount, HashNodeDBCount, NetNodeDBCount;
|
||||
extern const char *AcctTxnDBInit[], *TxnDBInit[], *LedgerDBInit[], *WalletDBInit[],
|
||||
*HashNodeDBInit[], *NetNodeDBInit[];
|
||||
extern int TxnDBCount, AcctTxnDBCount, LedgerDBCount, WalletDBCount, HashNodeDBCount, NetNodeDBCount;
|
||||
|
||||
void Application::stop()
|
||||
{
|
||||
@@ -59,11 +60,12 @@ void Application::run()
|
||||
//
|
||||
// Construct databases.
|
||||
//
|
||||
mTxnDB=new DatabaseCon("transaction.db", TxnDBInit, TxnDBCount);
|
||||
mLedgerDB=new DatabaseCon("ledger.db", LedgerDBInit, LedgerDBCount);
|
||||
mWalletDB=new DatabaseCon("wallet.db", WalletDBInit, WalletDBCount);
|
||||
mHashNodeDB=new DatabaseCon("hashnode.db", HashNodeDBInit, HashNodeDBCount);
|
||||
mNetNodeDB=new DatabaseCon("netnode.db", NetNodeDBInit, NetNodeDBCount);
|
||||
mTxnDB = new DatabaseCon("transaction.db", TxnDBInit, TxnDBCount);
|
||||
mAcctTxnDB = new DatabaseCon("transacct.db", AcctTxnDBInit, AcctTxnDBCount);
|
||||
mLedgerDB = new DatabaseCon("ledger.db", LedgerDBInit, LedgerDBCount);
|
||||
mWalletDB = new DatabaseCon("wallet.db", WalletDBInit, WalletDBCount);
|
||||
mHashNodeDB = new DatabaseCon("hashnode.db", HashNodeDBInit, HashNodeDBCount);
|
||||
mNetNodeDB = new DatabaseCon("netnode.db", NetNodeDBInit, NetNodeDBCount);
|
||||
|
||||
//
|
||||
// Begin validation and ip maintenance.
|
||||
@@ -76,7 +78,7 @@ void Application::run()
|
||||
//
|
||||
if(!theConfig.PEER_IP.empty() && theConfig.PEER_PORT)
|
||||
{
|
||||
mPeerDoor=new PeerDoor(mIOService);
|
||||
mPeerDoor = new PeerDoor(mIOService);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -88,7 +90,7 @@ void Application::run()
|
||||
//
|
||||
if(!theConfig.RPC_IP.empty() && theConfig.RPC_PORT)
|
||||
{
|
||||
mRPCDoor=new RPCDoor(mIOService);
|
||||
mRPCDoor = new RPCDoor(mIOService);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -138,6 +140,7 @@ void Application::run()
|
||||
Application::~Application()
|
||||
{
|
||||
delete mTxnDB;
|
||||
delete mAcctTxnDB;
|
||||
delete mLedgerDB;
|
||||
delete mWalletDB;
|
||||
delete mHashNodeDB;
|
||||
|
||||
@@ -45,7 +45,7 @@ class Application
|
||||
NetworkOPs mNetOps;
|
||||
NodeCache mNodeCache;
|
||||
|
||||
DatabaseCon* mTxnDB, *mLedgerDB, *mWalletDB, *mHashNodeDB, *mNetNodeDB;
|
||||
DatabaseCon *mTxnDB, *mAcctTxnDB, *mLedgerDB, *mWalletDB, *mHashNodeDB, *mNetNodeDB;
|
||||
|
||||
ConnectionPool mConnectionPool;
|
||||
PeerDoor* mPeerDoor;
|
||||
@@ -76,6 +76,7 @@ public:
|
||||
NodeCache& getNodeCache() { return mNodeCache; }
|
||||
|
||||
DatabaseCon* getTxnDB() { return mTxnDB; }
|
||||
DatabaseCon* getAcctTxnDB() { return mAcctTxnDB; }
|
||||
DatabaseCon* getLedgerDB() { return mLedgerDB; }
|
||||
DatabaseCon* getWalletDB() { return mWalletDB; }
|
||||
DatabaseCon* getHashNodeDB() { return mHashNodeDB; }
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
#ifndef __AVALANCHE__
|
||||
#define __AVALANCHE__
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include "Transaction.h"
|
||||
|
||||
class DisputedTransaction
|
||||
{
|
||||
protected:
|
||||
Transaction::pointer mTransaction;
|
||||
// std::vector<Hanko::pointer> mNodesIncluding;
|
||||
// std::vector<Hanko::pointer> mNodesRejecting;
|
||||
uint64 mTimeTaken; // when we took our position on this transaction
|
||||
bool mOurPosition;
|
||||
};
|
||||
|
||||
class DTComp
|
||||
{
|
||||
public:
|
||||
bool operator()(const DisputedTransaction&, const DisputedTransaction&);
|
||||
};
|
||||
|
||||
class Avalanche
|
||||
{
|
||||
protected:
|
||||
SHAMap::pointer mOurLedger;
|
||||
std::map<uint256, DisputedTransaction:pointer> mTxByID;
|
||||
std::set<DisputedTransaction::pointer, DTComp> mTxInASOrder;
|
||||
|
||||
public:
|
||||
Avalanche(SHAMap::pointer ourLedger);
|
||||
};
|
||||
|
||||
#endif
|
||||
53
src/CanonicalTXSet.cpp
Normal file
53
src/CanonicalTXSet.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
|
||||
#include "CanonicalTXSet.h"
|
||||
|
||||
bool CanonicalTXKey::operator<(const CanonicalTXKey& key) const
|
||||
{
|
||||
if (mAccount < key.mAccount) return true;
|
||||
if (mAccount > key.mAccount) return false;
|
||||
if (mSeq < key.mSeq) return true;
|
||||
if (mSeq > key.mSeq) return false;
|
||||
return mTXid < key.mTXid;
|
||||
}
|
||||
|
||||
bool CanonicalTXKey::operator>(const CanonicalTXKey& key) const
|
||||
{
|
||||
if (mAccount > key.mAccount) return true;
|
||||
if (mAccount < key.mAccount) return false;
|
||||
if (mSeq > key.mSeq) return true;
|
||||
if (mSeq < key.mSeq) return false;
|
||||
return mTXid > key.mTXid;
|
||||
}
|
||||
|
||||
bool CanonicalTXKey::operator<=(const CanonicalTXKey& key) const
|
||||
{
|
||||
if (mAccount < key.mAccount) return true;
|
||||
if (mAccount > key.mAccount) return false;
|
||||
if (mSeq < key.mSeq) return true;
|
||||
if (mSeq > key.mSeq) return false;
|
||||
return mTXid <= key.mTXid;
|
||||
}
|
||||
|
||||
bool CanonicalTXKey::operator>=(const CanonicalTXKey& key)const
|
||||
{
|
||||
if (mAccount > key.mAccount) return true;
|
||||
if (mAccount < key.mAccount) return false;
|
||||
if (mSeq > key.mSeq) return true;
|
||||
if (mSeq < key.mSeq) return false;
|
||||
return mTXid >= key.mTXid;
|
||||
}
|
||||
|
||||
void CanonicalTXSet::push_back(SerializedTransaction::pointer txn)
|
||||
{
|
||||
uint256 effectiveAccount = mSetHash;
|
||||
effectiveAccount ^= txn->getSourceAccount().getAccountID().to256();
|
||||
mMap.insert(std::make_pair(CanonicalTXKey(effectiveAccount, txn->getSequence(), txn->getTransactionID()), txn));
|
||||
}
|
||||
|
||||
void CanonicalTXSet::eraseInc(iterator& it)
|
||||
{
|
||||
iterator tmp = it++;
|
||||
mMap.erase(tmp);
|
||||
}
|
||||
|
||||
|
||||
53
src/CanonicalTXSet.h
Normal file
53
src/CanonicalTXSet.h
Normal file
@@ -0,0 +1,53 @@
|
||||
#ifndef __CANONICAL_TX_SET_
|
||||
#define __CANONICAL_TX_SET_
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "uint256.h"
|
||||
#include "SerializedTransaction.h"
|
||||
|
||||
class CanonicalTXKey
|
||||
{
|
||||
protected:
|
||||
uint256 mAccount, mTXid;
|
||||
uint32 mSeq;
|
||||
|
||||
public:
|
||||
CanonicalTXKey(const uint256& account, uint32 seq, const uint256& id)
|
||||
: mAccount(account), mTXid(id), mSeq(seq) { ; }
|
||||
|
||||
bool operator<(const CanonicalTXKey&) const;
|
||||
bool operator>(const CanonicalTXKey&) const;
|
||||
bool operator<=(const CanonicalTXKey&) const;
|
||||
bool operator>=(const CanonicalTXKey&) const;
|
||||
|
||||
bool operator==(const CanonicalTXKey& k) const { return mTXid == k.mTXid; }
|
||||
bool operator!=(const CanonicalTXKey& k) const { return mTXid != k.mTXid; }
|
||||
};
|
||||
|
||||
class CanonicalTXSet
|
||||
{
|
||||
public:
|
||||
typedef std::map<CanonicalTXKey, SerializedTransaction::pointer>::iterator iterator;
|
||||
typedef std::map<CanonicalTXKey, SerializedTransaction::pointer>::const_iterator const_iterator;
|
||||
|
||||
protected:
|
||||
uint256 mSetHash;
|
||||
std::map<CanonicalTXKey, SerializedTransaction::pointer> mMap;
|
||||
|
||||
public:
|
||||
CanonicalTXSet(const uint256& lclHash) : mSetHash(lclHash) { ; }
|
||||
|
||||
void push_back(SerializedTransaction::pointer txn);
|
||||
void erase(const iterator& it) { mMap.erase(it); }
|
||||
void eraseInc(iterator& it);
|
||||
|
||||
iterator begin() { return mMap.begin(); }
|
||||
iterator end() { return mMap.end(); }
|
||||
const_iterator begin() const { return mMap.begin(); }
|
||||
const_iterator end() const { return mMap.end(); }
|
||||
size_t size() const { return mMap.size(); }
|
||||
bool empty() const { return mMap.empty(); }
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,44 +0,0 @@
|
||||
#ifndef __CONFIRMATION__
|
||||
#define __CONFIRMATION__
|
||||
|
||||
#include "../obj/src/newcoin.pb.h"
|
||||
#include "uint256.h"
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
enum ConfirmationStatus
|
||||
{
|
||||
NEW, // first for this account/seq
|
||||
CONFLICTED, // rejected as of this time
|
||||
ACCEPTED, // in active bundle, has confirmations
|
||||
COMMITTED
|
||||
};
|
||||
|
||||
|
||||
class Confirmation
|
||||
{ // used primarily to report conflicted or rejected transactions
|
||||
public:
|
||||
typedef boost::shared_ptr<Transaction> pointer;
|
||||
|
||||
private:
|
||||
uint256 mID;
|
||||
uint160 mHanko;
|
||||
uint64 mTimestamp;
|
||||
ConfirmationStatus mStatus;
|
||||
bool mConflicts;
|
||||
std::vector<unsigned char> mSignature;
|
||||
|
||||
public:
|
||||
Confirmation();
|
||||
Confirmation(const uint256 &id);
|
||||
Confirmation(const std::vector<unsigned char> rawConfirmation);
|
||||
|
||||
const uint256& GetID() const { return mID; }
|
||||
const uint160& GetHanko() const { return mHanko; }
|
||||
uint64 GetTimestamp() const { return mTimestamp; }
|
||||
ConfirmationStatus() const { return mStatus; }
|
||||
bool HasConflicts() const { return mConflicts; }
|
||||
|
||||
bool save();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -20,7 +20,21 @@ const char *TxnDBInit[] = {
|
||||
);"
|
||||
};
|
||||
|
||||
int TxnDBCount=sizeof(TxnDBInit)/sizeof(const char *);
|
||||
int TxnDBCount = sizeof(TxnDBInit) / sizeof(const char *);
|
||||
|
||||
const char *AcctTxnDBInit[] = {
|
||||
"CREATE TABLE AccountTransactions ( \
|
||||
TransID CHARACTER964) PRIMARY KEY \
|
||||
Account CHARACTER(64), \
|
||||
LedgerSeq BIGINT UNSIGNED, \
|
||||
);",
|
||||
"CREATE INDEX AcctTxindex ON \
|
||||
AccountTransactions(Account), \
|
||||
AccountTransactions(LedgerSeq), \
|
||||
AccountTransactions(TransID);"
|
||||
};
|
||||
|
||||
int AcctTxnDBCount = sizeof(AcctTxnDBInit) / sizeof(const char *);
|
||||
|
||||
// Ledger database holds ledgers and ledger confirmations
|
||||
const char *LedgerDBInit[] = {
|
||||
@@ -46,7 +60,7 @@ const char *LedgerDBInit[] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
int LedgerDBCount=sizeof(LedgerDBInit)/sizeof(const char *);
|
||||
int LedgerDBCount = sizeof(LedgerDBInit) / sizeof(const char *);
|
||||
|
||||
// Wallet database holds local accounts and trusted nodes
|
||||
const char *WalletDBInit[] = {
|
||||
@@ -212,7 +226,7 @@ const char *WalletDBInit[] = {
|
||||
PeerIps(ScanNext);"
|
||||
};
|
||||
|
||||
int WalletDBCount=sizeof(WalletDBInit)/sizeof(const char *);
|
||||
int WalletDBCount = sizeof(WalletDBInit) / sizeof(const char *);
|
||||
|
||||
// Hash node database holds nodes indexed by hash
|
||||
const char *HashNodeDBInit[] = {
|
||||
@@ -227,7 +241,7 @@ const char *HashNodeDBInit[] = {
|
||||
CommittedObjects(LedgerIndex, ObjType);"
|
||||
};
|
||||
|
||||
int HashNodeDBCount=sizeof(HashNodeDBInit)/sizeof(const char *);
|
||||
int HashNodeDBCount = sizeof(HashNodeDBInit) / sizeof(const char *);
|
||||
|
||||
// Net node database holds nodes seen on the network
|
||||
// XXX Not really used needs replacement.
|
||||
@@ -241,6 +255,6 @@ const char *NetNodeDBInit[] = {
|
||||
};
|
||||
|
||||
|
||||
int NetNodeDBCount=sizeof(NetNodeDBInit)/sizeof(const char *);
|
||||
int NetNodeDBCount = sizeof(NetNodeDBInit) / sizeof(const char *);
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/ecdsa.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
// Functions to add CKey support for deterministic EC keys
|
||||
|
||||
@@ -78,7 +79,7 @@ EC_KEY* CKey::GenerateRootDeterministicKey(const uint128& seed)
|
||||
{ // set the random point as the private key
|
||||
assert(false);
|
||||
EC_KEY_free(pkey);
|
||||
BN_free(privKey);
|
||||
BN_clear_free(privKey);
|
||||
BN_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
@@ -87,13 +88,13 @@ EC_KEY* CKey::GenerateRootDeterministicKey(const uint128& seed)
|
||||
if(!EC_POINT_mul(EC_KEY_get0_group(pkey), pubKey, privKey, NULL, NULL, ctx))
|
||||
{ // compute the corresponding public key point
|
||||
assert(false);
|
||||
BN_free(privKey);
|
||||
BN_clear_free(privKey);
|
||||
EC_POINT_free(pubKey);
|
||||
EC_KEY_free(pkey);
|
||||
BN_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
BN_free(privKey);
|
||||
BN_clear_free(privKey);
|
||||
if(!EC_KEY_set_public_key(pkey, pubKey))
|
||||
{
|
||||
assert(false);
|
||||
@@ -115,26 +116,32 @@ EC_KEY* CKey::GenerateRootDeterministicKey(const uint128& seed)
|
||||
// <-- root public generator in EC format
|
||||
EC_KEY* CKey::GenerateRootPubKey(BIGNUM* pubGenerator)
|
||||
{
|
||||
if(pubGenerator==NULL) return NULL;
|
||||
if (pubGenerator == NULL)
|
||||
{
|
||||
assert(false);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EC_KEY* pkey=EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
if(!pkey)
|
||||
EC_KEY* pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
if (!pkey)
|
||||
{
|
||||
BN_free(pubGenerator);
|
||||
return NULL;
|
||||
}
|
||||
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
|
||||
|
||||
EC_POINT* pubPoint=EC_POINT_bn2point(EC_KEY_get0_group(pkey), pubGenerator, NULL, NULL);
|
||||
EC_POINT* pubPoint = EC_POINT_bn2point(EC_KEY_get0_group(pkey), pubGenerator, NULL, NULL);
|
||||
BN_free(pubGenerator);
|
||||
if(!pubPoint)
|
||||
{
|
||||
assert(false);
|
||||
EC_KEY_free(pkey);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!EC_KEY_set_public_key(pkey, pubPoint))
|
||||
{
|
||||
assert(false);
|
||||
EC_POINT_free(pubPoint);
|
||||
EC_KEY_free(pkey);
|
||||
return NULL;
|
||||
@@ -144,14 +151,14 @@ EC_KEY* CKey::GenerateRootPubKey(BIGNUM* pubGenerator)
|
||||
}
|
||||
|
||||
// --> public generator
|
||||
static BIGNUM* makeHash(const NewcoinAddress& generator, int seq, BIGNUM* order)
|
||||
static BIGNUM* makeHash(const NewcoinAddress& pubGen, int seq, BIGNUM* order)
|
||||
{
|
||||
int subSeq=0;
|
||||
BIGNUM* ret=NULL;
|
||||
do
|
||||
{
|
||||
Serializer s((33*8+32+32)/8);
|
||||
s.addRaw(generator.getFamilyGenerator());
|
||||
s.addRaw(pubGen.getFamilyGenerator());
|
||||
s.add32(seq);
|
||||
s.add32(subSeq++);
|
||||
uint256 root=s.getSHA512Half();
|
||||
@@ -164,9 +171,9 @@ static BIGNUM* makeHash(const NewcoinAddress& generator, int seq, BIGNUM* order)
|
||||
}
|
||||
|
||||
// --> public generator
|
||||
EC_KEY* CKey::GeneratePublicDeterministicKey(const NewcoinAddress& generator, int seq)
|
||||
EC_KEY* CKey::GeneratePublicDeterministicKey(const NewcoinAddress& pubGen, int seq)
|
||||
{ // publicKey(n) = rootPublicKey EC_POINT_+ Hash(pubHash|seq)*point
|
||||
EC_KEY* rootKey = CKey::GenerateRootPubKey(generator.getFamilyGeneratorBN());
|
||||
EC_KEY* rootKey = CKey::GenerateRootPubKey(pubGen.getFamilyGeneratorBN());
|
||||
const EC_POINT* rootPubKey = EC_KEY_get0_public_key(rootKey);
|
||||
BN_CTX* ctx = BN_CTX_new();
|
||||
EC_KEY* pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
@@ -194,7 +201,7 @@ EC_KEY* CKey::GeneratePublicDeterministicKey(const NewcoinAddress& generator, in
|
||||
|
||||
// Calculate the private additional key.
|
||||
if (success) {
|
||||
hash = makeHash(generator, seq, order);
|
||||
hash = makeHash(pubGen, seq, order);
|
||||
if(!hash) success = false;
|
||||
}
|
||||
|
||||
@@ -217,8 +224,14 @@ EC_KEY* CKey::GeneratePublicDeterministicKey(const NewcoinAddress& generator, in
|
||||
return success ? pkey : NULL;
|
||||
}
|
||||
|
||||
EC_KEY* CKey::GeneratePrivateDeterministicKey(const NewcoinAddress& pubGen, const uint256& u, int seq)
|
||||
{
|
||||
CBigNum bn(u);
|
||||
return GeneratePrivateDeterministicKey(pubGen, static_cast<BIGNUM*>(&bn), seq);
|
||||
}
|
||||
|
||||
// --> root private key
|
||||
EC_KEY* CKey::GeneratePrivateDeterministicKey(const NewcoinAddress& family, const BIGNUM* rootPrivKey, int seq)
|
||||
EC_KEY* CKey::GeneratePrivateDeterministicKey(const NewcoinAddress& pubGen, const BIGNUM* rootPrivKey, int seq)
|
||||
{ // privateKey(n) = (rootPrivateKey + Hash(pubHash|seq)) % order
|
||||
BN_CTX* ctx=BN_CTX_new();
|
||||
if(ctx==NULL) return NULL;
|
||||
@@ -248,7 +261,7 @@ EC_KEY* CKey::GeneratePrivateDeterministicKey(const NewcoinAddress& family, cons
|
||||
}
|
||||
|
||||
// calculate the private additional key
|
||||
BIGNUM* privKey=makeHash(family, seq, order);
|
||||
BIGNUM* privKey=makeHash(pubGen, seq, order);
|
||||
if(privKey==NULL)
|
||||
{
|
||||
BN_free(order);
|
||||
@@ -266,19 +279,19 @@ EC_KEY* CKey::GeneratePrivateDeterministicKey(const NewcoinAddress& family, cons
|
||||
EC_POINT* pubKey=EC_POINT_new(EC_KEY_get0_group(pkey));
|
||||
if(!pubKey)
|
||||
{
|
||||
BN_free(privKey);
|
||||
BN_clear_free(privKey);
|
||||
BN_CTX_free(ctx);
|
||||
EC_KEY_free(pkey);
|
||||
return NULL;
|
||||
}
|
||||
if(EC_POINT_mul(EC_KEY_get0_group(pkey), pubKey, privKey, NULL, NULL, ctx)==0)
|
||||
{
|
||||
BN_free(privKey);
|
||||
BN_clear_free(privKey);
|
||||
BN_CTX_free(ctx);
|
||||
EC_KEY_free(pkey);
|
||||
return NULL;
|
||||
}
|
||||
BN_free(privKey);
|
||||
BN_clear_free(privKey);
|
||||
EC_KEY_set_public_key(pkey, pubKey);
|
||||
|
||||
EC_POINT_free(pubKey);
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
#include "Hanko.h"
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
using namespace boost;
|
||||
using namespace std;
|
||||
|
||||
Hanko::Hanko()
|
||||
{
|
||||
}
|
||||
|
||||
// vim:ts=4
|
||||
65
src/Hanko.h
65
src/Hanko.h
@@ -1,65 +0,0 @@
|
||||
#ifndef __HANKO__
|
||||
#define __HANKO__
|
||||
|
||||
// We use SECP256K1 http://www.secg.org/collateral/sec2_final.pdf
|
||||
|
||||
#include "key.h"
|
||||
|
||||
enum HankoFormat
|
||||
{
|
||||
TEXT, // Hanko in text form
|
||||
RAW, // Hanko in raw binary form
|
||||
CONTACT, // Hanko contact block
|
||||
};
|
||||
|
||||
|
||||
class Hanko
|
||||
{
|
||||
public:
|
||||
static const int smPubKeySize= 65;
|
||||
static const int smPrivKeySize = 279;
|
||||
static const int smSigSize = 57;
|
||||
|
||||
private:
|
||||
std::string mHanko;
|
||||
std::vector<unsigned char> mContactBlock;
|
||||
CKey mPubKey;
|
||||
|
||||
public:
|
||||
Hanko();
|
||||
Hanko(const std::string& TextHanko);
|
||||
Hanko(const std::vector<unsigned char>& Data, HankoFormat format);
|
||||
Hanko(const CKey &pubKey);
|
||||
Hanko(const Hanko &);
|
||||
|
||||
std::string GetHankoString(HankoFormat format) const;
|
||||
std::vector<unsigned char> GetHankoBinary(HankoFormat format) const;
|
||||
|
||||
const std::vector<unsigned char>& GetContactBlock() const { return mContactBlock; }
|
||||
const CKey& GetPublicKey() const { return mPubKey; }
|
||||
|
||||
int UpdateContact(std::vector<unsigned char>& Contact);
|
||||
|
||||
bool CheckHashSign(const uint256& hash, const std::vector<unsigned char>& Signature);
|
||||
bool CheckPrefixSign(const std::vector<unsigned char>& data, uint64 type,
|
||||
const std::vector<unsigned char> &signature);
|
||||
};
|
||||
|
||||
|
||||
class LocalHanko : public Hanko
|
||||
{
|
||||
private:
|
||||
CKey mPrivKey;
|
||||
|
||||
public:
|
||||
LocalHanko(std::vector<unsigned char> &PrivKey);
|
||||
LocalHanko(const CKey &Privkey);
|
||||
LocalHanko(const LocalHanko &);
|
||||
~LocalHanko();
|
||||
|
||||
bool HashSign(const uint256& hash, std::vector<unsigned char>& Signature);
|
||||
bool PrefixSign(std::vector<unsigned char> data, uint64 type, std::vector<unsigned char> &Signature);
|
||||
};
|
||||
|
||||
#endif
|
||||
// vim:ts=4
|
||||
@@ -36,6 +36,10 @@ CREATE TABLE CommittedObjects ( -- used to synch nodes
|
||||
CREATE INDEX ObjectLocate ON CommittedObjects(LedgerIndex, ObjType);
|
||||
*/
|
||||
|
||||
// FIXME: Stores should be added to a queue that's services by an auxilliary thread or from an
|
||||
// auxilliary thread pool. These should be tied into a cache, since you need one to handle
|
||||
// an immedate read back (before the write completes)
|
||||
|
||||
bool HashedObject::store(HashedObjectType type, uint32 index, const std::vector<unsigned char>& data,
|
||||
const uint256& hash)
|
||||
{
|
||||
@@ -44,7 +48,7 @@ bool HashedObject::store(HashedObjectType type, uint32 index, const std::vector<
|
||||
Serializer s(data);
|
||||
assert(hash == s.getSHA512Half());
|
||||
#endif
|
||||
std::string sql = "INSERT INTO CommitedObjects (Hash,ObjType,LedgerIndex,Object) VALUES ('";
|
||||
std::string sql = "INSERT INTO CommittedObjects (Hash,ObjType,LedgerIndex,Object) VALUES ('";
|
||||
sql.append(hash.GetHex());
|
||||
switch(type)
|
||||
{
|
||||
@@ -78,7 +82,7 @@ bool HashedObject::store() const
|
||||
HashedObject::pointer HashedObject::retrieve(const uint256& hash)
|
||||
{
|
||||
if (!theApp || !theApp->getHashNodeDB()) return HashedObject::pointer();
|
||||
std::string sql = "SELECT * from CommitedObjects WHERE Hash='";
|
||||
std::string sql = "SELECT * from CommittedObjects WHERE Hash='";
|
||||
sql.append(hash.GetHex());
|
||||
sql.append("';");
|
||||
|
||||
|
||||
@@ -336,20 +336,37 @@ void Ledger::addJson(Json::Value& ret, int options)
|
||||
else ledger["Closed"] = false;
|
||||
if (mCloseTime != 0)
|
||||
ledger["CloseTime"] = boost::posix_time::to_simple_string(ptFromSeconds(mCloseTime));
|
||||
if ((options & LEDGER_JSON_DUMP_TXNS) != 0)
|
||||
bool full = (options & LEDGER_JSON_FULL) != 0;
|
||||
if (full || ((options & LEDGER_JSON_DUMP_TXNS) != 0))
|
||||
{
|
||||
Json::Value txns(Json::arrayValue);
|
||||
for (SHAMapItem::pointer item = mTransactionMap->peekFirstItem(); !!item;
|
||||
item = mTransactionMap->peekNextItem(item->getTag()))
|
||||
txns.append(item->getTag().GetHex());
|
||||
{
|
||||
if (full)
|
||||
{
|
||||
SerializerIterator sit(item->peekSerializer());
|
||||
SerializedTransaction txn(sit);
|
||||
txns.append(txn.getJson(0));
|
||||
}
|
||||
else txns.append(item->getTag().GetHex());
|
||||
}
|
||||
ledger["Transactions"] = txns;
|
||||
}
|
||||
if ((options & LEDGER_JSON_DUMP_STATE) != 0)
|
||||
if (full || ((options & LEDGER_JSON_DUMP_STATE) != 0))
|
||||
{
|
||||
Json::Value state(Json::arrayValue);
|
||||
for (SHAMapItem::pointer item = mAccountStateMap->peekFirstItem(); !!item;
|
||||
item = mAccountStateMap->peekNextItem(item->getTag()))
|
||||
state.append(item->getTag().GetHex());
|
||||
{
|
||||
if (full)
|
||||
{
|
||||
SerializerIterator sit(item->peekSerializer());
|
||||
SerializedLedgerEntry sle(sit, item->getTag());
|
||||
state.append(sle.getJson(0));
|
||||
}
|
||||
else state.append(item->getTag().GetHex());
|
||||
}
|
||||
ledger["AccountState"] = state;
|
||||
}
|
||||
ret[boost::lexical_cast<std::string>(mLedgerSeq)] = ledger;
|
||||
|
||||
@@ -35,6 +35,7 @@ enum LedgerStateParms
|
||||
|
||||
#define LEDGER_JSON_DUMP_TXNS 0x10000000
|
||||
#define LEDGER_JSON_DUMP_STATE 0x20000000
|
||||
#define LEDGER_JSON_FULL 0x40000000
|
||||
|
||||
class Ledger : public boost::enable_shared_from_this<Ledger>
|
||||
{ // The basic Ledger structure, can be opened, closed, or synching
|
||||
|
||||
@@ -60,7 +60,7 @@ typedef std::vector<unsigned char> VUC;
|
||||
class THSyncFilter : public SHAMapSyncFilter
|
||||
{
|
||||
protected:
|
||||
NodeCache* mCache;
|
||||
NodeCache* mCache; // holds nodes we see during the consensus process
|
||||
|
||||
public:
|
||||
THSyncFilter(NodeCache* cache) : mCache(cache) { ; }
|
||||
|
||||
@@ -577,7 +577,7 @@ void LedgerConsensus::Saccept(boost::shared_ptr<LedgerConsensus> This, SHAMap::p
|
||||
}
|
||||
|
||||
void LedgerConsensus::applyTransactions(SHAMap::pointer set, Ledger::pointer ledger,
|
||||
std::list<SerializedTransaction::pointer>& failedTransactions)
|
||||
CanonicalTXSet& failedTransactions)
|
||||
{
|
||||
TransactionEngine engine(ledger);
|
||||
|
||||
@@ -620,16 +620,17 @@ void LedgerConsensus::applyTransactions(SHAMap::pointer set, Ledger::pointer led
|
||||
do
|
||||
{
|
||||
successes = 0;
|
||||
std::list<SerializedTransaction::pointer>::iterator it = failedTransactions.begin();
|
||||
CanonicalTXSet::iterator it = failedTransactions.begin();
|
||||
while (it != failedTransactions.end())
|
||||
{
|
||||
try
|
||||
{
|
||||
TransactionEngineResult result = engine.applyTransaction(**it, tepNO_CHECK_FEE | tepUPDATE_TOTAL, 0);
|
||||
TransactionEngineResult result =
|
||||
engine.applyTransaction(*it->second, tepNO_CHECK_FEE | tepUPDATE_TOTAL, 0);
|
||||
if (result <= 0)
|
||||
{
|
||||
if (result == 0) ++successes;
|
||||
failedTransactions.erase(it++);
|
||||
failedTransactions.eraseInc(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -639,7 +640,7 @@ void LedgerConsensus::applyTransactions(SHAMap::pointer set, Ledger::pointer led
|
||||
catch (...)
|
||||
{
|
||||
Log(lsWARNING) << " Throws";
|
||||
failedTransactions.erase(it++);
|
||||
failedTransactions.eraseInc(it);
|
||||
}
|
||||
}
|
||||
} while (successes > 0);
|
||||
@@ -653,6 +654,7 @@ void LedgerConsensus::accept(SHAMap::pointer set)
|
||||
Log(lsDEBUG) << "Previous LCL " << mPreviousLedger->getHash().GetHex();
|
||||
|
||||
Ledger::pointer newLCL = boost::make_shared<Ledger>(false, boost::ref(*mPreviousLedger));
|
||||
uint32 newLedgerSeq = newLCL->getLedgerSeq();
|
||||
|
||||
#ifdef DEBUG
|
||||
Json::StyledStreamWriter ssw;
|
||||
@@ -665,7 +667,7 @@ void LedgerConsensus::accept(SHAMap::pointer set)
|
||||
}
|
||||
#endif
|
||||
|
||||
std::list<SerializedTransaction::pointer> failedTransactions;
|
||||
CanonicalTXSet failedTransactions(set->getHash());
|
||||
applyTransactions(set, newLCL, failedTransactions);
|
||||
newLCL->setClosed();
|
||||
newLCL->setAccepted();
|
||||
@@ -703,10 +705,10 @@ void LedgerConsensus::accept(SHAMap::pointer set)
|
||||
|
||||
ScopedLock sl = theApp->getMasterLedger().getLock();
|
||||
|
||||
applyTransactions(theApp->getMasterLedger().getCurrentLedger()->peekTransactionMap(),
|
||||
newOL, failedTransactions);
|
||||
applyTransactions(theApp->getMasterLedger().getCurrentLedger()->peekTransactionMap(), newOL, failedTransactions);
|
||||
theApp->getMasterLedger().pushLedger(newLCL, newOL);
|
||||
mState = lcsACCEPTED;
|
||||
sl.unlock();
|
||||
|
||||
#ifdef DEBUG
|
||||
if (1)
|
||||
@@ -718,8 +720,6 @@ void LedgerConsensus::accept(SHAMap::pointer set)
|
||||
}
|
||||
#endif
|
||||
|
||||
sl.unlock();
|
||||
|
||||
SerializedValidation v(newLCLHash, mOurPosition->peekKey(), true);
|
||||
std::vector<unsigned char> validation = v.getSigned();
|
||||
newcoin::TMValidation val;
|
||||
@@ -727,6 +727,34 @@ void LedgerConsensus::accept(SHAMap::pointer set)
|
||||
theApp->getConnectionPool().relayMessage(NULL, boost::make_shared<PackedMessage>(val, newcoin::mtVALIDATION));
|
||||
Log(lsINFO) << "Validation sent " << newLCL->getHash().GetHex();
|
||||
statusChange(newcoin::neACCEPTED_LEDGER, newOL);
|
||||
|
||||
// Insert the transactions in set into the AcctTxn database
|
||||
Database *db = theApp->getAcctTxnDB()->getDB();
|
||||
ScopedLock dbLock = theApp->getAcctTxnDB()->getDBLock();
|
||||
db->executeSQL("BEGIN TRANSACTION");
|
||||
for (SHAMapItem::pointer item = set->peekFirstItem(); !!item; item = set->peekNextItem(item->getTag()))
|
||||
{
|
||||
SerializerIterator sit(item->peekSerializer());
|
||||
SerializedTransaction txn(sit);
|
||||
std::vector<NewcoinAddress> accts = txn.getAffectedAccounts();
|
||||
|
||||
std::string sql = "INSERT INTO AccountTransactions (TransID,Account,LedgerSeq) VALUES ";
|
||||
bool first = true;
|
||||
for (std::vector<NewcoinAddress>::iterator it = accts.begin(), end = accts.end(); it != end; ++it)
|
||||
{
|
||||
if (!first) sql += ", (";
|
||||
else sql += "(";
|
||||
sql += txn.getTransactionID().GetHex();
|
||||
sql += ",";
|
||||
sql += it->humanAccountID();
|
||||
sql += ",";
|
||||
sql += boost::lexical_cast<std::string>(newLedgerSeq);
|
||||
sql += ")";
|
||||
}
|
||||
sql += ";";
|
||||
db->executeSQL(sql);
|
||||
}
|
||||
db->executeSQL("COMMIT TRANSACTION");
|
||||
}
|
||||
|
||||
void LedgerConsensus::endConsensus()
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "LedgerAcquire.h"
|
||||
#include "LedgerProposal.h"
|
||||
#include "Peer.h"
|
||||
#include "CanonicalTXSet.h"
|
||||
|
||||
class TransactionAcquire : public PeerSet, public boost::enable_shared_from_this<TransactionAcquire>
|
||||
{ // A transaction set we are trying to acquire
|
||||
@@ -113,7 +114,7 @@ protected:
|
||||
void removePosition(LedgerProposal&, bool ours);
|
||||
void sendHaveTxSet(const uint256& set, bool direct);
|
||||
void applyTransactions(SHAMap::pointer transactionSet, Ledger::pointer targetLedger,
|
||||
std::list<SerializedTransaction::pointer>& failedTransactions);
|
||||
CanonicalTXSet& failedTransactions);
|
||||
|
||||
// manipulating our own position
|
||||
void takeInitialPosition(Ledger::pointer initialLedger);
|
||||
|
||||
@@ -490,7 +490,7 @@ std::vector<unsigned char> NewcoinAddress::accountPrivateDecrypt(const NewcoinAd
|
||||
//
|
||||
|
||||
BIGNUM* NewcoinAddress::getFamilyGeneratorBN() const
|
||||
{
|
||||
{ // returns the public generator
|
||||
switch (nVersion) {
|
||||
case VER_NONE:
|
||||
throw std::runtime_error("unset source");
|
||||
@@ -505,12 +505,11 @@ BIGNUM* NewcoinAddress::getFamilyGeneratorBN() const
|
||||
|
||||
BIGNUM* ret = BN_bin2bn(&vchData[0], vchData.size(), NULL);
|
||||
assert(ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const std::vector<unsigned char>& NewcoinAddress::getFamilyGenerator() const
|
||||
{
|
||||
{ // returns the public generator
|
||||
switch (nVersion) {
|
||||
case VER_NONE:
|
||||
throw std::runtime_error("unset source");
|
||||
|
||||
@@ -135,7 +135,7 @@ public:
|
||||
// Family Generators
|
||||
// Use to generate a master or regular family.
|
||||
//
|
||||
BIGNUM* getFamilyGeneratorBN() const;
|
||||
BIGNUM* getFamilyGeneratorBN() const; // DEPRECATED
|
||||
const std::vector<unsigned char>& getFamilyGenerator() const;
|
||||
|
||||
std::string humanFamilyGenerator() const;
|
||||
|
||||
@@ -1410,10 +1410,20 @@ Json::Value RPCServer::doTx(Json::Value& params)
|
||||
return JSONRPCError(501, "not implemented");
|
||||
}
|
||||
|
||||
// ledger
|
||||
// ledger [id|current|lastclosed] [full]
|
||||
Json::Value RPCServer::doLedger(Json::Value& params)
|
||||
{
|
||||
if (getParamCount(params)== 0)
|
||||
|
||||
if (params.size() > 2)
|
||||
{
|
||||
return "invalid params";
|
||||
}
|
||||
else if (!mNetOps->available())
|
||||
{
|
||||
return JSONRPCError(503, "network not available");
|
||||
}
|
||||
|
||||
if (getParamCount(params) == 0)
|
||||
{
|
||||
Json::Value ret(Json::objectValue), current(Json::objectValue), closed(Json::objectValue);
|
||||
theApp->getMasterLedger().getCurrentLedger()->addJson(current, 0);
|
||||
@@ -1423,7 +1433,35 @@ Json::Value RPCServer::doLedger(Json::Value& params)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return JSONRPCError(501, "not implemented");
|
||||
std::string param;
|
||||
if (!extractString(param, params, 0))
|
||||
{
|
||||
return "bad params";
|
||||
}
|
||||
|
||||
Ledger::pointer ledger;
|
||||
if (param == "current")
|
||||
ledger = theApp->getMasterLedger().getCurrentLedger();
|
||||
else if (param == "lastclosed")
|
||||
ledger = theApp->getMasterLedger().getClosedLedger();
|
||||
else if (param.size() > 12)
|
||||
ledger = theApp->getMasterLedger().getLedgerByHash(uint256(param));
|
||||
else
|
||||
ledger = theApp->getMasterLedger().getLedgerBySeq(boost::lexical_cast<uint32>(param));
|
||||
|
||||
if (!ledger)
|
||||
return JSONRPCError(503, "Unable to locate ledger");
|
||||
|
||||
bool full = false;
|
||||
if (extractString(param, params, 1))
|
||||
{
|
||||
if (param == "full")
|
||||
full = true;
|
||||
}
|
||||
|
||||
Json::Value ret(Json::objectValue);
|
||||
ledger->addJson(ret, full ? LEDGER_JSON_FULL : 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// unl_add <domain>|<node_public> [<comment>]
|
||||
@@ -2105,12 +2143,13 @@ Json::Value RPCServer::doCommand(const std::string& command, Json::Value& params
|
||||
if (command == "wallet_propose") return doWalletPropose(params);
|
||||
if (command == "wallet_seed") return doWalletSeed(params);
|
||||
|
||||
if (command=="ledger") return doLedger(params);
|
||||
|
||||
//
|
||||
// Obsolete or need rewrite:
|
||||
//
|
||||
|
||||
if (command=="tx") return doTx(params);
|
||||
if (command=="ledger") return doLedger(params);
|
||||
|
||||
return "unknown command";
|
||||
}
|
||||
|
||||
@@ -69,4 +69,4 @@ public:
|
||||
};
|
||||
|
||||
|
||||
#endif // HTTP_REQUEST_PARSER_HPP
|
||||
#endif // HTTP_REQUEST_PARSER_HPP
|
||||
|
||||
@@ -57,6 +57,7 @@ std::string SerializedLedgerEntry::getText() const
|
||||
Json::Value SerializedLedgerEntry::getJson(int options) const
|
||||
{
|
||||
Json::Value ret(mObject.getJson(options));
|
||||
ret["Type"] = mFormat->t_name;
|
||||
ret["Index"] = mIndex.GetHex();
|
||||
ret["Version"] = mVersion.getText();
|
||||
return ret;
|
||||
|
||||
@@ -272,11 +272,14 @@ void SerializedTransaction::makeITFieldAbsent(SOE_Field field)
|
||||
|
||||
Json::Value SerializedTransaction::getJson(int options) const
|
||||
{
|
||||
Json::Value ret(Json::objectValue);
|
||||
ret["Type"] = mFormat->t_name;
|
||||
Json::Value ret = Json::objectValue;
|
||||
ret["ID"] = getTransactionID().GetHex();
|
||||
ret["Signature"] = mSignature.getText();
|
||||
ret["Middle"] = mMiddleTxn.getJson(options);
|
||||
|
||||
Json::Value middle = mMiddleTxn.getJson(options);
|
||||
middle["Type"] = mFormat->t_name;
|
||||
ret["Middle"] = middle;
|
||||
|
||||
ret["Inner"] = mInnerTxn.getJson(options);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,12 @@
|
||||
// in the map. The map allows multiple code paths that reference objects
|
||||
// with the same tag to get the same actual object.
|
||||
|
||||
// So long as data is in the cache, it will stay in memory.
|
||||
// If it stays in memory even after it is ejected from the cache,
|
||||
// the map will track it.
|
||||
|
||||
// CAUTION: Callers must not modify data objects that are stored in the cache!
|
||||
|
||||
template <typename c_Key, typename c_Data> class TaggedCache
|
||||
{
|
||||
public:
|
||||
@@ -46,7 +52,9 @@ public:
|
||||
bool touch(const key_type& key);
|
||||
bool del(const key_type& key);
|
||||
bool canonicalize(const key_type& key, boost::shared_ptr<c_Data>& data);
|
||||
bool store(const key_type& key, const c_Data& data);
|
||||
boost::shared_ptr<c_Data> fetch(const key_type& key);
|
||||
bool retrieve(const key_type& key, c_Data& data);
|
||||
|
||||
boost::recursive_mutex& peekMutex() { return mLock; }
|
||||
};
|
||||
@@ -86,7 +94,10 @@ template<typename c_Key, typename c_Data> void TaggedCache<c_Key, c_Data>::sweep
|
||||
while (cit != mCache.end())
|
||||
{
|
||||
if (cit->second->second.first < target)
|
||||
mCache.erase(cit++);
|
||||
{
|
||||
typename boost::unordered_map<key_type, cache_entry>::iterator tmp = cit++;
|
||||
mCache.erase(tmp);
|
||||
}
|
||||
else ++cit;
|
||||
}
|
||||
|
||||
@@ -95,7 +106,10 @@ template<typename c_Key, typename c_Data> void TaggedCache<c_Key, c_Data>::sweep
|
||||
while (mit != mMap.end())
|
||||
{
|
||||
if (mit->second->expired())
|
||||
mMap.erase(mit++);
|
||||
{
|
||||
typename boost::unordered_map<key_type, weak_data_ptr>::iterator tmp = mit++;
|
||||
mMap.erase(mit);
|
||||
}
|
||||
else ++mit;
|
||||
}
|
||||
}
|
||||
@@ -149,15 +163,16 @@ bool TaggedCache<c_Key, c_Data>::canonicalize(const key_type& key, boost::shared
|
||||
mMap.insert(std::make_pair(key, data));
|
||||
return false;
|
||||
}
|
||||
if (mit->second.expired())
|
||||
{ // in map, but expired
|
||||
|
||||
boost::shared_ptr<c_Data> cachedData = mit->second.lock();
|
||||
if (!cachedData)
|
||||
{ // in map, but expired. Update in map, insert in cache
|
||||
mit->second = data;
|
||||
mCache.insert(std::make_pair(key, std::make_pair(time(NULL), data)));
|
||||
return false;
|
||||
}
|
||||
|
||||
data = mit->second.lock();
|
||||
assert(!!data);
|
||||
data = cachedData;
|
||||
|
||||
// Valid in map, is it in cache?
|
||||
typename boost::unordered_map<key_type, cache_entry>::iterator cit = mCache.find(key);
|
||||
@@ -171,28 +186,46 @@ bool TaggedCache<c_Key, c_Data>::canonicalize(const key_type& key, boost::shared
|
||||
|
||||
template<typename c_Key, typename c_Data>
|
||||
boost::shared_ptr<c_Data> TaggedCache<c_Key, c_Data>::fetch(const key_type& key)
|
||||
{
|
||||
{ // fetch us a shared pointer to the stored data object
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
|
||||
// Is it in the map?
|
||||
typename boost::unordered_map<key_type, weak_data_ptr>::iterator mit = mMap.find(key);
|
||||
if (mit == mMap.end()) return data_ptr(); // No, we're done
|
||||
if (mit->second.expired())
|
||||
{ // in map, but expired
|
||||
mMap.erase(mit);
|
||||
return data_ptr();
|
||||
}
|
||||
|
||||
boost::shared_ptr<c_Data> data = mit->second.lock();
|
||||
boost::shared_ptr<c_Data> cachedData = mit->second.lock();
|
||||
if (!cachedData)
|
||||
{ // in map, but expired. Sorry, we don't have it
|
||||
mMap.erase(mit);
|
||||
return cachedData;
|
||||
}
|
||||
|
||||
// Valid in map, is it in the cache?
|
||||
typename boost::unordered_map<key_type, cache_entry>::iterator cit = mCache.find(key);
|
||||
if (cit != mCache.end())
|
||||
cit->second.first = time(NULL); // Yes, refresh
|
||||
else // No, add to cache
|
||||
mCache.insert(std::make_pair(key, std::make_pair(time(NULL), data)));
|
||||
mCache.insert(std::make_pair(key, std::make_pair(time(NULL), cachedData)));
|
||||
|
||||
return data;
|
||||
return cachedData;
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data>
|
||||
bool TaggedCache<c_Key, c_Data>::store(const key_type& key, const c_Data& data)
|
||||
{
|
||||
if (!canonicalize(key, boost::shared_ptr<c_Data>(data)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data>
|
||||
bool TaggedCache<c_Key, c_Data>::retrieve(const key_type& key, c_Data& data)
|
||||
{ // retrieve the value of the stored data
|
||||
boost::shared_ptr<c_Data> dataPtr = fetch(key);
|
||||
if (!dataPtr)
|
||||
return false;
|
||||
data = *dataPtr;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -20,11 +20,11 @@ TransactionMaster::TransactionMaster() : mCache(CACHED_TRANSACTION_NUM, CACHED_T
|
||||
|
||||
Transaction::pointer TransactionMaster::fetch(const uint256& txnID, bool checkDisk)
|
||||
{
|
||||
Transaction::pointer txn=mCache.fetch(txnID);
|
||||
if(!checkDisk || txn) return txn;
|
||||
Transaction::pointer txn = mCache.fetch(txnID);
|
||||
if( !checkDisk || txn) return txn;
|
||||
|
||||
txn=Transaction::load(txnID);
|
||||
if(!txn) return txn;
|
||||
txn = Transaction::load(txnID);
|
||||
if (!txn) return txn;
|
||||
|
||||
mCache.canonicalize(txnID, txn);
|
||||
return txn;
|
||||
@@ -32,10 +32,10 @@ Transaction::pointer TransactionMaster::fetch(const uint256& txnID, bool checkDi
|
||||
|
||||
bool TransactionMaster::canonicalize(Transaction::pointer& txn, bool may_be_new)
|
||||
{
|
||||
uint256 tid=txn->getID();
|
||||
if(!tid) return false;
|
||||
if(mCache.canonicalize(tid, txn)) return true;
|
||||
if(may_be_new)
|
||||
uint256 tid = txn->getID();
|
||||
if (!tid) return false;
|
||||
if (mCache.canonicalize(tid, txn)) return true;
|
||||
if (may_be_new) // FIXME: Don't dispatch to main pool
|
||||
theApp->getIOService().post(boost::bind(&Transaction::saveTransaction, txn));
|
||||
return false;
|
||||
}
|
||||
|
||||
812
src/bignum.h
812
src/bignum.h
@@ -14,7 +14,7 @@
|
||||
class bignum_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
explicit bignum_error(const std::string& str) : std::runtime_error(str) {}
|
||||
explicit bignum_error(const std::string& str) : std::runtime_error(str) {}
|
||||
};
|
||||
|
||||
|
||||
@@ -26,27 +26,27 @@ private:
|
||||
CAutoBN_CTX& operator=(const CAutoBN_CTX&); // no implementation
|
||||
|
||||
protected:
|
||||
BN_CTX* pctx;
|
||||
BN_CTX* operator=(BN_CTX* pnew) { return pctx = pnew; }
|
||||
BN_CTX* pctx;
|
||||
BN_CTX* operator=(BN_CTX* pnew) { return pctx = pnew; }
|
||||
|
||||
public:
|
||||
CAutoBN_CTX()
|
||||
{
|
||||
pctx = BN_CTX_new();
|
||||
if (pctx == NULL)
|
||||
throw bignum_error("CAutoBN_CTX : BN_CTX_new() returned NULL");
|
||||
}
|
||||
CAutoBN_CTX()
|
||||
{
|
||||
pctx = BN_CTX_new();
|
||||
if (pctx == NULL)
|
||||
throw bignum_error("CAutoBN_CTX : BN_CTX_new() returned NULL");
|
||||
}
|
||||
|
||||
~CAutoBN_CTX()
|
||||
{
|
||||
if (pctx != NULL)
|
||||
BN_CTX_free(pctx);
|
||||
}
|
||||
~CAutoBN_CTX()
|
||||
{
|
||||
if (pctx != NULL)
|
||||
BN_CTX_free(pctx);
|
||||
}
|
||||
|
||||
operator BN_CTX*() { return pctx; }
|
||||
BN_CTX& operator*() { return *pctx; }
|
||||
BN_CTX** operator&() { return &pctx; }
|
||||
bool operator!() { return (pctx == NULL); }
|
||||
operator BN_CTX*() { return pctx; }
|
||||
BN_CTX& operator*() { return *pctx; }
|
||||
BN_CTX** operator&() { return &pctx; }
|
||||
bool operator!() { return (pctx == NULL); }
|
||||
};
|
||||
|
||||
|
||||
@@ -54,482 +54,454 @@ public:
|
||||
class CBigNum : public BIGNUM
|
||||
{
|
||||
public:
|
||||
CBigNum()
|
||||
{
|
||||
BN_init(this);
|
||||
}
|
||||
CBigNum()
|
||||
{
|
||||
BN_init(this);
|
||||
}
|
||||
|
||||
CBigNum(const CBigNum& b)
|
||||
{
|
||||
BN_init(this);
|
||||
if (!BN_copy(this, &b))
|
||||
{
|
||||
BN_clear_free(this);
|
||||
throw bignum_error("CBigNum::CBigNum(const CBigNum&) : BN_copy failed");
|
||||
}
|
||||
}
|
||||
CBigNum(const CBigNum& b)
|
||||
{
|
||||
BN_init(this);
|
||||
if (!BN_copy(this, &b))
|
||||
{
|
||||
BN_clear_free(this);
|
||||
throw bignum_error("CBigNum::CBigNum(const CBigNum&) : BN_copy failed");
|
||||
}
|
||||
}
|
||||
|
||||
CBigNum& operator=(const CBigNum& b)
|
||||
{
|
||||
if (!BN_copy(this, &b))
|
||||
throw bignum_error("CBigNum::operator= : BN_copy failed");
|
||||
return (*this);
|
||||
}
|
||||
CBigNum& operator=(const CBigNum& b)
|
||||
{
|
||||
if (!BN_copy(this, &b))
|
||||
throw bignum_error("CBigNum::operator= : BN_copy failed");
|
||||
return (*this);
|
||||
}
|
||||
|
||||
~CBigNum()
|
||||
{
|
||||
BN_clear_free(this);
|
||||
}
|
||||
~CBigNum()
|
||||
{
|
||||
BN_clear_free(this);
|
||||
}
|
||||
|
||||
CBigNum(char n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
|
||||
CBigNum(short n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
|
||||
CBigNum(int n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
|
||||
CBigNum(long n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
|
||||
CBigNum(int64 n) { BN_init(this); setint64(n); }
|
||||
CBigNum(unsigned char n) { BN_init(this); setulong(n); }
|
||||
CBigNum(unsigned short n) { BN_init(this); setulong(n); }
|
||||
CBigNum(unsigned int n) { BN_init(this); setulong(n); }
|
||||
CBigNum(unsigned long n) { BN_init(this); setulong(n); }
|
||||
CBigNum(uint64 n) { BN_init(this); setuint64(n); }
|
||||
explicit CBigNum(uint256 n) { BN_init(this); setuint256(n); }
|
||||
CBigNum(char n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
|
||||
CBigNum(short n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
|
||||
CBigNum(int n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
|
||||
CBigNum(long n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
|
||||
CBigNum(int64 n) { BN_init(this); setint64(n); }
|
||||
CBigNum(unsigned char n) { BN_init(this); setulong(n); }
|
||||
CBigNum(unsigned short n) { BN_init(this); setulong(n); }
|
||||
CBigNum(unsigned int n) { BN_init(this); setulong(n); }
|
||||
CBigNum(unsigned long n) { BN_init(this); setulong(n); }
|
||||
CBigNum(uint64 n) { BN_init(this); setuint64(n); }
|
||||
explicit CBigNum(uint256 n) { BN_init(this); setuint256(n); }
|
||||
|
||||
explicit CBigNum(const std::vector<unsigned char>& vch)
|
||||
{
|
||||
BN_init(this);
|
||||
setvch(vch);
|
||||
}
|
||||
explicit CBigNum(const std::vector<unsigned char>& vch)
|
||||
{
|
||||
BN_init(this);
|
||||
setvch(vch);
|
||||
}
|
||||
|
||||
void setulong(unsigned long n)
|
||||
{
|
||||
if (!BN_set_word(this, n))
|
||||
throw bignum_error("CBigNum conversion from unsigned long : BN_set_word failed");
|
||||
}
|
||||
void setulong(unsigned long n)
|
||||
{
|
||||
if (!BN_set_word(this, n))
|
||||
throw bignum_error("CBigNum conversion from unsigned long : BN_set_word failed");
|
||||
}
|
||||
|
||||
unsigned long getulong() const
|
||||
{
|
||||
return BN_get_word(this);
|
||||
}
|
||||
unsigned long getulong() const
|
||||
{
|
||||
return BN_get_word(this);
|
||||
}
|
||||
|
||||
unsigned int getuint() const
|
||||
{
|
||||
return BN_get_word(this);
|
||||
}
|
||||
unsigned int getuint() const
|
||||
{
|
||||
return BN_get_word(this);
|
||||
}
|
||||
|
||||
int getint() const
|
||||
{
|
||||
unsigned long n = BN_get_word(this);
|
||||
if (!BN_is_negative(this))
|
||||
return (n > INT_MAX ? INT_MAX : n);
|
||||
else
|
||||
return (n > INT_MAX ? INT_MIN : -(int)n);
|
||||
}
|
||||
int getint() const
|
||||
{
|
||||
unsigned long n = BN_get_word(this);
|
||||
if (!BN_is_negative(this))
|
||||
return (n > INT_MAX ? INT_MAX : n);
|
||||
else
|
||||
return (n > INT_MAX ? INT_MIN : -(int)n);
|
||||
}
|
||||
|
||||
void setint64(int64 n)
|
||||
{
|
||||
unsigned char pch[sizeof(n) + 6];
|
||||
unsigned char* p = pch + 4;
|
||||
bool fNegative = false;
|
||||
if (n < (int64)0)
|
||||
{
|
||||
n = -n;
|
||||
fNegative = true;
|
||||
}
|
||||
bool fLeadingZeroes = true;
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
unsigned char c = (n >> 56) & 0xff;
|
||||
n <<= 8;
|
||||
if (fLeadingZeroes)
|
||||
{
|
||||
if (c == 0)
|
||||
continue;
|
||||
if (c & 0x80)
|
||||
*p++ = (fNegative ? 0x80 : 0);
|
||||
else if (fNegative)
|
||||
c |= 0x80;
|
||||
fLeadingZeroes = false;
|
||||
}
|
||||
*p++ = c;
|
||||
}
|
||||
unsigned int nSize = p - (pch + 4);
|
||||
pch[0] = (nSize >> 24) & 0xff;
|
||||
pch[1] = (nSize >> 16) & 0xff;
|
||||
pch[2] = (nSize >> 8) & 0xff;
|
||||
pch[3] = (nSize) & 0xff;
|
||||
BN_mpi2bn(pch, p - pch, this);
|
||||
}
|
||||
void setint64(int64 n)
|
||||
{
|
||||
unsigned char pch[sizeof(n) + 6];
|
||||
unsigned char* p = pch + 4;
|
||||
bool fNegative = false;
|
||||
if (n < (int64)0)
|
||||
{
|
||||
n = -n;
|
||||
fNegative = true;
|
||||
}
|
||||
bool fLeadingZeroes = true;
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
unsigned char c = (n >> 56) & 0xff;
|
||||
n <<= 8;
|
||||
if (fLeadingZeroes)
|
||||
{
|
||||
if (c == 0)
|
||||
continue;
|
||||
if (c & 0x80)
|
||||
*p++ = (fNegative ? 0x80 : 0);
|
||||
else if (fNegative)
|
||||
c |= 0x80;
|
||||
fLeadingZeroes = false;
|
||||
}
|
||||
*p++ = c;
|
||||
}
|
||||
unsigned int nSize = p - (pch + 4);
|
||||
pch[0] = (nSize >> 24) & 0xff;
|
||||
pch[1] = (nSize >> 16) & 0xff;
|
||||
pch[2] = (nSize >> 8) & 0xff;
|
||||
pch[3] = (nSize) & 0xff;
|
||||
BN_mpi2bn(pch, p - pch, this);
|
||||
}
|
||||
|
||||
void setuint64(uint64 n)
|
||||
{
|
||||
unsigned char pch[sizeof(n) + 6];
|
||||
unsigned char* p = pch + 4;
|
||||
bool fLeadingZeroes = true;
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
unsigned char c = (n >> 56) & 0xff;
|
||||
n <<= 8;
|
||||
if (fLeadingZeroes)
|
||||
{
|
||||
if (c == 0)
|
||||
continue;
|
||||
if (c & 0x80)
|
||||
*p++ = 0;
|
||||
fLeadingZeroes = false;
|
||||
}
|
||||
*p++ = c;
|
||||
}
|
||||
unsigned int nSize = p - (pch + 4);
|
||||
pch[0] = (nSize >> 24) & 0xff;
|
||||
pch[1] = (nSize >> 16) & 0xff;
|
||||
pch[2] = (nSize >> 8) & 0xff;
|
||||
pch[3] = (nSize) & 0xff;
|
||||
BN_mpi2bn(pch, p - pch, this);
|
||||
}
|
||||
void setuint64(uint64 n)
|
||||
{
|
||||
unsigned char pch[sizeof(n) + 6];
|
||||
unsigned char* p = pch + 4;
|
||||
bool fLeadingZeroes = true;
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
unsigned char c = (n >> 56) & 0xff;
|
||||
n <<= 8;
|
||||
if (fLeadingZeroes)
|
||||
{
|
||||
if (c == 0)
|
||||
continue;
|
||||
if (c & 0x80)
|
||||
*p++ = 0;
|
||||
fLeadingZeroes = false;
|
||||
}
|
||||
*p++ = c;
|
||||
}
|
||||
unsigned int nSize = p - (pch + 4);
|
||||
pch[0] = (nSize >> 24) & 0xff;
|
||||
pch[1] = (nSize >> 16) & 0xff;
|
||||
pch[2] = (nSize >> 8) & 0xff;
|
||||
pch[3] = (nSize) & 0xff;
|
||||
BN_mpi2bn(pch, p - pch, this);
|
||||
}
|
||||
|
||||
void setuint256(uint256 n)
|
||||
{
|
||||
unsigned char pch[sizeof(n) + 6];
|
||||
unsigned char* p = pch + 4;
|
||||
bool fLeadingZeroes = true;
|
||||
unsigned char* pbegin = (unsigned char*)&n;
|
||||
unsigned char* psrc = pbegin + sizeof(n);
|
||||
while (psrc != pbegin)
|
||||
{
|
||||
unsigned char c = *(--psrc);
|
||||
if (fLeadingZeroes)
|
||||
{
|
||||
if (c == 0)
|
||||
continue;
|
||||
if (c & 0x80)
|
||||
*p++ = 0;
|
||||
fLeadingZeroes = false;
|
||||
}
|
||||
*p++ = c;
|
||||
}
|
||||
unsigned int nSize = p - (pch + 4);
|
||||
pch[0] = (nSize >> 24) & 0xff;
|
||||
pch[1] = (nSize >> 16) & 0xff;
|
||||
pch[2] = (nSize >> 8) & 0xff;
|
||||
pch[3] = (nSize >> 0) & 0xff;
|
||||
BN_mpi2bn(pch, p - pch, this);
|
||||
}
|
||||
void setuint256(const uint256& n)
|
||||
{
|
||||
BN_bin2bn(n.begin(), n.size(), NULL);
|
||||
}
|
||||
|
||||
uint256 getuint256()
|
||||
{
|
||||
unsigned int nSize = BN_bn2mpi(this, NULL);
|
||||
if (nSize < 4)
|
||||
return 0;
|
||||
std::vector<unsigned char> vch(nSize);
|
||||
BN_bn2mpi(this, &vch[0]);
|
||||
if (vch.size() > 4)
|
||||
vch[4] &= 0x7f;
|
||||
uint256 n = 0;
|
||||
for (int i = 0, j = vch.size()-1; i < sizeof(n) && j >= 4; i++, j--)
|
||||
((unsigned char*)&n)[i] = vch[j];
|
||||
return n;
|
||||
}
|
||||
uint256 getuint256()
|
||||
{
|
||||
uint256 ret;
|
||||
int size = BN_num_bytes(this);
|
||||
if (size > ret.size())
|
||||
return ret;
|
||||
BN_bn2bin(this, ret.begin() + (ret.size() - BN_num_bytes(this)));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void setvch(const std::vector<unsigned char>& vch)
|
||||
{
|
||||
std::vector<unsigned char> vch2(vch.size() + 4);
|
||||
unsigned int nSize = vch.size();
|
||||
// BIGNUM's byte stream format expects 4 bytes of
|
||||
// big endian size data info at the front
|
||||
vch2[0] = (nSize >> 24) & 0xff;
|
||||
vch2[1] = (nSize >> 16) & 0xff;
|
||||
vch2[2] = (nSize >> 8) & 0xff;
|
||||
vch2[3] = (nSize >> 0) & 0xff;
|
||||
// swap data to big endian
|
||||
std::reverse_copy(vch.begin(), vch.end(), vch2.begin() + 4);
|
||||
BN_mpi2bn(&vch2[0], vch2.size(), this);
|
||||
}
|
||||
void setvch(const std::vector<unsigned char>& vch)
|
||||
{
|
||||
std::vector<unsigned char> vch2(vch.size() + 4);
|
||||
unsigned int nSize = vch.size();
|
||||
// BIGNUM's byte stream format expects 4 bytes of
|
||||
// big endian size data info at the front
|
||||
vch2[0] = (nSize >> 24) & 0xff;
|
||||
vch2[1] = (nSize >> 16) & 0xff;
|
||||
vch2[2] = (nSize >> 8) & 0xff;
|
||||
vch2[3] = (nSize >> 0) & 0xff;
|
||||
// swap data to big endian
|
||||
std::reverse_copy(vch.begin(), vch.end(), vch2.begin() + 4);
|
||||
BN_mpi2bn(&vch2[0], vch2.size(), this);
|
||||
}
|
||||
|
||||
std::vector<unsigned char> getvch() const
|
||||
{
|
||||
unsigned int nSize = BN_bn2mpi(this, NULL);
|
||||
if (nSize < 4)
|
||||
return std::vector<unsigned char>();
|
||||
std::vector<unsigned char> vch(nSize);
|
||||
BN_bn2mpi(this, &vch[0]);
|
||||
vch.erase(vch.begin(), vch.begin() + 4);
|
||||
reverse(vch.begin(), vch.end());
|
||||
return vch;
|
||||
}
|
||||
std::vector<unsigned char> getvch() const
|
||||
{
|
||||
unsigned int nSize = BN_bn2mpi(this, NULL);
|
||||
if (nSize < 4)
|
||||
return std::vector<unsigned char>();
|
||||
std::vector<unsigned char> vch(nSize);
|
||||
BN_bn2mpi(this, &vch[0]);
|
||||
vch.erase(vch.begin(), vch.begin() + 4);
|
||||
reverse(vch.begin(), vch.end());
|
||||
return vch;
|
||||
}
|
||||
|
||||
CBigNum& SetCompact(unsigned int nCompact)
|
||||
{
|
||||
unsigned int nSize = nCompact >> 24;
|
||||
std::vector<unsigned char> vch(4 + nSize);
|
||||
vch[3] = nSize;
|
||||
if (nSize >= 1) vch[4] = (nCompact >> 16) & 0xff;
|
||||
if (nSize >= 2) vch[5] = (nCompact >> 8) & 0xff;
|
||||
if (nSize >= 3) vch[6] = (nCompact >> 0) & 0xff;
|
||||
BN_mpi2bn(&vch[0], vch.size(), this);
|
||||
return *this;
|
||||
}
|
||||
CBigNum& SetCompact(unsigned int nCompact)
|
||||
{
|
||||
unsigned int nSize = nCompact >> 24;
|
||||
std::vector<unsigned char> vch(4 + nSize);
|
||||
vch[3] = nSize;
|
||||
if (nSize >= 1) vch[4] = (nCompact >> 16) & 0xff;
|
||||
if (nSize >= 2) vch[5] = (nCompact >> 8) & 0xff;
|
||||
if (nSize >= 3) vch[6] = (nCompact >> 0) & 0xff;
|
||||
BN_mpi2bn(&vch[0], vch.size(), this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
unsigned int GetCompact() const
|
||||
{
|
||||
unsigned int nSize = BN_bn2mpi(this, NULL);
|
||||
std::vector<unsigned char> vch(nSize);
|
||||
nSize -= 4;
|
||||
BN_bn2mpi(this, &vch[0]);
|
||||
unsigned int nCompact = nSize << 24;
|
||||
if (nSize >= 1) nCompact |= (vch[4] << 16);
|
||||
if (nSize >= 2) nCompact |= (vch[5] << 8);
|
||||
if (nSize >= 3) nCompact |= (vch[6] << 0);
|
||||
return nCompact;
|
||||
}
|
||||
unsigned int GetCompact() const
|
||||
{
|
||||
unsigned int nSize = BN_bn2mpi(this, NULL);
|
||||
std::vector<unsigned char> vch(nSize);
|
||||
nSize -= 4;
|
||||
BN_bn2mpi(this, &vch[0]);
|
||||
unsigned int nCompact = nSize << 24;
|
||||
if (nSize >= 1) nCompact |= (vch[4] << 16);
|
||||
if (nSize >= 2) nCompact |= (vch[5] << 8);
|
||||
if (nSize >= 3) nCompact |= (vch[6] << 0);
|
||||
return nCompact;
|
||||
}
|
||||
|
||||
void SetHex(const std::string& str)
|
||||
{
|
||||
// skip 0x
|
||||
const char* psz = str.c_str();
|
||||
while (isspace(*psz))
|
||||
psz++;
|
||||
bool fNegative = false;
|
||||
if (*psz == '-')
|
||||
{
|
||||
fNegative = true;
|
||||
psz++;
|
||||
}
|
||||
if (psz[0] == '0' && tolower(psz[1]) == 'x')
|
||||
psz += 2;
|
||||
while (isspace(*psz))
|
||||
psz++;
|
||||
void SetHex(const std::string& str)
|
||||
{
|
||||
// skip 0x
|
||||
const char* psz = str.c_str();
|
||||
while (isspace(*psz))
|
||||
psz++;
|
||||
bool fNegative = false;
|
||||
if (*psz == '-')
|
||||
{
|
||||
fNegative = true;
|
||||
psz++;
|
||||
}
|
||||
if (psz[0] == '0' && tolower(psz[1]) == 'x')
|
||||
psz += 2;
|
||||
while (isspace(*psz))
|
||||
psz++;
|
||||
|
||||
// hex string to bignum
|
||||
static char phexdigit[256] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0 };
|
||||
*this = 0;
|
||||
while (isxdigit(*psz))
|
||||
{
|
||||
*this <<= 4;
|
||||
int n = phexdigit[(int) *psz++];
|
||||
*this += n;
|
||||
}
|
||||
if (fNegative)
|
||||
*this = 0 - *this;
|
||||
}
|
||||
// hex string to bignum
|
||||
static char phexdigit[256] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0 };
|
||||
*this = 0;
|
||||
while (isxdigit(*psz))
|
||||
{
|
||||
*this <<= 4;
|
||||
int n = phexdigit[(int) *psz++];
|
||||
*this += n;
|
||||
}
|
||||
if (fNegative)
|
||||
*this = 0 - *this;
|
||||
}
|
||||
|
||||
std::string ToString(int nBase=10) const
|
||||
{
|
||||
CAutoBN_CTX pctx;
|
||||
CBigNum bnBase = nBase;
|
||||
CBigNum bn0 = 0;
|
||||
std::string str;
|
||||
CBigNum bn = *this;
|
||||
BN_set_negative(&bn, false);
|
||||
CBigNum dv;
|
||||
CBigNum rem;
|
||||
if (BN_cmp(&bn, &bn0) == 0)
|
||||
return "0";
|
||||
while (BN_cmp(&bn, &bn0) > 0)
|
||||
{
|
||||
if (!BN_div(&dv, &rem, &bn, &bnBase, pctx))
|
||||
throw bignum_error("CBigNum::ToString() : BN_div failed");
|
||||
bn = dv;
|
||||
unsigned int c = rem.getulong();
|
||||
str += "0123456789abcdef"[c];
|
||||
}
|
||||
if (BN_is_negative(this))
|
||||
str += "-";
|
||||
reverse(str.begin(), str.end());
|
||||
return str;
|
||||
}
|
||||
std::string ToString(int nBase=10) const
|
||||
{
|
||||
CAutoBN_CTX pctx;
|
||||
CBigNum bnBase = nBase;
|
||||
CBigNum bn0 = 0;
|
||||
std::string str;
|
||||
CBigNum bn = *this;
|
||||
BN_set_negative(&bn, false);
|
||||
CBigNum dv;
|
||||
CBigNum rem;
|
||||
if (BN_cmp(&bn, &bn0) == 0)
|
||||
return "0";
|
||||
while (BN_cmp(&bn, &bn0) > 0)
|
||||
{
|
||||
if (!BN_div(&dv, &rem, &bn, &bnBase, pctx))
|
||||
throw bignum_error("CBigNum::ToString() : BN_div failed");
|
||||
bn = dv;
|
||||
unsigned int c = rem.getulong();
|
||||
str += "0123456789abcdef"[c];
|
||||
}
|
||||
if (BN_is_negative(this))
|
||||
str += "-";
|
||||
reverse(str.begin(), str.end());
|
||||
return str;
|
||||
}
|
||||
|
||||
std::string GetHex() const
|
||||
{
|
||||
return ToString(16);
|
||||
}
|
||||
std::string GetHex() const
|
||||
{
|
||||
return ToString(16);
|
||||
}
|
||||
/* JED
|
||||
unsigned int GetSerializeSize(int nType=0, int nVersion=VERSION) const
|
||||
{
|
||||
return ::GetSerializeSize(getvch(), nType, nVersion);
|
||||
}
|
||||
unsigned int GetSerializeSize(int nType=0, int nVersion=VERSION) const
|
||||
{
|
||||
return ::GetSerializeSize(getvch(), nType, nVersion);
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void Serialize(Stream& s, int nType=0, int nVersion=VERSION) const
|
||||
{
|
||||
::Serialize(s, getvch(), nType, nVersion);
|
||||
}
|
||||
template<typename Stream>
|
||||
void Serialize(Stream& s, int nType=0, int nVersion=VERSION) const
|
||||
{
|
||||
::Serialize(s, getvch(), nType, nVersion);
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void Unserialize(Stream& s, int nType=0, int nVersion=VERSION)
|
||||
{
|
||||
std::vector<unsigned char> vch;
|
||||
::Unserialize(s, vch, nType, nVersion);
|
||||
setvch(vch);
|
||||
}*/
|
||||
template<typename Stream>
|
||||
void Unserialize(Stream& s, int nType=0, int nVersion=VERSION)
|
||||
{
|
||||
std::vector<unsigned char> vch;
|
||||
::Unserialize(s, vch, nType, nVersion);
|
||||
setvch(vch);
|
||||
}*/
|
||||
|
||||
|
||||
bool operator!() const
|
||||
{
|
||||
return BN_is_zero(this);
|
||||
}
|
||||
bool operator!() const
|
||||
{
|
||||
return BN_is_zero(this);
|
||||
}
|
||||
|
||||
CBigNum& operator+=(const CBigNum& b)
|
||||
{
|
||||
if (!BN_add(this, this, &b))
|
||||
throw bignum_error("CBigNum::operator+= : BN_add failed");
|
||||
return *this;
|
||||
}
|
||||
CBigNum& operator+=(const CBigNum& b)
|
||||
{
|
||||
if (!BN_add(this, this, &b))
|
||||
throw bignum_error("CBigNum::operator+= : BN_add failed");
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBigNum& operator-=(const CBigNum& b)
|
||||
{
|
||||
*this = *this - b;
|
||||
return *this;
|
||||
}
|
||||
CBigNum& operator-=(const CBigNum& b)
|
||||
{
|
||||
*this = *this - b;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBigNum& operator*=(const CBigNum& b)
|
||||
{
|
||||
CAutoBN_CTX pctx;
|
||||
if (!BN_mul(this, this, &b, pctx))
|
||||
throw bignum_error("CBigNum::operator*= : BN_mul failed");
|
||||
return *this;
|
||||
}
|
||||
CBigNum& operator*=(const CBigNum& b)
|
||||
{
|
||||
CAutoBN_CTX pctx;
|
||||
if (!BN_mul(this, this, &b, pctx))
|
||||
throw bignum_error("CBigNum::operator*= : BN_mul failed");
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBigNum& operator/=(const CBigNum& b)
|
||||
{
|
||||
*this = *this / b;
|
||||
return *this;
|
||||
}
|
||||
CBigNum& operator/=(const CBigNum& b)
|
||||
{
|
||||
*this = *this / b;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBigNum& operator%=(const CBigNum& b)
|
||||
{
|
||||
*this = *this % b;
|
||||
return *this;
|
||||
}
|
||||
CBigNum& operator%=(const CBigNum& b)
|
||||
{
|
||||
*this = *this % b;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBigNum& operator<<=(unsigned int shift)
|
||||
{
|
||||
if (!BN_lshift(this, this, shift))
|
||||
throw bignum_error("CBigNum:operator<<= : BN_lshift failed");
|
||||
return *this;
|
||||
}
|
||||
CBigNum& operator<<=(unsigned int shift)
|
||||
{
|
||||
if (!BN_lshift(this, this, shift))
|
||||
throw bignum_error("CBigNum:operator<<= : BN_lshift failed");
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBigNum& operator>>=(unsigned int shift)
|
||||
{
|
||||
// Note: BN_rshift segfaults on 64-bit if 2^shift is greater than the number
|
||||
// if built on ubuntu 9.04 or 9.10, probably depends on version of openssl
|
||||
CBigNum a = 1;
|
||||
a <<= shift;
|
||||
if (BN_cmp(&a, this) > 0)
|
||||
{
|
||||
*this = 0;
|
||||
return *this;
|
||||
}
|
||||
CBigNum& operator>>=(unsigned int shift)
|
||||
{
|
||||
// Note: BN_rshift segfaults on 64-bit if 2^shift is greater than the number
|
||||
// if built on ubuntu 9.04 or 9.10, probably depends on version of openssl
|
||||
CBigNum a = 1;
|
||||
a <<= shift;
|
||||
if (BN_cmp(&a, this) > 0)
|
||||
{
|
||||
*this = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
if (!BN_rshift(this, this, shift))
|
||||
throw bignum_error("CBigNum:operator>>= : BN_rshift failed");
|
||||
return *this;
|
||||
}
|
||||
if (!BN_rshift(this, this, shift))
|
||||
throw bignum_error("CBigNum:operator>>= : BN_rshift failed");
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
CBigNum& operator++()
|
||||
{
|
||||
// prefix operator
|
||||
if (!BN_add(this, this, BN_value_one()))
|
||||
throw bignum_error("CBigNum::operator++ : BN_add failed");
|
||||
return *this;
|
||||
}
|
||||
CBigNum& operator++()
|
||||
{
|
||||
// prefix operator
|
||||
if (!BN_add(this, this, BN_value_one()))
|
||||
throw bignum_error("CBigNum::operator++ : BN_add failed");
|
||||
return *this;
|
||||
}
|
||||
|
||||
const CBigNum operator++(int)
|
||||
{
|
||||
// postfix operator
|
||||
const CBigNum ret = *this;
|
||||
++(*this);
|
||||
return ret;
|
||||
}
|
||||
const CBigNum operator++(int)
|
||||
{
|
||||
// postfix operator
|
||||
const CBigNum ret = *this;
|
||||
++(*this);
|
||||
return ret;
|
||||
}
|
||||
|
||||
CBigNum& operator--()
|
||||
{
|
||||
// prefix operator
|
||||
CBigNum r;
|
||||
if (!BN_sub(&r, this, BN_value_one()))
|
||||
throw bignum_error("CBigNum::operator-- : BN_sub failed");
|
||||
*this = r;
|
||||
return *this;
|
||||
}
|
||||
CBigNum& operator--()
|
||||
{
|
||||
// prefix operator
|
||||
CBigNum r;
|
||||
if (!BN_sub(&r, this, BN_value_one()))
|
||||
throw bignum_error("CBigNum::operator-- : BN_sub failed");
|
||||
*this = r;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const CBigNum operator--(int)
|
||||
{
|
||||
// postfix operator
|
||||
const CBigNum ret = *this;
|
||||
--(*this);
|
||||
return ret;
|
||||
}
|
||||
const CBigNum operator--(int)
|
||||
{
|
||||
// postfix operator
|
||||
const CBigNum ret = *this;
|
||||
--(*this);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
friend inline const CBigNum operator-(const CBigNum& a, const CBigNum& b);
|
||||
friend inline const CBigNum operator/(const CBigNum& a, const CBigNum& b);
|
||||
friend inline const CBigNum operator%(const CBigNum& a, const CBigNum& b);
|
||||
friend inline const CBigNum operator-(const CBigNum& a, const CBigNum& b);
|
||||
friend inline const CBigNum operator/(const CBigNum& a, const CBigNum& b);
|
||||
friend inline const CBigNum operator%(const CBigNum& a, const CBigNum& b);
|
||||
};
|
||||
|
||||
|
||||
|
||||
inline const CBigNum operator+(const CBigNum& a, const CBigNum& b)
|
||||
{
|
||||
CBigNum r;
|
||||
if (!BN_add(&r, &a, &b))
|
||||
throw bignum_error("CBigNum::operator+ : BN_add failed");
|
||||
return r;
|
||||
CBigNum r;
|
||||
if (!BN_add(&r, &a, &b))
|
||||
throw bignum_error("CBigNum::operator+ : BN_add failed");
|
||||
return r;
|
||||
}
|
||||
|
||||
inline const CBigNum operator-(const CBigNum& a, const CBigNum& b)
|
||||
{
|
||||
CBigNum r;
|
||||
if (!BN_sub(&r, &a, &b))
|
||||
throw bignum_error("CBigNum::operator- : BN_sub failed");
|
||||
return r;
|
||||
CBigNum r;
|
||||
if (!BN_sub(&r, &a, &b))
|
||||
throw bignum_error("CBigNum::operator- : BN_sub failed");
|
||||
return r;
|
||||
}
|
||||
|
||||
inline const CBigNum operator-(const CBigNum& a)
|
||||
{
|
||||
CBigNum r(a);
|
||||
BN_set_negative(&r, !BN_is_negative(&r));
|
||||
return r;
|
||||
CBigNum r(a);
|
||||
BN_set_negative(&r, !BN_is_negative(&r));
|
||||
return r;
|
||||
}
|
||||
|
||||
inline const CBigNum operator*(const CBigNum& a, const CBigNum& b)
|
||||
{
|
||||
CAutoBN_CTX pctx;
|
||||
CBigNum r;
|
||||
if (!BN_mul(&r, &a, &b, pctx))
|
||||
throw bignum_error("CBigNum::operator* : BN_mul failed");
|
||||
return r;
|
||||
CAutoBN_CTX pctx;
|
||||
CBigNum r;
|
||||
if (!BN_mul(&r, &a, &b, pctx))
|
||||
throw bignum_error("CBigNum::operator* : BN_mul failed");
|
||||
return r;
|
||||
}
|
||||
|
||||
inline const CBigNum operator/(const CBigNum& a, const CBigNum& b)
|
||||
{
|
||||
CAutoBN_CTX pctx;
|
||||
CBigNum r;
|
||||
if (!BN_div(&r, NULL, &a, &b, pctx))
|
||||
throw bignum_error("CBigNum::operator/ : BN_div failed");
|
||||
return r;
|
||||
CAutoBN_CTX pctx;
|
||||
CBigNum r;
|
||||
if (!BN_div(&r, NULL, &a, &b, pctx))
|
||||
throw bignum_error("CBigNum::operator/ : BN_div failed");
|
||||
return r;
|
||||
}
|
||||
|
||||
inline const CBigNum operator%(const CBigNum& a, const CBigNum& b)
|
||||
{
|
||||
CAutoBN_CTX pctx;
|
||||
CBigNum r;
|
||||
if (!BN_mod(&r, &a, &b, pctx))
|
||||
throw bignum_error("CBigNum::operator% : BN_div failed");
|
||||
return r;
|
||||
CAutoBN_CTX pctx;
|
||||
CBigNum r;
|
||||
if (!BN_mod(&r, &a, &b, pctx))
|
||||
throw bignum_error("CBigNum::operator% : BN_div failed");
|
||||
return r;
|
||||
}
|
||||
|
||||
inline const CBigNum operator<<(const CBigNum& a, unsigned int shift)
|
||||
{
|
||||
CBigNum r;
|
||||
if (!BN_lshift(&r, &a, shift))
|
||||
throw bignum_error("CBigNum:operator<< : BN_lshift failed");
|
||||
return r;
|
||||
CBigNum r;
|
||||
if (!BN_lshift(&r, &a, shift))
|
||||
throw bignum_error("CBigNum:operator<< : BN_lshift failed");
|
||||
return r;
|
||||
}
|
||||
|
||||
inline const CBigNum operator>>(const CBigNum& a, unsigned int shift)
|
||||
{
|
||||
CBigNum r = a;
|
||||
r >>= shift;
|
||||
return r;
|
||||
CBigNum r = a;
|
||||
r >>= shift;
|
||||
return r;
|
||||
}
|
||||
|
||||
inline bool operator==(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) == 0); }
|
||||
@@ -540,3 +512,5 @@ inline bool operator<(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a,
|
||||
inline bool operator>(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) > 0); }
|
||||
|
||||
#endif
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
79
src/key.h
79
src/key.h
@@ -128,25 +128,45 @@ public:
|
||||
static EC_KEY* GenerateRootPubKey(BIGNUM* pubGenerator);
|
||||
static EC_KEY* GeneratePublicDeterministicKey(const NewcoinAddress& generator, int n);
|
||||
static EC_KEY* GeneratePrivateDeterministicKey(const NewcoinAddress& family, const BIGNUM* rootPriv, int n);
|
||||
static EC_KEY* GeneratePrivateDeterministicKey(const NewcoinAddress& family, const uint256& rootPriv, int n);
|
||||
|
||||
CKey(const uint128& passPhrase) : fSet(true)
|
||||
CKey(const uint128& passPhrase) : fSet(false)
|
||||
{
|
||||
pkey = GenerateRootDeterministicKey(passPhrase);
|
||||
fSet = true;
|
||||
assert(pkey);
|
||||
}
|
||||
|
||||
CKey(const NewcoinAddress& generator, int n) : fSet(true)
|
||||
CKey(const NewcoinAddress& generator, int n) : fSet(false)
|
||||
{ // public deterministic key
|
||||
pkey = GeneratePublicDeterministicKey(generator, n);
|
||||
fSet = true;
|
||||
assert(pkey);
|
||||
}
|
||||
|
||||
CKey(const NewcoinAddress& base, const BIGNUM* rootPrivKey, int n) : fSet(true)
|
||||
CKey(const NewcoinAddress& base, const BIGNUM* rootPrivKey, int n) : fSet(false)
|
||||
{ // private deterministic key
|
||||
pkey = GeneratePrivateDeterministicKey(base, rootPrivKey, n);
|
||||
fSet = true;
|
||||
assert(pkey);
|
||||
}
|
||||
|
||||
CKey(const uint256& privateKey) : pkey(NULL), fSet(false)
|
||||
{
|
||||
SetPrivateKeyU(privateKey);
|
||||
}
|
||||
|
||||
#if 0
|
||||
CKey(const NewcoinAddress& masterKey, int keyNum, bool isPublic) : pkey(NULL), fSet(false)
|
||||
{
|
||||
if (isPublic)
|
||||
SetPubSeq(masterKey, keyNum);
|
||||
else
|
||||
SetPrivSeq(masterKey, keyNum); // broken, need seed
|
||||
fSet = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool IsNull() const
|
||||
{
|
||||
return !fSet;
|
||||
@@ -161,7 +181,7 @@ public:
|
||||
}
|
||||
|
||||
bool SetPrivKey(const CPrivKey& vchPrivKey)
|
||||
{
|
||||
{ // DEPRECATED
|
||||
const unsigned char* pbegin = &vchPrivKey[0];
|
||||
if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
|
||||
return false;
|
||||
@@ -171,7 +191,7 @@ public:
|
||||
}
|
||||
|
||||
bool SetSecret(const CSecret& vchSecret)
|
||||
{
|
||||
{ // DEPRECATED
|
||||
EC_KEY_free(pkey);
|
||||
pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
if (pkey == NULL)
|
||||
@@ -189,7 +209,7 @@ public:
|
||||
}
|
||||
|
||||
CSecret GetSecret()
|
||||
{
|
||||
{ // DEPRECATED
|
||||
CSecret vchRet;
|
||||
vchRet.resize(32);
|
||||
const BIGNUM *bn = EC_KEY_get0_private_key(pkey);
|
||||
@@ -203,10 +223,55 @@ public:
|
||||
}
|
||||
|
||||
BIGNUM* GetSecretBN() const
|
||||
{
|
||||
{ // DEPRECATED
|
||||
return BN_dup(EC_KEY_get0_private_key(pkey));
|
||||
}
|
||||
|
||||
void GetPrivateKeyU(uint256& privKey)
|
||||
{
|
||||
const BIGNUM* bn = EC_KEY_get0_private_key(pkey);
|
||||
if (bn == NULL)
|
||||
throw key_error("CKey::GetPrivateKeyU: EC_KEY_get0_private_key failed");
|
||||
privKey.zero();
|
||||
BN_bn2bin(bn, privKey.begin() + (privKey.size() - BN_num_bytes(bn)));
|
||||
}
|
||||
|
||||
void SetPrivateKeyU(const uint256& key)
|
||||
{
|
||||
BIGNUM* bn = BN_bin2bn(key.begin(), key.size(), NULL);
|
||||
if (!EC_KEY_set_private_key(pkey, bn))
|
||||
{
|
||||
BN_clear_free(bn);
|
||||
throw key_error("CKey::SetPrivateKeyU: EC_KEY_set_private_key failed");
|
||||
}
|
||||
fSet = true;
|
||||
BN_clear_free(bn);
|
||||
}
|
||||
|
||||
void SetPubSeq(const NewcoinAddress& masterKey, int keyNum)
|
||||
{
|
||||
EC_KEY* key = GeneratePublicDeterministicKey(masterKey, keyNum);
|
||||
if (key == NULL)
|
||||
throw key_error("CKey::SetPubSeq: GenPubDetKey failed");
|
||||
if (pkey != NULL)
|
||||
EC_KEY_free(pkey);
|
||||
pkey = key;
|
||||
fSet = true;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void SetPrivSeq(const NewcoinAddress& masterKey, int keyNum)
|
||||
{ // broken: Need the seed
|
||||
uint256 privKey;
|
||||
EC_KEY* key = GeneratePrivateDeterministicKey(masterKey, masterKey.getFamilyGeneratorU(), keyNum);
|
||||
privKey.zero();
|
||||
if (pkey != NULL)
|
||||
EC_KEY_free(pkey);
|
||||
pkey = key;
|
||||
fSet = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
CPrivKey GetPrivKey()
|
||||
{
|
||||
unsigned int nSize = i2d_ECPrivateKey(pkey, NULL);
|
||||
|
||||
Reference in New Issue
Block a user