Skip to content

Commit

Permalink
six auxpow
Browse files Browse the repository at this point in the history
  • Loading branch information
sidhujag committed Dec 22, 2016
1 parent 8fdcf86 commit 0e11c91
Show file tree
Hide file tree
Showing 8 changed files with 154 additions and 91 deletions.
40 changes: 40 additions & 0 deletions src/auxpow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,15 @@ int CMerkleTx::SetMerkleBranch(const CBlock& block)
break;
if (nIndex == (int)block.vtx.size())
{
vMerkleBranch.clear();
nIndex = -1;
LogPrintf("ERROR: SetMerkleBranch(): couldn't find tx in block\n");
return 0;
}

// Fill in merkle branch
vMerkleBranch = BlockMerkleBranch (block, nIndex);

// Is the tx in a block that's in the main chain
BlockMap::iterator mi = mapBlockIndex.find(hashBlock);
if (mi == mapBlockIndex.end())
Expand Down Expand Up @@ -206,4 +210,40 @@ CAuxPow::CheckMerkleBranch (uint256 hash,
nIndex >>= 1;
}
return hash;
}
void
CAuxPow::initAuxPow (CBlockHeader& header)
{
/* Set auxpow flag right now, since we take the block hash below. */
header.SetAuxpowVersion(true);

/* Build a minimal coinbase script input for merge-mining. */
const uint256 blockHash = header.GetHash ();
std::vector<unsigned char> inputData(blockHash.begin (), blockHash.end ());
std::reverse (inputData.begin (), inputData.end ());
inputData.push_back (1);
inputData.insert (inputData.end (), 7, 0);

/* Fake a parent-block coinbase with just the required input
script and no outputs. */
CMutableTransaction coinbase;
coinbase.vin.resize (1);
coinbase.vin[0].prevout.SetNull ();
coinbase.vin[0].scriptSig = (CScript () << inputData);
assert (coinbase.vout.empty ());

/* Build a fake parent block with the coinbase. */
CBlock parent;
parent.nVersion = 1;
parent.vtx.resize (1);
parent.vtx[0] = coinbase;
parent.hashMerkleRoot = BlockMerkleRoot (parent);

/* Construct the auxpow object. */
header.SetAuxpow (new CAuxPow (coinbase));
assert (header.auxpow->vChainMerkleBranch.empty ());
header.auxpow->nChainIndex = 0;
assert (header.auxpow->vMerkleBranch.empty ());
header.auxpow->nIndex = 0;
header.auxpow->parentBlock = parent;
}
16 changes: 13 additions & 3 deletions src/auxpow.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@
#include <vector>

class CBlock;
class CBlockHeader;
class CBlockIndex;
class CValidationState;

/** Header for merge-mining data in the coinbase. */
static const unsigned char pchMergedMiningHeader[] = { 0xfa, 0xbe, 'm', 'm' };

Expand All @@ -33,7 +35,8 @@ class CMerkleTx : public CTransaction

public:
uint256 hashBlock;
std::vector<uint256> vMerkleBranch;
std::vector<uint256> vMerkleBranch;

/* An nIndex == -1 means that hashBlock (in nonzero) refers to the earliest
* block in the chain we know this or any in-wallet dependency conflicts
* with. Older clients interpret nIndex == -1 as unconfirmed for backward
Expand Down Expand Up @@ -61,8 +64,6 @@ class CMerkleTx : public CTransaction

template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
// SYSCOIN
//std::vector<uint256> vMerkleBranch; // For compatibility with older versions.
READWRITE(*(CTransaction*)this);
nVersion = this->nVersion;
READWRITE(hashBlock);
Expand Down Expand Up @@ -188,6 +189,15 @@ class CAuxPow : public CMerkleTx
const std::vector<uint256>& vMerkleBranch,
int nIndex);

/**
* Initialise the auxpow of the given block header. This constructs
* a minimal CAuxPow object with a minimal parent block and sets
* it on the block header. The auxpow is not necessarily valid, but
* can be "mined" to make it valid.
* @param header The header to set the auxpow on.
*/
static void initAuxPow (CBlockHeader& header);

};

#endif // SYSCOIN_AUXPOW_H
12 changes: 0 additions & 12 deletions src/chain.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,6 @@ class CBlockIndex
//! pointer to the index of some further predecessor of this block
CBlockIndex* pskip;

// SYSCOIN pointer to the AuxPoW header, if this block has one
boost::shared_ptr<CAuxPow> pauxpow;

//! height of the entry in the chain. The genesis block has height 0
int nHeight;
Expand Down Expand Up @@ -211,8 +209,6 @@ class CBlockIndex
phashBlock = NULL;
pprev = NULL;
pskip = NULL;
// SYSCOIN
pauxpow.reset();
nHeight = 0;
nFile = 0;
nDataPos = 0;
Expand Down Expand Up @@ -374,14 +370,6 @@ class CDiskBlockIndex : public CBlockIndex
READWRITE(nTime);
READWRITE(nBits);
READWRITE(nNonce);
// SYSCOIN
if (this->nVersion.IsAuxpow()) {
if (ser_action.ForRead())
pauxpow.reset(new CAuxPow());
assert(pauxpow);
READWRITE(*pauxpow);
} else if (ser_action.ForRead())
pauxpow.reset();
}

uint256 GetBlockHash() const
Expand Down
66 changes: 52 additions & 14 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3643,11 +3643,6 @@ CBlockIndex* AddToBlockIndex(const CBlockHeader& block)
pindexNew->BuildSkip();
}
pindexNew->nChainWork = (pindexNew->pprev ? pindexNew->pprev->nChainWork : 0) + GetBlockProof(*pindexNew);
// SYSCOIN: Add AuxPoW
if (block.nVersion.IsAuxpow()) {
pindexNew->pauxpow = block.auxpow;
assert(NULL != pindexNew->pauxpow.get());
}
pindexNew->RaiseValidity(BLOCK_VALID_TREE);
if (pindexBestHeader == NULL || pindexBestHeader->nChainWork < pindexNew->nChainWork)
pindexBestHeader = pindexNew;
Expand Down Expand Up @@ -5876,20 +5871,40 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// we must use CBlocks, as CBlockHeaders won't include the 0x00 nTx count at the end
vector<CBlock> vHeaders;
int nLimit = MAX_HEADERS_RESULTS;
// SYSCOIN
unsigned nSize = 0;
LogPrint("net", "getheaders %d to %s from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.ToString(), pfrom->id);
for (; pindex; pindex = chainActive.Next(pindex))
{
// SYSCOIN
vHeaders.push_back(pindex->GetBlockHeader(chainparams.GetConsensus()));
const CBlockHeader &header = pindex->GetBlockHeader(chainparams.GetConsensus());
vHeaders.push_back(header);
if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
break;
// SYSCOIN
nSize += GetSerializeSize(header, SER_NETWORK, PROTOCOL_VERSION);
if (pfrom->nVersion >= SIZE_HEADERS_LIMIT_VERSION
&& nSize >= THRESHOLD_HEADERS_SIZE)
break;
}
// pindex can be NULL either if we sent chainActive.Tip() OR
// if our peer has chainActive.Tip() (and thus we are sending an empty
// headers message). In both cases it's safe to update
// pindexBestHeaderSent to be our tip.
nodestate->pindexBestHeaderSent = pindex ? pindex : chainActive.Tip();
pfrom->PushMessage(NetMsgType::HEADERS, vHeaders);
// SYSCOIN
/* Check maximum headers size before pushing the message
if the peer enforces it. This should not fail since we
break above in the loop at the threshold and the threshold
should be small enough in comparison to the hard max size.
Do it nevertheless to be sure. */
if (pfrom->nVersion >= SIZE_HEADERS_LIMIT_VERSION
&& nSize > MAX_HEADERS_SIZE)
LogPrintf("ERROR: not pushing 'headers', too large\n");
else
{
// pindex can be NULL either if we sent chainActive.Tip() OR
// if our peer has chainActive.Tip() (and thus we are sending an empty
// headers message). In both cases it's safe to update
// pindexBestHeaderSent to be our tip.
nodestate->pindexBestHeaderSent = pindex ? pindex : chainActive.Tip();
pfrom->PushMessage(NetMsgType::HEADERS, vHeaders);
}
}


Expand Down Expand Up @@ -6320,9 +6335,18 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
return error("headers message size = %u", nCount);
}
headers.resize(nCount);
// SYSCOIN
unsigned nSize = 0;
for (unsigned int n = 0; n < nCount; n++) {
vRecv >> headers[n];
ReadCompactSize(vRecv); // ignore tx count; assume it is 0.
//SYSCOIN
nSize += GetSerializeSize(headers[n], SER_NETWORK, PROTOCOL_VERSION);
if (pfrom->nVersion >= SIZE_HEADERS_LIMIT_VERSION
&& nSize > MAX_HEADERS_SIZE) {
Misbehaving(pfrom->GetId(), 20);
return error("headers message size = %u", nSize);
}
}

{
Expand Down Expand Up @@ -6386,8 +6410,22 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,

assert(pindexLast);
UpdateBlockAvailability(pfrom->GetId(), pindexLast->GetBlockHash());

if (nCount == MAX_HEADERS_RESULTS) {
// SYSCOIN
// If we already know the last header in the message, then it contains
// no new information for us. In this case, we do not request
// more headers later. This prevents multiple chains of redundant
// getheader requests from running in parallel if triggered by incoming
// blocks while the node is still in initial headers sync.
const bool hasNewHeaders = (mapBlockIndex.count(headers.back().GetHash()) == 0);

bool maxSize = (nCount == MAX_HEADERS_RESULTS);
if (pfrom->nVersion >= SIZE_HEADERS_LIMIT_VERSION
&& nSize >= THRESHOLD_HEADERS_SIZE)
maxSize = true;
// FIXME: This change (with hasNewHeaders) is rolled back in Bitcoin,
// but I think it should stay here for merge-mined coins. Try to get
// it fixed again upstream and then update the fix.
if (maxSize && hasNewHeaders) {
// Headers message had its maximum size; the peer may have more headers.
// TODO: optimize: if pindexLast is an ancestor of chainActive.Tip or pindexBestHeader, continue
// from there instead.
Expand Down
15 changes: 15 additions & 0 deletions src/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,21 @@ static const unsigned int BLOCK_STALLING_TIMEOUT = 2;
/** Number of headers sent in one getheaders result. We rely on the assumption that if a peer sends
* less than this number, we reached its tip. Changing this value is a protocol upgrade. */
static const unsigned int MAX_HEADERS_RESULTS = 2000;
// SYSCOIN
/** Maximum size of a "headers" message. This is enforced starting with
* SIZE_HEADERS_LIMIT_VERSION peers and prevents overloading if we have
* very large headers (due to auxpow).
*/
static const unsigned int MAX_HEADERS_SIZE = (6 << 20); // 6 MiB
/** Size of a headers message that is the threshold for assuming that the
* peer has more headers (even if we have less than MAX_HEADERS_RESULTS).
* This is used starting with SIZE_HEADERS_LIMIT_VERSION peers.
*/
static const unsigned int THRESHOLD_HEADERS_SIZE = (4 << 20); // 4 MiB
/** Size of the "block download window": how far ahead of our current height do we fetch?
* Larger windows tolerate larger download speed differences between peer, but increase the potential
* degree of disordering of blocks on disk (which make reindexing and in the future perhaps pruning
* harder). We'll probably want to make this a per-peer adaptive value at some point. */
/** Maximum depth of blocks we're willing to serve as compact blocks to peers
* when requested. For older blocks, a regular BLOCK response will be sent. */
static const int MAX_CMPCTBLOCK_DEPTH = 5;
Expand Down

0 comments on commit 0e11c91

Please sign in to comment.