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"
|
#include "types.h"
|
||||||
|
|
||||||
// TXN
|
// TXN - Hash of transaction plus signature to give transaction ID
|
||||||
const uint32 sHP_TransactionID = 0x54584E00;
|
const uint32 sHP_TransactionID = 0x54584E00;
|
||||||
|
|
||||||
// STX
|
// STX - Hash of inner transaction to sign
|
||||||
const uint32 sHP_TransactionSign = 0x53545800;
|
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;
|
const uint32 sHP_LeafNode = 0x4D4C4E00;
|
||||||
|
|
||||||
// MIN
|
// MIN - Hash of inner node in tree
|
||||||
const uint32 sHP_InnerNode = 0x4D494E00;
|
const uint32 sHP_InnerNode = 0x4D494E00;
|
||||||
|
|
||||||
// LGR
|
// LGR - Hash of ledger master data for signing
|
||||||
const uint32 sHP_Ledger = 0x4C575200;
|
const uint32 sHP_Ledger = 0x4C575200;
|
||||||
|
|
||||||
// VAL
|
// VAL - Hash of validation for signing
|
||||||
const uint32 sHP_Validation = 0x56414C00;
|
const uint32 sHP_Validation = 0x56414C00;
|
||||||
|
|
||||||
// PRP
|
// PRP - Hash of proposal for signing
|
||||||
const uint32 sHP_Proposal = 0x50525000;
|
const uint32 sHP_Proposal = 0x50525000;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -186,14 +186,16 @@ bool Ledger::addTransaction(Transaction::pointer trans)
|
|||||||
Serializer s;
|
Serializer s;
|
||||||
trans->getSTransaction()->add(s);
|
trans->getSTransaction()->add(s);
|
||||||
SHAMapItem::pointer item = boost::make_shared<SHAMapItem>(trans->getID(), s.peekData());
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Ledger::addTransaction(const uint256& txID, const Serializer& txn)
|
bool Ledger::addTransaction(const uint256& txID, const Serializer& txn)
|
||||||
{ // low-level - just add to table
|
{ // low-level - just add to table
|
||||||
SHAMapItem::pointer item = boost::make_shared<SHAMapItem>(txID, txn.peekData());
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ LedgerStateParms Ledger::writeBack(LedgerStateParms parms, SLE::pointer entry)
|
|||||||
if (create)
|
if (create)
|
||||||
{
|
{
|
||||||
assert(!mAccountStateMap->hasItem(entry->getIndex()));
|
assert(!mAccountStateMap->hasItem(entry->getIndex()));
|
||||||
if(!mAccountStateMap->addGiveItem(item, false))
|
if(!mAccountStateMap->addGiveItem(item, false, false)) // FIXME: TX metadata
|
||||||
{
|
{
|
||||||
assert(false);
|
assert(false);
|
||||||
return lepERROR;
|
return lepERROR;
|
||||||
@@ -35,7 +35,7 @@ LedgerStateParms Ledger::writeBack(LedgerStateParms parms, SLE::pointer entry)
|
|||||||
return lepCREATED;
|
return lepCREATED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mAccountStateMap->updateGiveItem(item, false))
|
if (!mAccountStateMap->updateGiveItem(item, false, false)) // FIXME: TX metadata
|
||||||
{
|
{
|
||||||
assert(false);
|
assert(false);
|
||||||
return lepERROR;
|
return lepERROR;
|
||||||
|
|||||||
@@ -488,14 +488,15 @@ bool SHAMap::delItem(const uint256& id)
|
|||||||
return true;
|
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
|
{ // add the specified item, does not update
|
||||||
#ifdef ST_DEBUG
|
#ifdef ST_DEBUG
|
||||||
std::cerr << "aGI " << item->getTag().GetHex() << std::endl;
|
std::cerr << "aGI " << item->getTag().GetHex() << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint256 tag = item->getTag();
|
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);
|
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||||
assert(mState != Immutable);
|
assert(mState != Immutable);
|
||||||
@@ -580,12 +581,12 @@ bool SHAMap::addGiveItem(SHAMapItem::pointer item, bool isTransaction)
|
|||||||
return true;
|
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
|
{ // can't change the tag but can change the hash
|
||||||
uint256 tag = item->getTag();
|
uint256 tag = item->getTag();
|
||||||
|
|
||||||
@@ -605,7 +606,8 @@ bool SHAMap::updateGiveItem(SHAMapItem::pointer item, bool isTransaction)
|
|||||||
}
|
}
|
||||||
|
|
||||||
returnNode(node, true);
|
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";
|
Log(lsWARNING) << "SHAMap setItem, no change";
|
||||||
return true;
|
return true;
|
||||||
@@ -747,8 +749,8 @@ BOOST_AUTO_TEST_CASE( SHAMap_test )
|
|||||||
SHAMap sMap;
|
SHAMap sMap;
|
||||||
SHAMapItem i1(h1, IntToVUC(1)), i2(h2, IntToVUC(2)), i3(h3, IntToVUC(3)), i4(h4, IntToVUC(4)), i5(h5, IntToVUC(5));
|
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(i2, true, false)) BOOST_FAIL("no add");
|
||||||
if(!sMap.addItem(i1, true)) BOOST_FAIL("no add");
|
if(!sMap.addItem(i1, true, false)) BOOST_FAIL("no add");
|
||||||
|
|
||||||
SHAMapItem::pointer i;
|
SHAMapItem::pointer i;
|
||||||
|
|
||||||
@@ -759,9 +761,9 @@ BOOST_AUTO_TEST_CASE( SHAMap_test )
|
|||||||
i = sMap.peekNextItem(i->getTag());
|
i = sMap.peekNextItem(i->getTag());
|
||||||
if (i) BOOST_FAIL("bad traverse");
|
if (i) BOOST_FAIL("bad traverse");
|
||||||
|
|
||||||
sMap.addItem(i4, true);
|
sMap.addItem(i4, true, false);
|
||||||
sMap.delItem(i2.getTag());
|
sMap.delItem(i2.getTag());
|
||||||
sMap.addItem(i3, true);
|
sMap.addItem(i3, true, false);
|
||||||
|
|
||||||
i = sMap.peekFirstItem();
|
i = sMap.peekFirstItem();
|
||||||
if (!i || (*i != i1)) BOOST_FAIL("bad traverse");
|
if (!i || (*i != i1)) BOOST_FAIL("bad traverse");
|
||||||
|
|||||||
21
src/SHAMap.h
21
src/SHAMap.h
@@ -135,8 +135,9 @@ public:
|
|||||||
{
|
{
|
||||||
tnERROR = 0,
|
tnERROR = 0,
|
||||||
tnINNER = 1,
|
tnINNER = 1,
|
||||||
tnTRANSACTION = 2,
|
tnTRANSACTION_NM = 2, // transaction, no metadata
|
||||||
tnACCOUNT_STATE = 3
|
tnTRANSACTION_MD = 3, // transaction, with metadata
|
||||||
|
tnACCOUNT_STATE = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -173,11 +174,13 @@ public:
|
|||||||
TNType getType() const { return mType; }
|
TNType getType() const { return mType; }
|
||||||
|
|
||||||
// type functions
|
// 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 isInner() const { return mType == tnINNER; }
|
||||||
bool isValid() const { return mType != tnERROR; }
|
bool isValid() const { return mType != tnERROR; }
|
||||||
bool isTransaction() const { return mType != tnTRANSACTION; }
|
bool isTransaction() const { return (mType == tnTRANSACTION_NM) || (mType == tnTRANSACTION_MD); }
|
||||||
bool isAccountState() const { return mType != tnACCOUNT_STATE; }
|
bool hasMetaData() const { return mType == tnTRANSACTION_MD; }
|
||||||
|
bool isAccountState() const { return mType == tnACCOUNT_STATE; }
|
||||||
|
|
||||||
// inner node functions
|
// inner node functions
|
||||||
bool isInnerNode() const { return !mItem; }
|
bool isInnerNode() const { return !mItem; }
|
||||||
@@ -299,15 +302,15 @@ public:
|
|||||||
// normal hash access functions
|
// normal hash access functions
|
||||||
bool hasItem(const uint256& id);
|
bool hasItem(const uint256& id);
|
||||||
bool delItem(const uint256& id);
|
bool delItem(const uint256& id);
|
||||||
bool addItem(const SHAMapItem& i, bool isTransaction);
|
bool addItem(const SHAMapItem& i, bool isTransaction, bool hasMeta);
|
||||||
bool updateItem(const SHAMapItem& i, bool isTransaction);
|
bool updateItem(const SHAMapItem& i, bool isTransaction, bool hasMeta);
|
||||||
SHAMapItem getItem(const uint256& id);
|
SHAMapItem getItem(const uint256& id);
|
||||||
uint256 getHash() const { return root->getNodeHash(); }
|
uint256 getHash() const { return root->getNodeHash(); }
|
||||||
uint256 getHash() { return root->getNodeHash(); }
|
uint256 getHash() { return root->getNodeHash(); }
|
||||||
|
|
||||||
// save a copy if you have a temporary anyway
|
// save a copy if you have a temporary anyway
|
||||||
bool updateGiveItem(SHAMapItem::pointer, bool isTransaction);
|
bool updateGiveItem(SHAMapItem::pointer, bool isTransaction, bool hasMeta);
|
||||||
bool addGiveItem(SHAMapItem::pointer, bool isTransaction);
|
bool addGiveItem(SHAMapItem::pointer, bool isTransaction, bool hasMeta);
|
||||||
|
|
||||||
// save a copy if you only need a temporary
|
// save a copy if you only need a temporary
|
||||||
SHAMapItem::pointer peekItem(const uint256& id);
|
SHAMapItem::pointer peekItem(const uint256& id);
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& id, const std::vector<unsigned
|
|||||||
Serializer s(rawNode);
|
Serializer s(rawNode);
|
||||||
int type = s.removeLastByte();
|
int type = s.removeLastByte();
|
||||||
int len = s.getLength();
|
int len = s.getLength();
|
||||||
if ((type < 0) || (type > 3))
|
if ((type < 0) || (type > 4))
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
std::cerr << "Invalid wire format node" << std::endl;
|
std::cerr << "Invalid wire format node" << std::endl;
|
||||||
@@ -210,7 +210,7 @@ SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& id, const std::vector<unsigned
|
|||||||
if (type == 0)
|
if (type == 0)
|
||||||
{ // transaction
|
{ // transaction
|
||||||
mItem = boost::make_shared<SHAMapItem>(s.getPrefixHash(sHP_TransactionID), s.peekData());
|
mItem = boost::make_shared<SHAMapItem>(s.getPrefixHash(sHP_TransactionID), s.peekData());
|
||||||
mType = tnTRANSACTION;
|
mType = tnTRANSACTION_NM;
|
||||||
}
|
}
|
||||||
else if (type == 1)
|
else if (type == 1)
|
||||||
{ // account state
|
{ // account state
|
||||||
@@ -242,6 +242,11 @@ SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& id, const std::vector<unsigned
|
|||||||
}
|
}
|
||||||
mType = tnINNER;
|
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)
|
if (format == STN_ARF_PREFIXED)
|
||||||
@@ -259,7 +264,7 @@ SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& id, const std::vector<unsigned
|
|||||||
if (prefix == sHP_TransactionID)
|
if (prefix == sHP_TransactionID)
|
||||||
{
|
{
|
||||||
mItem = boost::make_shared<SHAMapItem>(s.getSHA512Half(), s.peekData());
|
mItem = boost::make_shared<SHAMapItem>(s.getSHA512Half(), s.peekData());
|
||||||
mType = tnTRANSACTION;
|
mType = tnTRANSACTION_NM;
|
||||||
}
|
}
|
||||||
else if (prefix == sHP_LeafNode)
|
else if (prefix == sHP_LeafNode)
|
||||||
{
|
{
|
||||||
@@ -282,6 +287,11 @@ SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& id, const std::vector<unsigned
|
|||||||
s.get256(mHashes[i] , i * 32);
|
s.get256(mHashes[i] , i * 32);
|
||||||
mType = tnINNER;
|
mType = tnINNER;
|
||||||
}
|
}
|
||||||
|
else if (prefix == sHP_TransactionNode)
|
||||||
|
{
|
||||||
|
mItem = boost::make_shared<SHAMapItem>(s.getPrefixHash(sHP_TransactionNode), s.peekData());
|
||||||
|
mType = tnTRANSACTION_MD;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log(lsINFO) << "Unknown node prefix " << std::hex << prefix << std::dec;
|
Log(lsINFO) << "Unknown node prefix " << std::hex << prefix << std::dec;
|
||||||
@@ -316,10 +326,14 @@ bool SHAMapTreeNode::updateHash()
|
|||||||
s.add256(mItem->getTag());
|
s.add256(mItem->getTag());
|
||||||
nh = s.getSHA512Half();
|
nh = s.getSHA512Half();
|
||||||
}
|
}
|
||||||
else if (mType == tnTRANSACTION)
|
else if (mType == tnTRANSACTION_NM)
|
||||||
{
|
{
|
||||||
nh = Serializer::getPrefixHash(sHP_TransactionID, mItem->peekData());
|
nh = Serializer::getPrefixHash(sHP_TransactionID, mItem->peekData());
|
||||||
}
|
}
|
||||||
|
else if (mType == tnTRANSACTION_MD)
|
||||||
|
{
|
||||||
|
nh = Serializer::getPrefixHash(sHP_TransactionNode, mItem->peekData());
|
||||||
|
}
|
||||||
else assert(false);
|
else assert(false);
|
||||||
|
|
||||||
if (nh == mHash) return false;
|
if (nh == mHash) return false;
|
||||||
@@ -375,7 +389,7 @@ void SHAMapTreeNode::addRaw(Serializer& s, int format)
|
|||||||
s.add8(1);
|
s.add8(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mType == tnTRANSACTION)
|
else if (mType == tnTRANSACTION_NM)
|
||||||
{
|
{
|
||||||
if (format == STN_ARF_PREFIXED)
|
if (format == STN_ARF_PREFIXED)
|
||||||
{
|
{
|
||||||
@@ -388,6 +402,19 @@ void SHAMapTreeNode::addRaw(Serializer& s, int format)
|
|||||||
s.add8(0);
|
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);
|
else assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -362,7 +362,7 @@ static bool confuseMap(SHAMap &map, int count)
|
|||||||
{
|
{
|
||||||
SHAMapItem::pointer item = makeRandomAS();
|
SHAMapItem::pointer item = makeRandomAS();
|
||||||
items.push_back(item->getTag());
|
items.push_back(item->getTag());
|
||||||
if (!map.addItem(*item, false))
|
if (!map.addItem(*item, false, false))
|
||||||
{
|
{
|
||||||
Log(lsFATAL) << "Unable to add item to map";
|
Log(lsFATAL) << "Unable to add item to map";
|
||||||
return false;
|
return false;
|
||||||
@@ -423,7 +423,7 @@ BOOST_AUTO_TEST_CASE( SHAMapSync_test )
|
|||||||
Log(lsTRACE) << "Adding random data";
|
Log(lsTRACE) << "Adding random data";
|
||||||
int items = 10000;
|
int items = 10000;
|
||||||
for (int i = 0; i < items; ++i)
|
for (int i = 0; i < items; ++i)
|
||||||
source.addItem(*makeRandomAS(), false);
|
source.addItem(*makeRandomAS(), false, false);
|
||||||
|
|
||||||
Log(lsTRACE) << "Adding items, then removing them";
|
Log(lsTRACE) << "Adding items, then removing them";
|
||||||
if (!confuseMap(source, 500)) BOOST_FAIL("ConfuseMap");
|
if (!confuseMap(source, 500)) BOOST_FAIL("ConfuseMap");
|
||||||
|
|||||||
Reference in New Issue
Block a user