diff --git a/README.md b/README.md index 476c4d6..c242c3b 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,24 @@ the shipped config sets `max_authentication_rescan_times` to 0, because at the stock budget a wrong finger never yields a terminal frame and a PAM client waits forever for the `verify-no-match` it needs. +**Template learning is implemented and OFF, because it makes matching worse on +this hardware.** Measured, with learning disabled during each measurement so +nothing moved underneath the numbers: + +| template | folds | rate | +|---|---|---| +| fresh 20-sample enrolment | 0 | **30/30** | +| same lineage, later | 40 | 12/15 | +| same lineage, later still | 185 | total failure | + +The frames one press contributes are near-duplicates of a single image from one +finger position. Folding them spends the template's 96 slots on that position +and evicts the diversity the enrolment put there. There is no upside to weigh +against it either: a plain enrolment already measures 30/30, and learning has +never once been observed to raise a rate under controlled conditions. + +`--learn=1` enables it for experiments. What follows describes how it works. + **Template learning.** Stock rewrites the stored template on every successful press — `0x1015 UPDATE_TEMPLATE` while the finger is still down, then a deferred `SAVE_DATA` — and the stored body measurably grows over a template's life diff --git a/implementations/main.cpp b/implementations/main.cpp index 336c33a..0cf6063 100644 --- a/implementations/main.cpp +++ b/implementations/main.cpp @@ -117,12 +117,30 @@ bool g_irqObserve = false; bool g_edgeWake = false; // TEMPLATE LEARNING: fold the frames of a successful press back into the -// stored template, as stock does. On by default because stock does it and -// because every match rate this project has measured was taken against a -// day-zero template; `--learn=0` turns it off so the two can be compared on -// one binary without a rebuild, which is the only way the comparison is -// single-variable. -bool g_learn = true; +// stored template, as stock does. +// +// OFF by default, and that is a measured decision rather than caution. Stock +// does it, this daemon can do it, and on this hardware it makes matching WORSE: +// +// fresh template, 0 folds 30/30 (two consecutive blocks of 15) +// same lineage, 40 folds 12/15 +// same lineage, 185 folds total failure, 108 consecutive rejections +// +// all measured with learning switched off during the measurement itself, so +// nothing moved underneath the numbers. The mechanism is that the frames one +// press contributes are near-duplicates of a single image from one finger +// position, so folding them spends the template's slots -- 96 of them -- on +// that position and evicts the diversity a 20-sample enrolment put there. +// +// And there is no upside to weigh against it: a plain enrolment measures 30/30, +// so there is nothing for learning to improve. It has never once been observed +// to raise a rate under controlled conditions; the one run that suggested it +// did was confounded by a freshly wiped sensor and a user learning the +// technique, both spotted by Jorijn at the time. +// +// `--learn=1` turns it on for experiments. The code stays because the finding +// is about THIS trustlet's algorithm, not about the idea. +bool g_learn = false; // Dump the trustlet's own log out of the response buffer after every command. // See DumpTaLog: on pmOS this is the ONLY way to read it. bool g_taLog = false;