static bool CheckBlockHeader(const CBlockHeader& block, BlockValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW = true)
{
// Check proof of work's matches claimed amount (dual pow logic)
bool powResult1 = fCheckPOW ? CheckProofOfWork(block.GetYespowerPoWHash(), block.nBits, consensusParams) : true;
bool powResult2 = fCheckPOW ? CheckProofOfWork(block.GetArgon2idPoWHash(), block.nBits, consensusParams) : true;
// Checking if both POW's are valid
if (!powResult1 || !powResult2) {
return state.Invalid(BlockValidationResult::BLOCK_INVALID_HEADER, "high-hash", "proof of work's failed");
}
return true;
}
/* Yespower */
uint256 CBlockHeader::GetYespowerPoWHash() const
{
static const yespower_params_t yespower_1_0_dpowcoin = {
.version = YESPOWER_1_0,
.N = 2048,
.r = 8,
.pers = (const uint8_t *)"One POW? Why not two? 17/04/2024",
.perslen = 32
};
uint256 hash;
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << *this;
if (yespower_tls((const uint8_t *)&ss[0], ss.size(), &yespower_1_0_dpowcoin, (yespower_binary_t *)&hash)) {
tfm::format(std::cerr, "Error: CBlockHeader::GetYespowerPoWHash(): failed to compute PoW hash (out of memory?)\n");
exit(1);
}
return hash;
}
// CBlockHeader::GetArgon2idPoWHash() instance
// -> Serialize Block Header using CDataStream
// -> Compute SHA-512 hash of serialized data (Two Rounds)
// -> Use the computed hash as the salt for argon2id_hash_raw function for the first round
// -> Call argon2id_hash_raw function for the first round using the serialized data as password and SHA-512 hash as salt
// -> Use the hash obtained from the first round as the salt for the second round
// -> Call argon2id_hash_raw function for the second round using the serialized data as password and the hash from the first round as salt
// -> Return the hash computed in the second round (hash2)
uint256 CBlockHeader::GetArgon2idPoWHash() const
{
uint256 hash;
uint256 hash2;
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << *this;
// Hashing the data using SHA-512 (two rounds)
std::vector<unsigned char> salt_sha512(CSHA512::OUTPUT_SIZE);
CSHA512 sha512;
sha512.Write((unsigned char*)&ss[0], ss.size()).Finalize(salt_sha512.data());
sha512.Reset().Write(salt_sha512.data(), salt_sha512.size()).Finalize(salt_sha512.data());
// Preparing data for hashing
const void* pwd = &ss[0];
size_t pwdlen = ss.size();
const void* salt = salt_sha512.data();
size_t saltlen = salt_sha512.size();
// Calling the argon2id_hash_raw function for the first round
int rc = argon2id_hash_raw(2, 4096, 2, pwd, pwdlen, salt, saltlen, &hash, 32);
if (rc != ARGON2_OK) {
printf("Error: Failed to compute Argon2id hash for the first round\n");
exit(1);
}
// Using the hash from the first round as the salt for the second round
salt = &hash;
saltlen = 32;
// Calling the argon2id_hash_raw function for the second round
rc = argon2id_hash_raw(2, 32768, 2, pwd, pwdlen, salt, saltlen, &hash2, 32);
if (rc != ARGON2_OK) {
printf("Error: Failed to compute Argon2id hash for the second round\n");
exit(1);
}
// Return the result of the second round of Argon2id
return hash2;
}
Logic
https://bitcointalk.org/index.php?topic=5493459.0
https://github.com/dpowcore-project/dpowcoin/tree/master/src/crypto