Change ledger and db structures to use new ledger close timing logic.

This commit is contained in:
JoelKatz
2012-07-11 18:18:28 -07:00
parent c637c01abc
commit 513d248c93
3 changed files with 106 additions and 98 deletions

View File

@@ -43,7 +43,10 @@ const char *LedgerDBInit[] = {
LedgerSeq BIGINT UNSIGNED, \
PrevHash CHARACTER(64), \
TotalCoins BIGINT UNSIGNED, \
ClosingTime BIGINT UNSINGED, \
ClosingTime BIGINT UNSIGNED, \
PrevClosingTime BIGINT UNSIGNED, \
CloseTimeRes BIGINT UNSIGNED, \
CloseFlags, BIGINT UNSIGNED, \
AccountSetHash CHARACTER(64), \
TransSetHash CHARACTER(64) \
);",

View File

@@ -16,14 +16,14 @@
#include "Conversion.h"
#include "BitcoinUtil.h"
#include "Wallet.h"
#include "BinaryFormats.h"
#include "LedgerTiming.h"
#include "HashPrefixes.h"
#include "Log.h"
Ledger::Ledger(const NewcoinAddress& masterID, uint64 startAmount) : mTotCoins(startAmount),
mCloseTime(0), mLedgerSeq(0), mClosed(false), mValidHash(false),
mAccepted(false), mImmutable(false), mTransactionMap(new SHAMap()), mAccountStateMap(new SHAMap())
Ledger::Ledger(const NewcoinAddress& masterID, uint64 startAmount) : mTotCoins(startAmount), mLedgerSeq(0),
mCloseTime(0), mParentCloseTime(0), mCloseResolution(LEDGER_TIME_ACCURACY), mCloseFlags(0),
mClosed(false), mValidHash(false), mAccepted(false), mImmutable(false),
mTransactionMap(new SHAMap()), mAccountStateMap(new SHAMap())
{
// special case: put coins in root account
AccountState::pointer startAccount = boost::make_shared<AccountState>(masterID);
@@ -37,15 +37,18 @@ Ledger::Ledger(const NewcoinAddress& masterID, uint64 startAmount) : mTotCoins(s
}
Ledger::Ledger(const uint256 &parentHash, const uint256 &transHash, const uint256 &accountHash,
uint64 totCoins, uint64 timeStamp, uint32 ledgerSeq)
: mParentHash(parentHash), mTransHash(transHash), mAccountHash(accountHash),
mTotCoins(totCoins), mCloseTime(timeStamp), mLedgerSeq(ledgerSeq),
uint64 totCoins, uint32 closeTime, uint32 parentCloseTime, int closeFlags, int closeResolution, uint32 ledgerSeq)
: mParentHash(parentHash), mTransHash(transHash), mAccountHash(accountHash), mTotCoins(totCoins),
mLedgerSeq(ledgerSeq), mCloseTime(closeTime), mParentCloseTime(parentCloseTime),
mCloseResolution(closeResolution), mCloseFlags(closeFlags),
mClosed(false), mValidHash(false), mAccepted(false), mImmutable(false)
{
updateHash();
}
Ledger::Ledger(Ledger& ledger, bool isMutable) : mTotCoins(ledger.mTotCoins), mLedgerSeq(ledger.mLedgerSeq),
mCloseTime(ledger.mCloseTime), mParentCloseTime(ledger.mParentCloseTime),
mCloseResolution(ledger.mCloseResolution), mCloseFlags(ledger.mCloseFlags),
mClosed(ledger.mClosed), mValidHash(false), mAccepted(ledger.mAccepted), mImmutable(!isMutable),
mTransactionMap(ledger.mTransactionMap->snapShot(isMutable)),
mAccountStateMap(ledger.mAccountStateMap->snapShot(isMutable))
@@ -54,9 +57,10 @@ Ledger::Ledger(Ledger& ledger, bool isMutable) : mTotCoins(ledger.mTotCoins), mL
}
Ledger::Ledger(uint64 closeTime, Ledger& prevLedger) :
mTotCoins(prevLedger.mTotCoins), mCloseTime(closeTime), mLedgerSeq(prevLedger.mLedgerSeq + 1),
mClosed(false), mValidHash(false), mAccepted(false), mImmutable(false),
Ledger::Ledger(bool dummy, Ledger& prevLedger) :
mTotCoins(prevLedger.mTotCoins), mLedgerSeq(prevLedger.mLedgerSeq + 1),
mCloseTime(0), mParentCloseTime(prevLedger.mCloseTime), mCloseResolution(prevLedger.mCloseResolution),
mCloseFlags(0), mClosed(false), mValidHash(false), mAccepted(false), mImmutable(false),
mTransactionMap(new SHAMap()), mAccountStateMap(prevLedger.mAccountStateMap->snapShot(true))
{ // Create a new ledger that follows this one
prevLedger.updateHash();
@@ -64,42 +68,16 @@ Ledger::Ledger(uint64 closeTime, Ledger& prevLedger) :
assert(mParentHash.isNonZero());
}
Ledger::Ledger(const std::vector<unsigned char>& rawLedger) : mCloseTime(0),
mLedgerSeq(0), mClosed(false), mValidHash(false), mAccepted(false), mImmutable(true)
Ledger::Ledger(const std::vector<unsigned char>& rawLedger) :
mClosed(false), mValidHash(false), mAccepted(false), mImmutable(true)
{
Serializer s(rawLedger);
// 32seq, 64fee, 256phash, 256thash, 256ahash, 64ts
if (!s.get32(mLedgerSeq, BLgPIndex)) return;
if (!s.get64(mTotCoins, BLgPTotCoins)) return;
if (!s.get256(mParentHash, BLgPPrevLg)) return;
if (!s.get256(mTransHash, BLgPTxT)) return;
if (!s.get256(mAccountHash, BLgPAcT)) return;
if (!s.get64(mCloseTime, BLgPClTs)) return;
updateHash();
if(mValidHash)
{
mTransactionMap = boost::make_shared<SHAMap>();
mAccountStateMap = boost::make_shared<SHAMap>();
}
setRaw(Serializer(rawLedger));
}
Ledger::Ledger(const std::string& rawLedger) : mCloseTime(0),
mLedgerSeq(0), mClosed(false), mValidHash(false), mAccepted(false), mImmutable(true)
Ledger::Ledger(const std::string& rawLedger) :
mClosed(false), mValidHash(false), mAccepted(false), mImmutable(true)
{
Serializer s(rawLedger);
// 32seq, 64fee, 256phash, 256thash, 256ahash, 64ts
if (!s.get32(mLedgerSeq, BLgPIndex)) return;
if (!s.get64(mTotCoins, BLgPTotCoins)) return;
if (!s.get256(mParentHash, BLgPPrevLg)) return;
if (!s.get256(mTransHash, BLgPTxT)) return;
if (!s.get256(mAccountHash, BLgPAcT)) return;
if (!s.get64(mCloseTime, BLgPClTs)) return;
updateHash();
if(mValidHash)
{
mTransactionMap = boost::make_shared<SHAMap>();
mAccountStateMap = boost::make_shared<SHAMap>();
}
setRaw(Serializer(rawLedger));
}
void Ledger::updateHash()
@@ -112,21 +90,62 @@ void Ledger::updateHash()
else mAccountHash.zero();
}
Serializer s(116);
Serializer s(118);
s.add32(sHP_Ledger);
addRaw(s);
mHash = s.getSHA512Half();
mValidHash = true;
}
void Ledger::addRaw(Serializer &s)
void Ledger::setRaw(const Serializer &s)
{
SerializerIterator sit(s);
mLedgerSeq = sit.get32();
mTotCoins = sit.get64();
mParentHash = sit.get256();
mTransHash = sit.get256();
mAccountHash = sit.get256();
mCloseTime = sit.get32();
mCloseResolution = sit.get8();
mCloseFlags = sit.get8();
updateHash();
if(mValidHash)
{
mTransactionMap = boost::make_shared<SHAMap>(mTransHash);
mAccountStateMap = boost::make_shared<SHAMap>(mAccountHash);
}
}
void Ledger::addRaw(Serializer &s) const
{
s.add32(mLedgerSeq);
s.add64(mTotCoins);
s.add256(mParentHash);
s.add256(mTransHash);
s.add256(mAccountHash);
s.add64(mCloseTime);
s.add32(mParentCloseTime);
s.add32(mCloseTime);
s.add8(mCloseResolution);
s.add8(mCloseFlags);
}
void Ledger::setAccepted(uint32 closeTime, int closeResolution, bool correctCloseTime)
{ // used when we witnessed the consensus
assert(mClosed && !mAccepted);
mCloseTime = closeTime;
mCloseResolution = closeResolution;
mCloseFlags = correctCloseTime ? 0 : sLCF_NoConsensusTime;
updateHash();
mAccepted = true;
mImmutable = true;
}
void Ledger::setAccepted()
{ // used when we acquired the ledger
assert(mClosed && !mAccepted && (mCloseResolution != 0));
updateHash();
mAccepted = true;
mImmutable = true;
}
AccountState::pointer Ledger::getAccountState(const NewcoinAddress& accountID)
@@ -238,28 +257,18 @@ void Ledger::saveAcceptedLedger(Ledger::pointer ledger)
static boost::format AcctTransExists("SELECT LedgerSeq FROM AccountTransactions WHERE TransId = '%s';");
static boost::format transExists("SELECT Status FROM Transactions WHERE TransID = '%s';");
static boost::format updateTx("UPDATE Transactions SET LedgerSeq = %d, Status = '%c' WHERE TransID = '%s';");
std::string sql="INSERT INTO Ledgers "
"(LedgerHash,LedgerSeq,PrevHash,TotalCoins,ClosingTime,AccountSetHash,TransSetHash) VALUES ('";
sql.append(ledger->getHash().GetHex());
sql.append("','");
sql.append(boost::lexical_cast<std::string>(ledger->mLedgerSeq));
sql.append("','");
sql.append(ledger->mParentHash.GetHex());
sql.append("','");
sql.append(boost::lexical_cast<std::string>(ledger->mTotCoins));
sql.append("','");
sql.append(boost::lexical_cast<std::string>(ledger->mCloseTime));
sql.append("','");
sql.append(ledger->mAccountHash.GetHex());
sql.append("','");
sql.append(ledger->mTransHash.GetHex());
sql.append("');");
static boost::format addLedger("INSERT INTO Ledgers "
"(LedgerHash,LedgerSeq,PrevHash,TotalCoins,ClosingTime,PrevClosingTime,CloseTimeRes,CloseFlags,"
"AccountSetHash,TranSetHash) VALUES ('%s','%u','%s','%s','%u','%u','%d','%u','%s','%s');");
ScopedLock sl(theApp->getLedgerDB()->getDBLock());
if (SQL_EXISTS(theApp->getLedgerDB()->getDB(), boost::str(ledgerExists % ledger->mLedgerSeq)))
theApp->getLedgerDB()->getDB()->executeSQL(boost::str(deleteLedger % ledger->mLedgerSeq));
theApp->getLedgerDB()->getDB()->executeSQL(sql);
theApp->getLedgerDB()->getDB()->executeSQL(boost::str(addLedger %
ledger->getHash().GetHex() % ledger->mLedgerSeq % ledger->mParentHash.GetHex() %
boost::lexical_cast<std::string>(ledger->mTotCoins) % ledger->mCloseTime % ledger->mParentCloseTime %
ledger->mCloseResolution % ledger->mCloseFlags %
ledger->mAccountHash.GetHex() % ledger->mTransHash.GetHex()));
// write out dirty nodes
while(ledger->mTransactionMap->flushDirty(256, TRANSACTION_NODE, ledger->mLedgerSeq))
@@ -328,8 +337,10 @@ void Ledger::saveAcceptedLedger(Ledger::pointer ledger)
Ledger::pointer Ledger::getSQL(const std::string& sql)
{
uint256 ledgerHash, prevHash, accountHash, transHash;
uint64 totCoins, closingTime;
uint32 ledgerSeq;
uint64 totCoins;
uint32 closingTime, prevClosingTime, ledgerSeq;
int closeResolution;
unsigned closeFlags;
std::string hash;
{
@@ -349,12 +360,16 @@ Ledger::pointer Ledger::getSQL(const std::string& sql)
transHash.SetHex(hash);
totCoins = db->getBigInt("TotalCoins");
closingTime = db->getBigInt("ClosingTime");
prevClosingTime = db->getBigInt("PrevClosingTime");
closeResolution = db->getBigInt("CloseTimeRes");
closeFlags = db->getBigInt("CloseFlags");
ledgerSeq = db->getBigInt("LedgerSeq");
db->endIterRows();
}
Ledger::pointer ret =
boost::make_shared<Ledger>(prevHash, transHash, accountHash, totCoins, closingTime, ledgerSeq);
boost::make_shared<Ledger>(prevHash, transHash, accountHash, totCoins, closingTime, prevClosingTime,
closeFlags, closeResolution, ledgerSeq);
if (ret->getHash() != ledgerHash)
{
Json::StyledStreamWriter ssw;
@@ -474,24 +489,4 @@ void Ledger::setCloseTime(boost::posix_time::ptime ptm)
mCloseTime = iToSeconds(ptm);
}
uint64 Ledger::sGenesisClose = 0;
uint64 Ledger::getNextLedgerClose(int prevCloseSeconds) const
{
if (mCloseTime == 0)
{
if (sGenesisClose == 0)
{
uint64 closeTime = theApp->getOPs().getNetworkTimeNC() + LEDGER_IDLE_INTERVAL - 1;
sGenesisClose = closeTime - (closeTime % LEDGER_IDLE_INTERVAL);
}
return sGenesisClose;
}
if (prevCloseSeconds < 0)
return mCloseTime + LEDGER_IDLE_INTERVAL;
if (prevCloseSeconds < 2)
return mCloseTime + prevCloseSeconds;
return mCloseTime + prevCloseSeconds - 1;
}
// vim:ts=4

View File

@@ -58,15 +58,18 @@ public:
TR_TOOSMALL = 9, // amount is less than Tx fee
};
// ledger close flags
static const uint32 sLCF_NoConsensusTime = 1;
private:
static uint64 sGenesisClose;
uint256 mHash, mParentHash, mTransHash, mAccountHash;
uint64 mTotCoins;
uint64 mCloseTime; // when this ledger should close / did close
uint64 mParentCloseTime;
uint32 mLedgerSeq;
uint32 mCloseTime; // when this ledger closed
uint32 mParentCloseTime; // when the previous ledger closed
int mCloseResolution; // the resolution for this ledger close time (2-120 seconds)
uint32 mCloseFlags; // flags indicating how this ledger close took place
bool mClosed, mValidHash, mAccepted, mImmutable;
SHAMap::pointer mTransactionMap, mAccountStateMap;
@@ -87,16 +90,23 @@ protected:
public:
Ledger(const NewcoinAddress& masterID, uint64 startAmount); // used for the starting bootstrap ledger
Ledger(const uint256 &parentHash, const uint256 &transHash, const uint256 &accountHash,
uint64 totCoins, uint64 timeStamp, uint32 ledgerSeq); // used for database ledgers
uint64 totCoins, uint32 closeTime, uint32 parentCloseTime, int closeFlags, int closeResolution,
uint32 ledgerSeq); // used for database ledgers
Ledger(const std::vector<unsigned char>& rawLedger);
Ledger(const std::string& rawLedger);
Ledger(uint64 defaultCloseTime, Ledger& previous); // ledger after this one
Ledger(bool dummy, Ledger& previous); // ledger after this one
Ledger(Ledger& target, bool isMutable); // snapshot
void updateHash();
void setClosed() { mClosed = true; }
void setAccepted() { mAccepted = true; }
void setAccepted(uint32 closeTime, int closeResolution, bool correctCloseTime);
void setAccepted();
void setImmutable() { updateHash(); mImmutable = true; }
bool isClosed() { return mClosed; }
bool isAccepted() { return mAccepted; }
@@ -109,7 +119,8 @@ public:
void bumpSeq() { mClosed = true; mLedgerSeq++; }
// ledger signature operations
void addRaw(Serializer &s);
void addRaw(Serializer &s) const;
void setRaw(const Serializer& s);
uint256 getHash();
const uint256& getParentHash() const { return mParentHash; }
@@ -117,15 +128,14 @@ public:
const uint256& getAccountHash() const { return mAccountHash; }
uint64 getTotalCoins() const { return mTotCoins; }
void destroyCoins(uint64 fee) { mTotCoins -= fee; }
uint64 getCloseTimeNC() const { return mCloseTime; }
uint64 getParentCloseTimeNC() const { return mParentCloseTime; }
uint32 getCloseTimeNC() const { return mCloseTime; }
uint32 getParentCloseTimeNC() const { return mParentCloseTime; }
uint32 getLedgerSeq() const { return mLedgerSeq; }
// close time functions
void setCloseTime(uint64 ct) { assert(!mImmutable); mCloseTime = ct; }
void setCloseTime(uint32 ct) { assert(!mImmutable); mCloseTime = ct; }
void setCloseTime(boost::posix_time::ptime);
boost::posix_time::ptime getCloseTime() const;
uint64 getNextLedgerClose(int prevCloseSeconds) const;
// low level functions
SHAMap::pointer peekTransactionMap() { return mTransactionMap; }