Merge branch 'master' of github.com:jedmccaleb/NewCoin

This commit is contained in:
jed
2012-06-09 13:37:59 -07:00
26 changed files with 815 additions and 670 deletions

View File

@@ -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;

View File

@@ -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; }

View File

@@ -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
View 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
View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -1,12 +0,0 @@
#include "Hanko.h"
#include <boost/foreach.hpp>
using namespace boost;
using namespace std;
Hanko::Hanko()
{
}
// vim:ts=4

View File

@@ -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

View File

@@ -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("';");

View File

@@ -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;

View File

@@ -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

View File

@@ -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) { ; }

View File

@@ -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()

View File

@@ -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);

View File

@@ -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");

View File

@@ -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;

View File

@@ -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";
}

View File

@@ -69,4 +69,4 @@ public:
};
#endif // HTTP_REQUEST_PARSER_HPP
#endif // HTTP_REQUEST_PARSER_HPP

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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);