diff --git a/deploy/cointoss.nsi b/deploy/cointoss.nsi index 9e32d62bbd..1f3656ba7d 100644 --- a/deploy/cointoss.nsi +++ b/deploy/cointoss.nsi @@ -21,10 +21,10 @@ Page instfiles ; The stuff to install Section "" ;No components page, name is not important - ; Set output path to the installation directory. - SetOutPath $INSTDIR + ; Set output path to the installation directory. + SetOutPath $INSTDIR - ; Put file there + ; Put file there File ..\Release\newcoin.exe File ..\*.dll File "start CoinToss.bat" @@ -32,6 +32,8 @@ Section "" ;No components page, name is not important File validators.txt File /r /x .git ..\..\nc-client\*.* + CreateDirectory $INSTDIR\db + SectionEnd ; end the section diff --git a/newcoin.sln b/newcoin.sln index ad70dac84e..bae4207cc2 100644 --- a/newcoin.sln +++ b/newcoin.sln @@ -11,27 +11,39 @@ EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 FlashDebug|Win32 = FlashDebug|Win32 + FlashDebug|x64 = FlashDebug|x64 Release|Win32 = Release|Win32 + Release|x64 = Release|x64 ReleaseD|Win32 = ReleaseD|Win32 + ReleaseD|x64 = ReleaseD|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {19465545-42EE-42FA-9CC8-F8975F8F1CC7}.Debug|Win32.ActiveCfg = Debug|Win32 {19465545-42EE-42FA-9CC8-F8975F8F1CC7}.Debug|Win32.Build.0 = Debug|Win32 + {19465545-42EE-42FA-9CC8-F8975F8F1CC7}.Debug|x64.ActiveCfg = Debug|Win32 {19465545-42EE-42FA-9CC8-F8975F8F1CC7}.FlashDebug|Win32.ActiveCfg = Debug|Win32 {19465545-42EE-42FA-9CC8-F8975F8F1CC7}.FlashDebug|Win32.Build.0 = Debug|Win32 + {19465545-42EE-42FA-9CC8-F8975F8F1CC7}.FlashDebug|x64.ActiveCfg = Debug|Win32 {19465545-42EE-42FA-9CC8-F8975F8F1CC7}.Release|Win32.ActiveCfg = Release|Win32 {19465545-42EE-42FA-9CC8-F8975F8F1CC7}.Release|Win32.Build.0 = Release|Win32 + {19465545-42EE-42FA-9CC8-F8975F8F1CC7}.Release|x64.ActiveCfg = Release|Win32 {19465545-42EE-42FA-9CC8-F8975F8F1CC7}.ReleaseD|Win32.ActiveCfg = Release|Win32 {19465545-42EE-42FA-9CC8-F8975F8F1CC7}.ReleaseD|Win32.Build.0 = Release|Win32 + {19465545-42EE-42FA-9CC8-F8975F8F1CC7}.ReleaseD|x64.ActiveCfg = Release|Win32 {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}.Debug|Win32.ActiveCfg = Debug|Win32 {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}.Debug|Win32.Build.0 = Debug|Win32 + {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}.Debug|x64.ActiveCfg = Debug|Win32 {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}.FlashDebug|Win32.ActiveCfg = Debug|Win32 {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}.FlashDebug|Win32.Build.0 = Debug|Win32 + {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}.FlashDebug|x64.ActiveCfg = Debug|Win32 {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}.Release|Win32.ActiveCfg = Release|Win32 {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}.Release|Win32.Build.0 = Release|Win32 + {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}.Release|x64.ActiveCfg = Release|Win32 {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}.ReleaseD|Win32.ActiveCfg = Release|Win32 {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}.ReleaseD|Win32.Build.0 = Release|Win32 + {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}.ReleaseD|x64.ActiveCfg = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/newcoin.vcxproj b/newcoin.vcxproj index ea76caa586..e9790d155a 100644 --- a/newcoin.vcxproj +++ b/newcoin.vcxproj @@ -153,6 +153,15 @@ + + + + + + + + + @@ -233,14 +242,12 @@ - - Designer + - Document @@ -248,11 +255,7 @@ obj\src\newcoin.pb.h - - Designer - - diff --git a/newcoin.vcxproj.filters b/newcoin.vcxproj.filters index 0d25cfe28b..7de6413e29 100644 --- a/newcoin.vcxproj.filters +++ b/newcoin.vcxproj.filters @@ -25,18 +25,12 @@ {77d2a621-b503-4ce4-aee8-ef0b337c4ee2} - - {209ce0bd-b197-4cb2-ad50-f8f43bcd1e03} - - - {46b84833-f245-4c3d-94b8-472efdb3a040} - - - {b27b04b8-1c6e-4b20-9364-f18d4682dc00} - {60c3631e-8855-4a61-bdd3-9892d96242d5} + + {92775c5f-dc9f-4a97-a9a6-6d4bd4e424b4} + @@ -243,6 +237,33 @@ Source Files + + Source Files + + + Source Files\websocketpp + + + Source Files\websocketpp + + + Source Files\websocketpp + + + Source Files\websocketpp + + + Source Files\websocketpp + + + Source Files\websocketpp + + + Source Files\websocketpp + + + Source Files\websocketpp + @@ -475,23 +496,17 @@ - - - html - - - tests\client2 - + diff --git a/src/Application.h b/src/Application.h index ff0024adc7..5dac2be6cc 100644 --- a/src/Application.h +++ b/src/Application.h @@ -85,6 +85,7 @@ public: ValidationCollection& getValidations() { return mValidations; } bool isNew(const uint256& s) { return mSuppressions.addSuppression(s); } bool isNew(const uint160& s) { return mSuppressions.addSuppression(s); } + bool running() { return mTxnDB != NULL; } DatabaseCon* getTxnDB() { return mTxnDB; } DatabaseCon* getLedgerDB() { return mLedgerDB; } diff --git a/src/DBInit.cpp b/src/DBInit.cpp index bc1b71217b..2d390564ed 100644 --- a/src/DBInit.cpp +++ b/src/DBInit.cpp @@ -24,6 +24,8 @@ const char *TxnDBInit[] = { );", "CREATE INDEX AcctTxindex ON \ AccountTransactions(Account, LedgerSeq, TransID);", + "CREATE INDEX AcctLgrIndex ON \ + AccountTransactions(LedgerSeq, Account, TransID);", "END TRANSACTION;" }; diff --git a/src/HashPrefixes.h b/src/HashPrefixes.h new file mode 100644 index 0000000000..80c3d79685 --- /dev/null +++ b/src/HashPrefixes.h @@ -0,0 +1,29 @@ +#ifndef __HASHPREFIXES__ +#define __HASHPREFIXES__ + +#include "types.h" + +// TXN +const uint32 sHP_TransactionID = 0x54584E00; + +// STX +const uint32 sHP_TransactionSign = 0x53545800; + +// MLN +const uint32 sHP_LeafNode = 0x4D4C4E00; + +// MIN +const uint32 sHP_InnerNode = 0x4D494E00; + +// LGR +const uint32 sHP_Ledger = 0x4C575200; + +// VAL +const uint32 sHP_Validation = 0x56414C00; + +// PRP +const uint32 sHP_Proposal = 0x50525000; + +#endif + +// vim:ts=4 diff --git a/src/Ledger.cpp b/src/Ledger.cpp index 3838ce4104..fe125c360d 100644 --- a/src/Ledger.cpp +++ b/src/Ledger.cpp @@ -18,6 +18,7 @@ #include "Wallet.h" #include "BinaryFormats.h" #include "LedgerTiming.h" +#include "HashPrefixes.h" #include "Log.h" Ledger::Ledger(const NewcoinAddress& masterID, uint64 startAmount) : mTotCoins(startAmount), @@ -116,6 +117,7 @@ void Ledger::updateHash() } Serializer s(116); + s.add32(sHP_Ledger); addRaw(s); mHash = s.getSHA512Half(); mValidHash = true; @@ -440,7 +442,7 @@ void Ledger::addJson(Json::Value& ret, int options) void Ledger::setAcquiring(void) { - if (!mTransactionMap || !mAccountStateMap) throw SHAMapException(InvalidMap); + if (!mTransactionMap || !mAccountStateMap) throw std::runtime_error("invalid map"); mTransactionMap->setSynching(); mAccountStateMap->setSynching(); } diff --git a/src/LedgerProposal.cpp b/src/LedgerProposal.cpp index 7d79bf0b6b..4de5d37f4f 100644 --- a/src/LedgerProposal.cpp +++ b/src/LedgerProposal.cpp @@ -5,6 +5,7 @@ #include "key.h" #include "Application.h" +#include "HashPrefixes.h" LedgerProposal::LedgerProposal(const uint256& pLgr, uint32 seq, const uint256& tx, const NewcoinAddress& naPeerPublic) : mPreviousLedger(pLgr), mCurrentHash(tx), mProposeSeq(seq) @@ -37,7 +38,7 @@ uint256 LedgerProposal::getSigningHash() const { Serializer s(72); - s.add32(sProposeMagic); + s.add32(sHP_Proposal); s.add32(mProposeSeq); s.add256(mPreviousLedger); s.add256(mCurrentHash); diff --git a/src/LedgerProposal.h b/src/LedgerProposal.h index 35557920c5..6e924734ed 100644 --- a/src/LedgerProposal.h +++ b/src/LedgerProposal.h @@ -19,8 +19,6 @@ protected: NewcoinAddress mPublicKey; NewcoinAddress mPrivateKey; // If ours - static const uint32 sProposeMagic = 0x50525000; // PRP - public: typedef boost::shared_ptr pointer; diff --git a/src/NetworkOPs.cpp b/src/NetworkOPs.cpp index 8a055f203f..9220d86d4c 100644 --- a/src/NetworkOPs.cpp +++ b/src/NetworkOPs.cpp @@ -629,22 +629,46 @@ std::vector< std::pair > std::string sql = str(boost::format("SELECT LedgerSeq,TransID FROM AccountTransactions INDEXED BY AcctTxIndex " - " WHERE Account = '%s' AND LedgerSeq <= '%d' AND LedgerSeq >= '%d' ORDER BY LedgerSeq LIMIT 1000") + " WHERE Account = '%s' AND LedgerSeq <= '%d' AND LedgerSeq >= '%d' ORDER BY LedgerSeq LIMIT 1000;") % account.humanAccountID() % maxLedger % minLedger); - Database *db = theApp->getTxnDB()->getDB(); - ScopedLock dbLock = theApp->getTxnDB()->getDBLock(); - - SQL_FOREACH(db, sql) { - std::string txID; - db->getStr("TransID", txID); - affectedAccounts.push_back(std::make_pair(db->getInt("LedgerSeq"), uint256(txID))); + Database* db = theApp->getTxnDB()->getDB(); + ScopedLock dbLock = theApp->getTxnDB()->getDBLock(); + + SQL_FOREACH(db, sql) + { + std::string txID; + db->getStr("TransID", txID); + affectedAccounts.push_back(std::make_pair(db->getInt("LedgerSeq"), uint256(txID))); + } } return affectedAccounts; } +std::vector + NetworkOPs::getAffectedAccounts(uint32 ledgerSeq) +{ + std::vector accounts; + std::string sql = str(boost::format + ("SELECT DISTINCT Account FROM AccountTransactions INDEXED BY AcctLgrIndex WHERE LedgerSeq = '%d';") + % ledgerSeq); + NewcoinAddress acct; + { + Database* db = theApp->getTxnDB()->getDB(); + ScopedLock dblock = theApp->getTxnDB()->getDBLock(); + SQL_FOREACH(db, sql) + { + std::string str; + db->getStr("Account", str); + if (acct.setAccountID(str)) + accounts.push_back(acct); + } + } + return accounts; +} + bool NetworkOPs::recvValidation(SerializedValidation::pointer val) { Log(lsINFO) << "recvValidation " << val->getLedgerHash().GetHex(); diff --git a/src/NetworkOPs.h b/src/NetworkOPs.h index 9a55184744..b68f046efe 100644 --- a/src/NetworkOPs.h +++ b/src/NetworkOPs.h @@ -152,6 +152,7 @@ public: // client information retrieval functions std::vector< std::pair > getAffectedAccounts(const NewcoinAddress& account, uint32 minLedger, uint32 maxLedger); + std::vector getAffectedAccounts(uint32 ledgerSeq); // // Monitoring: publisher side diff --git a/src/Peer.cpp b/src/Peer.cpp index ea677631ca..8d9a823c95 100644 --- a/src/Peer.cpp +++ b/src/Peer.cpp @@ -566,18 +566,16 @@ void Peer::processReadBuffer() void Peer::recvHello(newcoin::TMHello& packet) { - Log(lsTRACE) << "Recv(Hello) v=" << packet.versionmajor() << "." << packet.versionminor(); bool bDetach = true; // Cancel verification timeout. (void) mVerifyTimer.cancel(); - if ((packet.minprotoversionmajor() > PROTO_VERSION_MAJ) || - ((packet.minprotoversionmajor() == PROTO_VERSION_MAJ) && (packet.minprotoversionminor() > PROTO_VERSION_MIN))) + if (packet.protoversionmin() < MAKE_VERSION_INT(MIN_PROTO_MAJOR, MIN_PROTO_MINOR)) { Log(lsINFO) << "Recv(Hello): Server requires protocol version " << - packet.minprotoversionmajor() << "." << packet.minprotoversionminor() << " we run " << - PROTO_VERSION_MAJ << "." << PROTO_VERSION_MIN; + GET_VERSION_MAJOR(packet.protoversion()) << "." << GET_VERSION_MINOR(packet.protoversion()) + << " we run " << PROTO_VERSION_MAJOR << "." << PROTO_VERSION_MINOR; } else if (!mNodePublic.setNodePublic(packet.nodepublic())) { @@ -590,16 +588,11 @@ void Peer::recvHello(newcoin::TMHello& packet) else { // Successful connection. Log(lsINFO) << "Recv(Hello): Connect: " << mNodePublic.humanNodePublic(); + if (packet.protoversion() != MAKE_VERSION_INT(PROTO_VERSION_MAJOR, PROTO_VERSION_MINOR)) + Log(lsINFO) << "Peer speaks version " << + (packet.protoversion() >> 16) << "." << (packet.protoversion() & 0xFF); mHello = packet; - if ( (packet.versionmajor() != SERVER_VERSION_MAJ) || (packet.versionminor() != SERVER_VERSION_MIN)) - { - if (packet.has_fullversion()) - Log(lsINFO) << " Peer is running version " << packet.fullversion(); - else - Log(lsINFO) << " Peer is running version " << packet.versionmajor() << "." << packet.versionminor(); - } - if (mClientConnect) { // If we connected due to scan, no longer need to scan. @@ -1119,12 +1112,8 @@ void Peer::sendHello() newcoin::TMHello h; - h.set_versionmajor(SERVER_VERSION_MAJ); - h.set_versionminor(SERVER_VERSION_MIN); - h.set_protoversionmajor(PROTO_VERSION_MAJ); - h.set_protoversionminor(PROTO_VERSION_MIN); - h.set_minprotoversionminor(MIN_PROTO_MAJ); - h.set_minprotoversionmajor(MIN_PROTO_MIN); + h.set_protoversion(MAKE_VERSION_INT(PROTO_VERSION_MAJOR, PROTO_VERSION_MINOR)); + h.set_protoversionmin(MAKE_VERSION_INT(MIN_PROTO_MAJOR, MIN_PROTO_MINOR)); h.set_fullversion(SERVER_VERSION); h.set_nettime(theApp->getOPs().getNetworkTimeNC()); h.set_nodepublic(theApp->getWallet().getNodePublic().humanNodePublic()); @@ -1164,26 +1153,24 @@ Json::Value Peer::getJson() { Json::Value ret(Json::objectValue); - ret["this"] = ADDRESS(this); + //ret["this"] = ADDRESS(this); ret["public_key"] = mNodePublic.ToString(); ret["ip"] = mIpPortConnect.first; ret["port"] = mIpPortConnect.second; if (mHello.has_fullversion()) ret["version"] = mHello.fullversion(); - else if (mHello.has_versionminor() && mHello.has_versionmajor()) - ret["version"] = boost::lexical_cast(mHello.versionmajor()) + "." + - boost::lexical_cast(mHello.versionminor()); - - if (mHello.has_protoversionminor() && mHello.has_protoversionmajor()) - ret["protocol"] = boost::lexical_cast(mHello.protoversionmajor()) + "." + - boost::lexical_cast(mHello.protoversionminor()); + if (mHello.has_protoversion() && + (mHello.protoversion() != MAKE_VERSION_INT(PROTO_VERSION_MAJOR, PROTO_VERSION_MINOR))) + ret["protocol"] = boost::lexical_cast(GET_VERSION_MAJOR(mHello.protoversion())) + "." + + boost::lexical_cast(GET_VERSION_MINOR(mHello.protoversion())); + /* if (!mIpPort.first.empty()) { ret["verified_ip"] = mIpPort.first; ret["verified_port"] = mIpPort.second; - } + }*/ return ret; } diff --git a/src/SHAMap.cpp b/src/SHAMap.cpp index ea592d60a5..0da1f50e85 100644 --- a/src/SHAMap.cpp +++ b/src/SHAMap.cpp @@ -79,7 +79,7 @@ std::stack SHAMap::getStack(const uint256& id, bool inc if (!node) { if (isSynching()) return stack; - throw SHAMapException(MissingNode); + throw std::runtime_error("missing node"); } } @@ -139,7 +139,7 @@ SHAMapTreeNode::pointer SHAMap::walkTo(const uint256& id, bool modify) uint256 childHash = inNode->getChildHash(branch); SHAMapTreeNode::pointer nextNode = getNode(inNode->getChildNodeID(branch), childHash, false); - if (!nextNode) throw SHAMapException(MissingNode); + if (!nextNode) throw std::runtime_error("missing node"); inNode = nextNode; } if (inNode->getTag() != id) return SHAMapTreeNode::pointer(); @@ -156,7 +156,7 @@ SHAMapTreeNode* SHAMap::walkToPointer(const uint256& id) const uint256& nextHash = inNode->getChildHash(branch); if (!nextHash) return NULL; inNode = getNodePointer(inNode->getChildNodeID(branch), nextHash); - if (!inNode) throw SHAMapException(MissingNode); + if (!inNode) throw std::runtime_error("missing node"); } return (inNode->getTag() == id) ? inNode : NULL; } @@ -175,17 +175,17 @@ SHAMapTreeNode::pointer SHAMap::getNode(const SHAMapNode& id, const uint256& has std::cerr << "NodHash " << node->getNodeHash().GetHex() << std::endl; dump(); #endif - throw SHAMapException(InvalidNode); + throw std::runtime_error("invalid node"); } returnNode(node, modify); return node; } - std::vector nodeData; - if (!fetchNode(hash, nodeData)) return SHAMapTreeNode::pointer(); + node = fetchNode(id, hash); + if (!node) return node; - node = boost::make_shared(id, nodeData, mSeq); - if (node->getNodeHash() != hash) throw SHAMapException(InvalidNode); + if (node->getNodeHash() != hash) + throw std::runtime_error("invalid node hash"); if (!mTNByID.insert(std::make_pair(id, node)).second) assert(false); @@ -198,12 +198,11 @@ SHAMapTreeNode* SHAMap::getNodePointer(const SHAMapNode& id, const uint256& hash if (it != mTNByID.end()) return &*it->second; - SHAMapTreeNode::pointer node; - std::vector nodeData; - if (!fetchNode(hash, nodeData)) return NULL; + SHAMapTreeNode::pointer node = fetchNode(id, hash); + if (!node) return NULL; - node = boost::make_shared(id, nodeData, mSeq); - if (node->getNodeHash() != hash) throw SHAMapException(InvalidNode); + if (node->getNodeHash() != hash) + throw std::runtime_error("invalid node fetched"); if (!mTNByID.insert(std::make_pair(id, node)).second) assert(false); @@ -367,9 +366,9 @@ SHAMapItem::pointer SHAMap::peekNextItem(const uint256& id) if(!node->isEmptyBranch(i)) { node = getNode(node->getChildNodeID(i), node->getChildHash(i), false); - if (!node) throw SHAMapException(MissingNode); + if (!node) throw std::runtime_error("missing node"); SHAMapItem::pointer item = firstBelow(&*node); - if (!item) throw SHAMapException(MissingNode); + if (!item) throw std::runtime_error("missing node"); return item; } } @@ -396,9 +395,9 @@ SHAMapItem::pointer SHAMap::peekPrevItem(const uint256& id) if(!node->isEmptyBranch(i)) { node = getNode(node->getChildNodeID(i), node->getChildHash(i), false); - if(!node) throw SHAMapException(MissingNode); + if(!node) throw std::runtime_error("missing node"); SHAMapItem::pointer item = firstBelow(&*node); - if (!item) throw SHAMapException(MissingNode); + if (!item) throw std::runtime_error("missing node"); return item; } } @@ -428,7 +427,7 @@ bool SHAMap::delItem(const uint256& id) assert(mState != Immutable); std::stack stack=getStack(id, true); - if(stack.empty()) throw SHAMapException(MissingNode); + if(stack.empty()) throw std::runtime_error("missing node"); SHAMapTreeNode::pointer leaf=stack.top(); stack.pop(); @@ -503,7 +502,7 @@ bool SHAMap::addGiveItem(SHAMapItem::pointer item, bool isTransaction) assert(mState != Immutable); std::stack stack = getStack(tag, true); - if (stack.empty()) throw SHAMapException(MissingNode); + if (stack.empty()) throw std::runtime_error("missing node"); SHAMapTreeNode::pointer node = stack.top(); stack.pop(); @@ -529,7 +528,7 @@ bool SHAMap::addGiveItem(SHAMapItem::pointer item, bool isTransaction) std::cerr << "NewNode: " << newNode->getString() << std::endl; dump(); assert(false); - throw SHAMapException(InvalidNode); + throw std::runtime_error("invalid inner node"); } node->setChildHash(branch, newNode->getNodeHash()); } @@ -594,7 +593,7 @@ bool SHAMap::updateGiveItem(SHAMapItem::pointer item, bool isTransaction) assert(mState != Immutable); std::stack stack = getStack(tag, true); - if (stack.empty()) throw SHAMapException(MissingNode); + if (stack.empty()) throw std::runtime_error("missing node"); SHAMapTreeNode::pointer node = stack.top(); stack.pop(); @@ -621,12 +620,15 @@ void SHAMapItem::dump() std::cerr << "SHAMapItem(" << mTag.GetHex() << ") " << mData.size() << "bytes" << std::endl; } -bool SHAMap::fetchNode(const uint256& hash, std::vector& data) +SHAMapTreeNode::pointer SHAMap::fetchNode(const SHAMapNode& id, const uint256& hash) { + if (!theApp->running()) return SHAMapTreeNode::pointer(); + HashedObject::pointer obj(theApp->getHashedObjectStore().retrieve(hash)); - if(!obj) return false; - data = obj->getData(); - return true; + if(!obj) return SHAMapTreeNode::pointer(); + assert(Serializer::getSHA512Half(obj->getData()) == hash); + + return boost::make_shared(id, obj->getData(), mSeq, STN_ARF_PREFIXED); } void SHAMap::armDirty() @@ -647,7 +649,7 @@ int SHAMap::flushDirty(int maxNodes, HashedObjectType t, uint32 seq) while (it != dirtyNodes.end()) { s.erase(); - it->second->addRaw(s); + it->second->addRaw(s, STN_ARF_PREFIXED); theApp->getHashedObjectStore().store(t, seq, s.peekData(), s.getSHA512Half()); if (flushed++ >= maxNodes) return flushed; @@ -679,7 +681,7 @@ SHAMapTreeNode::pointer SHAMap::getNode(const SHAMapNode& nodeID) return SHAMapTreeNode::pointer(); node = getNode(node->getChildNodeID(branch), node->getChildHash(branch), false); - if (!node) throw SHAMapException(MissingNode); + if (!node) throw std::runtime_error("missing node"); } return node; } diff --git a/src/SHAMap.h b/src/SHAMap.h index 8dda9db8d0..6c6770a122 100644 --- a/src/SHAMap.h +++ b/src/SHAMap.h @@ -158,8 +158,11 @@ public: SHAMapTreeNode(const SHAMapNode& nodeID, SHAMapItem::pointer item, TNType type, uint32 seq); // raw node functions - SHAMapTreeNode(const SHAMapNode& id, const std::vector& contents, uint32 seq); // raw node - void addRaw(Serializer &); + SHAMapTreeNode(const SHAMapNode& id, const std::vector& contents, uint32 seq, int format); + +#define STN_ARF_PREFIXED 1 +#define STN_ARF_WIRE 2 + void addRaw(Serializer &, int format); virtual bool isPopulated() const { return true; } @@ -205,13 +208,6 @@ public: virtual std::string getString() const; }; -enum SHAMapException -{ - MissingNode = 1, - InvalidNode = 2, - InvalidMap = 3, -}; - enum SHAMapState { Modifying = 0, // Objects can be added and removed (like an open ledger) @@ -337,7 +333,7 @@ public: uint32 getSeq() { return mSeq; } // overloads for backed maps - bool fetchNode(const uint256& hash, std::vector& rawNode); + boost::shared_ptr fetchNode(const SHAMapNode& id, const uint256& hash); bool operator==(const SHAMap& s) { return getHash() == s.getHash(); } diff --git a/src/SHAMapNodes.cpp b/src/SHAMapNodes.cpp index acd27eb271..dbdc8ee109 100644 --- a/src/SHAMapNodes.cpp +++ b/src/SHAMapNodes.cpp @@ -14,6 +14,7 @@ #include "Serializer.h" #include "BitcoinUtil.h" #include "Log.h" +#include "HashPrefixes.h" std::string SHAMapNode::getString() const { @@ -188,90 +189,99 @@ SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& node, SHAMapItem::pointer item, updateHash(); } -SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& id, const std::vector& rawNode, uint32 seq) +SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& id, const std::vector& rawNode, uint32 seq, int format) : SHAMapNode(id), mSeq(seq), mType(tnERROR), mFullBelow(false) { - Serializer s(rawNode); - - int type = s.removeLastByte(); - int len = s.getLength(); - if ((type < 0) || (type > 3)) throw SHAMapException(InvalidNode); - assert(len >= 33); - - if (type == 0) - { // transaction - mItem = boost::make_shared(s.getSHA512Half(), s.peekData()); - mType = tnTRANSACTION; - } - else if (type == 1) - { // account state - uint256 u; - s.get256(u, len - 32); - s.chop(256 / 8); - if (u.isZero()) throw SHAMapException(InvalidNode); - mItem = boost::make_shared(u, s.peekData()); - mType = tnACCOUNT_STATE; - } - else if (type == 2) - { // full inner - if (len != 512) throw SHAMapException(InvalidNode); - for (int i = 0; i < 16; ++i) - s.get256(mHashes[i], i * 32); - mType = tnINNER; - } - else if (type == 3) - { // compressed inner - for (int i = 0; i < (len / 33); ++i) + if (format == STN_ARF_WIRE) + { + Serializer s(rawNode); + int type = s.removeLastByte(); + int len = s.getLength(); + if ((type < 0) || (type > 3)) { - int pos; - s.get8(pos, 32 + (i * 33)); - if ((pos < 0) || (pos >= 16)) throw SHAMapException(InvalidNode); - s.get256(mHashes[pos], i * 33); +#ifdef DEBUG + std::cerr << "Invalid wire format node" << std::endl; + std::cerr << strHex(rawNode) << std::endl; + assert(false); +#endif + throw std::runtime_error("invalid node AW type"); } - mType = tnINNER; + + if (type == 0) + { // transaction + mItem = boost::make_shared(s.getPrefixHash(sHP_TransactionID), s.peekData()); + mType = tnTRANSACTION; + } + else if (type == 1) + { // account state + if (len < (256 / 8)) + throw std::runtime_error("short AS node"); + uint256 u; + s.get256(u, len - 32); + s.chop(256 / 8); + if (u.isZero()) throw std::runtime_error("invalid AS node"); + mItem = boost::make_shared(u, s.peekData()); + mType = tnACCOUNT_STATE; + } + else if (type == 2) + { // full inner + if (len != 512) + throw std::runtime_error("invalid FI node"); + for (int i = 0; i < 16; ++i) + s.get256(mHashes[i], i * 32); + mType = tnINNER; + } + else if (type == 3) + { // compressed inner + for (int i = 0; i < (len / 33); ++i) + { + int pos; + s.get8(pos, 32 + (i * 33)); + if ((pos < 0) || (pos >= 16)) throw std::runtime_error("invalid CI node"); + s.get256(mHashes[pos], i * 33); + } + mType = tnINNER; + } + } + + if (format == STN_ARF_PREFIXED) + { + if (rawNode.size() < 4) + throw std::runtime_error("invalid P node"); + + uint32 prefix = rawNode[0]; prefix <<= 8; prefix |= rawNode[1]; prefix <<= 8; + prefix |= rawNode[2]; prefix <<= 8; prefix |= rawNode[3]; + Serializer s(rawNode.begin() + 4, rawNode.end()); + + if (prefix == sHP_TransactionID) + { + mItem = boost::make_shared(Serializer::getSHA512Half(rawNode), s.peekData()); + mType = tnTRANSACTION; + } + if (prefix == sHP_LeafNode) + { + uint256 u; + s.get256(u, s.getLength() - 32); + s.chop(256 / 8); + if (u.isZero()) throw std::runtime_error("invalid PLN node"); + mItem = boost::make_shared(u, s.peekData()); + mType = tnACCOUNT_STATE; + } + if (prefix == sHP_InnerNode) + { + if (rawNode.size() != (512 + 4)) + throw std::runtime_error("invalid PIN node"); + for (int i = 0; i < 16; ++i) + s.get256(mHashes[i] , i * 32); + mType = tnINNER; + } + else + throw std::runtime_error("invalid node prefix"); } updateHash(); } -void SHAMapTreeNode::addRaw(Serializer &s) -{ - if (mType == tnERROR) throw SHAMapException(InvalidNode); - - if (mType == tnTRANSACTION) - { - mItem->addRaw(s); - s.add8(0); - assert(s.getLength() > 32); - return; - } - - if (mType == tnACCOUNT_STATE) - { - mItem->addRaw(s); - s.add256(mItem->getTag()); - s.add8(1); - return; - } - - if (getBranchCount() < 12) - { // compressed node - for (int i = 0; i < 16; ++i) - if (mHashes[i].isNonZero()) - { - s.add256(mHashes[i]); - s.add8(i); - } - s.add8(3); - return; - } - - for (int i = 0; i < 16; ++i) - s.add256(mHashes[i]); - - s.add8(2); -} - bool SHAMapTreeNode::updateHash() { uint256 nh; @@ -286,18 +296,19 @@ bool SHAMapTreeNode::updateHash() break; } if(!empty) - nh = Serializer::getSHA512Half(reinterpret_cast(mHashes), sizeof(mHashes)); + nh = Serializer::getPrefixHash(sHP_InnerNode, reinterpret_cast(mHashes), sizeof(mHashes)); } else if (mType == tnACCOUNT_STATE) { Serializer s; + s.add32(sHP_LeafNode); mItem->addRaw(s); s.add256(mItem->getTag()); nh = s.getSHA512Half(); } else if (mType == tnTRANSACTION) { - nh = Serializer::getSHA512Half(mItem->peekData()); + nh = Serializer::getPrefixHash(sHP_TransactionID, mItem->peekData()); } else assert(false); @@ -306,6 +317,70 @@ bool SHAMapTreeNode::updateHash() return true; } +void SHAMapTreeNode::addRaw(Serializer& s, int format) +{ + assert((format == STN_ARF_PREFIXED) || (format == STN_ARF_WIRE)); + if (mType == tnERROR) throw std::runtime_error("invalid I node type"); + + if (mType == tnINNER) + { + if (format == STN_ARF_PREFIXED) + { + s.add32(sHP_InnerNode); + for (int i = 0; i < 16; ++i) + s.add256(mHashes[i]); + } + else + { + if (getBranchCount() < 12) + { // compressed node + for (int i = 0; i < 16; ++i) + if (mHashes[i].isNonZero()) + { + s.add256(mHashes[i]); + s.add8(i); + } + s.add8(3); + } + else + { + for (int i = 0; i < 16; ++i) + s.add256(mHashes[i]); + s.add8(2); + } + } + } + else if (mType == tnACCOUNT_STATE) + { + if (format == STN_ARF_PREFIXED) + { + s.add32(sHP_LeafNode); + mItem->addRaw(s); + s.add256(mItem->getTag()); + } + else + { + mItem->addRaw(s); + s.add256(mItem->getTag()); + s.add8(1); + } + } + else if (mType == tnTRANSACTION) + { + if (format == STN_ARF_PREFIXED) + { + s.add32(sHP_TransactionID); + mItem->addRaw(s); + } + else + { + mItem->addRaw(s); + s.add8(0); + } + } + else assert(false); +} + bool SHAMapTreeNode::setItem(SHAMapItem::pointer& i, TNType type) { uint256 hash = getNodeHash(); diff --git a/src/SHAMapSync.cpp b/src/SHAMapSync.cpp index 089ca444b4..722c179b24 100644 --- a/src/SHAMapSync.cpp +++ b/src/SHAMapSync.cpp @@ -52,7 +52,7 @@ void SHAMap::getMissingNodes(std::vector& nodeIDs, std::vector nodeData; if (filter->haveNode(childID, childHash, nodeData)) { - d = boost::make_shared(childID, nodeData, mSeq); + d = boost::make_shared(childID, nodeData, mSeq, STN_ARF_WIRE); if (childHash != d->getNodeHash()) { Log(lsERROR) << "Wrong hash from cached object"; @@ -92,7 +92,7 @@ bool SHAMap::getNodeFat(const SHAMapNode& wanted, std::vector& nodeI nodeIDs.push_back(*node); Serializer s; - node->addRaw(s); + node->addRaw(s, STN_ARF_WIRE); rawNodes.push_back(s.peekData()); if (node->isRoot() || node->isLeaf()) // don't get a fat root, can't get a fat leaf @@ -107,7 +107,7 @@ bool SHAMap::getNodeFat(const SHAMapNode& wanted, std::vector& nodeI { nodeIDs.push_back(*nextNode); Serializer s; - nextNode->addRaw(s); + nextNode->addRaw(s, STN_ARF_WIRE); rawNodes.push_back(s.peekData()); } } @@ -126,7 +126,7 @@ bool SHAMap::addRootNode(const std::vector& rootNode) return true; } - SHAMapTreeNode::pointer node = boost::make_shared(SHAMapNode(), rootNode, 0); + SHAMapTreeNode::pointer node = boost::make_shared(SHAMapNode(), rootNode, 0, STN_ARF_WIRE); if (!node) return false; #ifdef DEBUG @@ -158,7 +158,7 @@ bool SHAMap::addRootNode(const uint256& hash, const std::vector& return true; } - SHAMapTreeNode::pointer node = boost::make_shared(SHAMapNode(), rootNode, 0); + SHAMapTreeNode::pointer node = boost::make_shared(SHAMapNode(), rootNode, 0, STN_ARF_WIRE); if (!node) return false; if (node->getNodeHash() != hash) return false; @@ -217,7 +217,7 @@ bool SHAMap::addKnownNode(const SHAMapNode& node, const std::vectorgetChildHash(branch); if (!hash) return false; - SHAMapTreeNode::pointer newNode = boost::make_shared(node, rawNode, mSeq); + SHAMapTreeNode::pointer newNode = boost::make_shared(node, rawNode, mSeq, STN_ARF_WIRE); if (hash != newNode->getNodeHash()) // these aren't the droids we're looking for return false; @@ -368,7 +368,7 @@ std::list > SHAMap::getTrustedPath(const uint256& ind Serializer s; while (!stack.empty()) { - stack.top()->addRaw(s); + stack.top()->addRaw(s, STN_ARF_WIRE); path.push_back(s.getData()); s.erase(); stack.pop(); @@ -380,13 +380,16 @@ BOOST_AUTO_TEST_SUITE( SHAMapSync ) BOOST_AUTO_TEST_CASE( SHAMapSync_test ) { + Log(lsTRACE) << "being sync test"; unsigned int seed; RAND_pseudo_bytes(reinterpret_cast(&seed), sizeof(seed)); srand(seed); + Log(lsTRACE) << "Constructing maps"; SHAMap source, destination; // add random data to the source map + Log(lsTRACE) << "Adding random data"; int items = 10000; for (int i = 0; i < items; ++i) source.addItem(*makeRandomAS(), false); diff --git a/src/SerializedTransaction.cpp b/src/SerializedTransaction.cpp index 16334e89d0..bab0a4a9f5 100644 --- a/src/SerializedTransaction.cpp +++ b/src/SerializedTransaction.cpp @@ -1,8 +1,9 @@ #include "SerializedTransaction.h" -#include "Application.h" +#include "Application.h" #include "Log.h" +#include "HashPrefixes.h" SerializedTransaction::SerializedTransaction(TransactionType type) : mType(type) { @@ -126,7 +127,7 @@ bool SerializedTransaction::isEquivalent(const SerializedType& t) const uint256 SerializedTransaction::getSigningHash() const { Serializer s; - s.add32(TransactionMagic); + s.add32(sHP_TransactionSign); mMiddleTxn.add(s); mInnerTxn.add(s); return s.getSHA512Half(); @@ -135,6 +136,7 @@ uint256 SerializedTransaction::getSigningHash() const uint256 SerializedTransaction::getTransactionID() const { // perhaps we should cache this Serializer s; + s.add32(sHP_TransactionID); mSignature.add(s); mMiddleTxn.add(s); mInnerTxn.add(s); diff --git a/src/SerializedValidation.cpp b/src/SerializedValidation.cpp index 71c11c831c..dd24a51726 100644 --- a/src/SerializedValidation.cpp +++ b/src/SerializedValidation.cpp @@ -1,6 +1,8 @@ #include "SerializedValidation.h" +#include "HashPrefixes.h" + SOElement SerializedValidation::sValidationFormat[] = { { sfFlags, "Flags", STI_UINT32, SOE_FLAGS, 0 }, { sfLedgerHash, "LedgerHash", STI_HASH256, SOE_REQUIRED, 0 }, @@ -11,7 +13,6 @@ SOElement SerializedValidation::sValidationFormat[] = { }; const uint32 SerializedValidation::sFullFlag = 0x00010000; -const uint32 SerializedValidation::sValidationMagic = 0x4c575200; // "LGR" SerializedValidation::SerializedValidation(SerializerIterator& sit, bool checkSignature) : STObject(sValidationFormat, sit), mSignature(sit, "Signature"), mTrusted(false) @@ -39,7 +40,7 @@ uint256 SerializedValidation::getSigningHash() const { Serializer s; - s.add32(sValidationMagic); + s.add32(sHP_Validation); add(s); return s.getSHA512Half(); diff --git a/src/SerializedValidation.h b/src/SerializedValidation.h index 863dea31b9..85cfa0d840 100644 --- a/src/SerializedValidation.h +++ b/src/SerializedValidation.h @@ -17,7 +17,6 @@ public: static SOElement sValidationFormat[16]; static const uint32 sFullFlag; - static const uint32 sValidationMagic; // These throw if the object is not valid SerializedValidation(SerializerIterator& sit, bool checkSignature = true); diff --git a/src/Serializer.cpp b/src/Serializer.cpp index 09536bb557..51fd734668 100644 --- a/src/Serializer.cpp +++ b/src/Serializer.cpp @@ -1,9 +1,15 @@ + #include "Serializer.h" -#include "key.h" + #include + #include #include +#include + +#include "key.h" + int Serializer::addZeros(size_t uBytes) { int ret = mData.size(); @@ -238,6 +244,24 @@ uint256 Serializer::getSHA512Half(const std::string& strData) return getSHA512Half(reinterpret_cast(strData.c_str()), strData.size()); } +uint256 Serializer::getPrefixHash(uint32 prefix, const unsigned char *data, int len) +{ + char be_prefix[4]; + be_prefix[0] = static_cast(prefix >> 24); + be_prefix[1] = static_cast((prefix >> 16) & 0xff); + be_prefix[2] = static_cast((prefix >> 8) & 0xff); + be_prefix[3] = static_cast(prefix & 0xff); + + uint256 j[2]; + SHA512_CTX ctx; + SHA512_Init(&ctx); + SHA512_Update(&ctx, &be_prefix[0], 4); + SHA512_Update(&ctx, data, len); + SHA512_Final(reinterpret_cast(&j[0]), &ctx); + + return j[0]; +} + bool Serializer::checkSignature(int pubkeyOffset, int signatureOffset) const { std::vector pubkey, signature; @@ -593,4 +617,23 @@ std::vector SerializerIterator::getRaw(int iLength) return mSerializer.getRaw(iPos, iLength); } +BOOST_AUTO_TEST_SUITE(Serializer_suite) + +BOOST_AUTO_TEST_CASE( Serializer_PrefixHash_test ) +{ + Serializer s1; + s1.add32(3); + s1.add256(uint256()); + + Serializer s2; + s2.add32(0x12345600); + s2.addRaw(s1.peekData()); + + if (s1.getPrefixHash(0x12345600) != s2.getSHA512Half()) + BOOST_FAIL("Prefix hash does not work"); +} + + +BOOST_AUTO_TEST_SUITE_END(); + // vim:ts=4 diff --git a/src/Serializer.h b/src/Serializer.h index 40613dd52b..a0962c43a4 100644 --- a/src/Serializer.h +++ b/src/Serializer.h @@ -67,7 +67,7 @@ public: bool getTaggedList(std::list&, int offset, int& length) const; bool getTaggedList(std::vector&, int offset, int& length) const; - // hash functions + // normal hash functions uint160 getRIPEMD160(int size=-1) const; uint256 getSHA256(int size=-1) const; uint256 getSHA512Half(int size=-1) const; @@ -75,6 +75,15 @@ public: static uint256 getSHA512Half(const unsigned char *data, int len); static uint256 getSHA512Half(const std::string& strData); + // prefix hash functions + static uint256 getPrefixHash(uint32 prefix, const unsigned char *data, int len); + uint256 getPrefixHash(uint32 prefix) const + { return getPrefixHash(prefix, &(mData.front()), mData.size()); } + static uint256 getPrefixHash(uint32 prefix, const std::vector& data) + { return getPrefixHash(prefix, &(data.front()), data.size()); } + static uint256 getPrefixHash(uint32 prefix, const std::string& strData) + { return getPrefixHash(prefix, reinterpret_cast(strData.c_str()), strData.size()); } + // totality functions int getCapacity() const { return mData.capacity(); } int getDataLength() const { return mData.size(); } diff --git a/src/Transaction.cpp b/src/Transaction.cpp index 934304195e..8baaa0a334 100644 --- a/src/Transaction.cpp +++ b/src/Transaction.cpp @@ -528,7 +528,7 @@ bool Transaction::save() Database *db = theApp->getTxnDB()->getDB(); ScopedLock dbLock = theApp->getTxnDB()->getDBLock(); - if (!SQL_EXISTS(db, exists)) return false; + if (SQL_EXISTS(db, exists)) return false; return db->executeSQL(mTransaction->getSQLInsertHeader() + mTransaction->getSQL(getLedger(), status) + ";"); } diff --git a/src/TransactionFormats.h b/src/TransactionFormats.h index 3f053521f2..d8c8fc38df 100644 --- a/src/TransactionFormats.h +++ b/src/TransactionFormats.h @@ -26,8 +26,6 @@ struct TransactionFormat SOElement elements[16]; }; -const int32 TransactionMagic = 0x54584E00; // 'TXN' - const int TransactionISigningPubKey = 0; const int TransactionISourceID = 1; const int TransactionISequence = 2; diff --git a/src/Version.h b/src/Version.h index e9fe8bc151..27cec8c5a2 100644 --- a/src/Version.h +++ b/src/Version.h @@ -1,22 +1,26 @@ // Versions -#ifndef SERVER_VERSION_MAJ +#ifndef SERVER_VERSION_MAJOR -#define SERVER_VERSION_MAJ 0 -#define SERVER_VERSION_MIN 1 +#define SERVER_VERSION_MAJOR 0 +#define SERVER_VERSION_MINOR 1 #define SERVER_VERSION_SUB "-a" #define SERVER_NAME "NewCoin" #define SV_STRINGIZE(x) SV_STRINGIZE2(x) #define SV_STRINGIZE2(x) #x #define SERVER_VERSION \ - (SERVER_NAME "-" SV_STRINGIZE(SERVER_VERSION_MAJ) "." SV_STRINGIZE(SERVER_VERSION_MIN) SERVER_VERSION_SUB) + (SERVER_NAME "-" SV_STRINGIZE(SERVER_VERSION_MAJOR) "." SV_STRINGIZE(SERVER_VERSION_MINOR) SERVER_VERSION_SUB) -#define PROTO_VERSION_MAJ 0 -#define PROTO_VERSION_MIN 0 +#define PROTO_VERSION_MAJOR 0 +#define PROTO_VERSION_MINOR 1 -#define MIN_PROTO_MAJ 0 -#define MIN_PROTO_MIN 0 +#define MIN_PROTO_MAJOR 0 +#define MIN_PROTO_MINOR 1 + +#define MAKE_VERSION_INT(maj,min) ((maj << 16) | min) +#define GET_VERSION_MAJOR(ver) (ver >> 16) +#define GET_VERSION_MINOR(ver) (ver & 0xff) #endif diff --git a/src/WSDoor.cpp b/src/WSDoor.cpp index 3b38380baf..198180de7d 100644 --- a/src/WSDoor.cpp +++ b/src/WSDoor.cpp @@ -45,8 +45,8 @@ class WSServerHandler; class WSConnection : public InfoSub { public: - typedef typename websocketpp::WSDOOR_SERVER::handler::connection_ptr connection_ptr; - typedef typename websocketpp::WSDOOR_SERVER::handler::message_ptr message_ptr; + typedef websocketpp::WSDOOR_SERVER::handler::connection_ptr connection_ptr; + typedef websocketpp::WSDOOR_SERVER::handler::message_ptr message_ptr; protected: typedef void (WSConnection::*doFuncPtr)(Json::Value& jvResult, const Json::Value &jvRequest); @@ -67,7 +67,7 @@ public: virtual ~WSConnection(); - // Implement overriden functions from base class: + // Implement overridden functions from base class: void send(const Json::Value& jvObj); // Utilities @@ -83,7 +83,7 @@ public: // A single instance of this object is made. -// This instance dispatches all events. There is no per connection persistency. +// This instance dispatches all events. There is no per connection persistence. template class WSServerHandler : public endpoint_type::handler { diff --git a/src/newcoin.proto b/src/newcoin.proto index 99d9b591fb..b12afbbe24 100644 --- a/src/newcoin.proto +++ b/src/newcoin.proto @@ -37,20 +37,16 @@ enum MessageType { message TMHello { - required uint32 versionMinor = 1; - required uint32 versionMajor = 2; - required uint32 protoVersionMinor = 3; - required uint32 protoVersionMajor = 4; - required uint32 minProtoVersionMinor = 5; - required uint32 minProtoVersionMajor = 6; - required bytes nodePublic = 7; - required bytes nodeProof = 8; - optional string fullVersion = 9; - optional uint64 netTime = 10; - optional uint32 ipv4Port = 11; - optional uint32 ledgerIndex = 12; - optional bytes closedLedger = 13; // our last closed ledger - optional bytes previousLedger = 14; // the ledger before the last closed ledger + required uint32 protoVersion = 1; + required uint32 protoVersionMin = 2; + required bytes nodePublic = 3; + required bytes nodeProof = 4; + optional string fullVersion = 5; + optional uint64 netTime = 6; + optional uint32 ipv4Port = 7; + optional uint32 ledgerIndex = 8; + optional bytes closedLedger = 9; // our last closed ledger + optional bytes previousLedger = 10; // the ledger before the last closed ledger }