The problem is that in assign_virtual_table_to_raw it was using assign_virtual_to_raw, which has the following danger:
It will "assign" a virtual cell to a raw Halo2 cell by inserting the assignment into the HashMap of assigned_advices. However later the BaseCircuitBuilderraw_assign might overwrite this assignment without adding any real equality constraints. Therefore the first raw cell becomes a dangling unconstrained cell.
The fix is that now assign_virtual_table_to_raw uses constrain_virtual_equals_external, and we have modified constrain_virtual_equals_external so that it checks whether the virtual cell has already been assigned or not. It is only allowed to not have been assigned if the type_id of the virtual cell was marked as EXTERNAL_CELL_TYPE_ID. This marks the virtual cell as safe from ever being reassigned by a different virtual region manager.
If the virtual cell is already assigned to a raw cell, we constrain equality between the raw cell and the new external cell.
If the virtual cell has not been assigned and is marked EXTERNAL_CELL_TYPE_ID, then we assign the virtual cell to the new external cell.
The usage in the latter case is demonstrated in the memory.rs test.
We add a check whenever we do assigned_advice.insert that there was not already a cell present or that the occupied raw cell equals the raw cell to be inserted (this latter case is just because keygen_vk and keygen_pk each call synthesize and we cannot call clear because of mutable borrows).
The problem is that in
assign_virtual_table_to_raw
it was usingassign_virtual_to_raw
, which has the following danger:HashMap
ofassigned_advices
. However later theBaseCircuitBuilder
raw_assign
might overwrite this assignment without adding any real equality constraints. Therefore the first raw cell becomes a dangling unconstrained cell.The fix is that now
assign_virtual_table_to_raw
usesconstrain_virtual_equals_external
, and we have modifiedconstrain_virtual_equals_external
so that it checks whether the virtual cell has already been assigned or not. It is only allowed to not have been assigned if thetype_id
of the virtual cell was marked asEXTERNAL_CELL_TYPE_ID
. This marks the virtual cell as safe from ever being reassigned by a different virtual region manager.EXTERNAL_CELL_TYPE_ID
, then we assign the virtual cell to the new external cell.The usage in the latter case is demonstrated in the
memory.rs
test.We add a check whenever we do
assigned_advice.insert
that there was not already a cell present or that the occupied raw cell equals the raw cell to be inserted (this latter case is just becausekeygen_vk
andkeygen_pk
each callsynthesize
and we cannot callclear
because of mutable borrows).