mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Low-level support for transaction metadata.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
21
src/SHAMap.h
21
src/SHAMap.h
@@ -135,8 +135,9 @@ public:
|
||||
{
|
||||
tnERROR = 0,
|
||||
tnINNER = 1,
|
||||
tnTRANSACTION = 2,
|
||||
tnACCOUNT_STATE = 3
|
||||
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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user