func (b *Builder) StopSmeshing(deleteFiles bool) error {
	b.mtx.Lock()
	defer b.mtx.Unlock()
	if b.exited == nil {
		return errors.New("not started")
	}
	if err := b.postSetupProvider.StopSession(deleteFiles); err != nil {
		return fmt.Errorf("failed to stop post data creation session: %v", err)
	}
	b.stop()
	<-b.exited
	b.exited = nil
	return nil
}
StopSmeshing stops the atx builder.
package activation
import (
	"context"
	"errors"
	"fmt"
	"sync"
	"time"
	"unsafe"
	"github.com/spacemeshos/ed25519"
	"github.com/spacemeshos/post/shared"
	"go.uber.org/atomic"
	"github.com/spacemeshos/go-spacemesh/common/types"
	"github.com/spacemeshos/go-spacemesh/events"
	"github.com/spacemeshos/go-spacemesh/log"
	"github.com/spacemeshos/go-spacemesh/p2p/pubsub"
	"github.com/spacemeshos/go-spacemesh/signing"
)
var (
	ErrStopRequested = errors.New("builder: stop requested")
	ErrATXChallengeExpired = errors.New("builder: atx expired")
	ErrPoetServiceUnstable = errors.New("builder: poet service is unstable")
)
const AtxProtocol = "AtxGossip"
const defaultPoetRetryInterval = 5 * time.Second
type meshProvider interface {
	GetOrphanBlocksBefore(l types.LayerID) ([]types.BlockID, error)
	LatestLayer() types.LayerID
}
type poetNumberOfTickProvider struct{}
func (provider *poetNumberOfTickProvider) NumOfTicks() uint64 {
	return 1
}
type nipostBuilder interface {
	updatePoETProver(PoetProvingServiceClient)
	BuildNIPost(ctx context.Context, challenge *types.Hash32, timeout chan struct{}) (*types.NIPost, error)
}
type idStore interface {
	StoreNodeIdentity(id types.NodeID) error
	GetIdentity(id string) (types.NodeID, error)
}
type nipostValidator interface {
	Validate(id signing.PublicKey, NIPost *types.NIPost, expectedChallenge types.Hash32, numUnits uint) error
	ValidatePost(id []byte, Post *types.Post, PostMetadata *types.PostMetadata, numUnits uint) error
}
type atxDBProvider interface {
	GetAtxHeader(id types.ATXID) (*types.ActivationTxHeader, error)
	GetNodeLastAtxID(nodeID types.NodeID) (types.ATXID, error)
	GetPosAtxID() (types.ATXID, error)
	GetAtxTimestamp(id types.ATXID) (time.Time, error)
	AwaitAtx(id types.ATXID) chan struct{}
	UnsubscribeAtx(id types.ATXID)
}
type bytesStore interface {
	Put(key []byte, buf []byte) error
	Get(key []byte) ([]byte, error)
}
type signer interface {
	Sign(m []byte) []byte
}
type layerClock interface {
	AwaitLayer(layerID types.LayerID) chan struct{}
	GetCurrentLayer() types.LayerID
}
type syncer interface {
	RegisterChForSynced(context.Context, chan struct{})
}
type SmeshingProvider interface {
	Smeshing() bool
	StartSmeshing(types.Address, PostSetupOpts) error
	StopSmeshing(bool) error
	SmesherID() types.NodeID
	Coinbase() types.Address
	SetCoinbase(coinbase types.Address)
	MinGas() uint64
	SetMinGas(value uint64)
}
var _ SmeshingProvider = (*Builder)(nil)
type Config struct {
	CoinbaseAccount types.Address
	GoldenATXID     types.ATXID
	LayersPerEpoch  uint32
}
type Builder struct {
	pendingPoetClient atomic.UnsafePointer
	started           atomic.Bool
	signer
	accountLock       sync.RWMutex
	nodeID            types.NodeID
	coinbaseAccount   types.Address
	goldenATXID       types.ATXID
	layersPerEpoch    uint32
	db                atxDBProvider
	publisher         pubsub.Publisher
	mesh              meshProvider
	tickProvider      poetNumberOfTickProvider
	nipostBuilder     nipostBuilder
	postSetupProvider PostSetupProvider
	challenge         *types.NIPostChallenge
	initialPost       *types.Post
	pendingATX            *types.ActivationTx
	layerClock            layerClock
	mtx                   sync.Mutex
	store                 bytesStore
	syncer                syncer
	log                   log.Log
	parentCtx             context.Context
	stop                  func()
	exited                chan struct{}
	poetRetryInterval     time.Duration
	poetClientInitializer PoETClientInitializer
}
type BuilderOption func(*Builder)
func WithPoetRetryInterval(interval time.Duration) BuilderOption {
	return func(b *Builder) {
		b.poetRetryInterval = interval
	}
}
type PoETClientInitializer func(string) PoetProvingServiceClient
func WithPoETClientInitializer(initializer PoETClientInitializer) BuilderOption {
	return func(b *Builder) {
		b.poetClientInitializer = initializer
	}
}
func WithContext(ctx context.Context) BuilderOption {
	return func(b *Builder) {
		b.parentCtx = ctx
	}
}
func NewBuilder(conf Config, nodeID types.NodeID, signer signer, db atxDBProvider, publisher pubsub.Publisher, mesh meshProvider,
	layersPerEpoch uint32, nipostBuilder nipostBuilder, postSetupProvider PostSetupProvider, layerClock layerClock,
	syncer syncer, store bytesStore, log log.Log, opts ...BuilderOption) *Builder {
	b := &Builder{
		parentCtx:         context.Background(),
		signer:            signer,
		nodeID:            nodeID,
		coinbaseAccount:   conf.CoinbaseAccount,
		goldenATXID:       conf.GoldenATXID,
		layersPerEpoch:    conf.LayersPerEpoch,
		db:                db,
		publisher:         publisher,
		mesh:              mesh,
		nipostBuilder:     nipostBuilder,
		postSetupProvider: postSetupProvider,
		layerClock:        layerClock,
		store:             store,
		syncer:            syncer,
		log:               log,
		poetRetryInterval: defaultPoetRetryInterval,
	}
	for _, opt := range opts {
		opt(b)
	}
	return b
}
func (b *Builder) Smeshing() bool {
	return b.started.Load()
}
func (b *Builder) StartSmeshing(coinbase types.Address, opts PostSetupOpts) error {
	b.mtx.Lock()
	if b.exited != nil {
		select {
		case <-b.exited:
		default:
			b.mtx.Unlock()
			return errors.New("already started")
		}
	}
	b.started.Store(true)
	b.coinbaseAccount = coinbase
	var ctx context.Context
	exited := make(chan struct{})
	ctx, b.stop = context.WithCancel(b.parentCtx)
	b.exited = exited
	b.mtx.Unlock()
	doneChan, err := b.postSetupProvider.StartSession(opts)
	if err != nil {
		close(exited)
		b.started.Store(false)
		return fmt.Errorf("failed to start post setup session: %w", err)
	}
	go func() {
		defer b.started.Store(false)
		defer close(exited)
		select {
		case <-ctx.Done():
			return
		case <-doneChan:
		}
		if s := b.postSetupProvider.Status(); s.State != postSetupStateComplete {
			b.log.WithContext(ctx).With().Error("failed to complete post setup", log.Err(b.postSetupProvider.LastError()))
			return
		}
		b.loop(ctx)
	}()
	return nil
}