jiebi/TextFlow huggingface dataset:
Original text:
4.1. <del> Long headers take the form described in fig-long.  Bits that have version-specific semantics are marked with an X. </del>  A QUIC packet with a long header has the high bit of the first byte set to 1.  All other bits in that byte are version specific. 4.2. <del> Short headers take the form described in fig-short.  Bits that have version-specific semantics are marked with an X. </del>  A QUIC packet with a short header has the high bit of the first byte set to 0.

Reviewer comments:
Happened to notice that the updated figure (didn't check the old one) was inconsistent with the text about the allowed length of the CID fields. Should be editorial, since the text wins any conflicts.
Bah, yes, 255 bytes = 2,040 bits.
:D That's exactly the process that my mind followed.
Both section 4.2 and 4.3 say Unfortunately, the doesn't have Xs. I'm not sure how to reword this to support both formats.
how about :)
I think this was fixed by URL, I dont know if that was just a coincidence or it was untagged
That was intentional. I just neglected to tag this.

Revised text:
4.1.  <ins> Long headers take the form described in fig-long. </ins> A QUIC packet with a long header has the high bit of the first byte set to 1.  All other bits in that byte are version specific. 4.2.  <ins> Short headers take the form described in fig-short. </ins> A QUIC packet with a short header has the high bit of the first byte set to 0.
Original text:
preferred_address transport parameter. An endpoint SHOULD ensure that its peer has a sufficient number of <del> available and unused connection IDs.  Endpoints store received connection IDs for future use and advertise the number of connection IDs they are willing to store with the active_connection_id_limit transport parameter.  An endpoint MUST NOT provide more connection IDs than the peer's limit.  An endpoint that receives more connection IDs than its advertised active_connection_id_limit MUST close the connection with an error of type CONNECTION_ID_LIMIT_ERROR. </del>  An endpoint SHOULD supply a new connection ID when the peer retires a connection ID.  If an endpoint provided fewer connection IDs than the

Reviewer comments:
The rules for the active connection ID limit were such that the brief bump that NEWCONNECTIONID + Retire Prior To could add was not permitted. Strictly speaking, if you requested retirement, the connection IDs that you requested be retired are still active until you receive a RETIRECONNECTIONID frame. That means that you were technically violating this MUST in the spec. Adding an exception for this case was the best way I could see to fix this. The other was to change the definition of "active connection ID". I tried that and, while it was a smaller change, it made the definition less crisp. This approach seems best. (This is not new normative requirements as this is already .)
LGTMThanks for making (yet) another attempt to clarify this. Looks good.

Revised text:
preferred_address transport parameter. An endpoint SHOULD ensure that its peer has a sufficient number of  <ins> available and unused connection IDs.  Endpoints advertise the number of active connection IDs they are willing to maintain using the active_connection_id_limit transport parameter.  An endpoint MUST NOT provide more connection IDs than the peer's limit.  An endpoint MAY send connection IDs that temporarily exceed a peer's limit if the NEW_CONNECTION_ID frame also requires the retirement of any excess, by including a sufficiently large value in the Retire Prior To field. A NEW_CONNECTION_ID frame might cause an endpoint to add some active connection IDs and retire others based on the value of the Retire Prior To field.  After processing a NEW_CONNECTION_ID frame and adding and retiring active connection IDs, if the number of active connection IDs exceeds the value advertised in its active_connection_id_limit transport parameter, an endpoint MUST close the connection with an error of type CONNECTION_ID_LIMIT_ERROR. </ins> An endpoint SHOULD supply a new connection ID when the peer retires a connection ID.  If an endpoint provided fewer connection IDs than the
Original text:
A Probe Timeout (PTO) triggers sending one or two probe datagrams when ack-eliciting packets are not acknowledged within the expected <del> period of time or the handshake has not been completed.  A PTO enables a connection to recover from loss of tail packets or acknowledgements. </del>  As with loss detection, the probe timeout is per packet number space. The PTO algorithm used in QUIC implements the reliability functions Sending different payloads each time reduces the chances of spurious retransmission. <del> 5.2.5. Delivery or loss of packets in flight is established when an ACK frame is received that newly acknowledges one or more packets. A PTO timer expiration event does not indicate packet loss and MUST NOT cause prior unacknowledged packets to be marked as lost.  When an acknowledgement is received that newly acknowledges packets, loss detection proceeds as dictated by packet and time threshold mechanisms; see ack-loss-detection. </del> 5.3. A Retry packet causes a client to send another Initial packet,

Reviewer comments:
The fact that PTO doesn't declare losses when it expires is quite important. It at the very end of the section, so I moved it to the first part. Also removed a section heading(pto-loss) which was never referenced.
A reasonable simplification.

Revised text:
A Probe Timeout (PTO) triggers sending one or two probe datagrams when ack-eliciting packets are not acknowledged within the expected  <ins> period of time or the server may not have validated the client's address.  A PTO enables a connection to recover from loss of tail packets or acknowledgements. A PTO timer expiration event does not indicate packet loss and MUST NOT cause prior unacknowledged packets to be marked as lost.  When an acknowledgement is received that newly acknowledges packets, loss detection proceeds as dictated by packet and time threshold mechanisms; see ack-loss-detection. </ins> As with loss detection, the probe timeout is per packet number space. The PTO algorithm used in QUIC implements the reliability functions Sending different payloads each time reduces the chances of spurious retransmission.  5.3. A Retry packet causes a client to send another Initial packet,
Original text:
This document does not specify a pacer, but it is RECOMMENDED that a sender pace sending of all in-flight packets based on input from the <del> congestion controller.  For example, a pacer might distribute the congestion window over the smoothed RTT when used with a window-based controller, or a pacer might use the rate estimate of a rate-based controller. </del>  An implementation should take care to architect its congestion controller to work well with a pacer.  For instance, a pacer might Practical considerations, such as packetization, scheduling delays, and computational efficiency, can cause a sender to deviate from this rate over time periods that are much shorter than a round-trip time. <del> Sending multiple packets into the network without any delay between them creates a packet burst that might cause short-term congestion and losses.  Implementations MUST either use pacing or limit such bursts to the initial congestion window; see initial-cwnd. </del> One possible implementation strategy for pacing uses a leaky bucket algorithm, where the capacity of the "bucket" is limited to the

Reviewer comments:
I prefer to have MUSTs towards the top of sections when possible so they're not missed. This is a follow-on from
I'm not a fan of this change -- I think there's value in having that text below where we talk about how bursts can occur. That said, I don't feel strongly about it, so I'm not going to fight for it.

Revised text:
This document does not specify a pacer, but it is RECOMMENDED that a sender pace sending of all in-flight packets based on input from the  <ins> congestion controller.  Sending multiple packets into the network without any delay between them creates a packet burst that might cause short-term congestion and losses.  Implementations MUST either use pacing or another method to limit such bursts to the initial congestion window; see initial-cwnd. </ins> An implementation should take care to architect its congestion controller to work well with a pacer.  For instance, a pacer might Practical considerations, such as packetization, scheduling delays, and computational efficiency, can cause a sender to deviate from this rate over time periods that are much shorter than a round-trip time.  One possible implementation strategy for pacing uses a leaky bucket algorithm, where the capacity of the "bucket" is limited to the
Original text:
attacker is able to successfully forge a packet; see AEBounds and ROBUST.  For AEAD_AES_128_GCM, AEAD_AES_256_GCM, and AEAD_CHACHA20_POLY1305, the limit on the number of packets that fail authentication is 2^36. Note that the analysis in AEBounds supports a higher limit for the

Reviewer comments:
This is an update to , so check where it is being merged to carefully.
I'm going to merge this into the other PR.
NAME pointed out to me that when you receive junk (i.e., unauthenticated) packets, the odds are that these will be distributed evenly between the "current" packet protection keys and the "next" packet protection keys, as the key phase bit will be nearly random if they are true forgeries. The result is that an endpoint that approaches the integrity limit on key usage will update to the next packet protection keys and find that those keys will have similar amounts of authentication failures. That might lead to needing two updates in quick succession. That isn't fatal, but if the timing is tight, then more time might be needed for an update. We might say that endpoints shouldn't be calculating the forgery rate and trying to delay updates as late as possible, nor should they be allowing that many forgeries without doing anything but react with key updates. However, as a matter of good hygiene, it's worth saying something about this. Taking this as an editorial follow-on to .
Integrated into .

Revised text:
attacker is able to successfully forge a packet; see AEBounds and ROBUST. <ins> Due to the way that header protection protects the Key Phase, packets that are discarded are likely to have an even distribution of both Key Phase values.  This means that packets that fail authentication will often use the packet protection keys from the next key phase.  It is therefore necessary to also track the number of packets that fail authentication with the next set of packet protection keys.  To avoid exhaustion of both sets of keys, it might be necessary to initiate two key updates in succession. </ins> For AEAD_AES_128_GCM, AEAD_AES_256_GCM, and AEAD_CHACHA20_POLY1305, the limit on the number of packets that fail authentication is 2^36. Note that the analysis in AEBounds supports a higher limit for the
Original text:
connection ID values in transport parameters and verifying them ensures that that an attacker cannot influence the choice of connection ID for a successful connection by injecting packets <del> carrying attacker-chosen connection IDs during the handshake.  An endpoint MUST treat any of the following as a connection error of type PROTOCOL_VIOLATION: </del>  <del> absence of the initial_source_connection_id transport parameter from either endpoint, </del>  <del> absence of the original_destination_connection_id transport parameter from the server, </del>  absence of the retry_source_connection_id transport parameter from the server after receiving a Retry packet,

Reviewer comments:
As discussed in URL, most of the errors that can occur when authenticating connection IDs should be TRANSPORTPARAMETERERRORs, not PROTOCOL_VIOLATIONs.
This changes the error codes that we require, so it is technically a design change. I think we'll need an issue to track this.
NAME Created .
The guiding principle here (as we apply it for FRAMEENCODINGERRORs) is that if an error is detectable without accessing connection state, we use the more specific error. So for example, since and are required transport parameters, their absence should be responded to with a TRANSPORTPARAMETERERROR. A similar argument applies to the absence of the TP, although I can see how one might use PROTOCOLVIOLATION here (note that this is still valid behavior with this PR, as every more specific error can be replaced with a PROTOCOL_VIOLATION, if an implementation wishes to do so).
Thanks. I think that this is fine. I will make a few editorial comments on the PR, but I think that the application of the agreed principles is correct.
If you take the suggestions here, I will mark this for inclusion in the next consensus call. (Otherwise, we should continue discussion.)

Revised text:
connection ID values in transport parameters and verifying them ensures that that an attacker cannot influence the choice of connection ID for a successful connection by injecting packets  <ins> carrying attacker-chosen connection IDs during the handshake. </ins>  <ins> An endpoint MUST treat absence of the initial_source_connection_id transport parameter from either endpoint or absence of the original_destination_connection_id transport parameter from the server as a connection error of type TRANSPORT_PARAMETER_ERROR. </ins>  <ins> An endpoint MUST treat the following as a connection error of type TRANSPORT_PARAMETER_ERROR or PROTOCOL_VIOLATION: </ins> absence of the retry_source_connection_id transport parameter from the server after receiving a Retry packet,
Original text:
This document defines QUIC version 1, which conforms to the protocol invariants in QUIC-INVARIANTS.  1.2. The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",

Reviewer comments:
I don't see much point in doing the same for invariants, but I'm willing to take input on that choice.
The chairs just had a question from someone who wanted to cite "QUIC" on what document they should be citing. We responded that they should cite -transport, since we see this as the central document. Should we add brief notes to the documents saying "if you want to cite QUIC, cite -transport"?
That seems reasonable, since we say in there that accompanying documents describe TLS and recovery. Where are you thinking of adding that note?
As early as possible?
If you want to cite QUIC version 1, transport. If you want to cite QUIC all-up, invariants.
, or immediately after it, seems like as good a place as any.
I probably would have made it part of the preceding paragraph, but I don't feel strongly.

Revised text:
This document defines QUIC version 1, which conforms to the protocol invariants in QUIC-INVARIANTS. <ins> To refer to QUIC version 1, cite this document.  References to the limited set of version-independent properties of QUIC can cite QUIC- INVARIANTS. </ins> 1.2. The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
Original text:
RFC3629. The application-specific variant of CONNECTION_CLOSE (type 0x1d) can <del> only be sent using 0-RTT or 1-RTT packets (QUIC-TLS, Section 4). </del>  When an application wishes to abandon a connection during the handshake, an endpoint can send a CONNECTION_CLOSE frame (type 0x1c) with an error code of APPLICATION_ERROR in an Initial or a Handshake

Reviewer comments:
The longer the draft sits in my edit buffer, the more opportunities I have to see this sort of thing.

Revised text:
RFC3629. The application-specific variant of CONNECTION_CLOSE (type 0x1d) can  <ins> only be sent using 0-RTT or 1-RTT packets; see Section 4 of QUIC-TLS. </ins> When an application wishes to abandon a connection during the handshake, an endpoint can send a CONNECTION_CLOSE frame (type 0x1c) with an error code of APPLICATION_ERROR in an Initial or a Handshake
Original text:
fig-auth-cid-retry shows a similar handshake that includes a Retry packet. <del> For the handshakes in fig-auth-cid and fig-auth-cid-retry the client sets the value of the initial_source_connection_id transport parameter to "C1".  In fig-auth-cid-retry, the server sets original_destination_connection_id to "S1", </del>  retry_source_connection_id to "S2", and initial_source_connection_id <del> to "S3".  In fig-auth-cid, the server sets original_destination_connection_id to "S1", initial_source_connection_id to "S3", and does not include retry_source_connection_id.  Each endpoint validates the transport parameters set by their peer, including the client confirming that retry_source_connection_id is absent if no Retry packet was processed. </del>  7.4.

Reviewer comments:
An attempt to make this slightly easier to read, based on feedback that this was hard to read and follow.
Looks good, but I think the paragraph on lines 1574 to 1582 might be best split too, into sub-paragraphs for each TP and how it's used.

Revised text:
fig-auth-cid-retry shows a similar handshake that includes a Retry packet.  <ins> In both cases (fig-auth-cid and fig-auth-cid-retry), the client sets the value of the initial_source_connection_id transport parameter to "C1". When the handshake does not include a Retry (fig-auth-cid), the server sets original_destination_connection_id to "S1" and initial_source_connection_id to "S3".  In this case, the server does not include a retry_source_connection_id transport parameter. When the handshake includes a Retry (fig-auth-cid-retry), the server sets original_destination_connection_id to "S1", </ins> retry_source_connection_id to "S2", and initial_source_connection_id  <ins> to "S3". Each endpoint validates transport parameters set by the peer.  The client confirms that the retry_source_connection_id transport parameter is absent if it did not process a Retry packet. </ins> 7.4.
Original text:
generally, this is one higher than the offset of the byte with the largest offset sent on the stream, or zero if no bytes were sent. <del> For a stream that is reset, the final size is carried explicitly in a RESET_STREAM frame.  Otherwise, the final size is the offset plus the length of a STREAM frame marked with a FIN flag, or 0 in the case of incoming unidirectional streams. </del>  An endpoint will know the final size for a stream when the receiving part of the stream enters the "Size Known" or "Reset Recvd" state

Reviewer comments:
Section: Stream Final Size /An endpoint MUST NOT send data on a stream at or beyond the final size./ It seems reasonable not to send after the Final Size , but why is this a “MUST NOT”? The need to require this is not stated, and the reaction of the receiver appears to be ignore. Is this requirement justified?
Because the Final Size is used to synchronize flow control consumption. If the Final Size is not, in fact, the last data ever sent on a stream, the two sides will disagree about how much flow control credit has been consumed. The reaction of the receiver isn't to ignore; in the very next paragraph:
Aha, I knew there must be a reason - could we add something like this sentence? "This is used to synchronize flow control consumption between the endpoints."
:+1: LGTM modulo a nitpick.Some suggestions

Revised text:
generally, this is one higher than the offset of the byte with the largest offset sent on the stream, or zero if no bytes were sent.  <ins> The final size of a stream is always signaled to the recipient.  The final size is the sum of the Offset and Length fields of a STREAM frame with a FIN flag, noting that these fields might be implicit. Alternatively, the Final Size field of a RESET_STREAM frame carries this value.  This ensures that all ways that a stream can be closed result in the number of bytes on the stream being reliably transmitted.  This guarantees that both endpoints agree on how much flow control credit was consumed by the stream. </ins> An endpoint will know the final size for a stream when the receiving part of the stream enters the "Size Known" or "Reset Recvd" state
Original text:
A sender bundles one or more frames in a QUIC packet; see frames. A sender can minimize per-packet bandwidth and computational costs by <del> bundling as many frames as possible within a QUIC packet.  A sender MAY wait for a short period of time to bundle multiple frames before </del>  sending a packet that is not maximally packed, to avoid sending out large numbers of small packets.  An implementation MAY use knowledge about application sending behavior or heuristics to determine whether across multiple streams.  When a packet loss occurs, only streams with data in that packet are blocked waiting for a retransmission to be received, while other streams can continue making progress.  Note <del> that when data from multiple streams is bundled into a single QUIC </del>  packet, loss of that packet blocks all those streams from making <del> progress.  Implementations are advised to bundle as few streams as </del>  necessary in outgoing packets without losing transmission efficiency to underfilled packets.

Reviewer comments:
We didn't really need to use a new "term" for the concept of including multiple frames in a packet. The use of "bundle" implied more than what was really happening. Using plain words is probably better.
What does “bundling” refer to? I think I might now understand coalescing, but I don’t understand if bundling is subtly different?
Several instances I see in the draft refer to the situation where an endpoint is required to send a packet containing certain frames. The endpoint might opportunistically add other frames, not mandated to be sent, as long as it's doing the work of generating and sending a packet anyway. These opportunistically added frames are "bundled" with the mandatory frames. More generally, the term refers to selecting a collection of frames waiting to be sent when generating an outgoing packet.
(Versus coalescing, which is putting more than one packet in a single UDP datagram.)
tbh, I think the text reads a lot better with bundling.Thanks! Clearer is better.

Revised text:
A sender bundles one or more frames in a QUIC packet; see frames. A sender can minimize per-packet bandwidth and computational costs by  <ins> including as many frames as possible in each QUIC packet.  A sender MAY wait for a short period of time to collect multiple frames before </ins> sending a packet that is not maximally packed, to avoid sending out large numbers of small packets.  An implementation MAY use knowledge about application sending behavior or heuristics to determine whether across multiple streams.  When a packet loss occurs, only streams with data in that packet are blocked waiting for a retransmission to be received, while other streams can continue making progress.  Note  <ins> that when data from multiple streams is included in a single QUIC </ins> packet, loss of that packet blocks all those streams from making  <ins> progress.  Implementations are advised to include as few streams as </ins> necessary in outgoing packets without losing transmission efficiency to underfilled packets.