Skip to content

Commit

Permalink
validation: added scrypt-sse2 and block_header_hash
Browse files Browse the repository at this point in the history
block: updated dogecoin_auxpow_block_new and check for chain_merkle
auxpow: updated check_merkle_branch for Hash and to shift n_index
hash: update Hash for uint256 and added allocation for sha2 ctx
  • Loading branch information
edtubbs committed Nov 22, 2023
1 parent a66af58 commit 33cacae
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 52 deletions.
2 changes: 1 addition & 1 deletion include/dogecoin/auxpow.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ LIBDOGECOIN_BEGIN_DECL
static const unsigned char pch_merged_mining_header[] = { 0xfa, 0xbe, 'm', 'm' };

int get_expected_index(uint32_t nNonce, int nChainId, unsigned h);
uint256* check_merkle_branch(uint256 hash, const vector* parent_coinbase_merkle, unsigned int n_index);
uint256* check_merkle_branch(uint256* hash, const vector* merkle_branch, int index);

LIBDOGECOIN_END_DECL

Expand Down
29 changes: 22 additions & 7 deletions include/dogecoin/hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ typedef struct _chash256 {

static inline chash256* dogecoin_chash256_init() {
chash256* chash = dogecoin_calloc(1, sizeof(*chash));
sha256_context* ctx = NULL;
sha256_context* ctx = dogecoin_calloc(1, sizeof(*ctx));
sha256_init(ctx);
chash->sha = ctx;
chash->write = sha256_write;
Expand All @@ -107,19 +107,34 @@ static inline chash256* dogecoin_chash256_init() {
return chash;
}

static inline uint256* Hash(const uint256 p1begin, const uint256 p1end,
const uint256 p2begin, const uint256 p2end) {
static const unsigned char pblank[1];
// Hashes the data from two uint256 values and returns the double SHA-256 hash.
static inline uint256* Hash(const uint256* p1, const uint256* p2) {
uint256* result = dogecoin_uint256_vla(1);
chash256* chash = dogecoin_chash256_init();
chash->write(chash->sha, p1begin == p1end ? pblank : (const unsigned char*)&p1begin[0], (p1end - p1begin) * sizeof(p1begin[0]));
chash->write(chash->sha, p2begin == p2end ? pblank : (const unsigned char*)&p2begin[0], (p2end - p2begin) * sizeof(p2begin[0]));

// Write the first uint256 to the hash context
if (p1) {
chash->write(chash->sha, (const uint8_t*)p1, sizeof(uint256));
}

// Write the second uint256 to the hash context
if (p2) {
chash->write(chash->sha, (const uint8_t*)p2, sizeof(uint256));
}

// Finalize and reset for double hashing
chash->finalize(chash->sha, (unsigned char*)result);
chash->reset(chash->sha);
chash->write(chash->sha, (const uint8_t*)result, SHA256_DIGEST_LENGTH);
chash->finalize(chash->sha, (unsigned char*)result);

// Cleanup
free(chash->sha);
free(chash);

return result;
}


/** Hashwriter Psuedoclass */
static enum ser_type {
// primary actions
Expand Down
2 changes: 1 addition & 1 deletion include/dogecoin/validation.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ LIBDOGECOIN_BEGIN_DECL
LIBDOGECOIN_API uint32_t get_chainid(uint32_t version);
LIBDOGECOIN_API dogecoin_bool is_auxpow(uint32_t version);
LIBDOGECOIN_API dogecoin_bool is_legacy(uint32_t version);
LIBDOGECOIN_API dogecoin_bool check_auxpow(dogecoin_auxpow_block block, dogecoin_chainparams* params);
LIBDOGECOIN_API dogecoin_bool check_auxpow(dogecoin_auxpow_block* block, dogecoin_chainparams* params);
LIBDOGECOIN_API dogecoin_bool dogecoin_block_header_scrypt_hash(cstring* s, uint256* hash);

LIBDOGECOIN_END_DECL
Expand Down
36 changes: 24 additions & 12 deletions src/auxpow.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,29 @@ int get_expected_index (uint32_t nNonce, int nChainId, unsigned h)
return rand % (1 << h);
}

uint256* check_merkle_branch(uint256 hash, const vector* parent_coinbase_merkle, unsigned int n_index) {
if (n_index == (unsigned int)-1) return dogecoin_uint256_vla(1);
unsigned int i = n_index;
for (; i < parent_coinbase_merkle->len; ++i) {
uint256 pcm;
memcpy(pcm, vector_idx(parent_coinbase_merkle, i), 32);
if (i & 1)
hash = (uint8_t *)Hash(UBEGIN(*pcm), UEND(*pcm), UBEGIN(hash), UEND(hash));
else
hash = (uint8_t *)Hash(UBEGIN(hash), UEND(hash), UBEGIN(*pcm), UEND(*pcm));
i >>= 1;
// Computes the Merkle root from a given hash, Merkle branch, and index.
uint256* check_merkle_branch(uint256* hash, const vector* merkle_branch, int index) {
if (index == -1) {
return dogecoin_uint256_vla(1); // Return a zeroed-out uint256 array.
}
return (uint256*)*&hash;

uint256* current_hash = dogecoin_uint256_vla(1);
memcpy(current_hash, hash, sizeof(uint256)); // Copy the initial hash

for (int i = 0; i < merkle_branch->len; ++i) {
uint256* next_branch_hash = (uint256*)vector_idx(merkle_branch, i);
uint256* new_hash;

if (index & 1) {
new_hash = Hash(next_branch_hash, current_hash);
} else {
new_hash = Hash(current_hash, next_branch_hash);
}

memcpy(current_hash, new_hash, sizeof(uint256)); // Update the current hash
dogecoin_free(new_hash); // Free the new hash memory
index >>= 1;
}

return current_hash;
}
44 changes: 30 additions & 14 deletions src/block.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,25 +53,29 @@ dogecoin_bool check(void *ctx, uint256* hash, uint32_t chainid, dogecoin_chainpa

uint32_t parent_chainid = get_chainid(block->parent_header->version);
if (params->strict_id && parent_chainid == chainid) {
printf("Aux POW parent has our chain ID");
printf("Aux POW parent has our chain ID\n");
return false;
}

vector* parent_merkle = vector_new(8, NULL);
size_t p = 0;
for (; p < block->parent_merkle_count; p++) {
vector_add(parent_merkle, block->parent_coinbase_merkle[p]);
vector* chain_merkle_branch = vector_new(block->aux_merkle_count, NULL);
for (size_t p = 0; p < block->aux_merkle_count; p++) {
vector_add(chain_merkle_branch, block->aux_merkle_branch[p]);
}

if (parent_merkle->len > 30) {
if (chain_merkle_branch->len > 30) {
printf("Aux POW chain merkle branch too long\n");
vector_free(chain_merkle_branch, true);
return false;
}

// Check that the chain merkle root is in the coinbase
uint256* n_roothash = check_merkle_branch((uint8_t*)hash, parent_merkle, parent_merkle->len);
const unsigned char* vch_roothash = (unsigned char*)hash_to_string((uint8_t*)n_roothash); // correct endian
vector_free(parent_merkle, true);
// First call to check_merkle_branch for the auxiliary blockchain's merkle branch
uint256* chain_merkle_root = check_merkle_branch(hash, chain_merkle_branch, block->aux_merkle_index);
vector_free(chain_merkle_branch, true);

// Convert the root hash to a human-readable format (hex)
unsigned char vch_roothash[64]; // Make sure it's large enough to hold the hash
memcpy(vch_roothash, hash_to_string((uint8_t*)chain_merkle_root), 64); // Copy the data
dogecoin_free(chain_merkle_root); // Free the computed merkle root

dogecoin_tx_in *tx_in = vector_idx(block->parent_coinbase->vin, 0);
size_t idx = 0, count = 0;
Expand Down Expand Up @@ -146,6 +150,13 @@ dogecoin_auxpow_block* dogecoin_auxpow_block_new() {
dogecoin_auxpow_block* block = dogecoin_calloc(1, sizeof(*block));
block->header = dogecoin_block_header_new();
block->parent_coinbase = dogecoin_tx_new();
dogecoin_mem_zero(&block->parent_hash, DOGECOIN_HASH_LENGTH);
block->parent_merkle_count = 0;
block->parent_coinbase_merkle;
block->parent_merkle_index = 0;
block->aux_merkle_count = 0;
block->aux_merkle_branch;
block->aux_merkle_index = 0;
block->parent_header = dogecoin_block_header_new();
block->header->auxpow->check = check;
block->header->auxpow->ctx = block;
Expand Down Expand Up @@ -244,7 +255,7 @@ void print_parent_header(dogecoin_auxpow_block* block) {
printf("block->aux_merkle_count: %d\n", block->aux_merkle_count);
j = 0;
for (; j < block->aux_merkle_count; j++) {
printf("block->aux_merkle_branch[%zu]: "
printf("block->aux_merkle_branch[%zu]: "
"%s\n", j, hash_to_string((uint8_t*)block->aux_merkle_branch[j]));
}
printf("block->aux_merkle_index: %d\n", block->aux_merkle_index);
Expand Down Expand Up @@ -328,7 +339,9 @@ int deserialize_dogecoin_auxpow_block(dogecoin_auxpow_block* block, struct const
return false;
}
uint8_t i = 0;
block->parent_coinbase_merkle = dogecoin_calloc(block->parent_merkle_count, sizeof(uint256));
if (block->parent_merkle_count > 0) {
block->parent_coinbase_merkle = dogecoin_calloc(block->parent_merkle_count, sizeof(uint256));
}
for (; i < block->parent_merkle_count; i++) {
if (!deser_u256(block->parent_coinbase_merkle[i], buffer)) {
printf("%d:%s:%d\n", __LINE__, __func__, i);
Expand All @@ -344,7 +357,9 @@ int deserialize_dogecoin_auxpow_block(dogecoin_auxpow_block* block, struct const
printf("%s:%d:%s:%s\n", __FILE__, __LINE__, __func__, strerror(errno));
return false;
}
block->aux_merkle_branch = dogecoin_calloc(block->aux_merkle_count, sizeof(uint256));
if (block->aux_merkle_count > 0) {
block->aux_merkle_branch = dogecoin_calloc(block->aux_merkle_count, sizeof(uint256));
}
for (i = 0; i < block->aux_merkle_count; i++) {
if (!deser_u256(block->aux_merkle_branch[i], buffer)) {
printf("%d:%s:%d\n", __LINE__, __func__, i);
Expand Down Expand Up @@ -381,8 +396,9 @@ int deserialize_dogecoin_auxpow_block(dogecoin_auxpow_block* block, struct const
return false;
}

if (!check_auxpow(*block, (dogecoin_chainparams*)params)) {
if (!check_auxpow(block, (dogecoin_chainparams*)params)) {
printf("check_auxpow failed!\n");
print_block(block);
return false;
}

Expand Down
35 changes: 18 additions & 17 deletions src/validation.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,13 @@
*/
dogecoin_bool dogecoin_block_header_scrypt_hash(cstring* s, uint256* hash) {
char scratchpad[SCRYPT_SCRATCHPAD_SIZE];
#if defined(USE_SSE2)
scrypt_1024_1_1_256_sp_sse2((const char*)s->str, (char *) hash, scratchpad);
#else
scrypt_1024_1_1_256_sp_generic((const char*)s->str, (char *) hash, scratchpad);
#endif
return true;
}
}

uint32_t get_chainid(uint32_t version) {
return version >> 16;
Expand All @@ -60,29 +64,29 @@ dogecoin_bool is_legacy(uint32_t version) {
|| (version == 2 && get_chainid(version) == 0);
}

dogecoin_bool check_auxpow(dogecoin_auxpow_block block, dogecoin_chainparams* params) {
dogecoin_bool check_auxpow(dogecoin_auxpow_block* block, dogecoin_chainparams* params) {
/* Except for legacy blocks with full version 1, ensure that
the chain ID is correct. Legacy blocks are not allowed since
the merge-mining start, which is checked in AcceptBlockHeader
where the height is known. */
if (!is_legacy(block.header->version) && params->strict_id && get_chainid(block.header->version) != params->auxpow_id) {
if (!is_legacy(block->header->version) && params->strict_id && get_chainid(block->header->version) != params->auxpow_id) {
printf("%s:%d:%s : block does not have our chain ID"
" (got %d, expected %d, full nVersion %d) : %s\n",
__FILE__, __LINE__, __func__, get_chainid(block.header->version),
params->auxpow_id, block.header->version, strerror(errno));
__FILE__, __LINE__, __func__, get_chainid(block->header->version),
params->auxpow_id, block->header->version, strerror(errno));
return false;
}

/* If there is no auxpow, just check the block hash. */
if (!block.header->auxpow->is) {
if (!block->header->auxpow->is) {

uint256 hash = {0};
cstring* s = cstr_new_sz(64);
dogecoin_block_header_serialize(s, block.header);
dogecoin_block_header_serialize(s, block->header);
dogecoin_block_header_scrypt_hash(s, &hash);
cstr_free(s, true);

if (!check_pow(&hash, block.header->bits, params)) {
if (!check_pow(&hash, block->header->bits, params)) {
printf("%s:%d:%s : non-AUX proof of work failed : %s\n", __FILE__, __LINE__, __func__, strerror(errno));
return false;
}
Expand All @@ -92,23 +96,20 @@ dogecoin_bool check_auxpow(dogecoin_auxpow_block block, dogecoin_chainparams* pa

/* We have auxpow. Check it. */
uint256 block_header_hash;
cstring* s = cstr_new_sz(64);
dogecoin_block_header_serialize(s, block.header);
dogecoin_block_header_scrypt_hash(s, &block_header_hash);
cstr_free(s, true);
uint32_t chainid = get_chainid(block.header->version);
if (!block.header->auxpow->check(&block, &block_header_hash, chainid, params)) {
dogecoin_block_header_hash(block->header, block_header_hash);
uint32_t chainid = get_chainid(block->header->version);
if (!block->header->auxpow->check(block, &block_header_hash, chainid, params)) {
printf("%s:%d:%s : AUX POW is not valid : %s\n", __FILE__, __LINE__, __func__, strerror(errno));
return false;
}

uint256 parent_hash;
cstring* s2 = cstr_new_sz(64);
dogecoin_block_header_serialize(s2, block.parent_header);
dogecoin_block_header_serialize(s2, block->parent_header);
dogecoin_block_header_scrypt_hash(s2, &parent_hash);
cstr_free(s2, true);
if (!check_pow(&parent_hash, block.header->bits, params)) {
printf("%s:%d:%s : check_pow failure : %s\n", __FILE__, __LINE__, __func__, strerror(errno));
if (!check_pow(&parent_hash, block->header->bits, params)) {
printf("%s:%d:%s : AUX proof of work failed: %s\n", __FILE__, __LINE__, __func__, strerror(errno));
return false;
}

Expand Down

0 comments on commit 33cacae

Please sign in to comment.