mirror of
https://github.com/Xahau/xahaud.git
synced 2025-11-19 18:15:50 +00:00
.
This commit is contained in:
@@ -36,7 +36,7 @@ public:
|
||||
LedgerMaster& getLedgerMaster(){ return(mLedgerMaster); }
|
||||
UniqueNodeList& getUNL(){ return(mUNL); }
|
||||
ValidationCollection& getValidationCollection(){ return(mValidations); }
|
||||
|
||||
Wallet& getWallet(){ return(mWallet); }
|
||||
|
||||
|
||||
void run();
|
||||
|
||||
@@ -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()
|
||||
|
||||
2
Config.h
2
Config.h
@@ -7,6 +7,8 @@ public:
|
||||
std::string VERSION_STR;
|
||||
bool TEST_NET;
|
||||
|
||||
int TRANSACTION_FEE;
|
||||
int ACCOUNT_FEE;
|
||||
int PEER_PORT;
|
||||
int RPC_PORT;
|
||||
int NUMBER_CONNECTIONS;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
};
|
||||
325
Ledger.cpp
325
Ledger.cpp
@@ -12,7 +12,7 @@ using namespace boost;
|
||||
using namespace std;
|
||||
|
||||
|
||||
Ledger::Ledger(uint64 index)
|
||||
Ledger::Ledger(uint32 index)
|
||||
{
|
||||
mIndex=index;
|
||||
mValidSig=false;
|
||||
@@ -22,19 +22,20 @@ Ledger::Ledger(uint64 index)
|
||||
// TODO: we should probably make a shared pointer type for each of these PB types
|
||||
newcoin::FullLedger* Ledger::createFullLedger()
|
||||
{
|
||||
// TODO: do we need to hash and create mone map first?
|
||||
// TODO: do we need to hash and create accounts map first?
|
||||
newcoin::FullLedger* ledger=new newcoin::FullLedger();
|
||||
ledger->set_index(mIndex);
|
||||
ledger->set_hash(mHash);
|
||||
|
||||
pair<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);
|
||||
pair<uint64,uint32> account=mAccounts[address];
|
||||
if( (account.first<trans->amount()) &&
|
||||
(trans->seqnum()==account.second) )
|
||||
{
|
||||
account.first -= trans->amount();
|
||||
account.second++;
|
||||
mAccounts[address]=account;
|
||||
|
||||
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())
|
||||
{
|
||||
mBundle.addDiscardedTransaction(trans);
|
||||
cout << "Not enough money" << endl;
|
||||
return(false);
|
||||
}
|
||||
cacheInputLeftOverAmount[n]=amountHeld-input.amount();
|
||||
}
|
||||
|
||||
for(int n=0; n<numInputs; n++)
|
||||
{
|
||||
const newcoin::TransInput& input=trans.inputs(n);
|
||||
mBundle.checkValid(input.from(),cacheInputLeftOverAmount[n],trans.seconds(),theConfig.LEDGER_SECONDS);
|
||||
}
|
||||
uint160 destAddress=NewcoinAddress::protobufToInternal(trans->dest());
|
||||
|
||||
Account destAccount=mAccounts[destAddress];
|
||||
destAccount.first += trans->amount();
|
||||
mAccounts[destAddress]=destAccount;
|
||||
|
||||
|
||||
mValidSig=false;
|
||||
mValidHash=false;
|
||||
mBundle.addTransaction(trans);
|
||||
|
||||
mTransactions.push_back(trans);
|
||||
if(mChild)
|
||||
{
|
||||
mChild->parentAddedTransaction(trans);
|
||||
}
|
||||
return(true);
|
||||
}else
|
||||
{
|
||||
mDiscardedTransactions.push_back(trans);
|
||||
return false;
|
||||
}
|
||||
}else
|
||||
{
|
||||
mDiscardedTransactions.push_back(trans);
|
||||
return false;
|
||||
}
|
||||
|
||||
}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);
|
||||
}
|
||||
}
|
||||
|
||||
// Don't check the amounts. We will do this at the end.
|
||||
void Ledger::addTransactionRecalculate(TransactionPtr trans)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
void Ledger::recheck(Ledger::pointer parent,newcoin::Transaction& cause)
|
||||
{
|
||||
// TODO:
|
||||
}
|
||||
49
Ledger.h
49
Ledger.h
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
125
LedgerMaster.cpp
125
LedgerMaster.cpp
@@ -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);
|
||||
}
|
||||
|
||||
// returns true if we should broadcast it
|
||||
bool LedgerMaster::addTransaction(newcoin::Transaction& trans)
|
||||
{
|
||||
if(! isValidTransactionSig(trans)) return(false);
|
||||
|
||||
if(trans.ledgerindex()==mFinalizingLedger->getIndex())
|
||||
// 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(mFinalizingLedger->addTransaction(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 relay it
|
||||
bool LedgerMaster::addTransaction(TransactionPtr trans)
|
||||
{
|
||||
if(mFinalizingLedger && (trans->ledgerindex()==mFinalizingLedger->getIndex()))
|
||||
{
|
||||
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(false);
|
||||
return( mCurrentLedger->addTransaction(trans,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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -21,6 +21,10 @@ public:
|
||||
|
||||
uint160 GetHash160();
|
||||
|
||||
static uint160 protobufToInternal(const std::string& buf);
|
||||
static uint160 humanToInternal(const std::string& buf);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
33
Peer.cpp
33
Peer.cpp
@@ -145,7 +145,7 @@ void Peer::sendFullLedger(Ledger::pointer ledger)
|
||||
}
|
||||
}
|
||||
|
||||
void Peer::sendGetFullLedger(uint64 index)
|
||||
void Peer::sendGetFullLedger(uint32 index)
|
||||
{
|
||||
newcoin::GetFullLedger* gfl=new newcoin::GetFullLedger();
|
||||
gfl->set_ledgerindex(index);
|
||||
@@ -207,8 +207,8 @@ void Peer::processReadBuffer()
|
||||
break;
|
||||
case newcoin::TRANSACTION:
|
||||
{
|
||||
newcoin::Transaction trans;
|
||||
if(trans.ParseFromArray(&mReadbuf[HEADER_SIZE], mReadbuf.size() - HEADER_SIZE))
|
||||
TransactionPtr trans(new newcoin::Transaction());
|
||||
if(trans->ParseFromArray(&mReadbuf[HEADER_SIZE], mReadbuf.size() - HEADER_SIZE))
|
||||
receiveTransaction(trans);
|
||||
else cout << "parse error: " << type << endl; //else BOOST_LOG_TRIVIAL(info) << "Error: " << error;
|
||||
|
||||
@@ -289,25 +289,22 @@ void Peer::receiveGetValidations(newcoin::GetValidations& request)
|
||||
}
|
||||
}
|
||||
|
||||
void Peer::receiveTransaction(newcoin::Transaction& trans)
|
||||
void Peer::receiveTransaction(TransactionPtr trans)
|
||||
{
|
||||
ConnectionPool& pool=theApp->getConnectionPool();
|
||||
PackedMessage::pointer packet(new PackedMessage(PackedMessage::MessagePointer(new newcoin::Transaction(trans)),newcoin::TRANSACTION));
|
||||
|
||||
// check if this transaction is already known
|
||||
if(pool.isMessageKnown(packet)) return;
|
||||
|
||||
// check if this transaction is valid
|
||||
// add to the correct transaction bundle
|
||||
if(!theApp->getLedgerMaster().addTransaction(trans))
|
||||
// add to the correct transaction bundle and relay if we need to
|
||||
if(theApp->getLedgerMaster().addTransaction(trans))
|
||||
{
|
||||
cout << "Invalid transaction: " << trans.transid() << endl;
|
||||
return;
|
||||
}
|
||||
// tell the wallet in case it was to us
|
||||
theApp->getWallet().transactionAdded(trans);
|
||||
|
||||
// broadcast it to other Peers
|
||||
pool.relayMessage(this,packet,trans.ledgerindex());
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void Peer::receiveProposeLedger(newcoin::ProposeLedger& packet)
|
||||
|
||||
5
Peer.h
5
Peer.h
@@ -7,6 +7,7 @@
|
||||
#include "newcoin.pb.h"
|
||||
#include "PackedMessage.h"
|
||||
#include "Ledger.h"
|
||||
#include "Transaction.h"
|
||||
#include "list"
|
||||
|
||||
class KnownNode;
|
||||
@@ -48,7 +49,7 @@ class Peer : public boost::enable_shared_from_this<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
35
Transaction.cpp
Normal 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());
|
||||
}
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
bool TransactionBundle::hasTransaction(TransactionPtr needle)
|
||||
{
|
||||
return(t1.transid()==t2.transid());
|
||||
BOOST_FOREACH(TransactionPtr trans,mTransactions)
|
||||
{
|
||||
if( Transaction::isEqual(needle,trans) ) return(true);
|
||||
}
|
||||
|
||||
bool TransactionBundle::hasTransaction(newcoin::Transaction& t)
|
||||
BOOST_FOREACH(TransactionPtr trans,mDisacrdedTransactions)
|
||||
{
|
||||
BOOST_FOREACH(newcoin::Transaction& trans,mTransactions)
|
||||
{
|
||||
if( t.transid()==trans.transid())
|
||||
return(true);
|
||||
}
|
||||
|
||||
BOOST_FOREACH(newcoin::Transaction& 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
|
||||
@@ -137,3 +129,5 @@ void TransactionBundle::updateMap(std::map<std::string,uint64>& moneyMap)
|
||||
moneyMap[trans.dest()] += total;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
@@ -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
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef __VALIDATION_COLLECTION__
|
||||
#define __VALIDATION_COLLECTION__
|
||||
|
||||
#include "newcoin.pb.h"
|
||||
#include "types.h"
|
||||
#include "uint256.h"
|
||||
|
||||
class ValidationCollection
|
||||
{
|
||||
@@ -15,3 +17,5 @@ public:
|
||||
|
||||
std::vector<newcoin::Validation>* getValidations(uint64 ledgerIndex);
|
||||
};
|
||||
|
||||
#endif
|
||||
152
Wallet.cpp
152
Wallet.cpp
@@ -17,9 +17,9 @@ void Wallet::load()
|
||||
|
||||
}
|
||||
|
||||
uint64 Wallet::getBalance()
|
||||
int64 Wallet::getBalance()
|
||||
{
|
||||
uint64 total = 0;
|
||||
int64 total = 0;
|
||||
|
||||
LedgerMaster& ledgerMaster=theApp->getLedgerMaster();
|
||||
|
||||
@@ -31,79 +31,99 @@ uint64 Wallet::getBalance()
|
||||
return total;
|
||||
}
|
||||
|
||||
string Wallet::sendMoneyToAddress(NewcoinAddress& destAddress, uint64 amount)
|
||||
void Wallet::refreshAccounts()
|
||||
{
|
||||
// Check amount
|
||||
if(amount > getBalance())
|
||||
return("Insufficient funds");
|
||||
LedgerMaster& ledgerMaster=theApp->getLedgerMaster();
|
||||
|
||||
newcoin::Transaction trans;
|
||||
if(!createTransaction(destAddress, amount, trans))
|
||||
BOOST_FOREACH(Account& account, mYourAccounts)
|
||||
{
|
||||
return "Error: Transaction creation failed ";
|
||||
Ledger::Account* ledgerAccount=ledgerMaster.getAccount(account.mAddress);
|
||||
if(ledgerAccount)
|
||||
{
|
||||
account.mAmount= ledgerAccount->first;
|
||||
account.mSeqNum= ledgerAccount->second;
|
||||
}else
|
||||
{
|
||||
account.mAmount=0;
|
||||
account.mSeqNum=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Wallet::transactionAdded(TransactionPtr trans)
|
||||
{ // TODO: optimize
|
||||
refreshAccounts();
|
||||
}
|
||||
|
||||
Wallet::Account* Wallet::consolidateAccountOfSize(int64 amount)
|
||||
{
|
||||
int64 total=0;
|
||||
BOOST_FOREACH(Account& account, mYourAccounts)
|
||||
{
|
||||
if(account.mAmount>=amount) return(&account);
|
||||
total += account.mAmount;
|
||||
}
|
||||
if(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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
36
Wallet.h
36
Wallet.h
@@ -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);
|
||||
|
||||
bool createTransaction(NewcoinAddress& destAddress, uint64 amount,newcoin::Transaction& trans);
|
||||
bool commitTransaction(newcoin::Transaction& trans);
|
||||
|
||||
TransactionPtr createTransaction(Account& fromAccount, uint160& destAddr, int64 amount);
|
||||
bool commitTransaction(TransactionPtr trans);
|
||||
|
||||
Account* consolidateAccountOfSize(int64 amount);
|
||||
|
||||
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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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" />
|
||||
|
||||
11
notes.txt
11
notes.txt
@@ -2,7 +2,7 @@
|
||||
Dependencies:
|
||||
Boost 1_47
|
||||
boost log http://boost-log.sourceforge.net/libs/log/doc/html/log/installation.html
|
||||
protocol buffers
|
||||
protocol buffers: expects ..\protobuf-2.4.1 and ..\protoc-2.4.1-win32
|
||||
openssl
|
||||
|
||||
Using:
|
||||
@@ -25,18 +25,9 @@ code from:
|
||||
|
||||
|
||||
|
||||
message Packet {
|
||||
enum Type { HELLO = 1; TRANSACTION = 2; VALIDATION = 3; }
|
||||
|
||||
// Identifies which field is filled in.
|
||||
required Type type = 1;
|
||||
|
||||
// One of the following will be filled in.
|
||||
optional Hello hello=2;
|
||||
optional Transaction transaction=3;
|
||||
optional Validation validation=4;
|
||||
|
||||
}
|
||||
|
||||
Threads
|
||||
----
|
||||
|
||||
6
types.h
6
types.h
@@ -1,9 +1,15 @@
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
|
||||
typedef __int64 int64;
|
||||
typedef unsigned __int64 uint64;
|
||||
typedef unsigned int uint32;
|
||||
|
||||
#else
|
||||
|
||||
typedef long long int64;
|
||||
typedef unsigned long long uint64;
|
||||
typedef unsigned int uint32;
|
||||
|
||||
#endif
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1300
|
||||
#define for if (false) ; else for
|
||||
|
||||
Reference in New Issue
Block a user