mirror of
https://github.com/Kpa-clawbot/meshcore-analyzer.git
synced 2026-04-26 13:27:21 +00:00
## Problem The firmware computes packet content hash as: ``` SHA256(payload_type_byte + [path_len for TRACE] + payload) ``` Where `payload_type_byte = (header >> 2) & 0x0F` — just the payload type bits (2-5). CoreScope was using the **full header byte** in its hash computation, which includes route type bits (0-1) and version bits (6-7). This meant the same logical packet produced different content hashes depending on route type — breaking dedup and packet lookup. **Firmware reference:** `Packet.cpp::calculatePacketHash()` uses `getPayloadType()` which returns `(header >> PH_TYPE_SHIFT) & PH_TYPE_MASK`. ## Fix - Extract only payload type bits: `payloadType := (headerByte >> 2) & 0x0F` - Include `path_len` byte in hash for TRACE packets (matching firmware behavior) - Applied to both `cmd/server/decoder.go` and `cmd/ingestor/decoder.go` ## Tests Added - **Route type independence:** Same payload with FLOOD vs DIRECT route types produces identical hash - **TRACE path_len inclusion:** TRACE packets with different `path_len` produce different hashes - **Firmware compatibility:** Hash output matches manual computation of firmware algorithm ## Migration Impact Existing packets in the DB have content hashes computed with the old (incorrect) formula. Options: 1. **Recompute hashes** via migration (recommended for clean state) 2. **Dual lookup** — check both old and new hash on queries (backward compat) 3. **Accept the break** — old hashes become stale, new packets get correct hashes Recommend option 1 (migration) as a follow-up. The volume of affected packets depends on how many distinct route types were seen for the same logical packet. Fixes #786 --------- Co-authored-by: you <you@example.com>
79 lines
2.0 KiB
Go
79 lines
2.0 KiB
Go
package main
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestMigrateContentHashesAsync(t *testing.T) {
|
|
db := setupTestDBv2(t)
|
|
store := NewPacketStore(db, nil)
|
|
|
|
// Insert a packet with a manually wrong hash (simulating old formula).
|
|
rawHex := "0A00D69FD7A5A7475DB07337749AE61FA53A4788E976"
|
|
correctHash := ComputeContentHash(rawHex)
|
|
wrongHash := "deadbeef12345678"
|
|
|
|
_, err := db.conn.Exec(`INSERT INTO transmissions (raw_hex, hash, first_seen, route_type, payload_type)
|
|
VALUES (?, ?, datetime('now'), 0, 2)`, rawHex, wrongHash)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if err := store.Load(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if store.byHash[wrongHash] == nil {
|
|
t.Fatal("expected packet under wrong hash before migration")
|
|
}
|
|
|
|
migrateContentHashesAsync(store, 100, time.Millisecond)
|
|
|
|
if !store.hashMigrationComplete.Load() {
|
|
t.Error("expected hashMigrationComplete to be true")
|
|
}
|
|
if store.byHash[wrongHash] != nil {
|
|
t.Error("old hash should be removed from index")
|
|
}
|
|
if store.byHash[correctHash] == nil {
|
|
t.Error("new hash should be in index")
|
|
}
|
|
|
|
var dbHash string
|
|
err = db.conn.QueryRow("SELECT hash FROM transmissions WHERE raw_hex = ?", rawHex).Scan(&dbHash)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if dbHash != correctHash {
|
|
t.Errorf("DB hash = %s, want %s", dbHash, correctHash)
|
|
}
|
|
}
|
|
|
|
func TestMigrateContentHashesAsync_NoOp(t *testing.T) {
|
|
db := setupTestDBv2(t)
|
|
store := NewPacketStore(db, nil)
|
|
|
|
rawHex := "0A00D69FD7A5A7475DB07337749AE61FA53A4788E976"
|
|
correctHash := ComputeContentHash(rawHex)
|
|
|
|
_, err := db.conn.Exec(`INSERT INTO transmissions (raw_hex, hash, first_seen, route_type, payload_type)
|
|
VALUES (?, ?, datetime('now'), 0, 2)`, rawHex, correctHash)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if err := store.Load(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
migrateContentHashesAsync(store, 100, time.Millisecond)
|
|
|
|
if !store.hashMigrationComplete.Load() {
|
|
t.Error("expected hashMigrationComplete to be true")
|
|
}
|
|
if store.byHash[correctHash] == nil {
|
|
t.Error("hash should remain in index")
|
|
}
|
|
}
|