Code change:
2.2.1. <del> Given: </del> <ins> Given the following inputs: </ins> <del> "digest-value", an array of bits </del> <ins> "URL" a string corresponding to the Effective Request URI (RFC7230, Section 5.5) of a cached response RFC7234. </ins> <del> "URL", an array of characters </del> <ins> "ETag" a string corresponding to the entity-tag RFC7232 of a cached response RFC7234 (if the ETag is available; otherwise, null). </ins> <del> "ETag", an array of characters </del> <ins> "digest-value", an array of bits. Let "f" be the value of the first byte of "digest-value". Let "b" be the bucket size, defined as 4. </ins> <del> "validators", a boolean </del> <ins> Let "N" be the value of the second to fifth bytes of "digest- value" in big endian form. </ins> <del> we can determine whether there is a match in the digest using the following algorithm: </del> <ins> Let "key" be the return value of key with "URL" and "ETag" as inputs. </ins> <del> Read the first 5 bits of "digest-value" as an integer; let "N" be two raised to the power of that value. </del> <ins> Let "h1" be the return value of hash with "key" and "N" as inputs. </ins> <del> Read the next 5 bits of "digest-value" as an integer; let "P" be two raised to the power of that value. </del> <ins> Let "fingerprint" be the return value of fingerprint with "key" and "f" as inputs. </ins> <del> Let "hash-value" be the result of computing a hash value (hash). </del> <ins> Let "fingerprint-string" be the value of "fingerprint" in base 10, expressed as a string. </ins> <del> Let "C" be -1. </del> <ins> Let "h2" be the return value of hash with "fingerprint" and "N" as inputs, XORed with "h1". </ins> <del> Read '0' bits from "digest-value" until a '1' bit is found; let "Q" be the number of '0' bits.  Discard the '1'. </del> <ins> Let "h" be "h1". </ins> <del> Read log2("P") bits from "digest-value" after the '1' as an integer; let "R" be its value. </del> <ins> Let "position_start" be 40 + "h" * "f" * "b". </ins> <del> Let "D" be "Q" * "P" + "R". </del> <ins> Let "position_end" be "position_start" + "f" * "b". </ins> <del> Increment "C" by "D" + 1. </del> <ins> While "position_start" < "position_end": </ins> <del> If "C" is equal to "hash-value", return 'true'. </del> <ins> Let "bits" be "f" bits from "digest_value" starting at "position_start". </ins> <del> Otherwise, return to step 5 and continue processing; if no match is found before "digest-value" is exhausted, return 'false'. </del> <ins> If "bits" is "fingerprint", return true Add "f" to "position_start". Return false. </ins> 3. <ins> A Client SHOULD notify its support for CACHE_DIGEST frames by sending the SENDING_CACHE_DIGEST (0xXXX) SETTINGS parameter. The value of the parameter is a bit-field of which the following bits are defined: DIGEST_PENDING (0x1): When set it indicates that the client has a digest to send, and the server may choose to wait for a digest in order to make server push decisions. Rest of the bits MUST be ignored and MUST be left unset when sending. The initial value of the parameter is zero (0x0) meaning that the client has no digest to send the server. 4. </ins> A server can notify its support for CACHE_DIGEST frame by sending the ACCEPT_CACHE_DIGEST (0x7) SETTINGS parameter.  If the server is tempted to making optimizations based on CACHE_DIGEST frames, it

Related discussion:
text: The 35 collisions are on top of the false positive rates, and represents resources that we failed to put into the table to begin with (due to both their buckets being full). That rate of collisions seems high compared to the results in the paper, so I need to dig further to see who's wrong...
The collisions are now fixed. It was an algorithm issue, where the entry to be pushed was always the same one at the end of the bucket. I've change that to be a random fingerprint from the bucket, which significantly improved things. The ref implementation is now collision free almost up to the point where the digest is full.