You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
104 lines
3.4 KiB
104 lines
3.4 KiB
// Copyright (c) 2009-2010 Satoshi Nakamoto |
|
// Copyright (c) 2009-2017 The Bitcoin Core developers |
|
// Distributed under the MIT software license, see the accompanying |
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php. |
|
|
|
#include <arith_uint256.h> |
|
#include <primitives/block.h> |
|
#include <streams.h> |
|
|
|
#include <hash.h> |
|
#include <tinyformat.h> |
|
#include <utilstrencodings.h> |
|
#include <crypto/common.h> |
|
#include <validation.h> |
|
#include <crypto/hash-ops.h> |
|
|
|
extern "C" void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int prehashed, uint64_t height); |
|
extern "C" void cn_fast_hash(const void *data, size_t length, char *hash); |
|
|
|
static void cn_get_block_hash_by_height(uint64_t seed_height, char cnHash[32]) |
|
{ |
|
CBlockIndex* pblockindex = chainActive[seed_height]; |
|
if (pblockindex == nullptr) { |
|
// This will happen during initial block downloading, or when we |
|
// are out of sync by more than at least SEEDHASH_EPOCH_BLOCKS blocks. |
|
LOCK(cs_main); |
|
std::map<uint64_t, CBlockIndex*>::iterator iter = mapBlockSeedHeight.find(seed_height); |
|
if (iter != mapBlockSeedHeight.end()) { |
|
pblockindex = iter->second; |
|
} |
|
} |
|
if (pblockindex == nullptr) { |
|
return; |
|
} |
|
uint256 blockHash = pblockindex->GetBlockHash(); |
|
const unsigned char* pHash = blockHash.begin(); |
|
for (int j = 31; j >= 0; j--) { |
|
cnHash[31 - j] = pHash[j]; |
|
} |
|
} |
|
|
|
uint256 CBlockHeader::GetOriginalBlockHash() const |
|
{ |
|
CHashWriter hashWriter(SER_GETHASH, PROTOCOL_VERSION); |
|
hashWriter.write(BEGIN(nVersion), 80); |
|
return hashWriter.GetHash(); |
|
} |
|
|
|
// prev_id of CN header is used to store the kevacoin block hash. |
|
// The value of prev_id and block hash must be the same to prove |
|
// that PoW has been properly done. |
|
bool CBlockHeader::isCNConsistent() const |
|
{ |
|
return (GetOriginalBlockHash() == cnHeader.prev_id); |
|
} |
|
|
|
uint256 CBlockHeader::GetHash() const |
|
{ |
|
uint256 thash; |
|
if (!isCNConsistent()) { |
|
memset(thash.begin(), 0xff, thash.size()); |
|
return thash; |
|
} |
|
cryptonote::blobdata blob = cryptonote::t_serializable_object_to_blob(cnHeader); |
|
cn_fast_hash(blob.data(), blob.size(), BEGIN(thash)); |
|
return thash; |
|
} |
|
|
|
uint256 CBlockHeader::GetPoWHash() const |
|
{ |
|
uint256 thash; |
|
if (!isCNConsistent()) { |
|
memset(thash.begin(), 0xff, thash.size()); |
|
return thash; |
|
} |
|
cryptonote::blobdata blob = cryptonote::t_serializable_object_to_blob(cnHeader); |
|
uint32_t height = nNonce; |
|
if (cnHeader.major_version >= RX_BLOCK_VERSION) { |
|
uint64_t seed_height; |
|
char cnHash[32]; |
|
seed_height = crypto::rx_seedheight(height); |
|
cn_get_block_hash_by_height(seed_height, cnHash); |
|
crypto::rx_slow_hash(height, seed_height, cnHash, blob.data(), blob.size(), BEGIN(thash), 0, 0); |
|
} else { |
|
cn_slow_hash(blob.data(), blob.size(), BEGIN(thash), cnHeader.major_version - 6, 0, height); |
|
} |
|
return thash; |
|
} |
|
|
|
std::string CBlock::ToString() const |
|
{ |
|
std::stringstream s; |
|
s << strprintf("CBlock(hash=%s, ver=0x%08x, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%u)\n", |
|
GetOriginalBlockHash().ToString(), |
|
nVersion, |
|
hashPrevBlock.ToString(), |
|
hashMerkleRoot.ToString(), |
|
nTime, nBits, nNonce, |
|
vtx.size()); |
|
for (const auto& tx : vtx) { |
|
s << " " << tx->ToString() << "\n"; |
|
} |
|
return s.str(); |
|
}
|
|
|