-
Notifications
You must be signed in to change notification settings - Fork 5
/
docker-compose.yml
483 lines (446 loc) · 17.1 KB
/
docker-compose.yml
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
version: "3.9"
x-common-vars:
- &STACKS_BLOCKCHAIN_COMMIT e2bd98230483a3ee18d03cbfccfc795dbdcb2004 # develop, Oct 14, 12:20 PST
- &STACKS_API_COMMIT f6e50f6d28f292d79dbebd70b2b00831c95997f6 # 7.13.2
- &BITCOIN_ADDRESSES miEJtNKa3ASpA19v5ZhvbKTEieYjLpzCYT
- &MINER_SEED 9e446f6b0c6a96cf2190e54bcd5a8569c3e386f091605499464389b8d4e0bfc201 # stx: STEW4ZNT093ZHK4NEQKX8QJGM2Y7WWJ2FQQS5C19, btc: miEJtNKa3ASpA19v5ZhvbKTEieYjLpzCYT, pub_key: 035379aa40c02890d253cfa577964116eb5295570ae9f7287cbae5f2585f5b2c7c, wif: cStMQXkK5yTFGP3KbNXYQ3sJf2qwQiKrZwR9QJnksp32eKzef1za
- &BITCOIN_PEER_PORT 18444
- &BITCOIN_RPC_PORT 18443
- &BITCOIN_RPC_USER btc
- &BITCOIN_RPC_PASS btc
- &MINE_INTERVAL ${MINE_INTERVAL:-1s}
- &MINE_INTERVAL_EPOCH25 ${MINE_INTERVAL_EPOCH25:-5s} # 5 second bitcoin block times in epoch 2.5
- &MINE_INTERVAL_EPOCH3 ${MINE_INTERVAL_EPOCH3:-30s} # 30 second bitcoin block times in epoch 3
- &NAKAMOTO_BLOCK_INTERVAL 2 # seconds to wait between issuing stx-transfer transactions (which triggers Nakamoto block production)
- &STACKS_20_HEIGHT ${STACKS_20_HEIGHT:-0}
- &STACKS_2_05_HEIGHT ${STACKS_2_05_HEIGHT:-102}
- &STACKS_21_HEIGHT ${STACKS_21_HEIGHT:-103}
- &STACKS_POX2_HEIGHT ${STACKS_POX2_HEIGHT:-104} # 104 is is stacks_block=1, 106 is stacks_block=3
- &STACKS_22_HEIGHT ${STACKS_22_HEIGHT:-105}
- &STACKS_23_HEIGHT ${STACKS_23_HEIGHT:-106}
- &STACKS_24_HEIGHT ${STACKS_24_HEIGHT:-107}
- &STACKS_25_HEIGHT ${STACKS_25_HEIGHT:-108}
- &STACKS_30_HEIGHT ${STACKS_30_HEIGHT:-131}
- &STACKING_CYCLES ${STACKING_CYCLES:-1} # number of cycles to stack-stx or stack-extend for
- &POX_PREPARE_LENGTH ${POX_PREPARE_LENGTH:-5}
- &POX_REWARD_LENGTH ${POX_REWARD_LENGTH:-20}
- &REWARD_RECIPIENT ${REWARD_RECIPIENT:-STQM73RQC4EX0A07KWG1J5ECZJYBZS4SJ4ERC6WN} # priv: 6ad9cadb42d4edbfbe0c5bfb3b8a4125ddced021c4174f829b714ccbf527f02001
- &EXIT_FROM_MONITOR 1 # set to "1" to automatically shut down via monitor.ts
# Choose one to override the default
# - &STACKS_CHAIN_ID ${STACKS_CHAIN_ID:-0x80000000}
- &STACKS_CHAIN_ID ${STACKS_CHAIN_ID:-0x80000100}
- &CUSTOM_CHAIN_IDS ${CUSTOM_CHAIN_IDS:-testnet=0x55005500,mainnet=12345678,mainnet=0xdeadbeaf,testnet=0x80000100}
services:
bitcoind:
networks:
- stacks
build:
context: .
dockerfile: Dockerfile.btc
ports:
- "18443:18443"
- "18444:18444"
volumes:
- ./bitcoin.conf:/root/.bitcoin/bitcoin.conf
- ./init-data:/init-data
- chainstate:/chainstate
environment:
DATA_DIR: /chainstate/bitcoin-data
entrypoint:
- /bin/bash
- -c
- |
set -e
mkdir -p $${DATA_DIR}
rm -rf $${DATA_DIR}/*
bitcoind
bitcoind-miner:
networks:
- stacks
build:
context: .
dockerfile: Dockerfile.btc
depends_on:
- bitcoind
volumes:
- ./bitcoin.conf:/root/.bitcoin/bitcoin.conf
environment:
BITCOIN_ADDRESSES: *BITCOIN_ADDRESSES
MINE_INTERVAL: *MINE_INTERVAL
MINE_INTERVAL_EPOCH3: *MINE_INTERVAL_EPOCH3
MINE_INTERVAL_EPOCH25: *MINE_INTERVAL_EPOCH25
INIT_BLOCKS: 101
STACKS_30_HEIGHT: *STACKS_30_HEIGHT
STACKS_25_HEIGHT: *STACKS_25_HEIGHT
entrypoint:
- /bin/bash
- -c
- |
set -e
trap "exit" INT TERM
trap "kill 0" EXIT
OLD_IFS="$${IFS}"
IFS=','
read -ra BITCOIN_ADDRESSES_ARRAY <<< "$${BITCOIN_ADDRESSES}"
IFS="$${OLD_IFS}"
# Install dependencies
apt update && apt install -y jq bc
# Wait for bitcoin-core container to start
sleep 5
echo "Checking if the main wallet exists"
if ! bitcoin-cli -rpcconnect=bitcoind listwallets | grep -q "main"; then
echo "Generating wallet and initial set of blocks"
bitcoin-cli -rpcconnect=bitcoind -rpcwait getmininginfo
bitcoin-cli -rpcconnect=bitcoind -named createwallet wallet_name="main" descriptors=false load_on_startup=true
fi
# Generate a new or use an existing address for the Bitcoin miner
BITCOIN_MINER_ADDRESS=$$(bitcoin-cli -rpcconnect=bitcoind -rpcwallet="main" getnewaddress "btc_miner")
echo "Bitcoin miner address: $${BITCOIN_MINER_ADDRESS}"
echo "Importing addresses and generating blocks"
# Import the addresses from BITCOIN_ADDRESSES_ARRAY
i=0
for bitcoin_address in "$${BITCOIN_ADDRESSES_ARRAY[@]}"; do
# Create a unique wallet name for each address
wallet_name="stx_miner_$${i}"
# Check if the wallet already exists
if ! bitcoin-cli -rpcconnect=bitcoind listwallets | grep -q "$${wallet_name}"; then
# Create a new wallet with the unique name
bitcoin-cli -rpcconnect=bitcoind -named createwallet wallet_name="$${wallet_name}" descriptors=false load_on_startup=true
echo "Wallet $${wallet_name} created."
else
echo "Wallet $${wallet_name} already exists."
fi
echo "Importing $${bitcoin_address} into wallet $${wallet_name}"
# Import the address into the newly created wallet
bitcoin-cli \
-rpcconnect=bitcoind \
-rpcwallet="$${wallet_name}" \
-named importaddress \
address="$${bitcoin_address}" \
rescan=false \
label="user_addresses"
# Generate 1 block to fund the address
bitcoin-cli -rpcconnect=bitcoind -rpcwallet="$${wallet_name}" -named generatetoaddress nblocks=1 address="$${bitcoin_address}"
# Increment the counter
i=$$((i + 1))
done
# Generate the initial blocks to fund the Bitcoin miner address
bitcoin-cli -rpcconnect=bitcoind -rpcwallet="main" -named generatetoaddress nblocks=$${INIT_BLOCKS} address="$${BITCOIN_MINER_ADDRESS}"
DEFAULT_TIMEOUT=$$(($$(date +%s) + 30))
while true; do
TX_FOUND=false
i=0
for bitcoin_address in "$${BITCOIN_ADDRESSES_ARRAY[@]}"; do
wallet_name="stx_miner_$${i}"
# Get the most recent transaction for the wallet
TX=$$(bitcoin-cli -rpcconnect=bitcoind -rpcwallet="$${wallet_name}" -named listtransactions label='*' count=1 include_watchonly=true)
# Check if there is a transaction
if [ "$${TX}" != "[]" ]; then
# Extract the confirmations
CONFS=$$(echo "$${TX}" | jq '.[0].confirmations')
# Check if there is a transaction with 0 confirmations
if [ "$${CONFS}" = "0" ]; then
echo "Detected unconfirmed transaction in wallet $${wallet_name} (address $${bitcoin_address})"
TX_FOUND=true
fi
else
echo "No transactions found in wallet $${wallet_name}"
fi
# Check this Stacks miner's Bitcoin balance and top it up if it is low
BALANCE=$$(bitcoin-cli -rpcconnect=bitcoind -rpcwallet="$${wallet_name}" getbalances | jq '.watchonly.trusted + .watchonly.untrusted_pending')
BALANCE=$${BALANCE:-0}
if (( $$(echo "$${BALANCE} < 0.1" | bc -l) )); then
echo "Balance of $${bitcoin_address} is low ($${BALANCE} BTC), sending 1 BTC from miner $${BITCOIN_MINER_ADDRESS}."
# Send 1 BTC from BITCOIN_MINER_ADDRESS wallet to bitcoin_address
TXID=$$(bitcoin-cli -rpcconnect=bitcoind -rpcwallet="main" -named sendtoaddress \
address="$${bitcoin_address}" \
amount=1.0 \
subtractfeefromamount=true \
fee_rate=1)
echo "Transaction ID: $${TXID}"
fi
i=$$((i + 1))
done
# Check if any unconfirmed transactions were found or if the timeout has been reached
if [ "$${TX_FOUND}" = true ] || [ $$(date +%s) -gt $${DEFAULT_TIMEOUT} ]; then
if [ $$(date +%s) -gt $${DEFAULT_TIMEOUT} ]; then
echo "Timed out waiting for a mempool tx, mining a btc block..."
else
echo "Detected Stacks mining mempool tx, mining btc block..."
fi
bitcoin-cli -rpcconnect=bitcoind -named -rpcwallet="main" -named generatetoaddress nblocks=1 address="$${BITCOIN_MINER_ADDRESS}"
DEFAULT_TIMEOUT=$(($(date +%s) + 30))
else
echo "No Stacks mining tx detected"
fi
SLEEP_DURATION=$${MINE_INTERVAL}
BLOCK_HEIGHT=$$(bitcoin-cli -rpcconnect=bitcoind getblockcount)
if [ "$${BLOCK_HEIGHT}" -ge $$(( $${STACKS_30_HEIGHT} - 1 )) ]; then
echo "In Epoch3, sleeping for $${MINE_INTERVAL_EPOCH3} ..."
SLEEP_DURATION=$${MINE_INTERVAL_EPOCH3}
elif [ "$${BLOCK_HEIGHT}" -ge "$${STACKS_25_HEIGHT}" ]; then
echo "In Epoch2.5, sleeping for $${MINE_INTERVAL_EPOCH25} ..."
SLEEP_DURATION=$${MINE_INTERVAL_EPOCH25}
fi
sleep $${SLEEP_DURATION} &
wait || exit 0
done
stacks-node:
networks:
- stacks
build:
context: .
dockerfile: Dockerfile.stacks-node
args:
GIT_COMMIT: *STACKS_BLOCKCHAIN_COMMIT
depends_on:
- bitcoind
ports:
- "20443:20443"
volumes:
- ./stacks-krypton-miner.toml/:/root/config.toml.in
- ./bitcoin.conf:/root/.bitcoin/bitcoin.conf
- ./init-data:/init-data
- chainstate:/chainstate
environment:
# STACKS_LOG_TRACE: 1 # uncomment for trace logging
# STACKS_LOG_DEBUG: 1
# RUST_LOG: debug
DATA_DIR: /chainstate/stacks-blockchain-miner-data
BITCOIN_PEER_HOST: bitcoind
BITCOIN_PEER_PORT: *BITCOIN_PEER_PORT
BITCOIN_RPC_PORT: *BITCOIN_RPC_PORT
BITCOIN_RPC_USER: *BITCOIN_RPC_USER
BITCOIN_RPC_PASS: *BITCOIN_RPC_PASS
MINER_SEED: *MINER_SEED
STACKS_20_HEIGHT: *STACKS_20_HEIGHT
STACKS_2_05_HEIGHT: *STACKS_2_05_HEIGHT
STACKS_21_HEIGHT: *STACKS_21_HEIGHT
STACKS_POX2_HEIGHT: *STACKS_POX2_HEIGHT
STACKS_22_HEIGHT: *STACKS_22_HEIGHT
STACKS_23_HEIGHT: *STACKS_23_HEIGHT
STACKS_24_HEIGHT: *STACKS_24_HEIGHT
STACKS_25_HEIGHT: *STACKS_25_HEIGHT
STACKS_30_HEIGHT: *STACKS_30_HEIGHT
POX_PREPARE_LENGTH: *POX_PREPARE_LENGTH
POX_REWARD_LENGTH: *POX_REWARD_LENGTH
REWARD_RECIPIENT: *REWARD_RECIPIENT
STACKS_CHAIN_ID: *STACKS_CHAIN_ID
entrypoint:
- /bin/bash
- -c
- |
set -e
if [[ ! -z "$${REWARD_RECIPIENT}" ]]; then
export REWARD_RECIPIENT_CONF="block_reward_recipient = \"$${REWARD_RECIPIENT}\""
fi
mkdir -p $${DATA_DIR}
rm -rf $${DATA_DIR}/*
envsubst < config.toml.in > config.toml
echo "Starting Stacks with config: $(cat config.toml)"
bitcoin-cli -rpcwait -rpcconnect=bitcoind getmininginfo
exec stacks-node start --config config.toml
stacker:
networks:
- stacks
build:
context: .
dockerfile: Dockerfile.stacker
environment:
STACKS_CORE_RPC_HOST: stacks-node
STACKS_CORE_RPC_PORT: 20443
STACKING_CYCLES: *STACKING_CYCLES
STACKING_KEYS: 6a1a754ba863d7bab14adbbc3f8ebb090af9e871ace621d3e5ab634e1422885e01,b463f0df6c05d2f156393eee73f8016c5372caa0e9e29a901bb7171d90dc4f1401,7036b29cb5e235e5fd9b09ae3e8eec4404e44906814d5d01cbca968a60ed4bfb01
STACKS_25_HEIGHT: *STACKS_25_HEIGHT
STACKS_30_HEIGHT: *STACKS_30_HEIGHT
POX_PREPARE_LENGTH: *POX_PREPARE_LENGTH
POX_REWARD_LENGTH: *POX_REWARD_LENGTH
STACKS_CHAIN_ID: *STACKS_CHAIN_ID
STACKING_INTERVAL: 2 # interval (seconds) for checking if stacking transactions are needed
POST_TX_WAIT: 10 # seconds to wait after a stacking transaction broadcast before continuing the loop
SERVICE_NAME: stacker
depends_on:
- stacks-node
monitor:
networks:
- stacks
build:
context: .
dockerfile: Dockerfile.stacker
environment:
STACKS_CORE_RPC_HOST: stacks-api
STACKS_CORE_RPC_PORT: 3999
STACKING_CYCLES: *STACKING_CYCLES
STACKING_KEYS: 6a1a754ba863d7bab14adbbc3f8ebb090af9e871ace621d3e5ab634e1422885e01,b463f0df6c05d2f156393eee73f8016c5372caa0e9e29a901bb7171d90dc4f1401,7036b29cb5e235e5fd9b09ae3e8eec4404e44906814d5d01cbca968a60ed4bfb01
STACKS_25_HEIGHT: *STACKS_25_HEIGHT
STACKS_30_HEIGHT: *STACKS_30_HEIGHT
POX_PREPARE_LENGTH: *POX_PREPARE_LENGTH
POX_REWARD_LENGTH: *POX_REWARD_LENGTH
EXIT_FROM_MONITOR: *EXIT_FROM_MONITOR
STACKS_CHAIN_ID: *STACKS_CHAIN_ID
SERVICE_NAME: monitor
depends_on:
- stacks-node
entrypoint:
- /bin/bash
- -c
- |
set -e
exec npx tsx /root/monitor.ts
tx-broadcaster:
networks:
- stacks
build:
context: .
dockerfile: Dockerfile.stacker
environment:
STACKS_CORE_RPC_HOST: stacks-node
STACKS_CORE_RPC_PORT: 20443
NAKAMOTO_BLOCK_INTERVAL: *NAKAMOTO_BLOCK_INTERVAL
STACKS_30_HEIGHT: *STACKS_30_HEIGHT
ACCOUNT_KEYS: 0d2f965b472a82efd5a96e6513c8b9f7edc725d5c96c7d35d6c722cedeb80d1b01,975b251dd7809469ef0c26ec3917971b75c51cd73a022024df4bf3b232cc2dc001,c71700b07d520a8c9731e4d0f095aa6efb91e16e25fb27ce2b72e7b698f8127a01
STACKS_25_HEIGHT: *STACKS_25_HEIGHT
POX_PREPARE_LENGTH: *POX_PREPARE_LENGTH
POX_REWARD_LENGTH: *POX_REWARD_LENGTH
STACKS_CHAIN_ID: *STACKS_CHAIN_ID
STACKING_KEYS: 6a1a754ba863d7bab14adbbc3f8ebb090af9e871ace621d3e5ab634e1422885e01,b463f0df6c05d2f156393eee73f8016c5372caa0e9e29a901bb7171d90dc4f1401,7036b29cb5e235e5fd9b09ae3e8eec4404e44906814d5d01cbca968a60ed4bfb01
depends_on:
- stacks-node
entrypoint:
- /bin/bash
- -c
- |
set -e
exec npx tsx /root/tx-broadcaster.ts
postgres:
networks:
- stacks
image: "postgres:15"
ports:
- "5490:5490"
volumes:
- chainstate:/chainstate
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: stacks_blockchain_api
PGPORT: 5490
PGDATA: /chainstate/pg-data
stacks-api:
networks:
- stacks
build:
context: .
dockerfile: Dockerfile.stacks-api
args:
GIT_COMMIT: *STACKS_API_COMMIT
depends_on:
- postgres
ports:
- "3999:3999"
expose:
- "3700"
environment:
NODE_ENVIRONMENT: production
STACKS_API_LOG_LEVEL: debug
STACKS_CHAIN_ID: *STACKS_CHAIN_ID
STACKS_BLOCKCHAIN_API_HOST: "0.0.0.0"
STACKS_BLOCKCHAIN_API_PORT: 3999
STACKS_CORE_EVENT_HOST: "0.0.0.0"
STACKS_CORE_EVENT_PORT: 3700
PG_HOST: postgres
PG_PORT: 5490
PG_USER: postgres
PG_PASSWORD: postgres
PG_DATABASE: stacks_blockchain_api
PG_SCHEMA: public
STACKS_CORE_RPC_HOST: stacks-node
STACKS_CORE_RPC_PORT: 20443
BTC_RPC_HOST: http://bitcoind
BTC_RPC_PORT: 18443
BTC_RPC_USER: btc
BTC_RPC_PW: btc
BTC_FAUCET_PK: *MINER_SEED
CUSTOM_CHAIN_IDS: *CUSTOM_CHAIN_IDS
stacks-signer-1:
networks:
- stacks
build:
context: .
dockerfile: Dockerfile.stacks-node
args:
GIT_COMMIT: *STACKS_BLOCKCHAIN_COMMIT
depends_on:
- stacks-node
volumes:
- ./signer-0.toml:/root/config.toml.in
- chainstate:/chainstate
environment:
SIGNER_DB_PATH: /chainstate/stacks-signer-1.sqlite
STACKS_NODE_HOST: stacks-node:20443
STACKS_SIGNER_ENDPOINT: 0.0.0.0:30001
SIGNER_PRIVATE_KEY: 6a1a754ba863d7bab14adbbc3f8ebb090af9e871ace621d3e5ab634e1422885e01
STACKS_CHAIN_ID: *STACKS_CHAIN_ID
entrypoint:
- /bin/bash
- -c
- |
set -e
envsubst < config.toml.in > config.toml
exec stacks-signer run --config config.toml
stacks-signer-2:
networks:
- stacks
build:
context: .
dockerfile: Dockerfile.stacks-node
args:
GIT_COMMIT: *STACKS_BLOCKCHAIN_COMMIT
depends_on:
- stacks-node
volumes:
- ./signer-0.toml:/root/config.toml.in
- chainstate:/chainstate
environment:
SIGNER_DB_PATH: /chainstate/stacks-signer-2.sqlite
STACKS_NODE_HOST: stacks-node:20443
STACKS_SIGNER_ENDPOINT: 0.0.0.0:30002
SIGNER_PRIVATE_KEY: b463f0df6c05d2f156393eee73f8016c5372caa0e9e29a901bb7171d90dc4f1401
STACKS_CHAIN_ID: *STACKS_CHAIN_ID
entrypoint:
- /bin/bash
- -c
- |
set -e
envsubst < config.toml.in > config.toml
exec stacks-signer run --config config.toml
stacks-signer-3:
networks:
- stacks
build:
context: .
dockerfile: Dockerfile.stacks-node
args:
GIT_COMMIT: *STACKS_BLOCKCHAIN_COMMIT
depends_on:
- stacks-node
volumes:
- ./signer-0.toml:/root/config.toml.in
- chainstate:/chainstate
environment:
SIGNER_DB_PATH: /chainstate/stacks-signer-3.sqlite
STACKS_NODE_HOST: stacks-node:20443
STACKS_SIGNER_ENDPOINT: 0.0.0.0:30003
SIGNER_PRIVATE_KEY: 7036b29cb5e235e5fd9b09ae3e8eec4404e44906814d5d01cbca968a60ed4bfb01
STACKS_CHAIN_ID: *STACKS_CHAIN_ID
entrypoint:
- /bin/bash
- -c
- |
set -e
envsubst < config.toml.in > config.toml
exec stacks-signer run --config config.toml
networks:
stacks:
volumes:
chainstate: