From 4e030dd93cf000a2023a13d1812cbb5afda8fcdc Mon Sep 17 00:00:00 2001 From: Matt Black Date: Sat, 27 Jun 2026 06:29:59 -0500 Subject: [PATCH] fix: add backward compat for DlcOffer without protocol_version Re-introduces the heuristic for detecting old-format DlcOffer messages that lack the protocol_version field (pre-dlcspecs PR #163). The previous heuristic (removed in #237) incorrectly required contract_flags === 0, which broke when contract_flags is 0x01 (refund-to-accepter). This version only checks whether the first 4 bytes are a plausible protocol_version (1-10), matching the Rust implementation in dlcdevkit. --- packages/messaging/lib/messages/DlcOffer.ts | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/packages/messaging/lib/messages/DlcOffer.ts b/packages/messaging/lib/messages/DlcOffer.ts index 13dd97f5..defa01d1 100644 --- a/packages/messaging/lib/messages/DlcOffer.ts +++ b/packages/messaging/lib/messages/DlcOffer.ts @@ -127,8 +127,23 @@ export class DlcOffer implements IDlcMessage { ); } - // Read protocol_version as 4 bytes (u32) as per dlcspecs PR #163 - instance.protocolVersion = reader.readUInt32BE(); + // BACKWARD COMPATIBILITY: Detect old vs new format + // New format: [type][protocol_version: 4 bytes][contract_flags: 1 byte][chain_hash: 32 bytes] + // Old format: [type][contract_flags: 1 byte][chain_hash: 32 bytes] + // + // Heuristic: peek first 4 bytes as u32. In new format this is protocol_version (1-10). + // In old format these are contract_flags (0x00/0x01) + first 3 chain_hash bytes, + // which always produces values outside 1-10 for any Bitcoin network. + const peekBuf = Buffer.from( + reader.buffer.subarray(reader.position, reader.position + 4), + ); + const possibleProtocolVersion = new BufferReader(peekBuf).readUInt32BE(); + + if (possibleProtocolVersion >= 1 && possibleProtocolVersion <= 10) { + instance.protocolVersion = reader.readUInt32BE(); + } else { + instance.protocolVersion = 1; + } instance.contractFlags = reader.readBytes(1); instance.chainHash = reader.readBytes(32);