SerializedTransaction::pointer TransactionMaster::fetch (SHAMapItem::ref item, SHAMapTreeNode::TNType type, bool checkDisk, uint32 uCommitLedger) { SerializedTransaction::pointer txn; Transaction::pointer iTx = getApp().getMasterTransaction ().fetch (item->getTag (), false); if (!iTx) { if (type == SHAMapTreeNode::tnTRANSACTION_NM) { SerializerIterator sit (item->peekSerializer ()); txn = boost::make_shared<SerializedTransaction> (boost::ref (sit)); } else if (type == SHAMapTreeNode::tnTRANSACTION_MD) { Serializer s; int length; item->peekSerializer ().getVL (s.modData (), 0, length); SerializerIterator sit (s); txn = boost::make_shared<SerializedTransaction> (boost::ref (sit)); } } else { if (uCommitLedger) iTx->setStatus (COMMITTED, uCommitLedger); txn = iTx->getSTransaction (); } return txn; }
sttx::pointer transactionmaster::fetch (shamapitem::ref item, shamaptreenode::tntype type, bool checkdisk, std::uint32_t ucommitledger) { sttx::pointer txn; transaction::pointer itx = getapp().getmastertransaction ().fetch (item->gettag (), false); if (!itx) { if (type == shamaptreenode::tntransaction_nm) { serializeriterator sit (item->peekserializer ()); txn = std::make_shared<sttx> (std::ref (sit)); } else if (type == shamaptreenode::tntransaction_md) { serializer s; int length; item->peekserializer ().getvl (s.moddata (), 0, length); serializeriterator sit (s); txn = std::make_shared<sttx> (std::ref (sit)); } } else { if (ucommitledger) itx->setstatus (committed, ucommitledger); txn = itx->getstransaction (); } return txn; }
bool Transaction::convertToTransactions (uint32 firstLedgerSeq, uint32 secondLedgerSeq, bool checkFirstTransactions, bool checkSecondTransactions, const SHAMap::Delta& inMap, std::map<uint256, std::pair<Transaction::pointer, Transaction::pointer> >& outMap) { // convert a straight SHAMap payload difference to a transaction difference table // return value: true=ledgers are valid, false=a ledger is invalid SHAMap::Delta::const_iterator it; for (it = inMap.begin (); it != inMap.end (); ++it) { uint256 const& id = it->first; SHAMapItem::ref first = it->second.first; SHAMapItem::ref second = it->second.second; Transaction::pointer firstTrans, secondTrans; if (!!first) { // transaction in our table firstTrans = sharedTransaction (first->peekData (), checkFirstTransactions); if ((firstTrans->getStatus () == INVALID) || (firstTrans->getID () != id )) { firstTrans->setStatus (INVALID, firstLedgerSeq); return false; } else firstTrans->setStatus (INCLUDED, firstLedgerSeq); } if (!!second) { // transaction in other table secondTrans = sharedTransaction (second->peekData (), checkSecondTransactions); if ((secondTrans->getStatus () == INVALID) || (secondTrans->getID () != id)) { secondTrans->setStatus (INVALID, secondLedgerSeq); return false; } else secondTrans->setStatus (INCLUDED, secondLedgerSeq); } assert (firstTrans || secondTrans); if (firstTrans && secondTrans && (firstTrans->getStatus () != INVALID) && (secondTrans->getStatus () != INVALID)) return false; // one or the other SHAMap is structurally invalid or a miracle has happened outMap[id] = std::pair<Transaction::pointer, Transaction::pointer> (firstTrans, secondTrans); } return true; }
static void addLeaf (std::vector <uint256> &vec, SHAMapItem::ref item) { vec.push_back (item->getTag ()); }
SHAMapTreeNode::SHAMapTreeNode (const SHAMapNode& node, SHAMapItem::ref item, TNType type, uint32 seq) : SHAMapNode (node), mItem (item), mSeq (seq), mType (type), mIsBranch (0), mFullBelow (false) { assert (item->peekData ().size () >= 12); updateHash (); }
bool shamap::walkbranch (shamaptreenode* node, shamapitem::ref othermapitem, bool isfirstmap, delta& differences, int& maxcount) { // walk a branch of a shamap that's matched by an empty branch or single item in the other map std::stack <shamaptreenode*, std::vector<shamaptreenode*>> nodestack; nodestack.push ({node}); bool emptybranch = !othermapitem; while (!nodestack.empty ()) { node = nodestack.top (); nodestack.pop (); if (node->isinner ()) { // this is an inner node, add all non-empty branches for (int i = 0; i < 16; ++i) if (!node->isemptybranch (i)) nodestack.push ({descendthrow (node, i)}); } else { // this is a leaf node, process its item shamapitem::pointer item = node->peekitem (); if (emptybranch || (item->gettag () != othermapitem->gettag ())) { // unmatched if (isfirstmap) differences.insert (std::make_pair (item->gettag (), deltaref (item, shamapitem::pointer ()))); else differences.insert (std::make_pair (item->gettag (), deltaref (shamapitem::pointer (), item))); if (--maxcount <= 0) return false; } else if (item->peekdata () != othermapitem->peekdata ()) { // non-matching items with same tag if (isfirstmap) differences.insert (std::make_pair (item->gettag (), deltaref (item, othermapitem))); else differences.insert (std::make_pair (item->gettag (), deltaref (othermapitem, item))); if (--maxcount <= 0) return false; emptybranch = true; } else { // exact match emptybranch = true; } } } if (!emptybranch) { // othermapitem was unmatched, must add if (isfirstmap) // this is first map, so other item is from second differences.insert (std::make_pair (othermapitem->gettag (), deltaref (shamapitem::pointer(), othermapitem))); else differences.insert (std::make_pair (othermapitem->gettag (), deltaref (othermapitem, shamapitem::pointer ()))); if (--maxcount <= 0) return false; } return true; }