From 95e52d5740a09e20761b1d15d77309c1f464fbd4 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 8 Jun 2012 04:09:22 -0700 Subject: [PATCH 01/25] Typo was causing this code not to work. --- src/HashedObject.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/HashedObject.cpp b/src/HashedObject.cpp index 0da7c29446..fd2aa94ef7 100644 --- a/src/HashedObject.cpp +++ b/src/HashedObject.cpp @@ -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& 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("';"); From 03d90e4f56a33d395479064045a14b8cb05b6eb6 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 8 Jun 2012 04:34:14 -0700 Subject: [PATCH 02/25] Whitespace. --- src/TransactionMaster.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/TransactionMaster.cpp b/src/TransactionMaster.cpp index 91f0d7d9e9..8cddedf819 100644 --- a/src/TransactionMaster.cpp +++ b/src/TransactionMaster.cpp @@ -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; } From 2c5f91a38497bf0161ae30ea07a07ecb3b859aa2 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 8 Jun 2012 04:34:23 -0700 Subject: [PATCH 03/25] Add comment. --- src/LedgerAcquire.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LedgerAcquire.h b/src/LedgerAcquire.h index f06c4dbabf..211567d320 100644 --- a/src/LedgerAcquire.h +++ b/src/LedgerAcquire.h @@ -60,7 +60,7 @@ typedef std::vector VUC; class THSyncFilter : public SHAMapSyncFilter { protected: - NodeCache* mCache; + NodeCache* mCache; // holds nodes we see during the consensus process public: THSyncFilter(NodeCache* cache) : mCache(cache) { ; } From 261b34e0c337e2586d166ed526c36d04e2f00dbd Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 8 Jun 2012 04:34:32 -0700 Subject: [PATCH 04/25] Bugfixes. If an object lost its last external reference while we were refreshing it, boom. New store/retrieve functions for objects that aren't held through shared pointers. --- src/TaggedCache.h | 63 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 48 insertions(+), 15 deletions(-) diff --git a/src/TaggedCache.h b/src/TaggedCache.h index 6f79e172c5..a53b7d3dc5 100644 --- a/src/TaggedCache.h +++ b/src/TaggedCache.h @@ -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 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& data); + bool store(const key_type& key, const c_Data& data); boost::shared_ptr 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 void TaggedCache::sweep while (cit != mCache.end()) { if (cit->second->second.first < target) - mCache.erase(cit++); + { + typename boost::unordered_map::iterator tmp = cit++; + mCache.erase(tmp); + } else ++cit; } @@ -95,7 +106,10 @@ template void TaggedCache::sweep while (mit != mMap.end()) { if (mit->second->expired()) - mMap.erase(mit++); + { + typename boost::unordered_map::iterator tmp = mit++; + mMap.erase(mit); + } else ++mit; } } @@ -149,15 +163,16 @@ bool TaggedCache::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 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::iterator cit = mCache.find(key); @@ -171,28 +186,46 @@ bool TaggedCache::canonicalize(const key_type& key, boost::shared template boost::shared_ptr TaggedCache::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::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 data = mit->second.lock(); + boost::shared_ptr 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::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 +bool TaggedCache::store(const key_type& key, const c_Data& data) +{ + if (!canonicalize(key, boost::shared_ptr(data))) + return false; + return true; +} + +template +bool TaggedCache::retrieve(const key_type& key, c_Data& data) +{ // retrieve the value of the stored data + boost::shared_ptr dataPtr = fetch(key); + if (!dataPtr) + return false; + data = *dataPtr; + return true; } #endif From 4b79e7dca80795f334dc775103b5ac07c3919af5 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 8 Jun 2012 05:09:23 -0700 Subject: [PATCH 05/25] New canonical transaction order code. Tested and working. CanonicalTXSet acts much like a map, but sorts the transactions in a simple order that makes them take fewer passed. --- src/CanonicalTXSet.cpp | 53 +++++++++++++++++++++++++++++++++++++++++ src/CanonicalTXSet.h | 53 +++++++++++++++++++++++++++++++++++++++++ src/LedgerConsensus.cpp | 16 ++++++------- src/LedgerConsensus.h | 3 ++- 4 files changed, 116 insertions(+), 9 deletions(-) create mode 100644 src/CanonicalTXSet.cpp create mode 100644 src/CanonicalTXSet.h diff --git a/src/CanonicalTXSet.cpp b/src/CanonicalTXSet.cpp new file mode 100644 index 0000000000..93ed79ccd4 --- /dev/null +++ b/src/CanonicalTXSet.cpp @@ -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); +} + + diff --git a/src/CanonicalTXSet.h b/src/CanonicalTXSet.h new file mode 100644 index 0000000000..f78c580cd9 --- /dev/null +++ b/src/CanonicalTXSet.h @@ -0,0 +1,53 @@ +#ifndef __CANONICAL_TX_SET_ +#define __CANONICAL_TX_SET_ + +#include + +#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::iterator iterator; + typedef std::map::const_iterator const_iterator; + +protected: + uint256 mSetHash; + std::map 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 diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index 4232c57e24..72190d24a0 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -577,7 +577,7 @@ void LedgerConsensus::Saccept(boost::shared_ptr This, SHAMap::p } void LedgerConsensus::applyTransactions(SHAMap::pointer set, Ledger::pointer ledger, - std::list& failedTransactions) + CanonicalTXSet& failedTransactions) { TransactionEngine engine(ledger); @@ -620,16 +620,17 @@ void LedgerConsensus::applyTransactions(SHAMap::pointer set, Ledger::pointer led do { successes = 0; - std::list::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); @@ -665,7 +666,7 @@ void LedgerConsensus::accept(SHAMap::pointer set) } #endif - std::list failedTransactions; + CanonicalTXSet failedTransactions(set->getHash()); applyTransactions(set, newLCL, failedTransactions); newLCL->setClosed(); newLCL->setAccepted(); @@ -703,8 +704,7 @@ 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; diff --git a/src/LedgerConsensus.h b/src/LedgerConsensus.h index 820d65a65c..5595435f5a 100644 --- a/src/LedgerConsensus.h +++ b/src/LedgerConsensus.h @@ -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 { // 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& failedTransactions); + CanonicalTXSet& failedTransactions); // manipulating our own position void takeInitialPosition(Ledger::pointer initialLedger); From 240971775b6d0788536fb52428393d8ac2451481 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 8 Jun 2012 05:31:43 -0700 Subject: [PATCH 06/25] Dead code. --- src/Confirmation.h | 44 -------------------------------------------- 1 file changed, 44 deletions(-) delete mode 100644 src/Confirmation.h diff --git a/src/Confirmation.h b/src/Confirmation.h deleted file mode 100644 index a47e3fa1e5..0000000000 --- a/src/Confirmation.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef __CONFIRMATION__ -#define __CONFIRMATION__ - -#include "../obj/src/newcoin.pb.h" -#include "uint256.h" -#include - -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 pointer; - -private: - uint256 mID; - uint160 mHanko; - uint64 mTimestamp; - ConfirmationStatus mStatus; - bool mConflicts; - std::vector mSignature; - -public: - Confirmation(); - Confirmation(const uint256 &id); - Confirmation(const std::vector 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 From 85d31c240f61425b51322c4c4f7137673847f7c9 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 8 Jun 2012 05:31:51 -0700 Subject: [PATCH 07/25] Dead code. --- src/Avalanche.h | 36 ------------------------------------ 1 file changed, 36 deletions(-) delete mode 100644 src/Avalanche.h diff --git a/src/Avalanche.h b/src/Avalanche.h deleted file mode 100644 index 301188edd4..0000000000 --- a/src/Avalanche.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef __AVALANCHE__ -#define __AVALANCHE__ - -#include -#include - -#include "Transaction.h" - -class DisputedTransaction -{ -protected: - Transaction::pointer mTransaction; -// std::vector mNodesIncluding; -// std::vector 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 mTxByID; - std::set mTxInASOrder; - -public: - Avalanche(SHAMap::pointer ourLedger); -}; - -#endif From 398ce4b95f099483e4c135e5bc35ad2ae4096d6f Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 8 Jun 2012 05:42:02 -0700 Subject: [PATCH 08/25] Whitespace. --- src/RequestParser.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/RequestParser.h b/src/RequestParser.h index 9e973dd143..f0906daa88 100644 --- a/src/RequestParser.h +++ b/src/RequestParser.h @@ -69,4 +69,4 @@ public: }; -#endif // HTTP_REQUEST_PARSER_HPP \ No newline at end of file +#endif // HTTP_REQUEST_PARSER_HPP From 17c57e781956028ad4b7de999116a1e981bdbbf0 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 8 Jun 2012 15:55:52 -0700 Subject: [PATCH 09/25] Add skeleton of new code. --- src/key.h | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/key.h b/src/key.h index b9fcd775cb..6caad3db53 100644 --- a/src/key.h +++ b/src/key.h @@ -147,6 +147,11 @@ public: assert(pkey); } + CKey(const uint256& pKey) : fSet(false) + { + SetPrivateKey(pKey); + } + bool IsNull() const { return !fSet; @@ -161,7 +166,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 +176,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 +194,7 @@ public: } CSecret GetSecret() - { + { // DEPRECATED CSecret vchRet; vchRet.resize(32); const BIGNUM *bn = EC_KEY_get0_private_key(pkey); @@ -202,6 +207,16 @@ public: return vchRet; } + uint256 GetPrivateKeyU(void) + { + // WRITEME + } + + void SetPrivateKeyU(const uint256& key) + { + // WRITEME + } + BIGNUM* GetSecretBN() const { return BN_dup(EC_KEY_get0_private_key(pkey)); From 0f16669987cc71ad3f114e01f4237bf4c3b15fa9 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 8 Jun 2012 15:56:41 -0700 Subject: [PATCH 10/25] Bufix. --- src/key.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/key.h b/src/key.h index 6caad3db53..2d1eeb253a 100644 --- a/src/key.h +++ b/src/key.h @@ -149,7 +149,7 @@ public: CKey(const uint256& pKey) : fSet(false) { - SetPrivateKey(pKey); + SetPrivateKeyU(pKey); } bool IsNull() const @@ -210,11 +210,13 @@ public: uint256 GetPrivateKeyU(void) { // WRITEME + throw 0; } void SetPrivateKeyU(const uint256& key) { // WRITEME + throw 0; } BIGNUM* GetSecretBN() const From b70cdd7fa4b24c838e0688386c1337bdc7790c4a Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 8 Jun 2012 16:13:24 -0700 Subject: [PATCH 11/25] Make Get/Set PrivateKeyU work. --- src/key.h | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/key.h b/src/key.h index 2d1eeb253a..10ab23a237 100644 --- a/src/key.h +++ b/src/key.h @@ -207,21 +207,30 @@ public: return vchRet; } - uint256 GetPrivateKeyU(void) + BIGNUM* GetSecretBN() const + { // DEPRECATED + return BN_dup(EC_KEY_get0_private_key(pkey)); + } + + void GetPrivateKeyU(uint256& privKey) { - // WRITEME - throw 0; + 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) { - // WRITEME - throw 0; - } - - BIGNUM* GetSecretBN() const - { - return BN_dup(EC_KEY_get0_private_key(pkey)); + BIGNUM* bn = BN_bin2bn(key.begin(), key.size(), NULL); + if (!EC_KEY_set_private_key(pkey, bn)) + { + BN_free(bn); + throw key_error("CKey::SetPrivateKeyU: EC_KEY_set_private_key failed"); + } + fSet = true; + BN_free(bn); } CPrivKey GetPrivKey() From ea5ae2a113c53dfe27b299a319cbf3c2707892c3 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 8 Jun 2012 18:13:13 -0700 Subject: [PATCH 12/25] Structures for tracking transactions by which accounts they affect. --- src/Application.cpp | 25 ++++++++++++++----------- src/Application.h | 3 ++- src/DBInit.cpp | 24 +++++++++++++++++++----- 3 files changed, 35 insertions(+), 17 deletions(-) diff --git a/src/Application.cpp b/src/Application.cpp index 37ca4f3952..5b27580c97 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -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(&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; diff --git a/src/Application.h b/src/Application.h index 2c1fd6c006..546d0aad51 100644 --- a/src/Application.h +++ b/src/Application.h @@ -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; } diff --git a/src/DBInit.cpp b/src/DBInit.cpp index 9f1f3a92a8..470d28fb31 100644 --- a/src/DBInit.cpp +++ b/src/DBInit.cpp @@ -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 From eb2ce22eff2e64ebd30a80d0edc043d27695075a Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 8 Jun 2012 20:45:20 -0700 Subject: [PATCH 13/25] Our bit order change to uint256 broke the logic used to convert CBigNum's to and from uint256's. This code is really awful though. We probably should just re-implement what we need of it. (Which is very little.) It looks like the author just didn't know about BN_bin2bn and BIN_bn2bin. --- src/bignum.h | 44 ++++++++------------------------------------ 1 file changed, 8 insertions(+), 36 deletions(-) diff --git a/src/bignum.h b/src/bignum.h index 01e614a79c..e11de65026 100644 --- a/src/bignum.h +++ b/src/bignum.h @@ -186,47 +186,19 @@ public: BN_mpi2bn(pch, p - pch, this); } - void setuint256(uint256 n) + void setuint256(const 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); + BN_bin2bn(n.begin(), n.size(), NULL); } uint256 getuint256() { - unsigned int nSize = BN_bn2mpi(this, NULL); - if (nSize < 4) - return 0; - std::vector 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 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& vch) From 51d0a44cdd741319cba286a32e1186616d5c61a8 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 8 Jun 2012 20:46:29 -0700 Subject: [PATCH 14/25] Whitespace --- src/bignum.h | 772 +++++++++++++++++++++++++-------------------------- 1 file changed, 386 insertions(+), 386 deletions(-) diff --git a/src/bignum.h b/src/bignum.h index e11de65026..c02c3b6a78 100644 --- a/src/bignum.h +++ b/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,454 +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& vch) - { - BN_init(this); - setvch(vch); - } + explicit CBigNum(const std::vector& 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(const uint256& n) - { - BN_bin2bn(n.begin(), n.size(), NULL); - } + void setuint256(const uint256& n) + { + BN_bin2bn(n.begin(), n.size(), NULL); + } - uint256 getuint256() - { + 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; - } + return ret; + } - void setvch(const std::vector& vch) - { - std::vector 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& vch) + { + std::vector 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 getvch() const - { - unsigned int nSize = BN_bn2mpi(this, NULL); - if (nSize < 4) - return std::vector(); - std::vector vch(nSize); - BN_bn2mpi(this, &vch[0]); - vch.erase(vch.begin(), vch.begin() + 4); - reverse(vch.begin(), vch.end()); - return vch; - } + std::vector getvch() const + { + unsigned int nSize = BN_bn2mpi(this, NULL); + if (nSize < 4) + return std::vector(); + std::vector 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 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 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 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 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 - void Serialize(Stream& s, int nType=0, int nVersion=VERSION) const - { - ::Serialize(s, getvch(), nType, nVersion); - } + template + void Serialize(Stream& s, int nType=0, int nVersion=VERSION) const + { + ::Serialize(s, getvch(), nType, nVersion); + } - template - void Unserialize(Stream& s, int nType=0, int nVersion=VERSION) - { - std::vector vch; - ::Unserialize(s, vch, nType, nVersion); - setvch(vch); - }*/ + template + void Unserialize(Stream& s, int nType=0, int nVersion=VERSION) + { + std::vector 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); } From f92d5b6cebf6bac303f4db68d96ee22c192f4c79 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 8 Jun 2012 20:47:05 -0700 Subject: [PATCH 15/25] Untie the dependencies between NewcoinAddress and BIGNUM. --- src/DeterministicKeys.cpp | 20 +++++++++++------ src/NewcoinAddress.cpp | 21 ++++++++++++++++++ src/NewcoinAddress.h | 3 ++- src/key.h | 45 ++++++++++++++++++++++++++++++++++----- 4 files changed, 76 insertions(+), 13 deletions(-) diff --git a/src/DeterministicKeys.cpp b/src/DeterministicKeys.cpp index e6717540bc..75e36bdc21 100644 --- a/src/DeterministicKeys.cpp +++ b/src/DeterministicKeys.cpp @@ -144,14 +144,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 +164,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 +194,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 +217,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(&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 +254,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); diff --git a/src/NewcoinAddress.cpp b/src/NewcoinAddress.cpp index 05179cfd06..715863c3e7 100644 --- a/src/NewcoinAddress.cpp +++ b/src/NewcoinAddress.cpp @@ -503,12 +503,33 @@ BIGNUM* NewcoinAddress::getFamilyGeneratorBN() const throw std::runtime_error(str(boost::format("bad source: %d") % int(nVersion))); } + assert(vchData.size() <= (256 / 8)); BIGNUM* ret = BN_bin2bn(&vchData[0], vchData.size(), NULL); assert(ret); return ret; } +uint256 NewcoinAddress::getFamilyGeneratorU() const +{ + switch (nVersion) { + case VER_NONE: + throw std::runtime_error("unset source"); + + case VER_FAMILY_GENERATOR: + // Do nothing. + break; + + default: + throw std::runtime_error(str(boost::format("bad source: %d") % int(nVersion))); + } + + assert(vchData.size() <= (256 / 8)); + uint256 ret; + memcpy(ret.begin() + (ret.size() - vchData.size()), &vchData[0], vchData.size()); + return ret; +} + const std::vector& NewcoinAddress::getFamilyGenerator() const { switch (nVersion) { diff --git a/src/NewcoinAddress.h b/src/NewcoinAddress.h index daf30cdb9c..8e3069d722 100644 --- a/src/NewcoinAddress.h +++ b/src/NewcoinAddress.h @@ -135,7 +135,8 @@ public: // Family Generators // Use to generate a master or regular family. // - BIGNUM* getFamilyGeneratorBN() const; + BIGNUM* getFamilyGeneratorBN() const; // DEPRECATED + uint256 getFamilyGeneratorU() const; const std::vector& getFamilyGenerator() const; std::string humanFamilyGenerator() const; diff --git a/src/key.h b/src/key.h index 10ab23a237..c287c51490 100644 --- a/src/key.h +++ b/src/key.h @@ -128,28 +128,41 @@ 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& pKey) : fSet(false) + CKey(const uint256& privateKey) : pkey(NULL), fSet(false) { - SetPrivateKeyU(pKey); + SetPrivateKeyU(privateKey); + } + + CKey(const NewcoinAddress& masterKey, int keyNum, bool isPublic) : pkey(NULL), fSet(false) + { + if (isPublic) + SetPubSeq(masterKey, keyNum); + else + SetPrivSeq(masterKey, keyNum); + fSet = true; } bool IsNull() const @@ -233,6 +246,28 @@ public: BN_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; + } + + void SetPrivSeq(const NewcoinAddress& masterKey, int keyNum) + { + uint256 privKey; + EC_KEY* key = GeneratePrivateDeterministicKey(masterKey, masterKey.getFamilyGeneratorU(), keyNum); + privKey.zero(); + if (pkey != NULL) + EC_KEY_free(pkey); + pkey = key; + fSet = true; + } + CPrivKey GetPrivKey() { unsigned int nSize = i2d_ECPrivateKey(pkey, NULL); From 349272cddcef1dc431725bcbcd00de40efcb25b3 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 8 Jun 2012 20:48:22 -0700 Subject: [PATCH 16/25] Missing from previous. --- src/bignum.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/bignum.h b/src/bignum.h index c02c3b6a78..74c87aa73f 100644 --- a/src/bignum.h +++ b/src/bignum.h @@ -512,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 From bb54bf8c1db42be2c5002f6c5a5e46e074533229 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 8 Jun 2012 22:21:16 -0700 Subject: [PATCH 17/25] Change some BN_free to BN_clear_free --- src/DeterministicKeys.cpp | 12 ++++++------ src/key.h | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/DeterministicKeys.cpp b/src/DeterministicKeys.cpp index 75e36bdc21..2373fe52c1 100644 --- a/src/DeterministicKeys.cpp +++ b/src/DeterministicKeys.cpp @@ -78,7 +78,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 +87,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); @@ -272,19 +272,19 @@ EC_KEY* CKey::GeneratePrivateDeterministicKey(const NewcoinAddress& pubGen, 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); diff --git a/src/key.h b/src/key.h index c287c51490..38a47e8c26 100644 --- a/src/key.h +++ b/src/key.h @@ -239,11 +239,11 @@ public: BIGNUM* bn = BN_bin2bn(key.begin(), key.size(), NULL); if (!EC_KEY_set_private_key(pkey, bn)) { - BN_free(bn); + BN_clear_free(bn); throw key_error("CKey::SetPrivateKeyU: EC_KEY_set_private_key failed"); } fSet = true; - BN_free(bn); + BN_clear_free(bn); } void SetPubSeq(const NewcoinAddress& masterKey, int keyNum) From 40748df5054e043880952fc29cc9e72f574b72f6 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sat, 9 Jun 2012 01:33:13 -0700 Subject: [PATCH 18/25] Store completed transactions in the SQL database, indexed by accounts affected and ledger seq. --- src/LedgerConsensus.cpp | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index 72190d24a0..bd15efe5f9 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -654,6 +654,7 @@ void LedgerConsensus::accept(SHAMap::pointer set) Log(lsDEBUG) << "Previous LCL " << mPreviousLedger->getHash().GetHex(); Ledger::pointer newLCL = boost::make_shared(false, boost::ref(*mPreviousLedger)); + uint32 newLedgerSeq = newLCL->getLedgerSeq(); #ifdef DEBUG Json::StyledStreamWriter ssw; @@ -707,6 +708,7 @@ void LedgerConsensus::accept(SHAMap::pointer set) 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 validation = v.getSigned(); newcoin::TMValidation val; @@ -727,6 +727,34 @@ void LedgerConsensus::accept(SHAMap::pointer set) theApp->getConnectionPool().relayMessage(NULL, boost::make_shared(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 accts = txn.getAffectedAccounts(); + + std::string sql = "INSERT INTO AccountTransactions (TransID,Account,LedgerSeq) VALUES "; + bool first = true; + for (std::vector::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(newLedgerSeq); + sql += ")"; + } + sql += ";"; + db->executeSQL(sql); + } + db->executeSQL("COMMIT TRANSACTION"); } void LedgerConsensus::endConsensus() From 5dcc7908dd7d759467b23bfd5c2909220e1ee926 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sat, 9 Jun 2012 01:49:18 -0700 Subject: [PATCH 19/25] ledger [id|current|lastclosed] [full] Implementation is not 100% complete yet. --- src/Ledger.h | 1 + src/RPCServer.cpp | 44 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/Ledger.h b/src/Ledger.h index 9d82641295..cb9c4cfd15 100644 --- a/src/Ledger.h +++ b/src/Ledger.h @@ -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 { // The basic Ledger structure, can be opened, closed, or synching diff --git a/src/RPCServer.cpp b/src/RPCServer.cpp index b071c83c82..f325ce6a81 100644 --- a/src/RPCServer.cpp +++ b/src/RPCServer.cpp @@ -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(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 | [] From 424582a2193c9c9885dae5f0d4402ed61ea48598 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sat, 9 Jun 2012 01:50:52 -0700 Subject: [PATCH 20/25] Dead code. --- src/Hanko.cpp | 12 ---------- src/Hanko.h | 65 --------------------------------------------------- 2 files changed, 77 deletions(-) delete mode 100644 src/Hanko.cpp delete mode 100644 src/Hanko.h diff --git a/src/Hanko.cpp b/src/Hanko.cpp deleted file mode 100644 index 4c2bb25b81..0000000000 --- a/src/Hanko.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "Hanko.h" - -#include - -using namespace boost; -using namespace std; - -Hanko::Hanko() -{ -} - -// vim:ts=4 diff --git a/src/Hanko.h b/src/Hanko.h deleted file mode 100644 index 4a1079a5b8..0000000000 --- a/src/Hanko.h +++ /dev/null @@ -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 mContactBlock; - CKey mPubKey; - -public: - Hanko(); - Hanko(const std::string& TextHanko); - Hanko(const std::vector& Data, HankoFormat format); - Hanko(const CKey &pubKey); - Hanko(const Hanko &); - - std::string GetHankoString(HankoFormat format) const; - std::vector GetHankoBinary(HankoFormat format) const; - - const std::vector& GetContactBlock() const { return mContactBlock; } - const CKey& GetPublicKey() const { return mPubKey; } - - int UpdateContact(std::vector& Contact); - - bool CheckHashSign(const uint256& hash, const std::vector& Signature); - bool CheckPrefixSign(const std::vector& data, uint64 type, - const std::vector &signature); -}; - - -class LocalHanko : public Hanko -{ -private: - CKey mPrivKey; - -public: - LocalHanko(std::vector &PrivKey); - LocalHanko(const CKey &Privkey); - LocalHanko(const LocalHanko &); - ~LocalHanko(); - - bool HashSign(const uint256& hash, std::vector& Signature); - bool PrefixSign(std::vector data, uint64 type, std::vector &Signature); -}; - -#endif -// vim:ts=4 From dd27ce9324c5fb779703f0085059ecdd4bcbeb48 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sat, 9 Jun 2012 01:59:00 -0700 Subject: [PATCH 21/25] Sorry, I broke this. --- src/NewcoinAddress.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/NewcoinAddress.cpp b/src/NewcoinAddress.cpp index 715863c3e7..ccb6e311fb 100644 --- a/src/NewcoinAddress.cpp +++ b/src/NewcoinAddress.cpp @@ -503,8 +503,8 @@ BIGNUM* NewcoinAddress::getFamilyGeneratorBN() const throw std::runtime_error(str(boost::format("bad source: %d") % int(nVersion))); } - assert(vchData.size() <= (256 / 8)); - BIGNUM* ret = BN_bin2bn(&vchData[0], vchData.size(), NULL); + assert(vchData.size() <= ((256 + 8) / 8)); + BIGNUM* ret = BN_bin2bn(&vchData[1], vchData.size() - 1, NULL); assert(ret); return ret; @@ -524,9 +524,9 @@ uint256 NewcoinAddress::getFamilyGeneratorU() const throw std::runtime_error(str(boost::format("bad source: %d") % int(nVersion))); } - assert(vchData.size() <= (256 / 8)); + assert(vchData.size() <= ((256 + 1) / 8)); uint256 ret; - memcpy(ret.begin() + (ret.size() - vchData.size()), &vchData[0], vchData.size()); + memcpy(ret.begin() + (ret.size() - (vchData.size() - 1)), &vchData[1], vchData.size() - 1); return ret; } From 51ba107e2ca2b510053a5459b318ced946ccf7df Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sat, 9 Jun 2012 02:22:00 -0700 Subject: [PATCH 22/25] Fix breakage. --- src/DeterministicKeys.cpp | 15 +++++++++++---- src/NewcoinAddress.cpp | 28 +++------------------------- src/NewcoinAddress.h | 1 - src/key.h | 8 ++++++-- 4 files changed, 20 insertions(+), 32 deletions(-) diff --git a/src/DeterministicKeys.cpp b/src/DeterministicKeys.cpp index 2373fe52c1..e95280c72c 100644 --- a/src/DeterministicKeys.cpp +++ b/src/DeterministicKeys.cpp @@ -3,6 +3,7 @@ #include #include #include +#include // Functions to add CKey support for deterministic EC keys @@ -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; diff --git a/src/NewcoinAddress.cpp b/src/NewcoinAddress.cpp index ccb6e311fb..a621b7f75b 100644 --- a/src/NewcoinAddress.cpp +++ b/src/NewcoinAddress.cpp @@ -490,7 +490,7 @@ std::vector NewcoinAddress::accountPrivateDecrypt(const NewcoinAd // BIGNUM* NewcoinAddress::getFamilyGeneratorBN() const -{ +{ // returns the public generator switch (nVersion) { case VER_NONE: throw std::runtime_error("unset source"); @@ -503,35 +503,13 @@ BIGNUM* NewcoinAddress::getFamilyGeneratorBN() const throw std::runtime_error(str(boost::format("bad source: %d") % int(nVersion))); } - assert(vchData.size() <= ((256 + 8) / 8)); - BIGNUM* ret = BN_bin2bn(&vchData[1], vchData.size() - 1, NULL); + BIGNUM* ret = BN_bin2bn(&vchData[0], vchData.size(), NULL); assert(ret); - - return ret; -} - -uint256 NewcoinAddress::getFamilyGeneratorU() const -{ - switch (nVersion) { - case VER_NONE: - throw std::runtime_error("unset source"); - - case VER_FAMILY_GENERATOR: - // Do nothing. - break; - - default: - throw std::runtime_error(str(boost::format("bad source: %d") % int(nVersion))); - } - - assert(vchData.size() <= ((256 + 1) / 8)); - uint256 ret; - memcpy(ret.begin() + (ret.size() - (vchData.size() - 1)), &vchData[1], vchData.size() - 1); return ret; } const std::vector& NewcoinAddress::getFamilyGenerator() const -{ +{ // returns the public generator switch (nVersion) { case VER_NONE: throw std::runtime_error("unset source"); diff --git a/src/NewcoinAddress.h b/src/NewcoinAddress.h index 8e3069d722..3418669152 100644 --- a/src/NewcoinAddress.h +++ b/src/NewcoinAddress.h @@ -136,7 +136,6 @@ public: // Use to generate a master or regular family. // BIGNUM* getFamilyGeneratorBN() const; // DEPRECATED - uint256 getFamilyGeneratorU() const; const std::vector& getFamilyGenerator() const; std::string humanFamilyGenerator() const; diff --git a/src/key.h b/src/key.h index 38a47e8c26..213bae4ddc 100644 --- a/src/key.h +++ b/src/key.h @@ -156,14 +156,16 @@ public: 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); + SetPrivSeq(masterKey, keyNum); // broken, need seed fSet = true; } +#endif bool IsNull() const { @@ -257,8 +259,9 @@ public: 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(); @@ -267,6 +270,7 @@ public: pkey = key; fSet = true; } +#endif CPrivKey GetPrivKey() { From eaf511ebb605108707f3d1f998832a333685eddd Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sat, 9 Jun 2012 02:22:15 -0700 Subject: [PATCH 23/25] New ledger code. --- src/Ledger.cpp | 25 +++++++++++++++++++++---- src/RPCServer.cpp | 3 ++- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/Ledger.cpp b/src/Ledger.cpp index 440fb393a2..a77b0e649c 100644 --- a/src/Ledger.cpp +++ b/src/Ledger.cpp @@ -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(mLedgerSeq)] = ledger; diff --git a/src/RPCServer.cpp b/src/RPCServer.cpp index f325ce6a81..6ba9ad38d4 100644 --- a/src/RPCServer.cpp +++ b/src/RPCServer.cpp @@ -2143,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"; } From 182d23e22a63fad8ae3e21d1f7e6814b5d55a1df Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sat, 9 Jun 2012 02:27:57 -0700 Subject: [PATCH 24/25] Give account state node types. --- src/SerializedLedger.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/SerializedLedger.cpp b/src/SerializedLedger.cpp index beeb69dee5..726296d189 100644 --- a/src/SerializedLedger.cpp +++ b/src/SerializedLedger.cpp @@ -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; From c0fced82c8a9fb4ee7f728c79e3a650c5ec2b119 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sat, 9 Jun 2012 02:31:56 -0700 Subject: [PATCH 25/25] Cleanup. --- src/SerializedTransaction.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/SerializedTransaction.cpp b/src/SerializedTransaction.cpp index ec94093f0b..daadbd5b39 100644 --- a/src/SerializedTransaction.cpp +++ b/src/SerializedTransaction.cpp @@ -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; }