diff --git a/Application.cpp b/Application.cpp index 8fbc6d1999..c5b3a5aaab 100644 --- a/Application.cpp +++ b/Application.cpp @@ -34,7 +34,8 @@ Application::Application() void Application::run() { - theApp->setDB(new SqliteDatabase("data.db")); + string filename=strprintf("%sdata.db",theConfig.DATA_DIR); + theApp->setDB(new SqliteDatabase(filename.c_str())); mDatabase->connect(); if(theConfig.PEER_PORT) diff --git a/Config.cpp b/Config.cpp index e35f4c2724..517d2a20dc 100644 --- a/Config.cpp +++ b/Config.cpp @@ -13,6 +13,9 @@ Config::Config() VERSION=1; TEST_NET=false; + NETWORK_START_TIME=1319844908; + + PEER_PORT=6561; RPC_PORT=5001; NUMBER_CONNECTIONS=30; @@ -32,7 +35,7 @@ Config::Config() RPC_USER="admin"; RPC_PASSWORD="pass"; - HISTORY_DIR="history/"; + DATA_DIR=""; TRANSACTION_FEE=1000; ACCOUNT_FEE=1000; diff --git a/Config.h b/Config.h index 199ba15a3a..57ac47320c 100644 --- a/Config.h +++ b/Config.h @@ -6,6 +6,7 @@ public: int VERSION; std::string VERSION_STR; bool TEST_NET; + int NETWORK_START_TIME; // The Unix time we start ledger 0 int TRANSACTION_FEE; int ACCOUNT_FEE; @@ -22,7 +23,7 @@ public: std::string RPC_PASSWORD; std::string HANKO; - std::string HISTORY_DIR; + std::string DATA_DIR; int MIN_VOTES_FOR_CONSENSUS; diff --git a/Convertion.cpp b/Conversion.cpp similarity index 80% rename from Convertion.cpp rename to Conversion.cpp index b6d6ce4c4f..3c11bb958d 100644 --- a/Convertion.cpp +++ b/Conversion.cpp @@ -1,4 +1,4 @@ -#include "Convertion.h" +#include "Conversion.h" #include "base58.h" using namespace std; @@ -21,11 +21,8 @@ uint160 humanTo160(const std::string& buf) vector retVec; DecodeBase58(buf,retVec); uint160 ret; - for(unsigned int n=0; n=ret.GetSerializeSize()) break; - ret.begin()[n]=retVec[n]; - } + memcpy((unsigned char*)&ret,&retVec[0],ret.GetSerializeSize()); + return(ret); } diff --git a/Convertion.h b/Conversion.h similarity index 100% rename from Convertion.h rename to Conversion.h diff --git a/Ledger.cpp b/Ledger.cpp index 8a9ceafa50..595b646de2 100644 --- a/Ledger.cpp +++ b/Ledger.cpp @@ -3,7 +3,7 @@ #include "PackedMessage.h" #include "Application.h" #include "Config.h" -#include "Convertion.h" +#include "Conversion.h" #include "BitcoinUtil.h" #include #include @@ -203,41 +203,6 @@ void Ledger::save() } } -/* -bool Ledger::load(std::string dir) -{ - - string filename=strprintf("%s%u.ledger",dir,mIndex); - - ifstream loadfile(filename, ios::in | ios::binary); - if(loadfile.is_open()) // TODO: does this fail correctly? - { - newcoin::FullLedger ledger; - ledger.ParseFromIstream(&loadfile); - loadfile.close(); - setTo(ledger); - return(true); - } - - return(false); -} - - -void Ledger::save(string dir) -{ - string filename=strprintf("%s%u.ledger",dir,mIndex); - - newcoin::FullLedger* ledger=createFullLedger(); - ofstream savefile(filename, ios::out | ios::trunc | ios::binary); - if(savefile.is_open()) - { - ledger->SerializeToOstream(&savefile); - savefile.close(); - } - delete(ledger); -} -*/ - int64 Ledger::getAmountHeld(uint160& address) { if(mAccounts.count(address)) @@ -440,7 +405,7 @@ void Ledger::recalculate(bool recursive) void Ledger::parentAddedTransaction(TransactionPtr cause) { - // TODO: we can make this more efficient at some point. For now just redo everything + // TODO: optimize we can make this more efficient at some point. For now just redo everything recalculate(); diff --git a/LedgerMaster.cpp b/LedgerMaster.cpp index 4ff70f2860..77ed22dcbf 100644 --- a/LedgerMaster.cpp +++ b/LedgerMaster.cpp @@ -1,14 +1,16 @@ #include "LedgerMaster.h" #include "Application.h" #include "NewcoinAddress.h" -#include "Convertion.h" +#include "TimingService.h" +#include "Conversion.h" #include using namespace std; LedgerMaster::LedgerMaster() { - //mAfterProposed=false; + mFinalizingLedger=Ledger::pointer(); + mCurrentLedger=Ledger::pointer(new Ledger(TimingService::getCurrentLedgerIndex())); } void LedgerMaster::load() @@ -128,11 +130,11 @@ bool LedgerMaster::addTransaction(TransactionPtr trans) void LedgerMaster::addFullLedger(newcoin::FullLedger& ledger) { // check if we already have this ledger - // check that the hash is correct uint256 inHash=protobufTo256(ledger.hash()); Ledger::pointer existingLedger=mLedgerHistory.getLedger( inHash ); if(existingLedger) return; + // check that the hash is correct Ledger::pointer newLedger=Ledger::pointer(new Ledger(ledger)); if(newLedger->getHash()==inHash) { @@ -210,36 +212,39 @@ void LedgerMaster::checkLedgerProposal(Peer::pointer peer, newcoin::ProposeLedge // if doesn't match and you have <= transactions ask for the complete ledger // if doesn't match and you have > transactions send your complete ledger - if(otherLedger.ledgerindex()getIndex()) - { // you have already closed this ledger - Ledger::pointer oldLedger=mLedgerHistory.getAcceptedLedger(otherLedger.ledgerindex()); - if(oldLedger) - { - if( (oldLedger->getHash()!=protobufTo256(otherLedger.hash())) && - (oldLedger->getNumTransactions()>=otherLedger.numtransactions())) + + if(otherLedger.ledgerindex()getIndex()) + { + if( (!mFinalizingLedger) || + otherLedger.ledgerindex()getIndex()) + { // you have already closed this ledger + Ledger::pointer oldLedger=mLedgerHistory.getAcceptedLedger(otherLedger.ledgerindex()); + if(oldLedger) { - peer->sendLedgerProposal(oldLedger); + if( (oldLedger->getHash()!=protobufTo256(otherLedger.hash())) && + (oldLedger->getNumTransactions()>=otherLedger.numtransactions())) + { + peer->sendLedgerProposal(oldLedger); + } + } + }else + { // you guys are on the same page + uint256 otherHash=protobufTo256(otherLedger.hash()); + if(mFinalizingLedger->getHash()!= otherHash) + { + if( mFinalizingLedger->getNumTransactions()>=otherLedger.numtransactions()) + { + peer->sendLedgerProposal(mFinalizingLedger); + }else + { + peer->sendGetFullLedger(otherHash); + } } } - }else if(otherLedger.ledgerindex()>mFinalizingLedger->getIndex()) - { // you haven't started finalizing this one yet save it for when you do - addFutureProposal(peer,otherLedger); }else - { // you guys are on the same page - uint256 otherHash=protobufTo256(otherLedger.hash()); - if(mFinalizingLedger->getHash()!= otherHash) - { - if( mFinalizingLedger->getNumTransactions()>=otherLedger.numtransactions()) - { - peer->sendLedgerProposal(mFinalizingLedger); - }else - { - peer->sendGetFullLedger(otherHash); - } - } + { // you haven't started finalizing this one yet save it for when you do + addFutureProposal(peer,otherLedger); } - - } diff --git a/NewcoinAddress.h b/NewcoinAddress.h index 4a5ec3392d..7b9a69af61 100644 --- a/NewcoinAddress.h +++ b/NewcoinAddress.h @@ -4,6 +4,9 @@ #include "base58.h" +// TODO: https://en.bitcoin.it/wiki/Address +// TODO: Why do we need steps 5 and 6? why not just use a checksum function to get the checksum? + class NewcoinAddress : public CBase58Data { public: diff --git a/Peer.cpp b/Peer.cpp index 8bd0adada0..f8acb5bef4 100644 --- a/Peer.cpp +++ b/Peer.cpp @@ -6,7 +6,7 @@ //#include #include #include -#include "Convertion.h" +#include "Conversion.h" using namespace std; using namespace boost; @@ -226,14 +226,6 @@ void Peer::processReadBuffer() } break; - case newcoin::VALIDATION: - { - newcoin::Validation validation; - if(validation.ParseFromArray(&mReadbuf[HEADER_SIZE], mReadbuf.size() - HEADER_SIZE)) - receiveValidation(validation); - else cout << "parse error: " << type << endl; //else BOOST_LOG_TRIVIAL(info) << "Error: " << error; - } - break; case newcoin::FULL_LEDGER: { newcoin::FullLedger ledger; @@ -243,6 +235,23 @@ void Peer::processReadBuffer() } break; + case newcoin::VALIDATION: + { + newcoin::Validation validation; + if(validation.ParseFromArray(&mReadbuf[HEADER_SIZE], mReadbuf.size() - HEADER_SIZE)) + receiveValidation(validation); + else cout << "parse error: " << type << endl; //else BOOST_LOG_TRIVIAL(info) << "Error: " << error; + } + break; + case newcoin::PROPOSE_LEDGER: + { + newcoin::ProposeLedger prop; + if(prop.ParseFromArray(&mReadbuf[HEADER_SIZE], mReadbuf.size() - HEADER_SIZE)) + receiveProposeLedger(prop); + else cout << "parse error: " << type << endl; //else BOOST_LOG_TRIVIAL(info) << "Error: " << error; + } + break; + case newcoin::GET_FULL_LEDGER: { newcoin::GetFullLedger getFullLedger; @@ -259,14 +268,6 @@ void Peer::processReadBuffer() else cout << "parse error: " << type << endl; //else BOOST_LOG_TRIVIAL(info) << "Error: " << error; } - case newcoin::PROPOSE_LEDGER: - { - newcoin::ProposeLedger prop; - if(prop.ParseFromArray(&mReadbuf[HEADER_SIZE], mReadbuf.size() - HEADER_SIZE)) - receiveProposeLedger(prop); - else cout << "parse error: " << type << endl; //else BOOST_LOG_TRIVIAL(info) << "Error: " << error; - } - break; default: cout << "Unknown Msg: " << type << endl; //else BOOST_LOG_TRIVIAL(info) << "Error: " << error; } diff --git a/RPCServer.cpp b/RPCServer.cpp index 069f197438..77d2ac4cf2 100644 --- a/RPCServer.cpp +++ b/RPCServer.cpp @@ -9,7 +9,7 @@ #include "json/json_spirit_reader_template.h" #include "json/json_spirit_writer_template.h" #include "RPC.h" -#include "Convertion.h" +#include "Conversion.h" using namespace std; using namespace json_spirit; diff --git a/TimingService.cpp b/TimingService.cpp index 2f16545671..62b0c65f7f 100644 --- a/TimingService.cpp +++ b/TimingService.cpp @@ -3,6 +3,7 @@ #include "Application.h" #include +#include #include using namespace std; @@ -49,3 +50,8 @@ void TimingService::handleValid() theApp->getLedgerMaster().endFinalization(); } +int TimingService::getCurrentLedgerIndex() +{ + return( (time(NULL)-theConfig.NETWORK_START_TIME)/theConfig.LEDGER_SECONDS ); +} + diff --git a/TimingService.h b/TimingService.h index 12725cb725..b160ab7908 100644 --- a/TimingService.h +++ b/TimingService.h @@ -20,7 +20,7 @@ public: TimingService(); void start(boost::asio::io_service& ioService); - + static int getCurrentLedgerIndex(); }; #endif \ No newline at end of file diff --git a/Transaction.cpp b/Transaction.cpp index 97b2d32e68..8f739d2ff2 100644 --- a/Transaction.cpp +++ b/Transaction.cpp @@ -37,6 +37,6 @@ uint256 Transaction::calcHash(TransactionPtr trans) bool Transaction::isSigValid(TransactionPtr trans) { - // TODO: + // TODO: Transaction::isSigValid return(true); } \ No newline at end of file diff --git a/UniqueNodeList.cpp b/UniqueNodeList.cpp index 9f93fba700..21efa24965 100644 --- a/UniqueNodeList.cpp +++ b/UniqueNodeList.cpp @@ -1,6 +1,6 @@ #include "UniqueNodeList.h" #include "Application.h" -#include "Convertion.h" +#include "Conversion.h" using namespace std; diff --git a/ValidationCollection.cpp b/ValidationCollection.cpp index d3b1f9b8cd..49cb2ea5c6 100644 --- a/ValidationCollection.cpp +++ b/ValidationCollection.cpp @@ -2,7 +2,8 @@ #include "Application.h" #include "NewcoinAddress.h" #include "Config.h" -#include "Convertion.h" +#include "Conversion.h" +#include "Application.h" #include using namespace std; @@ -27,6 +28,12 @@ void ValidationCollection::load() } +void ValidationCollection::addToDB(newcoin::Validation& valid,bool weCare) +{ + Database* db=theApp->getDB(); + +} + bool ValidationCollection::hasValidation(uint256& ledgerHash,uint160& hanko,uint32 seqnum) { if(mValidations.count(ledgerHash)) @@ -69,11 +76,12 @@ void ValidationCollection::addValidation(newcoin::Validation& valid) mValidations[hash].push_back(valid); mIndexValidations[valid.ledgerindex()].push_back(valid); addToGroup(valid); - + addToDB(valid,true); theApp->getLedgerMaster().checkConsensus(valid.ledgerindex()); }else if(validity==0) { mIgnoredValidations[hash].push_back(valid); + addToDB(valid,false); }else { // the signature wasn't valid cout << "Invalid Validation" << endl; diff --git a/ValidationCollection.h b/ValidationCollection.h index f2ff481169..ff4973312e 100644 --- a/ValidationCollection.h +++ b/ValidationCollection.h @@ -11,8 +11,8 @@ class ValidationCollection { // from ledger hash to the validation - std::map > mValidations; - std::map > mIgnoredValidations; + //std::map > mValidations; + //std::map > mIgnoredValidations; // this maps ledgerIndex to an array of groups. Each group is a list of validations. // a validation can be in multiple groups since compatibility isn't transitive @@ -27,10 +27,11 @@ class ValidationCollection }; std::map > mIndexGroups; // all the groups at each index - std::map > mIndexValidations; // all the validations at each index + //std::map > mIndexValidations; // all the validations at each index bool hasValidation(uint256& ledgerHash,uint160& hanko,uint32 seqnum); void addToGroup(newcoin::Validation& valid); + void addToDB(newcoin::Validation& valid,bool weCare); public: ValidationCollection(); diff --git a/Wallet.cpp b/Wallet.cpp index cc0f941383..d3a540dd1b 100644 --- a/Wallet.cpp +++ b/Wallet.cpp @@ -1,6 +1,6 @@ #include "Wallet.h" #include "NewcoinAddress.h" -#include "Convertion.h" +#include "Conversion.h" #include "Application.h" #include "LedgerMaster.h" #include diff --git a/Wallet.h b/Wallet.h index 808b77baff..4bfc2c63a1 100644 --- a/Wallet.h +++ b/Wallet.h @@ -23,7 +23,6 @@ class Wallet : public CBasicKeyStore std::vector mPublicKey; std::vector mPrivateKey; int64 mAmount; - uint64 mAge; // do we need this uint32 mSeqNum; diff --git a/database/SqliteDatabase.cpp b/database/SqliteDatabase.cpp index 8f02c0aefd..d6bb75c8c8 100644 --- a/database/SqliteDatabase.cpp +++ b/database/SqliteDatabase.cpp @@ -70,7 +70,13 @@ int SqliteDatabase::getLastInsertID() // returns false if there are no results bool SqliteDatabase::startIterRows() { - needs to fill out the column table + mColNameTable.clear(); + mColNameTable.resize(sqlite3_column_count(mCurrentStmt)); + for(unsigned n=0; n +#include #include "../types.h" /* @@ -14,7 +15,7 @@ protected: std::string mUser; std::string mHost; std::string mDBPass; - std::string* mColNameTable; + std::vector mColNameTable; bool getColNumber(const char* colName, int* retIndex); diff --git a/db layout.txt b/db layout.txt index 2b544ca802..d84c21c7c7 100644 --- a/db layout.txt +++ b/db layout.txt @@ -10,6 +10,9 @@ CREATE TABLE LedgerAccountMap(LedgerID INT UNSIGNED,AccountID INT UNSIGNED); CREATE TABLE Accounts (AccountID INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, Address BLOB, Amount BIGINT UNSIGNED, SeqNum INT); CREATE TABLE AcceptedLedgers (LedgerIndex INT UNSIGNED PRIMARY KEY, LedgerID INT UNSIGNED); +CREATE TABLE Wallet (Address BLOB,PubKey BLOB,PrivateKey BLOB,int SeqNum); +CREATE TABLE YourValidations(LedgerIndex INT UNSIGNED PRIMARY KEY, Hash BLOB, SeqNum INT UNSIGNED ); + // MYSQL @@ -17,7 +20,7 @@ drop database if exists newcoin; CREATE DATABASE newcoin; use newcoin; CREATE TABLE UNL (Hanko BINARY(20) PRIMARY KEY, PubKey BINARY(128)); -CREATE TABLE Transactions (TransactionID INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, From BINARY(20), Dest BINARY(20), Amount BIGINT UNSIGNED, LedgerIndex INT UNSIGNED, SeqNum INT, PubKey BINARY(128), Sig BINARY(32)); +CREATE TABLE Transactions (TransactionID INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, From BINARY(20), Dest BINARY(20), Amount BIGINT UNSIGNED, LedgerIndex INT UNSIGNED, SeqNum INT, PubKey BINARY(64), Sig BINARY(32)); CREATE TABLE Ledgers (LedgerID INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, LedgerIndex INT UNSIGNED, Hash BINARY(32), ParentHash BINARY(32),FeeHeld BIGINT UNSIGNED); //, Accepted TINYINT CREATE TABLE Validations(LedgerIndex INT UNSIGNED, Hash BINARY(32), Hanko BINARY(20), SeqNum INT UNSIGNED, Sig BINARY(32), WeCare TINYINT); CREATE TABLE LedgerTransactionMap (LedgerID INT UNSIGNED, TransactionID INT UNSIGNED, Include TINYINT); diff --git a/main.cpp b/main.cpp index 7a5399433a..c891d44ef9 100644 --- a/main.cpp +++ b/main.cpp @@ -2,6 +2,7 @@ #include #include "CallRPC.h" +extern void runTests(); using namespace std; using namespace boost; @@ -44,6 +45,8 @@ int parseCommandline(int argc, char* argv[]) int main(int argc, char* argv[]) { + runTests(); + return(parseCommandline(argc,argv)); } diff --git a/newcoin.proto b/newcoin.proto index 7ac02136af..2d3fb9f25f 100644 --- a/newcoin.proto +++ b/newcoin.proto @@ -5,11 +5,11 @@ enum Type { TRANSACTION= 2; FULL_LEDGER= 3; VALIDATION= 4; - GET_FULL_LEDGER= 5; - GET_VALIDATIONS= 6; - GET_CONTACTS= 7; - CONTACT= 8; - PROPOSE_LEDGER= 9; + PROPOSE_LEDGER= 5; + GET_FULL_LEDGER= 6; + GET_VALIDATIONS= 7; + GET_CONTACTS= 8; + CONTACT= 9; ERROR_MSG= 10; } @@ -29,14 +29,13 @@ 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; - required bytes from = 2; - required bytes dest = 3; - required uint64 amount = 4; - required uint32 ledgerIndex = 5; - required int32 seqNum = 6; - required bytes pubKey = 7; - required bytes sig = 8; + required bytes from = 1; + required bytes dest = 2; + required uint64 amount = 3; + required uint32 ledgerIndex = 4; + required int32 seqNum = 5; + required bytes pubKey = 6; + required bytes sig = 7; } // Sequence number is incremented if you must change the ledger that you are validating diff --git a/newcoin.vcxproj b/newcoin.vcxproj index 4ed2def34b..628d4e4434 100644 --- a/newcoin.vcxproj +++ b/newcoin.vcxproj @@ -89,7 +89,7 @@ - + @@ -117,6 +117,7 @@ + @@ -134,7 +135,7 @@ - + @@ -205,6 +206,7 @@ + diff --git a/newcoin.vcxproj.filters b/newcoin.vcxproj.filters index 414c65909e..316de98532 100644 --- a/newcoin.vcxproj.filters +++ b/newcoin.vcxproj.filters @@ -147,7 +147,10 @@ Header Files\util - + + Source Files + + Source Files @@ -344,7 +347,7 @@ Header Files\util - + Header Files @@ -358,6 +361,7 @@ html + diff --git a/notes.txt b/notes.txt index 14d7c8fd66..cc30a3789e 100644 --- a/notes.txt +++ b/notes.txt @@ -25,7 +25,12 @@ code from: ---- -libeay32.dll +How much do we want to depend on the DB? Right now we are pulling a lot of stuff out f the DB and storing it in various data structures. but is that necessary? +Can't we keep everything in the DB? + LedgerMaster for example. mFutureTransactions should be in the DB + ValidationCollection +There is some trade off since reconstructing a whole ledger from the DB is a bit intense. So it might be good to cache these in memory. + diff --git a/todo.txt b/todo.txt new file mode 100644 index 0000000000..2337d27993 --- /dev/null +++ b/todo.txt @@ -0,0 +1,3 @@ + + +Remove data from DB when it is too old. diff --git a/uint256.h b/uint256.h index 51d1fe9c2f..3482b5267b 100644 --- a/uint256.h +++ b/uint256.h @@ -24,7 +24,7 @@ typedef unsigned long long uint64; inline int Testuint256AdHoc(std::vector vArg); - +// TODO: Do we need these things? Why not just use vector ? // We have to keep a separate base class without constructors // so the compiler will let us use it in a union