An execution trace is a 2D matrix where rows are time steps and columns are algebraic registers. While you can implement the Trace trait on any custom struct, Winterfell provides the TraceTable struct for convenience.
Option 1: Manual Initialization
Use TraceTable::init() by passing a set of vectors, where each vector represents a column.
Requirements:
- All columns must have the same length.
- The length must be a power of two.
Option 2: Functional Initialization (Recommended)
Use TraceTable::new(width, length) to allocate memory, then use the fill() method. fill() takes two closures:
- An initializer for the first row (the initial state).
- A state transition function that receives the previous state and updates it to the next state.
This approach is simpler and facilitates concurrent trace generation.
// Example concept for TraceTable initialization
let mut trace = TraceTable::new(width, length);
trace.fill(
|| { /* initialize first row */ },
|prev_state| { /* compute next state from prev_state */ }
);