// Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2011 Vince Durham // Copyright (c) 2009-2014 The Bitcoin developers // Copyright (c) 2014-2015 Daniel Kraft // Distributed under the MIT/X11 software license, see the accompanying // file license.txt or http://www.opensource.org/licenses/mit-license.php. #include "auxpow.h" #include "chainparams.h" #include "consensus/validation.h" #include "main.h" #include "script/script.h" #include "util.h" #include /* Moved from wallet.cpp. CMerkleTx is necessary for auxpow, independent of an enabled (or disabled) wallet. Always include the code. */ int CMerkleTx::SetMerkleBranch(const CBlock& block) { AssertLockHeld(cs_main); CBlock blockTmp; // Update the tx's hashBlock hashBlock = block.GetHash(); // Locate the transaction for (nIndex = 0; nIndex < (int)block.vtx.size(); nIndex++) if (block.vtx[nIndex] == *(CTransaction*)this) 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 = block.GetMerkleBranch(nIndex); // Is the tx in a block that's in the main chain BlockMap::iterator mi = mapBlockIndex.find(hashBlock); if (mi == mapBlockIndex.end()) return 0; const CBlockIndex* pindex = (*mi).second; if (!pindex || !chainActive.Contains(pindex)) return 0; return chainActive.Height() - pindex->nHeight + 1; } int CMerkleTx::GetDepthInMainChainINTERNAL(const CBlockIndex*& pindexRet) const { if (hashBlock.IsNull() || nIndex == -1) return 0; AssertLockHeld(cs_main); // Find the block it claims to be in BlockMap::iterator mi = mapBlockIndex.find(hashBlock); if (mi == mapBlockIndex.end()) return 0; CBlockIndex* pindex = (*mi).second; if (!pindex || !chainActive.Contains(pindex)) return 0; // Make sure the merkle branch connects to this block if (!fMerkleVerified) { if (CBlock::CheckMerkleBranch(GetHash(), vMerkleBranch, nIndex) != pindex->hashMerkleRoot) return 0; fMerkleVerified = true; } pindexRet = pindex; return chainActive.Height() - pindex->nHeight + 1; } int CMerkleTx::GetDepthInMainChain(const CBlockIndex*& pindexRet) const { AssertLockHeld(cs_main); int nResult = GetDepthInMainChainINTERNAL(pindexRet); if (nResult == 0 && !mempool.exists(GetHash())) return -1; // Not in chain, not in mempool return nResult; } int CMerkleTx::GetBlocksToMaturity() const { if (!IsCoinBase()) return 0; int nCoinbaseMaturity = Params().GetConsensus(chainActive.Height()).nCoinbaseMaturity; return std::max(0, (nCoinbaseMaturity + 1) - GetDepthInMainChain()); } bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree, bool fRejectAbsurdFee) { CValidationState state; return ::AcceptToMemoryPool(mempool, state, *this, fLimitFree, NULL, fRejectAbsurdFee); } /* ************************************************************************** */ bool CAuxPow::check(const uint256& hashAuxBlock, int nChainId, const Consensus::Params& params) const { if (nIndex != 0) return error("AuxPow is not a generate"); if (params.fStrictChainId && parentBlock.nVersion.GetChainId() == nChainId) return error("Aux POW parent has our chain ID"); if (vChainMerkleBranch.size() > 30) return error("Aux POW chain merkle branch too long"); // Check that the chain merkle root is in the coinbase const uint256 nRootHash = CBlock::CheckMerkleBranch(hashAuxBlock, vChainMerkleBranch, nChainIndex); std::vector vchRootHash(nRootHash.begin(), nRootHash.end()); std::reverse(vchRootHash.begin(), vchRootHash.end()); // correct endian // Check that we are in the parent block merkle tree if (CBlock::CheckMerkleBranch(GetHash(), vMerkleBranch, nIndex) != parentBlock.hashMerkleRoot) return error("Aux POW merkle root incorrect"); const CScript script = vin[0].scriptSig; // Check that the same work is not submitted twice to our chain. // CScript::const_iterator pcHead = std::search(script.begin(), script.end(), UBEGIN(pchMergedMiningHeader), UEND(pchMergedMiningHeader)); CScript::const_iterator pc = std::search(script.begin(), script.end(), vchRootHash.begin(), vchRootHash.end()); if (pc == script.end()) return error("Aux POW missing chain merkle root in parent coinbase"); if (pcHead != script.end()) { // Enforce only one chain merkle root by checking that a single instance of the merged // mining header exists just before. if (script.end() != std::search(pcHead + 1, script.end(), UBEGIN(pchMergedMiningHeader), UEND(pchMergedMiningHeader))) return error("Multiple merged mining headers in coinbase"); if (pcHead + sizeof(pchMergedMiningHeader) != pc) return error("Merged mining header is not just before chain merkle root"); } else { // For backward compatibility. // Enforce only one chain merkle root by checking that it starts early in the coinbase. // 8-12 bytes are enough to encode extraNonce and nBits. if (pc - script.begin() > 20) return error("Aux POW chain merkle root must start in the first 20 bytes of the parent coinbase"); } // Ensure we are at a deterministic point in the merkle leaves by hashing // a nonce and our chain ID and comparing to the index. pc += vchRootHash.size(); if (script.end() - pc < 8) return error("Aux POW missing chain merkle tree size and nonce in parent coinbase"); int nSize; memcpy(&nSize, &pc[0], 4); const unsigned merkleHeight = vChainMerkleBranch.size(); if (nSize != (1 << merkleHeight)) return error("Aux POW merkle branch size does not match parent coinbase"); int nNonce; memcpy(&nNonce, &pc[4], 4); if (nChainIndex != getExpectedIndex(nNonce, nChainId, merkleHeight)) return error("Aux POW wrong index"); return true; } int CAuxPow::getExpectedIndex(int nNonce, int nChainId, unsigned h) { // Choose a pseudo-random slot in the chain merkle tree // but have it be fixed for a size/nonce/chain combination. // // This prevents the same work from being used twice for the // same chain while reducing the chance that two chains clash // for the same slot. unsigned rand = nNonce; rand = rand * 1103515245 + 12345; rand += nChainId; rand = rand * 1103515245 + 12345; return rand % (1 << h); }