diff --git a/Application.h b/Application.h index 1662200998..9faa98a0e0 100644 --- a/Application.h +++ b/Application.h @@ -36,7 +36,7 @@ public: LedgerMaster& getLedgerMaster(){ return(mLedgerMaster); } UniqueNodeList& getUNL(){ return(mUNL); } ValidationCollection& getValidationCollection(){ return(mValidations); } - + Wallet& getWallet(){ return(mWallet); } void run(); diff --git a/Config.cpp b/Config.cpp index ee8c907014..c840c568e9 100644 --- a/Config.cpp +++ b/Config.cpp @@ -15,8 +15,8 @@ Config::Config() RPC_PORT=5001; NUMBER_CONNECTIONS=30; - // a new ledger every 5 min - LEDGER_SECONDS=(60*5); + // a new ledger every 30 min + LEDGER_SECONDS=(60*30); // length of delay between start finalization and sending your first proposal // This delay allows us to collect a few extra transactions from people who's clock is different than ours @@ -26,11 +26,14 @@ Config::Config() // How long to wait between proposal send and ledger close. // at which point you publish your validation // You are only waiting to get extra transactions from your peers - LEDGER_FINALIZATION_SECONDS=30; + LEDGER_FINALIZATION_SECONDS=(60*5); RPC_USER="admin"; RPC_PASSWORD="pass"; HISTORY_DIR="history/"; + + TRANSACTION_FEE=1000; + ACCOUNT_FEE=1000; } void Config::load() diff --git a/Config.h b/Config.h index 62d9e17775..f2ae454cf0 100644 --- a/Config.h +++ b/Config.h @@ -7,6 +7,8 @@ public: std::string VERSION_STR; bool TEST_NET; + int TRANSACTION_FEE; + int ACCOUNT_FEE; int PEER_PORT; int RPC_PORT; int NUMBER_CONNECTIONS; diff --git a/ConnectionPool.cpp b/ConnectionPool.cpp index 6be6068099..5c1ac56167 100644 --- a/ConnectionPool.cpp +++ b/ConnectionPool.cpp @@ -27,7 +27,7 @@ void ConnectionPool::connectToNetwork(KnownNodeList& nodeList,boost::asio::io_se } } - +/* bool ConnectionPool::isMessageKnown(PackedMessage::pointer msg) { for(unsigned int n=0; n class KnownNodeList; + /* This is the list of all the Peers we are currently connected to */ class ConnectionPool { std::vector mPeers; - std::vector > mBroadcastMessages; + //std::vector > mBroadcastMessages; public: ConnectionPool(); void connectToNetwork(KnownNodeList& nodeList,boost::asio::io_service& io_service); - void relayMessage(Peer* fromPeer,PackedMessage::pointer msg,uint64 ledgerIndex); - bool isMessageKnown(PackedMessage::pointer msg); + void relayMessage(Peer* fromPeer,PackedMessage::pointer msg); + //bool isMessageKnown(PackedMessage::pointer msg); }; \ No newline at end of file diff --git a/Ledger.cpp b/Ledger.cpp index 36c3a1ba41..9f2b72fb4c 100644 --- a/Ledger.cpp +++ b/Ledger.cpp @@ -12,7 +12,7 @@ using namespace boost; using namespace std; -Ledger::Ledger(uint64 index) +Ledger::Ledger(uint32 index) { mIndex=index; mValidSig=false; @@ -22,19 +22,20 @@ Ledger::Ledger(uint64 index) // TODO: we should probably make a shared pointer type for each of these PB types newcoin::FullLedger* Ledger::createFullLedger() { - // TODO: do we need to hash and create mone map first? + // TODO: do we need to hash and create accounts map first? newcoin::FullLedger* ledger=new newcoin::FullLedger(); ledger->set_index(mIndex); ledger->set_hash(mHash); - pair& account=pair(); - BOOST_FOREACH(account,mMoneyMap) + pair >& account=pair >(); + BOOST_FOREACH(account,mAccounts) { newcoin::Account* saveAccount=ledger->add_accounts(); - saveAccount->set_address(account.first); - saveAccount->set_amount(account.second); + saveAccount->set_address(account.first.begin(),account.first.GetSerializeSize()); + saveAccount->set_amount(account.second.first); + saveAccount->set_seqnum(account.second.second); } - mBundle.addTransactionsToPB(ledger); + //mBundle.addTransactionsToPB(ledger); return(ledger); } @@ -42,8 +43,9 @@ newcoin::FullLedger* Ledger::createFullLedger() void Ledger::setTo(newcoin::FullLedger& ledger) { mIndex=ledger.index(); - mBundle.clear(); - mMoneyMap.clear(); + mTransactions.clear(); + mDiscardedTransactions.clear(); + mAccounts.clear(); mValidSig=false; mValidHash=false; @@ -51,14 +53,14 @@ void Ledger::setTo(newcoin::FullLedger& ledger) for(int n=0; n(account.amount(),account.seqnum()); } int numTrans=ledger.transactions_size(); for(int n=0; ngetConnectionPool().relayMessage(NULL,packet,mIndex); + theApp->getConnectionPool().relayMessage(NULL,packet); } void Ledger::finalize() @@ -121,8 +141,10 @@ void Ledger::sign() { // TODO: } + void Ledger::calcMoneyMap() { +/* // start with map from the previous ledger // go through every transaction Ledger::pointer parent=theApp->getLedgerMaster().getLedger(mIndex-1); @@ -133,7 +155,7 @@ void Ledger::calcMoneyMap() mBundle.updateMap(mMoneyMap); // TODO: strip the 0 ones - } + } */ } void Ledger::hash() @@ -143,62 +165,265 @@ void Ledger::hash() // TODO: } +/* uint64 Ledger::getAmount(std::string address) { - return(mMoneyMap[address]); -} + return(mAccounts[NewcoinAddress:: address].first); +}*/ -// returns true if the transaction was valid -bool Ledger::addTransaction(newcoin::Transaction& trans) +// returns true if the from account has enough for the transaction and seq num is correct +bool Ledger::addTransaction(TransactionPtr trans,bool checkDuplicate) { - if(mBundle.hasTransaction(trans)) return(false); + if(checkDuplicate && hasTransaction(trans)) return(false); - Ledger::pointer parent=theApp->getLedgerMaster().getLedger(mIndex-1); - if(parent) + if(mParent) { // check the lineage of the from addresses - vector cacheInputLeftOverAmount; - int numInputs=trans.inputs_size(); - cacheInputLeftOverAmount.resize(numInputs); - for(int n=0; nfrom()); + if(mAccounts.count(address)) { - const newcoin::TransInput& input=trans.inputs(n); - - uint64 amountHeld=parent->getAmount(input.from()); - // TODO: checkValid could invalidate mValidSig and mValidHash - amountHeld = mBundle.checkValid(input.from(),amountHeld,0,trans.seconds()); - if(amountHeld account=mAccounts[address]; + if( (account.firstamount()) && + (trans->seqnum()==account.second) ) { - mBundle.addDiscardedTransaction(trans); - cout << "Not enough money" << endl; - return(false); - } - cacheInputLeftOverAmount[n]=amountHeld-input.amount(); - } + account.first -= trans->amount(); + account.second++; + mAccounts[address]=account; - for(int n=0; ndest()); + + Account destAccount=mAccounts[destAddress]; + destAccount.first += trans->amount(); + mAccounts[destAddress]=destAccount; + + + mValidSig=false; + mValidHash=false; + mTransactions.push_back(trans); + if(mChild) + { + mChild->parentAddedTransaction(trans); + } + return(true); + }else + { + mDiscardedTransactions.push_back(trans); + return false; + } + }else { - const newcoin::TransInput& input=trans.inputs(n); - mBundle.checkValid(input.from(),cacheInputLeftOverAmount[n],trans.seconds(),theConfig.LEDGER_SECONDS); + mDiscardedTransactions.push_back(trans); + return false; } - mValidSig=false; - mValidHash=false; - mBundle.addTransaction(trans); - - }else - { // we have no way to know so just accept it + { // we have no way to know so just hold on to it but don't add to the accounts mValidSig=false; mValidHash=false; - mBundle.addTransaction(trans); + mDiscardedTransactions.push_back(trans); return(true); } - - - return(false); } -void Ledger::recheck(Ledger::pointer parent,newcoin::Transaction& cause) +// Don't check the amounts. We will do this at the end. +void Ledger::addTransactionRecalculate(TransactionPtr trans) { - // TODO: + uint160 fromAddress=NewcoinAddress::protobufToInternal(trans->from()); + + if(mAccounts.count(fromAddress)) + { + Account fromAccount=mAccounts[fromAddress]; + if(trans->seqnum()==fromAccount.second) + { + fromAccount.first -= trans->amount(); + fromAccount.second++; + mAccounts[fromAddress]=fromAccount; + + uint160 destAddress=NewcoinAddress::protobufToInternal(trans->dest()); + + Account destAccount=mAccounts[destAddress]; + destAccount.first += trans->amount(); + mAccounts[destAddress]=destAccount; + + mTransactions.push_back(trans); + + }else + { // invalid seqnum + mDiscardedTransactions.push_back(trans); + } + }else + { + if(trans->seqnum()==0) + { + + mAccounts[fromAddress]=Account(-((int64)trans->amount()),1); + + uint160 destAddress=NewcoinAddress::protobufToInternal(trans->dest()); + + Account destAccount=mAccounts[destAddress]; + destAccount.first += trans->amount(); + mAccounts[destAddress]=destAccount; + + mTransactions.push_back(trans); + + }else + { + mDiscardedTransactions.push_back(trans); + } + } +} + +// Must look for transactions to discard to make this account positive +// When we chuck transactions it might cause other accounts to need correcting +void Ledger::correctAccount(uint160& address) +{ + list effected; + + // do this in reverse so we take of the higher seqnum first + for( list::reverse_iterator iter=mTransactions.rbegin(); iter != mTransactions.rend(); ) + { + TransactionPtr trans= *iter; + if(NewcoinAddress::protobufToInternal(trans->from()) == address) + { + Account fromAccount=mAccounts[address]; + assert(fromAccount.second==trans->seqnum()+1); + if(fromAccount.first<0) + { + fromAccount.first += trans->amount(); + fromAccount.second --; + + mAccounts[address]=fromAccount; + + uint160 destAddress=NewcoinAddress::protobufToInternal(trans->dest()); + Account destAccount=mAccounts[destAddress]; + destAccount.first -= trans->amount(); + mAccounts[destAddress]=destAccount; + if(destAccount.first<0) effected.push_back(destAddress); + + list::iterator temp=mTransactions.erase( --iter.base() ); + if(fromAccount.first>=0) break; + + iter=list::reverse_iterator(temp); + }else break; + }else iter--; + } + + BOOST_FOREACH(uint160& address,effected) + { + correctAccount(address); + } + +} + +// start from your parent and go through every transaction +// calls this on its child if recursive is set +void Ledger::recalculate(bool recursive) +{ + if(mParent) + { + mValidSig=false; + mValidHash=false; + + mAccounts.clear(); + mAccounts=mParent->getAccounts(); + list firstTransactions=mTransactions; + list secondTransactions=mDiscardedTransactions; + + mTransactions.clear(); + mDiscardedTransactions.clear(); + + firstTransactions.sort(gTransactionSorter); + secondTransactions.sort(gTransactionSorter); + + // don't check balances until the end + BOOST_FOREACH(TransactionPtr trans,firstTransactions) + { + addTransactionRecalculate(trans); + } + + BOOST_FOREACH(TransactionPtr trans,secondTransactions) + { + addTransactionRecalculate(trans); + } + + pair& fullAccount=pair(); + BOOST_FOREACH(fullAccount,mAccounts) + { + if(fullAccount.second.first <0 ) + { + correctAccount(fullAccount.first); + } + } + + + if(mChild && recursive) mChild->recalculate(); + }else + { + cout << "Can't recalculate if there is no parent" << endl; + } +} + + + +void Ledger::parentAddedTransaction(TransactionPtr cause) +{ + // TODO: we can make this more efficient at some point. For now just redo everything + + recalculate(); + + /* + // IMPORTANT: these changes can't change the sequence number. This means we only need to check the dest account + // If there was a seqnum change we have to re-do all the transactions again + + // There was a change to the balances of the parent ledger + // This could cause: + // an account to now be negative so we have to discard one + // a discarded transaction to be pulled back in + // seqnum invalidation + uint160 fromAddress=NewcoinAddress::protobufToInternal(cause->from()); + uint160 destAddress=NewcoinAddress::protobufToInternal(cause->dest()); + + Account* fromAccount=getAccount(fromAddress); + Account* destAccount=getAccount(destAddress); + + if(fromAccount) + { + if(fromAccount->firstamount()) + { + fromAccount->first -= cause->amount(); + fromAccount->second = cause->seqnum()+1; + mAccounts[fromAddress] = *fromAccount; + }else cout << "This shouldn't happen2" << endl; + }else + { + cout << "This shouldn't happen" << endl; + } + + if(destAccount) + { + destAccount->first += cause->amount(); + mAccounts[destAddress]= *destAccount; + }else + { + mAccounts[destAddress]=pair(cause->amount(),cause->seqnum()); + } + + // look for discarded transactions + BOOST_FOREACH(TransactionPtr trans,) + */ +} + +bool Ledger::hasTransaction(TransactionPtr needle) +{ + BOOST_FOREACH(TransactionPtr trans,mTransactions) + { + if( Transaction::isEqual(needle,trans) ) return(true); + } + + BOOST_FOREACH(TransactionPtr disTrans,mDiscardedTransactions) + { + if( Transaction::isEqual(needle,disTrans) ) return(true); + } + + return(false); } \ No newline at end of file diff --git a/Ledger.h b/Ledger.h index d4d2d5ba9a..eda4eade5c 100644 --- a/Ledger.h +++ b/Ledger.h @@ -1,53 +1,80 @@ #ifndef __LEDGER__ #define __LEDGER__ -#include "TransactionBundle.h" +#include "Transaction.h" #include "types.h" +#include "BitcoinUtil.h" + #include #include #include +#include + + class Ledger : public boost::enable_shared_from_this { +public: + typedef boost::shared_ptr pointer; + typedef std::pair Account; +private: bool mValidSig; bool mValidHash; bool mFaith; //TODO: if you will bother to validate this ledger or not. You have to accept the first ledger on Faith - uint64 mIndex; + uint32 mIndex; std::string mHash; std::string mSignature; - std::map mMoneyMap; - TransactionBundle mBundle; - + + + std::map mAccounts; + std::list mTransactions; + std::list mDiscardedTransactions; + + //TransactionBundle mBundle; + + // these can be NULL + // we need to keep track in case there are changes in this ledger that effect either the parent or child. + Ledger::pointer mParent; + Ledger::pointer mChild; + void calcMoneyMap(); void sign(); void hash(); + void addTransactionRecalculate(TransactionPtr trans); + void correctAccount(uint160& address); public: typedef boost::shared_ptr pointer; - Ledger(uint64 index); + Ledger(uint32 index); void setTo(newcoin::FullLedger& ledger); void save(std::string dir); bool load(std::string dir); + void recalculate(bool recursive=true); + void publish(); void finalize(); - uint64 getAmount(std::string address); - void recheck(Ledger::pointer parent,newcoin::Transaction& cause); - bool addTransaction(newcoin::Transaction& trans); + bool hasTransaction(TransactionPtr trans); + int64 getAmountHeld(uint160& address); + void parentAddedTransaction(TransactionPtr cause); + bool addTransaction(TransactionPtr trans,bool checkDuplicate=true); void addValidation(newcoin::Validation& valid); void addIgnoredValidation(newcoin::Validation& valid); - uint64 getIndex(){ return(mIndex); } + uint32 getIndex(){ return(mIndex); } std::string& getHash(); std::string& getSignature(); - unsigned int getNumTransactions(){ return(mBundle.size()); } - std::map& getMoneyMap(){ return(mMoneyMap); } + unsigned int getNumTransactions(){ return(mTransactions.size()); } + std::map >& getAccounts(){ return(mAccounts); } + Account* getAccount(uint160& address); newcoin::FullLedger* createFullLedger(); + + }; #endif \ No newline at end of file diff --git a/LedgerHistory.cpp b/LedgerHistory.cpp index 9d659d4c5f..73651622ac 100644 --- a/LedgerHistory.cpp +++ b/LedgerHistory.cpp @@ -11,12 +11,12 @@ void LedgerHistory::load() } -bool LedgerHistory::loadLedger(uint64 index) +bool LedgerHistory::loadLedger(uint32 index) { Ledger::pointer ledger(new Ledger(index)); if(ledger->load(theConfig.HISTORY_DIR)) { - mLedgers[index]=ledger; + mAcceptedLedgers[index]=ledger; } return(false); } @@ -24,16 +24,16 @@ bool LedgerHistory::loadLedger(uint64 index) // this will see if the ledger is in memory // if not it will check disk and load it // if not it will return NULL -Ledger::pointer LedgerHistory::getLedger(uint64 index) +Ledger::pointer LedgerHistory::getLedger(uint32 index) { - if(mLedgers.count(index)) - return(mLedgers[index]); - if(loadLedger(index)) return(mLedgers[index]); + if(mAcceptedLedgers.count(index)) + return(mAcceptedLedgers[index]); + if(loadLedger(index)) return(mAcceptedLedgers[index]); return(Ledger::pointer()); } void LedgerHistory::addLedger(Ledger::pointer ledger) { - mLedgers[ledger->getIndex()]=ledger; + mAcceptedLedgers[ledger->getIndex()]=ledger; ledger->save(theConfig.HISTORY_DIR); } \ No newline at end of file diff --git a/LedgerHistory.h b/LedgerHistory.h index 450c11fc80..1f89a10319 100644 --- a/LedgerHistory.h +++ b/LedgerHistory.h @@ -4,18 +4,28 @@ #include "Ledger.h" /* -This is all the history that you know of. +This is a collection of all the ledgers you know about. +One thread of them is the thread you validate. +But you keep others that you have heard about. + +Why do you need to keep them all? + In case people ask. + To make sure that there isn't a conflict between the validated ledgers */ + class LedgerHistory { - std::map mLedgers; - bool loadLedger(uint64 index); + std::map mAcceptedLedgers; + std::map mAllLedgers; + + bool loadLedger(uint32 index); public: void load(); void addLedger(Ledger::pointer ledger); - Ledger::pointer getLedger(uint64 index); + Ledger::pointer getLedger(uint32 index); + Ledger::pointer getLedger(uint256 hash); }; #endif \ No newline at end of file diff --git a/LedgerMaster.cpp b/LedgerMaster.cpp index b5e5425c28..f7e22b6713 100644 --- a/LedgerMaster.cpp +++ b/LedgerMaster.cpp @@ -1,11 +1,13 @@ #include "LedgerMaster.h" #include "Application.h" +#include "NewcoinAddress.h" +#include using namespace std; LedgerMaster::LedgerMaster() { - mAfterProposed=false; + //mAfterProposed=false; } void LedgerMaster::load() @@ -18,69 +20,106 @@ void LedgerMaster::save() } -uint64 LedgerMaster::getCurrentLedgerIndex() +uint32 LedgerMaster::getCurrentLedgerIndex() { return(mCurrentLedger->getIndex()); } -int LedgerMaster::getCurrentLedgerSeconds() +int64 LedgerMaster::getAmountHeld(uint160& addr) { - // TODO: - return(1); + return(mCurrentLedger->getAmountHeld(addr)); } -uint64 LedgerMaster::getAmountHeld(std::string& addr) +int64 LedgerMaster::getAmountHeld(std::string& addr) { - return(mCurrentLedger->getAmount(addr)); + return(mCurrentLedger->getAmountHeld(NewcoinAddress::humanToInternal(addr))); } -Ledger::pointer LedgerMaster::getLedger(uint64 index) +Ledger::pointer LedgerMaster::getLedger(uint32 index) { return(mLedgerHistory.getLedger(index)); } -// TODO: make sure the signature is valid -// TODO: make sure the transactionID is valid -// TODO: make sure no from address = dest address -// TODO: make sure no 0 amounts -// TODO: make sure no duplicate from addresses -bool LedgerMaster::isValidTransactionSig(newcoin::Transaction& trans) +bool LedgerMaster::isTransactionOnFutureList(TransactionPtr needle) { + BOOST_FOREACH(TransactionPtr straw,mFutureTransactions) + { + if(Transaction::isEqual(straw,needle)) + { + return(true); + } + } + return(false); +} + + +// make sure the signature is valid +// make sure from address != dest address +// make sure not 0 amount unless null dest (this is just a way to make sure your seqnum is incremented) +// make sure the sequence number is good (but the ones with a bad seqnum we need to save still?) +bool LedgerMaster::isValidTransaction(TransactionPtr trans) +{ + if(trans->from()==trans->dest()) return(false); + if(trans->amount()==0) return(false); + if(!Transaction::isSigValid(trans)) return(false); + Ledger::Account* account=mCurrentLedger->getAccount( NewcoinAddress::protobufToInternal(trans->from()) ); + if(!account) return(false); + if(trans->seqnum() != (account->second+1) ) return(false); // TODO: do we need to save these? + return(true); } -// returns true if we should broadcast it -bool LedgerMaster::addTransaction(newcoin::Transaction& trans) -{ - if(! isValidTransactionSig(trans)) return(false); - if(trans.ledgerindex()==mFinalizingLedger->getIndex()) +// returns true if we should relay it +bool LedgerMaster::addTransaction(TransactionPtr trans) +{ + if(mFinalizingLedger && (trans->ledgerindex()==mFinalizingLedger->getIndex())) { - if(mFinalizingLedger->addTransaction(trans)) + if(mFinalizingLedger->hasTransaction(trans)) return(false); + if(!isValidTransaction(trans)) return(false); + + if(mFinalizingLedger->addTransaction(trans,false)) { // TODO: we shouldn't really sendProposal right here // TODO: since maybe we are adding a whole bunch at once. we should send at the end of the batch - if(mAfterProposed) sendProposal(); - mCurrentLedger->recheck(mFinalizingLedger,trans); + // TODO: do we ever really need to re-propose? + //if(mAfterProposed) sendProposal(); return(true); - } - }else if(trans.ledgerindex()==mCurrentLedger->getIndex()) + }else return(false); + }else if(trans->ledgerindex()==mCurrentLedger->getIndex()) { - return( mCurrentLedger->addTransaction(trans) ); - }else if(trans.ledgerindex()>mCurrentLedger->getIndex()) + if(mCurrentLedger->hasTransaction(trans)) return(false); + if(!isValidTransaction(trans)) return(false); + return( mCurrentLedger->addTransaction(trans,false) ); + }else if(trans->ledgerindex()>mCurrentLedger->getIndex()) { // in the future - // TODO: should we broadcast this? - // TODO: if NO then we might be slowing down transmission because our clock is off - // TODO: if YES then we could be contributing to not following the protocol - // TODO: Probably just broadcast once we get to that ledger. - mFutureTransactions.push_back(trans); + + if(isTransactionOnFutureList(trans)) return(false); + if(!isValidTransaction(trans)) return(false); + mFutureTransactions.push_back(trans); // broadcast once we get to that ledger. + return(false); }else - { // transaction is too old. ditch it + { // transaction is old but we don't have it. Add it to the current ledger cout << "Old Transaction" << endl; + + // distant past + // This is odd make sure the transaction is valid before proceeding since checking all the past is expensive + if(! isValidTransaction(trans)) return(false); + + uint32 checkIndex=trans->ledgerindex(); + while(checkIndex <= mCurrentLedger->getIndex()) + { + Ledger::pointer ledger=mLedgerHistory.getLedger(checkIndex); + if(ledger) + { + if(ledger->hasTransaction(trans)) return(false); + } + checkIndex++; + } + + return( mCurrentLedger->addTransaction(trans,false) ); } - - return(false); } @@ -94,9 +133,9 @@ void LedgerMaster::gotFullLedger(newcoin::FullLedger& ledger) void LedgerMaster::sendProposal() { - mAfterProposed=true; + //mAfterProposed=true; PackedMessage::pointer packet=Peer::createLedgerProposal(mFinalizingLedger); - theApp->getConnectionPool().relayMessage(NULL,packet,mFinalizingLedger->getIndex()); + theApp->getConnectionPool().relayMessage(NULL,packet); } void LedgerMaster::nextLedger() @@ -105,7 +144,7 @@ void LedgerMaster::nextLedger() // finalize current ledger // start a new ledger - mAfterProposed=false; + //mAfterProposed=false; Ledger::pointer closedLedger=mFinalizingLedger; mFinalizingLedger=mCurrentLedger; mCurrentLedger=Ledger::pointer(new Ledger(mCurrentLedger->getIndex()+1)); @@ -114,8 +153,8 @@ void LedgerMaster::nextLedger() closedLedger->publish(); mLedgerHistory.addLedger(closedLedger); - applyFutureProposals(); - applyFutureTransactions(); + applyFutureProposals( mFinalizingLedger->getIndex() ); + applyFutureTransactions( mCurrentLedger->getIndex() ); } void LedgerMaster::addFutureProposal(Peer::pointer peer,newcoin::ProposeLedger& otherLedger) @@ -123,11 +162,11 @@ void LedgerMaster::addFutureProposal(Peer::pointer peer,newcoin::ProposeLedger& mFutureProposals.push_front(pair(peer,otherLedger)); } -void LedgerMaster::applyFutureProposals() +void LedgerMaster::applyFutureProposals(uint32 ledgerIndex) { for(list< pair >::iterator iter=mFutureProposals.begin(); iter !=mFutureProposals.end(); ) { - if( (*iter).second.ledgerindex() == mFinalizingLedger->getIndex()) + if( (*iter).second.ledgerindex() == ledgerIndex) { checkLedgerProposal((*iter).first,(*iter).second); mFutureProposals.erase(iter); @@ -135,11 +174,11 @@ void LedgerMaster::applyFutureProposals() } } -void LedgerMaster::applyFutureTransactions() +void LedgerMaster::applyFutureTransactions(uint32 ledgerIndex) { - for(list::iterator iter=mFutureTransactions.begin(); iter !=mFutureTransactions.end(); ) + for(list::iterator iter=mFutureTransactions.begin(); iter !=mFutureTransactions.end(); ) { - if( (*iter).ledgerindex() == mCurrentLedger->getIndex() ) + if( (*iter)->ledgerindex() == ledgerIndex) { addTransaction(*iter); mFutureTransactions.erase(iter); diff --git a/LedgerMaster.h b/LedgerMaster.h index 8f9519b1fc..0d4ad45580 100644 --- a/LedgerMaster.h +++ b/LedgerMaster.h @@ -5,6 +5,7 @@ #include "LedgerHistory.h" #include "Peer.h" #include "types.h" +#include "Transaction.h" /* Handles: @@ -12,6 +13,9 @@ Handles: finalizing the ledger validating the past ledger keeping the ledger history + + There is one ledger we are working on. + */ class LedgerMaster { @@ -19,28 +23,31 @@ class LedgerMaster Ledger::pointer mFinalizingLedger; LedgerHistory mLedgerHistory; - std::list mFutureTransactions; + std::list mFutureTransactions; std::list< std::pair > mFutureProposals; - bool mAfterProposed; + //bool mAfterProposed; void addFutureProposal(Peer::pointer peer,newcoin::ProposeLedger& packet); - void applyFutureProposals(); - void applyFutureTransactions(); - bool isValidTransactionSig(newcoin::Transaction& trans); + void applyFutureProposals(uint32 ledgerIndex); + void applyFutureTransactions(uint32 ledgerIndex); + bool isValidTransaction(TransactionPtr trans); + bool isTransactionOnFutureList(TransactionPtr trans); public: LedgerMaster(); void load(); void save(); - uint64 getCurrentLedgerIndex(); - int getCurrentLedgerSeconds(); - Ledger::pointer getLedger(uint64 index); - uint64 getAmountHeld(std::string& addr); + uint32 getCurrentLedgerIndex(); + //int getCurrentLedgerSeconds(); + Ledger::pointer getLedger(uint32 index); + int64 getAmountHeld(std::string& addr); + int64 getAmountHeld(uint160& addr); + Ledger::Account* getAccount(uint160& addr){ return(mCurrentLedger->getAccount(addr)); } - bool addTransaction(newcoin::Transaction& trans); + bool addTransaction(TransactionPtr trans); void gotFullLedger(newcoin::FullLedger& ledger); void nextLedger(); diff --git a/NewcoinAddress.h b/NewcoinAddress.h index 79b5dbe5f2..c02ab821ef 100644 --- a/NewcoinAddress.h +++ b/NewcoinAddress.h @@ -20,6 +20,10 @@ public: bool IsValid(); uint160 GetHash160(); + + static uint160 protobufToInternal(const std::string& buf); + static uint160 humanToInternal(const std::string& buf); + }; diff --git a/Peer.cpp b/Peer.cpp index 78a6055b2f..57926cbb3b 100644 --- a/Peer.cpp +++ b/Peer.cpp @@ -145,7 +145,7 @@ void Peer::sendFullLedger(Ledger::pointer ledger) } } -void Peer::sendGetFullLedger(uint64 index) +void Peer::sendGetFullLedger(uint32 index) { newcoin::GetFullLedger* gfl=new newcoin::GetFullLedger(); gfl->set_ledgerindex(index); @@ -207,8 +207,8 @@ void Peer::processReadBuffer() break; case newcoin::TRANSACTION: { - newcoin::Transaction trans; - if(trans.ParseFromArray(&mReadbuf[HEADER_SIZE], mReadbuf.size() - HEADER_SIZE)) + TransactionPtr trans(new newcoin::Transaction()); + if(trans->ParseFromArray(&mReadbuf[HEADER_SIZE], mReadbuf.size() - HEADER_SIZE)) receiveTransaction(trans); else cout << "parse error: " << type << endl; //else BOOST_LOG_TRIVIAL(info) << "Error: " << error; @@ -289,25 +289,22 @@ void Peer::receiveGetValidations(newcoin::GetValidations& request) } } -void Peer::receiveTransaction(newcoin::Transaction& trans) +void Peer::receiveTransaction(TransactionPtr trans) { - ConnectionPool& pool=theApp->getConnectionPool(); - PackedMessage::pointer packet(new PackedMessage(PackedMessage::MessagePointer(new newcoin::Transaction(trans)),newcoin::TRANSACTION)); - - // check if this transaction is already known - if(pool.isMessageKnown(packet)) return; - - // check if this transaction is valid - // add to the correct transaction bundle - if(!theApp->getLedgerMaster().addTransaction(trans)) + // add to the correct transaction bundle and relay if we need to + if(theApp->getLedgerMaster().addTransaction(trans)) { - cout << "Invalid transaction: " << trans.transid() << endl; - return; + // tell the wallet in case it was to us + theApp->getWallet().transactionAdded(trans); + + // broadcast it to other Peers + ConnectionPool& pool=theApp->getConnectionPool(); + PackedMessage::pointer packet(new PackedMessage(PackedMessage::MessagePointer(new newcoin::Transaction(*(trans.get()))),newcoin::TRANSACTION)); + pool.relayMessage(this,packet); + }else + { + cout << "Invalid transaction: " << trans->from() << endl; } - - // broadcast it to other Peers - pool.relayMessage(this,packet,trans.ledgerindex()); - } void Peer::receiveProposeLedger(newcoin::ProposeLedger& packet) diff --git a/Peer.h b/Peer.h index a768b5e874..f5f1e2ab8e 100644 --- a/Peer.h +++ b/Peer.h @@ -7,6 +7,7 @@ #include "newcoin.pb.h" #include "PackedMessage.h" #include "Ledger.h" +#include "Transaction.h" #include "list" class KnownNode; @@ -48,7 +49,7 @@ class Peer : public boost::enable_shared_from_this void sendTransaction(); void sendValidation(); void receiveHello(newcoin::Hello& packet); - void receiveTransaction(newcoin::Transaction& packet); + void receiveTransaction(TransactionPtr trans); void receiveValidation(newcoin::Validation& packet); void receiveFullLedger(newcoin::FullLedger& packet); void receiveProposeLedger(newcoin::ProposeLedger& packet); @@ -78,7 +79,7 @@ public: void sendPacket(PackedMessage::pointer packet); void sendLedgerProposal(Ledger::pointer ledger); void sendFullLedger(Ledger::pointer ledger); - void sendGetFullLedger(uint64 index); + void sendGetFullLedger(uint32 index); //static PackedMessage::pointer createFullLedger(Ledger::pointer ledger); static PackedMessage::pointer createLedgerProposal(Ledger::pointer ledger); diff --git a/Transaction.cpp b/Transaction.cpp new file mode 100644 index 0000000000..8f514ab8b9 --- /dev/null +++ b/Transaction.cpp @@ -0,0 +1,35 @@ +#include "Transaction.h" +#include "BitcoinUtil.h" + +using namespace std; + + +// sort by from address and then seqnum +bool gTransactionSorter(const TransactionPtr& lhs, const TransactionPtr& rhs) +{ + if(lhs->from() == rhs->from()) + { + return(lhs->seqnum() < rhs->seqnum() ); + }else return lhs->from() < rhs->from(); +} + +// I don't think we need to bother checking the sig or public key +bool Transaction::isEqual(TransactionPtr t1,TransactionPtr t2) +{ + if(t1->amount() != t2->amount()) return(false); + if(t1->seqnum() != t2->seqnum()) return(false); + if(t1->ledgerindex() != t2->ledgerindex()) return(false); + if(t1->from() != t2->from()) return(false); + if(t1->dest() != t2->dest()) return(false); + + return(true); +} + + +uint256 Transaction::calcHash(TransactionPtr trans) +{ + vector buffer; + buffer.resize(trans->ByteSize()); + trans->SerializeToArray(&(buffer[0]),buffer.size()); + return Hash(buffer.begin(), buffer.end()); +} \ No newline at end of file diff --git a/Transaction.h b/Transaction.h index f93cd75390..332cfb4452 100644 --- a/Transaction.h +++ b/Transaction.h @@ -1,17 +1,25 @@ -#include "string" +#ifndef __TRANSACTION__ +#define __TRANSACTION__ + +#include "newcoin.pb.h" +#include "uint256.h" +#include /* -A transaction can have only one input and one output. -If you want to send an amount that is greater than any single address of yours -you must first combine coins from one address to another. +We could have made something that inherited from the protobuf transaction but this seemed simpler */ +typedef boost::shared_ptr TransactionPtr; + class Transaction { - std::string mSource; - std::string mSig; - std::string mDest; - unsigned int mAmount; public: - Transaction(); -}; \ No newline at end of file + static bool isSigValid(TransactionPtr trans); + static bool isEqual(TransactionPtr t1, TransactionPtr t2); + static uint256 calcHash(TransactionPtr trans); +}; + + +extern bool gTransactionSorter(const TransactionPtr& lhs, const TransactionPtr& rhs); + +#endif \ No newline at end of file diff --git a/TransactionBundle.cpp b/TransactionBundle.cpp index 8a4f06ec67..3097bef16d 100644 --- a/TransactionBundle.cpp +++ b/TransactionBundle.cpp @@ -3,9 +3,17 @@ using namespace std; +/* +// do we need to make sure this preserves the order you received the transactions? Otherwise when we run through it we can see invalid transactions that get funded later. +// No we can just allow this. We just check when a transaction comes in and at ledger close. +// There needs to be a predictable order or the hashes will all be different. +// bool gTransactionSorter(const newcoin::Transaction& lhs, const newcoin::Transaction& rhs) { - return lhs.seconds() < rhs.seconds(); + if(lhs.from() == rhs.from()) + { + return(lhs.seqnum() < rhs.seqnum() ); + }else return lhs.from() < rhs.from(); } @@ -14,23 +22,17 @@ TransactionBundle::TransactionBundle() } -bool TransactionBundle::isEqual(newcoin::Transaction& t1,newcoin::Transaction& t2) -{ - return(t1.transid()==t2.transid()); -} -bool TransactionBundle::hasTransaction(newcoin::Transaction& t) +bool TransactionBundle::hasTransaction(TransactionPtr needle) { - BOOST_FOREACH(newcoin::Transaction& trans,mTransactions) + BOOST_FOREACH(TransactionPtr trans,mTransactions) { - if( t.transid()==trans.transid()) - return(true); + if( Transaction::isEqual(needle,trans) ) return(true); } - BOOST_FOREACH(newcoin::Transaction& trans,mDisacrdedTransactions) + BOOST_FOREACH(TransactionPtr trans,mDisacrdedTransactions) { - if( t.transid()==trans.transid()) - return(true); + if( Transaction::isEqual(needle,trans) ) return(true); } return(false); @@ -38,35 +40,25 @@ bool TransactionBundle::hasTransaction(newcoin::Transaction& t) void TransactionBundle::addTransactionsToPB(newcoin::FullLedger* ledger) { - BOOST_FOREACH(newcoin::Transaction& trans,mTransactions) + BOOST_FOREACH(TransactionPtr trans,mTransactions) { - newcoin::Transaction* newTrans=ledger->add_transactions(); + TransactionPtr newTrans=ledger->add_transactions(); newTrans->operator=(trans); } } -void TransactionBundle::addDiscardedTransaction(newcoin::Transaction& trans) +void TransactionBundle::addDiscardedTransaction(TransactionPtr trans) { mDisacrdedTransactions.push_back(trans); - mDisacrdedTransactions.sort(gTransactionSorter); + //mDisacrdedTransactions.sort(gTransactionSorter); } -void TransactionBundle::addTransaction(const newcoin::Transaction& trans) +void TransactionBundle::addTransaction(const TransactionPtr trans) { mTransactions.push_back(trans); - mTransactions.sort(gTransactionSorter); + //mTransactions.sort(gTransactionSorter); } -uint64 TransactionBundle::getTotalTransAmount(newcoin::Transaction& trans) -{ - uint64 total=0; - int numInputs=trans.inputs_size(); - for(int n=0; n& moneyMap) moneyMap[trans.dest()] += total; } -} \ No newline at end of file +} + +*/ \ No newline at end of file diff --git a/TransactionBundle.h b/TransactionBundle.h index 415a891150..bceceb560f 100644 --- a/TransactionBundle.h +++ b/TransactionBundle.h @@ -4,11 +4,14 @@ #include #include "newcoin.pb.h" #include "types.h" +#include "Transaction.h" + class TransactionBundle { - std::list mTransactions; - std::list mDisacrdedTransactions; + // we have to order this before we hash so the hash will be consistent + std::list mTransactions; + std::list mDisacrdedTransactions; //std::list mAllTransactions; public: TransactionBundle(); @@ -19,7 +22,8 @@ public: void addTransactionsToPB(newcoin::FullLedger* ledger); - bool hasTransaction(newcoin::Transaction& trans); + bool hasTransaction(TransactionPtr trans); + // returns the amount of money this address holds at the end time // it will discard any transactions till endTime that bring amount held under 0 uint64 checkValid(std::string address, uint64 startAmount, @@ -29,13 +33,13 @@ public: // will check if all transactions after this are valid //void checkTransactions(); - void addTransaction(const newcoin::Transaction& trans); + void addTransaction(TransactionPtr trans); // transaction is valid and signed except the guy didn't have the money - void addDiscardedTransaction(newcoin::Transaction& trans); + void addDiscardedTransaction(TransactionPtr trans); - static bool isEqual(newcoin::Transaction& t1,newcoin::Transaction& t2); - static uint64 getTotalTransAmount(newcoin::Transaction& trans); + + //static uint64 getTotalTransAmount(TransactionPtr trans); }; #endif \ No newline at end of file diff --git a/ValidationCollection.h b/ValidationCollection.h index 477c5e9fbd..a07f8046b3 100644 --- a/ValidationCollection.h +++ b/ValidationCollection.h @@ -1,6 +1,8 @@ +#ifndef __VALIDATION_COLLECTION__ +#define __VALIDATION_COLLECTION__ #include "newcoin.pb.h" -#include "types.h" +#include "uint256.h" class ValidationCollection { @@ -14,4 +16,6 @@ public: void addValidation(newcoin::Validation& valid); std::vector* getValidations(uint64 ledgerIndex); -}; \ No newline at end of file +}; + +#endif \ No newline at end of file diff --git a/Wallet.cpp b/Wallet.cpp index c98dee1c42..63dde0354a 100644 --- a/Wallet.cpp +++ b/Wallet.cpp @@ -17,9 +17,9 @@ void Wallet::load() } -uint64 Wallet::getBalance() +int64 Wallet::getBalance() { - uint64 total = 0; + int64 total = 0; LedgerMaster& ledgerMaster=theApp->getLedgerMaster(); @@ -31,79 +31,99 @@ uint64 Wallet::getBalance() return total; } -string Wallet::sendMoneyToAddress(NewcoinAddress& destAddress, uint64 amount) +void Wallet::refreshAccounts() { - // Check amount - if(amount > getBalance()) - return("Insufficient funds"); + LedgerMaster& ledgerMaster=theApp->getLedgerMaster(); - newcoin::Transaction trans; - if(!createTransaction(destAddress, amount, trans)) + BOOST_FOREACH(Account& account, mYourAccounts) { - return "Error: Transaction creation failed "; + Ledger::Account* ledgerAccount=ledgerMaster.getAccount(account.mAddress); + if(ledgerAccount) + { + account.mAmount= ledgerAccount->first; + account.mSeqNum= ledgerAccount->second; + }else + { + account.mAmount=0; + account.mSeqNum=0; + } + } +} + +void Wallet::transactionAdded(TransactionPtr trans) +{ // TODO: optimize + refreshAccounts(); +} + +Wallet::Account* Wallet::consolidateAccountOfSize(int64 amount) +{ + int64 total=0; + BOOST_FOREACH(Account& account, mYourAccounts) + { + if(account.mAmount>=amount) return(&account); + total += account.mAmount; + } + if(totalmAddress,account.mAmount); + commitTransaction(trans); + }else firstAccount=&account; + + if(total>=amount) return(firstAccount); } - if(!commitTransaction(trans)) - return("Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."); + assert(0); + return(NULL); +} +string Wallet::sendMoneyToAddress(uint160& destAddress, int64 amount) +{ + // we may have to bundle up money in order to send this amount + Account* fromAccount=consolidateAccountOfSize(amount); + if(fromAccount) + { + TransactionPtr trans=createTransaction(*fromAccount,destAddress,amount); + if(trans) + { + if(!commitTransaction(trans)) + return("Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."); + + } + }else return("Insufficient funds"); return ""; } - -bool Wallet::createTransaction(NewcoinAddress& destAddress, uint64 amount,newcoin::Transaction& trans) +TransactionPtr Wallet::createTransaction(Account& fromAccount, uint160& destAddr, int64 amount) { - // find accounts to send from - // sign each account that is sending + TransactionPtr trans(new newcoin::Transaction()); + trans->set_amount(amount); + trans->set_seqnum(fromAccount.mSeqNum); + trans->set_from(fromAccount.mAddress.begin(), fromAccount.mAddress.GetSerializeSize()); + trans->set_dest(destAddr.begin(),destAddr.GetSerializeSize()); + trans->set_ledgerindex(theApp->getLedgerMaster().getCurrentLedgerIndex()); + // TODO: trans->set_pubkey(fromAccount.mPublicKey); + fromAccount.signTransaction(trans); - - trans.set_ledgerindex(theApp->getLedgerMaster().getCurrentLedgerIndex()); - trans.set_seconds(theApp->getLedgerMaster().getCurrentLedgerSeconds()); - trans.set_dest(destAddress.ToString()); - - list inputs; - BOOST_FOREACH(Account& account, mYourAccounts) - { - newcoin::TransInput* input=trans.add_inputs(); - inputs.push_back(input); - input->set_from(account.mAddress); - - if(account.mAmount < amount) - { // this account can only fill a portion of the amount - input->set_amount(account.mAmount); - amount -= account.mAmount; - - }else - { // this account can fill the whole thing - input->set_amount(amount); - - break; - } - } - - uint256 hash = calcTransactionHash(trans); - BOOST_FOREACH(newcoin::TransInput* input,inputs) - { - vector sig; - if(signTransInput(hash,*input,sig)) - input->set_sig(&(sig[0]),sig.size()); - else return(false); - } - trans.set_transid(hash.ToString()); - return(true); -} - -uint256 Wallet::calcTransactionHash(newcoin::Transaction& trans) -{ - vector buffer; - buffer.resize(trans.ByteSize()); - trans.SerializeToArray(&(buffer[0]),buffer.size()); - return Hash(buffer.begin(), buffer.end()); + return(trans); } -bool Wallet::signTransInput(uint256 hash, newcoin::TransInput& input,vector& retSig) + + +bool Wallet::Account::signTransaction(TransactionPtr trans) { + /* TODO: + uint256 hash = Transaction::calcHash(trans); + CKey key; if(!GetKey(input.from(), key)) return false; @@ -114,6 +134,7 @@ bool Wallet::signTransInput(uint256 hash, newcoin::TransInput& input,vectorgetConnectionPool().relayMessage(NULL,msg,trans.ledgerindex()); - theApp->getLedgerMaster().addTransaction(trans); + if(trans) + { + if(theApp->getLedgerMaster().addTransaction(trans)) + { + ConnectionPool& pool=theApp->getConnectionPool(); + PackedMessage::pointer packet(new PackedMessage(PackedMessage::MessagePointer(new newcoin::Transaction(*(trans.get()))),newcoin::TRANSACTION)); + pool.relayMessage(NULL,packet); - return true; + }else cout << "Problem adding the transaction to your local ledger" << endl; + } + return(false); } diff --git a/Wallet.h b/Wallet.h index 2173576944..444c723d6b 100644 --- a/Wallet.h +++ b/Wallet.h @@ -3,6 +3,7 @@ #include "keystore.h" #include "newcoin.pb.h" +#include "Transaction.h" #include #include @@ -17,28 +18,41 @@ class Wallet : public CBasicKeyStore { public: //CKey mKey; - std::string mAddress; - //std::vector mPublicKey; - //std::vector mPrivateKey; - uint64 mAmount; - uint64 mAge; + //std::string mHumanAddress; + uint160 mAddress; + std::vector mPublicKey; + std::vector mPrivateKey; + int64 mAmount; + uint64 mAge; // do we need this + uint32 mSeqNum; + + Account(){} + bool signTransaction(TransactionPtr input); }; std::list mYourAccounts; - bool signTransInput(uint256 hash, newcoin::TransInput& input,std::vector& retSig); - uint256 calcTransactionHash(newcoin::Transaction& trans); + + + TransactionPtr createTransaction(Account& fromAccount, uint160& destAddr, int64 amount); + bool commitTransaction(TransactionPtr trans); + + Account* consolidateAccountOfSize(int64 amount); - bool createTransaction(NewcoinAddress& destAddress, uint64 amount,newcoin::Transaction& trans); - bool commitTransaction(newcoin::Transaction& trans); public: Wallet(); + void refreshAccounts(); void load(); - uint64 getBalance(); + int64 getBalance(); // returns some human error str? - std::string sendMoneyToAddress(NewcoinAddress& destAddress, uint64 amount); + std::string sendMoneyToAddress(uint160& destAddress, int64 amount); + + // you may need to update your balances + void transactionAdded(TransactionPtr trans); + + }; #endif \ No newline at end of file diff --git a/newcoin.proto b/newcoin.proto index d373ef4295..0ffbb7c9ce 100644 --- a/newcoin.proto +++ b/newcoin.proto @@ -20,20 +20,20 @@ message Hello { required int32 port = 3; } -message TransInput { - required string from = 1; - required uint64 amount = 2; - required bytes sig = 3; -} -// TODO: do we need a transID? +/* +A transaction can have only one input and one output. +If you want to send an amount that is greater than any single address of yours +you must first combine coins from one address to another. +*/ +// TODO: do we need a transID? I don't think we do // ledgerIndex should increase the ledger coherence message Transaction { required bytes transID = 1; - repeated bytes from = 2; + required bytes from = 2; required bytes dest = 3; required uint64 amount = 4; - required uint64 ledgerIndex = 5; + required uint32 ledgerIndex = 5; required int32 seqNum = 6; required bytes pubKey = 7; required bytes sig = 8; @@ -42,13 +42,14 @@ message Transaction { // Sequence number is incremented if you must change the ledger that you are validating // You will only need to change validation in cases of incompatible ledgers message Validation { - required uint64 ledgerIndex = 1; - required string hash = 2; - required string hanko = 3; + required uint32 ledgerIndex = 1; + required bytes hash = 2; + required bytes hanko = 3; required int32 seqNum = 4; required bytes sig = 5; } +// seqnum should == last transaction seqnum+1 message Account { required bytes address = 1; required uint64 amount = 2; @@ -58,7 +59,7 @@ message Account { // The ledger hash includes: // index,accounts,feeHeld,transactions? message FullLedger { - required uint64 index = 1; + required uint32 index = 1; required bytes hash = 2; required bytes parentHash = 3; required uint64 feeHeld = 4; @@ -68,12 +69,12 @@ message FullLedger { message GetFullLedger { - required uint64 ledgerIndex = 1; + required uint32 ledgerIndex = 1; optional bytes hash = 2; } message GetValidations { - required uint64 ledgerIndex = 1; + required uint32 ledgerIndex = 1; } message Contact { @@ -87,7 +88,7 @@ message Contact { // but I think the times this will happen are very rare so it's probably not worth it // but it might be worth also sending a hash of the accounts since if these match you don't care that the transactions don't message ProposeLedger { - required uint64 ledgerIndex = 1; + required uint32 ledgerIndex = 1; required bytes hash = 2; optional uint64 numTransactions = 3; } diff --git a/newcoin.vcxproj b/newcoin.vcxproj index bbe3076057..6ecbaea4a1 100644 --- a/newcoin.vcxproj +++ b/newcoin.vcxproj @@ -49,12 +49,12 @@ Level3 Disabled _CRT_SECURE_NO_WARNINGS;_WIN32_WINNT=0x0501;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - c:\code\OpenSSL\include;C:\code\boost_1_47_0;C:\code\protobuf-2.4.1\src\ + ..\OpenSSL\include;..\boost_1_47_0;..\protobuf-2.4.1\src\ Console true - C:\code\OpenSSL\lib\VC;C:\code\boost_1_47_0\stage\lib;C:\code\protobuf-2.4.1\vsprojects\Debug + ..\OpenSSL\lib\VC;..\boost_1_47_0\stage\lib;..\protobuf-2.4.1\vsprojects\Debug libeay32MTd.lib;libprotobuf.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) @@ -112,6 +112,7 @@ + @@ -119,6 +120,7 @@ + @@ -167,6 +169,7 @@ + @@ -180,7 +183,7 @@ Document - c:/code/protoc-2.4.1-win32/protoc -I=C:\code\newcoin --cpp_out=C:\code\newcoin C:\code\newcoin\newcoin.proto + ..\protoc-2.4.1-win32\protoc -I=..\newcoin --cpp_out=..\newcoin ..\newcoin\newcoin.proto newcoin.pb.h diff --git a/newcoin.vcxproj.filters b/newcoin.vcxproj.filters index b0ba328ec6..2fba4e4424 100644 --- a/newcoin.vcxproj.filters +++ b/newcoin.vcxproj.filters @@ -129,6 +129,9 @@ Source Files + + Source Files + @@ -173,9 +176,6 @@ Header Files - - Header Files - Header Files\json @@ -299,6 +299,15 @@ Header Files + + Header Files + + + Header Files + + + Header Files + diff --git a/notes.txt b/notes.txt index 38dac6a813..b8ba6f8220 100644 --- a/notes.txt +++ b/notes.txt @@ -2,7 +2,7 @@ Dependencies: Boost 1_47 boost log http://boost-log.sourceforge.net/libs/log/doc/html/log/installation.html - protocol buffers + protocol buffers: expects ..\protobuf-2.4.1 and ..\protoc-2.4.1-win32 openssl Using: @@ -25,18 +25,9 @@ code from: -message Packet { - enum Type { HELLO = 1; TRANSACTION = 2; VALIDATION = 3; } - // Identifies which field is filled in. - required Type type = 1; - // One of the following will be filled in. - optional Hello hello=2; - optional Transaction transaction=3; - optional Validation validation=4; -} Threads ---- diff --git a/types.h b/types.h index 324271f598..52fe37e465 100644 --- a/types.h +++ b/types.h @@ -1,9 +1,15 @@ #if defined(_MSC_VER) || defined(__BORLANDC__) + typedef __int64 int64; typedef unsigned __int64 uint64; +typedef unsigned int uint32; + #else + typedef long long int64; typedef unsigned long long uint64; +typedef unsigned int uint32; + #endif #if defined(_MSC_VER) && _MSC_VER < 1300 #define for if (false) ; else for diff --git a/uint256.h b/uint256.h index ece52f3536..d2dc0f7327 100644 --- a/uint256.h +++ b/uint256.h @@ -364,7 +364,7 @@ public: } - unsigned int GetSerializeSize(int nType=0, int nVersion=VERSION) const + unsigned int GetSerializeSize(int nType=0) const { return sizeof(pn); }