// SPDX-License-Identifier: LGPL-2.1-or-later
///|
/// No addition or narrowing before the unsigned output-length bounds check.
fn signature_size(count : UInt64, strong : UInt64) -> Int32 raise SyncError {
guard strong >= 1UL && strong <= 32UL else {
raise InvalidOptions("strong_sum_len")
}
let body = checked_block_offset(count, 4UL + strong)
guard body <= 0xffffffffffffffffUL - 12UL else { raise IntegerOutOfRange }
checked_index(body + 12UL)
}
///|
/// Generation precedence: limits, block option, strong option, representation,
/// old bytes, block budget, record budget, output representation, byte budget.
fn signature_plan(
basis_len : UInt64,
options : SignatureOptions,
limits : Limits,
) -> (Int32, Int32, Int32, Int32) raise SyncError {
limits.validate()
guard options.block_len > 0L else { raise InvalidOptions("block_len") }
guard options.strong_sum_len >= 1L && options.strong_sum_len <= 32L else {
raise InvalidOptions("strong_sum_len")
}
let block = checked_index(options.block_len.reinterpret_as_uint64())
let strong = checked_index(options.strong_sum_len.reinterpret_as_uint64())
guard basis_len <= limits.max_old_bytes.reinterpret_as_uint64() else {
raise LimitExceeded
}
guard options.block_len <= limits.max_block_bytes else { raise LimitExceeded }
let divisor = block.to_uint64()
let quotient = basis_len / divisor
// If there is a remainder, divisor >= 2 so quotient cannot be UInt64.MAX.
let count = quotient + (if basis_len % divisor != 0UL { 1UL } else { 0UL })
guard count <= limits.max_signature_records.reinterpret_as_uint64() else {
raise LimitExceeded
}
let size = signature_size(count, strong.to_uint64())
guard size.to_int64() <= limits.max_signature_bytes else {
raise LimitExceeded
}
(block, strong, checked_index(count), size)
}
///|
fn signature_header(
block : Int32,
strong : Int32,
size : Int32,
) -> FixedArray[Byte] raise SyncError {
let output = FixedArray::make(size, b'\x00')
write_u32_be(output, 0L, 0x72730147U)
write_u32_be(output, 4L, block.reinterpret_as_uint())
write_u32_be(output, 8L, strong.reinterpret_as_uint())
output
}
///|
fn write_signature_record(
output : FixedArray[Byte],
offset : Int64,
weak : UInt32,
strong : Bytes,
) -> Unit raise SyncError {
guard strong.length() >= 1 && strong.length() <= 32 else {
raise InvalidSignature
}
let start = checked_wire_span(output.length(), offset, 4 + strong.length())
write_u32_be(output, offset, weak)
for i in 0.. Bytes raise SyncError {
limits.validate()
guard sig.magic == 0x72730147U &&
sig.block_len > 0 &&
sig.strong_sum_len >= 1 &&
sig.strong_sum_len <= 32 else {
raise InvalidSignature
}
guard sig.block_len.to_int64() <= limits.max_block_bytes &&
sig.records.length().to_int64() <= limits.max_signature_records else {
raise LimitExceeded
}
let size = signature_size(
sig.records.length().to_uint64(),
sig.strong_sum_len.to_uint64(),
)
guard size.to_int64() <= limits.max_signature_bytes else {
raise LimitExceeded
}
for record in sig.records {
guard record.strong_sum.length() == sig.strong_sum_len else {
raise InvalidSignature
}
}
let output = signature_header(sig.block_len, sig.strong_sum_len, size)
let mut cursor = 12L
for record in sig.records {
write_signature_record(output, cursor, record.weak_sum, record.strong_sum)
cursor = cursor + (4 + sig.strong_sum_len).to_int64()
}
Bytes::from_array(output[:])
}
///|
/// Internal only. The wire format provides no actual final-block length.
/// Production consumers are the signature index and remote-delta scanner.
#warnings("-unused_field")
priv struct SignatureRecord {
block_index : Int32
nominal_offset : UInt64
weak_sum : UInt32
strong_sum : Bytes
}
///|
/// Parsed structure, not a generated signature or proof of basis identity.
/// The signature index and generator consume this private validated structure.
#warnings("-unused_field")
priv struct Signature {
magic : UInt32
block_len : Int32
strong_sum_len : Int32
records : Array[SignatureRecord]
}
///|
/// Only the RK/BLAKE2 profile is accepted. See docs/signature-format.md for
/// the explicit error precedence, resource policy, and wire-format sources.
/// Public delta generation uses this parser before index construction.
#warnings("-unused_value")
fn parse_signature(
input : BytesView,
limits : Limits,
) -> Signature raise SyncError {
limits.validate()
let input_len = input.length()
guard input_len.to_int64() <= limits.max_signature_bytes else {
raise LimitExceeded
}
guard input_len >= 12 else { raise TruncatedInput }
let magic = read_u32_be(input, 0L)
let block_wire = read_u32_be(input, 4L)
let strong_wire = read_u32_be(input, 8L)
match magic {
0x72730147U => ()
0x72730136U | 0x72730137U | 0x72730146U => raise UnsupportedSignatureProfile
_ => raise InvalidSignature
}
guard block_wire != 0U && strong_wire >= 1U && strong_wire <= 32U else {
raise InvalidSignature
}
// strong_wire is already proven to fit; never narrow an unchecked wire u32.
let strong_sum_len = checked_index(strong_wire.to_uint64())
let record_width = 4 + strong_sum_len // bounded by 5..36
let body_len = input_len - 12
guard body_len % record_width == 0 else { raise TruncatedInput }
let record_count = body_len / record_width
let block_len = checked_index(block_wire.to_uint64())
guard block_len.to_int64() <= limits.max_block_bytes else {
raise LimitExceeded
}
guard record_count.to_int64() <= limits.max_signature_records else {
raise LimitExceeded
}
// Validate the greatest nominal offset before any record storage allocation.
// Earlier offsets cannot exceed it: count >= 1 and block_len > 0 here.
if record_count > 0 {
let _ = checked_block_offset(
(record_count - 1).to_uint64(),
block_wire.to_uint64(),
)
}
// Record count and greatest offset are checked before exact slot allocation.
let records : Array[SignatureRecord] = Array(capacity=record_count)
let mut cursor = 12L
for block_index in 0..