Skip to content

Conversation

@jadepark-dev
Copy link
Contributor

@jadepark-dev jadepark-dev commented Feb 4, 2026

This PR unblocks ton devenv, while compatible with existing integration tests in chainlink-ton

  • testing in progress

Summary

  • Fix TON localnet component to join the shared CTF Docker network
    (framework.DefaultNetworkName) instead of creating an isolated network, enabling DNS-based
    communication with other containers (e.g., Chainlink nodes in devenv)
  • Use dynamic host port assignment for LiteServer to prevent port conflicts when running
    multiple TON instances in parallel
  • Use unique per-container volume names to prevent database lock conflicts
    (/var/ton-work/db/adnl/LOCK: Resource temporarily unavailable)

Context

This is a rework of #2339 (reverted in #2371). The previous fix changed the container's
internal ports to match host ports, which was fragile. This fix keeps internal ports fixed
(8000 for HTTP, 40000 for LiteServer) and only controls host-side mapping via nat.PortMap.


Below is a summarization created by an LLM (gpt-4-0125-preview). Be mindful of hallucinations and verify accuracy.

Why

The changes improve container configuration and networking for TON blockchain nodes by removing unnecessary port and network complexities, simplifying environment setup, and enhancing port mapping for better accessibility and integration with the host system.

What

  • framework/components/blockchain/ton.go
    • Removed unused import strconv.
    • Removed liteServerPortOffset and portMapping struct which were previously used for calculating port numbers and mapping.
    • Simplified container name generation by directly assigning it to a variable instead of recalculating it dynamically.
    • Removed the custom container networking setup, opting instead for the default network setup which reduces complexity and potential networking issues.
    • Updated environment variables setup to directly use predefined constants, removing the need for dynamically calculated port numbers.
    • Simplified port exposure by directly specifying the container's ports without dynamically assigning them, which makes the setup clearer and avoids potential port conflicts.
    • Added Networks and NetworkAliases configurations to explicitly define the network the container should connect to and its aliases, improving network predictability and accessibility.
    • Adjusted volume mounts to use a simplified naming convention that matches the container's name, enhancing clarity and consistency in volume management.
    • Introduced PortBindings in the HostConfigModifier function to explicitly map the container's ports to the host, including dynamic assignment for the LiteServer port, which enhances the container's accessibility from the host system.
    • Updated the method for retrieving the container's host and port information to be more reliable and to accommodate the changes in port mapping and networking.

@jadepark-dev jadepark-dev marked this pull request as ready for review February 10, 2026 23:53
@jadepark-dev jadepark-dev requested a review from a team as a code owner February 10, 2026 23:53
Copilot AI review requested due to automatic review settings February 10, 2026 23:53
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the TON localnet testcontainer setup to share the CTF Docker network, avoid host port conflicts via dynamic LiteServer ports, and prevent DB lock issues by using unique volume names.

Changes:

  • Switch TON container networking to framework.DefaultNetworkName with a stable alias for DNS-based connectivity.
  • Use Docker-assigned host ports for LiteServer while keeping container internal ports fixed.
  • Use per-container named volumes to avoid cross-instance DB lock contention.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

nat.Port(fmt.Sprintf("%s/tcp", defaultLiteServerPort)): []nat.PortBinding{
{
HostIP: "0.0.0.0",
HostPort: "", // Docker assigns a dynamic available port
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting HostPort to an empty string in Docker port bindings can be rejected by the Docker API (it typically expects a numeric string). To reliably request an ephemeral host port, either omit the LiteServer entry from PortBindings entirely (and rely on ExposedPorts + MappedPort), or set the host port explicitly to "0" (equivalent to -p 0:40000).

Suggested change
HostPort: "", // Docker assigns a dynamic available port
HostPort: "0", // Docker assigns a dynamic available port

Copilot uses AI. Check for mistakes.
Comment on lines +91 to +104
h.PortBindings = nat.PortMap{
nat.Port(fmt.Sprintf("%s/tcp", defaultTonHTTPServerPort)): []nat.PortBinding{
{
HostIP: "0.0.0.0",
HostPort: in.Port,
},
},
nat.Port(fmt.Sprintf("%s/tcp", defaultLiteServerPort)): []nat.PortBinding{
{
HostIP: "0.0.0.0",
HostPort: "", // Docker assigns a dynamic available port
},
},
}
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The modifier overwrites h.PortBindings wholesale, which can unintentionally discard bindings set elsewhere (e.g., by other modifiers or defaults). Prefer initializing h.PortBindings if nil and then setting/updating only the specific ports you care about, leaving any pre-existing bindings intact.

Suggested change
h.PortBindings = nat.PortMap{
nat.Port(fmt.Sprintf("%s/tcp", defaultTonHTTPServerPort)): []nat.PortBinding{
{
HostIP: "0.0.0.0",
HostPort: in.Port,
},
},
nat.Port(fmt.Sprintf("%s/tcp", defaultLiteServerPort)): []nat.PortBinding{
{
HostIP: "0.0.0.0",
HostPort: "", // Docker assigns a dynamic available port
},
},
}
if h.PortBindings == nil {
h.PortBindings = nat.PortMap{}
}
httpPort := nat.Port(fmt.Sprintf("%s/tcp", defaultTonHTTPServerPort))
lsPort := nat.Port(fmt.Sprintf("%s/tcp", defaultLiteServerPort))
h.PortBindings[httpPort] = []nat.PortBinding{
{
HostIP: "0.0.0.0",
HostPort: in.Port,
},
}
h.PortBindings[lsPort] = []nat.PortBinding{
{
HostIP: "0.0.0.0",
HostPort: "", // Docker assigns a dynamic available port
},
}

Copilot uses AI. Check for mistakes.
Comment on lines 131 to 137
return &Output{
UseCache: true,
ChainID: in.ChainID,
Type: in.Type,
Family: FamilyTon,
ContainerName: name,
ContainerName: containerName,
Container: c,
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Output.ContainerName previously reflected the actual container name returned by Docker via c.Name(ctx). Returning the requested name (containerName) is a behavior change and can break callers that rely on the real name (including Docker's leading '/' formatting). Consider restoring name, err := c.Name(ctx) for Output.ContainerName, while still using containerName exclusively for network aliasing/internal DNS.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant