Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
stacking/node_modules
package-lock.json
.cache
node_modules
ai
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"biome.enabled": false
}
8 changes: 6 additions & 2 deletions Dockerfile.stacker
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ WORKDIR /root
COPY ./stacking/package.json /root/
RUN npm i

COPY ./stacking/stacking.ts ./stacking/common.ts ./stacking/monitor.ts ./stacking/tx-broadcaster.ts /root/
COPY ./stacking/deployments/*.yaml /root/deployments/
COPY ./stacking/contracts/*.clar /root/contracts/
COPY ./stacking/*.ts /root/

CMD ["npx", "tsx", "/root/stacking.ts"]
ENV NODE_OPTIONS=--enable-source-maps

CMD ["./node_modules/.bin/tsx", "/root/stacking.ts"]
2 changes: 1 addition & 1 deletion Dockerfile.stacks-api
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ RUN git init && \
git reset --hard FETCH_HEAD && \
git fetch --all --tags

RUN rm ".env"
# RUN rm ".env"
RUN git describe --tags --abbrev=0 || git -c user.name='user' -c user.email='email' tag vNext
RUN echo "GIT_TAG=$(git tag --points-at HEAD)" >> .env

Expand Down
19 changes: 10 additions & 9 deletions Dockerfile.stacks-node
Original file line number Diff line number Diff line change
@@ -1,27 +1,28 @@
FROM rust:bookworm AS builder

# TODO: is there a built-in required arg syntax?
ARG GIT_COMMIT
RUN test -n "$GIT_COMMIT" || (echo "GIT_COMMIT not set" && false)

RUN echo "Building stacks-node from commit: https://github.com/stacks-network/stacks-blockchain/commit/$GIT_COMMIT"

RUN apt-get update && apt-get install -y libclang-dev
RUN rustup toolchain install stable
RUN rustup component add rustfmt --toolchain stable

ARG GIT_COMMIT
RUN test -n "$GIT_COMMIT" || (echo "GIT_COMMIT not set" && false)
RUN echo "Building stacks-node from commit: https://github.com/stacks-network/stacks-blockchain/commit/$GIT_COMMIT"

WORKDIR /stacks
RUN git init && \
git remote add origin https://github.com/stacks-network/stacks-blockchain.git && \
git -c protocol.version=2 fetch --depth=1 origin "$GIT_COMMIT" && \
git reset --hard FETCH_HEAD

RUN cargo build --package stacks-node --package stacks-signer --bin stacks-node --bin stacks-signer
RUN --mount=type=cache,target=/stacks/target \
--mount=type=cache,target=/usr/local/cargo/registry \
cargo build --package stacks-node --package stacks-signer --bin stacks-node --bin stacks-signer --features slog_json && \
cp target/debug/stacks-node target/debug/stacks-signer /usr/local/bin/

FROM debian:bookworm

COPY --from=builder /stacks/target/debug/stacks-node /usr/local/bin/
COPY --from=builder /stacks/target/debug/stacks-signer /usr/local/bin/
COPY --from=builder /usr/local/bin/stacks-node /usr/local/bin/
COPY --from=builder /usr/local/bin/stacks-signer /usr/local/bin/

COPY --from=dobtc/bitcoin:25.1 /opt/bitcoin-*/bin /usr/local/bin

Expand Down
95 changes: 86 additions & 9 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
version: "3.9"

x-common-vars:
- &STACKS_BLOCKCHAIN_COMMIT 1cba695b09690790b1220b0f5d149f70f78ddea5 # 3.3.0.0.1
- &STACKS_API_COMMIT 7ee1adbddac269d0c03567677013470a62e92f99 # 8.13.4
- &STACKS_BLOCKCHAIN_COMMIT 27877974d3c9a0daea20ec7204cb8d7e7aa95e83 # feat/epoch-4-rc
- &STACKS_API_COMMIT fc47a7cd054018d8ea098fbb3c8db207dbf7c8c9 # 9.0.0-pox5.1
- &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
- &MINE_INTERVAL_EPOCH25 ${MINE_INTERVAL_EPOCH25:-2s} # bitcoin block times in epoch 2.5
- &MINE_INTERVAL_EPOCH3 ${MINE_INTERVAL_EPOCH3:-1s} # bitcoin block times in epoch 3
- &MINE_INTERVAL_EPOCH40 ${MINE_INTERVAL_EPOCH40:-2s} # bitcoin block times in epoch 4
- &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}
Expand All @@ -25,7 +24,10 @@ x-common-vars:
- &STACKS_31_HEIGHT ${STACKS_31_HEIGHT:-132}
- &STACKS_32_HEIGHT ${STACKS_32_HEIGHT:-133}
- &STACKS_33_HEIGHT ${STACKS_33_HEIGHT:-134}
- &STACKS_34_HEIGHT ${STACKS_34_HEIGHT:-135}
- &STACKS_40_HEIGHT ${STACKS_40_HEIGHT:-141}
- &STACKING_CYCLES ${STACKING_CYCLES:-1} # number of cycles to stack-stx or stack-extend for
- &STACKING_CYCLES_POX_5 ${STACKING_CYCLES_POX_5:-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
Expand Down Expand Up @@ -75,9 +77,11 @@ services:
MINE_INTERVAL: *MINE_INTERVAL
MINE_INTERVAL_EPOCH3: *MINE_INTERVAL_EPOCH3
MINE_INTERVAL_EPOCH25: *MINE_INTERVAL_EPOCH25
MINE_INTERVAL_EPOCH40: *MINE_INTERVAL_EPOCH40
INIT_BLOCKS: 101
STACKS_30_HEIGHT: *STACKS_30_HEIGHT
STACKS_25_HEIGHT: *STACKS_25_HEIGHT
STACKS_40_HEIGHT: *STACKS_40_HEIGHT
entrypoint:
- /bin/bash
- -c
Expand Down Expand Up @@ -142,9 +146,20 @@ services:
i=$$((i + 1))
done

# Create the btc_staking wallet (used by the btc-staker container)
if ! bitcoin-cli -rpcconnect=bitcoind listwallets | grep -q "btc_staking"; then
bitcoin-cli -rpcconnect=bitcoind -named createwallet wallet_name="btc_staking" descriptors=false load_on_startup=true
echo "Created btc_staking wallet"
fi
STAKING_WALLET_ADDRESS=$$(bitcoin-cli -rpcconnect=bitcoind -rpcwallet="btc_staking" getnewaddress "staking_fund")

# 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}"

# Fund the staking wallet
bitcoin-cli -rpcconnect=bitcoind -rpcwallet="main" -named sendtoaddress address="$${STAKING_WALLET_ADDRESS}" amount=10.0
echo "Funded btc_staking wallet with 10 BTC"

DEFAULT_TIMEOUT=$$(($$(date +%s) + 30))
while true; do
TX_FOUND=false
Expand Down Expand Up @@ -190,6 +205,15 @@ services:
i=$$((i + 1))
done

# Top up btc_staking wallet if low (include unconfirmed balance)
STAKING_BALANCE=$$(bitcoin-cli -rpcconnect=bitcoind -rpcwallet="btc_staking" getbalances | jq '.mine.trusted + .mine.untrusted_pending')
STAKING_BALANCE=$${STAKING_BALANCE:-0}
if (( $$(echo "$${STAKING_BALANCE} < 1.0" | bc -l) )); then
STAKING_ADDR=$$(bitcoin-cli -rpcconnect=bitcoind -rpcwallet="btc_staking" getnewaddress "staking_topup")
bitcoin-cli -rpcconnect=bitcoind -rpcwallet="main" -named sendtoaddress address="$${STAKING_ADDR}" amount=5.0
echo "Topped up btc_staking wallet (was $${STAKING_BALANCE} BTC)"
fi

# 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
Expand All @@ -205,7 +229,10 @@ services:

SLEEP_DURATION=$${MINE_INTERVAL}
BLOCK_HEIGHT=$$(bitcoin-cli -rpcconnect=bitcoind getblockcount)
if [ "$${BLOCK_HEIGHT}" -ge $$(( $${STACKS_30_HEIGHT} - 1 )) ]; then
if [ "$${BLOCK_HEIGHT}" -ge "$${STACKS_40_HEIGHT}" ]; then
echo "In Epoch4.0, sleeping for $${MINE_INTERVAL_EPOCH40} ..."
SLEEP_DURATION=$${MINE_INTERVAL_EPOCH40}
elif [ "$${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
Expand Down Expand Up @@ -256,10 +283,13 @@ services:
STACKS_31_HEIGHT: *STACKS_31_HEIGHT
STACKS_32_HEIGHT: *STACKS_32_HEIGHT
STACKS_33_HEIGHT: *STACKS_33_HEIGHT
STACKS_34_HEIGHT: *STACKS_34_HEIGHT
STACKS_40_HEIGHT: *STACKS_40_HEIGHT
POX_PREPARE_LENGTH: *POX_PREPARE_LENGTH
POX_REWARD_LENGTH: *POX_REWARD_LENGTH
REWARD_RECIPIENT: *REWARD_RECIPIENT
STACKS_CHAIN_ID: *STACKS_CHAIN_ID
STACKS_LOG_JSON: 1
entrypoint:
- /bin/bash
- -c
Expand All @@ -285,18 +315,58 @@ services:
STACKS_CORE_RPC_HOST: stacks-node
STACKS_CORE_RPC_PORT: 20443
STACKING_CYCLES: *STACKING_CYCLES
STACKING_CYCLES_POX_5: *STACKING_CYCLES_POX_5
STACKING_KEYS: 6a1a754ba863d7bab14adbbc3f8ebb090af9e871ace621d3e5ab634e1422885e01,b463f0df6c05d2f156393eee73f8016c5372caa0e9e29a901bb7171d90dc4f1401,7036b29cb5e235e5fd9b09ae3e8eec4404e44906814d5d01cbca968a60ed4bfb01
STACKS_25_HEIGHT: *STACKS_25_HEIGHT
STACKS_30_HEIGHT: *STACKS_30_HEIGHT
STACKS_40_HEIGHT: *STACKS_40_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
NODE_OPTIONS: --enable-source-maps
depends_on:
- stacks-node

btc-staker:
networks:
- stacks
build:
context: .
dockerfile: Dockerfile.stacker
environment:
STACKS_CORE_RPC_HOST: stacks-api
STACKS_CORE_RPC_PORT: 3999
STACKING_CYCLES: *STACKING_CYCLES
STACKING_CYCLES_POX_5: *STACKING_CYCLES_POX_5
STACKING_KEYS: 6a1a754ba863d7bab14adbbc3f8ebb090af9e871ace621d3e5ab634e1422885e01,b463f0df6c05d2f156393eee73f8016c5372caa0e9e29a901bb7171d90dc4f1401,7036b29cb5e235e5fd9b09ae3e8eec4404e44906814d5d01cbca968a60ed4bfb01
STACKS_25_HEIGHT: *STACKS_25_HEIGHT
STACKS_30_HEIGHT: *STACKS_30_HEIGHT
STACKS_40_HEIGHT: *STACKS_40_HEIGHT
POX_PREPARE_LENGTH: *POX_PREPARE_LENGTH
POX_REWARD_LENGTH: *POX_REWARD_LENGTH
STACKS_CHAIN_ID: *STACKS_CHAIN_ID
STACKING_INTERVAL: 2
POST_TX_WAIT: 10
SERVICE_NAME: btc-staker
NODE_OPTIONS: --enable-source-maps
BITCOIN_RPC_HOST: bitcoind
BITCOIN_RPC_PORT: *BITCOIN_RPC_PORT
BITCOIN_RPC_USER: *BITCOIN_RPC_USER
BITCOIN_RPC_PASS: *BITCOIN_RPC_PASS
BTC_LOCK_AMOUNT_SATS: 100000
depends_on:
- stacks-node
- bitcoind
entrypoint:
- /bin/bash
- -c
- |
set -e
exec ./node_modules/.bin/tsx /root/btc-staker.ts

monitor:
networks:
- stacks
Expand All @@ -307,22 +377,25 @@ services:
STACKS_CORE_RPC_HOST: stacks-api
STACKS_CORE_RPC_PORT: 3999
STACKING_CYCLES: *STACKING_CYCLES
STACKING_CYCLES_POX_5: *STACKING_CYCLES_POX_5
STACKING_KEYS: 6a1a754ba863d7bab14adbbc3f8ebb090af9e871ace621d3e5ab634e1422885e01,b463f0df6c05d2f156393eee73f8016c5372caa0e9e29a901bb7171d90dc4f1401,7036b29cb5e235e5fd9b09ae3e8eec4404e44906814d5d01cbca968a60ed4bfb01
STACKS_25_HEIGHT: *STACKS_25_HEIGHT
STACKS_30_HEIGHT: *STACKS_30_HEIGHT
STACKS_40_HEIGHT: *STACKS_40_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
NODE_OPTIONS: --enable-source-maps
depends_on:
- stacks-node
entrypoint:
- /bin/bash
- -c
- |
set -e
exec npx tsx /root/monitor.ts
exec ./node_modules/.bin/tsx /root/monitor.ts

tx-broadcaster:
networks:
Expand All @@ -337,23 +410,26 @@ services:
STACKS_30_HEIGHT: *STACKS_30_HEIGHT
ACCOUNT_KEYS: 0d2f965b472a82efd5a96e6513c8b9f7edc725d5c96c7d35d6c722cedeb80d1b01,975b251dd7809469ef0c26ec3917971b75c51cd73a022024df4bf3b232cc2dc001,c71700b07d520a8c9731e4d0f095aa6efb91e16e25fb27ce2b72e7b698f8127a01
STACKS_25_HEIGHT: *STACKS_25_HEIGHT
STACKS_40_HEIGHT: *STACKS_40_HEIGHT
POX_PREPARE_LENGTH: *POX_PREPARE_LENGTH
POX_REWARD_LENGTH: *POX_REWARD_LENGTH
STACKS_CHAIN_ID: *STACKS_CHAIN_ID
STACKING_KEYS: 6a1a754ba863d7bab14adbbc3f8ebb090af9e871ace621d3e5ab634e1422885e01,b463f0df6c05d2f156393eee73f8016c5372caa0e9e29a901bb7171d90dc4f1401,7036b29cb5e235e5fd9b09ae3e8eec4404e44906814d5d01cbca968a60ed4bfb01
NODE_OPTIONS: --enable-source-maps
depends_on:
- stacks-node
entrypoint:
- /bin/bash
- -c
- |
set -e
exec npx tsx /root/tx-broadcaster.ts
exec ./node_modules/.bin/tsx /root/tx-broadcaster.ts

postgres:
networks:
- stacks
image: "postgres:15"
pull_policy: if_not_present
ports:
- "5490:5490"
volumes:
Expand Down Expand Up @@ -394,6 +470,7 @@ services:
PG_DATABASE: stacks_blockchain_api
PG_SCHEMA: public
STACKS_CORE_RPC_HOST: stacks-node
STACKS_CORE_PROXY_HOST: stacks-node
STACKS_CORE_RPC_PORT: 20443
BTC_RPC_HOST: http://bitcoind
BTC_RPC_PORT: 18443
Expand Down
4 changes: 2 additions & 2 deletions run.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env bash

docker compose down --volumes --remove-orphans --timeout=1 --rmi=all
docker compose down --volumes --remove-orphans --timeout=1 --rmi=local
# docker compose up --build
docker compose up --build --exit-code-from monitor
docker compose up --build
30 changes: 30 additions & 0 deletions stacking/Clarigen.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@

# Set to your project's Clarinet config file
clarinet = "./Clarinet.toml"

# Set where you'd like TypeScript types output.
# Comment or remove section to skip TypeScript types
[types]
# `output` should be a path to a single file
output = "clarigen-types.ts"

# You can also specify multiple output paths:
# outputs = [
# "src/clarigen-types.ts",
# "test/clarigen-types.ts"
# ]

# `types.after` - script to run after TypeScript types are generated.
# examples:
# after = "npm run prettier -w ./src/clarigen-types.ts"
# after = "echo 'yay'"

# Set where you'd like generated contract docs
# Generate docs by running `clarigen docs`
[docs]
# `output` should be a folder
output = "docs"

# `docs.after` - script to run after docs are generated.
# examples:
# after = "npm run prettier -w ./docs"
24 changes: 24 additions & 0 deletions stacking/Clarinet.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@

[project]
name = "core-contracts"

[[project.requirements]]
contract_id = "SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-withdrawal"

[repl]
costs_version = 1

[contracts.pox-5]
path = "./contracts/pox-5.clar"
clarity_version = 4
epoch = 3.3

[contracts.pox-5-signer]
path = "./contracts/pox-5-signer.clar"
clarity_version = 4
epoch = 3.3

[repl.analysis.lints]
unused_const = "warn"
unused_data_var = "warn"
panic = "off"
Loading