@@ -4,42 +4,35 @@ import (
44 "context"
55 "fmt"
66 "os"
7- "os/exec"
8- "strings"
7+ "strconv"
98 "time"
109
1110 "github.com/testcontainers/testcontainers-go"
11+ "github.com/testcontainers/testcontainers-go/network"
1212 "github.com/testcontainers/testcontainers-go/wait"
1313
1414 "github.com/smartcontractkit/chainlink-testing-framework/framework"
1515)
1616
1717const (
18- // default ports from mylocalton-docker
19- DefaultTonHTTPAPIPort = "8081"
2018 DefaultTonSimpleServerPort = "8000"
21- DefaultTonTONExplorerPort = "8080"
22- DefaultTonLiteServerPort = "40004"
23-
2419 // NOTE: Prefunded high-load wallet from MyLocalTon pre-funded wallet, that can send up to 254 messages per 1 external message
2520 // https://docs.ton.org/v3/documentation/smart-contracts/contracts-specs/highload-wallet#highload-wallet-v2
2621 DefaultTonHlWalletAddress = "-1:5ee77ced0b7ae6ef88ab3f4350d8872c64667ffbe76073455215d3cdfab3294b"
2722 DefaultTonHlWalletMnemonic = "twenty unfair stay entry during please water april fabric morning length lumber style tomorrow melody similar forum width ride render void rather custom coin"
2823)
2924
3025var (
31- CommonDBVars = map [string ]string {
32- "POSTGRES_DIALECT" : "postgresql+asyncpg" ,
33- "POSTGRES_HOST" : "index-postgres" ,
34- "POSTGRES_PORT" : "5432" ,
35- "POSTGRES_USER" : "postgres" ,
36- "POSTGRES_DB" : "ton_index" ,
37- "POSTGRES_PASSWORD" : "PostgreSQL1234" ,
38- "POSTGRES_DBNAME" : "ton_index" ,
39- "TON_INDEXER_TON_HTTP_API_ENDPOINT" : "http://tonhttpapi:8080/" ,
40- "TON_INDEXER_IS_TESTNET" : "0" ,
41- "TON_INDEXER_REDIS_DSN" : "redis://redis:6379" ,
42-
26+ commonDBVars = map [string ]string {
27+ "POSTGRES_DIALECT" : "postgresql+asyncpg" ,
28+ "POSTGRES_HOST" : "index-postgres" ,
29+ "POSTGRES_PORT" : "5432" ,
30+ "POSTGRES_USER" : "postgres" ,
31+ "POSTGRES_DB" : "ton_index" ,
32+ "POSTGRES_PASSWORD" : "PostgreSQL1234" ,
33+ "POSTGRES_DBNAME" : "ton_index" ,
34+ "TON_INDEXER_IS_TESTNET" : "0" ,
35+ "TON_INDEXER_REDIS_DSN" : "redis://redis:6379" ,
4336 "TON_WORKER_FROM" : "1" ,
4437 "TON_WORKER_DBROOT" : "/tondb" ,
4538 "TON_WORKER_BINARY" : "ton-index-postgres-v2" ,
@@ -59,6 +52,18 @@ type containerTemplate struct {
5952 Alias string
6053}
6154
55+ type hostPortMapping struct {
56+ SimpleServer string
57+ LiteServer string
58+ DHTServer string
59+ Console string
60+ ValidatorUDP string
61+ HTTPAPIPort string
62+ ExplorerPort string
63+ FaucetPort string
64+ IndexAPIPort string
65+ }
66+
6267func commonContainer (
6368 ctx context.Context ,
6469 name string ,
@@ -91,83 +96,114 @@ func commonContainer(
9196 })
9297}
9398
99+ func generateUniquePortsFromBase (basePort string ) (* hostPortMapping , error ) {
100+ base , err := strconv .Atoi (basePort )
101+ if err != nil {
102+ return nil , fmt .Errorf ("invalid base port %s: %w" , basePort , err )
103+ }
104+
105+ mapping := & hostPortMapping {
106+ SimpleServer : basePort ,
107+ HTTPAPIPort : strconv .Itoa (base + 10 ),
108+ ExplorerPort : strconv .Itoa (base + 20 ),
109+ IndexAPIPort : strconv .Itoa (base + 30 ),
110+ FaucetPort : strconv .Itoa (base + 40 ),
111+ LiteServer : strconv .Itoa (base + 50 ),
112+ DHTServer : strconv .Itoa (base + 60 ),
113+ Console : strconv .Itoa (base + 70 ),
114+ ValidatorUDP : strconv .Itoa (base + 80 ),
115+ }
116+
117+ return mapping , nil
118+ }
119+
94120func defaultTon (in * Input ) {
95121 if in .Image == "" {
96122 in .Image = "ghcr.io/neodix42/mylocalton-docker:latest"
97123 }
124+ if in .Port == "" {
125+ in .Port = DefaultTonSimpleServerPort
126+ }
98127}
99128
100129func newTon (in * Input ) (* Output , error ) {
101130 defaultTon (in )
102131
132+ hostPorts , err := generateUniquePortsFromBase (in .Port )
133+ if err != nil {
134+ return nil , fmt .Errorf ("failed to generate unique ports: %w" , err )
135+ }
136+
103137 ctx := context .Background ()
104138
105- networkName := "ton"
106- lightCLientSubNet := "172.28.0.0/16"
107- //nolint:gosec
108- cmd := exec .Command ("docker" , "network" , "create" ,
109- "--driver=bridge" ,
110- "--attachable" ,
111- fmt .Sprintf ("--subnet=%s" , lightCLientSubNet ),
112- "--label=framework=ctf" ,
113- networkName ,
139+ network , err := network .New (ctx ,
140+ network .WithAttachable (),
141+ network .WithLabels (framework .DefaultTCLabels ()),
114142 )
115- output , err := cmd .CombinedOutput ()
116- framework .L .Info ().Str ("output" , string (output )).Msg ("TON Docker network created" )
117143 if err != nil {
118- if ! strings .Contains (string (output ), "already exists" ) {
119- return nil , fmt .Errorf ("failed to create docker network: %v" , err )
120- }
121- framework .L .Info ().Msgf ("Network %q already exists, ignoring" , networkName )
144+ return nil , fmt .Errorf ("failed to create network: %w" , err )
122145 }
123146
147+ networkName := network .Name
148+ framework .L .Info ().Str ("output" , string (networkName )).Msg ("TON Docker network created" )
149+
124150 tonServices := []containerTemplate {
125151 {
152+ Name : fmt .Sprintf ("TON-genesis-%s" , networkName ),
126153 Image : "ghcr.io/neodix42/mylocalton-docker:latest" ,
127- Ports : []string {"8000:8000/tcp" , "40004:40004/tcp" , "40003:40003/udp" , "40002:40002/tcp" , "40001:40001/udp" },
154+ Ports : []string {
155+ fmt .Sprintf ("%s:%s/tcp" , hostPorts .SimpleServer , DefaultTonSimpleServerPort ),
156+ // Note: LITE_PORT port is used by the lite-client to connect to the genesis node in config
157+ fmt .Sprintf ("%s:%s/tcp" , hostPorts .LiteServer , hostPorts .LiteServer ),
158+ fmt .Sprintf ("%s:40003/udp" , hostPorts .DHTServer ),
159+ fmt .Sprintf ("%s:40002/tcp" , hostPorts .Console ),
160+ fmt .Sprintf ("%s:40001/udp" , hostPorts .ValidatorUDP ),
161+ },
128162 Env : map [string ]string {
129- "GENESIS" : "true" ,
130- "NAME" : "genesis" ,
163+ "GENESIS" : "true" ,
164+ "NAME" : "genesis" ,
165+ // Note: LITE_PORT port is used by the lite-client to connect to the genesis node in config
166+ "LITE_PORT" : hostPorts .LiteServer ,
131167 "CUSTOM_PARAMETERS" : "--state-ttl 315360000 --archive-ttl 315360000" ,
132168 },
133169 WaitFor : wait .ForExec ([]string {
134- "/usr/local/bin/lite-client" , "-a" , "127.0.0.1:40004" , "-b" ,
170+ "/usr/local/bin/lite-client" , "-a" , fmt . Sprintf ( "127.0.0.1:%s" , hostPorts . LiteServer ) , "-b" ,
135171 "E7XwFSQzNkcRepUC23J2nRpASXpnsEKmyyHYV4u/FZY=" , "-t" , "3" , "-c" , "last" ,
136172 }).WithStartupTimeout (2 * time .Minute ),
137173 Network : networkName ,
138174 Alias : "genesis" ,
139175 Mounts : testcontainers.ContainerMounts {
140176 {
141- Source : testcontainers.GenericVolumeMountSource {Name : "shared-data" },
177+ Source : testcontainers.GenericVolumeMountSource {Name : fmt . Sprintf ( "shared-data-%s" , networkName ) },
142178 Target : "/usr/share/data" ,
143179 },
144180 {
145- Source : testcontainers.GenericVolumeMountSource {Name : "ton-db" },
181+ Source : testcontainers.GenericVolumeMountSource {Name : fmt . Sprintf ( "ton-db-%s" , networkName ) },
146182 Target : "/var/ton-work/db" ,
147183 },
148184 },
149185 },
150186 {
151187 Image : "redis:latest" ,
152- Name : " redis" ,
188+ Name : fmt . Sprintf ( "TON- redis-%s" , networkName ) ,
153189 Network : networkName ,
154190 Alias : "redis" ,
155191 },
156192 {
157193 Image : "postgres:17" ,
158- Name : " index-postgres" ,
194+ Name : fmt . Sprintf ( "TON- index-postgres-%s" , networkName ) ,
159195 Network : networkName ,
160196 Alias : "index-postgres" ,
161- Env : CommonDBVars ,
197+ Env : commonDBVars ,
162198 Mounts : testcontainers.ContainerMounts {
163199 {
164- Source : testcontainers.GenericVolumeMountSource {Name : "pg" },
200+ Source : testcontainers.GenericVolumeMountSource {Name : fmt . Sprintf ( "pg-%s" , networkName ) },
165201 Target : "/var/lib/postgresql/data" ,
166202 },
167203 },
168204 },
169205 {
170- Name : " tonhttpapi" ,
206+ Name : fmt . Sprintf ( "TON- tonhttpapi-%s" , networkName ) ,
171207 Image : "ghcr.io/neodix42/ton-http-api:latest" ,
172208 Env : map [string ]string {
173209 "TON_API_LOGS_JSONIFY" : "0" ,
@@ -177,29 +213,29 @@ func newTon(in *Input) (*Output, error) {
177213 "TON_API_GET_METHODS_ENABLED" : "1" ,
178214 "TON_API_JSON_RPC_ENABLED" : "1" ,
179215
180- "POSTGRES_DIALECT" : "postgresql+asyncpg" ,
181- "POSTGRES_HOST" : "index-postgres" ,
182- "POSTGRES_PORT" : "5432" ,
183- "POSTGRES_USER" : "postgres" ,
184- "POSTGRES_PASSWORD" : "PostgreSQL1234" ,
185- "POSTGRES_DBNAME" : "ton_index" ,
186- "TON_INDEXER_IS_TESTNET" : "0" ,
187- "TON_INDEXER_REDIS_DSN" : "redis://redis:6379" ,
216+ "POSTGRES_DIALECT" : commonDBVars [ "POSTGRES_DIALECT" ] ,
217+ "POSTGRES_HOST" : commonDBVars [ "POSTGRES_HOST" ] ,
218+ "POSTGRES_PORT" : commonDBVars [ "POSTGRES_PORT" ] ,
219+ "POSTGRES_USER" : commonDBVars [ "POSTGRES_USER" ] ,
220+ "POSTGRES_PASSWORD" : commonDBVars [ "POSTGRES_PASSWORD" ] ,
221+ "POSTGRES_DBNAME" : commonDBVars [ "POSTGRES_DBNAME" ] ,
222+ "TON_INDEXER_IS_TESTNET" : commonDBVars [ "TON_INDEXER_IS_TESTNET" ] ,
223+ "TON_INDEXER_REDIS_DSN" : commonDBVars [ "TON_INDEXER_REDIS_DSN" ] ,
188224 },
189225 Mounts : testcontainers.ContainerMounts {
190226 {
191- Source : testcontainers.GenericVolumeMountSource {Name : "shared-data" },
227+ Source : testcontainers.GenericVolumeMountSource {Name : fmt . Sprintf ( "shared-data-%s" , networkName ) },
192228 Target : "/usr/share/data" ,
193229 },
194230 },
195- Ports : []string {" 8081/tcp" },
231+ Ports : []string {fmt . Sprintf ( "%s: 8081/tcp", hostPorts . HTTPAPIPort ) },
196232 WaitFor : wait .ForHTTP ("/healthcheck" ).WithStartupTimeout (90 * time .Second ),
197233 Command : []string {"-c" , "gunicorn -k uvicorn.workers.UvicornWorker -w 1 --bind 0.0.0.0:8081 pyTON.main:app" },
198234 Network : networkName ,
199235 Alias : "tonhttpapi" ,
200236 },
201237 {
202- Name : " faucet" ,
238+ Name : fmt . Sprintf ( "TON- faucet-%s" , networkName ) ,
203239 Image : "ghcr.io/neodix42/mylocalton-docker-faucet:latest" ,
204240 Env : map [string ]string {
205241 "FAUCET_USE_RECAPTCHA" : "false" ,
@@ -209,11 +245,11 @@ func newTon(in *Input) (*Output, error) {
209245 },
210246 Mounts : testcontainers.ContainerMounts {
211247 {
212- Source : testcontainers.GenericVolumeMountSource {Name : "shared-data" },
248+ Source : testcontainers.GenericVolumeMountSource {Name : fmt . Sprintf ( "shared-data-%s" , networkName ) },
213249 Target : "/usr/share/data" ,
214250 },
215251 },
216- Ports : []string {" 88/tcp" },
252+ Ports : []string {fmt . Sprintf ( "%s: 88/tcp", hostPorts . FaucetPort ) },
217253 WaitFor : wait .ForHTTP ("/" ).WithStartupTimeout (90 * time .Second ),
218254 Network : networkName ,
219255 Alias : "faucet" ,
@@ -222,32 +258,32 @@ func newTon(in *Input) (*Output, error) {
222258
223259 tonIndexingAndObservability := []containerTemplate {
224260 {
225- Name : " explorer" ,
261+ Name : fmt . Sprintf ( "TON- explorer-%s" , networkName ) ,
226262 Image : "ghcr.io/neodix42/mylocalton-docker-explorer:latest" ,
227263 Env : map [string ]string {
228264 "SERVER_PORT" : "8080" ,
229265 },
230266 Mounts : testcontainers.ContainerMounts {
231267 {
232- Source : testcontainers.GenericVolumeMountSource {Name : "shared-data" },
268+ Source : testcontainers.GenericVolumeMountSource {Name : fmt . Sprintf ( "shared-data-%s" , networkName ) },
233269 Target : "/usr/share/data" ,
234270 },
235271 },
236- Ports : []string {"8080 :8080/tcp" },
272+ Ports : []string {fmt . Sprintf ( "%s :8080/tcp", hostPorts . ExplorerPort ) },
237273 Network : networkName ,
238274 Alias : "explorer" ,
239275 },
240276 {
241- Name : " index-worker" ,
277+ Name : fmt . Sprintf ( "TON- index-worker-%s" , networkName ) ,
242278 Image : "toncenter/ton-indexer-worker:v1.2.0-test" ,
243- Env : CommonDBVars ,
279+ Env : commonDBVars ,
244280 Mounts : testcontainers.ContainerMounts {
245281 {
246- Source : testcontainers.GenericVolumeMountSource {Name : "ton-db" },
282+ Source : testcontainers.GenericVolumeMountSource {Name : fmt . Sprintf ( "ton-db-%s" , networkName ) },
247283 Target : "/tondb" ,
248284 },
249285 {
250- Source : testcontainers.GenericVolumeMountSource {Name : "index-workdir" },
286+ Source : testcontainers.GenericVolumeMountSource {Name : fmt . Sprintf ( "index-workdir-%s" , networkName ) },
251287 Target : "/workdir" ,
252288 },
253289 },
@@ -257,20 +293,20 @@ func newTon(in *Input) (*Output, error) {
257293 Alias : "index-worker" ,
258294 },
259295 {
260- Name : " index-api" ,
296+ Name : fmt . Sprintf ( "TON- index-api-%s" , networkName ) ,
261297 Image : "toncenter/ton-indexer-api:v1.2.0-test" ,
262- Env : CommonDBVars ,
263- Ports : []string {" 8082/tcp" },
298+ Env : commonDBVars ,
299+ Ports : []string {fmt . Sprintf ( "%s: 8082/tcp", hostPorts . IndexAPIPort ) },
264300 WaitFor : wait .ForHTTP ("/" ).
265301 WithStartupTimeout (90 * time .Second ),
266302 Command : []string {"-bind" , ":8082" , "-prefork" , "-threads" , "4" , "-v2" , "http://tonhttpapi:8081/" },
267303 Network : networkName ,
268304 Alias : "index-api" ,
269305 },
270306 {
271- Name : " event-classifier" ,
307+ Name : fmt . Sprintf ( "TON- event-classifier-%s" , networkName ) ,
272308 Image : "toncenter/ton-indexer-classifier:v1.2.0-test" ,
273- Env : CommonDBVars ,
309+ Env : commonDBVars ,
274310 WaitFor : wait .ForLog ("Reading finished tasks" ).
275311 WithStartupTimeout (90 * time .Second ),
276312 Command : []string {"--pool-size" , "4" , "--prefetch-size" , "1000" , "--batch-size" , "100" },
@@ -310,10 +346,9 @@ func newTon(in *Input) (*Output, error) {
310346 Type : in .Type ,
311347 Family : FamilyTon ,
312348 ContainerName : name ,
313- // Note: in case we need 1+ validators, we need to modify the compose file
314349 Nodes : []* Node {{
315350 // Note: define if we need more access other than the global config(tonutils-go only uses liteclients defined in the config)
316- ExternalHTTPUrl : fmt .Sprintf ("%s:%s" , "localhost" , DefaultTonSimpleServerPort ),
351+ ExternalHTTPUrl : fmt .Sprintf ("%s:%s" , "localhost" , hostPorts . SimpleServer ),
317352 InternalHTTPUrl : fmt .Sprintf ("%s:%s" , name , DefaultTonSimpleServerPort ),
318353 }},
319354 }, nil
0 commit comments