# Interactions in plonky3 In the valida/sp1 architecture, STARKs communicate with each other through a bus. This communication is defined as a set of interactions that a STARK sends or receives to a bus. These interactions are compiled to multiset checks and are constrained using logUp. ```rust pub trait Chip<F: Field> { fn sends(&self) -> Vec<Interaction<F>>; fn receives(&self) -> Vec<Interaction<F>>; } ``` An interaction is defined as: ```rust pub struct Interaction<F: Field> { pub fields: Vec<VirtualPairCol<F>>, pub count: VirtualPairCol<F>, pub argument_index: usize, } ``` Each interaction consists of: 1. `fields`: Specifies the `VirtualPairCol`s that are involved in the interaction 2. `count`: Specifies the multiplicity of each row in the interaction 3. `argument_index`: A unique integer given to each bus A `VirtualPairCol` is a linear function over a set of columns of the form $f(\textbf{C}) = b + \sum w_i C_i$. ```rust pub struct VirtualPairCol<F: Field> { column_weights: Vec<(PairCol, F)>, constant: F, } ``` Each interaction adds a new column to the permutation trace. Let the bus index be $b$ and let $f_k(\textbf{C}_k)$ be the $k$th field of an interaction. The added column would then be: $$ P = \frac{1}{\alpha^{b} + \sum_k \beta^k \cdot f_k(\textbf{C}_k)} $$ Finally, the values of each added column are combined to form a new partial sum column where each row is calculated as: $$ S[i] = S[i-1] + \sum_{j\in sends} m_j[i] * P_j[i] - \sum_{j\in receives} m_j[i] * P_j[i] $$ Here, $m_j$ specifies the count/multiplicity of the interaction The last value of the partial sum column gives a single `cumulative_sum` value that summarizes all the interactions involved in a STARK. If each "send" from a STARK is paired with a "receive" from another STARK, then the `cumulative_sum` values across all STARKs will add up to zero. This is checked by the verifier. ##### Why use `VirtualPairCol` instead of specifying a single Column for the interaction? A case where this is useful is when one STARK stores a value represented as a byte while the other STARK stores the value as bits spread across 8 columns. A `VirtualPairCol` can be used to create a "virtual" column that linearly combines the bit columns from the second STARK to get a byte value. This byte value can then be matched with the byte value from the first STARK.