This commit is contained in:
jed
2011-10-20 13:34:49 -07:00
parent 6715b966fc
commit 650ee74391
27 changed files with 726 additions and 314 deletions

View File

@@ -36,7 +36,7 @@ public:
LedgerMaster& getLedgerMaster(){ return(mLedgerMaster); }
UniqueNodeList& getUNL(){ return(mUNL); }
ValidationCollection& getValidationCollection(){ return(mValidations); }
Wallet& getWallet(){ return(mWallet); }
void run();

View File

@@ -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()

View File

@@ -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;

View File

@@ -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<mBroadcastMessages.size(); n++)
@@ -36,9 +36,10 @@ bool ConnectionPool::isMessageKnown(PackedMessage::pointer msg)
}
return(false);
}
*/
void ConnectionPool::relayMessage(Peer* fromPeer,PackedMessage::pointer msg,uint64 ledgerID)
void ConnectionPool::relayMessage(Peer* fromPeer,PackedMessage::pointer msg)
{
BOOST_FOREACH(Peer::pointer peer, mPeers)
{

View File

@@ -3,19 +3,20 @@
#include "types.h"
#include <boost/asio.hpp>
class KnownNodeList;
/*
This is the list of all the Peers we are currently connected to
*/
class ConnectionPool
{
std::vector<Peer::pointer> mPeers;
std::vector<std::pair<PackedMessage::pointer,int> > mBroadcastMessages;
//std::vector<std::pair<PackedMessage::pointer,int> > 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);
};

View File

@@ -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<string,uint64>& account=pair<string,uint64>();
BOOST_FOREACH(account,mMoneyMap)
pair<uint160, pair<uint64,uint32> >& account=pair<uint160, pair<uint64,uint32> >();
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<numAccounts; n++)
{
const newcoin::Account& account=ledger.accounts(n);
mMoneyMap[account.address()] = account.amount();
mAccounts[ NewcoinAddress::protobufToInternal(account.address()) ] = pair<uint64,uint32>(account.amount(),account.seqnum());
}
int numTrans=ledger.transactions_size();
for(int n=0; n<numTrans; n++)
{
const newcoin::Transaction& trans=ledger.transactions(n);
mBundle.addTransaction(trans);
mTransactions.push_back(TransactionPtr(new newcoin::Transaction(trans)));
}
}
@@ -94,6 +96,24 @@ void Ledger::save(string dir)
delete(ledger);
}
int64 Ledger::getAmountHeld(uint160& address)
{
if(mAccounts.count(address))
{
return(mAccounts[address].first);
}
return(0);
}
Ledger::Account* Ledger::getAccount(uint160& address)
{
if(mAccounts.count(address))
{
return(&(mAccounts[address]));
}
return(NULL);
}
string& Ledger::getHash()
{
if(!mValidHash) hash();
@@ -109,7 +129,7 @@ string& Ledger::getSignature()
void Ledger::publish()
{
PackedMessage::pointer packet=Peer::createValidation(shared_from_this());
theApp->getConnectionPool().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<uint64> cacheInputLeftOverAmount;
int numInputs=trans.inputs_size();
cacheInputLeftOverAmount.resize(numInputs);
for(int n=0; n<numInputs; n++)
uint160 address=NewcoinAddress::protobufToInternal(trans->from());
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<input.amount())
pair<uint64,uint32> account=mAccounts[address];
if( (account.first<trans->amount()) &&
(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; n<numInputs; n++)
uint160 destAddress=NewcoinAddress::protobufToInternal(trans->dest());
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<uint160> effected;
// do this in reverse so we take of the higher seqnum first
for( list<TransactionPtr>::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<TransactionPtr>::iterator temp=mTransactions.erase( --iter.base() );
if(fromAccount.first>=0) break;
iter=list<TransactionPtr>::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<TransactionPtr> firstTransactions=mTransactions;
list<TransactionPtr> 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<uint160, Account >& fullAccount=pair<uint160, Account >();
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->first<cause->amount())
{
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<uint64,uint32>(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);
}

View File

@@ -1,53 +1,80 @@
#ifndef __LEDGER__
#define __LEDGER__
#include "TransactionBundle.h"
#include "Transaction.h"
#include "types.h"
#include "BitcoinUtil.h"
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <map>
#include <list>
class Ledger : public boost::enable_shared_from_this<Ledger>
{
public:
typedef boost::shared_ptr<Ledger> pointer;
typedef std::pair<int64,uint32> 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<std::string,uint64> mMoneyMap;
TransactionBundle mBundle;
std::map<uint160, Account > mAccounts;
std::list<TransactionPtr> mTransactions;
std::list<TransactionPtr> 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<Ledger> 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<std::string,uint64>& getMoneyMap(){ return(mMoneyMap); }
unsigned int getNumTransactions(){ return(mTransactions.size()); }
std::map<uint160, std::pair<int64,uint32> >& getAccounts(){ return(mAccounts); }
Account* getAccount(uint160& address);
newcoin::FullLedger* createFullLedger();
};
#endif

View File

@@ -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);
}

View File

@@ -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<uint64, Ledger::pointer> mLedgers;
bool loadLedger(uint64 index);
std::map<uint32, Ledger::pointer> mAcceptedLedgers;
std::map<uint256, Ledger::pointer> 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

View File

@@ -1,11 +1,13 @@
#include "LedgerMaster.h"
#include "Application.h"
#include "NewcoinAddress.h"
#include <boost/foreach.hpp>
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::pointer,newcoin::ProposeLedger>(peer,otherLedger));
}
void LedgerMaster::applyFutureProposals()
void LedgerMaster::applyFutureProposals(uint32 ledgerIndex)
{
for(list< pair<Peer::pointer,newcoin::ProposeLedger> >::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<newcoin::Transaction>::iterator iter=mFutureTransactions.begin(); iter !=mFutureTransactions.end(); )
for(list<TransactionPtr>::iterator iter=mFutureTransactions.begin(); iter !=mFutureTransactions.end(); )
{
if( (*iter).ledgerindex() == mCurrentLedger->getIndex() )
if( (*iter)->ledgerindex() == ledgerIndex)
{
addTransaction(*iter);
mFutureTransactions.erase(iter);

View File

@@ -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<newcoin::Transaction> mFutureTransactions;
std::list<TransactionPtr> mFutureTransactions;
std::list< std::pair<Peer::pointer,newcoin::ProposeLedger> > 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();

View File

@@ -20,6 +20,10 @@ public:
bool IsValid();
uint160 GetHash160();
static uint160 protobufToInternal(const std::string& buf);
static uint160 humanToInternal(const std::string& buf);
};

View File

@@ -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)

5
Peer.h
View File

@@ -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<Peer>
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);

35
Transaction.cpp Normal file
View File

@@ -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<unsigned char> buffer;
buffer.resize(trans->ByteSize());
trans->SerializeToArray(&(buffer[0]),buffer.size());
return Hash(buffer.begin(), buffer.end());
}

View File

@@ -1,17 +1,25 @@
#include "string"
#ifndef __TRANSACTION__
#define __TRANSACTION__
#include "newcoin.pb.h"
#include "uint256.h"
#include <boost/shared_ptr.hpp>
/*
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<newcoin::Transaction> TransactionPtr;
class Transaction
{
std::string mSource;
std::string mSig;
std::string mDest;
unsigned int mAmount;
public:
Transaction();
};
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

View File

@@ -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<numInputs; n++)
{
total += trans.inputs(n).amount();
}
return(total);
}
// determine if all the transactions until end time from this address are valid
// return the amount left in this account
@@ -136,4 +128,6 @@ void TransactionBundle::updateMap(std::map<std::string,uint64>& moneyMap)
moneyMap[trans.dest()] += total;
}
}
}
*/

View File

@@ -4,11 +4,14 @@
#include <list>
#include "newcoin.pb.h"
#include "types.h"
#include "Transaction.h"
class TransactionBundle
{
std::list<newcoin::Transaction> mTransactions;
std::list<newcoin::Transaction> mDisacrdedTransactions;
// we have to order this before we hash so the hash will be consistent
std::list<TransactionPtr> mTransactions;
std::list<TransactionPtr> mDisacrdedTransactions;
//std::list<newcoin::Transaction> 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

View File

@@ -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<newcoin::Validation>* getValidations(uint64 ledgerIndex);
};
};
#endif

View File

@@ -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(total<amount) return(NULL);
Account* firstAccount=NULL;
uint160* firstAddr=NULL;
total=0;
BOOST_FOREACH(Account& account, mYourAccounts)
{
total += account.mAmount;
if(firstAccount)
{
TransactionPtr trans=createTransaction(account,firstAccount->mAddress,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<newcoin::TransInput*> 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<unsigned char> 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<unsigned char> 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<unsigned char>& 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,vector<unsi
if(!key.Sign(hash, retSig))
return false;
}
*/
return(true);
}
@@ -122,12 +143,17 @@ bool Wallet::signTransInput(uint256 hash, newcoin::TransInput& input,vector<unsi
// Call after CreateTransaction unless you want to abort
bool Wallet::commitTransaction(newcoin::Transaction& trans)
bool Wallet::commitTransaction(TransactionPtr trans)
{
// TODO: Q up the message if it can't be relayed properly. or we don't see it added.
PackedMessage::pointer msg(new PackedMessage(PackedMessage::MessagePointer(new newcoin::Transaction(trans)),newcoin::TRANSACTION));
theApp->getConnectionPool().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);
}

View File

@@ -3,6 +3,7 @@
#include "keystore.h"
#include "newcoin.pb.h"
#include "Transaction.h"
#include <list>
#include <vector>
@@ -17,28 +18,41 @@ class Wallet : public CBasicKeyStore
{
public:
//CKey mKey;
std::string mAddress;
//std::vector<unsigned char> mPublicKey;
//std::vector<unsigned char> mPrivateKey;
uint64 mAmount;
uint64 mAge;
//std::string mHumanAddress;
uint160 mAddress;
std::vector<unsigned char> mPublicKey;
std::vector<unsigned char> mPrivateKey;
int64 mAmount;
uint64 mAge; // do we need this
uint32 mSeqNum;
Account(){}
bool signTransaction(TransactionPtr input);
};
std::list<Account> mYourAccounts;
bool signTransInput(uint256 hash, newcoin::TransInput& input,std::vector<unsigned char>& 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

View File

@@ -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;
}

View File

@@ -49,12 +49,12 @@
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_WIN32_WINNT=0x0501;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>c:\code\OpenSSL\include;C:\code\boost_1_47_0;C:\code\protobuf-2.4.1\src\</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\OpenSSL\include;..\boost_1_47_0;..\protobuf-2.4.1\src\</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>C:\code\OpenSSL\lib\VC;C:\code\boost_1_47_0\stage\lib;C:\code\protobuf-2.4.1\vsprojects\Debug</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>..\OpenSSL\lib\VC;..\boost_1_47_0\stage\lib;..\protobuf-2.4.1\vsprojects\Debug</AdditionalLibraryDirectories>
<AdditionalDependencies>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)</AdditionalDependencies>
</Link>
<PreBuildEvent>
@@ -112,6 +112,7 @@
<ClCompile Include="RPCCommands.cpp" />
<ClCompile Include="RPCDoor.cpp" />
<ClCompile Include="TimingService.cpp" />
<ClCompile Include="Transaction.cpp" />
<ClCompile Include="TransactionBundle.cpp" />
<ClCompile Include="UniqueNodeList.cpp" />
<ClCompile Include="util\pugixml.cpp" />
@@ -119,6 +120,7 @@
<ClCompile Include="Wallet.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Account.h" />
<ClInclude Include="Application.h" />
<ClInclude Include="base58.h" />
<ClInclude Include="bignum.h" />
@@ -167,6 +169,7 @@
<ClInclude Include="script.h" />
<ClInclude Include="SecureAllocator.h" />
<ClInclude Include="TimingService.h" />
<ClInclude Include="ExtendedTransaction.h" />
<ClInclude Include="Transaction.h" />
<ClInclude Include="TransactionBundle.h" />
<ClInclude Include="types.h" />
@@ -180,7 +183,7 @@
<None Include="config.xml" />
<CustomBuild Include="newcoin.proto">
<FileType>Document</FileType>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">c:/code/protoc-2.4.1-win32/protoc -I=C:\code\newcoin --cpp_out=C:\code\newcoin C:\code\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>
</CustomBuild>
<None Include="html\newcoin.html">

View File

@@ -129,6 +129,9 @@
<ClCompile Include="ValidationCollection.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Transaction.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Application.h">
@@ -173,9 +176,6 @@
<ClInclude Include="PeerDoor.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Transaction.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="json\json_spirit.h">
<Filter>Header Files\json</Filter>
</ClInclude>
@@ -299,6 +299,15 @@
<ClInclude Include="ValidationCollection.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ExtendedTransaction.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Transaction.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Account.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="nodes.xml" />

View File

@@ -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
----

View File

@@ -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

View File

@@ -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);
}