diff --git a/.env b/.env index 25ca66d3e..4f06d5bc4 100644 --- a/.env +++ b/.env @@ -2,7 +2,7 @@ PG_HOST=127.0.0.1 PG_PORT=5490 PG_USER=postgres PG_PASSWORD=postgres -PG_DATABASE=stacks_blockchain_api +PG_DATABASE=stacks_api PG_SCHEMA=public PG_SSL=false # Idle connection timeout in seconds, defaults to 30 diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 24b522696..3a5269cb4 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -15,9 +15,9 @@ "presentation": { "echo": true, "reveal": "always", "focus": false, "panel": "dedicated", "clear": false } }, { - "label": "stacks-node:start-mocknet", + "label": "stacks-node:start-devnet", "type": "shell", - "command": "docker compose -f docker/docker-compose.dev.stacks-blockchain.yml up --force-recreate -V", + "command": "docker compose -f docker/devnet/docker-compose.yml up --force-recreate -V", "isBackground": true, "problemMatcher": { "pattern": { "regexp": ".", "file": 1, "location": 2, "message": 3, }, @@ -28,7 +28,7 @@ { "label": "stacks-node:stop-mocknet", "type": "shell", - "command": "docker compose -f docker/docker-compose.dev.stacks-blockchain.yml down -v -t 0", + "command": "docker compose -f docker/devnet/docker-compose.yml down -v -t 0", "isBackground": true, "problemMatcher": { "pattern": { "regexp": ".", "file": 1, "location": 2, "message": 3, }, @@ -85,7 +85,7 @@ { "label": "deploy:krypton", "type": "shell", - "command": "docker compose -f docker/docker-compose.dev.postgres.yml -f docker/docker-compose.dev.stacks-krypton.yml up --force-recreate -V", + "command": "docker compose -f docker/devnet/docker-compose.yml up --force-recreate -V", "isBackground": true, "problemMatcher": { "pattern": { "regexp": ".", "file": 1, "location": 2, "message": 3 }, @@ -96,7 +96,7 @@ { "label": "stop:krypton", "type": "shell", - "command": "docker compose -f docker/docker-compose.dev.postgres.yml -f docker/docker-compose.dev.stacks-krypton.yml down -v -t 0", + "command": "docker compose -f docker/devnet/docker-compose.yml down -v -t 0", "presentation": { "echo": true, "reveal": "silent", diff --git a/docker/devnet/Clarinet.toml b/docker/devnet/Clarinet.toml new file mode 100644 index 000000000..a9589ec94 --- /dev/null +++ b/docker/devnet/Clarinet.toml @@ -0,0 +1,18 @@ +[project] +name = "devnet" +description = "" +authors = [] +telemetry = false +cache_dir = "./.cache" + +[repl.analysis] +passes = ["check_checker"] +check_checker = { trusted_sender = false, trusted_caller = false, callee_filter = false } + +# Check-checker settings: +# trusted_sender: if true, inputs are trusted after tx_sender has been checked. +# trusted_caller: if true, inputs are trusted after contract-caller has been checked. +# callee_filter: if true, untrusted data may be passed into a private function without a +# warning, if it gets checked inside. This check will also propagate up to the +# caller. +# More informations: https://www.hiro.so/blog/new-safety-checks-in-clarinet diff --git a/docker/devnet/Dockerfile b/docker/devnet/Dockerfile new file mode 100644 index 000000000..5478f8de7 --- /dev/null +++ b/docker/devnet/Dockerfile @@ -0,0 +1,57 @@ +FROM --platform=$BUILDPLATFORM rust:alpine as clarinet-builder + +WORKDIR /usr/src/ + +RUN apk add --no-cache \ + git \ + build-base \ + curl \ + pkgconfig + +# Build Clarinet from source +RUN git clone https://github.com/hirosystems/clarinet.git && \ + cd clarinet && \ + # git checkout docker-sock-bind && \ + # git checkout main && \ + git checkout 4cb70b0c && \ + cargo build --release + +FROM --platform=$BUILDPLATFORM docker:dind + +RUN apk add --no-cache \ + ca-certificates \ + docker \ + sudo \ + net-tools \ + file \ + iproute2 \ + shadow + +# Add root to the docker group +RUN usermod -aG docker root + +# Copy Clarinet binary from builder image +COPY --from=clarinet-builder /usr/src/clarinet/target/release/clarinet /usr/local/bin/clarinet + +WORKDIR /app + +VOLUME /chainstate + +# Stacks API +# EXPOSE 3700 +# Stacks-node RPC +EXPOSE 20443 +# Bitcoind JSON-RPC +EXPOSE 18443 +# Postgres +EXPOSE 5490 + +# Copy Clarinet config files +COPY Clarinet.toml . +COPY settings/Devnet.toml ./settings/ +COPY start.sh . + +RUN chmod +x start.sh + +# Start the Docker daemon and the devnet +CMD ["/app/start.sh"] diff --git a/docker/devnet/Dockerfile.clarinet-builder b/docker/devnet/Dockerfile.clarinet-builder new file mode 100644 index 000000000..cff69d7dd --- /dev/null +++ b/docker/devnet/Dockerfile.clarinet-builder @@ -0,0 +1,19 @@ +# Dockerfile.clarinet-builder + +FROM --platform=$BUILDPLATFORM rust:alpine as builder + +WORKDIR /usr/src/ + +RUN apk add --no-cache \ + git \ + build-base \ + curl \ + pkgconfig + +# Build Clarinet from source +RUN git clone https://github.com/hirosystems/clarinet.git && \ + cd clarinet && \ + git checkout main && \ + cargo build --release + +# This image produces the built Clarinet binary diff --git a/docker/devnet/deployments/default.devnet-plan.yaml b/docker/devnet/deployments/default.devnet-plan.yaml new file mode 100644 index 000000000..abfa45abe --- /dev/null +++ b/docker/devnet/deployments/default.devnet-plan.yaml @@ -0,0 +1,8 @@ +--- +id: 0 +name: Devnet deployment +network: devnet +stacks-node: "http://localhost:20443" +bitcoin-node: "http://devnet:devnet@localhost:18443" +plan: + batches: [] diff --git a/docker/devnet/docker-compose.yml b/docker/devnet/docker-compose.yml new file mode 100644 index 000000000..c5288e243 --- /dev/null +++ b/docker/devnet/docker-compose.yml @@ -0,0 +1,39 @@ +services: + # clarinet-builder: + # build: + # context: . + # dockerfile: Dockerfile.clarinet-builder + # networks: + # - backend + + clarinet-devnet: + # depends_on: + # - clarinet-builder + # network_mode: "host" # equivalent to --network host + networks: + - backend + restart: on-failure + build: + context: . + # platform: ${BUILDPLATFORM:-linux/amd64} + ports: + - "20443:20443" + - '20444:20444' + - "18443:18443" + - "5490:5490" + volumes: + - chainstate:/chainstate + - ../stacks-blockchain/:/app/config + - ../stacks-blockchain/.chaindata:/tmp/stacks-blockchain-data + environment: + - PG_DATABASE=stacks_blockchain_api + - POSTGRES_DB=stacks_blockchain_api + - STACKS_CHAIN_ID=0x80000000 + extra_hosts: + - 'host.docker.internal:host-gateway' # fixes `host.docker.internal` on linux hosts + privileged: true + +networks: + backend: +volumes: + chainstate: diff --git a/docker/devnet/settings/Devnet.toml b/docker/devnet/settings/Devnet.toml new file mode 100644 index 000000000..6906396c0 --- /dev/null +++ b/docker/devnet/settings/Devnet.toml @@ -0,0 +1,170 @@ +[network] +name = "devnet" +deployment_fee_rate = 10 + +[accounts.deployer] +mnemonic = "twice kind fence tip hidden tilt action fragile skin nothing glory cousin green tomorrow spring wrist shed math olympic multiply hip blue scout claw" +balance = 100_000_000_000_000 +# secret_key: 753b7cc01a1a2e86221266a154af739463fce51219d97e4f856cd7200c3bd2a601 +# stx_address: ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM +# btc_address: mqVnk6NPRdhntvfm4hh9vvjiRkFDUuSYsH + +[accounts.wallet_1] +mnemonic = "sell invite acquire kitten bamboo drastic jelly vivid peace spawn twice guilt pave pen trash pretty park cube fragile unaware remain midnight betray rebuild" +balance = 100_000_000_000_000 +# secret_key: 7287ba251d44a4d3fd9276c88ce34c5c52a038955511cccaf77e61068649c17801 +# stx_address: ST1SJ3DTE5DN7X54YDH5D64R3BCB6A2AG2ZQ8YPD5 +# btc_address: mr1iPkD9N3RJZZxXRk7xF9d36gffa6exNC + +[accounts.wallet_2] +mnemonic = "hold excess usual excess ring elephant install account glad dry fragile donkey gaze humble truck breeze nation gasp vacuum limb head keep delay hospital" +balance = 100_000_000_000_000 +# secret_key: 530d9f61984c888536871c6573073bdfc0058896dc1adfe9a6a10dfacadc209101 +# stx_address: ST2CY5V39NHDPWSXMW9QDT3HC3GD6Q6XX4CFRK9AG +# btc_address: muYdXKmX9bByAueDe6KFfHd5Ff1gdN9ErG + +[accounts.wallet_3] +mnemonic = "cycle puppy glare enroll cost improve round trend wrist mushroom scorpion tower claim oppose clever elephant dinosaur eight problem before frozen dune wagon high" +balance = 100_000_000_000_000 +# secret_key: d655b2523bcd65e34889725c73064feb17ceb796831c0e111ba1a552b0f31b3901 +# stx_address: ST2JHG361ZXG51QTKY2NQCVBPPRRE2KZB1HR05NNC +# btc_address: mvZtbibDAAA3WLpY7zXXFqRa3T4XSknBX7 + +[accounts.wallet_4] +mnemonic = "board list obtain sugar hour worth raven scout denial thunder horse logic fury scorpion fold genuine phrase wealth news aim below celery when cabin" +balance = 100_000_000_000_000 +# secret_key: f9d7206a47f14d2870c163ebab4bf3e70d18f5d14ce1031f3902fbbc894fe4c701 +# stx_address: ST2NEB84ASENDXKYGJPQW86YXQCEFEX2ZQPG87ND +# btc_address: mg1C76bNTutiCDV3t9nWhZs3Dc8LzUufj8 + +[accounts.wallet_5] +mnemonic = "hurry aunt blame peanut heavy update captain human rice crime juice adult scale device promote vast project quiz unit note reform update climb purchase" +balance = 100_000_000_000_000 +# secret_key: 3eccc5dac8056590432db6a35d52b9896876a3d5cbdea53b72400bc9c2099fe801 +# stx_address: ST2REHHS5J3CERCRBEPMGH7921Q6PYKAADT7JP2VB +# btc_address: mweN5WVqadScHdA81aATSdcVr4B6dNokqx + +[accounts.wallet_6] +mnemonic = "area desk dutch sign gold cricket dawn toward giggle vibrant indoor bench warfare wagon number tiny universe sand talk dilemma pottery bone trap buddy" +balance = 100_000_000_000_000 +# secret_key: 7036b29cb5e235e5fd9b09ae3e8eec4404e44906814d5d01cbca968a60ed4bfb01 +# stx_address: ST3AM1A56AK2C1XAFJ4115ZSV26EB49BVQ10MGCS0 +# btc_address: mzxXgV6e4BZSsz8zVHm3TmqbECt7mbuErt + +[accounts.wallet_7] +mnemonic = "prevent gallery kind limb income control noise together echo rival record wedding sense uncover school version force bleak nuclear include danger skirt enact arrow" +balance = 100_000_000_000_000 +# secret_key: b463f0df6c05d2f156393eee73f8016c5372caa0e9e29a901bb7171d90dc4f1401 +# stx_address: ST3PF13W7Z0RRM42A8VZRVFQ75SV1K26RXEP8YGKJ +# btc_address: n37mwmru2oaVosgfuvzBwgV2ysCQRrLko7 + +[accounts.wallet_8] +mnemonic = "female adjust gallery certain visit token during great side clown fitness like hurt clip knife warm bench start reunion globe detail dream depend fortune" +balance = 100_000_000_000_000 +# secret_key: 6a1a754ba863d7bab14adbbc3f8ebb090af9e871ace621d3e5ab634e1422885e01 +# stx_address: ST3NBRSFKX28FQ2ZJ1MAKX58HKHSDGNV5N7R21XCP +# btc_address: n2v875jbJ4RjBnTjgbfikDfnwsDV5iUByw + +[accounts.faucet] +mnemonic = "shadow private easily thought say logic fault paddle word top book during ignore notable orange flight clock image wealth health outside kitten belt reform" +balance = 100_000_000_000_000 +# secret_key: de433bdfa14ec43aa1098d5be594c8ffb20a31485ff9de2923b2689471c401b801 +# stx_address: STNHKEPYEPJ8ET55ZZ0M5A34J0R3N5FM2CMMMAZ6 +# btc_address: mjSrB3wS4xab3kYqFktwBzfTdPg367ZJ2d + +[devnet] +use_docker_gateway_routing = true +disable_stacks_explorer = true +disable_stacks_api = true +disable_postgres = false +# disable_subnet_api = false +disable_bitcoin_explorer = true +# working_dir = "tmp/devnet" +# stacks_node_events_observers = ["host.docker.internal:3700"] +# miner_mnemonic = "fragile loan twenty basic net assault jazz absorb diet talk art shock innocent float punch travel gadget embrace caught blossom hockey surround initial reduce" +# miner_derivation_path = "m/44'/5757'/0'/0/0" +# faucet_mnemonic = "shadow private easily thought say logic fault paddle word top book during ignore notable orange flight clock image wealth health outside kitten belt reform" +# faucet_derivation_path = "m/44'/5757'/0'/0/0" +# orchestrator_port = 20445 +# bitcoin_node_p2p_port = 18444 +bitcoin_node_rpc_port = 18443 +bitcoin_node_username = "devnet" +bitcoin_node_password = "devnet" +# bitcoin_controller_block_time = 30_000 +stacks_node_rpc_port = 20443 +# stacks_node_p2p_port = 20444 +# stacks_api_port = 3999 +# stacks_api_events_port = 3700 +# bitcoin_explorer_port = 8001 +# stacks_explorer_port = 8000 +# postgres_port = 5432 +postgres_port = 5490 +postgres_username = "postgres" +postgres_password = "postgres" +# postgres_database = "postgres" +# postgres_database = "stacks_api" +postgres_database = "stacks_api" +# bitcoin_node_image_url = "quay.io/hirosystems/bitcoind:26.0" +# stacks_node_image_url = "quay.io/hirosystems/stacks-node:devnet-2.5" +# stacks_signer_image_url = "quay.io/hirosystems/stacks-signer:devnet-2.5" +# stacks_api_image_url = "hirosystems/stacks-blockchain-api:master" +# stacks_explorer_image_url = "hirosystems/explorer:latest" +# bitcoin_explorer_image_url = "quay.io/hirosystems/bitcoin-explorer:devnet" +# postgres_image_url = "postgres:alpine" +# enable_subnet_node = true +# subnet_node_image_url = "hirosystems/stacks-subnets:0.8.1" +# subnet_leader_mnemonic = "twice kind fence tip hidden tilt action fragile skin nothing glory cousin green tomorrow spring wrist shed math olympic multiply hip blue scout claw" +# subnet_leader_derivation_path = "m/44'/5757'/0'/0/0" +# subnet_contract_id = "ST173JK7NZBA4BS05ZRATQH1K89YJMTGEH1Z5J52E.subnet-v3-0-1" +# subnet_node_rpc_port = 30443 +# subnet_node_p2p_port = 30444 +# subnet_events_ingestion_port = 30445 +# subnet_node_events_observers = ["host.docker.internal:8002"] +# subnet_api_image_url = "hirosystems/stacks-blockchain-api:master" +# subnet_api_postgres_database = "subnet_api" + +# For testing in epoch 2.1 / using Clarity2 +# defaults +# epoch_2_0 = 100 +# epoch_2_05 = 100 +# epoch_2_1 = 101 +# epoch_2_2 = 102 +# epoch_2_3 = 103 +# epoch_2_4 = 104 +# epoch_2_5 = 108 + +# from stacks_blockchain_api settings +# epoch_2_0 = 100 +# epoch_2_05 = 104 +# epoch_2_1 = 106 +# epoch_2_2 = 108 +# epoch_2_3 = 109 +# epoch_2_4 = 111 +# epoch_2_5 = 112 +# epoch_3_0 = 144 +epoch_3_0 = 144 + +stacks_node_image_url = "quay.io/hirosystems/stacks-node:devnet2.9.0-epoch3.0" +stacks_signer_image_url = "quay.io/hirosystems/stacks-signer:devnet2.9.0-epoch3.0" + +# Send some stacking orders +[[devnet.pox_stacking_orders]] +start_at_cycle = 1 +duration = 12 +wallet = "wallet_1" +slots = 2 +btc_address = "mr1iPkD9N3RJZZxXRk7xF9d36gffa6exNC" + +[[devnet.pox_stacking_orders]] +start_at_cycle = 1 +duration = 12 +wallet = "wallet_2" +slots = 1 +btc_address = "muYdXKmX9bByAueDe6KFfHd5Ff1gdN9ErG" + +[[devnet.pox_stacking_orders]] +start_at_cycle = 1 +duration = 12 +wallet = "wallet_3" +slots = 1 +btc_address = "mvZtbibDAAA3WLpY7zXXFqRa3T4XSknBX7" diff --git a/docker/devnet/start.sh b/docker/devnet/start.sh new file mode 100755 index 000000000..123696653 --- /dev/null +++ b/docker/devnet/start.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +set -x # Enable debugging output + +sh -c dockerd-entrypoint.sh & + +until [ -S /var/run/docker.sock ]; do + echo "Waiting for Docker to start..." + sleep 1 +done +echo "starting clarinet devnet" +/usr/local/bin/clarinet devnet start --no-dashboard --manifest-path /app/Clarinet.toml diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index b9a4be63b..283f115cc 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -52,7 +52,7 @@ services: - ../stacks-blockchain/:/app/config networks: - backend - depends_on: + depends_on: - postgres networks: diff --git a/package.json b/package.json index 308683eb1..68bdfd8e2 100644 --- a/package.json +++ b/package.json @@ -48,14 +48,13 @@ "lint:prettier": "prettier --check src/**/*.{ts,json}", "lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx -f unix --fix && prettier --write --check src/**/*.{ts,json}", "migrate": "node-pg-migrate -m migrations", - "devenv:build": "docker compose -f docker/docker-compose.dev.postgres.yml -f docker/docker-compose.dev.stacks-blockchain.yml -f docker/docker-compose.dev.bitcoind.yml -f docker/docker-compose.dev.rosetta-cli.yml build --no-cache", - "devenv:deploy": "docker compose -f docker/docker-compose.dev.postgres.yml -f docker/docker-compose.dev.stacks-blockchain.yml -f docker/docker-compose.dev.bitcoind.yml up --force-recreate -V", - "devenv:follower": "docker compose -f docker/docker-compose.dev.postgres.yml -f docker/docker-compose.dev.stacks-blockchain-follower.yml up --force-recreate -V", - "devenv:stop": "docker compose -f docker/docker-compose.dev.postgres.yml -f docker/docker-compose.dev.stacks-blockchain.yml -f docker/docker-compose.dev.bitcoind.yml down -v -t 0", + "devenv:build": "docker compose -f docker/devnet/docker-compose.yml build", + "devenv:deploy": "docker compose -f docker/devnet/docker-compose.yml up --force-recreate -V", + "devenv:stop": "docker compose -f docker/devnet/docker-compose.yml down -v -t 0", "devenv:deploy:subnets": "docker compose -f docker/docker-compose.dev.postgres.yml -f docker/docker-compose.dev.subnets.yml up --force-recreate -V", "devenv:stop:subnets": "docker compose -f docker/docker-compose.dev.postgres.yml -f docker/docker-compose.dev.subnets.yml down -v -t 0", - "devenv:deploy-krypton": "docker compose -f docker/docker-compose.dev.postgres.yml -f docker/docker-compose.dev.stacks-krypton.yml up --force-recreate -V", - "devenv:stop-krypton": "docker compose -f docker/docker-compose.dev.postgres.yml -f docker/docker-compose.dev.stacks-krypton.yml down -v -t 0", + "devenv:deploy-krypton": "docker compose -f docker/devnet/docker-compose.yml up -d --force-recreate -V", + "devenv:stop-krypton": "docker compose -f docker/devnet/docker-compose.yml down -v -t 0", "devenv:stop:pg": "docker compose -f docker/docker-compose.dev.postgres.yml down -v -t 0", "devenv:logs": "docker compose -f docker/docker-compose.dev.postgres.yml -f docker/docker-compose.dev.stacks-blockchain.yml -f docker/docker-compose.dev.bitcoind.yml logs -t -f", "devenv:logs:subnets": "docker compose -f docker/docker-compose.dev.postgres.yml -f docker/docker-compose.dev.subnets.yml logs -t -f", diff --git a/src/datastore/connection.ts b/src/datastore/connection.ts index c1ff99cde..bdd660bd2 100644 --- a/src/datastore/connection.ts +++ b/src/datastore/connection.ts @@ -26,18 +26,18 @@ export function getPgConnectionEnvValue( } export function getConnectionArgs(server: PgServer = PgServer.default): PgConnectionArgs { - return ( - getPgConnectionEnvValue('CONNECTION_URI', server) ?? { - database: getPgConnectionEnvValue('DATABASE', server), - user: getPgConnectionEnvValue('USER', server), - password: getPgConnectionEnvValue('PASSWORD', server), - host: getPgConnectionEnvValue('HOST', server), - port: parseInt(getPgConnectionEnvValue('PORT', server) ?? '5432'), - ssl: getPgConnectionEnvValue('SSL', server) == 'true', - schema: getPgConnectionEnvValue('SCHEMA', server), - application_name: getPgConnectionEnvValue('APPLICATION_NAME', server), - } - ); + const conn = getPgConnectionEnvValue('CONNECTION_URI', server) ?? { + database: 'stacks_api', // getPgConnectionEnvValue('DATABASE', server), + user: getPgConnectionEnvValue('USER', server), + password: getPgConnectionEnvValue('PASSWORD', server), + host: getPgConnectionEnvValue('HOST', server), + port: parseInt(getPgConnectionEnvValue('PORT', server) ?? '5432'), + ssl: getPgConnectionEnvValue('SSL', server) == 'true', + schema: getPgConnectionEnvValue('SCHEMA', server), + application_name: getPgConnectionEnvValue('APPLICATION_NAME', server), + }; + console.log(conn); + return conn; } export function getConnectionConfig(server: PgServer = PgServer.default): PgConnectionOptions { diff --git a/tests/2.5/env-setup.ts b/tests/2.5/env-setup.ts index 65e6ce380..dc4f10983 100644 --- a/tests/2.5/env-setup.ts +++ b/tests/2.5/env-setup.ts @@ -16,7 +16,7 @@ beforeAll(async () => { } loadDotEnv(); - process.env.PG_DATABASE = 'postgres'; + process.env.PG_DATABASE = 'stacks_api'; process.env.STACKS_CHAIN_ID = '0x80000000'; const db = await PgWriteStore.connect({ usageName: 'tests' });