Files
FastSync/src/shared/delta.h
T
TapTap 0afda6b094 feat(checksum): --checksum-choice/--cc and --checksum-seed for whole-file digest
Adds real algorithm selection (xxh64 default, plus md5 via OpenSSL EVP) and a
64-bit seed for the per-file whole-file digest used by the --incremental/
--checksum handshake and basis-dir content verification. The seed also feeds
the delta path's per-block xxHash32 strong checksum (low 32 bits) so an
explicit seed deterministically changes those digests too. Sender and receiver
hash identically: the algorithm id and seed cross the config wire frame and the
STATUS_CHECK handshake now carries a length-prefixed, bounded digest instead of
a fixed 64-bit value. Unsupported algorithm names are rejected at parse time
(never a silent no-op). PROTOCOL_VERSION bumped 2.9.0 -> 2.10.0; defaults
(xxh64, seed 0) preserve prior byte-for-byte behavior.
2026-09-07 17:42:47 +02:00

89 lines
3.0 KiB
C

#ifndef DELTA_H
#define DELTA_H
#include "data.h"
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#define DELTA_BLOCK_SIZE_DEFAULT 8192U
#define DELTA_BLOCK_SIZE_MIN 1024U
#define DELTA_BLOCK_SIZE_MAX 65536U
#define DELTA_MIN_FILE_SIZE 16384ULL
#define DELTA_MAX_FILE_SIZE (256ULL * 1024 * 1024)
#define DELTA_MAX_SIZE_RATIO 10.0
#define DELTA_FALLBACK_RATIO 0.7
#define DELTA_ADLER32_MODULUS 65521U
#define DELTA_OP_BLOCK_MATCH 0x01
#define DELTA_OP_LITERAL 0x02
typedef struct {
uint32_t adler32;
uint32_t xxhash;
} DeltaBlockSig;
typedef struct {
uint64_t file_size;
uint32_t block_size;
uint32_t block_count;
DeltaBlockSig* blocks;
} DeltaSignature;
typedef enum { DELTA_INSTR_BLOCK_MATCH = 0x01, DELTA_INSTR_LITERAL = 0x02 } DeltaInstrType;
typedef struct {
DeltaInstrType type;
union {
struct {
uint32_t block_index;
uint32_t block_offset;
uint32_t length;
} match;
struct {
uint8_t* data;
uint32_t length;
} literal;
};
} DeltaInstruction;
typedef struct {
uint64_t new_file_size;
uint32_t instruction_count;
DeltaInstruction* instructions;
uint64_t delta_size;
} Delta;
DeltaSignature* delta_signature_create(const void* old_file_data, uint64_t old_file_size,
uint32_t block_size);
/* Seeded equivalent of delta_signature_create: the per-block strong (xxHash32)
* checksum uses `seed` (the low 32 bits of --checksum-seed). Passing seed 0 is
* identical to the unseeded function. */
DeltaSignature* delta_signature_create_seeded(const void* old_file_data, uint64_t old_file_size,
uint32_t block_size, uint32_t seed);
Data* delta_signature_serialize(const DeltaSignature* sig);
DeltaSignature* delta_signature_deserialize(const Data* data);
void delta_signature_destroy(DeltaSignature* sig);
Delta* delta_compute(const void* new_file_data, uint64_t new_file_size, const DeltaSignature* sig,
uint32_t block_size);
/* Seeded equivalent of delta_compute: the per-window strong (xxHash32) check
* uses `seed` (the low 32 bits of --checksum-seed). The receiver's signature
* must have been built with the same seed for matching. */
Delta* delta_compute_seeded(const void* new_file_data, uint64_t new_file_size,
const DeltaSignature* sig, uint32_t block_size, uint32_t seed);
Data* delta_serialize(const Delta* delta);
Delta* delta_deserialize(const Data* data);
void* delta_apply(const void* old_data, uint64_t old_size, const Delta* delta, uint32_t block_size);
void delta_destroy(Delta* delta);
bool delta_should_attempt(uint64_t old_size, uint64_t new_size, uint64_t max_file_size);
bool delta_is_worthwhile(const Delta* delta, uint64_t new_file_size);
uint32_t delta_adler32(const void* data, uint32_t len);
uint32_t delta_xxhash32(const void* data, uint32_t len);
uint32_t delta_xxhash32_seeded(const void* data, uint32_t len, uint32_t seed);
uint64_t delta_xxhash64(const void* data, size_t len);
#endif