# 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.