-
Notifications
You must be signed in to change notification settings - Fork 30
Expand file tree
/
Copy pathsettings.conf
More file actions
1388 lines (1049 loc) · 64.3 KB
/
Copy pathsettings.conf
File metadata and controls
1388 lines (1049 loc) · 64.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
# This file should only contain Teranode defaults and settings that are common across different environments
# @group: CLIENT_NAMES compact
clientName = teranode
clientName.docker.ss.teranode1 = teranode1
# @endgroup
# @group: DATA_DIRECTORY compact
DATADIR = ./data
DATADIR.operator = /data
DATADIR.docker.context.testrunner = ./../data
# @endgroup
KAFKA_BLOCKS = blocks
KAFKA_BLOCKS.docker.ss.teranode1 = blocks1
KAFKA_BLOCKS.operator = blocks-${clientName}
KAFKA_BLOCKS_FINAL = blocks-final
KAFKA_BLOCKS_FINAL.docker.ss.teranode1 = blocks-final1
KAFKA_BLOCKS_FINAL.operator = blocks-final-${clientName}
KAFKA_HOSTS = localhost:${KAFKA_PORT}
KAFKA_HOSTS.test = 127.0.0.1:${KAFKA_PORT}
KAFKA_HOSTS.docker = kafka-shared:${KAFKA_PORT}
KAFKA_INVALID_BLOCKS = invalid-blocks
KAFKA_INVALID_BLOCKS.docker.ss.teranode1 = invalid-blocks1
KAFKA_INVALID_BLOCKS.operator = invalid-blocks-${clientName}
KAFKA_INVALID_SUBTREES = invalid-subtrees
KAFKA_INVALID_SUBTREES.docker.ss.teranode1 = invalid-subtrees1
KAFKA_INVALID_SUBTREES.operator = invalid-subtrees-${clientName}
KAFKA_LEGACY_INV = legacy-inv
KAFKA_LEGACY_INV.docker.ss.teranode1 = legacy-inv1
KAFKA_LEGACY_INV.operator = legacy-inv-${clientName}
KAFKA_PARTITIONS_HIGH = 8
KAFKA_PARTITIONS_HIGH.docker.m = 32
KAFKA_PARTITIONS_HIGH.operator = 32
KAFKA_PARTITIONS_LOW = 1
KAFKA_PORT = 9092
KAFKA_PORT.dev.kafkatool = 9094
KAFKA_REJECTEDTX = rejectedtx
KAFKA_REJECTEDTX.docker.ss.teranode1 = rejectedtx1
KAFKA_REJECTEDTX.operator = rejectedtx-${clientName}
# use the same kafka cluster for the testing env
KAFKA_REPLICATION_FACTOR = 1
KAFKA_REPLICATION_FACTOR.operator = 3
KAFKA_SCHEMA = kafka
KAFKA_SCHEMA.dev = memory
KAFKA_SCHEMA.test = memory
KAFKA_SUBTREES = subtrees
KAFKA_SUBTREES.docker.ss.teranode1 = subtrees1
KAFKA_SUBTREES.operator = subtrees-${clientName}
# @group: KAFKA_TLS
KAFKA_ENABLE_TLS = false
KAFKA_TLS_SKIP_VERIFY = false
# @endgroup
# Enable debug logging from Sarama (Kafka client library)
# Set to true to see detailed Kafka connection and protocol logs
# Default: false (too verbose for production)
kafka_enable_debug_logging = false
KAFKA_TXMETA = txmeta
KAFKA_TXMETA.docker.ss.teranode1 = txmeta1
KAFKA_TXMETA.operator = txmeta-${clientName}
KAFKA_UNITTEST = unittest
KAFKA_VALIDATORTXS = validatortxs
KAFKA_VALIDATORTXS.docker.ss.teranode1 = validatortxs1
KAFKA_VALIDATORTXS.operator = validatortxs-${clientName}
# @group: PORT PREFIXES compact
PORT_PREFIX =
# @endgroup
# @group: PORTS compact
ALERT_P2P_PORT = 9908 # this is set in the mainnet.json in services/alert/config
ASSET_HTTP_PORT = 8090
BLOCKCHAIN_GRPC_PORT = 8087
BLOCKCHAIN_HTTP_PORT = 8082
BLOCK_ASSEMBLY_GRPC_PORT = 8085
BLOCK_PERSISTER_HTTP_PORT = 8083
BLOCK_VALIDATION_GRPC_PORT = 8088
CENTRIFUGE_PORT = 8892
PRUNER_GRPC_PORT = 8096
COINBASE_GRPC_PORT = 8093
FAUCET_HTTP_PORT = 8097
HEALTH_CHECK_PORT = 8000
JAEGER_PORT = 6831
JAEGER_PORT_HTTP = 4318
LEGACY_GRPC_PORT = 8099
LEGACY_HTTP_PORT = 8098
P2P_GRPC_PORT = 9904
P2P_HTTP_PORT = 9906
P2P_PORT = 9905
P2P_PORT_COINBASE = 9907
POSTGRES_PORT = 5432
# PostgreSQL Connection Pool Configuration
# These are GLOBAL defaults that apply to all PostgreSQL database connections across all services
# (blockchain, blockassembly, validator, RPC, asset_server, UTXO store, etc.)
# Individual services can override these with service-specific settings (see below)
# MaxOpenConns: Maximum number of open connections to the database (must be >= concurrent workers)
postgres_maxOpenConns = 50
# MaxIdleConns: Maximum number of connections in the idle connection pool (keep warm connections)
# Match MaxOpenConns to avoid connection churn — SCRAM-SHA-256 auth on new connections is CPU-expensive
postgres_maxIdleConns = 50
# ConnMaxLifetime: Maximum amount of time a connection may be reused (rotate connections regularly)
postgres_connMaxLifetime = 5m
# ConnMaxIdleTime: Maximum amount of time a connection may be idle before being closed (close stale idle connections)
postgres_connMaxIdleTime = 1m
# Service-Specific PostgreSQL Pool Overrides (optional)
# These override the global settings for specific services when configured
# Example: UTXO store might need different pool settings than blockchain store
# utxostore_postgres_maxOpenConns = 80
# utxostore_postgres_maxIdleConns = 20
# blockchain_postgres_maxOpenConns = 30
# blockchain_postgres_maxIdleConns = 5
PROFILE_PORT = 9091
PROFILE_PORT_TXBLASTER = 9092
PROPAGATION_GRPC_PORT = 8084
PROPAGATION_HTTP_PORT = 8833
SUBTREE_VALIDATION_GRPC_PORT = 8086
TERANODE_RPC_PORT = 9292
VALIDATOR_GRPC_PORT = 8081
VALIDATOR_HTTP_PORT = 8834
# @endgroup
advertisingInterval = 10s
# Advertising Configuration
# -------------------------
advertisingURL =
aerospike_debug = false
# @group: aerospike_policies compact
# The following 3 policies are used for all read/write operations when the aerospike_useDefaultPolicies is false
# SleepBetweenRetries is not being used in the current implementation
# SleepMultiplier is not being used in the current implementation
# ExitFastOnExhaustedConnectionPool is not being used in the current implementation
aerospike_batchPolicy = aerospike:///?MaxRetries=5&SleepBetweenRetries=500ms&SleepMultiplier=1&TotalTimeout=5m&SocketTimeout=60s&ConcurrentNodes=0
# docker.m: bound a single BatchOperate so the client's own retry loop cannot hang for
# minutes on an overloaded single node. The 5m global TotalTimeout means one stuck batch
# blocks a worker far longer than the server-side overload retry budget in
# bsv-blockchain/teranode#1085 (30s default) — the inner call must finish well inside that
# budget for the wrapper retry to control the cadence. 10s total / 5s socket / 2 retries.
aerospike_batchPolicy.docker.m = aerospike:///?MaxRetries=2&SleepBetweenRetries=200ms&SleepMultiplier=1&TotalTimeout=10s&SocketTimeout=5s&ConcurrentNodes=0
aerospike_readPolicy = aerospike:///?MaxRetries=5&SleepBetweenRetries=500ms&SleepMultiplier=1&TotalTimeout=1s&SocketTimeout=1s
aerospike_writePolicy = aerospike:///?MaxRetries=5&SleepBetweenRetries=500ms&SleepMultiplier=1&TotalTimeout=1s&SocketTimeout=1s
aerospike_queryPolicy = aerospike:///?MaxRetries=3&SleepBetweenRetries=500ms&SleepMultiplier=1&TotalTimeout=30m&SocketTimeout=25m
# @endgroup
aerospike_useDefaultBasePolicies = false
aerospike_useDefaultPolicies = false
aerospike_warmUp = true
alert_genesis_keys = "02a1589f2c8e1a4e7cbf28d4d6b676aa2f30811277883211027950e82a83eb2768 | 03aec1d40f02ac7f6df701ef8f629515812f1bcd949b6aa6c7a8dd778b748b2433 | 03ddb2806f3cc48aa36bd4aea6b9f1c7ed3ffc8b9302b198ca963f15beff123678 | 036846e3e8f4f944af644b6a6c6243889dd90d7b6c3593abb9ccf2acb8c9e606e2 | 03e45c9dd2b34829c1d27c8b5d16917dd0dc2c88fa0d7bad7bffb9b542229a9304"
alert_p2p_private_key = "e76c77795b43d2aacd564648bffebde74a4c31540357dad4a3694a561b4c4f1fbb0ba060a3015f7f367742500ef8486707e58032af1b4dfdb1203c790bcf2526"
alert_protocol_id = "/bitcoin/alert-system/1.0.0"
alert_store = sqlite:///alert
alert_topic_name = "bitcoin_alert_system"
asset_apiPrefix = /api/v1
asset_centrifugeListenAddress = :${CENTRIFUGE_PORT}
asset_centrifugeListenAddress.dev = localhost:${CENTRIFUGE_PORT}
# turn this on to activate the centrifuge server
asset_centrifuge_disable = false
asset_httpAddress = http://localhost:${ASSET_HTTP_PORT}${asset_apiPrefix}
asset_httpAddress.docker = http://${clientName}:${ASSET_HTTP_PORT}${asset_apiPrefix}
asset_httpAddress.docker.m = http://asset:${ASSET_HTTP_PORT}${asset_apiPrefix}
asset_httpAddress.docker.ss.teranode1 = http://asset-1:${ASSET_HTTP_PORT}${asset_apiPrefix}
asset_httpAddress.operator = http://asset:8090${asset_apiPrefix}
asset_httpListenAddress = :${ASSET_HTTP_PORT}
asset_httpListenAddress.dev = localhost:${ASSET_HTTP_PORT}
# these define the publicly available asset endpoint other Teranodes can use to download subtree/blocks
# asset_httpPublicAddress = "https://myteranode.example.com/api/v1"
# Optional URL for other peers to use for propagating transactions to this node
# If not set, defaults to asset_httpPublicAddress (or asset_httpAddress if that's also empty)
# asset_propagationPublicURL = "https://propagation.myteranode.example.com/api/v1"
# Propagation proxy: enables POST /api/v1/tx on asset server to proxy to propagation service
asset_propagation_proxy_enabled = true
asset_propagation_proxy_address = http://localhost:${PROPAGATION_HTTP_PORT}
asset_propagation_proxy_address.docker = http://${clientName}:${PROPAGATION_HTTP_PORT}
asset_propagation_proxy_address.docker.m = http://propagation:${PROPAGATION_HTTP_PORT}
asset_propagation_proxy_address.operator = http://propagation.${clientName}.svc.cluster.local:${PROPAGATION_HTTP_PORT}
# Asset Repository Concurrency Limits
# Limits concurrent operations per repository method
# Values: 0 = unlimited, -1 = runtime.NumCPU(), >0 = exact limit
# Recommended for high-load scenarios to prevent Aerospike overload
# Defaults listed below are the values applied when the key is unset.
# The subtree-related keys default to bounded non-zero values to cap memory
# under bursty traffic; raise them only after measuring impact.
# asset_concurrency_get_transaction = 0 # default: 0 (unlimited)
# asset_concurrency_get_transaction_meta = 0 # default: 0 (unlimited)
# asset_concurrency_get_subtree_data = 2 # default: 2
# asset_concurrency_get_subtree_data_reader = 4 # default: 4
# asset_concurrency_get_subtree_transactions = 2 # default: 2
# asset_concurrency_get_subtree_exists = 0 # default: 0 (unlimited)
# asset_concurrency_get_subtree_head = 0 # default: 0 (unlimited)
# asset_concurrency_get_utxo = 0 # default: 0 (unlimited)
# asset_concurrency_get_legacy_block_reader = 0 # default: 0 (unlimited)
# asset_subtreeDataStreamingConcurrency = 2 # default: 2 (concurrent chunk workers per streaming request)
blockMinedCacheMaxMB = 256
blockMinedCacheMaxMB.docker = 32
blockpersister_store = ${blockstore}
blockpersister_httpListenAddress = :${BLOCK_PERSISTER_HTTP_PORT}
blockpersister_concurrency = 8
blockpersister_batchMissingTransactions = true
blockpersister_skipUTXODelete = false
blockpersister_persistSleep = 10s
blockpersister_processUTXOFiles = true
block_checkDuplicateTransactionsConcurrency.docker.m = 32
block_checkDuplicateTransactionsConcurrency.operator = 32
# block concurrency settings
block_getAndValidateSubtreesConcurrency.docker.m = 32
block_getAndValidateSubtreesConcurrency.operator = 32
block_validOrderAndBlessedConcurrency.docker.m = 32
block_validOrderAndBlessedConcurrency.operator = 32
blockassembly_difficultyCache = true
blockassembly_disabled = false
blockassembly_grpcAddress = localhost:${BLOCK_ASSEMBLY_GRPC_PORT}
blockassembly_grpcAddress.docker.m = blockassembly:${BLOCK_ASSEMBLY_GRPC_PORT}
blockassembly_grpcAddress.docker = ${clientName}:${BLOCK_ASSEMBLY_GRPC_PORT}
blockassembly_grpcAddress.operator = k8s:///block-assembly.${clientName}.svc.cluster.local:${BLOCK_ASSEMBLY_GRPC_PORT}
blockassembly_grpcAddress.docker.ss.teranode1 = blockassembly-1:${BLOCK_ASSEMBLY_GRPC_PORT}
blockassembly_grpcListenAddress = :${BLOCK_ASSEMBLY_GRPC_PORT}
blockassembly_grpcListenAddress.dev = localhost:${BLOCK_ASSEMBLY_GRPC_PORT}
blockassembly_grpcMaxRetries = 3
blockassembly_grpcMaxRetries.operator.teratestnet = 5
blockassembly_grpcRetryBackoff = 2s
blockassembly_grpcRetryBackoff.operator.teratestnet = 5s
# the local DAH cache is only used when remote TTL stores are enabled
blockassembly_localDAHCache =
blockassembly_maxBlockReorgCatchup = 100
blockassembly_maxBlockReorgRollback = 100
blockassembly_moveBackBlockConcurrency.operator = 375
blockassembly_processRemainderTxHashesConcurrency.operator = 375
blockassembly_sendBatchSize = 1024
blockassembly_sendBatchTimeout = 5
blockassembly_subtreeProcessorBatcherSize = 32768
blockassembly_subtreeProcessorConcurrentReads = 375
blockassembly_useDynamicSubtreeSize = true
# Parent chain validation on restart
# When enabled, validates that parent transactions are on the best chain after restart
blockassembly_onRestartValidateParentChain = true
# Remove transactions with invalid parent chains on restart (requires onRestartValidateParentChain = true)
# When false: logs warnings but keeps transactions
# When true (default): logs warnings and removes invalid transactions
blockassembly_onRestartRemoveInvalidParentChainTxs = true
# Batch size for parent transaction queries during validation
# Larger values reduce round-trips but use more memory
blockassembly_parentValidationBatchSize = 1000
# Interval for announcing the current subtree when the network is not busy
# Ensures subtrees are announced at least every N seconds even during low activity
blockassembly_subtreeAnnouncementInterval = 10s
# Sleep duration when subtree processor queue is empty
# Prevents excessive CPU usage from busy-waiting while allowing responsive processing
blockassembly_idle_sleep_duration = 10ms
blockchain_grpcAddress = localhost:${BLOCKCHAIN_GRPC_PORT}
blockchain_grpcAddress.docker = ${clientName}:${BLOCKCHAIN_GRPC_PORT}
blockchain_grpcAddress.docker.m = blockchain:${BLOCKCHAIN_GRPC_PORT}
blockchain_grpcAddress.docker.ss.teranode1 = blockchain-1:${BLOCKCHAIN_GRPC_PORT}
blockchain_grpcAddress.operator = k8s:///blockchain.${clientName}.svc.cluster.local:${BLOCKCHAIN_GRPC_PORT}
blockchain_grpcListenAddress = :${BLOCKCHAIN_GRPC_PORT}
blockchain_grpcListenAddress.docker = 0.0.0.0:${BLOCKCHAIN_GRPC_PORT}
blockchain_grpcListenAddress.docker.m = :${BLOCKCHAIN_GRPC_PORT}
blockchain_grpcListenAddress.dev = localhost:${BLOCKCHAIN_GRPC_PORT}
blockchain_httpListenAddress = :${BLOCKCHAIN_HTTP_PORT}
blockchain_httpListenAddress.dev = localhost:${BLOCKCHAIN_HTTP_PORT}
blockchain_initializeNodeInState =
blockchain_use_in_memory_chain_check = false
# Blockchain Service Configuration
# --------------------------------
# @group: blockchain_store compact
# @endgroup
blockchain_store = sqlite:///blockchain
blockchain_store.dev = postgres://teranode:teranode@localhost:${POSTGRES_PORT}/teranode
blockchain_store.docker.m = postgres://teranode:teranode@postgres:${POSTGRES_PORT}/teranode
blockchain_store.docker.ss.teranode1 = postgres://miner1:miner1@postgres:${POSTGRES_PORT}/teranode1
blockchain_store.docker = postgres://${blockchainDBUserPwd}:${blockchainDBUserPwd}@postgres:${POSTGRES_PORT}/${blockchainDB}
blockchain_store.teratestnet = postgres://teranode:teranode@localhost:${POSTGRES_PORT}/teranode
# Set maximum block size in bytes we will mine. Size of the mined block will never exceed the maximum block size we will accept (excessiveblocksize)
blockmaxsize = 0
blockmaxsize.docker.m = 4294967296
blockmaxsize.operator = 4294967296
blockstore = file://${DATADIR}/blockstore?localTTLStore=file&localTTLStorePath=${DATADIR}/blockstore-ttl-1 | ${DATADIR}/blockstore-ttl-2
blockstore.dev = file://${DATADIR}/blockstore?localTTLStore=file&localTTLStorePath=${DATADIR}/blockstore-ttl
blockstore.docker = file://${DATADIR}/blockstore
blockstore.operator = file://${DATADIR}/${clientName}/blockstore
# File Store Concurrency Limits
# Separate read/write semaphores prevent deadlocks where write operations block on pipe data
# while read operations (that would provide that data) wait for semaphore slots.
# These limits protect against Linux ulimit exhaustion by controlling concurrent file descriptors.
# Total: read + write should stay under your system's open file limit (ulimit -n)
# Default: 768 + 256 = 1024 (matches original single semaphore capacity)
# Tune based on workload: higher read limits benefit read-heavy workloads, higher write limits
# benefit write-heavy workloads. Monitor with: lsof -p <pid> | wc -l
# filestore_read_concurrency = 768 # Concurrent read operations (Get, Exists, GetDAH, GetIoReader)
# filestore_write_concurrency = 256 # Concurrent write operations (Set, Del, SetDAH, SetFromReader)
# quick validation means it only uses the txmeta cache
# (ignored if blockvalidation_validation_max_retries is 0)
# This is only useful when all transactions are sent to all nodes, using something like ipv6
blockvalidation_fail_fast_validation = false
# limit this, this is happening in the background
blockvalidation_finalizeBlockValidationConcurrency = 8
blockvalidation_getMissingTransactions = 32
blockvalidation_grpcAddress = localhost:${BLOCK_VALIDATION_GRPC_PORT}
blockvalidation_grpcAddress.docker.m = blockvalidation:${BLOCK_VALIDATION_GRPC_PORT}
blockvalidation_grpcAddress.operator = k8s:///block-validation.${clientName}.svc.cluster.local:${BLOCK_VALIDATION_GRPC_PORT}
blockvalidation_grpcListenAddress = :${BLOCK_VALIDATION_GRPC_PORT}
blockvalidation_grpcListenAddress.dev = localhost:${BLOCK_VALIDATION_GRPC_PORT}
blockvalidation_localSetTxMinedConcurrency = 8
blockvalidation_maxPreviousBlockHeadersToCheck = 100
# too big a batch and you get asset service timeout challenges
blockvalidation_missingTransactionsBatchSize = 5000
blockvalidation_processTxMetaUsingCache_BatchSize = 1024
blockvalidation_processTxMetaUsingCache_Concurrency = 128
# cache miss threshold is the number of missing txs to allow before we fail
blockvalidation_processTxMetaUsingCache_MissingTxThreshold = 1
blockvalidation_processTxMetaUsingStore_BatchSize = 1024
blockvalidation_processTxMetaUsingStore_Concurrency = 128
# store miss threshold is the number of missing txs when searching our store, ignored during BlockValidation
blockvalidation_processTxMetaUsingStore_MissingTxThreshold = 1
# block validation concurrency settings
# this is basically making subtree processing unlimited
# it is very important that new subtrees are processed as fast as possible
blockvalidation_subtreeFoundChConcurrency = 64
# Timeout for fetching subtrees from peers (default: 120s)
blockvalidation_subtree_fetch_timeout = 120s
# abandon subtree validation when missing total exceeds threshold, ignored during BlockValidation
# This is only useful when all transactions are sent to all nodes, using something like ipv6
blockvalidation_subtree_validation_abandon_threshold = 0
blockvalidation_validateBlockSubtreesConcurrency = 64
blockvalidation_validation_max_retries = 3
blockvalidation_validation_retry_sleep = 5s
# Interval for periodic processing of blocks with mined_set=false (default: 1 minute)
# This is a safety net to catch any blocks that weren't processed immediately.
# Can be set lower for tests (e.g., 100ms) to avoid waiting.
blockvalidation_periodic_processing_interval = 1m
# Maximum number of recent block IDs to load for fast-path double-spend checking
# Larger values use more memory but reduce slow-path blockchain queries
# Transactions mined in blocks older than this window are checked via blockchain service
# Default: 50000 (covers ~347 days of blocks at 10min intervals)
blockvalidation_recentBlockIDsLimit = 50000
blockvalidation_recentBlockIDsLimit.docker.m = 10000
blockvalidation_recentBlockIDsLimit.dev = 1000
# Skip the per-transaction UTXO lock/unlock during quick-validation catchup (default: false).
# Quick validation runs only for blocks at or below the highest checkpoint. Normally each tx's
# UTXOs are created locked and unlocked again after the block is committed — two Aerospike record
# writes per tx, i.e. heavy write amplification on a from-genesis sync. Set to true to skip both for
# checkpointed blocks (UTXOs created unlocked, no unlock pass); blocks above the checkpoint always
# keep the lock. Reversible: set back to false and restart to restore the default behavior.
# Leave false unless a controlled catchup run has validated the throughput gain for your deployment.
blockvalidation_quick_validate_skip_utxo_lock = false
coinbase_arbitrary_text = /teranode/
coinbase_arbitrary_text.operator.teratestnet = /${clientName}-euc/
coinbase_arbitrary_text.operator.mainnet = /${clientName}-euw/
coinbase_arbitrary_text.docker.ss.teranode1 = /m1-eu/
coinbase_grpcAddress = # This should be empty by default
coinbase_grpcAddress.dev = localhost:${COINBASE_GRPC_PORT}
coinbase_grpcAddress.teratestnet = localhost:${COINBASE_GRPC_PORT}
coinbase_grpcAddress.docker.m = teranode-coinbase:${COINBASE_GRPC_PORT}
coinbase_grpcAddress.docker = ${clientName}:${COINBASE_GRPC_PORT}
coinbase_grpcAddress.docker.ss.teranode1 = coinbase-1:${COINBASE_GRPC_PORT}
coinbase_grpcAddress.operator.teratestnet = k8s:///coinbase.${clientName}.svc.cluster.local:${COINBASE_GRPC_PORT}
coinbase_grpcListenAddress = :${COINBASE_GRPC_PORT}
coinbase_grpcListenAddress.dev = localhost:${COINBASE_GRPC_PORT}
coinbase_notification_threshold.operator = 100000
coinbase_p2p_peer_id.dev = 12D3KooWBBV8PL949p46DJHwJkjESoPGCYhqHv1Ek1DkbQ6HGB8X
coinbase_p2p_peer_id.docker.ss.teranode1 = 12D3KooWNQWh27xAsZRuXzANGQjLVJqXGVdp1errjLfc3wWvawZw
coinbase_p2p_private_key.dev = 44a5a189fbad1d7bc0c59b33fbd5e485f2f4d3d8bf293838c56ce72e53b557171444c0bb7d5cf75112717084cee9e9e98651421b3cd29d721e43c0a51d81aa54
coinbase_p2p_private_key.docker.ss.teranode1 = e76c77795b43d2aacd564648bffebde74a4c31540357dad4a3694a561b4c4f1fbb0ba060a3015f7f367742500ef8486707e58032af1b4dfdb1203c790bcf2526
coinbase_p2p_static_peers.dev = /ip4/127.0.0.1/tcp/${P2P_PORT}/p2p/12D3KooWMQira6uh4rptNzMP5sojTdNXyveAWMKJi5ySoepVXGxo
coinbase_p2p_static_peers.docker.m =
coinbase_should_wait = false
coinbase_store = sqlite:///coinbase
coinbase_store.dev = postgres://teranode:teranode@localhost:${POSTGRES_PORT}/coinbase
coinbase_store.docker = postgres://${coinbaseDBUserPwd}:${coinbaseDBUserPwd}@postgres:${POSTGRES_PORT}/${coinbaseDB}
coinbase_store.docker.m = postgres://coinbase1:coinbase1@postgres:${POSTGRES_PORT}/coinbase1
coinbase_store.host.ss.teranode1 = postgres://coinbase1:coinbase1@postgres:${POSTGRES_PORT}/coinbase1
coinbase_store_dbTimeoutMillis = 5000
coinbase_test_mode = false
# coinbase are shared on the same server
coinbase_wait_for_peers = true
coinbase_wait_for_peers.dev.kafka = false
coinbase_wait_for_peers.operator = false
coinbase_wallet_private_key = ${PK1}
coinbase_wallet_private_key.docker.ss.teranode1 = ${PK1}
# Pruner Service Configuration
# ------------------------------
pruner_grpcAddress = localhost:${PRUNER_GRPC_PORT}
pruner_grpcAddress.docker.m = pruner:${PRUNER_GRPC_PORT}
pruner_grpcAddress.docker = ${clientName}:${PRUNER_GRPC_PORT}
pruner_grpcAddress.operator = k8s:///pruner.${clientName}.svc.cluster.local:${PRUNER_GRPC_PORT}
pruner_grpcListenAddress = :${PRUNER_GRPC_PORT}
pruner_grpcListenAddress.dev = localhost:${PRUNER_GRPC_PORT}
# Maximum time to wait for Block Assembly to be in "running" state before skipping pruning
# If Block Assembly is temporarily in a non-running state (reorging, resetting, etc.),
# the pruner will retry checking the state until this timeout is reached
# Default: 10m
pruner_blockAssemblyWaitTimeout = 10m
# Minimum block height before pruning begins
# When set to a value > 0, the pruner skips ALL operations until block height exceeds this value
# Useful for fresh environments where initial blocks must remain available for cross-node validation
# Default: 0 (prune from the start)
pruner_min_block_height = 0
# Skip pruning during blockchain catchup (FSMStateCATCHINGBLOCKS)
# When true, pruner skips all operations during catchup to prevent race conditions where
# block validation marks transactions as mined faster than pruner can preserve their parents.
# Once node transitions to FSMStateRUNNING, pruner resumes normal operation.
# Default: false (not safe with low retention value)
pruner_skipDuringCatchup = false
# Threshold (0.0-1.0) for Aerospike connection pool utilization before auto-adjusting concurrency
# The pruner validates on startup that its concurrency settings won't exceed this threshold.
# If they would, pruner_utxoChunkGroupLimit is automatically reduced to prevent pool exhaustion.
# Formula: maxPrunerConnections = (workers × chunkGroupLimit) + workers
# If maxPrunerConnections > (ConnectionQueueSize × threshold), adjustment occurs
# Default: 0.7 (70% - leaves 30% buffer for other operations)
pruner_connectionPoolWarningThreshold = 0.7
# Timeout for waiting for pruner job completion before coordinator moves on
# Large pruning operations (multi-million rows) may exceed this timeout, which is normal
# The pruner continues in background and will be re-queued immediately
# Default: 10m
pruner_jobTimeout = 10m
# UTXO-specific pruning settings
# Enable defensive checks before deleting UTXO transactions
# When enabled, verifies that all spending children are mined > BlockHeightRetention blocks ago
# Default: false
pruner_utxoDefensiveEnabled = false
# Batch size for reading child transactions during defensive UTXO pruning
pruner_utxoDefensiveBatchReadSize = 1024
# Chunk-based pruning settings (used by parallel partition pruning)
# Records are processed in chunks for efficient batch verification and operations
pruner_utxoChunkSize = 1024 # Records per chunk
pruner_utxoChunkGroupLimit = 1 # Parallel chunks per worker - at scale this can kill tx throughput so be conservative
pruner_utxoProgressLogInterval = 30s # Progress logging interval
# Parallel partition pruning (new in parallel implementation)
# 0 = auto-detect based on CPU cores and Aerospike query-threads-limit
# Typical: 16-32 workers on high-end servers for 30M+ records/second
pruner_utxoPartitionQueries = 0
pruner_utxoPartitionQueries.docker.m = 8
# Use TTL-based expiration instead of hard deletes for UTXO records
# When enabled, sets record TTL to 1 second instead of deleting, allowing
# Aerospike's nsup thread to handle expiration with optimized tombstone handling
# Default: false (standard hard delete)
pruner_utxoSetTTL = false
# @group: dashboard
# Vite dev server ports (comma-separated)
# dashboard_devServerPorts = 5173,4173
# Dashboard UI
# ------------------------
dashboard_enabled = true
# WebSocket path
# dashboard_websocketPath = /connection/websocket
# WebSocket port for development environment
# dashboard_websocketPort = 8090
# @endgroup
double_spend_window_millis = 0
# policy settings
# use these if you do not want unbounded scaling
excessiveblocksize = 10737418240
# end of policy settings
faucet_httpListenAddress = :${FAUCET_HTTP_PORT}
faucet_httpListenAddress.dev = localhost:${FAUCET_HTTP_PORT}
faucet_httpListenAddress.docker.m = :${FAUCET_HTTP_PORT}
fsm_state_restore = false
global_blockHeightRetention = 288
# @group: gocore
# Core Stats Configuration
# ------------------------
gocore_stats_reported_time_threshold = 24h
stats_prefix = gocore
# @endgroup
# TODO: change api key and move out of settings
grpc_admin_api_key = testkey
# Grpc Resolver Configuration
grpc_resolver = dns
grpc_resolver.operator = kubernetes
health_check_httpListenAddress = :${HEALTH_CHECK_PORT}
http_sign_response = true
http_timeout = 30000
# HTTP streaming timeout in milliseconds for large file downloads (subtree data, blocks during catchup)
# This is longer than http_timeout to accommodate large subtree data files which can be 100+ MB
# Default: 600000ms (10 minutes)
http_streaming_timeout = 600000
# IPV6 Addresses
# --------------
# ipv6_addresses = ff02::1234
k8s_resolver_ttl = 10
k8s_resolver_ttl.dev = 0
kafka_blocksConfig = ${KAFKA_SCHEMA}://${KAFKA_HOSTS}/${KAFKA_BLOCKS}?partitions=${KAFKA_PARTITIONS_LOW}&replication=${KAFKA_REPLICATION_FACTOR}&retention=60000&flush_bytes=64&consumerTimeout=1800000
kafka_blocksFinalConfig = ${KAFKA_SCHEMA}://${KAFKA_HOSTS}/${KAFKA_BLOCKS_FINAL}?partitions=${KAFKA_PARTITIONS_LOW}&replication=${KAFKA_REPLICATION_FACTOR}&retention=60000&flush_bytes=64&consumerTimeout=1800000
kafka_invalidBlocksConfig = ${KAFKA_SCHEMA}://${KAFKA_HOSTS}/${KAFKA_INVALID_BLOCKS}?partitions=${KAFKA_PARTITIONS_LOW}&replication=${KAFKA_REPLICATION_FACTOR}&retention=600000&flush_bytes=1024&flush_messages=10000&flush_frequency=1s&replay=0
kafka_invalidSubtreesConfig = ${KAFKA_SCHEMA}://${KAFKA_HOSTS}/${KAFKA_INVALID_SUBTREES}?partitions=${KAFKA_PARTITIONS_HIGH}&replication=${KAFKA_REPLICATION_FACTOR}&retention=60000&segment_bytes=33554432&flush_bytes=64&flush_messages=1&replay=0
kafka_legacyInvConfig = ${KAFKA_SCHEMA}://${KAFKA_HOSTS}/${KAFKA_LEGACY_INV}?partitions=${KAFKA_PARTITIONS_HIGH}&replication=${KAFKA_REPLICATION_FACTOR}&retention=6000&flush_bytes=1024&flush_messages=16&flush_frequency=10ms
kafka_rejectedTxConfig = ${KAFKA_SCHEMA}://${KAFKA_HOSTS}/${KAFKA_REJECTEDTX}?partitions=${KAFKA_PARTITIONS_LOW}&replication=${KAFKA_REPLICATION_FACTOR}&retention=600000&flush_bytes=1024&flush_messages=10000&flush_frequency=1s&replay=0
# subtree processing when propagation distributes to all nodes it super fast.
# sutree processing with no tx distrubtion is much slower and can take minutes for a very large subtree
# Excessive timeouts can mask performance issues.
# Monitor p99 latency and adjust if most subtrees complete faster than these limits.
kafka_subtreesConfig = ${KAFKA_SCHEMA}://${KAFKA_HOSTS}/${KAFKA_SUBTREES}?partitions=${KAFKA_PARTITIONS_HIGH}&replication=${KAFKA_REPLICATION_FACTOR}&retention=1800000&segment_bytes=33554432&flush_bytes=64&flush_messages=1&replay=0&maxProcessingTime=30000&sessionTimeout=120000&heartbeatInterval=20000&offsetReset=latest
kafka_txmetaConfig = ${KAFKA_SCHEMA}://${KAFKA_HOSTS}/${KAFKA_TXMETA}?partitions=${KAFKA_PARTITIONS_HIGH}&replication=${KAFKA_REPLICATION_FACTOR}&retention=60000&flush_bytes=1024&flush_messages=10000&flush_frequency=10ms
kafka_unitTest = ${KAFKA_SCHEMA}://localhost:${KAFKA_PORT}/${KAFKA_UNITTEST}?partitions=${KAFKA_PARTITIONS_LOW}&replication=${KAFKA_REPLICATION_FACTOR}&retention=600000&flush_bytes=1024&flush_messages=10000&flush_frequency=1s
# tx validation order is critical so we cannot have mutiple partitions :(
kafka_validatortxsConfig =
kafka_validatortxsConfig.operator = ${KAFKA_SCHEMA}://${KAFKA_HOSTS}/${KAFKA_VALIDATORTXS}?partitions=${KAFKA_PARTITIONS_HIGH}&replication=${KAFKA_REPLICATION_FACTOR}&retention=60000&flush_bytes=8192&flush_messages=10000&flush_frequency=10ms
kafka_validatortxsConfig.operator.teratestnet =
# Enable the multistreams protocol for legacy P2P connections to BSV Blockchain nodes.
# When enabled, peers negotiate multiple TCP streams per connection using stream
# policies (e.g. BlockPriority), separating block traffic from general traffic.
# Required for reliable download of large (multi-GB) mainnet blocks.
legacy_allowBlockPriority = true
legacy_allowSyncCandidateFromLocalPeers.docker = true
# legacy_config_AddPeers = 18.199.12.185:8333 | 3.213.100.250:8333 | 44.213.141.106:8333
# Any config from the legacy Config struct can be set here
# they need to be defined with a default value so they can be overridden from the env
legacy_config_ConnectPeers =
# legacy_config_ConnectPeers = 18.199.12.185:8333 | 3.213.100.250:8333 | 44.213.141.106:8333
# legacy_config_ConnectPeers = 3.123.101.88:18333 | 23.22.19.204:18333
legacy_config_DataDir = ${DATADIR}/legacy
legacy_config_DataDir.operator = ${DATADIR}/${clientName}/legacy
legacy_config_DisableCheckpoints = false
# this forces IPv4 only, set to empty for IPv4 & IPv6 support
legacy_config_Listeners = "0.0.0.0"
legacy_config_MaxPeers = 20
legacy_config_MaxPeersPerIP = 5
legacy_config_Upnp = false
legacy_config_Upnp.dev = true
legacy_config_Upnp.docker = true
legacy_config_Upnp.docker.m = false
legacy_grpcAddress = localhost:${LEGACY_GRPC_PORT}
legacy_grpcAddress.docker.m = legacy:${LEGACY_GRPC_PORT}
legacy_grpcAddress.operator = k8s:///legacy.${clientName}.svc.cluster.local:${LEGACY_GRPC_PORT}
legacy_grpcListenAddress = :${LEGACY_GRPC_PORT}
legacy_grpcListenAddress.dev = localhost:${LEGACY_GRPC_PORT}
legacy_httpAddress = http://localhost:${LEGACY_HTTP_PORT}
legacy_httpAddress.docker = http://${clientName}:${LEGACY_HTTP_PORT}
legacy_httpAddress.docker.m = http://legacy:${LEGACY_HTTP_PORT}
legacy_httpAddress.docker.ss.teranode1 = http://legacy-1:${LEGACY_HTTP_PORT}
legacy_httpAddress.operator = http://legacy.${clientName}.svc.cluster.local:${LEGACY_HTTP_PORT}
legacy_httpListenAddress = :${LEGACY_HTTP_PORT}
legacy_httpListenAddress.dev = localhost:${LEGACY_HTTP_PORT}
legacy_outpointBatcherConcurrency = 32
legacy_outpointBatcherSize = 1024
legacy_peerProcessingTimeout = 10m
legacy_printInvMessages = false
legacy_printInvMessages.dev = true
legacy_spendBatcherConcurrency = 4
legacy_spendBatcherSize = 1024
legacy_storeBatcherConcurrency = 32
# docker.m: createUtxos feeds the store batcher from an errgroup limited to
# legacy_storeBatcherSize x legacy_storeBatcherConcurrency. The global 1024 x 32 = 32768
# concurrent Create calls force-feed a single-node Aerospike far faster than it drains.
# 1024 x 4 = 4096 keeps the feed in line with utxostore_batcherMaxConcurrent.docker.m.
legacy_storeBatcherConcurrency.docker.m = 4
legacy_storeBatcherSize = 1024
legacy_workingDir = ${DATADIR}/legacy
# node listen mode: full (default, normal operation) or listen_only (receive only, no outbound messages)
# Applies to the modern P2P service only (DataHub URL advertisement, subtree/block/
# reject propagation). The legacy P2P announce path is intentionally NOT gated by
# this setting — legacy peers are explicit via legacy_config_ConnectPeers and the
# bog-standard Bitcoin INV→GETDATA flow is a separate concern. See PR #955 review.
#
# The .dev override stays at listen_only: dev nodes typically have unreachable
# asset_httpPublicAddress endpoints and shouldn't advertise DataHub URLs on the
# modern P2P service or be selected as a sync source. After PR #955 dropped the
# legacy-side gate, this override no longer silently disables legacy tx announce
# in dev runs — it does only what its modern-P2P docs say it does.
listen_mode = full
listen_mode.dev = listen_only
# only enable full listen_mode if you're asset_httpPublicAddress is publicly available for other nodes to download from
local_test_start_from_state =
# @group: logger
logLevel = INFO
# logLevel.dev = DEBUG
# Logging Configuration
# ---------------------
logger = zerolog
logger_output_format = | %-25s | %-7s | %s |
logger_show_socket_info = true
logger_show_timestamps = true
# @endgroup
# Subsystem debug toggles (spike defaults)
debug_all = false
debug_file = false
debug_blobstore = false
debug_utxostore = false
maxtxsigopscountspolicy = 4294967295
maxtxsizepolicy = 100000000
min_block_height_for_e2e = 100
# @group: miner_wallet_private_keys compact
PK1 = L56TgyTpDdvL3W24SMoALYotibToSCySQeo4pThLKxw6EFR6f93Q
PK2 = KyAwSjuXZNgj78w3W7mR1fVMbPFu2heaCJJkWK5Yy58NZ4xafV6k
PK3 = L3NVjmwg3nC7ZPrwMVF6FXiG1a1RZ89nhizmJVctGztRKLYrhtFL
PK4 = L3NVjmwg3nC7ZPrwMVF6FXiG1a1RZ89nhizmJVctGztRKLYrhtFL
PK5 = L3NVjmwg3nC7ZPrwMVF6FXiG1a1RZ89nhizmJVctGztRKLYrhtFL
PK6 = L3NVjmwg3nC7ZPrwMVF6FXiG1a1RZ89nhizmJVctGztRKLYrhtFL
# @endgroup
miner_wallet_private_keys = ${PK1}
miner_wallet_private_keys.operator.teratestnet = ${PK1} | ${PK2} | ${PK3}
miner_wallet_private_keys.operator.mainnet = ${PK1} | ${PK2} | ${PK3}
miner_wallet_private_keys.docker = ${PK1} | ${PK2} | ${PK3}
# This is the minimum fee per kB for transactions and is specified
# like in bitcoin-sv in BSV/kB. Therefore 0.00000001 is 1 satoshi per kB.
# Unless this value is exactly 0, transaction fees will always round
# to a minimum of 1 satoshi.
minminingtxfee = 0.00000001
minminingtxfee.dev = 0
minminingtxfee.docker = 0
minminingtxfee.docker.m = 0.00000001
minminingtxfee.teratestnet = 0
# network can be main, stn, test and regtest.
network = mainnet
network.dev = regtest # used by unit tests in your IDE
network.teratestnet = teratestnet
network.test = regtest # used by long tests
network.docker = regtest
network.operator = mainnet
network.operator.testnet = testnet
network.operator.teratestnet = teratestnet
network.dev.legacy.testnet = testnet
network.dev.legacy.mainnet = mainnet
# use separator | to list multiple advertise addresses (optional, for nodes behind proxies)
p2p_advertise_addresses =
p2p_advertise_addresses.dev =
p2p_advertise_addresses.teratestnet =
p2p_ban_duration = 24h
p2p_ban_threshold = 100
p2p_bestblock_topic = bestblock
p2p_block_topic = block
# Bootstrap peers for P2P network discovery (required for p2p_dht_mode "off" and "client").
# Resolved dynamically via DNS TXT records using the /dnsaddr/ protocol.
# This list is managed by the BSV Association — any Teranode running in
# p2p_dht_mode "server" with a public address can be added (contact BSVA).
# To override, use pipe-separated /dns4/ or /ip4/ multiaddrs.
p2p_bootstrap_peers = /dnsaddr/${network}.bootstrap.teranode.bsvb.tech
# NAT Traversal Settings
# These settings help nodes behind NAT/firewall establish connections
# Enable NAT port mapping using UPnP/NAT-PMP (default: false)
# This attempts to automatically configure your router to forward P2P ports
p2p_enable_nat = false
# Only enable this on home networks
p2p_enable_nat.dev = true
# Force sync from a specific peer ID, overriding automatic peer selection
# Empty string (default) means automatic selection based on best chain
# Format: libp2p peer ID (e.g., "12D3KooWG6aCkDmi5tqx4G4AvVDTQdSVvTSzzQvk1vh9CtSR8KEW")
p2p_force_sync_peer =
# If true, fall back to pruned nodes when no full nodes are available (default: true)
# When enabled, selects the youngest pruned node (smallest lag) to minimize UTXO pruning risk
p2p_allow_pruned_node_fallback = true
# DHT (Distributed Hash Table) configuration
# DHT mode: "server", "client", or "off" (default: "off")
# - "server": Full DHT participation. Advertises, stores provider records, routes queries.
# High overhead but collects peer addresses. Use for bootstrap/relay servers.
# Recommended: Configure p2p_advertise_addresses with your public IP/port
# (e.g., /ip4/203.0.113.1/tcp/9905) to be discoverable by other peers.
# - "client": Queries DHT but doesn't advertise. Still connects to 100+ peers for routing.
# Suitable for development environments and home networks.
# - "off": No DHT. Topic-only network. Only connects to bootstrap peers + topic peers.
# Most lightweight - no DHT crawling, no random connections.
# RECOMMENDED for abuse-sensitive cloud hosting (Hetzner, OVH) to avoid
# network scanning alerts from connecting to 100+ random IPs.
# Uses custom peer address exchange to get addresses from bootstrap servers.
p2p_dht_mode = off
p2p_dht_mode.operator = server
p2p_dht_mode.dev = client
# DHT cleanup interval: How often to clean up expired provider records (only applies in server mode)
# Default: 24h (reduces CPU usage compared to libp2p default of 1h)
# Increase this value to reduce CPU overhead from DHT maintenance
p2p_dht_cleanup_interval = 24h
p2p_grpcAddress = localhost:${P2P_GRPC_PORT}
p2p_grpcAddress.docker.m = peer:${P2P_GRPC_PORT}
p2p_grpcAddress.operator = k8s:///peer.${clientName}.svc.cluster.local:${P2P_GRPC_PORT}
p2p_grpcListenAddress = :${P2P_GRPC_PORT}
p2p_grpcListenAddress.dev = localhost:${P2P_GRPC_PORT}
p2p_handshake_topic = handshake
p2p_httpAddress = localhost:${P2P_HTTP_PORT}
p2p_httpAddress.dev = localhost:${P2P_HTTP_PORT}
p2p_httpAddress.operator = peer.${clientName}.svc.cluster.local:${P2P_HTTP_PORT}
p2p_httpAddress.docker.m = peer:${P2P_HTTP_PORT}
p2p_httpAddress.docker.ss.teranode1 = p2p-1:${P2P_HTTP_PORT}
p2p_httpListenAddress = :${P2P_HTTP_PORT}
p2p_httpListenAddress.dev = localhost:${P2P_HTTP_PORT}
p2p_httpListenAddress.docker = localhost:${P2P_HTTP_PORT}
p2p_httpListenAddress.docker.m = :${P2P_HTTP_PORT}
p2p_httpListenAddress.docker.ss = 0.0.0.0:${P2P_HTTP_PORT}
# use separator | to list multiple listen addresses
p2p_listen_addresses = 0.0.0.0
p2p_listen_addresses.dev = 127.0.0.1
p2p_mining_on_topic = miningon
# Optimise connection retries for better peer discovery
p2p_optimise_retries = true
# Peer Cache Settings
# Peer caching remembers successful peer connections for faster network recovery after restarts
# Directory for storing the peer cache file (default: current DATADIR)
# The cache file will always be named "teranode_peers.json"
# Leave empty to store teranode_peers.json in the current working directory
p2p_peer_cache_dir = ${DATADIR}
p2p_peer_cache_dir.operator = ${DATADIR}/${clientName}
p2p_peer_id.teratestnet =
p2p_peer_id.docker.ss.teranode1 = 12D3KooWAFXWuxgdJoRsaA4J4RRRr8yu6WCrAPf8FaS7UfZg3ceG
p2p_port = ${P2P_PORT}
p2p_port_coinbase = ${P2P_PORT}
p2p_port_coinbase.dev = ${P2P_PORT_COINBASE}
p2p_port_coinbase.docker = ${P2P_PORT_COINBASE}
p2p_port_coinbase.operator = ${P2P_PORT_COINBASE}
# create your own private key and peer ID using cmd/keygen, or have Teranode auto-generate
p2p_private_key.docker.ss.teranode1 = c8a1b91ae120878d91a04c904e0d565aa44b2575c1bb30a729bd3e36e2a1d5e6067216fa92b1a1a7e30d0aaabe288e25f1efc0830f309152638b61d84be6b71d
p2p_private_key.operator.mainnet.stage.1 = a4a361d2e1d3b73a4a50857794bf0a2dd148bf18531203dc403220f2365e06e3c12bcc09668d9603cd9f0e223ca101a59e9677721bd4d85a21f24d6faf79f22e
# The P2P topic to publish rejected transaction messages
p2p_rejected_tx_topic = rejected_tx
# Allow sharing of private IP addresses in peer lists (default: false)
# Set to true if you need peers to discover each other using private IPs (e.g., in private networks)
p2p_share_private_addresses = false
p2p_shared_key = 285b49e6d910726a70f205086c39cbac6d8dcc47839053a21b1f614773bbc137
# p2p_static_peers is optional, the node will use the bootstrap addresses to find peers regardless
p2p_static_peers =
p2p_static_peers.docker.m =
p2p_subtree_topic = subtree
# Number of stuck attempts before switching sync peers (default: 1)
p2p_sync_stuck_retry_threshold = 1
peerStatus_timeout = 5m
# Profiler Configuration
# ---------------------------------------
profilerAddr = :${PROFILE_PORT}
profilerAddr.dev = localhost:${PROFILE_PORT}
prometheusEndpoint = /metrics
# @group: propagation compact
PROD_T1 = dns:///prod-teranet-1.teratestnet.ubsv.dev:${PROPAGATION_GRPC_PORT}
PROD_T2 = dns:///prod-teranet-2.teratestnet.ubsv.dev:${PROPAGATION_GRPC_PORT}
PROD_T3 = dns:///prod-teranet-3.teratestnet.ubsv.dev:${PROPAGATION_GRPC_PORT}
# @endgroup
# Note the following settings can be a pipe separated list
propagation_grpcAddresses = localhost:${PROPAGATION_GRPC_PORT}
propagation_grpcAddresses.docker = teranode1:${PROPAGATION_GRPC_PORT} | teranode2:${PROPAGATION_GRPC_PORT} | teranode3:${PROPAGATION_GRPC_PORT}
propagation_grpcAddresses.docker.m = propagation:${PROPAGATION_GRPC_PORT}
propagation_grpcAddresses.docker.ss.teranode1 = propagation-1:${PROPAGATION_GRPC_PORT}
propagation_grpcAddresses.operator.teratestnet.prod = ${PROD_T1} | ${PROD_T2} | ${PROD_T3}
propagation_grpcAddresses.operator = k8s:///propagation.${clientName}.svc.cluster.local:${PROPAGATION_GRPC_PORT}
propagation_grpcListenAddress = :${PROPAGATION_GRPC_PORT}
propagation_grpcListenAddress.dev = localhost:${PROPAGATION_GRPC_PORT}
propagation_grpcMaxConnectionAge = 30s
propagation_grpcMaxConnectionAge.operator = 5m
propagation_httpAddresses = http://localhost:${PROPAGATION_HTTP_PORT}
propagation_httpAddresses.docker = http://${clientName}:${PROPAGATION_HTTP_PORT}
propagation_httpAddresses.docker.m = http://propagation:${PROPAGATION_HTTP_PORT}
propagation_httpAddresses.operator = http://propagation.${clientName}.svc.cluster.local:${PROPAGATION_HTTP_PORT}
propagation_httpAddresses.docker.ss.teranode1 = http://propagation-1:${PROPAGATION_HTTP_PORT}
# 6 nodes
propagation_httpListenAddress = :${PROPAGATION_HTTP_PORT}
propagation_httpListenAddress.dev = localhost:${PROPAGATION_HTTP_PORT}
# set this to 0 to disable the propagation client from sending transactions to the propagation service in batches
propagation_sendBatchSize = 100
propagation_sendBatchTimeout = 10
# The alert service uses this to connect to the rpc
rpc_address = http://localhost:${TERANODE_RPC_PORT}
rpc_listener_url = http://:${TERANODE_RPC_PORT}
rpc_listener_url.docker.m = http://:${TERANODE_RPC_PORT}
rpc_max_clients = 3
rpc_pass = bitcoin
rpc_user = bitcoin
securityLevelGRPC = 0
# Security Configuration
# ---------------------------------------
securityLevelHTTP = 0
server_certFile = certs/teranode.crt