Cleanups and fixes.

This commit is contained in:
JoelKatz
2011-12-20 22:01:06 -08:00
parent d4276bfbec
commit 780f94798e
6 changed files with 54 additions and 292 deletions

View File

@@ -260,26 +260,26 @@ Ledger::pointer Ledger::closeLedger(uint64 timeStamp)
bool Ledger::unitTest() bool Ledger::unitTest()
{ {
LocalAccount l1(true), l2(true); LocalAccount l1(true), l2(true);
assert(l1.peekPubKey()); assert(l1.peekPubKey());
uint160 la1(l1.getAddress()), la2(l2.getAddress()); uint160 la1(l1.getAddress()), la2(l2.getAddress());
#ifdef DEBUG #ifdef DEBUG
std::cerr << "Account1: " << la1.GetHex() << std::endl; std::cerr << "Account1: " << la1.GetHex() << std::endl;
std::cerr << "Account2: " << la2.GetHex() << std::endl; std::cerr << "Account2: " << la2.GetHex() << std::endl;
#endif #endif
Ledger::pointer ledger(new Ledger(la1, 100000)); Ledger::pointer ledger(new Ledger(la1, 100000));
l1.mAmount=100000; l1.mAmount=100000;
ledger=Ledger::pointer(new Ledger(*ledger, 0)); ledger=Ledger::pointer(new Ledger(*ledger, 0));
AccountState::pointer as=ledger->getAccountState(la1); AccountState::pointer as=ledger->getAccountState(la1);
assert(as); assert(as);
assert(as->getBalance()==100000); assert(as->getBalance()==100000);
assert(as->getSeq()==0); assert(as->getSeq()==0);
as=ledger->getAccountState(la2); as=ledger->getAccountState(la2);
assert(!as); assert(!as);
Transaction::pointer t(new Transaction(NEW, l1, l1.mSeqNum, l2.getAddress(), 2500, 0, 1)); Transaction::pointer t(new Transaction(NEW, l1, l1.mSeqNum, l2.getAddress(), 2500, 0, 1));
assert(!!t->getID()); assert(!!t->getID());
@@ -290,10 +290,9 @@ bool Ledger::unitTest()
#endif #endif
assert(tr==TR_SUCCESS); assert(tr==TR_SUCCESS);
return true; return true;
} }
uint256 Ledger::getHash() uint256 Ledger::getHash()
{ {
if(!mValidHash) updateHash(); if(!mValidHash) updateHash();
@@ -383,106 +382,6 @@ Ledger::pointer Ledger::loadByHash(const uint256& ledgerHash)
} }
#if 0 #if 0
Ledger::pointer Ledger::getParent()
{
if(!mParent)
{
mParent=theApp->getLedgerMaster().getLedger(mParentHash);
}
return(mParent);
}
// TODO: we can optimize so the ledgers only hold the delta from the accepted ledger
// TODO: check to make sure the ledger is consistent after we load it
bool Ledger::load(const uint256& hash)
{
Database* db=theApp->getDB();
string sql="SELECT * from Ledgers where hash=";
string hashStr;
db->escape(hash.begin(),hash.GetSerializeSize(),hashStr);
sql.append(hashStr);
if(db->executeSQL(sql.c_str()))
{
if(db->getNextRow())
{
mIndex=db->getInt("LedgerIndex");
mHash=hash;
mValidSig=false;
mAccounts.clear();
mTransactions.clear();
mDiscardedTransactions.clear();
db->getBinary("ParentHash",mParentHash.begin(),mParentHash.GetSerializeSize());
mFeeHeld=db->getBigInt("FeeHeld");
char buf[100];
sql="SELECT Transactions.* from Transactions,LedgerTransactionMap where Transactions.TransactionID=LedgerTransactionMap.TransactionID and LedgerTransactionMap.LedgerID=";
sprintf(buf, "%d", db->getInt(0));
sql.append(buf);
if(db->executeSQL(sql.c_str()))
{
unsigned char tbuf[1000];
while(db->getNextRow())
{
Transaction::pointer trans=Transaction::pointer(new newcoin::Transaction());
trans->set_amount( db->getBigInt("Amount"));
trans->set_seqnum( db->getInt("seqnum"));
trans->set_ledgerindex( db->getInt("ledgerIndex"));
db->getBinary("from",tbuf,1000);
trans->set_from(tbuf,20);
db->getBinary("dest",tbuf,1000);
trans->set_dest(tbuf,20);
db->getBinary("pubkey",tbuf,1000);
trans->set_pubkey(tbuf,128);
db->getBinary("sig",tbuf,1000);
trans->set_sig(tbuf,32);
mTransactions.push_back(trans);
}
}
sql="SELECT Accounts.* from Acconts,LedgerAcountMap where Accounts.AccountID=LedgerAccountMap.AccountID and LedgerAccountMap.LedgerID=";
sql.append(buf);
if(db->executeSQL(sql.c_str()))
{
while(db->getNextRow())
{
uint160 address;
db->getBinary("Address",address.begin(),address.GetSerializeSize());
mAccounts[address].first=db->getBigInt("Amount");
mAccounts[address].second=db->getInt("SeqNum");
}
}
return(true);
}
}
return(false);
}
uint256& Ledger::getSignature()
{
if(!mValidSig) sign();
return(mSignature);
}
void Ledger::publishValidation()
{
PackedMessage::pointer packet=Peer::createValidation(shared_from_this());
theApp->getConnectionPool().relayMessage(NULL,packet);
}
/*
uint64 Ledger::getAmount(std::string address)
{
return(mAccounts[NewcoinAddress:: address].first);
}*/
// returns true if the from account has enough for the transaction and seq num is correct // returns true if the from account has enough for the transaction and seq num is correct
bool Ledger::addTransaction(Transaction::pointer trans,bool checkDuplicate) bool Ledger::addTransaction(Transaction::pointer trans,bool checkDuplicate)
{ {
@@ -587,150 +486,6 @@ void Ledger::addTransactionAllowNeg(Transaction::pointer trans)
// 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<Transaction::pointer> firstTransactions=mTransactions;
list<Transaction::pointer> secondTransactions=mDiscardedTransactions;
mTransactions.clear();
mDiscardedTransactions.clear();
firstTransactions.sort(gTransactionSorter);
secondTransactions.sort(gTransactionSorter);
// don't check balances until the end
BOOST_FOREACH(Transaction::pointer trans,firstTransactions)
{
addTransactionAllowNeg(trans);
}
BOOST_FOREACH(Transaction::pointer trans,secondTransactions)
{
addTransactionAllowNeg(trans);
}
correctAccounts();
if(mChild && recursive) mChild->recalculate();
}else
{
cout << "Can't recalculate if there is no parent" << endl;
}
}
void Ledger::parentAddedTransaction(Transaction::pointer cause)
{
// TODO: optimize 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=protobufTo160(cause->from());
uint160 destAddress=protobufTo160(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(Transaction::pointer trans,)
*/
}
bool Ledger::hasTransaction(Transaction::pointer needle)
{
BOOST_FOREACH(Transaction::pointer trans,mTransactions)
{
if( Transaction::isEqual(needle,trans) ) return(true);
}
BOOST_FOREACH(Transaction::pointer disTrans,mDiscardedTransactions)
{
if( Transaction::isEqual(needle,disTrans) ) return(true);
}
return(false);
}
// Ledgers are compatible if both sets of transactions merged together would lead to the same ending balance
bool Ledger::isCompatible(Ledger::pointer other)
{
Ledger::pointer l1=Ledger::pointer(new Ledger(*this));
Ledger::pointer l2=Ledger::pointer(new Ledger(*other));
l1->mergeIn(l2);
l2->mergeIn(l1);
map<uint160, Account > a1=l1->getAccounts();
map<uint160, Account > a2=l2->getAccounts();
return(a1==a2);
}
void Ledger::mergeIn(Ledger::pointer other)
{
list<Transaction::pointer>& otherTransactions=other->getTransactions();
BOOST_FOREACH(Transaction::pointer trans,otherTransactions)
{
addTransactionAllowNeg(trans);
}
correctAccounts();
}
void Ledger::correctAccounts()
{
BOOST_FOREACH(PAIR(const uint160, Account)& fullAccount, mAccounts)
{
if(fullAccount.second.first <0 )
{
correctAccount(fullAccount.first);
}
}
}
// Must look for transactions to discard to make this account positive // Must look for transactions to discard to make this account positive
// When we chuck transactions it might cause other accounts to need correcting // When we chuck transactions it might cause other accounts to need correcting
void Ledger::correctAccount(const uint160& address) void Ledger::correctAccount(const uint160& address)

View File

@@ -445,7 +445,7 @@ bool SHAMap::addGiveItem(const SHAMapItem::pointer item)
#endif #endif
return false; return false;
} }
if(!leaf->addUpdateItem(item)) if(!leaf->addUpdateItem(item, true))
{ {
assert(false); assert(false);
return false; return false;
@@ -464,7 +464,7 @@ bool SHAMap::updateGiveItem(SHAMapItem::pointer item)
boost::recursive_mutex::scoped_lock sl(mLock); boost::recursive_mutex::scoped_lock sl(mLock);
SHAMapLeafNode::pointer leaf=walkToLeaf(item->getTag(), true, true); SHAMapLeafNode::pointer leaf=walkToLeaf(item->getTag(), true, true);
if(!leaf) return false; if(!leaf) return false;
if(!leaf->addUpdateItem(item)) return false; if(!leaf->addUpdateItem(item, true)) return false;
dirtyUp(item->getTag()); dirtyUp(item->getTag());
return true; return true;
} }

View File

@@ -125,7 +125,7 @@ private:
SHAMapLeafNode& operator=(const SHAMapLeafNode&); // no implementation SHAMapLeafNode& operator=(const SHAMapLeafNode&); // no implementation
protected: protected:
bool addUpdateItem(SHAMapItem::pointer); bool addUpdateItem(SHAMapItem::pointer, bool doHash);
bool delItem(const SHAMapItem::pointer i) { return delItem(i->getTag()); } bool delItem(const SHAMapItem::pointer i) { return delItem(i->getTag()); }
bool delItem(const uint256& tag); bool delItem(const uint256& tag);

View File

@@ -61,15 +61,14 @@ void SHAMapNode::ClassInit()
for(int i=0; i<=leafDepth; i++) for(int i=0; i<=leafDepth; i++)
{ {
smMasks[i]=selector; smMasks[i]=selector;
*(selector.begin()+i)=0x1f; *(selector.begin()+i)=0x1F;
} }
} }
uint256 SHAMapNode::getNodeID(int depth, const uint256& hash) uint256 SHAMapNode::getNodeID(int depth, const uint256& hash)
{ {
assert(depth>=0 && depth<=leafDepth); assert(depth>=0 && depth<=leafDepth);
uint256 ret = hash & smMasks[depth]; return hash & smMasks[depth];
return ret;
} }
SHAMapNode::SHAMapNode(int depth, const uint256 &hash) : mDepth(depth) SHAMapNode::SHAMapNode(int depth, const uint256 &hash) : mDepth(depth)
@@ -103,7 +102,7 @@ int SHAMapNode::selectBranch(const uint256 &hash)
return -1; // does not go under this node return -1; // does not go under this node
} }
uint256 selector=hash&smMasks[mDepth+1]; uint256 selector(hash & smMasks[mDepth+1]);
int branch=*(selector.begin()+mDepth); int branch=*(selector.begin()+mDepth);
assert(branch>=0 && branch<32); assert(branch>=0 && branch<32);
return branch; return branch;
@@ -127,7 +126,7 @@ SHAMapLeafNode::SHAMapLeafNode(const SHAMapLeafNode& node, uint32 seq) : SHAMapN
SHAMapLeafNode::SHAMapLeafNode(const SHAMapNode& id, const std::vector<unsigned char>& rawLeaf, uint32 seq) SHAMapLeafNode::SHAMapLeafNode(const SHAMapNode& id, const std::vector<unsigned char>& rawLeaf, uint32 seq)
: SHAMapNode(id), mSeq(seq) : SHAMapNode(id), mSeq(seq)
{ // OPTIMIZEME:: addUpdateItem updates the hash {
Serializer s(rawLeaf); Serializer s(rawLeaf);
int pos=0; int pos=0;
while(pos<s.getLength()) while(pos<s.getLength())
@@ -138,7 +137,7 @@ SHAMapLeafNode::SHAMapLeafNode(const SHAMapNode& id, const std::vector<unsigned
if(!s.get16(len, pos)) throw SHAMapException(InvalidNode); if(!s.get16(len, pos)) throw SHAMapException(InvalidNode);
pos+=2; pos+=2;
if(!id || !len || ((pos+len)>s.getLength())) throw SHAMapException(InvalidNode); if(!id || !len || ((pos+len)>s.getLength())) throw SHAMapException(InvalidNode);
addUpdateItem(SHAMapItem::pointer(new SHAMapItem(id, s.getRaw(pos, len)))); addUpdateItem(SHAMapItem::pointer(new SHAMapItem(id, s.getRaw(pos, len))), false);
pos+=len; pos+=len;
} }
updateHash(); updateHash();
@@ -161,7 +160,7 @@ bool SHAMapLeafNode::hasItem(const uint256& item) const
return false; return false;
} }
bool SHAMapLeafNode::addUpdateItem(SHAMapItem::pointer item) bool SHAMapLeafNode::addUpdateItem(SHAMapItem::pointer item, bool doHash)
{ // The node will almost never have more than one item in it { // The node will almost never have more than one item in it
#ifdef DEBUG #ifdef DEBUG
std::cerr << "Leaf(" << getString() << ")" << std::endl; std::cerr << "Leaf(" << getString() << ")" << std::endl;
@@ -176,16 +175,20 @@ bool SHAMapLeafNode::addUpdateItem(SHAMapItem::pointer item)
if(nodeItem.peekData()==item->peekData()) if(nodeItem.peekData()==item->peekData())
return false; // no change return false; // no change
nodeItem.updateData(item->peekData()); nodeItem.updateData(item->peekData());
return updateHash(); if(doHash) return updateHash();
return true;
} }
if(nodeItem.getTag()>item->getTag()) if(nodeItem.getTag()>item->getTag())
{ {
mItems.insert(it, item); mItems.insert(it, item);
return updateHash(); if(doHash) return updateHash();
return true;
} }
} }
mItems.push_back(item); mItems.push_back(item);
return updateHash();
if(doHash) return updateHash();
return true;
} }
bool SHAMapLeafNode::delItem(const uint256& tag) bool SHAMapLeafNode::delItem(const uint256& tag)
@@ -258,7 +261,6 @@ SHAMapItem::pointer SHAMapLeafNode::lastItem()
return *(mItems.rbegin()); return *(mItems.rbegin());
} }
bool SHAMapLeafNode::updateHash() bool SHAMapLeafNode::updateHash()
{ {
uint256 nh; uint256 nh;
@@ -289,6 +291,7 @@ SHAMapInnerNode::SHAMapInnerNode(const SHAMapNode& id, const std::vector<unsigne
: SHAMapNode(id), mSeq(seq) : SHAMapNode(id), mSeq(seq)
{ {
assert(!id.isLeaf()); assert(!id.isLeaf());
assert(contents.size()==32*256/8);
Serializer s(contents); Serializer s(contents);
for(int i=0; i<32; i++) for(int i=0; i<32; i++)
mHashes[i]=s.get256(i*32); mHashes[i]=s.get256(i*32);
@@ -340,7 +343,7 @@ const uint256& SHAMapInnerNode::getChildHash(int m) const
bool SHAMapInnerNode::updateHash() bool SHAMapInnerNode::updateHash()
{ {
int nc=0; int nc=0;
Serializer s; Serializer s(1024);
for(int i=0; i<32; i++) for(int i=0; i<32; i++)
{ {
if(mHashes[i]!=0) nc++; if(mHashes[i]!=0) nc++;

View File

@@ -12,26 +12,25 @@
std::vector<unsigned char> CKeyStore::GenerateNewKey() std::vector<unsigned char> CKeyStore::GenerateNewKey()
{ {
RandAddSeedPerfmon(); RandAddSeedPerfmon();
CKey key; CKey key;
key.MakeNewKey(); key.MakeNewKey();
if (!AddKey(key)) if (!AddKey(key))
throw std::runtime_error("CKeyStore::GenerateNewKey() : AddKey failed"); throw std::runtime_error("CKeyStore::GenerateNewKey() : AddKey failed");
return key.GetPubKey(); return key.GetPubKey();
} }
bool CKeyStore::GetPubKey(const NewcoinAddress &address, std::vector<unsigned char> &vchPubKeyOut) const bool CKeyStore::GetPubKey(const NewcoinAddress& address, std::vector<unsigned char>& vchPubKeyOut) const
{ {
CKey key; CKey key;
if (!GetKey(address, key)) if (!GetKey(address, key))
return false; return false;
vchPubKeyOut = key.GetPubKey(); vchPubKeyOut = key.GetPubKey();
return true; return true;
} }
bool CBasicKeyStore::AddKey(const CKey& key) bool CBasicKeyStore::AddKey(const CKey& key)
{ {
mapKeys[key.GetAddress()] = key.GetSecret();
mapKeys[key.GetAddress()] = key.GetSecret(); return true;
return true;
} }

View File

@@ -1,3 +1,6 @@
#ifndef __TYPES_HH__
#define __TYPES_HH__
#if defined(_MSC_VER) || defined(__BORLANDC__) #if defined(_MSC_VER) || defined(__BORLANDC__)
typedef __int64 int64; typedef __int64 int64;
@@ -17,4 +20,6 @@ typedef int int32;
#endif #endif
#if defined(_MSC_VER) && _MSC_VER < 1300 #if defined(_MSC_VER) && _MSC_VER < 1300
#define for if (false) ; else for #define for if (false) ; else for
#endif #endif
#endif