|
|
|
|
@ -165,15 +165,31 @@ static int _get_level_hashes(struct merkle_sync* ms, const char* ns,
|
|
|
|
|
memset(hashes, 0, sizeof(uint8_t) * MT_BUCKETS * MT_HASH_SIZE); |
|
|
|
|
*bitmap = 0; |
|
|
|
|
if (level >= MT_MAX_LEVEL) return 0; |
|
|
|
|
int next_shift = 63 - ((int)level + 1) * 5; |
|
|
|
|
|
|
|
|
|
for (int i = 0; i < MT_BUCKETS; i++) { |
|
|
|
|
uint64_t child_prefix = prefix | ((uint64_t)i << (next_shift > 0 ? next_shift : 0)); |
|
|
|
|
const uint8_t* h = merkle_sync_get_hash(ms->inst, ns, (uint8_t)(level + 1), child_prefix); |
|
|
|
|
int empty = 1; |
|
|
|
|
for (int j = 0; j < MT_HASH_SIZE; j++) { if (h[j] != 0) { empty = 0; break; } } |
|
|
|
|
if (!empty) { *bitmap |= (1u << i); memcpy(hashes[i], h, MT_HASH_SIZE); } |
|
|
|
|
sqlite3* db = _db(ms->inst); if (!db) return -1; |
|
|
|
|
int parent_shift = 63 - (int)level * 5; if (parent_shift < 0) parent_shift = 0; |
|
|
|
|
int next_shift = 63 - ((int)level + 1) * 5; if (next_shift < 0) next_shift = 0; |
|
|
|
|
uint64_t range_end = prefix | ((1ULL << parent_shift) - 1); |
|
|
|
|
|
|
|
|
|
sqlite3_stmt* stmt = NULL; |
|
|
|
|
if (sqlite3_prepare_v2(db, |
|
|
|
|
"SELECT prefix64, hash FROM merkle_tree_hash" |
|
|
|
|
" WHERE namespace=? AND level=? AND prefix64>=? AND prefix64<=?" |
|
|
|
|
" ORDER BY prefix64", -1, &stmt, NULL) != SQLITE_OK || !stmt) |
|
|
|
|
return -1; |
|
|
|
|
sqlite3_bind_text(stmt, 1, ns, -1, SQLITE_STATIC); |
|
|
|
|
sqlite3_bind_int(stmt, 2, (int)(level + 1)); |
|
|
|
|
sqlite3_bind_int64(stmt, 3, (sqlite3_int64)prefix); |
|
|
|
|
sqlite3_bind_int64(stmt, 4, (sqlite3_int64)range_end); |
|
|
|
|
while (sqlite3_step(stmt) == SQLITE_ROW) { |
|
|
|
|
sqlite3_int64 row_pfx = sqlite3_column_int64(stmt, 0); |
|
|
|
|
const void* h = sqlite3_column_blob(stmt, 1); |
|
|
|
|
if (!h || sqlite3_column_bytes(stmt, 1) < MT_HASH_SIZE) continue; |
|
|
|
|
int bucket = (int)(((uint64_t)row_pfx >> next_shift) & 0x1F); |
|
|
|
|
*bitmap |= (1u << bucket); |
|
|
|
|
memcpy(hashes[bucket], h, MT_HASH_SIZE); |
|
|
|
|
} |
|
|
|
|
sqlite3_finalize(stmt); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|