Arti uses createfast for one-hop directory fetches but it should use create if it can
In arti/tor-circmgr/src/path.rs we have
OneHop(_) | FallbackOneHop(_) => {
let circ = pcirc.create_firsthop_fast(rng, ¶ms).await?;
Ok(circ)
}
Path(p) => {
let circ = pcirc.create_firsthop_ntor(rng, &p[0], ¶ms).await?;
I.e. if the circuit is a one-hop directory fetching circuit, or a one-hop fallbackdir bootstrap connection, we opt to use createfast. Whereas if it is a 3-hop path then we use a normal create cell for the first hop.
Compare to the logic in C-tor's src/core/or/circuitbuild.c:
fast = should_use_create_fast_for_circuit(circ);
if (!fast) {
/* We know the right onion key: we should send a create cell. */
circuit_pick_create_handshake(&cc.cell_type, &cc.handshake_type,
circ->cpath->extend_info);
} else {
/* We don't know an onion key, so we need to fall back to CREATE_FAST. */
cc.cell_type = CELL_CREATE_FAST;
cc.handshake_type = ONION_HANDSHAKE_TYPE_FAST;
}
where that should_use_create_fast_for_circuit() essentially checks whether we have an onion key (ntor or tap) for the hop we're extending to.
That is, the choice of create vs create_fast is all about whether we have an onion key for that first hop, not about how many hops our circuit is going to be.
We made the shift to prefer create everywhere we can, in proposal 221, "Stop using CREATE_FAST", and in tor#9386 (closed).