This commit is contained in:
jed
2011-10-26 16:10:43 -07:00
parent fed4350ccc
commit 880c763dea
31 changed files with 1012 additions and 35 deletions

View File

@@ -5,6 +5,9 @@
#include "TimingService.h" #include "TimingService.h"
#include "ValidationCollection.h" #include "ValidationCollection.h"
#include "Wallet.h" #include "Wallet.h"
#include "Serializer.h"
#include "database/database.h"
#include <boost/asio.hpp> #include <boost/asio.hpp>
class RPCDoor; class RPCDoor;
@@ -18,12 +21,14 @@ class Application
KnownNodeList mKnownNodes; KnownNodeList mKnownNodes;
Wallet mWallet; Wallet mWallet;
ValidationCollection mValidations; ValidationCollection mValidations;
Database* mDatabase;
LedgerMaster mLedgerMaster; LedgerMaster mLedgerMaster;
ConnectionPool mConnectionPool; ConnectionPool mConnectionPool;
PeerDoor* mPeerDoor; PeerDoor* mPeerDoor;
RPCDoor* mRPCDoor; RPCDoor* mRPCDoor;
Serializer* mSerializer;
boost::asio::io_service mIOService; boost::asio::io_service mIOService;
@@ -37,6 +42,12 @@ public:
UniqueNodeList& getUNL(){ return(mUNL); } UniqueNodeList& getUNL(){ return(mUNL); }
ValidationCollection& getValidationCollection(){ return(mValidations); } ValidationCollection& getValidationCollection(){ return(mValidations); }
Wallet& getWallet(){ return(mWallet); } Wallet& getWallet(){ return(mWallet); }
Database* getDB(){ return(mDatabase); }
void setDatabase(Database* db){ mDatabase=db; }
Serializer* getSerializer(){ return(mSerializer); }
void setSerializer(Serializer* ser){ mSerializer=ser; }
void run(); void run();

View File

@@ -1,5 +1,8 @@
#include "Config.h" #include "Config.h"
#include "util/pugixml.hpp" #include "util/pugixml.hpp"
#include "Application.h"
#include "database/SqliteDatabase.h"
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
using namespace pugi; using namespace pugi;
@@ -50,5 +53,14 @@ void Config::load()
node= root.child("RPC_PORT"); node= root.child("RPC_PORT");
if(!node.empty()) RPC_PORT=boost::lexical_cast<int>(node.child_value()); if(!node.empty()) RPC_PORT=boost::lexical_cast<int>(node.child_value());
/*
node=root.child("DB_TYPE");
if(!node.empty())
{
if( stricmp(node.child_value(),"mysql")==0 ) theApp->setDB(Database::newMysqlDatabase("host","user","pass"));
else theApp->setSerializer(new DiskSerializer());
}else */
theApp->setDB(new SqliteDatabase());
} }

View File

@@ -28,6 +28,8 @@ public:
Config(); Config();
void load(); void load();

Binary file not shown.

View File

@@ -11,6 +11,13 @@
using namespace boost; using namespace boost;
using namespace std; using namespace std;
Ledger::Ledger()
{
mIndex=0;
mValidSig=false;
mValidHash=false;
mValidationSeqNum=0;
}
Ledger::Ledger(uint32 index) Ledger::Ledger(uint32 index)
{ {
@@ -20,6 +27,15 @@ Ledger::Ledger(uint32 index)
mValidationSeqNum=0; mValidationSeqNum=0;
} }
Ledger::Ledger(Ledger::pointer other)
{
mValidSig=false;
mValidHash=false;
mValidationSeqNum=0;
mIndex=other->getIndex();
mergeIn(other);
}
Ledger::Ledger(newcoin::FullLedger& ledger) Ledger::Ledger(newcoin::FullLedger& ledger)
{ {
setTo(ledger); setTo(ledger);
@@ -27,11 +43,11 @@ Ledger::Ledger(newcoin::FullLedger& ledger)
// TODO: we should probably make a shared pointer type for each of these PB types // TODO: we should probably make a shared pointer type for each of these PB types
newcoin::FullLedger* Ledger::createFullLedger() newcoin::FullLedger* Ledger::createFullLedger()
{ {
// TODO: do we need to hash and create accounts map first?
newcoin::FullLedger* ledger=new newcoin::FullLedger(); newcoin::FullLedger* ledger=new newcoin::FullLedger();
ledger->set_index(mIndex); ledger->set_index(mIndex);
ledger->set_hash(mHash.begin(),mHash.GetSerializeSize()); ledger->set_hash(getHash().begin(),getHash().GetSerializeSize());
ledger->set_parenthash(mParentHash.begin(),mParentHash.GetSerializeSize());
pair<uint160, pair<uint64,uint32> >& account=pair<uint160, pair<uint64,uint32> >(); pair<uint160, pair<uint64,uint32> >& account=pair<uint160, pair<uint64,uint32> >();
BOOST_FOREACH(account,mAccounts) BOOST_FOREACH(account,mAccounts)
@@ -41,7 +57,6 @@ newcoin::FullLedger* Ledger::createFullLedger()
saveAccount->set_amount(account.second.first); saveAccount->set_amount(account.second.first);
saveAccount->set_seqnum(account.second.second); saveAccount->set_seqnum(account.second.second);
} }
//mBundle.addTransactionsToPB(ledger);
return(ledger); return(ledger);
} }
@@ -81,8 +96,27 @@ Ledger::pointer Ledger::getParent()
return(mParent); return(mParent);
} }
bool Ledger::load(uint256& hash)
{
Database* db=theApp->getDB();
string sql="SELECT * from Ledgers where hash=";
string hashStr;
db->escape(hash.begin(),hash.GetSerializeSize(),hashStr);
sql.append(hashStr);
if(db->executeSQL(sql.c_str()))
{
db->getNextRow();
sql="SELECT * from Transactions where "
}
return(false);
}
/*
bool Ledger::load(std::string dir) bool Ledger::load(std::string dir)
{ {
string filename=strprintf("%s%u.ledger",dir,mIndex); string filename=strprintf("%s%u.ledger",dir,mIndex);
ifstream loadfile(filename, ios::in | ios::binary); ifstream loadfile(filename, ios::in | ios::binary);
@@ -112,6 +146,7 @@ void Ledger::save(string dir)
} }
delete(ledger); delete(ledger);
} }
*/
int64 Ledger::getAmountHeld(uint160& address) int64 Ledger::getAmountHeld(uint160& address)
{ {
@@ -151,13 +186,13 @@ void Ledger::publishValidation()
void Ledger::sign() void Ledger::sign()
{ {
// TODO: // TODO: Ledger::sign()
} }
void Ledger::hash() void Ledger::hash()
{ {
// TODO: // TODO: Ledger::hash()
} }
/* /*

View File

@@ -20,7 +20,6 @@ public:
private: private:
bool mValidSig; bool mValidSig;
bool mValidHash; bool mValidHash;
bool mFaith; //TODO: if you will bother to validate this ledger or not. You have to accept the first ledger on Faith
uint32 mIndex; uint32 mIndex;
uint256 mHash; uint256 mHash;
@@ -49,6 +48,7 @@ private:
void correctAccount(uint160& address); void correctAccount(uint160& address);
public: public:
typedef boost::shared_ptr<Ledger> pointer; typedef boost::shared_ptr<Ledger> pointer;
Ledger();
Ledger(uint32 index); Ledger(uint32 index);
Ledger(newcoin::FullLedger& ledger); Ledger(newcoin::FullLedger& ledger);
Ledger(Ledger::pointer other); Ledger(Ledger::pointer other);
@@ -56,8 +56,8 @@ public:
void setTo(newcoin::FullLedger& ledger); void setTo(newcoin::FullLedger& ledger);
void mergeIn(Ledger::pointer other); void mergeIn(Ledger::pointer other);
void save(std::string dir); void save(uint256& hash);
bool load(std::string dir); bool load(uint256& hash);
void recalculate(bool recursive=true); void recalculate(bool recursive=true);

View File

@@ -1,6 +1,7 @@
#include "LedgerHistory.h" #include "LedgerHistory.h"
#include "Config.h" #include "Config.h"
#include "Application.h"
#include <string>
/* /*
Soon we should support saving the ledger in a real DB Soon we should support saving the ledger in a real DB
For now save them all in For now save them all in
@@ -14,16 +15,33 @@ void LedgerHistory::load()
} }
bool LedgerHistory::loadLedger(uint32 index) bool LedgerHistory::loadLedger(uint256& hash)
{ {
Ledger::pointer ledger(new Ledger(index)); Ledger::pointer ledger=Ledger::pointer(new Ledger());
if(ledger->load(theConfig.HISTORY_DIR)) if(ledger->load(hash))
{ {
mAcceptedLedgers[index]=ledger; mAllLedgers[hash]=ledger;
return(true);
} }
return(false); return(false);
} }
bool LedgerHistory::loadAcceptedLedger(uint32 index)
{
Ledger::pointer ledger=theApp->getSerializer()->loadAcceptedLedger(index);
if(ledger)
{
mAcceptedLedgers[index]=ledger;
return(true);
}
return(false);
}
void LedgerHistory::addAcceptedLedger(Ledger::pointer ledger)
{
mAcceptedLedgers[ledger->getIndex()]=ledger;
}
// this will see if the ledger is in memory // this will see if the ledger is in memory
// if not it will check disk and load it // if not it will check disk and load it
// if not it will return NULL // if not it will return NULL
@@ -31,7 +49,7 @@ Ledger::pointer LedgerHistory::getAcceptedLedger(uint32 index)
{ {
if(mAcceptedLedgers.count(index)) if(mAcceptedLedgers.count(index))
return(mAcceptedLedgers[index]); return(mAcceptedLedgers[index]);
if(loadLedger(index)) return(mAcceptedLedgers[index]); if(loadAcceptedLedger(index)) return(mAcceptedLedgers[index]);
return(Ledger::pointer()); return(Ledger::pointer());
} }
@@ -39,4 +57,12 @@ void LedgerHistory::addLedger(Ledger::pointer ledger)
{ {
mAcceptedLedgers[ledger->getIndex()]=ledger; mAcceptedLedgers[ledger->getIndex()]=ledger;
ledger->save(theConfig.HISTORY_DIR); ledger->save(theConfig.HISTORY_DIR);
} }
Ledger::pointer LedgerHistory::getLedger(uint256& hash)
{
if(mAllLedgers.count(hash))
return(mAllLedgers[hash]);
if(loadLedger(hash)) return(mAllLedgers[hash]);
return(Ledger::pointer());
}

View File

@@ -18,7 +18,8 @@ class LedgerHistory
std::map<uint32, Ledger::pointer> mAcceptedLedgers; std::map<uint32, Ledger::pointer> mAcceptedLedgers;
std::map<uint256, Ledger::pointer> mAllLedgers; std::map<uint256, Ledger::pointer> mAllLedgers;
bool loadLedger(uint32 index); bool loadAcceptedLedger(uint32 index);
bool loadLedger(uint256& hash);
public: public:
void load(); void load();

View File

@@ -225,14 +225,15 @@ void LedgerMaster::checkLedgerProposal(Peer::pointer peer, newcoin::ProposeLedge
addFutureProposal(peer,otherLedger); addFutureProposal(peer,otherLedger);
}else }else
{ // you guys are on the same page { // you guys are on the same page
if(mFinalizingLedger->getHash()!= Transaction::protobufToInternalHash(otherLedger.hash())) uint256 otherHash=Transaction::protobufToInternalHash(otherLedger.hash());
if(mFinalizingLedger->getHash()!= otherHash)
{ {
if( mFinalizingLedger->getNumTransactions()>=otherLedger.numtransactions()) if( mFinalizingLedger->getNumTransactions()>=otherLedger.numtransactions())
{ {
peer->sendLedgerProposal(mFinalizingLedger); peer->sendLedgerProposal(mFinalizingLedger);
}else }else
{ {
peer->sendGetFullLedger(otherLedger.ledgerindex()); peer->sendGetFullLedger(otherHash);
} }
} }
} }

View File

@@ -3,6 +3,22 @@
#include "BitcoinUtil.h" #include "BitcoinUtil.h"
#include <assert.h> #include <assert.h>
uint160 NewcoinAddress::protobufToInternal(const std::string& buf)
{
uint160 ret;
// TODO:
return(ret);
}
uint160 NewcoinAddress::humanToInternal(const std::string& buf)
{
uint160 ret;
// TODO:
return(ret);
}
bool NewcoinAddress::SetHash160(const uint160& hash160) bool NewcoinAddress::SetHash160(const uint160& hash160)
{ {
SetData(theConfig.TEST_NET ? 112 : 1, &hash160, 20); SetData(theConfig.TEST_NET ? 112 : 1, &hash160, 20);

View File

@@ -134,6 +134,15 @@ PackedMessage::pointer Peer::createValidation(Ledger::pointer ledger)
return(packet); return(packet);
} }
PackedMessage::pointer Peer::createGetFullLedger(uint256& hash)
{
newcoin::GetFullLedger* gfl=new newcoin::GetFullLedger();
gfl->set_hash(hash.begin(),hash.GetSerializeSize());
PackedMessage::pointer packet(new PackedMessage(PackedMessage::MessagePointer(gfl),newcoin::GET_FULL_LEDGER));
return(packet);
}
void Peer::sendLedgerProposal(Ledger::pointer ledger) void Peer::sendLedgerProposal(Ledger::pointer ledger)
{ {
PackedMessage::pointer packet=Peer::createLedgerProposal(ledger); PackedMessage::pointer packet=Peer::createLedgerProposal(ledger);
@@ -150,12 +159,9 @@ void Peer::sendFullLedger(Ledger::pointer ledger)
} }
} }
void Peer::sendGetFullLedger(uint32 index) void Peer::sendGetFullLedger(uint256& hash)
{ {
newcoin::GetFullLedger* gfl=new newcoin::GetFullLedger(); PackedMessage::pointer packet=createGetFullLedger(hash);
gfl->set_ledgerindex(index);
PackedMessage::pointer packet(new PackedMessage(PackedMessage::MessagePointer(gfl),newcoin::GET_FULL_LEDGER));
sendPacket(packet); sendPacket(packet);
} }

2
Peer.h
View File

@@ -79,7 +79,7 @@ public:
void sendPacket(PackedMessage::pointer packet); void sendPacket(PackedMessage::pointer packet);
void sendLedgerProposal(Ledger::pointer ledger); void sendLedgerProposal(Ledger::pointer ledger);
void sendFullLedger(Ledger::pointer ledger); void sendFullLedger(Ledger::pointer ledger);
void sendGetFullLedger(uint32 index); void sendGetFullLedger(uint256& hash);
//static PackedMessage::pointer createFullLedger(Ledger::pointer ledger); //static PackedMessage::pointer createFullLedger(Ledger::pointer ledger);
static PackedMessage::pointer createLedgerProposal(Ledger::pointer ledger); static PackedMessage::pointer createLedgerProposal(Ledger::pointer ledger);

View File

@@ -32,4 +32,17 @@ uint256 Transaction::calcHash(TransactionPtr trans)
buffer.resize(trans->ByteSize()); buffer.resize(trans->ByteSize());
trans->SerializeToArray(&(buffer[0]),buffer.size()); trans->SerializeToArray(&(buffer[0]),buffer.size());
return Hash(buffer.begin(), buffer.end()); return Hash(buffer.begin(), buffer.end());
}
uint256 Transaction::protobufToInternalHash(const std::string& hash)
{
uint256 ret;
// TODO:
return(ret);
}
bool Transaction::isSigValid(TransactionPtr trans)
{
// TODO:
return(true);
} }

View File

@@ -1,7 +1,31 @@
#include "UniqueNodeList.h" #include "UniqueNodeList.h"
#include "Application.h"
void UniqueNodeList::load()
void UniqueNodeList::addNode(uint160& hanko,uint1024& publicKey)
{ {
"INSERT INTO UNL values ("
theApp->getDB()->executeSQL(sql);
}
void UniqueNodeList::removeNode(uint160& hanko)
{
"DELETE FROM UNL where hanko="
theApp->getDB()->executeSQL(sql);
} }
int UniqueNodeList::checkValid(newcoin::Validation& valid)
{
"SELECT pubkey from UNL where hanko="
if( theApp->getDB()->executeSQL(sql) )
{
if(theApp->getDB()->getNextRow())
{
theApp->getDB()->getBytes();
}else return(0); // not on our list
}
return(1);
}

View File

@@ -4,11 +4,17 @@
class UniqueNodeList class UniqueNodeList
{ {
// hanko to public key
//std::map<uint160,uint512> mUNL;
public: public:
void load(); //void load();
void save(); //void save();
bool findHanko(const std::string& hanko); void addNode(uint160& hanko,uint1024& publicKey);
void removeNode(uint160& hanko);
// 0- we don't care, 1- we care and is valid, 2-invalid signature
int checkValid(newcoin::Validation& valid);
}; };

View File

@@ -13,7 +13,19 @@ Then we just have to check this ledger to see if a new ledger is compatible
This is also the ledger we hand back when we ask for the consensus ledger This is also the ledger we hand back when we ask for the consensus ledger
*/ */
ValidationCollection::ValidationCollection()
{
}
void ValidationCollection::save()
{
}
void ValidationCollection::load()
{
}
bool ValidationCollection::hasValidation(uint256& ledgerHash,uint160& hanko,uint32 seqnum) bool ValidationCollection::hasValidation(uint256& ledgerHash,uint160& hanko,uint32 seqnum)
{ {
@@ -51,16 +63,20 @@ void ValidationCollection::addValidation(newcoin::Validation& valid)
if(hasValidation(hash,hanko,valid.seqnum())) return; if(hasValidation(hash,hanko,valid.seqnum())) return;
// check if we care about this hanko // check if we care about this hanko
if( theApp->getUNL().findHanko(valid.hanko()) ) int validity=theApp->getUNL().checkValid(valid);
if( validity==1 )
{ {
mValidations[hash].push_back(valid); mValidations[hash].push_back(valid);
mIndexValidations[valid.ledgerindex()].push_back(valid); mIndexValidations[valid.ledgerindex()].push_back(valid);
addToGroup(valid); addToGroup(valid);
theApp->getLedgerMaster().checkConsensus(valid.ledgerindex()); theApp->getLedgerMaster().checkConsensus(valid.ledgerindex());
}else }else if(validity==0)
{ {
mIgnoredValidations[hash].push_back(valid); mIgnoredValidations[hash].push_back(valid);
}else
{ // the signature wasn't valid
cout << "Invalid Validation" << endl;
} }
} }

View File

@@ -0,0 +1,23 @@
#include "SqliteDatabase.h"
SqliteDatabase::SqliteDatabase()
{
}
/* http://www.sqlite.org/lang_expr.html
BLOB literals are string literals containing hexadecimal data and preceded by a single "x" or "X" character. For example:
X'53514C697465'
*/
void SqliteDatabase::escape(unsigned char* start,int size,std::string& retStr)
{
retStr.clear();
char buf[3];
retStr.append("X'");
for(int n=0; n<size; n++)
{
retStr.append( itoa(*start,buf,16) );
}
retStr.push_back('\'');
}

11
database/SqliteDatabase.h Normal file
View File

@@ -0,0 +1,11 @@
#include "database.h"
class SqliteDatabase : public Database
{
public:
SqliteDatabase();
void escape(unsigned char* start,int size,std::string& retStr);
};

118
database/database.cpp Normal file
View File

@@ -0,0 +1,118 @@
#include "database.h"
#include "../utillib/reportingmechanism.h"
#include "string/i4string.h"
#include <stdlib.h>
Database::Database(const char* host,const char* user,const char* pass) : mDBPass(pass), mHost(host) ,mUser(user), mNumCol(0)
{
mColNameTable=NULL;
}
Database::~Database()
{
delete[] mColNameTable;
}
char* Database::getStr(const char* colName,std::string& retStr)
{
int index;
if(getColNumber(colName,&index))
{
return(getStr(index,retStr));
}
return(NULL);
}
w32 Database::getInt(const char* colName)
{
int index;
if(getColNumber(colName,&index))
{
return(getInt(index));
}
return(0);
}
float Database::getFloat(const char* colName)
{
int index;
if(getColNumber(colName,&index))
{
return(getFloat(index));
}
return(0);
}
bool Database::getBool(const char* colName)
{
int index;
if(getColNumber(colName,&index))
{
return(getBool(index));
}
return(0);
}
// returns false if can't find col
bool Database::getColNumber(const char* colName,int* retIndex)
{
for(int n=0; n<mNumCol; n++)
{
if(i4_stricmp(colName,mColNameTable[n])==0)
{
*retIndex=n;
return(true);
}
}
return(false);
}
int Database::getSingleDBValueInt(const char* sql)
{
int ret;
if( executeSQL(sql) && startIterRows() && getNextRow())
{
ret=getInt(0);
endIterRows();
}else
{
//theUI->statusMsg("ERROR with database: %s",sql);
ret=0;
}
return(ret);
}
float Database::getSingleDBValueFloat(const char* sql)
{
float ret;
if( executeSQL(sql) && startIterRows() && getNextRow())
{
ret=getFloat(0);
endIterRows();
}else
{
//theUI->statusMsg("ERROR with database: %s",sql);
ret=0;
}
return(ret);
}
char* Database::getSingleDBValueStr(const char* sql,std::string& retStr)
{
char* ret;
if( executeSQL(sql) && startIterRows() && getNextRow())
{
ret=getStr(0,retStr);
endIterRows();
}else
{
//theUI->statusMsg("ERROR with database: %s",sql);
ret=0;
}
return(ret);
}

73
database/database.h Normal file
View File

@@ -0,0 +1,73 @@
#ifndef __DATABASE__
#define __DATABASE__
#include <string>
/*
this maintains the connection to the database
*/
class Database
{
protected:
int mNumCol;
std:string mUser;
std:string mHost;
std:string mDBPass;
std:string* mColNameTable;
bool getColNumber(const char* colName, int* retIndex);
public:
Database(const char* host,const char* user,const char* pass);
static Database* newMysqlDatabase(const char* host,const char* user,const char* pass);
virtual ~Database();
virtual void connect()=0;
virtual void disconnect()=0;
std::string& getPass(){ return(mDBPass); }
virtual void escape(unsigned char* start,int size,std::string& retStr)=0;
// returns true if the query went ok
virtual bool executeSQL(const char* sql)=0;
// tells you how many rows were changed by an update or insert
virtual int getNumRowsAffected()=0;
// returns false if there are no results
virtual bool startIterRows()=0;
virtual void endIterRows()=0;
// call this after you executeSQL
// will return false if there are no more rows
virtual bool getNextRow()=0;
// get Data from the current row
char* getStr(const char* colName,std::string& retStr);
int32 getInt(const char* colName);
float getFloat(const char* colName);
bool getBool(const char* colName);
bool getBinary(const char* colName,char* buf,int maxSize);
virtual char* getStr(int colIndex,std::string& retStr)=0;
virtual int32 getInt(int colIndex)=0;
virtual float getFloat(int colIndex)=0;
virtual bool getBool(int colIndex)=0;
virtual bool getBinary(int colIndex,char* buf,int maxSize)=0;
int getSingleDBValueInt(const char* sql);
float getSingleDBValueFloat(const char* sql);
char* getSingleDBValueStr(const char* sql, std::string& retStr);
};
class MsqlDatabase
{
};
#endif

View File

@@ -0,0 +1,136 @@
#include "mysqldatabase.h"
#include "reportingmechanism.h"
#include "string/i4string.h"
#include <stdlib.h>
Database* Database::newDatabase(const char* host,const char* user,const char* pass)
{
return(new MySqlDatabase(host,user,pass));
}
MySqlDatabase::MySqlDatabase(const char* host,const char* user,const char* pass) : Database(host,user,pass)
{
}
MySqlDatabase::~MySqlDatabase()
{
}
void MySqlDatabase::connect()
{
mysql_init(&mMysql);
mysql_options(&mMysql,MYSQL_READ_DEFAULT_GROUP,"i4min");
if(!mysql_real_connect(&mMysql,mHost,mUser,mDBPass,NULL,0,NULL,0))
{
theUI->statusMsg("Failed to connect to database: Error: %s\n", mysql_error(&mMysql));
}else theUI->statusMsg("Connection Established to DB");
}
void MySqlDatabase::disconnect()
{
mysql_close(&mMysql);
}
int MySqlDatabase::getNumRowsAffected()
{
return( mysql_affected_rows(&mMysql));
}
// returns true if the query went ok
bool MySqlDatabase::executeSQL(const char* sql)
{
int ret=mysql_query(&mMysql, sql);
if(ret)
{
connect();
int ret=mysql_query(&mMysql, sql);
if(ret)
{
theUI->statusMsg("ERROR with executeSQL: %d %s",ret,sql);
return(false);
}
}
return(true);
}
bool MySqlDatabase::startIterRows()
{
mResult=mysql_store_result(&mMysql);
// get total number of columns from the resultset
mNumCol = mysql_num_fields(mResult);
if(mNumCol)
{
delete[](mColNameTable);
mColNameTable=new i4_str[mNumCol];
// fill out the column name table
for(int n = 0; n < mNumCol; n++)
{
MYSQL_FIELD* field=mysql_fetch_field(mResult);
mColNameTable[n]= field->name;
}
return(true);
}
return(false);
}
// call this after you executeSQL
// will return false if there are no more rows
bool MySqlDatabase::getNextRow()
{
mCurRow=mysql_fetch_row(mResult);
return(mCurRow!=NULL);
}
char* MySqlDatabase::getStr(int colIndex,i4_str* retStr)
{
if(mCurRow[colIndex])
{
(*retStr)=mCurRow[colIndex];
}else (*retStr)="";
return(*retStr);
}
w32 MySqlDatabase::getInt(int colIndex)
{
if(mCurRow[colIndex])
{
w32 ret=atoll(mCurRow[colIndex]);
//theUI->statusMsg("getInt: %s,%c,%u",mCurRow[colIndex],mCurRow[colIndex][0],ret);
return(ret);
}
return(0);
}
float MySqlDatabase::getFloat(int colIndex)
{
if(mCurRow[colIndex])
{
float ret=atof(mCurRow[colIndex]);
return(ret);
}
return(0.0);
}
bool MySqlDatabase::getBool(int colIndex)
{
if(mCurRow[colIndex])
{
int ret=atoi(mCurRow[colIndex]);
return(ret);
}
return(false);
}
void MySqlDatabase::endIterRows()
{
mysql_free_result(mResult);
}

View File

@@ -0,0 +1,47 @@
#ifndef __MYSQLDATABASE__
#define __MYSQLDATABASE__
#include "../database.h"
#include "string/i4string.h"
#include "mysql.h"
/*
this maintains the connection to the database
*/
class MySqlDatabase : public Database
{
MYSQL mMysql;
MYSQL_RES* mResult;
MYSQL_ROW mCurRow;
public:
MySqlDatabase(const char* host,const char* user,const char* pass);
~MySqlDatabase();
void connect();
void disconnect();
// returns true if the query went ok
bool executeSQL(const char* sql);
int getNumRowsAffected();
// returns false if there are no results
bool startIterRows();
void endIterRows();
// call this after you executeSQL
// will return false if there are no more rows
bool getNextRow();
// get Data from the current row
char* getStr(int colIndex,i4_str* retStr);
w32 getInt(int colIndex);
float getFloat(int colIndex);
bool getBool(int colIndex);
};
#endif

82
database/win/dbutility.h Normal file
View File

@@ -0,0 +1,82 @@
#ifndef __TMYODBC_UTILITY_H__
#define __TMYODBC_UTILITY_H__
#ifdef HAVE_CONFIG_H
#include <myconf.h>
#endif
/* STANDARD C HEADERS */
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
/* ODBC HEADERS */
#include <sqlext.h>
#define MAX_NAME_LEN 95
#define MAX_COLUMNS 255
#define MAX_ROW_DATA_LEN 255
/* PROTOTYPE */
void myerror(SQLRETURN rc,SQLSMALLINT htype, SQLHANDLE handle);
/* UTILITY MACROS */
#define myenv(henv,r) \
if ( ((r) != SQL_SUCCESS) ) \
myerror(r, 1,henv); \
assert( ((r) == SQL_SUCCESS) || ((r) == SQL_SUCCESS_WITH_INFO) )
#define myenv_err(henv,r,rc) \
if ( rc == SQL_ERROR || rc == SQL_SUCCESS_WITH_INFO ) \
myerror(rc, 1, henv); \
assert( r )
#define mycon(hdbc,r) \
if ( ((r) != SQL_SUCCESS) ) \
myerror(r, 2, hdbc); \
assert( ((r) == SQL_SUCCESS) || ((r) == SQL_SUCCESS_WITH_INFO) )
#define mycon_err(hdbc,r,rc) \
if ( rc == SQL_ERROR || rc == SQL_SUCCESS_WITH_INFO ) \
myerror(rc, 2, hdbc); \
assert( r )
#define mystmt(hstmt,r) \
if ( ((r) != SQL_SUCCESS) ) \
myerror(r, 3, hstmt); \
assert( ((r) == SQL_SUCCESS) || ((r) == SQL_SUCCESS_WITH_INFO) )
#define mystmt_err(hstmt,r,rc) \
if ( rc == SQL_ERROR || rc == SQL_SUCCESS_WITH_INFO ) \
myerror(rc, 3, hstmt); \
assert( r )
/********************************************************
* MyODBC 3.51 error handler *
*********************************************************/
void myerror(SQLRETURN rc, SQLSMALLINT htype, SQLHANDLE handle)
{
SQLRETURN lrc;
if( rc == SQL_ERROR || rc == SQL_SUCCESS_WITH_INFO )
{
SQLCHAR szSqlState[6],szErrorMsg[SQL_MAX_MESSAGE_LENGTH];
SQLINTEGER pfNativeError;
SQLSMALLINT pcbErrorMsg;
lrc = SQLGetDiagRec(htype, handle,1,
(SQLCHAR *)&szSqlState,
(SQLINTEGER *)&pfNativeError,
(SQLCHAR *)&szErrorMsg,
SQL_MAX_MESSAGE_LENGTH-1,
(SQLSMALLINT *)&pcbErrorMsg);
if(lrc == SQL_SUCCESS || lrc == SQL_SUCCESS_WITH_INFO)
printf("\n [%s][%d:%s]\n",szSqlState,pfNativeError,szErrorMsg);
}
}
#endif /* __TMYODBC_UTILITY_H__ */

View File

@@ -0,0 +1,212 @@
#include "windatabase.h"
#include "dbutility.h"
Database* Database::newMysqlDatabase(const char* host,const char* user,const char* pass)
{
return(new WinDatabase(host,user,pass));
}
WinDatabase::WinDatabase(const char* host,const char* user,const char* pass) : Database(host,user,pass)
{
}
WinDatabase::~WinDatabase()
{
disconnect();
}
void WinDatabase::connect()
{
SQLRETURN rc;
rc = SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&henv);
myenv(henv, rc);
rc = SQLSetEnvAttr(henv,SQL_ATTR_ODBC_VERSION,(SQLPOINTER)SQL_OV_ODBC3,0);
myenv(henv, rc);
rc = SQLAllocHandle(SQL_HANDLE_DBC,henv, &hdbc);
myenv(henv, rc);
rc = SQLConnect(hdbc, (unsigned char*)(char*) mHost, SQL_NTS, (unsigned char*)(char*) mUser, SQL_NTS, (unsigned char*)(char*) mDBPass, SQL_NTS);
mycon(hdbc, rc);
rc = SQLSetConnectAttr(hdbc,SQL_ATTR_AUTOCOMMIT,(SQLPOINTER)SQL_AUTOCOMMIT_ON,0);
mycon(hdbc,rc);
rc = SQLAllocHandle(SQL_HANDLE_STMT,hdbc,&hstmt);
mycon(hdbc,rc);
//rc = SQLGetInfo(hdbc,SQL_DBMS_NAME,&server_name,40,NULL);
//mycon(hdbc, rc);
theUI->statusMsg("Connection Established to DB");
}
void WinDatabase::disconnect()
{
SQLRETURN rc;
rc = SQLFreeStmt(hstmt, SQL_DROP);
mystmt(hstmt,rc);
rc = SQLDisconnect(hdbc);
mycon(hdbc, rc);
rc = SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
mycon(hdbc, rc);
rc = SQLFreeHandle(SQL_HANDLE_ENV, henv);
myenv(henv, rc);
}
int WinDatabase::getNumRowsAffected()
{
// theUI->statusMsg("getNumRowsAffected()");
SQLINTEGER ret;
SQLRowCount(hstmt,&ret);
return(ret);
}
// returns true if the query went ok
bool WinDatabase::executeSQL(const char* sql)
{
SQLRETURN rc = SQLExecDirect(hstmt,(unsigned char*) sql,SQL_NTS);
if(rc==SQL_ERROR)
{
theUI->errorMsg("Trying to recover from DB error");
rc = SQLExecDirect(hstmt,(unsigned char*) sql,SQL_NTS);
if(rc==SQL_ERROR)
{
SQLCHAR SqlState[6], /*SQLStmt[100],*/ Msg[SQL_MAX_MESSAGE_LENGTH];
SQLINTEGER NativeError;
SQLSMALLINT i, MsgLen;
SQLRETURN /*rc1,*/ rc2;
i = 1;
while ((rc2 = SQLGetDiagRec(SQL_HANDLE_STMT, hstmt, i, SqlState, &NativeError, Msg, sizeof(Msg), &MsgLen)) != SQL_NO_DATA)
{
theUI->errorMsg("DB ERROR: %s,%d,%s",SqlState,NativeError,Msg);
i++;
}
return(false);
}
}
mystmt(hstmt,rc);
// commit the transaction
rc = SQLEndTran(SQL_HANDLE_DBC, hdbc, SQL_COMMIT);
mycon(hdbc,rc);
return(true);
}
bool WinDatabase::startIterRows()
{
SQLUINTEGER pcColDef;
SQLCHAR szColName[MAX_NAME_LEN];
SQLSMALLINT pfSqlType, pcbScale, pfNullable;
SQLSMALLINT numCol;
/* get total number of columns from the resultset */
SQLRETURN rc = SQLNumResultCols(hstmt,&numCol);
mystmt(hstmt,rc);
mNumCol=(int)numCol;
if(mNumCol)
{
delete[](mColNameTable);
mColNameTable=new i4_str[mNumCol];
// fill out the column name table
for(int n = 1; n <= mNumCol; n++)
{
rc = SQLDescribeCol(hstmt,n,szColName, MAX_NAME_LEN, NULL, &pfSqlType,&pcColDef,&pcbScale,&pfNullable);
mystmt(hstmt,rc);
mColNameTable[n-1]= (char*)szColName;
}
return(true);
}
return(false);
}
// call this after you executeSQL
// will return false if there are no more rows
bool WinDatabase::getNextRow()
{
SQLRETURN rc = SQLFetch(hstmt);
return((rc==SQL_SUCCESS) || (rc==SQL_SUCCESS_WITH_INFO));
}
char* WinDatabase::getStr(int colIndex,i4_str* retStr)
{
colIndex++;
(*retStr)="";
char buf[1000];
// SQLINTEGER len;
buf[0]=0;
while(SQLGetData(hstmt, colIndex, SQL_C_CHAR, &buf, 1000,NULL)!= SQL_NO_DATA)
{
(*retStr) += buf;
// theUI->statusMsg("Win: %s",buf);
}
//SQLRETURN rc = SQLGetData(hstmt,colIndex,SQL_C_CHAR,&buf,30000,&len);
//mystmt(hstmt,rc);
//*retStr=buf;
//theUI->statusMsg("Win: %s",buf);
return(*retStr);
}
w32 WinDatabase::getInt(int colIndex)
{
colIndex++;
int ret=0;
SQLRETURN rc = SQLGetData(hstmt,colIndex,SQL_INTEGER,&ret,sizeof(int),NULL);
mystmt(hstmt,rc);
return(ret);
}
float WinDatabase::getFloat(int colIndex)
{
colIndex++;
float ret=0;
SQLRETURN rc = SQLGetData(hstmt,colIndex,SQL_C_FLOAT,&ret,sizeof(float),NULL);
mystmt(hstmt,rc);
return(ret);
}
bool WinDatabase::getBool(int colIndex)
{
colIndex++;
char buf[1];
buf[0]=0;
SQLRETURN rc = SQLGetData(hstmt,colIndex,SQL_C_CHAR,&buf,1,NULL);
mystmt(hstmt,rc);
return(buf[0] != 0);
}
void WinDatabase::endIterRows()
{
// free the statement row bind resources
SQLRETURN rc = SQLFreeStmt(hstmt, SQL_UNBIND);
mystmt(hstmt,rc);
// free the statement cursor
rc = SQLFreeStmt(hstmt, SQL_CLOSE);
mystmt(hstmt,rc);
}

View File

@@ -0,0 +1,55 @@
#ifndef __WINDATABASE__
#define __WINDATABASE__
#include "../database.h"
#ifdef WIN32
#define _WINSOCKAPI_ // prevent inclusion of winsock.h in windows.h
#include <windows.h>
#include "sql.h"
#endif
#include "string/i4string.h"
/*
this maintains the connection to the database
*/
class WinDatabase : public Database
{
SQLHENV henv;
SQLHDBC hdbc;
SQLHSTMT hstmt;
public:
WinDatabase(const char* host,const char* user,const char* pass);
virtual ~WinDatabase();
void connect();
void disconnect();
char* getPass(){ return(mDBPass); }
// returns true if the query went ok
bool executeSQL(const char* sql);
int getNumRowsAffected();
// returns false if there are no results
bool startIterRows();
void endIterRows();
// call this after you executeSQL
// will return false if there are no more rows
bool getNextRow();
// get Data from the current row
char* getStr(int colIndex,i4_str* retStr);
w32 getInt(int colIndex);
float getFloat(int colIndex);
bool getBool(int colIndex);
};
#endif

13
db layout.txt Normal file
View File

@@ -0,0 +1,13 @@
// need to make this compatible with at least SQLite and Mysql
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 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);
CREATE TABLE LedgerAccountMap(LedgerID INT UNSIGNED,AccountID INT UNSIGNED);
CREATE TABLE Accounts (AccountID INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, Address BINARY(20), Amount BIGINT UNSIGNED, SeqNum INT);
CREATE TABLE AcceptedLedgers (LedgerIndex INT UNSIGNED PRIMARY KEY, LedgerID INT UNSIGNED);

View File

@@ -70,8 +70,7 @@ message FullLedger {
message GetFullLedger { message GetFullLedger {
required uint32 ledgerIndex = 1; required bytes hash = 1;
optional bytes hash = 2;
} }
message GetValidations { message GetValidations {

View File

@@ -91,6 +91,10 @@
<ClCompile Include="ConnectionPool.cpp" /> <ClCompile Include="ConnectionPool.cpp" />
<ClCompile Include="cryptopp\cpu.cpp" /> <ClCompile Include="cryptopp\cpu.cpp" />
<ClCompile Include="cryptopp\sha.cpp" /> <ClCompile Include="cryptopp\sha.cpp" />
<ClCompile Include="database\database.cpp" />
<ClCompile Include="database\SqliteDatabase.cpp" />
<ClCompile Include="database\win\windatabase.cpp" />
<ClCompile Include="DiskSerializer.cpp" />
<ClCompile Include="HttpReply.cpp" /> <ClCompile Include="HttpReply.cpp" />
<ClCompile Include="json\json_spirit_reader.cpp" /> <ClCompile Include="json\json_spirit_reader.cpp" />
<ClCompile Include="json\json_spirit_value.cpp" /> <ClCompile Include="json\json_spirit_value.cpp" />
@@ -100,6 +104,7 @@
<ClCompile Include="Ledger.cpp" /> <ClCompile Include="Ledger.cpp" />
<ClCompile Include="LedgerHistory.cpp" /> <ClCompile Include="LedgerHistory.cpp" />
<ClCompile Include="LedgerMaster.cpp" /> <ClCompile Include="LedgerMaster.cpp" />
<ClCompile Include="MySqlSerializer.cpp" />
<ClCompile Include="newcoin.pb.cc" /> <ClCompile Include="newcoin.pb.cc" />
<ClCompile Include="NewcoinAddress.cpp" /> <ClCompile Include="NewcoinAddress.cpp" />
<ClCompile Include="PackedMessage.cpp" /> <ClCompile Include="PackedMessage.cpp" />
@@ -139,6 +144,8 @@
<ClInclude Include="cryptopp\simple.h" /> <ClInclude Include="cryptopp\simple.h" />
<ClInclude Include="cryptopp\smartptr.h" /> <ClInclude Include="cryptopp\smartptr.h" />
<ClInclude Include="cryptopp\stdcpp.h" /> <ClInclude Include="cryptopp\stdcpp.h" />
<ClInclude Include="database\database.h" />
<ClInclude Include="database\SqliteDatabase.h" />
<ClInclude Include="HttpReply.h" /> <ClInclude Include="HttpReply.h" />
<ClInclude Include="HttpRequest.h" /> <ClInclude Include="HttpRequest.h" />
<ClInclude Include="json\json_spirit.h" /> <ClInclude Include="json\json_spirit.h" />
@@ -168,11 +175,13 @@
<ClInclude Include="RPCDoor.h" /> <ClInclude Include="RPCDoor.h" />
<ClInclude Include="script.h" /> <ClInclude Include="script.h" />
<ClInclude Include="SecureAllocator.h" /> <ClInclude Include="SecureAllocator.h" />
<ClInclude Include="Serializer.h" />
<ClInclude Include="TimingService.h" /> <ClInclude Include="TimingService.h" />
<ClInclude Include="ExtendedTransaction.h" /> <ClInclude Include="ExtendedTransaction.h" />
<ClInclude Include="Transaction.h" /> <ClInclude Include="Transaction.h" />
<ClInclude Include="TransactionBundle.h" /> <ClInclude Include="TransactionBundle.h" />
<ClInclude Include="types.h" /> <ClInclude Include="types.h" />
<ClInclude Include="uint256.h" />
<ClInclude Include="UniqueNodeList.h" /> <ClInclude Include="UniqueNodeList.h" />
<ClInclude Include="util\pugiconfig.hpp" /> <ClInclude Include="util\pugiconfig.hpp" />
<ClInclude Include="util\pugixml.hpp" /> <ClInclude Include="util\pugixml.hpp" />
@@ -186,6 +195,7 @@
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\protoc-2.4.1-win32\protoc -I=..\newcoin --cpp_out=..\newcoin ..\newcoin\newcoin.proto</Command> <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\protoc-2.4.1-win32\protoc -I=..\newcoin --cpp_out=..\newcoin ..\newcoin\newcoin.proto</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">newcoin.pb.h</Outputs> <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">newcoin.pb.h</Outputs>
</CustomBuild> </CustomBuild>
<None Include="db layout.txt" />
<None Include="html\newcoin.html"> <None Include="html\newcoin.html">
<SubType>Designer</SubType> <SubType>Designer</SubType>
</None> </None>

View File

@@ -132,6 +132,21 @@
<ClCompile Include="Transaction.cpp"> <ClCompile Include="Transaction.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="MySqlSerializer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DiskSerializer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="database\database.cpp">
<Filter>Header Files\util</Filter>
</ClCompile>
<ClCompile Include="database\win\windatabase.cpp">
<Filter>Header Files\util</Filter>
</ClCompile>
<ClCompile Include="database\SqliteDatabase.cpp">
<Filter>Header Files\util</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Application.h"> <ClInclude Include="Application.h">
@@ -308,6 +323,18 @@
<ClInclude Include="Account.h"> <ClInclude Include="Account.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Serializer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="database\database.h">
<Filter>Header Files\util</Filter>
</ClInclude>
<ClInclude Include="database\SqliteDatabase.h">
<Filter>Header Files\util</Filter>
</ClInclude>
<ClInclude Include="uint256.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="nodes.xml" /> <None Include="nodes.xml" />
@@ -318,6 +345,7 @@
<None Include="html\newcoin.html"> <None Include="html\newcoin.html">
<Filter>html</Filter> <Filter>html</Filter>
</None> </None>
<None Include="db layout.txt" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<CustomBuild Include="newcoin.proto" /> <CustomBuild Include="newcoin.proto" />

View File

@@ -1,9 +1,10 @@
Dependencies: Dependencies:
Boost 1_47 Boost 1_47
boost log http://boost-log.sourceforge.net/libs/log/doc/html/log/installation.html boost log http://boost-log.sourceforge.net/libs/log/doc/html/log/installation.html // this didn't work immediatly so I stopped messing with it but we should probably use it
protocol buffers: expects ..\protobuf-2.4.1 and ..\protoc-2.4.1-win32 protocol buffers: expects ..\protobuf-2.4.1 and ..\protoc-2.4.1-win32
openssl openssl
sqlite
Using: Using:
pugixml version 1.0 download new versions at http://pugixml.org/ pugixml version 1.0 download new versions at http://pugixml.org/
@@ -49,3 +50,4 @@ Peers are causing:
Actualy I think this can all be in one thread. Commands to the app must be done by RPC. Actualy I think this can all be in one thread. Commands to the app must be done by RPC.

View File

@@ -5,7 +5,6 @@
#ifndef BITCOIN_UINT256_H #ifndef BITCOIN_UINT256_H
#define BITCOIN_UINT256_H #define BITCOIN_UINT256_H
//#include "serialize.h"
#include <limits.h> #include <limits.h>
#include <string> #include <string>