mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Merge branch 'master' of github.com:jedmccaleb/NewCoin
This commit is contained in:
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "Ledger.h"
|
#include "Ledger.h"
|
||||||
|
#include "utils.h"
|
||||||
#include "../obj/src/newcoin.pb.h"
|
#include "../obj/src/newcoin.pb.h"
|
||||||
#include "PackedMessage.h"
|
#include "PackedMessage.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
@@ -50,9 +51,7 @@ Ledger::Ledger(Ledger::pointer prevLedger) : mParentHash(prevLedger->getHash()),
|
|||||||
prevLedger->setClosed();
|
prevLedger->setClosed();
|
||||||
prevLedger->updateHash();
|
prevLedger->updateHash();
|
||||||
mAccountStateMap->setSeq(mLedgerSeq);
|
mAccountStateMap->setSeq(mLedgerSeq);
|
||||||
if (prevLedger->mTimeStamp == 0)
|
mTimeStamp = prevLedger->getNextLedgerClose();
|
||||||
mTimeStamp = (theApp->getOPs().getNetworkTime() % mLedgerInterval) + mLedgerInterval;
|
|
||||||
else mTimeStamp = prevLedger->mTimeStamp + prevLedger->mLedgerInterval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ledger::Ledger(const std::vector<unsigned char>& rawLedger) : mTotCoins(0), mTimeStamp(0),
|
Ledger::Ledger(const std::vector<unsigned char>& rawLedger) : mTotCoins(0), mTimeStamp(0),
|
||||||
@@ -426,4 +425,22 @@ bool Ledger::isAcquiringAS(void)
|
|||||||
{
|
{
|
||||||
return mAccountStateMap->isSynching();
|
return mAccountStateMap->isSynching();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boost::posix_time::ptime Ledger::getCloseTime() const
|
||||||
|
{
|
||||||
|
return ptFromSeconds(mTimeStamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ledger::setCloseTime(boost::posix_time::ptime ptm)
|
||||||
|
{
|
||||||
|
mTimeStamp = iToSeconds(ptm);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 Ledger::getNextLedgerClose() const
|
||||||
|
{
|
||||||
|
if (mTimeStamp == 0)
|
||||||
|
return theApp->getOPs().getNetworkTimeNC() + 2 * mLedgerInterval - 1;
|
||||||
|
return mTimeStamp + mLedgerInterval;
|
||||||
|
}
|
||||||
|
|
||||||
// vim:ts=4
|
// vim:ts=4
|
||||||
|
|||||||
13
src/Ledger.h
13
src/Ledger.h
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <boost/enable_shared_from_this.hpp>
|
#include <boost/enable_shared_from_this.hpp>
|
||||||
|
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||||
|
|
||||||
#include "../json/value.h"
|
#include "../json/value.h"
|
||||||
|
|
||||||
@@ -56,7 +57,8 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
uint256 mHash, mParentHash, mTransHash, mAccountHash;
|
uint256 mHash, mParentHash, mTransHash, mAccountHash;
|
||||||
uint64 mTotCoins, mTimeStamp;
|
uint64 mTotCoins;
|
||||||
|
uint64 mTimeStamp; // when this ledger closes
|
||||||
uint32 mLedgerSeq;
|
uint32 mLedgerSeq;
|
||||||
uint16 mLedgerInterval;
|
uint16 mLedgerInterval;
|
||||||
bool mClosed, mValidHash, mAccepted, mImmutable;
|
bool mClosed, mValidHash, mAccepted, mImmutable;
|
||||||
@@ -81,7 +83,7 @@ protected:
|
|||||||
public:
|
public:
|
||||||
Ledger(const NewcoinAddress& masterID, uint64 startAmount); // used for the starting bootstrap ledger
|
Ledger(const NewcoinAddress& masterID, uint64 startAmount); // used for the starting bootstrap ledger
|
||||||
Ledger(const uint256 &parentHash, const uint256 &transHash, const uint256 &accountHash,
|
Ledger(const uint256 &parentHash, const uint256 &transHash, const uint256 &accountHash,
|
||||||
uint64 totCoins, uint64 timeStamp, uint32 ledgerSeq); // used for received ledgers
|
uint64 totCoins, uint64 timeStamp, uint32 ledgerSeq); // used for database ledgers
|
||||||
Ledger(const std::vector<unsigned char>& rawLedger);
|
Ledger(const std::vector<unsigned char>& rawLedger);
|
||||||
Ledger(const std::string& rawLedger);
|
Ledger(const std::string& rawLedger);
|
||||||
Ledger(Ledger::pointer previous); // ledger after this one
|
Ledger(Ledger::pointer previous); // ledger after this one
|
||||||
@@ -100,10 +102,15 @@ public:
|
|||||||
const uint256& getTransHash() const { return mTransHash; }
|
const uint256& getTransHash() const { return mTransHash; }
|
||||||
const uint256& getAccountHash() const { return mAccountHash; }
|
const uint256& getAccountHash() const { return mAccountHash; }
|
||||||
uint64 getTotalCoins() const { return mTotCoins; }
|
uint64 getTotalCoins() const { return mTotCoins; }
|
||||||
uint64 getTimeStamp() const { return mTimeStamp; }
|
uint64 getRawTimeStamp() const { return mTimeStamp; }
|
||||||
uint32 getLedgerSeq() const { return mLedgerSeq; }
|
uint32 getLedgerSeq() const { return mLedgerSeq; }
|
||||||
uint16 getInterval() const { return mLedgerInterval; }
|
uint16 getInterval() const { return mLedgerInterval; }
|
||||||
|
|
||||||
|
// close time functions
|
||||||
|
boost::posix_time::ptime getCloseTime() const;
|
||||||
|
void setCloseTime(boost::posix_time::ptime);
|
||||||
|
uint64 getNextLedgerClose() const;
|
||||||
|
|
||||||
// low level functions
|
// low level functions
|
||||||
SHAMap::pointer peekTransactionMap() { return mTransactionMap; }
|
SHAMap::pointer peekTransactionMap() { return mTransactionMap; }
|
||||||
SHAMap::pointer peekAccountStateMap() { return mAccountStateMap; }
|
SHAMap::pointer peekAccountStateMap() { return mAccountStateMap; }
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
#include <boost/unordered_map.hpp>
|
#include <boost/unordered_map.hpp>
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "Transaction.h"
|
#include "Transaction.h"
|
||||||
|
|
||||||
@@ -24,11 +25,21 @@ NetworkOPs::NetworkOPs(boost::asio::io_service& io_service) : mMode(omDISCONNECT
|
|||||||
setStateTimer(5);
|
setStateTimer(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 NetworkOPs::getNetworkTime()
|
time_t NetworkOPs::getNetworkTimeTT()
|
||||||
{
|
{
|
||||||
return time(NULL);
|
return time(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boost::posix_time::ptime NetworkOPs::getNetworkTimePT()
|
||||||
|
{
|
||||||
|
return boost::posix_time::from_time_t(getNetworkTimeTT());
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 NetworkOPs::getNetworkTimeNC()
|
||||||
|
{
|
||||||
|
return iToSeconds(getNetworkTimePT());
|
||||||
|
}
|
||||||
|
|
||||||
uint32 NetworkOPs::getCurrentLedgerID()
|
uint32 NetworkOPs::getCurrentLedgerID()
|
||||||
{
|
{
|
||||||
return theApp->getMasterLedger().getCurrentLedger()->getLedgerSeq();
|
return theApp->getMasterLedger().getCurrentLedger()->getLedgerSeq();
|
||||||
@@ -89,7 +100,7 @@ Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans,
|
|||||||
trans->getSTransaction()->getTransaction(*s, false);
|
trans->getSTransaction()->getTransaction(*s, false);
|
||||||
tx->set_rawtransaction(&s->getData().front(), s->getLength());
|
tx->set_rawtransaction(&s->getData().front(), s->getLength());
|
||||||
tx->set_status(newcoin::tsCURRENT);
|
tx->set_status(newcoin::tsCURRENT);
|
||||||
tx->set_receivetimestamp(getNetworkTime());
|
tx->set_receivetimestamp(getNetworkTimeNC());
|
||||||
tx->set_ledgerindexpossible(trans->getLedger());
|
tx->set_ledgerindexpossible(trans->getLedger());
|
||||||
|
|
||||||
PackedMessage::pointer packet(new PackedMessage(PackedMessage::MessagePointer(tx), newcoin::mtTRANSACTION));
|
PackedMessage::pointer packet(new PackedMessage(PackedMessage::MessagePointer(tx), newcoin::mtTRANSACTION));
|
||||||
@@ -280,8 +291,19 @@ void NetworkOPs::checkState()
|
|||||||
|
|
||||||
void NetworkOPs::switchLastClosedLedger(Ledger::pointer newLedger)
|
void NetworkOPs::switchLastClosedLedger(Ledger::pointer newLedger)
|
||||||
{ // set the newledger as our last closed ledger
|
{ // set the newledger as our last closed ledger
|
||||||
// FIXME: Must recover transactions
|
// FIXME: Correct logic is:
|
||||||
|
// 1) Mark this ledger closed, schedule it to be saved
|
||||||
|
// 2) Open a new subsequent ledger
|
||||||
|
// 3) Walk back the previous ledger chain from our current ledger and the new last closed ledger
|
||||||
|
// find a common previous ledger, if possible. Try to insert any transactions in our ledger
|
||||||
|
// chain into the new open ledger. Broadcast any that make it in.
|
||||||
|
|
||||||
Ledger::pointer openLedger = boost::make_shared<Ledger>(newLedger);
|
Ledger::pointer openLedger = boost::make_shared<Ledger>(newLedger);
|
||||||
theApp->getMasterLedger().switchLedgers(newLedger, openLedger);
|
theApp->getMasterLedger().switchLedgers(newLedger, openLedger);
|
||||||
// FIXME: Set close timer
|
|
||||||
|
#if 0
|
||||||
|
if (getNetworkTime() > openLedger->getCloseTime())
|
||||||
|
{ // this ledger has already closed
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,9 @@ public:
|
|||||||
NetworkOPs(boost::asio::io_service& io_service);
|
NetworkOPs(boost::asio::io_service& io_service);
|
||||||
|
|
||||||
// network information
|
// network information
|
||||||
uint64 getNetworkTime();
|
uint64 getNetworkTimeNC();
|
||||||
|
time_t getNetworkTimeTT();
|
||||||
|
boost::posix_time::ptime getNetworkTimePT();
|
||||||
uint32 getCurrentLedgerID();
|
uint32 getCurrentLedgerID();
|
||||||
OperatingMode getOperatingMode() { return mMode; }
|
OperatingMode getOperatingMode() { return mMode; }
|
||||||
|
|
||||||
|
|||||||
@@ -774,7 +774,7 @@ void Peer::sendHello()
|
|||||||
|
|
||||||
h->set_version(theConfig.VERSION);
|
h->set_version(theConfig.VERSION);
|
||||||
h->set_ledgerindex(theApp->getOPs().getCurrentLedgerID());
|
h->set_ledgerindex(theApp->getOPs().getCurrentLedgerID());
|
||||||
h->set_nettime(theApp->getOPs().getNetworkTime());
|
h->set_nettime(theApp->getOPs().getNetworkTimeNC());
|
||||||
h->set_nodepublic(theApp->getWallet().getNodePublic().humanNodePublic());
|
h->set_nodepublic(theApp->getWallet().getNodePublic().humanNodePublic());
|
||||||
h->set_nodeproof(&vchSig[0], vchSig.size());
|
h->set_nodeproof(&vchSig[0], vchSig.size());
|
||||||
h->set_ipv4port(theConfig.PEER_PORT);
|
h->set_ipv4port(theConfig.PEER_PORT);
|
||||||
|
|||||||
140
src/SHAMap.cpp
140
src/SHAMap.cpp
@@ -11,9 +11,9 @@
|
|||||||
|
|
||||||
SHAMap::SHAMap(uint32 seq) : mSeq(seq), mState(Modifying)
|
SHAMap::SHAMap(uint32 seq) : mSeq(seq), mState(Modifying)
|
||||||
{
|
{
|
||||||
root=boost::make_shared<SHAMapTreeNode>(SHAMapNode(0, uint256()), mSeq);
|
root = boost::make_shared<SHAMapTreeNode>(SHAMapNode(0, uint256()), mSeq);
|
||||||
root->makeInner();
|
root->makeInner();
|
||||||
mTNByID[*root]=root;
|
mTNByID[*root] = root;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::stack<SHAMapTreeNode::pointer> SHAMap::getStack(const uint256& id, bool include_nonmatching_leaf)
|
std::stack<SHAMapTreeNode::pointer> SHAMap::getStack(const uint256& id, bool include_nonmatching_leaf)
|
||||||
@@ -21,27 +21,27 @@ std::stack<SHAMapTreeNode::pointer> SHAMap::getStack(const uint256& id, bool inc
|
|||||||
// Walk the tree as far as possible to the specified identifier
|
// Walk the tree as far as possible to the specified identifier
|
||||||
// produce a stack of nodes along the way, with the terminal node at the top
|
// produce a stack of nodes along the way, with the terminal node at the top
|
||||||
std::stack<SHAMapTreeNode::pointer> stack;
|
std::stack<SHAMapTreeNode::pointer> stack;
|
||||||
SHAMapTreeNode::pointer node=root;
|
SHAMapTreeNode::pointer node = root;
|
||||||
|
|
||||||
while(!node->isLeaf())
|
while (!node->isLeaf())
|
||||||
{
|
{
|
||||||
stack.push(node);
|
stack.push(node);
|
||||||
|
|
||||||
int branch=node->selectBranch(id);
|
int branch = node->selectBranch(id);
|
||||||
assert(branch>=0);
|
assert(branch >= 0);
|
||||||
|
|
||||||
uint256 hash=node->getChildHash(branch);
|
uint256 hash = node->getChildHash(branch);
|
||||||
if(hash.isZero()) return stack;
|
if (hash.isZero()) return stack;
|
||||||
|
|
||||||
node=getNode(node->getChildNodeID(branch), hash, false);
|
node = getNode(node->getChildNodeID(branch), hash, false);
|
||||||
if(!node)
|
if (!node)
|
||||||
{
|
{
|
||||||
if(isSynching()) return stack;
|
if (isSynching()) return stack;
|
||||||
throw SHAMapException(MissingNode);
|
throw SHAMapException(MissingNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(include_nonmatching_leaf || (node->peekItem()->getTag()==id))
|
if (include_nonmatching_leaf || (node->peekItem()->getTag() == id))
|
||||||
stack.push(node);
|
stack.push(node);
|
||||||
|
|
||||||
return stack;
|
return stack;
|
||||||
@@ -51,20 +51,20 @@ void SHAMap::dirtyUp(std::stack<SHAMapTreeNode::pointer>& stack, const uint256&
|
|||||||
{ // walk the tree up from through the inner nodes to the root
|
{ // walk the tree up from through the inner nodes to the root
|
||||||
// update linking hashes and add nodes to dirty list
|
// update linking hashes and add nodes to dirty list
|
||||||
|
|
||||||
assert(mState!=Synching && mState!=Immutable);
|
assert((mState != Synching) && (mState != Immutable));
|
||||||
|
|
||||||
while(!stack.empty())
|
while (!stack.empty())
|
||||||
{
|
{
|
||||||
SHAMapTreeNode::pointer node=stack.top();
|
SHAMapTreeNode::pointer node=stack.top();
|
||||||
stack.pop();
|
stack.pop();
|
||||||
assert(node->isInnerNode());
|
assert(node->isInnerNode());
|
||||||
|
|
||||||
int branch=node->selectBranch(target);
|
int branch = node->selectBranch(target);
|
||||||
assert(branch>=0);
|
assert(branch >= 0);
|
||||||
|
|
||||||
returnNode(node, true);
|
returnNode(node, true);
|
||||||
|
|
||||||
if(!node->setChildHash(branch, prevHash))
|
if (!node->setChildHash(branch, prevHash))
|
||||||
{
|
{
|
||||||
std::cerr << "dirtyUp terminates early" << std::endl;
|
std::cerr << "dirtyUp terminates early" << std::endl;
|
||||||
assert(false);
|
assert(false);
|
||||||
@@ -73,15 +73,15 @@ void SHAMap::dirtyUp(std::stack<SHAMapTreeNode::pointer>& stack, const uint256&
|
|||||||
#ifdef ST_DEBUG
|
#ifdef ST_DEBUG
|
||||||
std::cerr << "dirtyUp sets branch " << branch << " to " << prevHash.GetHex() << std::endl;
|
std::cerr << "dirtyUp sets branch " << branch << " to " << prevHash.GetHex() << std::endl;
|
||||||
#endif
|
#endif
|
||||||
prevHash=node->getNodeHash();
|
prevHash = node->getNodeHash();
|
||||||
assert(prevHash.isNonZero());
|
assert(prevHash.isNonZero());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SHAMapTreeNode::pointer SHAMap::checkCacheNode(const SHAMapNode& iNode)
|
SHAMapTreeNode::pointer SHAMap::checkCacheNode(const SHAMapNode& iNode)
|
||||||
{
|
{
|
||||||
boost::unordered_map<SHAMapNode, SHAMapTreeNode::pointer>::iterator it=mTNByID.find(iNode);
|
boost::unordered_map<SHAMapNode, SHAMapTreeNode::pointer>::iterator it = mTNByID.find(iNode);
|
||||||
if(it==mTNByID.end()) return SHAMapTreeNode::pointer();
|
if (it == mTNByID.end()) return SHAMapTreeNode::pointer();
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,27 +90,27 @@ SHAMapTreeNode::pointer SHAMap::walkTo(const uint256& id, bool modify)
|
|||||||
|
|
||||||
SHAMapTreeNode::pointer inNode=root;
|
SHAMapTreeNode::pointer inNode=root;
|
||||||
|
|
||||||
while(!inNode->isLeaf())
|
while (!inNode->isLeaf())
|
||||||
{
|
{
|
||||||
int branch=inNode->selectBranch(id);
|
int branch = inNode->selectBranch(id);
|
||||||
if(inNode->isEmptyBranch(branch)) return inNode;
|
if (inNode->isEmptyBranch(branch)) return inNode;
|
||||||
uint256 childHash=inNode->getChildHash(branch);
|
uint256 childHash = inNode->getChildHash(branch);
|
||||||
if(childHash.isZero()) return inNode;
|
if (childHash.isZero()) return inNode;
|
||||||
|
|
||||||
SHAMapTreeNode::pointer nextNode=getNode(inNode->getChildNodeID(branch), childHash, false);
|
SHAMapTreeNode::pointer nextNode = getNode(inNode->getChildNodeID(branch), childHash, false);
|
||||||
if(!nextNode) throw SHAMapException(MissingNode);
|
if (!nextNode) throw SHAMapException(MissingNode);
|
||||||
inNode=nextNode;
|
inNode = nextNode;
|
||||||
}
|
}
|
||||||
if(modify) returnNode(inNode, true);
|
if (modify) returnNode(inNode, true);
|
||||||
return inNode;
|
return inNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHAMapTreeNode::pointer SHAMap::getNode(const SHAMapNode& id, const uint256& hash, bool modify)
|
SHAMapTreeNode::pointer SHAMap::getNode(const SHAMapNode& id, const uint256& hash, bool modify)
|
||||||
{ // retrieve a node whose node hash is known
|
{ // retrieve a node whose node hash is known
|
||||||
SHAMapTreeNode::pointer node=checkCacheNode(id);
|
SHAMapTreeNode::pointer node = checkCacheNode(id);
|
||||||
if(node)
|
if (node)
|
||||||
{
|
{
|
||||||
if(node->getNodeHash()!=hash)
|
if (node->getNodeHash()!=hash)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
std::cerr << "Attempt to get node, hash not in tree" << std::endl;
|
std::cerr << "Attempt to get node, hash not in tree" << std::endl;
|
||||||
@@ -128,10 +128,10 @@ SHAMapTreeNode::pointer SHAMap::getNode(const SHAMapNode& id, const uint256& has
|
|||||||
std::vector<unsigned char> nodeData;
|
std::vector<unsigned char> nodeData;
|
||||||
if(!fetchNode(hash, nodeData)) return SHAMapTreeNode::pointer();
|
if(!fetchNode(hash, nodeData)) return SHAMapTreeNode::pointer();
|
||||||
|
|
||||||
node=boost::make_shared<SHAMapTreeNode>(id, nodeData, mSeq);
|
node = boost::make_shared<SHAMapTreeNode>(id, nodeData, mSeq);
|
||||||
if(node->getNodeHash()!=hash) throw SHAMapException(InvalidNode);
|
if (node->getNodeHash() != hash) throw SHAMapException(InvalidNode);
|
||||||
|
|
||||||
if(!mTNByID.insert(std::make_pair(id, node)).second)
|
if (!mTNByID.insert(std::make_pair(id, node)).second)
|
||||||
assert(false);
|
assert(false);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
@@ -139,15 +139,15 @@ SHAMapTreeNode::pointer SHAMap::getNode(const SHAMapNode& id, const uint256& has
|
|||||||
void SHAMap::returnNode(SHAMapTreeNode::pointer& node, bool modify)
|
void SHAMap::returnNode(SHAMapTreeNode::pointer& node, bool modify)
|
||||||
{ // make sure the node is suitable for the intended operation (copy on write)
|
{ // make sure the node is suitable for the intended operation (copy on write)
|
||||||
assert(node->isValid());
|
assert(node->isValid());
|
||||||
if(node && modify && (node->getSeq()!=mSeq))
|
if (node && modify && (node->getSeq()!=mSeq))
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
std::cerr << "returnNode COW" << std::endl;
|
std::cerr << "returnNode COW" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
if(mDirtyNodes) (*mDirtyNodes)[*node]=node;
|
if (mDirtyNodes) (*mDirtyNodes)[*node] = node;
|
||||||
node=boost::make_shared<SHAMapTreeNode>(*node, mSeq);
|
node = boost::make_shared<SHAMapTreeNode>(*node, mSeq);
|
||||||
assert(node->isValid());
|
assert(node->isValid());
|
||||||
mTNByID[*node]=node;
|
mTNByID[*node] = node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,24 +163,24 @@ SHAMapItem::pointer SHAMap::firstBelow(SHAMapTreeNode::pointer node)
|
|||||||
#endif
|
#endif
|
||||||
do
|
do
|
||||||
{ // Walk down the tree
|
{ // Walk down the tree
|
||||||
if(node->hasItem()) return node->peekItem();
|
if (node->hasItem()) return node->peekItem();
|
||||||
|
|
||||||
bool foundNode=false;
|
bool foundNode = false;
|
||||||
for(int i=0; i<16; i++)
|
for (int i = 0; i < 16; ++i)
|
||||||
if(!node->isEmptyBranch(i))
|
if (!node->isEmptyBranch(i))
|
||||||
{
|
{
|
||||||
#ifdef ST_DEBUG
|
#ifdef ST_DEBUG
|
||||||
std::cerr << " FB: node " << node->getString() << std::endl;
|
std::cerr << " FB: node " << node->getString() << std::endl;
|
||||||
std::cerr << " has non-empty branch " << i << " : " <<
|
std::cerr << " has non-empty branch " << i << " : " <<
|
||||||
node->getChildNodeID(i).getString() << ", " << node->getChildHash(i).GetHex() << std::endl;
|
node->getChildNodeID(i).getString() << ", " << node->getChildHash(i).GetHex() << std::endl;
|
||||||
#endif
|
#endif
|
||||||
node=getNode(node->getChildNodeID(i), node->getChildHash(i), false);
|
node = getNode(node->getChildNodeID(i), node->getChildHash(i), false);
|
||||||
if(!node) throw SHAMapException(MissingNode);
|
if (!node) throw SHAMapException(MissingNode);
|
||||||
foundNode=true;
|
foundNode = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!foundNode) return SHAMapItem::pointer();
|
if (!foundNode) return SHAMapItem::pointer();
|
||||||
} while(1);
|
} while (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
SHAMapItem::pointer SHAMap::lastBelow(SHAMapTreeNode::pointer node)
|
SHAMapItem::pointer SHAMap::lastBelow(SHAMapTreeNode::pointer node)
|
||||||
@@ -191,46 +191,46 @@ SHAMapItem::pointer SHAMap::lastBelow(SHAMapTreeNode::pointer node)
|
|||||||
|
|
||||||
do
|
do
|
||||||
{ // Walk down the tree
|
{ // Walk down the tree
|
||||||
if(node->hasItem()) return node->peekItem();
|
if (node->hasItem()) return node->peekItem();
|
||||||
|
|
||||||
bool foundNode=false;
|
bool foundNode = false;
|
||||||
for(int i=15; i>=0; i++)
|
for (int i = 15; i >= 0; ++i)
|
||||||
if(!node->isEmptyBranch(i))
|
if (!node->isEmptyBranch(i))
|
||||||
{
|
{
|
||||||
node=getNode(node->getChildNodeID(i), node->getChildHash(i), false);
|
node = getNode(node->getChildNodeID(i), node->getChildHash(i), false);
|
||||||
if(!node) throw SHAMapException(MissingNode);
|
if (!node) throw SHAMapException(MissingNode);
|
||||||
foundNode=true;
|
foundNode = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!foundNode) return SHAMapItem::pointer();
|
if (!foundNode) return SHAMapItem::pointer();
|
||||||
} while(1);
|
} while (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
SHAMapItem::pointer SHAMap::onlyBelow(SHAMapTreeNode::pointer node)
|
SHAMapItem::pointer SHAMap::onlyBelow(SHAMapTreeNode::pointer node)
|
||||||
{
|
{
|
||||||
// If there is only one item below this node, return it
|
// If there is only one item below this node, return it
|
||||||
bool found;
|
bool found;
|
||||||
while(!node->isLeaf())
|
while (!node->isLeaf())
|
||||||
{
|
{
|
||||||
found=false;
|
found = false;
|
||||||
SHAMapTreeNode::pointer nextNode;
|
SHAMapTreeNode::pointer nextNode;
|
||||||
|
|
||||||
for(int i=0; i<16; i++)
|
for (int i = 0; i < 16; ++i)
|
||||||
if(!node->isEmptyBranch(i))
|
if (!node->isEmptyBranch(i))
|
||||||
{
|
{
|
||||||
if(found) return SHAMapItem::pointer(); // two leaves below
|
if( found) return SHAMapItem::pointer(); // two leaves below
|
||||||
nextNode=getNode(node->getChildNodeID(i), node->getChildHash(i), false);
|
nextNode = getNode(node->getChildNodeID(i), node->getChildHash(i), false);
|
||||||
if(!nextNode) throw SHAMapException(MissingNode);
|
if (!nextNode) throw SHAMapException(MissingNode);
|
||||||
found=true;
|
found = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
std::cerr << node->getString() << std::endl;
|
std::cerr << node->getString() << std::endl;
|
||||||
assert(false);
|
assert(false);
|
||||||
return SHAMapItem::pointer();
|
return SHAMapItem::pointer();
|
||||||
}
|
}
|
||||||
node=nextNode;
|
node = nextNode;
|
||||||
}
|
}
|
||||||
assert(node->hasItem());
|
assert(node->hasItem());
|
||||||
return node->peekItem();
|
return node->peekItem();
|
||||||
@@ -618,11 +618,11 @@ void SHAMap::dump(bool hash)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<unsigned char>IntToVUC(int i)
|
static std::vector<unsigned char>IntToVUC(int v)
|
||||||
{
|
{
|
||||||
std::vector<unsigned char> vuc;
|
std::vector<unsigned char> vuc;
|
||||||
for(int i=0; i<32; i++)
|
for (int i = 0; i < 32; ++i)
|
||||||
vuc.push_back((unsigned char) i);
|
vuc.push_back(static_cast<unsigned char>(v));
|
||||||
return vuc;
|
return vuc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
38
src/SHAMap.h
38
src/SHAMap.h
@@ -40,14 +40,14 @@ public:
|
|||||||
SHAMapNode(int depth, const uint256& hash);
|
SHAMapNode(int depth, const uint256& hash);
|
||||||
int getDepth() const { return mDepth; }
|
int getDepth() const { return mDepth; }
|
||||||
const uint256& getNodeID() const { return mNodeID; }
|
const uint256& getNodeID() const { return mNodeID; }
|
||||||
bool isValid() const { return (mDepth>=0) && (mDepth<64); }
|
bool isValid() const { return (mDepth >= 0) && (mDepth < 64); }
|
||||||
|
|
||||||
virtual bool isPopulated() const { return false; }
|
virtual bool isPopulated() const { return false; }
|
||||||
|
|
||||||
SHAMapNode getParentNodeID() const
|
SHAMapNode getParentNodeID() const
|
||||||
{
|
{
|
||||||
assert(mDepth);
|
assert(mDepth);
|
||||||
return SHAMapNode(mDepth-1, mNodeID);
|
return SHAMapNode(mDepth - 1, mNodeID);
|
||||||
}
|
}
|
||||||
SHAMapNode getChildNodeID(int m) const;
|
SHAMapNode getChildNodeID(int m) const;
|
||||||
int selectBranch(const uint256& hash) const;
|
int selectBranch(const uint256& hash) const;
|
||||||
@@ -108,18 +108,18 @@ public:
|
|||||||
|
|
||||||
void updateData(const std::vector<unsigned char>& data) { mData=data; }
|
void updateData(const std::vector<unsigned char>& data) { mData=data; }
|
||||||
|
|
||||||
bool operator<(const SHAMapItem& i) const { return mTag<i.mTag; }
|
bool operator<(const SHAMapItem& i) const { return mTag < i.mTag; }
|
||||||
bool operator>(const SHAMapItem& i) const { return mTag>i.mTag; }
|
bool operator>(const SHAMapItem& i) const { return mTag > i.mTag; }
|
||||||
bool operator==(const SHAMapItem& i) const { return mTag==i.mTag; }
|
bool operator==(const SHAMapItem& i) const { return mTag == i.mTag; }
|
||||||
bool operator!=(const SHAMapItem& i) const { return mTag!=i.mTag; }
|
bool operator!=(const SHAMapItem& i) const { return mTag != i.mTag; }
|
||||||
bool operator<=(const SHAMapItem& i) const { return mTag<=i.mTag; }
|
bool operator<=(const SHAMapItem& i) const { return mTag <= i.mTag; }
|
||||||
bool operator>=(const SHAMapItem& i) const { return mTag>=i.mTag; }
|
bool operator>=(const SHAMapItem& i) const { return mTag >= i.mTag; }
|
||||||
bool operator<(const uint256& i) const { return mTag<i; }
|
bool operator<(const uint256& i) const { return mTag < i; }
|
||||||
bool operator>(const uint256& i) const { return mTag>i; }
|
bool operator>(const uint256& i) const { return mTag > i; }
|
||||||
bool operator==(const uint256& i) const { return mTag==i; }
|
bool operator==(const uint256& i) const { return mTag == i; }
|
||||||
bool operator!=(const uint256& i) const { return mTag!=i; }
|
bool operator!=(const uint256& i) const { return mTag != i; }
|
||||||
bool operator<=(const uint256& i) const { return mTag<=i; }
|
bool operator<=(const uint256& i) const { return mTag <= i; }
|
||||||
bool operator>=(const uint256& i) const { return mTag>=i; }
|
bool operator>=(const uint256& i) const { return mTag >= i; }
|
||||||
virtual void dump();
|
virtual void dump();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -132,10 +132,10 @@ public:
|
|||||||
|
|
||||||
enum TNType
|
enum TNType
|
||||||
{
|
{
|
||||||
tnERROR =0,
|
tnERROR = 0,
|
||||||
tnINNER =1,
|
tnINNER = 1,
|
||||||
tnTRANSACTION =2,
|
tnTRANSACTION = 2,
|
||||||
tnACCOUNT_STATE =3
|
tnACCOUNT_STATE = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -295,7 +295,7 @@ public:
|
|||||||
// status functions
|
// status functions
|
||||||
void setImmutable(void) { assert(mState != Invalid); mState = Immutable; }
|
void setImmutable(void) { assert(mState != Invalid); mState = Immutable; }
|
||||||
void clearImmutable(void) { mState = Modifying; }
|
void clearImmutable(void) { mState = Modifying; }
|
||||||
bool isSynching(void) const { return mState == Floating || mState == Synching; }
|
bool isSynching(void) const { return (mState == Floating) || (mState == Synching); }
|
||||||
void setSynching(void) { mState = Synching; }
|
void setSynching(void) { mState = Synching; }
|
||||||
void setFloating(void) { mState = Floating; }
|
void setFloating(void) { mState = Floating; }
|
||||||
void clearSynching(void) { mState = Modifying; }
|
void clearSynching(void) { mState = Modifying; }
|
||||||
|
|||||||
@@ -97,11 +97,11 @@ SHAMapNode::SHAMapNode(int depth, const uint256 &hash) : mDepth(depth)
|
|||||||
|
|
||||||
SHAMapNode::SHAMapNode(const void *ptr, int len)
|
SHAMapNode::SHAMapNode(const void *ptr, int len)
|
||||||
{
|
{
|
||||||
if(len<33) mDepth=-1;
|
if (len < 33) mDepth = -1;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memcpy(&mNodeID, ptr, 32);
|
memcpy(&mNodeID, ptr, 32);
|
||||||
mDepth=*(static_cast<const unsigned char *>(ptr) + 32);
|
mDepth = *(static_cast<const unsigned char *>(ptr) + 32);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,21 +120,21 @@ std::string SHAMapNode::getRawString() const
|
|||||||
|
|
||||||
SHAMapNode SHAMapNode::getChildNodeID(int m) const
|
SHAMapNode SHAMapNode::getChildNodeID(int m) const
|
||||||
{ // This can be optimized to avoid the << if needed
|
{ // This can be optimized to avoid the << if needed
|
||||||
assert((m>=0) && (m<16));
|
assert((m >= 0) && (m < 16));
|
||||||
|
|
||||||
uint256 child(mNodeID);
|
uint256 child(mNodeID);
|
||||||
child.PeekAt(mDepth/8) |= m << (4*(mDepth%8));
|
child.PeekAt(mDepth / 8) |= m << (4 * (mDepth % 8));
|
||||||
return SHAMapNode(mDepth+1, child);
|
return SHAMapNode(mDepth + 1, child);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SHAMapNode::selectBranch(const uint256& hash) const
|
int SHAMapNode::selectBranch(const uint256& hash) const
|
||||||
{ // Which branch would contain the specified hash
|
{ // Which branch would contain the specified hash
|
||||||
if(mDepth==63)
|
if (mDepth == 63)
|
||||||
{
|
{
|
||||||
assert(false);
|
assert(false);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if((hash&smMasks[mDepth])!=mNodeID)
|
if ((hash & smMasks[mDepth]) != mNodeID)
|
||||||
{
|
{
|
||||||
std::cerr << "selectBranch(" << getString() << std::endl;
|
std::cerr << "selectBranch(" << getString() << std::endl;
|
||||||
std::cerr << " " << hash.GetHex() << " off branch" << std::endl;
|
std::cerr << " " << hash.GetHex() << " off branch" << std::endl;
|
||||||
@@ -142,11 +142,11 @@ int SHAMapNode::selectBranch(const uint256& hash) const
|
|||||||
return -1; // does not go under this node
|
return -1; // does not go under this node
|
||||||
}
|
}
|
||||||
|
|
||||||
int branch=*(hash.begin()+(mDepth/2));
|
int branch = *(hash.begin() + (mDepth / 2));
|
||||||
if(mDepth%2) branch>>=4;
|
if (mDepth % 2) branch >>= 4;
|
||||||
else branch&=0xf;
|
else branch &= 0xf;
|
||||||
|
|
||||||
assert(branch>=0 && branch<16);
|
assert((branch >= 0) && (branch < 16));
|
||||||
return branch;
|
return branch;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,7 +164,7 @@ SHAMapTreeNode::SHAMapTreeNode(const SHAMapTreeNode& node, uint32 seq) : SHAMapN
|
|||||||
mHash(node.mHash), mItem(node.mItem), mSeq(seq), mType(node.mType), mFullBelow(false)
|
mHash(node.mHash), mItem(node.mItem), mSeq(seq), mType(node.mType), mFullBelow(false)
|
||||||
{
|
{
|
||||||
if(node.mItem)
|
if(node.mItem)
|
||||||
mItem=boost::make_shared<SHAMapItem>(*node.mItem);
|
mItem = boost::make_shared<SHAMapItem>(*node.mItem);
|
||||||
else
|
else
|
||||||
memcpy(mHashes, node.mHashes, sizeof(mHashes));
|
memcpy(mHashes, node.mHashes, sizeof(mHashes));
|
||||||
}
|
}
|
||||||
@@ -172,7 +172,7 @@ SHAMapTreeNode::SHAMapTreeNode(const SHAMapTreeNode& node, uint32 seq) : SHAMapN
|
|||||||
SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& node, SHAMapItem::pointer item, TNType type, uint32 seq) :
|
SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& node, SHAMapItem::pointer item, TNType type, uint32 seq) :
|
||||||
SHAMapNode(node), mItem(item), mSeq(seq), mType(type), mFullBelow(true)
|
SHAMapNode(node), mItem(item), mSeq(seq), mType(type), mFullBelow(true)
|
||||||
{
|
{
|
||||||
assert(item->peekData().size()>=12);
|
assert(item->peekData().size() >= 12);
|
||||||
updateHash();
|
updateHash();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,41 +181,41 @@ 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) || (len<32) ) throw SHAMapException(InvalidNode);
|
if ((type < 0) || (type > 3) || (len < 32)) throw SHAMapException(InvalidNode);
|
||||||
|
|
||||||
if(type==0)
|
if (type == 0)
|
||||||
{ // transaction
|
{ // transaction
|
||||||
mItem=boost::make_shared<SHAMapItem>(s.getSHA512Half(), s.peekData());
|
mItem = boost::make_shared<SHAMapItem>(s.getSHA512Half(), s.peekData());
|
||||||
mType=tnTRANSACTION;
|
mType = tnTRANSACTION;
|
||||||
}
|
}
|
||||||
else if(type==1)
|
else if (type == 1)
|
||||||
{ // account state
|
{ // account state
|
||||||
uint256 u;
|
uint256 u;
|
||||||
s.get256(u, len-32);
|
s.get256(u, len - 32);
|
||||||
s.chop(256/8);
|
s.chop(256 / 8);
|
||||||
if(u.isZero()) throw SHAMapException(InvalidNode);
|
if (u.isZero()) throw SHAMapException(InvalidNode);
|
||||||
mItem=boost::make_shared<SHAMapItem>(u, s.peekData());
|
mItem = boost::make_shared<SHAMapItem>(u, s.peekData());
|
||||||
mType=tnACCOUNT_STATE;
|
mType = tnACCOUNT_STATE;
|
||||||
}
|
}
|
||||||
else if(type==2)
|
else if (type == 2)
|
||||||
{ // full inner
|
{ // full inner
|
||||||
if(len!=512) throw SHAMapException(InvalidNode);
|
if (len != 512) throw SHAMapException(InvalidNode);
|
||||||
for(int i=0; i<16; i++)
|
for (int i = 0; i < 16; ++i)
|
||||||
s.get256(mHashes[i], i*32);
|
s.get256(mHashes[i], i * 32);
|
||||||
mType=tnINNER;
|
mType = tnINNER;
|
||||||
}
|
}
|
||||||
else if(type==3)
|
else if (type == 3)
|
||||||
{ // compressed inner
|
{ // compressed inner
|
||||||
for(int i=0; i<(len/33); i++)
|
for (int i = 0; i < (len / 33); ++i)
|
||||||
{
|
{
|
||||||
int pos;
|
int pos;
|
||||||
s.get8(pos, 32+(i*33));
|
s.get8(pos, 32 + (i * 33));
|
||||||
if( (pos<0) || (pos>=16)) throw SHAMapException(InvalidNode);
|
if ((pos < 0) || (pos >= 16)) throw SHAMapException(InvalidNode);
|
||||||
s.get256(mHashes[pos], i*33);
|
s.get256(mHashes[pos], i* 3 3);
|
||||||
}
|
}
|
||||||
mType=tnINNER;
|
mType = tnINNER;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateHash();
|
updateHash();
|
||||||
@@ -223,17 +223,17 @@ SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& id, const std::vector<unsigned
|
|||||||
|
|
||||||
void SHAMapTreeNode::addRaw(Serializer &s)
|
void SHAMapTreeNode::addRaw(Serializer &s)
|
||||||
{
|
{
|
||||||
if(mType==tnERROR) throw SHAMapException(InvalidNode);
|
if (mType == tnERROR) throw SHAMapException(InvalidNode);
|
||||||
|
|
||||||
if(mType==tnTRANSACTION)
|
if (mType == tnTRANSACTION)
|
||||||
{
|
{
|
||||||
mItem->addRaw(s);
|
mItem->addRaw(s);
|
||||||
s.add8(0);
|
s.add8(0);
|
||||||
assert(s.getLength()>32);
|
assert(s.getLength() > 32);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mType==tnACCOUNT_STATE)
|
if (mType == tnACCOUNT_STATE)
|
||||||
{
|
{
|
||||||
mItem->addRaw(s);
|
mItem->addRaw(s);
|
||||||
s.add256(mItem->getTag());
|
s.add256(mItem->getTag());
|
||||||
@@ -241,10 +241,10 @@ void SHAMapTreeNode::addRaw(Serializer &s)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(getBranchCount()<12)
|
if (getBranchCount() < 12)
|
||||||
{ // compressed node
|
{ // compressed node
|
||||||
for(int i=0; i<16; i++)
|
for (int i = 0; i < 16; ++i)
|
||||||
if(mHashes[i].isNonZero())
|
if (mHashes[i].isNonZero())
|
||||||
{
|
{
|
||||||
s.add256(mHashes[i]);
|
s.add256(mHashes[i]);
|
||||||
s.add8(i);
|
s.add8(i);
|
||||||
@@ -253,7 +253,7 @@ void SHAMapTreeNode::addRaw(Serializer &s)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i=0; i<16; i++)
|
for (int i = 0; i < 16; ++i)
|
||||||
s.add256(mHashes[i]);
|
s.add256(mHashes[i]);
|
||||||
s.add8(2);
|
s.add8(2);
|
||||||
}
|
}
|
||||||
@@ -262,44 +262,44 @@ bool SHAMapTreeNode::updateHash()
|
|||||||
{
|
{
|
||||||
uint256 nh;
|
uint256 nh;
|
||||||
|
|
||||||
if(mType==tnINNER)
|
if (mType == tnINNER)
|
||||||
{
|
{
|
||||||
bool empty=true;
|
bool empty = true;
|
||||||
for(int i=0; i<16; i++)
|
for (int i = 0; i < 16; ++i)
|
||||||
if(mHashes[i].isNonZero())
|
if (mHashes[i].isNonZero())
|
||||||
{
|
{
|
||||||
empty=false;
|
empty = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!empty)
|
if(!empty)
|
||||||
nh=Serializer::getSHA512Half(reinterpret_cast<unsigned char *>(mHashes), sizeof(mHashes));
|
nh = Serializer::getSHA512Half(reinterpret_cast<unsigned char *>(mHashes), sizeof(mHashes));
|
||||||
}
|
}
|
||||||
else if(mType==tnACCOUNT_STATE)
|
else if (mType == tnACCOUNT_STATE)
|
||||||
{
|
{
|
||||||
Serializer s;
|
Serializer s;
|
||||||
mItem->addRaw(s);
|
mItem->addRaw(s);
|
||||||
s.add160(mItem->getTag().to160());
|
s.add160(mItem->getTag().to160());
|
||||||
nh=s.getSHA512Half();
|
nh = s.getSHA512Half();
|
||||||
}
|
}
|
||||||
else if(mType==tnTRANSACTION)
|
else if (mType == tnTRANSACTION)
|
||||||
{
|
{
|
||||||
nh=Serializer::getSHA512Half(mItem->peekData());
|
nh = Serializer::getSHA512Half(mItem->peekData());
|
||||||
}
|
}
|
||||||
else assert(false);
|
else assert(false);
|
||||||
|
|
||||||
if(nh==mHash) return false;
|
if (nh == mHash) return false;
|
||||||
mHash=nh;
|
mHash = nh;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHAMapTreeNode::setItem(SHAMapItem::pointer& i, TNType type)
|
bool SHAMapTreeNode::setItem(SHAMapItem::pointer& i, TNType type)
|
||||||
{
|
{
|
||||||
uint256 hash=getNodeHash();
|
uint256 hash = getNodeHash();
|
||||||
mType=type;
|
mType = type;
|
||||||
mItem=i;
|
mItem = i;
|
||||||
assert(isLeaf());
|
assert(isLeaf());
|
||||||
updateHash();
|
updateHash();
|
||||||
return getNodeHash()==hash;
|
return getNodeHash() == hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHAMapItem::pointer SHAMapTreeNode::getItem() const
|
SHAMapItem::pointer SHAMapTreeNode::getItem() const
|
||||||
@@ -311,17 +311,17 @@ SHAMapItem::pointer SHAMapTreeNode::getItem() const
|
|||||||
int SHAMapTreeNode::getBranchCount() const
|
int SHAMapTreeNode::getBranchCount() const
|
||||||
{
|
{
|
||||||
assert(isInner());
|
assert(isInner());
|
||||||
int ret=0;
|
int ret = 0;
|
||||||
for(int i=0; i<16; ++i)
|
for (int i = 0; i < 16; ++i)
|
||||||
if(mHashes[i].isNonZero()) ++ret;
|
if (mHashes[i].isNonZero()) ++ret;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHAMapTreeNode::makeInner()
|
void SHAMapTreeNode::makeInner()
|
||||||
{
|
{
|
||||||
mItem=SHAMapItem::pointer();
|
mItem = SHAMapItem::pointer();
|
||||||
memset(mHashes, 0, sizeof(mHashes));
|
memset(mHashes, 0, sizeof(mHashes));
|
||||||
mType=tnINNER;
|
mType = tnINNER;
|
||||||
mHash.zero();
|
mHash.zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -332,40 +332,40 @@ void SHAMapTreeNode::dump()
|
|||||||
|
|
||||||
std::string SHAMapTreeNode::getString() const
|
std::string SHAMapTreeNode::getString() const
|
||||||
{
|
{
|
||||||
std::string ret="NodeID(";
|
std::string ret = "NodeID(";
|
||||||
ret+=boost::lexical_cast<std::string>(getDepth());
|
ret += boost::lexical_cast<std::string>(getDepth());
|
||||||
ret+=",";
|
ret += ",";
|
||||||
ret+=getNodeID().GetHex();
|
ret += getNodeID().GetHex();
|
||||||
ret+=")";
|
ret += ")";
|
||||||
if(isInner())
|
if (isInner())
|
||||||
{
|
{
|
||||||
for(int i=0; i<16; i++)
|
for(int i = 0; i < 16; ++i)
|
||||||
if(!isEmptyBranch(i))
|
if (!isEmptyBranch(i))
|
||||||
{
|
{
|
||||||
ret+=",b";
|
ret += ",b";
|
||||||
ret+=boost::lexical_cast<std::string>(i);
|
ret += boost::lexical_cast<std::string>(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(isLeaf())
|
if (isLeaf())
|
||||||
{
|
{
|
||||||
ret+=",leaf";
|
ret += ",leaf";
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHAMapTreeNode::setChildHash(int m, const uint256 &hash)
|
bool SHAMapTreeNode::setChildHash(int m, const uint256 &hash)
|
||||||
{
|
{
|
||||||
assert( (m>=0) && (m<16) );
|
assert((m >= 0) && (m < 16));
|
||||||
assert(mType==tnINNER);
|
assert(mType == tnINNER);
|
||||||
if(mHashes[m]==hash)
|
if(mHashes[m] == hash)
|
||||||
return false;
|
return false;
|
||||||
mHashes[m]=hash;
|
mHashes[m] = hash;
|
||||||
return updateHash();
|
return updateHash();
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint256& SHAMapTreeNode::getChildHash(int m) const
|
const uint256& SHAMapTreeNode::getChildHash(int m) const
|
||||||
{
|
{
|
||||||
assert( (m>=0) && (m<16) && (mType==tnINNER) );
|
assert((m >= 0) && (m < 16) && (mType == tnINNER));
|
||||||
return mHashes[m];
|
return mHashes[m];
|
||||||
}
|
}
|
||||||
// vim:ts=4
|
// vim:ts=4
|
||||||
|
|||||||
Reference in New Issue
Block a user