Files
vm/rpc/factory_zap.go
zeekay 1741f49099 rpc: rip LUX_ prefix from rpcchainvm handshake env vars
luxd v1.26+ sets the unprefixed VM_RUNTIME_ENGINE_ADDR and VM_TRANSPORT
env vars when launching plugin VMs. The historical LUX_VM_RUNTIME_ENGINE_ADDR
and LUX_VM_TRANSPORT names came from a now-dropped luxd<->plugin compatibility
shim — the canonical names are the unprefixed ones.

Renames:
  - rpc/runtime/runtime.go: EngineAddressKey constant
  - rpc/factory_zap.go:     LUX_VM_TRANSPORT -> VM_TRANSPORT
  - rpc/runtime/README.md:  documentation aligned with code

Plugins built against luxfi/vm <= v1.1.0 read the LUX_-prefixed names and
will fail handshake against post-v1.1.1 luxd. Those plugins must rebuild
against this release.

Cleanup:
  - drop dead xsvm protobuf+connect tree (no callers; xsvm has been on ZAP
    since v1.0.41)
  - drop indirect corona dep (consensus moved to corona+pulsar in v1.0.41+)
  - .gitignore: ignore .DS_Store at every level
2026-05-15 09:53:30 -07:00

97 lines
2.3 KiB
Go

//go:build !grpc
// Copyright (C) 2019-2025, Lux Industries, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package rpc
import (
"context"
"fmt"
"net"
"os"
zapwire "github.com/luxfi/api/zap"
"github.com/luxfi/log"
"github.com/luxfi/metric"
"github.com/luxfi/resource"
"github.com/luxfi/vm/manager"
"github.com/luxfi/vm/rpc/runtime"
"github.com/luxfi/vm/rpc/runtime/subprocess"
)
var _ manager.Factory = (*factory)(nil)
type factory struct {
path string
processTracker resource.ProcessTracker
runtimeTracker runtime.Tracker
metricsGatherer metric.MultiGatherer
}
// NewFactory creates a new VM factory for external plugin VMs using ZAP transport.
func NewFactory(
path string,
processTracker resource.ProcessTracker,
runtimeTracker runtime.Tracker,
metricsGatherer metric.MultiGatherer,
) manager.Factory {
return &factory{
path: path,
processTracker: processTracker,
runtimeTracker: runtimeTracker,
metricsGatherer: metricsGatherer,
}
}
func (f *factory) New(logger log.Logger) (interface{}, error) {
config := &subprocess.Config{
Stderr: os.Stderr,
Stdout: os.Stdout,
HandshakeTimeout: runtime.DefaultHandshakeTimeout,
Log: logger,
}
// Create TCP listener for ZAP handshake
listener, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
return nil, fmt.Errorf("failed to create ZAP listener: %w", err)
}
// Tell subprocess to use ZAP transport
cmd := subprocess.NewCmd(f.path)
cmd.Env = append(cmd.Env, "VM_TRANSPORT=zap")
status, stopper, err := subprocess.Bootstrap(
context.TODO(),
listener,
cmd,
config,
)
if err != nil {
return nil, err
}
// Connect via ZAP
ctx, cancel := context.WithTimeout(context.Background(), runtime.DefaultHandshakeTimeout)
defer cancel()
zapConn, err := zapwire.Dial(ctx, status.Addr, nil)
if err != nil {
stopper.Stop(context.Background())
logger.Error("failed to dial VM ZAP service", "error", err)
return nil, err
}
f.processTracker.TrackProcess(status.Pid)
f.runtimeTracker.TrackRuntime(stopper)
logger.Info("VM client connected via ZAP",
"path", f.path,
"addr", status.Addr,
"pid", status.Pid,
)
return NewZAPClient(zapConn, stopper, status.Pid, f.processTracker, f.metricsGatherer, logger), nil
}