Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

validation: added scrypt-sse2 #172

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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