Low-level support for transaction metadata.

This commit is contained in:
JoelKatz
2012-07-05 18:27:40 -07:00
parent 3c91b36684
commit 00ab5ed0cf
7 changed files with 78 additions and 41 deletions

View File

@@ -3,25 +3,28 @@
#include "types.h"
// TXN
// TXN - Hash of transaction plus signature to give transaction ID
const uint32 sHP_TransactionID = 0x54584E00;
// STX
// STX - Hash of inner transaction to sign
const uint32 sHP_TransactionSign = 0x53545800;
// MLN
// TND - Hash of transaction plus metadata
const uint32 sHP_TransactionNode = 0x534E4400;
// MLN - Hash of account state
const uint32 sHP_LeafNode = 0x4D4C4E00;
// MIN
// MIN - Hash of inner node in tree
const uint32 sHP_InnerNode = 0x4D494E00;
// LGR
// LGR - Hash of ledger master data for signing
const uint32 sHP_Ledger = 0x4C575200;
// VAL
// VAL - Hash of validation for signing
const uint32 sHP_Validation = 0x56414C00;
// PRP
// PRP - Hash of proposal for signing
const uint32 sHP_Proposal = 0x50525000;
#endif

View File

@@ -186,14 +186,16 @@ bool Ledger::addTransaction(Transaction::pointer trans)
Serializer s;
trans->getSTransaction()->add(s);
SHAMapItem::pointer item = boost::make_shared<SHAMapItem>(trans->getID(), s.peekData());
if (!mTransactionMap->addGiveItem(item, true)) return false;
if (!mTransactionMap->addGiveItem(item, true, false)) // FIXME: TX metadata
return false;
return true;
}
bool Ledger::addTransaction(const uint256& txID, const Serializer& txn)
{ // low-level - just add to table
SHAMapItem::pointer item = boost::make_shared<SHAMapItem>(txID, txn.peekData());
if (!mTransactionMap->addGiveItem(item, true)) return false;
if (!mTransactionMap->addGiveItem(item, true, false)) // FIXME: TX metadata
return false;
return true;
}

View File

@@ -27,7 +27,7 @@ LedgerStateParms Ledger::writeBack(LedgerStateParms parms, SLE::pointer entry)
if (create)
{
assert(!mAccountStateMap->hasItem(entry->getIndex()));
if(!mAccountStateMap->addGiveItem(item, false))
if(!mAccountStateMap->addGiveItem(item, false, false)) // FIXME: TX metadata
{
assert(false);
return lepERROR;
@@ -35,7 +35,7 @@ LedgerStateParms Ledger::writeBack(LedgerStateParms parms, SLE::pointer entry)
return lepCREATED;
}
if (!mAccountStateMap->updateGiveItem(item, false))
if (!mAccountStateMap->updateGiveItem(item, false, false)) // FIXME: TX metadata
{
assert(false);
return lepERROR;

View File

@@ -488,14 +488,15 @@ bool SHAMap::delItem(const uint256& id)
return true;
}
bool SHAMap::addGiveItem(SHAMapItem::pointer item, bool isTransaction)
bool SHAMap::addGiveItem(SHAMapItem::pointer item, bool isTransaction, bool hasMeta)
{ // add the specified item, does not update
#ifdef ST_DEBUG
std::cerr << "aGI " << item->getTag().GetHex() << std::endl;
#endif
uint256 tag = item->getTag();
SHAMapTreeNode::TNType type = isTransaction ? SHAMapTreeNode::tnTRANSACTION : SHAMapTreeNode::tnACCOUNT_STATE;
SHAMapTreeNode::TNType type = !isTransaction ? SHAMapTreeNode::tnACCOUNT_STATE :
(hasMeta ? SHAMapTreeNode::tnTRANSACTION_MD : SHAMapTreeNode::tnTRANSACTION_NM);
boost::recursive_mutex::scoped_lock sl(mLock);
assert(mState != Immutable);
@@ -580,12 +581,12 @@ bool SHAMap::addGiveItem(SHAMapItem::pointer item, bool isTransaction)
return true;
}
bool SHAMap::addItem(const SHAMapItem& i, bool isTransaction)
bool SHAMap::addItem(const SHAMapItem& i, bool isTransaction, bool hasMetaData)
{
return addGiveItem(boost::make_shared<SHAMapItem>(i), isTransaction);
return addGiveItem(boost::make_shared<SHAMapItem>(i), isTransaction, hasMetaData);
}
bool SHAMap::updateGiveItem(SHAMapItem::pointer item, bool isTransaction)
bool SHAMap::updateGiveItem(SHAMapItem::pointer item, bool isTransaction, bool hasMeta)
{ // can't change the tag but can change the hash
uint256 tag = item->getTag();
@@ -605,7 +606,8 @@ bool SHAMap::updateGiveItem(SHAMapItem::pointer item, bool isTransaction)
}
returnNode(node, true);
if (!node->setItem(item, isTransaction ? SHAMapTreeNode::tnTRANSACTION : SHAMapTreeNode::tnACCOUNT_STATE))
if (!node->setItem(item, !isTransaction ? SHAMapTreeNode::tnACCOUNT_STATE :
(hasMeta ? SHAMapTreeNode::tnTRANSACTION_MD : SHAMapTreeNode::tnTRANSACTION_NM)))
{
Log(lsWARNING) << "SHAMap setItem, no change";
return true;
@@ -747,8 +749,8 @@ BOOST_AUTO_TEST_CASE( SHAMap_test )
SHAMap sMap;
SHAMapItem i1(h1, IntToVUC(1)), i2(h2, IntToVUC(2)), i3(h3, IntToVUC(3)), i4(h4, IntToVUC(4)), i5(h5, IntToVUC(5));
if(!sMap.addItem(i2, true)) BOOST_FAIL("no add");
if(!sMap.addItem(i1, true)) BOOST_FAIL("no add");
if(!sMap.addItem(i2, true, false)) BOOST_FAIL("no add");
if(!sMap.addItem(i1, true, false)) BOOST_FAIL("no add");
SHAMapItem::pointer i;
@@ -759,9 +761,9 @@ BOOST_AUTO_TEST_CASE( SHAMap_test )
i = sMap.peekNextItem(i->getTag());
if (i) BOOST_FAIL("bad traverse");
sMap.addItem(i4, true);
sMap.addItem(i4, true, false);
sMap.delItem(i2.getTag());
sMap.addItem(i3, true);
sMap.addItem(i3, true, false);
i = sMap.peekFirstItem();
if (!i || (*i != i1)) BOOST_FAIL("bad traverse");

View File

@@ -61,7 +61,7 @@ public:
bool operator!=(const uint256&) const;
bool operator<=(const SHAMapNode&) const;
bool operator>=(const SHAMapNode&) const;
bool isRoot() const { return mDepth==0; }
bool isRoot() const { return mDepth == 0; }
virtual std::string getString() const;
void dump() const;
@@ -133,10 +133,11 @@ public:
enum TNType
{
tnERROR = 0,
tnINNER = 1,
tnTRANSACTION = 2,
tnACCOUNT_STATE = 3
tnERROR = 0,
tnINNER = 1,
tnTRANSACTION_NM = 2, // transaction, no metadata
tnTRANSACTION_MD = 3, // transaction, with metadata
tnACCOUNT_STATE = 4
};
private:
@@ -173,11 +174,13 @@ public:
TNType getType() const { return mType; }
// type functions
bool isLeaf() const { return (mType == tnTRANSACTION) || (mType == tnACCOUNT_STATE); }
bool isLeaf() const { return (mType == tnTRANSACTION_NM) || (mType == tnTRANSACTION_MD) ||
(mType == tnACCOUNT_STATE); }
bool isInner() const { return mType == tnINNER; }
bool isValid() const { return mType != tnERROR; }
bool isTransaction() const { return mType != tnTRANSACTION; }
bool isAccountState() const { return mType != tnACCOUNT_STATE; }
bool isTransaction() const { return (mType == tnTRANSACTION_NM) || (mType == tnTRANSACTION_MD); }
bool hasMetaData() const { return mType == tnTRANSACTION_MD; }
bool isAccountState() const { return mType == tnACCOUNT_STATE; }
// inner node functions
bool isInnerNode() const { return !mItem; }
@@ -299,15 +302,15 @@ public:
// normal hash access functions
bool hasItem(const uint256& id);
bool delItem(const uint256& id);
bool addItem(const SHAMapItem& i, bool isTransaction);
bool updateItem(const SHAMapItem& i, bool isTransaction);
bool addItem(const SHAMapItem& i, bool isTransaction, bool hasMeta);
bool updateItem(const SHAMapItem& i, bool isTransaction, bool hasMeta);
SHAMapItem getItem(const uint256& id);
uint256 getHash() const { return root->getNodeHash(); }
uint256 getHash() { return root->getNodeHash(); }
// save a copy if you have a temporary anyway
bool updateGiveItem(SHAMapItem::pointer, bool isTransaction);
bool addGiveItem(SHAMapItem::pointer, bool isTransaction);
bool updateGiveItem(SHAMapItem::pointer, bool isTransaction, bool hasMeta);
bool addGiveItem(SHAMapItem::pointer, bool isTransaction, bool hasMeta);
// save a copy if you only need a temporary
SHAMapItem::pointer peekItem(const uint256& id);

View File

@@ -197,7 +197,7 @@ SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& id, const std::vector<unsigned
Serializer s(rawNode);
int type = s.removeLastByte();
int len = s.getLength();
if ((type < 0) || (type > 3))
if ((type < 0) || (type > 4))
{
#ifdef DEBUG
std::cerr << "Invalid wire format node" << std::endl;
@@ -210,7 +210,7 @@ SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& id, const std::vector<unsigned
if (type == 0)
{ // transaction
mItem = boost::make_shared<SHAMapItem>(s.getPrefixHash(sHP_TransactionID), s.peekData());
mType = tnTRANSACTION;
mType = tnTRANSACTION_NM;
}
else if (type == 1)
{ // account state
@@ -242,6 +242,11 @@ SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& id, const std::vector<unsigned
}
mType = tnINNER;
}
else if (type == 4)
{ // transaction with metadata
mItem = boost::make_shared<SHAMapItem>(s.getPrefixHash(sHP_TransactionNode), s.peekData());
mType = tnTRANSACTION_MD;
}
}
if (format == STN_ARF_PREFIXED)
@@ -259,7 +264,7 @@ SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& id, const std::vector<unsigned
if (prefix == sHP_TransactionID)
{
mItem = boost::make_shared<SHAMapItem>(s.getSHA512Half(), s.peekData());
mType = tnTRANSACTION;
mType = tnTRANSACTION_NM;
}
else if (prefix == sHP_LeafNode)
{
@@ -271,7 +276,7 @@ SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& id, const std::vector<unsigned
Log(lsINFO) << "invalid PLN node";
throw std::runtime_error("invalid PLN node");
}
mItem = boost::make_shared<SHAMapItem>(u, s.peekData());
mItem = boost::make_shared<SHAMapItem>(u, s.peekData());
mType = tnACCOUNT_STATE;
}
else if (prefix == sHP_InnerNode)
@@ -282,6 +287,11 @@ SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& id, const std::vector<unsigned
s.get256(mHashes[i] , i * 32);
mType = tnINNER;
}
else if (prefix == sHP_TransactionNode)
{
mItem = boost::make_shared<SHAMapItem>(s.getPrefixHash(sHP_TransactionNode), s.peekData());
mType = tnTRANSACTION_MD;
}
else
{
Log(lsINFO) << "Unknown node prefix " << std::hex << prefix << std::dec;
@@ -316,10 +326,14 @@ bool SHAMapTreeNode::updateHash()
s.add256(mItem->getTag());
nh = s.getSHA512Half();
}
else if (mType == tnTRANSACTION)
else if (mType == tnTRANSACTION_NM)
{
nh = Serializer::getPrefixHash(sHP_TransactionID, mItem->peekData());
}
else if (mType == tnTRANSACTION_MD)
{
nh = Serializer::getPrefixHash(sHP_TransactionNode, mItem->peekData());
}
else assert(false);
if (nh == mHash) return false;
@@ -375,7 +389,7 @@ void SHAMapTreeNode::addRaw(Serializer& s, int format)
s.add8(1);
}
}
else if (mType == tnTRANSACTION)
else if (mType == tnTRANSACTION_NM)
{
if (format == STN_ARF_PREFIXED)
{
@@ -388,6 +402,19 @@ void SHAMapTreeNode::addRaw(Serializer& s, int format)
s.add8(0);
}
}
else if (mType == tnTRANSACTION_MD)
{
if (format == STN_ARF_PREFIXED)
{
s.add32(sHP_TransactionNode);
mItem->addRaw(s);
}
else
{
mItem->addRaw(s);
s.add8(4);
}
}
else assert(false);
}

View File

@@ -362,7 +362,7 @@ static bool confuseMap(SHAMap &map, int count)
{
SHAMapItem::pointer item = makeRandomAS();
items.push_back(item->getTag());
if (!map.addItem(*item, false))
if (!map.addItem(*item, false, false))
{
Log(lsFATAL) << "Unable to add item to map";
return false;
@@ -423,7 +423,7 @@ BOOST_AUTO_TEST_CASE( SHAMapSync_test )
Log(lsTRACE) << "Adding random data";
int items = 10000;
for (int i = 0; i < items; ++i)
source.addItem(*makeRandomAS(), false);
source.addItem(*makeRandomAS(), false, false);
Log(lsTRACE) << "Adding items, then removing them";
if (!confuseMap(source, 500)) BOOST_FAIL("ConfuseMap");