88 "encoding/json"
99 "errors"
1010 "fmt"
11+ "math/bits"
1112 "time"
1213
1314 "github.com/cartesi/rollups-node/pkg/emulator"
@@ -28,6 +29,7 @@ type RemoteMachineInterface interface {
2829 Delete ()
2930 ForkServer () (* emulator.RemoteMachine , string , uint32 , error )
3031 ShutdownServer () error
32+ CollectMCycleRootHashes (mcycleEnd , log2McyclePeriod , mcyclePhase uint64 , log2BundleMcycleCount int32 , previousBackTree string ) ([]byte , error )
3133}
3234
3335type proofJson struct {
@@ -230,10 +232,82 @@ func (e *LibCartesiBackend) CmioRxBufferSize() uint64 {
230232 return 1 << emulator .CmioRxBufferLog2Size
231233}
232234
235+ func decodeBreakReason (s string ) BreakReason {
236+ switch s {
237+ case "yielded_automatically" :
238+ return YieldedAutomatically
239+ case "yielded_manually" :
240+ return YieldedManually
241+ case "yielded_softly" :
242+ return YieldedSoftly
243+ case "reached_target_mcycle" :
244+ return ReachedTargetMcycle
245+ case "halted" :
246+ return Halted
247+ case "failed" :
248+ return Failed
249+ default :
250+ return Failed
251+ }
252+ }
253+
233254func (e * LibCartesiBackend ) RunAndCollectRootHashes (
234255 mcycleEnd uint64 ,
235256 state * HashCollectorState ,
236257 timeout time.Duration ,
258+ ) (reason BreakReason , err error ) {
259+ return e .RunAndCollectRootHashesNew (mcycleEnd , state , timeout )
260+ //return e.RunAndCollectRootHashesOld(mcycleEnd, state, timeout)
261+ }
262+
263+ func (e * LibCartesiBackend ) RunAndCollectRootHashesNew (
264+ mcycleEnd uint64 ,
265+ state * HashCollectorState ,
266+ timeout time.Duration ,
267+ ) (reason BreakReason , err error ) {
268+
269+ // v0.21 API expects log2(mcycle_period) instead of the raw period value
270+ // Use exact integer arithmetic: for powers of 2, log2 = position of highest set bit
271+ log2Period := uint64 (bits .Len64 (state .Period ) - 1 )
272+ if (1 << log2Period != state .Period ) {
273+ return Failed , fmt .Errorf ("period must be a power of 2, got %v." , state .Period )
274+ }
275+
276+ rawResult , err := e .inner .CollectMCycleRootHashes (mcycleEnd , log2Period , state .Phase , state .BundleLog2 , "" )
277+ if err != nil {
278+ return Failed , err
279+ }
280+
281+ result := struct {
282+ RootHashes []string `json:"hashes"`
283+ MCyclePhase uint64 `json:"mcycle_phase"`
284+ BreakReason string `json:"break_reason"`
285+ BackTree json.RawMessage `json:"back_tree,omitempty"`
286+ }{}
287+ err = json .Unmarshal (rawResult , & result )
288+ if err != nil {
289+ return Failed , errors .New ("failed to unmarshal CollectMCycleRootHashes result" )
290+ }
291+
292+ // convert from base64
293+ for i , base64Hash := range result .RootHashes {
294+ rawHash , err := base64 .StdEncoding .DecodeString (base64Hash )
295+ if err != nil {
296+ return Failed , err
297+ }
298+ if len (rawHash ) != HashSize {
299+ return Failed , fmt .Errorf ("received an invalid hash during RunAndCollectRootHashes at index %v, with value: %v." , i , base64Hash )
300+ }
301+ state .Hashes = append (state .Hashes , (Hash )(rawHash ))
302+
303+ }
304+ return decodeBreakReason (result .BreakReason ), nil
305+ }
306+
307+ func (e * LibCartesiBackend ) RunAndCollectRootHashesOld (
308+ mcycleEnd uint64 ,
309+ state * HashCollectorState ,
310+ timeout time.Duration ,
237311) (reason BreakReason , err error ) {
238312 if state == nil {
239313 return Failed , errors .New ("nil state" )
0 commit comments