diff --git a/cmd/tvx/extract.go b/cmd/tvx/extract.go index 62314c6f6..06b3d6fe8 100644 --- a/cmd/tvx/extract.go +++ b/cmd/tvx/extract.go @@ -164,7 +164,9 @@ func runExtract(_ *cli.Context) error { g = NewSurgeon(ctx, api, pst) ) - driver := conformance.NewDriver(ctx, schema.Selector{}) + driver := conformance.NewDriver(ctx, schema.Selector{}, conformance.DriverOpts{ + DisableVMFlush: true, + }) // this is the root of the state tree we start with. root := incTs.ParentState() diff --git a/conformance/driver.go b/conformance/driver.go index ee9727cae..fdd4fe3a9 100644 --- a/conformance/driver.go +++ b/conformance/driver.go @@ -33,10 +33,24 @@ var ( type Driver struct { ctx context.Context selector schema.Selector + vmFlush bool } -func NewDriver(ctx context.Context, selector schema.Selector) *Driver { - return &Driver{ctx: ctx, selector: selector} +type DriverOpts struct { + // DisableVMFlush, when true, avoids calling VM.Flush(), forces a blockstore + // recursive copy, from the temporary buffer blockstore, to the real + // system's blockstore. Disabling VM flushing is useful when extracting test + // vectors and trimming state, as we don't want to force an accidental + // deep copy of the state tree. + // + // Disabling VM flushing almost always should go hand-in-hand with + // LOTUS_DISABLE_VM_BUF=iknowitsabadidea. That way, state tree writes are + // immediately committed to the blockstore. + DisableVMFlush bool +} + +func NewDriver(ctx context.Context, selector schema.Selector, opts DriverOpts) *Driver { + return &Driver{ctx: ctx, selector: selector, vmFlush: !opts.DisableVMFlush} } type ExecuteTipsetResult struct { @@ -155,12 +169,17 @@ func (d *Driver) ExecuteMessage(bs blockstore.Blockstore, preroot cid.Cid, epoch return nil, cid.Undef, err } - // do not flush the VM, as this forces a recursive copy to the blockstore, - // walking the full state tree, which we don't require. - // root, err := lvm.Flush(d.ctx) - // - // instead, flush the pending writes on the state tree. - root, err := lvm.StateTree().(*state.StateTree).Flush(d.ctx) + var root cid.Cid + if d.vmFlush { + // flush the VM, committing the state tree changes and forcing a + // recursive copoy from the temporary blcokstore to the real blockstore. + root, err = lvm.Flush(d.ctx) + } else { + // do not flush the VM, just the state tree; this should be used with + // LOTUS_DISABLE_VM_BUF enabled, so writes will anyway be visible. + root, err = lvm.StateTree().(*state.StateTree).Flush(d.ctx) + } + return ret, root, err } diff --git a/conformance/runner.go b/conformance/runner.go index 1fc1c1425..6ffdcd2eb 100644 --- a/conformance/runner.go +++ b/conformance/runner.go @@ -43,7 +43,7 @@ func ExecuteMessageVector(r Reporter, vector *schema.TestVector) { } // Create a new Driver. - driver := NewDriver(ctx, vector.Selector) + driver := NewDriver(ctx, vector.Selector, DriverOpts{}) // Apply every message. for i, m := range vector.ApplyMessages { @@ -93,7 +93,7 @@ func ExecuteTipsetVector(r Reporter, vector *schema.TestVector) { } // Create a new Driver. - driver := NewDriver(ctx, vector.Selector) + driver := NewDriver(ctx, vector.Selector, DriverOpts{}) // Apply every tipset. var receiptsIdx int