From 229969c566131fd2916e6e8b480a1a1f2cf3fb01 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 14 May 2012 13:34:40 -0700 Subject: [PATCH 01/24] Add virtual destructor. Add TransactionAcquire code. --- src/LedgerAcquire.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/LedgerAcquire.h b/src/LedgerAcquire.h index 3fb7c0c5ad..424b4bcf95 100644 --- a/src/LedgerAcquire.h +++ b/src/LedgerAcquire.h @@ -25,6 +25,7 @@ protected: std::list< boost::weak_ptr > mPeers; PeerSet(const uint256& hash, int interval); + virtual ~PeerSet() { ; } public: const uint256& getHash() const { return mHash; } @@ -85,6 +86,29 @@ public: Peer::pointer); }; +class TransactionAcquire : public PeerSet, public boost::enable_shared_from_this +{ // A transaction set we are trying to acquire +public: + typedef boost::shared_ptr pointer; + +protected: + SHAMap::pointer mMap; + + void onTimer() { trigger(Peer::pointer()); } + void newPeer(Peer::pointer peer) { trigger(peer); } + + void done(); + void trigger(Peer::pointer); + boost::weak_ptr pmDowncast(); + +public: + TransactionAcquire(const uint256& hash); + SHAMap::pointer getMap(); + + bool takeNode(const std::list& IDs, const std::list >& data, + Peer::pointer); +}; + class LedgerAcquireMaster { protected: From faaea1e332432d015e54693ec09b8a4821d81561 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 14 May 2012 13:35:00 -0700 Subject: [PATCH 02/24] Add virtual destructor. --- src/SHAMap.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/SHAMap.h b/src/SHAMap.h index edbbbe4f71..35cc4a5797 100644 --- a/src/SHAMap.h +++ b/src/SHAMap.h @@ -38,6 +38,7 @@ public: SHAMapNode() : mDepth(0) { ; } SHAMapNode(int depth, const uint256& hash); + virtual ~SHAMapNode() { ; } int getDepth() const { return mDepth; } const uint256& getNodeID() const { return mNodeID; } bool isValid() const { return (mDepth >= 0) && (mDepth < 64); } From b0ad2b95ae3b7103dc84e72b074e95e6e985474f Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 14 May 2012 13:35:09 -0700 Subject: [PATCH 03/24] Cleanups. --- src/SHAMapSync.cpp | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/src/SHAMapSync.cpp b/src/SHAMapSync.cpp index e243e5e0b7..3138e89391 100644 --- a/src/SHAMapSync.cpp +++ b/src/SHAMapSync.cpp @@ -15,9 +15,6 @@ void SHAMap::getMissingNodes(std::vector& nodeIDs, std::vectorisFullBelow()) { -#ifdef GMN_DEBUG - std::cerr << "getMissingNodes: root is full below" << std::endl; -#endif clearSynching(); return; } @@ -31,34 +28,23 @@ void SHAMap::getMissingNodes(std::vector& nodeIDs, std::vector stack; stack.push(root); - while ((max > 0) && (!stack.empty())) + while (!stack.empty()) { SHAMapTreeNode::pointer node = stack.top(); stack.pop(); -#ifdef GMN_DEBUG - std::cerr << "gMN: popped " << node->getString() << std::endl; -#endif - for (int i = 0; i < 16; ++i) - if( !node->isEmptyBranch(i)) + if (!node->isEmptyBranch(i)) { -#ifdef GMN_DEBUG - std::cerr << "gMN: " << node->getString() << " has non-empty branch " << i << std::endl; -#endif SHAMapTreeNode::pointer desc = getNode(node->getChildNodeID(i), node->getChildHash(i), false); - if(desc) + if (!desc) { - if (desc->isInner() && !desc->isFullBelow()) - stack.push(desc); - } - else if (max-- > 0) - { -#ifdef GMN_DEBUG - std::cerr << "gMN: need " << node->getChildNodeID(i).getString() << std::endl; -#endif nodeIDs.push_back(node->getChildNodeID(i)); + if (--max <= 0) + return; } + else if (desc->isInner() && !desc->isFullBelow()) + stack.push(desc); } } } From a8c26d4d33153f48928f96332b7c87142aacbfd1 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 14 May 2012 13:35:17 -0700 Subject: [PATCH 04/24] Cleanups for ledger close logic. --- src/newcoin.proto | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/newcoin.proto b/src/newcoin.proto index 8317c71887..598694ad41 100644 --- a/src/newcoin.proto +++ b/src/newcoin.proto @@ -101,7 +101,7 @@ message TMStatusChange { message TMProposeLedger { required uint32 closingSeq = 1; - required uint32 secondsSinceClose = 2; + required uint32 proposeSeq = 2; required bytes previousLedgerHash = 3; // 0 if first proposal, hash we no longer propose required bytes currentLedgerHash = 4; // the hash of the ledger we are proposing required bytes hanko = 5; @@ -210,9 +210,10 @@ message TMLedgerNode { } enum TMLedgerInfoType { - liBASE = 0; // basic ledger info - liTX_NODE = 1; // transaction node - liAS_NODE = 2; // account state node + liBASE = 0; // basic ledger info + liTX_NODE = 1; // transaction node + liAS_NODE = 2; // account state node + liTS_CANDIDATE = 3; // candidate transaction set } enum TMLedgerType { From 80ed62481deb7153cc0a03c1430e59c75611cc4c Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 14 May 2012 13:35:36 -0700 Subject: [PATCH 05/24] Structures for ledger closing logic. --- src/LedgerConsensus.h | 88 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 src/LedgerConsensus.h diff --git a/src/LedgerConsensus.h b/src/LedgerConsensus.h new file mode 100644 index 0000000000..980efb8a5b --- /dev/null +++ b/src/LedgerConsensus.h @@ -0,0 +1,88 @@ +#ifndef __LEDGER_CONSENSUS__ +#define __LEDGER_CONSENSUS__ + +#include + +#include "key.h" +#include "Transaction.h" +#include "LedgerAcquire.h" + +class LCPosition +{ // A position taken by one of our trusted peers +protected: + uint256 mPubKeyHash; + CKey::pointer mPubKey; + uint256 mCurrentPosition; + uint32 mSequence; + +public: + typedef boost::shared_ptr pointer; + + LCPosition(CKey::pointer pubKey, const uint256& currentPosition, uint32 seq) : + mPubKey(pubKey), mCurrentPosition(currentPosition), mSequence(seq) { ; } + + const uint256& getPubKeyHash() const { return mPubKeyHash; } + const uint256& getCurrentPosition() const { return mCurrentPosition; } + uint32 getSeq() const { return mSequence; } + + bool verifySignature(const uint256& hash, const std::vector& signature) const; + void setPosition(const uint256& position, uint32 sequence); +}; + + +class LCTransaction +{ // A transaction that may be disputed +protected: + uint256 mTransactionID; + int mYays, mNays; + bool mOurPosition; + boost::unordered_map mVotes; + Transaction::pointer mTransaction; + +public: + typedef boost::shared_ptr pointer; + + LCTransaction(const uint256 &txID, bool ourPosition) : mTransactionID(txID), mYays(0), mNays(0), + mOurPosition(ourPosition) { ; } + + const uint256& getTransactionID() const { return mTransactionID; } + bool getOurPosition() const { return mOurPosition; } + + bool haveTransaction() const { return !!mTransaction; } + Transaction::pointer getTransaction() { return mTransaction; } + + void setVote(const uint256& peer, bool votesYes); + + bool updatePosition(int timePassed); +}; + + +class LedgerConsensus +{ +protected: + Ledger::pointer mPreviousLedger, mCurrentLedger; + + // Convergence tracking, trusted peers indexed by hash of public key + boost::unordered_map mPeerPositions; + + // Transaction Sets, indexed by hash of transaction tree + boost::unordered_map mComplete; + boost::unordered_map mAcquiring; + + +public: + LedgerConsensus(Ledger::pointer previousLedger, Ledger::pointer currentLedger) : + mPreviousLedger(previousLedger), mCurrentLedger(currentLedger) { ; } + + Ledger::pointer peekPreviousLedger() { return mPreviousLedger; } + Ledger::pointer peekCurrentLedger() { return mCurrentLedger; } + + LCPosition::pointer getCreatePeerPosition(const uint256& pubKeyHash); + + SHAMap::pointer getTransactionTree(const uint256& hash); + TransactionAcquire::pointer getAcquiring(const uint256& hash); + void acquireComplete(const uint256& hash); +}; + + +#endif From 1eb5ab4ad0f83bd579e572c08db1991d71a474fc Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 14 May 2012 14:06:15 -0700 Subject: [PATCH 06/24] Constants for ledger timing. --- src/Ledger.cpp | 5 +++-- src/LedgerTiming.h | 28 ++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 src/LedgerTiming.h diff --git a/src/Ledger.cpp b/src/Ledger.cpp index 7e058d6bc2..d5269a806d 100644 --- a/src/Ledger.cpp +++ b/src/Ledger.cpp @@ -15,9 +15,10 @@ #include "BitcoinUtil.h" #include "Wallet.h" #include "BinaryFormats.h" +#include "LedgerTiming.h" Ledger::Ledger(const NewcoinAddress& masterID, uint64 startAmount) : mTotCoins(startAmount), - mCloseTime(0), mLedgerSeq(0), mLedgerInterval(60), mClosed(false), mValidHash(false), + mCloseTime(0), mLedgerSeq(0), mLedgerInterval(LEDGER_INTERVAL), mClosed(false), mValidHash(false), mAccepted(false), mImmutable(false) { mTransactionMap = boost::make_shared(); @@ -37,7 +38,7 @@ Ledger::Ledger(const NewcoinAddress& masterID, uint64 startAmount) : mTotCoins(s Ledger::Ledger(const uint256 &parentHash, const uint256 &transHash, const uint256 &accountHash, uint64 totCoins, uint64 timeStamp, uint32 ledgerSeq) : mParentHash(parentHash), mTransHash(transHash), mAccountHash(accountHash), - mTotCoins(totCoins), mCloseTime(timeStamp), mLedgerSeq(ledgerSeq), mLedgerInterval(60), + mTotCoins(totCoins), mCloseTime(timeStamp), mLedgerSeq(ledgerSeq), mLedgerInterval(LEDGER_INTERVAL), mClosed(false), mValidHash(false), mAccepted(false), mImmutable(false) { updateHash(); diff --git a/src/LedgerTiming.h b/src/LedgerTiming.h new file mode 100644 index 0000000000..50ef49fa80 --- /dev/null +++ b/src/LedgerTiming.h @@ -0,0 +1,28 @@ +#ifndef __LEDGERTIMING__ +#define __LEDGERTIMING__ + +#define LEDGER_CLOSE_FAST +// #define LEDGER_CLOSE_SLOW + +#ifdef LEDGER_CLOSE_FAST + +// Time between one ledger close and the next ledger close +# define LEDGER_INTERVAL 60 + +// Time we expect avalanche to finish +# define LEDGER_CONVERGE 20 + +#endif + +#ifdef LEDGER_CLOSE_SLOW + +# define LEDGER_INTERVAL 1800 + +# define LEDGER_CONVERGE 180 + +// Time a transaction must be unconflicted before we consider it protected +# define LEDGER_PROTECT 90 + +#endif + +#endif From 7ba67479342e252492caca95351fce448239602e Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 14 May 2012 16:08:29 -0700 Subject: [PATCH 07/24] Make nodeid required. --- src/newcoin.proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/newcoin.proto b/src/newcoin.proto index 598694ad41..d62cb233e5 100644 --- a/src/newcoin.proto +++ b/src/newcoin.proto @@ -205,7 +205,7 @@ message TMObjectByHash } message TMLedgerNode { - optional bytes nodeid = 1; + required bytes nodeid = 1; required bytes nodedata = 2; } From 667b7bb3fba737de09488f638ebfffbbb656848d Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 14 May 2012 16:08:48 -0700 Subject: [PATCH 08/24] Cosmetic changes. --- src/LedgerAcquire.cpp | 8 ++++---- src/Peer.cpp | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/LedgerAcquire.cpp b/src/LedgerAcquire.cpp index 1876b5872b..89ab4ca3dd 100644 --- a/src/LedgerAcquire.cpp +++ b/src/LedgerAcquire.cpp @@ -220,7 +220,7 @@ void LedgerAcquire::trigger(Peer::pointer peer) tmGL->set_ledgerhash(mHash.begin(), mHash.size()); tmGL->set_ledgerseq(mLedger->getLedgerSeq()); tmGL->set_itype(newcoin::liAS_NODE); - for (std::vector::iterator it =nodeIDs.begin(); it != nodeIDs.end(); ++it) + for (std::vector::iterator it = nodeIDs.begin(); it != nodeIDs.end(); ++it) *(tmGL->add_nodeids()) = it->getRawString(); if (peer) { @@ -325,7 +325,7 @@ bool LedgerAcquire::takeAsNode(const std::list& nodeIDs, #endif if (!mHaveBase) return false; std::list::const_iterator nodeIDit = nodeIDs.begin(); - std::list >::const_iterator nodeDatait = data.begin(); + std::list< std::vector >::const_iterator nodeDatait = data.begin(); while (nodeIDit != nodeIDs.end()) { if (nodeIDit->isRoot()) @@ -411,10 +411,10 @@ bool LedgerAcquireMaster::gotLedgerData(newcoin::TMLedgerData& packet, Peer::poi std::list nodeIDs; std::list > nodeData; - if (packet.nodes().size()<=0) return false; + if (packet.nodes().size() <= 0) return false; for (int i = 0; i::iterator nodeIDIterator; std::list >::iterator rawNodeIterator; - for(nodeIDIterator=nodeIDs.begin(), rawNodeIterator=rawNodes.begin(); - nodeIDIterator!=nodeIDs.end(); ++nodeIDIterator, ++rawNodeIterator) + for(nodeIDIterator = nodeIDs.begin(), rawNodeIterator = rawNodes.begin(); + nodeIDIterator != nodeIDs.end(); ++nodeIDIterator, ++rawNodeIterator) { Serializer nID(33); nodeIDIterator->addIDRaw(nID); - newcoin::TMLedgerNode* node=data->add_nodes(); + newcoin::TMLedgerNode* node = data->add_nodes(); node->set_nodeid(nID.getDataPtr(), nID.getLength()); node->set_nodedata(&rawNodeIterator->front(), rawNodeIterator->size()); } @@ -766,14 +766,14 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet) punishPeer(PP_INVALID_REQUEST); return; } - PackedMessage::pointer oPacket=boost::make_shared + PackedMessage::pointer oPacket = boost::make_shared (PackedMessage::MessagePointer(data), newcoin::mtLEDGER); sendPacket(oPacket); } void Peer::recvLedger(newcoin::TMLedgerData& packet) { - if(!theApp->getMasterLedgerAcquire().gotLedgerData(packet, shared_from_this())) + if (!theApp->getMasterLedgerAcquire().gotLedgerData(packet, shared_from_this())) punishPeer(PP_UNWANTED_DATA); } From 2a7b635cc63cdc5546ece9ccd01ec7c3d0cee91d Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Mon, 14 May 2012 22:11:17 -0700 Subject: [PATCH 09/24] Avoid dynamically sized array. --- src/main.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index bc2b1fcb2d..d770187722 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -115,12 +115,14 @@ int main(int argc, char* argv[]) if (iCmd) vCmd = vm["parameters"].as >(); - char* pvCmd[iCmd]; + std::vector pvCmd; + + pvCmd.resize(iCmd); for (int i=0; i != iCmd; ++i) pvCmd[i] = (char*) (vCmd[0].c_str()); - iResult = unit_test_main(init_unit_test, iCmd, pvCmd); + iResult = unit_test_main(init_unit_test, iCmd, &pvCmd.front()); } else if (!vm.count("parameters")) { From ad2174ca72384eaf85fa216fd197a7bcbf99839d Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Mon, 14 May 2012 22:12:17 -0700 Subject: [PATCH 10/24] Rework Transaction with static constructors & support Claim --- src/Transaction.cpp | 180 ++++++++++++++++++++++++-------------------- src/Transaction.h | 53 ++++++++++--- 2 files changed, 142 insertions(+), 91 deletions(-) diff --git a/src/Transaction.cpp b/src/Transaction.cpp index ef39a564c0..f1620b12e8 100644 --- a/src/Transaction.cpp +++ b/src/Transaction.cpp @@ -11,47 +11,6 @@ #include "Serializer.h" #include "SerializedTransaction.h" -Transaction::Transaction(const NewcoinAddress& naPublicKey, const NewcoinAddress& naPrivateKey, - const NewcoinAddress& naFromAccount, const NewcoinAddress& toAccount, - uint64 amount, - uint32 iSeq, uint32 ident, uint32 ledger) : mInLedger(0), mStatus(NEW) -{ - mAccountFrom = naFromAccount; - - mFromPubKey = naPublicKey; - assert(mFromPubKey.isValid()); - - mTransaction = boost::make_shared(ttMAKE_PAYMENT); - - mTransaction->setSigningPubKey(mFromPubKey); - mTransaction->setSourceAccount(mAccountFrom); - - mTransaction->setSequence(iSeq); - - mTransaction->setTransactionFee(100); // for now - - mTransaction->setITFieldAccount(sfDestination, toAccount); - mTransaction->setITFieldU64(sfAmount, amount); - if (ledger != 0) - { - mTransaction->makeITFieldPresent(sfTargetLedger); - mTransaction->setITFieldU32(sfTargetLedger, ledger); - } - if (ident != 0) - { - mTransaction->makeITFieldPresent(sfSourceTag); - mTransaction->setITFieldU32(sfSourceTag, ident); - } - - if (!sign(naPrivateKey)) - { -#ifdef DEBUG - std::cerr << "Unable to sign transaction" << std::endl; -#endif - mStatus = INCOMPLETE; - } -} - Transaction::Transaction(const SerializedTransaction::pointer sit, bool bValidate) : mInLedger(0), mStatus(INVALID), mTransaction(sit) { @@ -87,67 +46,126 @@ Transaction::pointer Transaction::sharedTransaction(const std::vector& signature, uint32 ledgerSeq, TransStatus st) : - mAccountFrom(fromID), mFromPubKey(pubKey), mInLedger(ledgerSeq), mStatus(st) +Transaction::Transaction( + TransactionType ttKind, + const NewcoinAddress& naPublicKey, + const NewcoinAddress& naSourceAccount, + uint32 uSeq, + uint64 uFee, + uint32 uSourceTag) : + mInLedger(0), mStatus(NEW) { - mTransaction = boost::make_shared(ttMAKE_PAYMENT); - mTransaction->setSignature(signature); - mTransaction->setTransactionFee(fee); - mTransaction->setSigningPubKey(pubKey); // BROKEN - mTransaction->setSourceAccount(mAccountFrom); // BROKEN - mTransaction->setSequence(fromSeq); - if (fromLedger != 0) - { - mTransaction->makeITFieldPresent(sfTargetLedger); - mTransaction->setITFieldU32(sfTargetLedger, fromLedger); - } - if (ident != 0) + mAccountFrom = naSourceAccount; + mFromPubKey = naPublicKey; + assert(mFromPubKey.isValid()); + + mTransaction = boost::make_shared(ttKind); + + mTransaction->setSigningPubKey(mFromPubKey); + mTransaction->setSourceAccount(mAccountFrom); + mTransaction->setSequence(uSeq); + mTransaction->setTransactionFee(uFee); + + if (uSourceTag) { mTransaction->makeITFieldPresent(sfSourceTag); - mTransaction->setITFieldU32(sfSourceTag, ident); + mTransaction->setITFieldU32(sfSourceTag, uSourceTag); } - mTransaction->setITFieldU64(sfAmount, amount); - mTransaction->setITFieldAccount(sfDestination, toID.getAccountID()); - updateID(); } -#endif + +Transaction::pointer Transaction::setPayment( + const NewcoinAddress& naPrivateKey, + const NewcoinAddress& toAccount, + uint64 uAmount, + uint32 ledger) +{ + mTransaction->setITFieldAccount(sfDestination, toAccount); + mTransaction->setITFieldU64(sfAmount, uAmount); + + if (ledger != 0) + { + mTransaction->makeITFieldPresent(sfTargetLedger); + mTransaction->setITFieldU32(sfTargetLedger, ledger); + } + + sign(naPrivateKey); + + return shared_from_this(); +} + +Transaction::pointer Transaction::sharedPayment( + const NewcoinAddress& naPublicKey, const NewcoinAddress& naPrivateKey, + const NewcoinAddress& naSourceAccount, + uint32 uSeq, + uint64 uFee, + uint32 uSourceTag, + const NewcoinAddress& toAccount, + uint64 uAmount, + uint32 ledger) +{ + pointer tResult = boost::make_shared(ttMAKE_PAYMENT, + naPublicKey, naSourceAccount, + uSeq, uFee, uSourceTag); + + return tResult->setPayment(naPrivateKey, toAccount, uAmount, ledger); +} + +Transaction::pointer Transaction::setClaim( + const NewcoinAddress& naPrivateKey, + const NewcoinAddress& naGeneratorID, + const std::vector& vucGenerator) +{ + sign(naPrivateKey); + + return shared_from_this(); +} + +Transaction::pointer Transaction::sharedClaim( + const NewcoinAddress& naPublicKey, const NewcoinAddress& naPrivateKey, + const NewcoinAddress& naSourceAccount, + uint32 uSourceTag, + const NewcoinAddress& naGeneratorID, + const std::vector& vucGenerator) +{ + pointer tResult = boost::make_shared(ttCLAIM, + naPublicKey, naSourceAccount, + 0, // Sequence of 0. + 0, // Free. + uSourceTag); + + return tResult->setClaim(naPrivateKey, naGeneratorID, vucGenerator); +} bool Transaction::sign(const NewcoinAddress& naAccountPrivate) { - if(!naAccountPrivate.isValid()) + bool bResult = true; + + if (!naAccountPrivate.isValid()) { #ifdef DEBUG std::cerr << "No private key for signing" << std::endl; #endif - return false; + bResult = false; } - -#if 0 - if( (mTransaction->getITFieldU64(sfAmount)==0) ) - { -#ifdef DEBUG - std::cerr << "Bad amount or destination" << std::endl; -#endif - assert(false); - return false; - } -#endif - - if(!getSTransaction()->sign(naAccountPrivate)) + else if (!getSTransaction()->sign(naAccountPrivate)) { #ifdef DEBUG std::cerr << "Failed to make signature" << std::endl; #endif assert(false); - return false; + bResult = false; } - updateID(); + if (bResult) + { + updateID(); + } + else + { + mStatus = INCOMPLETE; + } - return true; + return bResult; } bool Transaction::checkSign() const diff --git a/src/Transaction.h b/src/Transaction.h index 20f068c657..9a336db450 100644 --- a/src/Transaction.h +++ b/src/Transaction.h @@ -30,35 +30,66 @@ enum TransStatus INCOMPLETE = 8 // needs more signatures }; +// This class is for constructing and examining transactions. Transactions are static so manipulation functions are unnecessary. class Transaction : public boost::enable_shared_from_this { public: - typedef boost::shared_ptr pointer; private: uint256 mTransactionID; NewcoinAddress mAccountFrom; - NewcoinAddress mFromPubKey; + NewcoinAddress mFromPubKey; // Sign transaction with this. mSignPubKey + NewcoinAddress mSourcePrivate; // Sign transaction with this. - uint32 mInLedger; - TransStatus mStatus; + uint32 mInLedger; + TransStatus mStatus; SerializedTransaction::pointer mTransaction; + Transaction::pointer setPayment( + const NewcoinAddress& naPrivateKey, + const NewcoinAddress& toAccount, + uint64 uAmount, + uint32 ledger); + + Transaction::pointer setClaim( + const NewcoinAddress& naPrivateKey, + const NewcoinAddress& naGeneratorID, + const std::vector& vucGenerator); + public: Transaction(const SerializedTransaction::pointer st, bool bValidate); static Transaction::pointer sharedTransaction(const std::vector&vucTransaction, bool bValidate); - Transaction(const NewcoinAddress& naPublicKey, const NewcoinAddress& naPrivateKey, - const NewcoinAddress& naFromAccount, const NewcoinAddress& toAccount, - uint64 amount, - uint32 iSeq, uint32 ident, uint32 ledger); + Transaction( + TransactionType ttKind, + const NewcoinAddress& naPublicKey, + const NewcoinAddress& naSourceAccount, + uint32 uSeq, + uint64 uFee, + uint32 uSourceTag); + static Transaction::pointer sharedPayment( + const NewcoinAddress& naPublicKey, const NewcoinAddress& naPrivateKey, + const NewcoinAddress& naSourceAccount, + uint32 uSeq, + uint64 uFee, + uint32 uSourceTag, + const NewcoinAddress& toAccount, + uint64 uAmount, + uint32 ledger); + + static Transaction::pointer sharedClaim( + const NewcoinAddress& naPublicKey, const NewcoinAddress& naPrivateKey, + const NewcoinAddress& naSourceAccount, + uint32 uSourceTag, + const NewcoinAddress& naGeneratorID, + const std::vector& vucGenerator); #if 0 Transaction(const NewcoinAddress& fromID, const NewcoinAddress& toID, - CKey::pointer pubKey, uint64 amount, uint64 fee, uint32 fromSeq, uint32 fromLedger, + CKey::pointer pubKey, uint64 uAmount, uint64 fee, uint32 fromSeq, uint32 fromLedger, uint32 ident, const std::vector& signature, uint32 ledgerSeq, TransStatus st); #endif @@ -106,9 +137,11 @@ public: protected: static Transaction::pointer transactionFromSQL(const std::string& statement); +#if 0 Transaction(const uint256& transactionID, const NewcoinAddress& accountFrom, const NewcoinAddress& accountTo, - CKey::pointer key, uint64 amount, uint64 fee, uint32 fromAccountSeq, uint32 sourceLedger, + CKey::pointer key, uint64 uAmount, uint64 fee, uint32 fromAccountSeq, uint32 sourceLedger, uint32 ident, const std::vector& signature, uint32 inLedger, TransStatus status); +#endif }; #endif From f3c9138e4b86010db7ddc54d874fbe851e1e4b0a Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Mon, 14 May 2012 22:13:03 -0700 Subject: [PATCH 11/24] Have RPC command claim use new constructor and output transaction --- src/RPCServer.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/RPCServer.cpp b/src/RPCServer.cpp index 3934a6af96..92d33ed5bf 100644 --- a/src/RPCServer.cpp +++ b/src/RPCServer.cpp @@ -608,8 +608,9 @@ Json::Value RPCServer::doWalletClaim(Json::Value& params) // // Which has no confidential information. + // XXX Need better parsing. + uint32 uSourceTag = (params.size() == 2) ? 0 : boost::lexical_cast(params[2u].asString()); // XXX Annotation is ignored. - uint32 uSourceTag = (params.size() == 2) ? 0 : params[2u].asUInt(); std::string strAnnotation = (params.size() == 3) ? "" : params[3u].asString(); NewcoinAddress naMasterSeed; @@ -641,13 +642,12 @@ Json::Value RPCServer::doWalletClaim(Json::Value& params) std::vector vucGeneratorCipher = naRegularReservedPrivate.accountPrivateEncrypt(naRegularReservedPublic, naMasterGenerator.getFamilyGenerator()); - Transaction::pointer trns = boost::make_shared( + Transaction::pointer trns = Transaction::sharedClaim( naAccountPublic, naAccountPrivate, - naAccountPublic, naUnset, - 0, // Free - 0, // Seq - uSourceTag, // Source tag - 0); // Ledger not specified. + naAccountPublic, + uSourceTag, + naRegularReservedPublic, // GeneratorID + vucGeneratorCipher); Json::Value obj(Json::objectValue); @@ -662,6 +662,8 @@ Json::Value RPCServer::doWalletClaim(Json::Value& params) obj["generator"] = strHex(vucGeneratorCipher); obj["annotation"] = strAnnotation; + obj["transaction"] = trns->getSTransaction()->getJson(0); + return obj; } } From 7403820e88a55650cd473d9331f8a0cea12d7e42 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Mon, 14 May 2012 22:17:02 -0700 Subject: [PATCH 12/24] Comment out verbose debugging. --- src/NewcoinAddress.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/NewcoinAddress.cpp b/src/NewcoinAddress.cpp index b472d374ab..1f2745639c 100644 --- a/src/NewcoinAddress.cpp +++ b/src/NewcoinAddress.cpp @@ -631,16 +631,17 @@ void NewcoinAddress::setFamilySeedGeneric(const std::string& strText) { if (setFamilySeed(strText)) { - std::cerr << "Recognized seed." << std::endl; + // std::cerr << "Recognized seed." << std::endl; + nothing(); } else if (1 == setFamilySeed1751(strText)) { - std::cerr << "Recognized 1751 seed." << std::endl; + // std::cerr << "Recognized 1751 seed." << std::endl; + nothing(); } else { - std::cerr << "Creating seed from pass phrase." << std::endl; - + // std::cerr << "Creating seed from pass phrase." << std::endl; setFamilySeed(CKey::PassPhraseToKey(strText)); } } From 0a894f159c1f7f6c8a8ecf9ee0eaf61eec58e44b Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Mon, 14 May 2012 22:24:24 -0700 Subject: [PATCH 13/24] Cosmetic reorg of Transaction. --- src/Transaction.cpp | 172 ++++++++++++++++++++++++-------------------- 1 file changed, 96 insertions(+), 76 deletions(-) diff --git a/src/Transaction.cpp b/src/Transaction.cpp index f1620b12e8..25d7bf7d8e 100644 --- a/src/Transaction.cpp +++ b/src/Transaction.cpp @@ -46,6 +46,10 @@ Transaction::pointer Transaction::sharedTransaction(const std::vectorsign(naAccountPrivate)) + { +#ifdef DEBUG + std::cerr << "Failed to make signature" << std::endl; +#endif + assert(false); + bResult = false; + } + + if (bResult) + { + updateID(); + } + else + { + mStatus = INCOMPLETE; + } + + return bResult; +} + +// +// Claim +// + +Transaction::pointer Transaction::setClaim( + const NewcoinAddress& naPrivateKey, + const NewcoinAddress& naGeneratorID, + const std::vector& vucGenerator) +{ + sign(naPrivateKey); + + return shared_from_this(); +} + +Transaction::pointer Transaction::sharedClaim( + const NewcoinAddress& naPublicKey, const NewcoinAddress& naPrivateKey, + const NewcoinAddress& naSourceAccount, + uint32 uSourceTag, + const NewcoinAddress& naGeneratorID, + const std::vector& vucGenerator) +{ + pointer tResult = boost::make_shared(ttCLAIM, + naPublicKey, naSourceAccount, + 0, // Sequence of 0. + 0, // Free. + uSourceTag); + + return tResult->setClaim(naPrivateKey, naGeneratorID, vucGenerator); +} + +// +// Payment +// + Transaction::pointer Transaction::setPayment( const NewcoinAddress& naPrivateKey, const NewcoinAddress& toAccount, @@ -110,63 +180,9 @@ Transaction::pointer Transaction::sharedPayment( return tResult->setPayment(naPrivateKey, toAccount, uAmount, ledger); } -Transaction::pointer Transaction::setClaim( - const NewcoinAddress& naPrivateKey, - const NewcoinAddress& naGeneratorID, - const std::vector& vucGenerator) -{ - sign(naPrivateKey); - - return shared_from_this(); -} - -Transaction::pointer Transaction::sharedClaim( - const NewcoinAddress& naPublicKey, const NewcoinAddress& naPrivateKey, - const NewcoinAddress& naSourceAccount, - uint32 uSourceTag, - const NewcoinAddress& naGeneratorID, - const std::vector& vucGenerator) -{ - pointer tResult = boost::make_shared(ttCLAIM, - naPublicKey, naSourceAccount, - 0, // Sequence of 0. - 0, // Free. - uSourceTag); - - return tResult->setClaim(naPrivateKey, naGeneratorID, vucGenerator); -} - -bool Transaction::sign(const NewcoinAddress& naAccountPrivate) -{ - bool bResult = true; - - if (!naAccountPrivate.isValid()) - { -#ifdef DEBUG - std::cerr << "No private key for signing" << std::endl; -#endif - bResult = false; - } - else if (!getSTransaction()->sign(naAccountPrivate)) - { -#ifdef DEBUG - std::cerr << "Failed to make signature" << std::endl; -#endif - assert(false); - bResult = false; - } - - if (bResult) - { - updateID(); - } - else - { - mStatus = INCOMPLETE; - } - - return bResult; -} +// +// Misc. +// bool Transaction::checkSign() const { @@ -176,8 +192,8 @@ bool Transaction::checkSign() const void Transaction::setStatus(TransStatus ts, uint32 lseq) { - mStatus = ts; - mInLedger = lseq; + mStatus = ts; + mInLedger = lseq; } void Transaction::saveTransaction(Transaction::pointer txn) @@ -265,7 +281,6 @@ Transaction::pointer Transaction::transactionFromSQL(const std::string& sql) tr->setStatus(st); return tr; - } Transaction::pointer Transaction::load(const uint256& id) @@ -329,22 +344,6 @@ bool Transaction::convertToTransactions(uint32 firstLedgerSeq, uint32 secondLedg return true; } -static bool isHex(char j) -{ - if ((j >= '0') && (j <= '9')) return true; - if ((j >= 'A') && (j <= 'F')) return true; - if ((j >= 'a') && (j <= 'f')) return true; - return false; -} - -bool Transaction::isHexTxID(const std::string& txid) -{ - if (txid.size() != 64) return false; - for (int i = 0; i < 64; ++i) - if (!isHex(txid[i])) return false; - return true; -} - Json::Value Transaction::getJson(bool decorate, bool paid, bool credited) const { Json::Value ret(mTransaction->getJson(0)); @@ -378,4 +377,25 @@ Json::Value Transaction::getJson(bool decorate, bool paid, bool credited) const return ret; } + +// +// Obsolete +// + +static bool isHex(char j) +{ + if ((j >= '0') && (j <= '9')) return true; + if ((j >= 'A') && (j <= 'F')) return true; + if ((j >= 'a') && (j <= 'f')) return true; + return false; +} + +bool Transaction::isHexTxID(const std::string& txid) +{ + if (txid.size() != 64) return false; + for (int i = 0; i < 64; ++i) + if (!isHex(txid[i])) return false; + return true; +} + // vim:ts=4 From 04e44960e4d0221054c9a4644f3fa30de5e8cd27 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Tue, 15 May 2012 00:09:22 -0700 Subject: [PATCH 14/24] Clean up root account generation. --- src/Application.cpp | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/Application.cpp b/src/Application.cpp index 7651c126eb..84f0771709 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -118,16 +118,7 @@ void Application::run() std::cerr << "Master seed: " << rootSeedMaster.humanFamilySeed() << std::endl; std::cerr << "Master generator: " << rootGeneratorMaster.humanFamilyGenerator() << std::endl; - std::cerr << "Root address: " << rootAddress.humanAccountPublic() << std::endl; - - // Temporary root account will be ["This is my payphrase."]:0 - NewcoinAddress rootFamilySeed; // Hold the 128 password. - NewcoinAddress rootFamilyGenerator; // Hold the generator. - // NewcoinAddress rootAddress; - - rootFamilySeed.setFamilySeed(CKey::PassPhraseToKey("This is my payphrase.")); - rootFamilyGenerator.setFamilyGenerator(rootFamilySeed); - rootAddress.setAccountPublic(rootFamilyGenerator, 0); + std::cerr << "Root public key: " << rootAddress.humanAccountPublic() << std::endl; std::cerr << "Root account: " << rootAddress.humanAccountID() << std::endl; Ledger::pointer firstLedger = boost::make_shared(rootAddress, 100000000); From 5202326384b582889a996345e0f57be2eb828c70 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Tue, 15 May 2012 00:10:03 -0700 Subject: [PATCH 15/24] Revise account_info for new model. --- src/RPCServer.cpp | 143 ++++++++++++++++++++++++++++++++-------------- src/RPCServer.h | 1 + src/main.cpp | 5 +- 3 files changed, 103 insertions(+), 46 deletions(-) diff --git a/src/RPCServer.cpp b/src/RPCServer.cpp index 92d33ed5bf..5c23706bf0 100644 --- a/src/RPCServer.cpp +++ b/src/RPCServer.cpp @@ -172,6 +172,7 @@ NewcoinAddress RPCServer::parseFamily(const std::string& fParam) return family; } +#if 0 Json::Value RPCServer::doCreateFamily(Json::Value& params) { // createfamily FXXXX @@ -216,37 +217,83 @@ Json::Value RPCServer::doCreateFamily(Json::Value& params) return ret; } +#endif +// account_info || +// account_info || [] Json::Value RPCServer::doAccountInfo(Json::Value ¶ms) -{ // accountinfo : - // accountinfo - std::string acct; - if (!extractString(acct, params, 0)) - return JSONRPCError(500, "Invalid account identifier"); - - LocalAccount::pointer account = theApp->getWallet().parseAccount(acct); - if (account) return account->getJson(); - - NewcoinAddress acctid; - if (!acctid.setAccountID(acct)) - return JSONRPCError(500, "Unable to parse account"); - - LocalAccount::pointer lac(theApp->getWallet().getLocalAccount(acctid)); - if (!!lac) return lac->getJson(); - - AccountState::pointer as=theApp->getMasterLedger().getCurrentLedger()->getAccountState(acctid); - Json::Value ret(Json::objectValue); - if (as) - as->addJson(ret); +{ + if (params.size() < 1 || params.size() > 2) + { + return "invalid params"; + } else { - NewcoinAddress ad; - ad.setAccountID(acct); - ret[ad.humanAccountID()]="NotFound"; + std::string strIdent = params[0u].asString(); + bool bIndex = 2 == params.size(); + int iIndex = bIndex ? boost::lexical_cast(params[1u].asString()) : 0; + + NewcoinAddress naAccount; + NewcoinAddress naSeed; + + if (!bIndex && (naAccount.setAccountPublic(strIdent) || naAccount.setAccountID(strIdent))) + { + // Got the account. + nothing(); + } + else + { + // Must be a seed. + naSeed.setFamilySeedGeneric(strIdent); + + NewcoinAddress naGenerator; + NewcoinAddress naRegularReservedPublic; + + naGenerator.setFamilyGenerator(naSeed); + + naRegularReservedPublic.setAccountPublic(naGenerator, -1); + + uint160 uGeneratorID = naRegularReservedPublic.getAccountID(); + + // if (probe (uGeneratorID)) + if (false) + { + // Found master public key. + + } + else + { + // Didn't find a generator map, assume it is a master generator. + nothing(); + } + + bIndex = true; + + naAccount.setAccountPublic(naGenerator, iIndex); + } + + // Get info on account. + Json::Value ret(Json::objectValue); + + AccountState::pointer as=theApp->getMasterLedger().getCurrentLedger()->getAccountState(naAccount); + if (as) + { + as->addJson(ret); + } + else + { + ret["account"] = naAccount.humanAccountID(); + ret["status"] = "NotFound"; + ret["bIndex"] = bIndex; + if (bIndex) + ret["index"] = iIndex; + } + + return ret; } - return ret; } +#if 0 Json::Value RPCServer::doNewAccount(Json::Value ¶ms) { // newaccount [] std::string fParam; @@ -262,6 +309,7 @@ Json::Value RPCServer::doNewAccount(Json::Value ¶ms) return account->getJson(); } +#endif Json::Value RPCServer::doLock(Json::Value ¶ms) { // lock @@ -811,38 +859,47 @@ Json::Value RPCServer::doUnlScore(Json::Value& params) { else return "invalid params"; } -Json::Value RPCServer::doCommand(const std::string& command, Json::Value& params) -{ - std::cerr << "RPC:" << command << std::endl; - - if (command== "stop") +Json::Value RPCServer::doStop(Json::Value& params) { + if (!params.size()) { theApp->stop(); return SYSTEM_NAME " server stopping"; } + else return "invalid params"; +} - if (command=="unl_add") return doUnlAdd(params); - if (command=="unl_default") return doUnlDefault(params); - if (command=="unl_delete") return doUnlDelete(params); - if (command=="unl_list") return doUnlList(params); - if (command=="unl_reset") return doUnlReset(params); - if (command=="unl_score") return doUnlScore(params); +Json::Value RPCServer::doCommand(const std::string& command, Json::Value& params) +{ + std::cerr << "RPC:" << command << std::endl; - if (command=="validation_create") return doValidatorCreate(params); + if (command == "account_info") return doAccountInfo(params); + if (command == "connect") return doConnect(params); + if (command == "peers") return doPeers(params); + if (command == "stop") return doStop(params); - if (command=="wallet_claim") return doWalletClaim(params); - if (command=="wallet_propose") return doWalletPropose(params); + if (command == "unl_add") return doUnlAdd(params); + if (command == "unl_default") return doUnlDefault(params); + if (command == "unl_delete") return doUnlDelete(params); + if (command == "unl_list") return doUnlList(params); + if (command == "unl_reset") return doUnlReset(params); + if (command == "unl_score") return doUnlScore(params); - if (command=="createfamily") return doCreateFamily(params); + if (command == "validation_create") return doValidatorCreate(params); + + if (command == "wallet_claim") return doWalletClaim(params); + if (command == "wallet_propose") return doWalletPropose(params); + + // + // Obsolete or need rewrite: + // + +// if (command=="createfamily") return doCreateFamily(params); if (command=="familyinfo") return doFamilyInfo(params); - if (command=="accountinfo") return doAccountInfo(params); - if (command=="newaccount") return doNewAccount(params); +// if (command=="newaccount") return doNewAccount(params); if (command=="lock") return doLock(params); if (command=="unlock") return doUnlock(params); if (command=="sendto") return doSendTo(params); - if (command=="connect") return doConnect(params); - if (command=="peers") return doPeers(params); if (command=="tx") return doTx(params); if (command=="ledger") return doLedger(params); diff --git a/src/RPCServer.h b/src/RPCServer.h index c2c3286c61..904603dcd7 100644 --- a/src/RPCServer.h +++ b/src/RPCServer.h @@ -45,6 +45,7 @@ class RPCServer : public boost::enable_shared_from_this Json::Value doTx(Json::Value& params); Json::Value doLedger(Json::Value& params); Json::Value doAccount(Json::Value& params); + Json::Value doStop(Json::Value& params); Json::Value doUnlAdd(Json::Value& params); Json::Value doUnlDefault(Json::Value& params); diff --git a/src/main.cpp b/src/main.cpp index d770187722..2497515764 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -36,13 +36,12 @@ void printHelp(const po::options_description& desc) cout << desc << endl; cout << "Commands: " << endl; - cout << " accountinfo :" << endl; + cout << " account_info |" << endl; + cout << " account_info || []" << endl; cout << " connect []" << endl; - cout << " createfamily []" << endl; cout << " familyinfo" << endl; cout << " ledger" << endl; cout << " lock " << endl; - cout << " newaccount []" << endl; cout << " peers" << endl; cout << " sendto []" << endl; cout << " stop" << endl; From e5a4a8ba2069943d2cb06a0b0818476d7ba13d8d Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Tue, 15 May 2012 04:12:18 -0700 Subject: [PATCH 16/24] High-level functions. --- src/LedgerConsensus.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/LedgerConsensus.h b/src/LedgerConsensus.h index 980efb8a5b..ef2f7a9f00 100644 --- a/src/LedgerConsensus.h +++ b/src/LedgerConsensus.h @@ -1,6 +1,8 @@ #ifndef __LEDGER_CONSENSUS__ #define __LEDGER_CONSENSUS__ +#include + #include #include "key.h" @@ -69,6 +71,8 @@ protected: boost::unordered_map mComplete; boost::unordered_map mAcquiring; + // Peer sets + boost::unordered_map > > mPeerData; public: LedgerConsensus(Ledger::pointer previousLedger, Ledger::pointer currentLedger) : @@ -82,6 +86,14 @@ public: SHAMap::pointer getTransactionTree(const uint256& hash); TransactionAcquire::pointer getAcquiring(const uint256& hash); void acquireComplete(const uint256& hash); + + LCPosition::pointer getPeerPosition(const uint256& peer); + + // high-level functions + bool peerPosition(Peer::pointer peer, const Serializer& report); + bool peerHasSet(Peer::pointer peer, const std::vector& sets); + bool peerGaveNodes(Peer::pointer peer, const uint256& setHash, + const std::list& nodeIDs, const std::list< std::vector >& nodeData); }; From 96bdc953bfa474a8ae696542d54c1b1ed15bdbbd Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Tue, 15 May 2012 04:12:32 -0700 Subject: [PATCH 17/24] Cleanup. --- src/LedgerTiming.h | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/LedgerTiming.h b/src/LedgerTiming.h index 50ef49fa80..3221122bb1 100644 --- a/src/LedgerTiming.h +++ b/src/LedgerTiming.h @@ -7,18 +7,23 @@ #ifdef LEDGER_CLOSE_FAST // Time between one ledger close and the next ledger close -# define LEDGER_INTERVAL 60 +# define LEDGER_INTERVAL 60 // Time we expect avalanche to finish -# define LEDGER_CONVERGE 20 +# define LEDGER_CONVERGE 20 + +// Time we forcibly abort avalanche +# define LEDGER_FORCE_CONVERGE 30 #endif #ifdef LEDGER_CLOSE_SLOW -# define LEDGER_INTERVAL 1800 +# define LEDGER_INTERVAL 1800 -# define LEDGER_CONVERGE 180 +# define LEDGER_CONVERGE 180 + +# define LEDGER_FORCE_CONVERGE 240 // Time a transaction must be unconflicted before we consider it protected # define LEDGER_PROTECT 90 From 8d97f4438cb98a9c7a7a705db14e250466be07cc Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Tue, 15 May 2012 04:12:45 -0700 Subject: [PATCH 18/24] Allow peers to report which transaction sets they have. --- src/newcoin.proto | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/newcoin.proto b/src/newcoin.proto index d62cb233e5..ada5c59433 100644 --- a/src/newcoin.proto +++ b/src/newcoin.proto @@ -22,6 +22,7 @@ enum MessageType { mtPROPOSE_LEDGER= 33; mtCLOSE_LEDGER= 35; mtSTATUS_CHANGE= 36; + mtPEER_POSITION= 37; // data replication and synchronization mtGET_VALIDATIONS= 40; @@ -98,6 +99,17 @@ message TMStatusChange { } +message TMPeerPosition { + required uint32 ledgerSequence = 1; + required bytes pubKey = 2; + required uint32 sequence = 3; + required bytes transactionHash = 4; + required bytes signature = 5; +} + +message TMHaveTransactionSet { + repeated bytes hashes = 1; +} message TMProposeLedger { required uint32 closingSeq = 1; @@ -110,6 +122,8 @@ message TMProposeLedger { required bytes signature = 8; } + + // Used to propose/validate during ledger close message TMValidation { required uint32 ledgerIndex = 1; From 063ba4e3817e500dc334876a491e5c28b0a91c42 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Tue, 15 May 2012 13:02:01 -0700 Subject: [PATCH 19/24] Add accountPublicVerify to NewcoinAddress. --- src/NewcoinAddress.cpp | 19 +++++++++++++++++++ src/NewcoinAddress.h | 2 ++ 2 files changed, 21 insertions(+) diff --git a/src/NewcoinAddress.cpp b/src/NewcoinAddress.cpp index 1f2745639c..7cf62467e3 100644 --- a/src/NewcoinAddress.cpp +++ b/src/NewcoinAddress.cpp @@ -303,6 +303,25 @@ void NewcoinAddress::setAccountPublic(const NewcoinAddress& generator, int seq) setAccountPublic(pubkey.GetPubKey()); } +bool NewcoinAddress::accountPublicVerify(const uint256& uHash, const std::vector& vucSig) const +{ + CKey ckPublic; + bool bVerified; + + if (!ckPublic.SetPubKey(getAccountPublic())) + { + // Bad private key. + std::cerr << "accountPublicVerify: Bad private key." << std::endl; + bVerified = false; + } + else + { + bVerified = ckPublic.Verify(uHash, vucSig); + } + + return bVerified; +} + // // AccountPrivate // diff --git a/src/NewcoinAddress.h b/src/NewcoinAddress.h index 46d90233da..6ea8fa1e2e 100644 --- a/src/NewcoinAddress.h +++ b/src/NewcoinAddress.h @@ -76,6 +76,8 @@ public: void setAccountPublic(const std::vector& vPublic); void setAccountPublic(const NewcoinAddress& generator, int seq); + bool accountPublicVerify(const uint256& uHash, const std::vector& vucSig) const; + // // Accounts Private // From 383e9c69aa8eac8430b8e7226591487505cc9c08 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Tue, 15 May 2012 13:03:18 -0700 Subject: [PATCH 20/24] Fix checkSign for SerializedTransaction. --- src/SerializedTransaction.cpp | 4 ++-- src/SerializedTransaction.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/SerializedTransaction.cpp b/src/SerializedTransaction.cpp index 67a067ea2e..a007be1122 100644 --- a/src/SerializedTransaction.cpp +++ b/src/SerializedTransaction.cpp @@ -136,9 +136,9 @@ bool SerializedTransaction::sign(const NewcoinAddress& naAccountPrivate) return naAccountPrivate.accountPrivateSign(getSigningHash(), mSignature.peekValue()); } -bool SerializedTransaction::checkSign(const NewcoinAddress& naAccountPrivate) const +bool SerializedTransaction::checkSign(const NewcoinAddress& naAccountPublic) const { - return naAccountPrivate.accountPrivateVerify(getSigningHash(), mSignature.getValue()); + return naAccountPublic.accountPublicVerify(getSigningHash(), mSignature.getValue()); } void SerializedTransaction::setSignature(const std::vector& sig) diff --git a/src/SerializedTransaction.h b/src/SerializedTransaction.h index 5ce70312ed..fe03d1c181 100644 --- a/src/SerializedTransaction.h +++ b/src/SerializedTransaction.h @@ -112,7 +112,7 @@ public: virtual Json::Value getJson(int options) const; bool sign(const NewcoinAddress& naAccountPrivate); - bool checkSign(const NewcoinAddress& naAccountPrivate) const; + bool checkSign(const NewcoinAddress& naAccountPublic) const; }; #endif From 329b1437b04fc76173c42a43308ded95f6200954 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Tue, 15 May 2012 13:04:02 -0700 Subject: [PATCH 21/24] Improve feedback for RPC wallet_claim. --- src/RPCServer.cpp | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/RPCServer.cpp b/src/RPCServer.cpp index 5c23706bf0..b0a7536c0a 100644 --- a/src/RPCServer.cpp +++ b/src/RPCServer.cpp @@ -645,10 +645,26 @@ Json::Value RPCServer::doValidatorCreate(Json::Value& params) { // To provide an example to client writers, we do everything we expect a client to do here. Json::Value RPCServer::doWalletClaim(Json::Value& params) { + NewcoinAddress naTemp; + if (params.size() < 2 || params.size() > 4) { return "invalid params"; } + else if (naTemp.setAccountID(params[0u].asString()) + || naTemp.setAccountPublic(params[0u].asString()) + || naTemp.setAccountPrivate(params[0u].asString())) + { + // Should also not allow account id's as seeds. + return "master seed expected"; + } + else if (naTemp.setAccountID(params[1u].asString()) + || naTemp.setAccountPublic(params[1u].asString()) + || naTemp.setAccountPrivate(params[1u].asString())) + { + // Should also not allow account id's as seeds. + return "regular seed expected"; + } else { // Trying to build: @@ -671,7 +687,6 @@ Json::Value RPCServer::doWalletClaim(Json::Value& params) NewcoinAddress naAccountPublic; NewcoinAddress naAccountPrivate; - NewcoinAddress naUnset; naMasterSeed.setFamilySeedGeneric(params[0u].asString()); naRegularSeed.setFamilySeedGeneric(params[1u].asString()); @@ -689,7 +704,6 @@ Json::Value RPCServer::doWalletClaim(Json::Value& params) uint160 uGeneratorID = naRegularReservedPublic.getAccountID(); std::vector vucGeneratorCipher = naRegularReservedPrivate.accountPrivateEncrypt(naRegularReservedPublic, naMasterGenerator.getFamilyGenerator()); - Transaction::pointer trns = Transaction::sharedClaim( naAccountPublic, naAccountPrivate, naAccountPublic, @@ -697,6 +711,8 @@ Json::Value RPCServer::doWalletClaim(Json::Value& params) naRegularReservedPublic, // GeneratorID vucGeneratorCipher); + (void) theApp->getOPs().processTransaction(trns); + Json::Value obj(Json::objectValue); // We "echo" the seeds so they can be checked. @@ -711,6 +727,7 @@ Json::Value RPCServer::doWalletClaim(Json::Value& params) obj["annotation"] = strAnnotation; obj["transaction"] = trns->getSTransaction()->getJson(0); + obj["status"] = trns->getStatus(); return obj; } From 099d70787874e4a27d6618245f870a17f364242b Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Tue, 15 May 2012 13:04:37 -0700 Subject: [PATCH 22/24] Improve debugging for applyTransaction. --- src/Transaction.cpp | 3 ++ src/TransactionEngine.cpp | 64 +++++++++++++++++++++++++++++++++++---- 2 files changed, 61 insertions(+), 6 deletions(-) diff --git a/src/Transaction.cpp b/src/Transaction.cpp index 25d7bf7d8e..4b663dec99 100644 --- a/src/Transaction.cpp +++ b/src/Transaction.cpp @@ -1,5 +1,6 @@ #include +#include #include "boost/lexical_cast.hpp" #include "boost/make_shared.hpp" #include "boost/ref.hpp" @@ -65,6 +66,8 @@ Transaction::Transaction( mTransaction = boost::make_shared(ttKind); + std::cerr << str(boost::format("Transaction: account: %s") % naSourceAccount.humanAccountID()) << std::endl; + std::cerr << str(boost::format("Transaction: mAccountFrom: %s") % mAccountFrom.humanAccountID()) << std::endl; mTransaction->setSigningPubKey(mFromPubKey); mTransaction->setSourceAccount(mAccountFrom); mTransaction->setSequence(uSeq); diff --git a/src/TransactionEngine.cpp b/src/TransactionEngine.cpp index a7c2dd1008..0900987df8 100644 --- a/src/TransactionEngine.cpp +++ b/src/TransactionEngine.cpp @@ -1,15 +1,21 @@ - #include "TransactionEngine.h" - #include "TransactionFormats.h" +#include + TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTransaction& txn, TransactionEngineParams params) { + std::cerr << "applyTransaction>" << std::endl; + TransactionEngineResult result = terSUCCESS; uint256 txID = txn.getTransactionID(); - if(!txID) return tenINVALID; + if (!txID) + { + std::cerr << "applyTransaction: invalid transaction id" << std::endl; + return tenINVALID; + } // Extract signing key // Transactions contain a signing key. This allows us to trivially verify a transaction has at least been properly signed @@ -22,7 +28,10 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran // check signature if (!txn.checkSign(naPubKey)) + { + std::cerr << "applyTransaction: invalid signature" << std::endl; return tenINVALID; + } bool bPrepaid = false; @@ -40,10 +49,12 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran break; case ttINVALID: + std::cerr << "applyTransaction: ttINVALID transaction type" << std::endl; result = tenINVALID; break; default: + std::cerr << "applyTransaction: unknown transaction type" << std::endl; result = tenUNKNOWN; break; } @@ -57,20 +68,30 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran if (bPrepaid) { if (txnFee) + { // Transaction is malformed. + std::cerr << "applyTransaction: fee not allowed" << std::endl; return tenINSUF_FEE_P; + } } else { // WRITEME: Check if fee is adequate if (txnFee == 0) + { + std::cerr << "applyTransaction: insufficient fee" << std::endl; return tenINSUF_FEE_P; + } } } // get source account ID uint160 srcAccount = txn.getSourceAccount().getAccountID(); - if (!srcAccount) return tenINVALID; + if (!srcAccount) + { + std::cerr << "applyTransaction: bad source id" << std::endl; + return tenINVALID; + } boost::recursive_mutex::scoped_lock sl(mLedger->mLock); @@ -78,7 +99,11 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran // If we are only verifying some transactions, this would be probablistic. LedgerStateParms qry = lepNONE; SerializedLedgerEntry::pointer src = mLedger->getAccountRoot(qry, srcAccount); - if (!src) return terNO_ACCOUNT; + if (!src) + { + std::cerr << str(boost::format("applyTransaction: no such account: %s") % txn.getSourceAccount().humanAccountID()) << std::endl; + return terNO_ACCOUNT; + } // deduct the fee, so it's not available during the transaction // we only write the account back if the transaction succeeds @@ -87,7 +112,10 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran uint64 balance = src->getIFieldU64(sfBalance); if (balance < txnFee) + { + std::cerr << "applyTransaction: insufficent balance" << std::endl; return terINSUF_FEE_B; + } src->setIFieldU64(sfBalance, balance - txnFee); } @@ -98,7 +126,10 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran if (bPrepaid) { if (t_seq) + { + std::cerr << "applyTransaction: bad sequence for pre-paid transaction" << std::endl; return terPAST_SEQ; + } } else { @@ -107,9 +138,18 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran if (t_seq != a_seq) { // WRITEME: Special case code for changing transaction key - if (a_seq < t_seq) return terPRE_SEQ; + if (a_seq < t_seq) + { + std::cerr << "applyTransaction: future sequence number" << std::endl; + return terPRE_SEQ; + } if (mLedger->hasTransaction(txID)) + { + std::cerr << "applyTransaction: duplicate sequence number" << std::endl; return terALREADY; + } + + std::cerr << "applyTransaction: past sequence number" << std::endl; return terPAST_SEQ; } else src->setIFieldU32(sfSequence, t_seq); @@ -121,6 +161,7 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran switch(txn.getTxnType()) { case ttINVALID: + std::cerr << "applyTransaction: invalid type" << std::endl; result = tenINVALID; break; @@ -178,6 +219,7 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran TransactionEngineResult TransactionEngine::doClaim(const SerializedTransaction& txn, std::vector& accounts) { + std::cerr << "doClaim>" << std::endl; NewcoinAddress naSigningPubKey; naSigningPubKey.setAccountPublic(txn.peekSigningPubKey()); @@ -185,15 +227,24 @@ TransactionEngineResult TransactionEngine::doClaim(const SerializedTransaction& uint160 sourceAccountID = naSigningPubKey.getAccountID(); if (sourceAccountID != txn.getSourceAccount().getAccountID()) + { // Signing Pub Key must be for Source Account ID. + std::cerr << "sourceAccountID: " << naSigningPubKey.humanAccountID() << std::endl; + std::cerr << "txn accountID: " << txn.getSourceAccount().humanAccountID() << std::endl; return tenINVALID; + } LedgerStateParms qry = lepNONE; SerializedLedgerEntry::pointer dest = mLedger->getAccountRoot(qry, sourceAccountID); if (!dest) + { // Source account does not exist. Could succeed if it was created first. + std::cerr << str(boost::format("doClaim: no such account: %s") % txn.getSourceAccount().humanAccountID()) << std::endl; return terNO_ACCOUNT; + } + + std::cerr << str(boost::format("doClaim: %s") % dest->getFullText()) << std::endl; if (dest->getIFieldPresent(sfAuthorizedKey)) // Source account already claimed. @@ -225,6 +276,7 @@ TransactionEngineResult TransactionEngine::doClaim(const SerializedTransaction& accounts.push_back(std::make_pair(taaCREATE, gen)); + std::cerr << "doClaim<" << std::endl; return terSUCCESS; } From c9571a2692f7099946e41334119eba0eb0e3b59d Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Tue, 15 May 2012 13:30:30 -0700 Subject: [PATCH 23/24] Fix a case where we don't create a stub for a non-present field. --- src/SerializedObject.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/SerializedObject.cpp b/src/SerializedObject.cpp index 3818ded576..871b4862fb 100644 --- a/src/SerializedObject.cpp +++ b/src/SerializedObject.cpp @@ -107,12 +107,20 @@ STObject::STObject(SOElement* elem, SerializerIterator& sit, const char *name) : if (elem->e_type == SOE_IFFLAG) { assert(flags >= 0); - if ((flags&elem->e_flags) == 0) done = true; + if ((flags&elem->e_flags) == 0) + { + done = true; + giveObject(new SerializedType(elem->e_name)); + } } else if (elem->e_type == SOE_IFNFLAG) { assert(flags >= 0); - if ((flags&elem->e_flags) != 0) done = true; + if ((flags&elem->e_flags) != 0) + { + done = true; + giveObject(new SerializedType(elem->e_name)); + } } else if (elem->e_type == SOE_FLAGS) { @@ -141,12 +149,14 @@ std::string STObject::getFullText() const ret += " = {"; } else ret = "{"; + for (boost::ptr_vector::const_iterator it = mData.begin(), end = mData.end(); it != end; ++it) { if (!first) ret += ", "; else first = false; ret += it->getFullText(); } + ret += "}"; return ret; } From cb4fcfddac5a97023a7962c8b313c70ee206dedd Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Tue, 15 May 2012 16:07:42 -0700 Subject: [PATCH 24/24] Get rid of some ugliness in the use of ptr_vectors. I hope I didn't break anything. --- src/SerializedLedger.h | 3 +- src/SerializedObject.cpp | 88 ++++++++++++++++++------------------ src/SerializedObject.h | 12 ++--- src/SerializedTransaction.h | 3 +- src/SerializedTypes.h | 90 ++++++++++++++++++++++++++----------- 5 files changed, 120 insertions(+), 76 deletions(-) diff --git a/src/SerializedLedger.h b/src/SerializedLedger.h index 88536b8423..a553003023 100644 --- a/src/SerializedLedger.h +++ b/src/SerializedLedger.h @@ -17,6 +17,8 @@ protected: STObject mObject; LedgerEntryFormat* mFormat; + SerializedLedgerEntry* duplicate() const { return new SerializedLedgerEntry(*this); } + public: SerializedLedgerEntry(const Serializer& s, const uint256& index); SerializedLedgerEntry(SerializerIterator& sit, const uint256& index); @@ -24,7 +26,6 @@ public: int getLength() const { return mVersion.getLength() + mObject.getLength(); } SerializedTypeID getSType() const { return STI_LEDGERENTRY; } - SerializedLedgerEntry* duplicate() const { return new SerializedLedgerEntry(*this); } std::string getFullText() const; std::string getText() const; Json::Value getJson(int options) const; diff --git a/src/SerializedObject.cpp b/src/SerializedObject.cpp index 871b4862fb..7d1ed46803 100644 --- a/src/SerializedObject.cpp +++ b/src/SerializedObject.cpp @@ -5,77 +5,88 @@ #include "../json/writer.h" -SerializedType* STObject::makeDefaultObject(SerializedTypeID id, const char *name) +std::auto_ptr STObject::makeDefaultObject(SerializedTypeID id, const char *name) { switch(id) { + case STI_NOTPRESENT: + return std::auto_ptr(new SerializedType(name)); + case STI_UINT16: - return new STUInt16(name); + return std::auto_ptr(new STUInt16(name)); case STI_UINT32: - return new STUInt32(name); + return std::auto_ptr(new STUInt32(name)); case STI_UINT64: - return new STUInt64(name); + return std::auto_ptr(new STUInt64(name)); case STI_AMOUNT: - return new STAmount(name); + return std::auto_ptr(new STAmount(name)); + + case STI_HASH128: + return std::auto_ptr(new STHash128(name)); case STI_HASH160: - return new STHash160(name); + return std::auto_ptr(new STHash160(name)); case STI_HASH256: - return new STHash256(name); + return std::auto_ptr(new STHash256(name)); case STI_VL: - return new STVariableLength(name); + return std::auto_ptr(new STVariableLength(name)); case STI_TL: - return new STTaggedList(name); + return std::auto_ptr(new STTaggedList(name)); case STI_ACCOUNT: - return new STAccount(name); + return std::auto_ptr(new STAccount(name)); default: - assert(false); - return NULL; + throw std::runtime_error("Unknown object type"); } } -SerializedType* STObject::makeDeserializedObject(SerializedTypeID id, const char *name, SerializerIterator& sit) +std::auto_ptr STObject::makeDeserializedObject(SerializedTypeID id, const char *name, + SerializerIterator& sit) { switch(id) { + case STI_NOTPRESENT: + return SerializedType::deserialize(name); + case STI_UINT16: - return STUInt16::construct(sit, name); + return STUInt16::deserialize(sit, name); case STI_UINT32: - return STUInt32::construct(sit, name); + return STUInt32::deserialize(sit, name); case STI_UINT64: - return STUInt64::construct(sit, name); + return STUInt64::deserialize(sit, name); case STI_AMOUNT: - return STAmount::construct(sit, name); + return STAmount::deserialize(sit, name); + + case STI_HASH128: + return STHash128::deserialize(sit, name); case STI_HASH160: - return STHash160::construct(sit, name); + return STHash160::deserialize(sit, name); case STI_HASH256: - return STHash256::construct(sit, name); + return STHash256::deserialize(sit, name); case STI_VL: - return STVariableLength::construct(sit, name); + return STVariableLength::deserialize(sit, name); case STI_TL: - return STTaggedList::construct(sit, name); + return STTaggedList::deserialize(sit, name); case STI_ACCOUNT: - return STAccount::construct(sit, name); + return STAccount::deserialize(sit, name); default: - assert(false); - return NULL; + throw std::runtime_error("Unknown object type"); } } @@ -86,13 +97,9 @@ STObject::STObject(SOElement* elem, const char *name) : SerializedType(name), mF if (elem->e_type == SOE_FLAGS) mFlagIdx = mType.size(); mType.push_back(elem); if (elem->e_type == SOE_IFFLAG) - giveObject(new SerializedType(elem->e_name)); + giveObject(makeDefaultObject(STI_NOTPRESENT, elem->e_name)); else - { - SerializedType* t = makeDefaultObject(elem->e_id, elem->e_name); - if (!t) throw std::runtime_error("invalid transaction element"); - giveObject(t); - } + giveObject(makeDefaultObject(elem->e_id, elem->e_name)); ++elem; } } @@ -110,7 +117,7 @@ STObject::STObject(SOElement* elem, SerializerIterator& sit, const char *name) : if ((flags&elem->e_flags) == 0) { done = true; - giveObject(new SerializedType(elem->e_name)); + giveObject(makeDefaultObject(elem->e_id, elem->e_name)); } } else if (elem->e_type == SOE_IFNFLAG) @@ -119,7 +126,7 @@ STObject::STObject(SOElement* elem, SerializerIterator& sit, const char *name) : if ((flags&elem->e_flags) != 0) { done = true; - giveObject(new SerializedType(elem->e_name)); + giveObject(makeDefaultObject(STI_NOTPRESENT, elem->e_name)); } } else if (elem->e_type == SOE_FLAGS) @@ -130,11 +137,7 @@ STObject::STObject(SOElement* elem, SerializerIterator& sit, const char *name) : done = true; } if (!done) - { - SerializedType* t = makeDeserializedObject(elem->e_id, elem->e_name, sit); - if (!t) throw std::runtime_error("invalid transaction element"); - giveObject(t); - } + giveObject(makeDeserializedObject(elem->e_id, elem->e_name, sit)); elem++; } } @@ -279,23 +282,22 @@ uint32 STObject::getFlags(void) const SerializedType* STObject::makeFieldPresent(SOE_Field field) { - SerializedType* ret = NULL; int index = getFieldIndex(field); if (index == -1) throw std::runtime_error("Field not found"); if ((mType[index]->e_type != SOE_IFFLAG) && (mType[index]->e_type != SOE_IFNFLAG)) throw std::runtime_error("field is not optional"); - ret = getPIndex(index); - if (ret->getSType() != STI_NOTPRESENT) return ret; - ret = makeDefaultObject(mType[index]->e_id, mType[index]->e_name); - mData.replace(index, ret); + SerializedType* f = getPIndex(index); + if (f->getSType() != STI_NOTPRESENT) return f; + mData.replace(index, makeDefaultObject(mType[index]->e_id, mType[index]->e_name)); + f = getPIndex(index); if (mType[index]->e_type == SOE_IFFLAG) setFlag(mType[index]->e_flags); else if (mType[index]->e_type == SOE_IFNFLAG) clearFlag(mType[index]->e_flags); - return ret; + return f; } void STObject::makeFieldAbsent(SOE_Field field) diff --git a/src/SerializedObject.h b/src/SerializedObject.h index 9ed15f4011..9202717c0f 100644 --- a/src/SerializedObject.h +++ b/src/SerializedObject.h @@ -54,8 +54,10 @@ protected: boost::ptr_vector mData; std::vector mType; - static SerializedType* makeDefaultObject(SerializedTypeID id, const char *name); - static SerializedType* makeDeserializedObject(SerializedTypeID id, const char *name, SerializerIterator&); + static std::auto_ptr makeDefaultObject(SerializedTypeID id, const char *name); + static std::auto_ptr makeDeserializedObject(SerializedTypeID id, const char *name, + SerializerIterator&); + STObject* duplicate() const { return new STObject(*this); } public: STObject(const char *n = NULL) : SerializedType(n), mFlagIdx(-1) { ; } @@ -65,7 +67,6 @@ public: int getLength() const; SerializedTypeID getSType() const { return STI_OBJECT; } - STObject* duplicate() const { return new STObject(*this); } virtual bool isEquivalent(const SerializedType& t) const; void add(Serializer& s) const; @@ -74,8 +75,9 @@ public: std::string getText() const; virtual Json::Value getJson(int options) const; - int addObject(const SerializedType& t) { mData.push_back(t.duplicate()); return mData.size()-1; } - int giveObject(SerializedType* t) { mData.push_back(t); return mData.size()-1; } + int addObject(const SerializedType& t) { mData.push_back(t.clone()); return mData.size() - 1; } + int giveObject(std::auto_ptr t) { mData.push_back(t); return mData.size() - 1; } + int giveObject(SerializedType* t) { mData.push_back(t); return mData.size() - 1; } const boost::ptr_vector& peekData() const { return mData; } boost::ptr_vector& peekData() { return mData; } diff --git a/src/SerializedTransaction.h b/src/SerializedTransaction.h index fe03d1c181..ff30e63e04 100644 --- a/src/SerializedTransaction.h +++ b/src/SerializedTransaction.h @@ -23,6 +23,8 @@ protected: STObject mMiddleTxn, mInnerTxn; TransactionFormat* mFormat; + SerializedTransaction* duplicate() const { return new SerializedTransaction(*this); } + public: SerializedTransaction(SerializerIterator& sit, int length); // -1=all remaining, 0=get from sit SerializedTransaction(TransactionType type); @@ -30,7 +32,6 @@ public: // STObject functions int getLength() const; SerializedTypeID getSType() const { return STI_TRANSACTION; } - SerializedTransaction* duplicate() const { return new SerializedTransaction(*this); } std::string getFullText() const; std::string getText() const; void add(Serializer& s) const { getTransaction(s, true); } diff --git a/src/SerializedTypes.h b/src/SerializedTypes.h index 8454fd7615..2e8ebbfd56 100644 --- a/src/SerializedTypes.h +++ b/src/SerializedTypes.h @@ -26,6 +26,8 @@ class SerializedType protected: const char *name; + virtual SerializedType* duplicate() const { return new SerializedType(name); } + public: SerializedType() : name(NULL) { ; } @@ -33,12 +35,15 @@ public: SerializedType(const SerializedType& n) : name(n.name) { ; } virtual ~SerializedType() { ; } + static std::auto_ptr deserialize(const char *name) + { return std::auto_ptr(new SerializedType(name)); } + void setName(const char *n) { name=n; } const char *getName() const { return name; } virtual int getLength() const { return 0; } virtual SerializedTypeID getSType() const { return STI_NOTPRESENT; } - virtual SerializedType* duplicate() const { return new SerializedType(name); } + std::auto_ptr clone() const { return std::auto_ptr(duplicate()); } virtual std::string getFullText() const; virtual std::string getText() const // just the value @@ -49,12 +54,12 @@ public: virtual bool isEquivalent(const SerializedType& t) const { return true; } bool operator==(const SerializedType& t) const - { return (getSType()==t.getSType()) && isEquivalent(t); } + { return (getSType() == t.getSType()) && isEquivalent(t); } bool operator!=(const SerializedType& t) const - { return (getSType()!=t.getSType()) || !isEquivalent(t); } + { return (getSType() != t.getSType()) || !isEquivalent(t); } }; -inline SerializedType* new_clone(const SerializedType& s) { return s.duplicate(); } +inline SerializedType* new_clone(const SerializedType& s) { return s.clone().release(); } inline void delete_clone(const SerializedType* s) { boost::checked_delete(s); } class STUInt8 : public SerializedType @@ -62,15 +67,18 @@ class STUInt8 : public SerializedType protected: unsigned char value; + STUInt8* duplicate() const { return new STUInt8(name, value); } + static STUInt8* construct(SerializerIterator&, const char *name = NULL); + public: STUInt8(unsigned char v=0) : value(v) { ; } STUInt8(const char *n, unsigned char v=0) : SerializedType(n), value(v) { ; } - static STUInt8* construct(SerializerIterator&, const char *name = NULL); + static std::auto_ptr deserialize(SerializerIterator& sit, const char *name) + { return std::auto_ptr(construct(sit, name)); } int getLength() const { return 1; } SerializedTypeID getSType() const { return STI_UINT8; } - STUInt8* duplicate() const { return new STUInt8(name, value); } std::string getText() const; void add(Serializer& s) const { s.add8(value); } @@ -87,15 +95,18 @@ class STUInt16 : public SerializedType protected: uint16 value; + STUInt16* duplicate() const { return new STUInt16(name, value); } + static STUInt16* construct(SerializerIterator&, const char *name = NULL); + public: STUInt16(uint16 v=0) : value(v) { ; } STUInt16(const char *n, uint16 v=0) : SerializedType(n), value(v) { ; } - static STUInt16* construct(SerializerIterator&, const char *name = NULL); + static std::auto_ptr deserialize(SerializerIterator& sit, const char *name) + { return std::auto_ptr(construct(sit, name)); } int getLength() const { return 2; } SerializedTypeID getSType() const { return STI_UINT16; } - STUInt16* duplicate() const { return new STUInt16(name, value); } std::string getText() const; void add(Serializer& s) const { s.add16(value); } @@ -112,15 +123,18 @@ class STUInt32 : public SerializedType protected: uint32 value; + STUInt32* duplicate() const { return new STUInt32(name, value); } + static STUInt32* construct(SerializerIterator&, const char *name = NULL); + public: STUInt32(uint32 v=0) : value(v) { ; } STUInt32(const char *n, uint32 v=0) : SerializedType(n), value(v) { ; } - static STUInt32* construct(SerializerIterator&, const char *name = NULL); + static std::auto_ptr deserialize(SerializerIterator& sit, const char *name) + { return std::auto_ptr(construct(sit, name)); } int getLength() const { return 4; } SerializedTypeID getSType() const { return STI_UINT32; } - STUInt32* duplicate() const { return new STUInt32(name, value); } std::string getText() const; void add(Serializer& s) const { s.add32(value); } @@ -137,15 +151,18 @@ class STUInt64 : public SerializedType protected: uint64 value; + STUInt64* duplicate() const { return new STUInt64(name, value); } + static STUInt64* construct(SerializerIterator&, const char *name = NULL); + public: STUInt64(uint64 v=0) : value(v) { ; } STUInt64(const char *n, uint64 v=0) : SerializedType(n), value(v) { ; } - static STUInt64* construct(SerializerIterator&, const char *name = NULL); + static std::auto_ptr deserialize(SerializerIterator& sit, const char *name) + { return std::auto_ptr(construct(sit, name)); } int getLength() const { return 8; } SerializedTypeID getSType() const { return STI_UINT64; } - STUInt64* duplicate() const { return new STUInt64(name, value); } std::string getText() const; void add(Serializer& s) const { s.add64(value); } @@ -175,6 +192,8 @@ protected: uint64 value; void canonicalize(); + STAmount* duplicate() const { return new STAmount(name, offset, value); } + static STAmount* construct(SerializerIterator&, const char *name = NULL); static const int cMinOffset=-96, cMaxOffset=80; static const uint64 cMinValue=1000000000000000ull, cMaxValue=9999999999999999ull; @@ -184,11 +203,11 @@ public: { canonicalize(); } // (1,0)=$1 (1,-2)=$.01 (100,0)=(10000,-2)=$.01 STAmount(const char *n, uint64 v = 0, int off = 0) : SerializedType(n), offset(off), value(v) { canonicalize(); } - static STAmount* construct(SerializerIterator&, const char *name = NULL); + static std::auto_ptr deserialize(SerializerIterator& sit, const char *name) + { return std::auto_ptr(construct(sit, name)); } int getLength() const { return 8; } SerializedTypeID getSType() const { return STI_AMOUNT; } - STAmount* duplicate() const { return new STAmount(name, offset, value); } std::string getText() const; std::string getRaw() const; void add(Serializer& s) const; @@ -245,17 +264,20 @@ class STHash128 : public SerializedType protected: uint128 value; + STHash128* duplicate() const { return new STHash128(name, value); } + static STHash128* construct(SerializerIterator&, const char *name = NULL); + public: STHash128(const uint128& v) : value(v) { ; } STHash128(const char *n, const uint128& v) : SerializedType(n), value(v) { ; } STHash128(const char *n) : SerializedType(n) { ; } STHash128() { ; } - static STHash128* construct(SerializerIterator&, const char *name = NULL); + static std::auto_ptr deserialize(SerializerIterator& sit, const char *name) + { return std::auto_ptr(construct(sit, name)); } int getLength() const { return 20; } SerializedTypeID getSType() const { return STI_HASH128; } - STHash128* duplicate() const { return new STHash128(name, value); } virtual std::string getText() const; void add(Serializer& s) const { s.add128(value); } @@ -272,17 +294,20 @@ class STHash160 : public SerializedType protected: uint160 value; + STHash160* duplicate() const { return new STHash160(name, value); } + static STHash160* construct(SerializerIterator&, const char *name = NULL); + public: STHash160(const uint160& v) : value(v) { ; } STHash160(const char *n, const uint160& v) : SerializedType(n), value(v) { ; } STHash160(const char *n) : SerializedType(n) { ; } STHash160() { ; } - static STHash160* construct(SerializerIterator&, const char *name = NULL); + static std::auto_ptr deserialize(SerializerIterator& sit, const char *name) + { return std::auto_ptr(construct(sit, name)); } int getLength() const { return 20; } SerializedTypeID getSType() const { return STI_HASH160; } - STHash160* duplicate() const { return new STHash160(name, value); } virtual std::string getText() const; void add(Serializer& s) const { s.add160(value); } @@ -299,17 +324,20 @@ class STHash256 : public SerializedType protected: uint256 value; + STHash256* duplicate() const { return new STHash256(name, value); } + static STHash256* construct(SerializerIterator&, const char *name = NULL); + public: STHash256(const uint256& v) : value(v) { ; } STHash256(const char *n, const uint256& v) : SerializedType(n), value(v) { ; } STHash256(const char *n) : SerializedType(n) { ; } STHash256() { ; } - static STHash256* construct(SerializerIterator&, const char *name = NULL); + static std::auto_ptr deserialize(SerializerIterator& sit, const char *name) + { return std::auto_ptr(construct(sit, name)); } int getLength() const { return 32; } SerializedTypeID getSType() const { return STI_HASH256; } - STHash256* duplicate() const { return new STHash256(name, value); } std::string getText() const; void add(Serializer& s) const { s.add256(value); } @@ -326,6 +354,9 @@ class STVariableLength : public SerializedType protected: std::vector value; + virtual STVariableLength* duplicate() const { return new STVariableLength(name, value); } + static STVariableLength* construct(SerializerIterator&, const char *name = NULL); + public: STVariableLength(const std::vector& v) : value(v) { ; } @@ -333,11 +364,11 @@ public: STVariableLength(const char *n) : SerializedType(n) { ; } STVariableLength(SerializerIterator&, const char *name = NULL); STVariableLength() { ; } - static STVariableLength* construct(SerializerIterator&, const char *name = NULL); + static std::auto_ptr deserialize(SerializerIterator& sit, const char *name) + { return std::auto_ptr(construct(sit, name)); } int getLength() const; virtual SerializedTypeID getSType() const { return STI_VL; } - virtual STVariableLength* duplicate() const { return new STVariableLength(name, value); } virtual std::string getText() const; void add(Serializer& s) const { s.addVL(value); } @@ -353,16 +384,20 @@ public: class STAccount : public STVariableLength { +protected: + virtual STAccount* duplicate() const { return new STAccount(name, value); } + static STAccount* construct(SerializerIterator&, const char *name = NULL); + public: STAccount(const std::vector& v) : STVariableLength(v) { ; } STAccount(const char *n, const std::vector& v) : STVariableLength(n, v) { ; } STAccount(const char *n) : STVariableLength(n) { ; } STAccount() { ; } - static STAccount* construct(SerializerIterator&, const char *name = NULL); + static std::auto_ptr deserialize(SerializerIterator& sit, const char *name) + { return std::auto_ptr(construct(sit, name)); } SerializedTypeID getSType() const { return STI_ACCOUNT; } - virtual STAccount* duplicate() const { return new STAccount(name, value); } std::string getText() const; NewcoinAddress getValueNCA() const; @@ -378,17 +413,20 @@ class STTaggedList : public SerializedType protected: std::vector value; + STTaggedList* duplicate() const { return new STTaggedList(name, value); } + static STTaggedList* construct(SerializerIterator&, const char *name = NULL); + public: STTaggedList() { ; } STTaggedList(const char *n) : SerializedType(n) { ; } STTaggedList(const std::vector& v) : value(v) { ; } STTaggedList(const char *n, const std::vector& v) : SerializedType(n), value(v) { ; } - static STTaggedList* construct(SerializerIterator&, const char *name = NULL); + static std::auto_ptr deserialize(SerializerIterator& sit, const char *name) + { return std::auto_ptr(construct(sit, name)); } int getLength() const; SerializedTypeID getSType() const { return STI_TL; } - STTaggedList* duplicate() const { return new STTaggedList(name, value); } std::string getText() const; void add(Serializer& s) const { if(s.addTaggedList(value)<0) throw(0); }