Skip to content

Transport Setup Node

Status Implemented
Revision 2026-10-27, skywire f37a464a4
Code pkg/deployment/tps, pkg/services/tps, pkg/transport/setup, pkg/visor/embedded_tps.go, pkg/visor/api_tps.go

Abstract

A transport setup node (TPS) creates and lists transports on a visor on behalf of an operator. A caller asks the TPS to set up a transport between two visors. The TPS asks the visor to create it. The visor accepts requests only from TPS keys it trusts.

Overview

Two services take part. The TPS is a dmsg client that serves a request interface on port 48. A visor serves the transport gateway on port 47 and refuses callers that are not in its trusted TPS list. A visor MAY also embed a TPS. The TPS holds no transports. It forwards each request to the target visor.

Addressing

Port Identifier Listener Purpose
48 skyenv.DmsgTransportSetupServicePort the TPS Requests to the TPS.
47 skyenv.DmsgTransportSetupPort every visor Requests from a TPS to the visor.
80 the standalone TPS GET /health over dmsg HTTP.

The TPS keys are transport_setup in deployment.Services. They are copied to transport.transport_setup in the visor configuration, with the visor's own additions in transport.user_transport_setup. A standalone TPS reads a configuration file (config.Config) with public_key, secret_key, port and dmsg. A visor embeds a TPS when transport.tps_sk is set, and the embedded TPS uses that key with its own dmsg client.

Data Formats

The RPC types use gob encoding. The same wire type is used by the standalone and the embedded TPS.

TransportSetupRequest (pkg/deployment/tps/api):

Field Type Meaning
TargetPK public key The visor that creates the transport.
RemotePK public key The other edge.
Type string Transport type from 01.

TransportSetupResponse: ID (UUID), Local, Remote (public keys) and Type. GetTransportsRequest has TargetPK, and GetTransportsResponse has Transports (array of TransportSetupResponse). RemoveTransportRequest has TargetPK and ID (string).

The visor side types (pkg/transport/setup) are TransportRequest (RemotePK, Type), UUIDRequest (ID), TransportResponse (ID, Local, Remote, Type) and BoolResponse (Result).

Interfaces

RPC

Port 48, service SetupRPCGateway

The TPS registers SetupRPCGateway on each accepted stream. It does not check the caller key.

Method Request Reply Behaviour
HealthCheck HealthCheckArgs{} HealthCheckReply{Status} Status is OK.
AddTransport TransportSetupRequest TransportSetupResponse Dials TargetPK on port 47 and calls TransportGateway.AddTransport. Fails when TargetPK equals RemotePK.
GetTransports GetTransportsRequest GetTransportsResponse Calls TransportGateway.GetTransports on the target.
RemoveTransport RemoveTransportRequest none Always returns ErrRemoteRemovalNotAllowed.

The embedded TPS has the same four methods (TPSRPCGateway). It bounds AddTransport and GetTransports at 30 seconds. Its RemoveTransport also refuses remote callers and is available only to the visor itself.

Port 47, service TransportGateway

A visor serves it on its dmsg client (transport.TransportListener). A stream from a key outside the visor's trusted TPS list is closed.

Method Request Reply Behaviour
AddTransport TransportRequest TransportResponse Saves a transport to RemotePK with the label skycoin (transport.LabelSkycoin).
RemoveTransport UUIDRequest BoolResponse Removes the transport when its label is skycoin or automatic. Otherwise ErrIncorrectType.
GetTransports none array of TransportResponse Transports labelled skycoin, automatic or user.

HTTP API

The standalone TPS serves an administration API on :<port> when the configuration port is not zero. It has no authentication. Bodies are JSON with unknown fields rejected and required fields validated. The server sets a header read timeout of 2 seconds and an idle timeout of 30 seconds.

Method and path Request Response
POST /add {"from": pk, "to": pk, "type": string} 200 setup.TransportResponse. 400 for a bad body or equal keys. 500 when the call to the visor fails.
POST /remove {"from": pk, "id": uuid} 200 setup.BoolResponse. 400. 500.
GET /{pk}/transports 200 array of setup.TransportResponse. 400. 500.

Error bodies are {"error": "<text>"}. A call to a visor that does not trust the TPS fails with the text "remote connection closed (visor may not trust current pkey)". Removal through POST /remove calls TransportGateway.RemoveTransport directly with the label rule above.

Behaviour

A visor creates the transport as for a local tp add, with the label skycoin. The label marks a transport set up by an operator. Transports labelled automatic come from the visor's public autoconnect and user from the visor's owner. A transport labelled setup is a control link to a route setup node and is not a TPS artefact; the route finder leaves it out of data routes (08). The visor lists user transports to the TPS but does not let it remove them.

The visor API probes a TPS with SetupRPCGateway.HealthCheck on port 48 (Visor.TPSExternalHealthCheck) and calls AddTransport and GetTransports on a TPS it names (TPSExternalAddTransport, TPSExternalGetTransports), each under a 30 second limit. The visor orders its configured TPS keys by health and latency (GetTransportSetupNodesSorted).

Security Considerations

The authorization is on the visor. The visor accepts a setup request only from a key in transport.transport_setup or transport.user_transport_setup. The TPS does not authenticate the callers of its dmsg service or its HTTP API, so any caller that reaches either can ask a TPS to create a transport on any visor that trusts it. The TPS dmsg service does not remove transports, and a TPS cannot remove a transport that has the label user.

References