diff --git a/compose/Dockerfile.dingo b/compose/Dockerfile.dingo new file mode 100644 index 0000000..2001693 --- /dev/null +++ b/compose/Dockerfile.dingo @@ -0,0 +1,100 @@ +ARG CARDANO_CLI_VERSION="${CARDANO_CLI_VERSION:-10.8.0.0}" +ARG CARDANO_NODE_VERSION="${CARDANO_NODE_VERSION:-10.4.1}" +ARG DINGO_VERSION="${DINGO_VERSION:-0.12.0}" +ARG UV_VERSION="${UV_VERSION:-0.6.11}" +# Blink Labs images are built from source on Debian Bookworm +FROM ghcr.io/blinklabs-io/cardano-cli:${CARDANO_CLI_VERSION} AS cardano-cli +FROM ghcr.io/astral-sh/uv:${UV_VERSION} AS uv + +FROM ghcr.io/blinklabs-io/cardano-node:${CARDANO_NODE_VERSION} AS build + +# Set time zone +ENV TZ="UTC" +RUN ln -snf /usr/share/zoneinfo/${TZ} /etc/localtime && \ + echo ${TZ} > /etc/timezone + +# Install packages required in build stage +RUN apt update && \ + apt install -y --no-install-recommends \ + ca-certificates \ + curl \ + git \ + tar + +# Copy cardano-cli from image +COPY --from=cardano-cli --chown=root:root /usr/local/bin/cardano-cli /usr/local/bin/cardano-cli +# Copy uv from image +COPY --from=uv --chown=root:root /uv /usr/local/bin/uv + +# Create cardano-node source directory +RUN install --directory --owner=root --group=root --mode=0755 /usr/local/src/cardano-node + +# Clone testnet-generation-tool.git repository +WORKDIR /usr/local/src +RUN git clone --branch main https://github.com/cardano-foundation/testnet-generation-tool.git + +# Download testnet-generation-tool dependencies +WORKDIR /usr/local/src/testnet-generation-tool +RUN uv sync + +# Copy testnet.yaml specification +COPY --chown=root:root .testnet.yaml /usr/local/src/testnet-generation-tool/testnet.yaml + +# Build testnet configuration files +RUN uv run python3 genesis-cli.py testnet.yaml -o /tmp/testnet -c generate + +# Remove dynamic topology.json +RUN find /tmp/testnet -type f -name 'topology.json' -exec rm -f '{}' ';' + +# Delete ftsSeed (dingo requires a string, currently) +RUN find /tmp/testnet -type f -name 'byron-genesis.json' -exec sed -i '/ftsSeed/d' '{}' ';' + +#--------------------------------------------------------------------- + +FROM ghcr.io/blinklabs-io/dingo:${DINGO_VERSION} + +# Set time zone +ENV TZ="UTC" +RUN ln -snf /usr/share/zoneinfo/${TZ} /etc/localtime && \ + echo ${TZ} > /etc/timezone + +# Install packages required in main stage +RUN apt update && \ + apt install -y --no-install-recommends \ + dnsutils \ + iproute2 \ + iputils-ping \ + jq \ + less \ + lsof \ + netbase \ + netcat-openbsd \ + openssl \ + procps \ + tcpdump \ + telnet \ + vim + +# Create cardano group and user +RUN groupadd --gid 10000 cardano && \ + useradd --comment 'cardano' --create-home --gid 10000 --password '!' --shell '/bin/bash' --uid 10000 cardano + +# Create cardano-node directories +RUN install --directory --owner=root --group=root --mode=0755 /opt/cardano-node && \ + install --directory --owner=cardano --group=cardano --mode=0750 /opt/cardano-node/config && \ + install --directory --owner=cardano --group=cardano --mode=0750 /opt/cardano-node/data && \ + install --directory --owner=cardano --group=cardano --mode=0750 /opt/cardano-node/data/db && \ + install --directory --owner=cardano --group=cardano --mode=0750 /opt/cardano-node/log && \ + install --directory --owner=cardano --group=cardano --mode=0750 /opt/cardano-node/pools + +# Copy pool config and key material +COPY --from=build --chown=cardano:cardano /tmp/testnet/pools /opt/cardano-node/pools + +# Copy dingo.sh +COPY dingo.sh / +RUN chmod 0755 /dingo.sh + +USER cardano +#STOPSIGNAL SIGINT + +ENTRYPOINT ["/dingo.sh"] diff --git a/compose/Makefile b/compose/Makefile index 98d8630..86cbdc7 100644 --- a/compose/Makefile +++ b/compose/Makefile @@ -48,7 +48,7 @@ help: @echo " make anti password='password1234' session_id= input_hash= vtime=" @echo -build: TESTNET build-image build-config build-sidecar build-tracer build-tracer-sidecar ## Build cardano-node, config, sidecar, and tracer images +build: TESTNET build-image build-config build-sidecar build-tracer build-tracer-sidecar build-dingo ## Build cardano-node, config, sidecar, and tracer images build-image: TESTNET ## Build cardano-node container image ln -snf testnets/${testnet}/testnet.yaml .testnet.yaml ; cd testnets/${testnet} ; docker compose build @@ -65,7 +65,10 @@ build-tracer: TESTNET ## Build tracer container image build-tracer-sidecar: TESTNET ## Build tracer container image docker build -f tracer-sidecar/Dockerfile -t ${registry}${testnet}_tracer-sidecar:latest tracer-sidecar/ -push: TESTNET push-image push-config push-tracer push-sidecar push-tracer-sidecar ## Push cardano-node, config and sidecar container image +build-dingo: TESTNET ## Build dingo container image + docker build -f Dockerfile.dingo -t ${registry}${testnet}_dingo:latest . + +push: TESTNET push-image push-config push-tracer push-sidecar push-tracer-sidecar push-dingo ## Push cardano-node, config and sidecar container image push-image: TESTNET ## Push cardano-node container image docker push ${registry}${testnet}:latest @@ -82,6 +85,9 @@ push-tracer: TESTNET ## Push tracer container image push-tracer-sidecar: TESTNET ## Push tracer container image docker push ${registry}${testnet}_tracer-sidecar:latest +push-dingo: TESTNET ## Push dingo container image + docker push ${registry}${testnet}_dingo:latest + up: TESTNET ## Start Run local Docker Compose cd testnets/${testnet} ; docker compose up --detach @@ -100,7 +106,7 @@ anti: TESTNET ## Run Antithesis job --arg description '${description}' \ --arg duration '${duration}' \ --arg config_image '${testnet}_config:latest' \ - --arg images '${testnet}:latest;${testnet}_sidecar:latest;${testnet}_tracer:latest;${testnet}_tracer-sidecar:latest' \ + --arg images '${testnet}:latest;${testnet}_sidecar:latest;${testnet}_tracer:latest;${testnet}_tracer-sidecar:latest;${testnet}_dingo:latest' \ --arg recipients '${recipients}' \ '{params: {"antithesis.description": $$description,"custom.duration": $$duration,"antithesis.config_image": $$config_image,"antithesis.images": $$images,"antithesis.report.recipients": $$recipients}}')" diff --git a/compose/dingo.sh b/compose/dingo.sh new file mode 100755 index 0000000..6edaa39 --- /dev/null +++ b/compose/dingo.sh @@ -0,0 +1,129 @@ +#!/usr/bin/env bash + +# Required for overriding exit code +#set -o errexit +set -o pipefail + +SHELL="/bin/bash" +PATH="/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin" + +# Environment variables +PORT="${PORT:-3001}" +PROMETHEUS_LISTEN="${PROMETHEUS_LISTEN:-127.0.0.1}" +PROMETHEUS_PORT="${PROMETHEUS_PORT:-12798}" +SYSTEM_START="${SYSTEM_START:-$(date -d "@$(( ( $(date +%s) / 120 ) * 120 ))" +%Y-%m-%dT%H:%M:00Z)}" +USE_LEDGER_AFTER_SLOT="${USE_LEDGER_AFTER_SLOT:-0}" + +# Antithesis +ANTITHESIS_OUTPUT_DIR="${ANTITHESIS_OUTPUT_DIR:-/tmp}" + +# Configuration files +BYRON_GENESIS_JSON="${BYRON_GENESIS_JSON:-/opt/cardano-node/pools/1/configs/byron-genesis.json}" +CARDANO_CONFIG="/opt/cardano-node/pools/1/configs/config.json" +CONFIG_PATH="/opt/cardano-node/config" +DATA_PATH="/opt/cardano-node/data" +SHELLEY_GENESIS_JSON="${SHELLEY_GENESIS_JSON:-/opt/cardano-node/pools/1/configs/shelley-genesis.json}" + +# Log file +LOG_FILE="/opt/cardano-node/log/node.json" + +# Implement sponge-like command without the need for binary nor TMPDIR environment variable +write_file() { + # Create temporary file + local tmp_file="${1}_$(tr "${tmp_file}" + + # Replace the original file + mv --force "${tmp_file}" "${1}" +} + +config_config_json() { + # .AlonzoGenesisHash, .ByronGenesisHash, .ConwayGenesisHash, .ShelleyGenesisHash + jq "del(.AlonzoGenesisHash, .ByronGenesisHash, .ConwayGenesisHash, .ShelleyGenesisHash)" "${CARDANO_CONFIG}" | write_file "${CARDANO_CONFIG}" + + # .PeerSharing + if [ "${PEER_SHARING,,}" = "true" ]; then + jq ".PeerSharing = true" "${CARDANO_CONFIG}" | write_file "${CARDANO_CONFIG}" + else + jq ".PeerSharing = false" "${CARDANO_CONFIG}" | write_file "${CARDANO_CONFIG}" + fi +} + +config_topology_json() { + # Connect to everything + mkdir -p ${CONFIG_PATH} + cat < "${CONFIG_PATH}/topology-dingo.json" +{ + "localRoots": [ + { + "accessPoints": [ + {"address": "p1.example", "port": 3001}, + {"address": "p2.example", "port": 3001}, + {"address": "p3.example", "port": 3001}, + {"address": "p4.example", "port": 3001}, + {"address": "p5.example", "port": 3001} + ], + "advertise": true, + "trustable": true, + "valency": 2 + } + ], + "publicRoots": [], + "useLedgerAfterSlot": 0 +} +EOF +} + +set_start_time() { + if [ ! -f "${DATA_PATH}/start_time.unix_epoch" ]; then + # Convert ISO time to unix epoch + SYSTEM_START_UNIX=$(date -d "${SYSTEM_START}" +%s) + mkdir -p ${DATA_PATH} + echo "${SYSTEM_START_UNIX}" >"${DATA_PATH}/start_time.unix_epoch" + + update_start_time + else + SYSTEM_START_UNIX="$(cat "${DATA_PATH}/start_time.unix_epoch")" + update_start_time + fi +} + +update_start_time() { + # Convert unix epoch to ISO time + SYSTEM_START_ISO="$(date -d @${SYSTEM_START_UNIX} '+%Y-%m-%dT%H:%M:00Z')" + + # .systemStart + jq ".systemStart = \"${SYSTEM_START_ISO}\"" "${SHELLEY_GENESIS_JSON}" | write_file "${SHELLEY_GENESIS_JSON}" + + # .startTime + jq ".startTime = ${SYSTEM_START_UNIX}" "${BYRON_GENESIS_JSON}" | write_file "${BYRON_GENESIS_JSON}" +} + +export_environment() { + export CARDANO_CONFIG + export CARDANO_DATABASE_PATH="/opt/cardano-node/data/db" + export CARDANO_NETWORK=devnet + export CARDANO_SOCKET_PATH="/opt/cardano-node/data/db/dingo.socket" + export CARDANO_TOPOLOGY="${CONFIG_PATH}/topology-dingo.json" +} + +# Establish run order +main() { + config_config_json + config_topology_json + set_start_time + export_environment + /bin/dingo + exit_code=$? + if [ ${exit_code} -eq 1 ]; then + echo "exit code: 0" + exit 0 + else + echo "exit code: ${exit_code}" + exit ${?} + fi +} + +main diff --git a/compose/testnets/cardano_node_10.4.1/README.md b/compose/testnets/cardano_node_10.4.1/README.md index e37e53a..4da569e 100644 --- a/compose/testnets/cardano_node_10.4.1/README.md +++ b/compose/testnets/cardano_node_10.4.1/README.md @@ -10,4 +10,4 @@ A 5 pools testnet using cardano-node version 10.4.1 testing consistency between ## Testnet -- **Pools**: 3 +- **Pools**: 5 diff --git a/compose/testnets/cardano_node_10.4.1_dingo_0.12.0/README.md b/compose/testnets/cardano_node_10.4.1_dingo_0.12.0/README.md new file mode 100644 index 0000000..f169eaf --- /dev/null +++ b/compose/testnets/cardano_node_10.4.1_dingo_0.12.0/README.md @@ -0,0 +1,13 @@ +# Description + +A 5 pools testnet using cardano-node version 10.4.1 testing consistency between nodes runnning UTxO-HD with LMDB and in-memory: We run 3 nodes with in-memory DB and 2 node with LMDB and check they are still consistent. A single Dingo 0.12.0 node is added to the network as a client not producing blocks. + +## Cardano-Node + +- **Version**: 10.4.1 +- **Branch**: - +- **Source/Compiled**: Compiled + +## Testnet + +- **Pools**: 5 diff --git a/compose/testnets/cardano_node_10.4.1_dingo_0.12.0/docker-compose.yaml b/compose/testnets/cardano_node_10.4.1_dingo_0.12.0/docker-compose.yaml new file mode 100644 index 0000000..af0db19 --- /dev/null +++ b/compose/testnets/cardano_node_10.4.1_dingo_0.12.0/docker-compose.yaml @@ -0,0 +1,153 @@ +--- + +x-base: &base + image: ${registry}${testnet}:latest + restart: on-failure + build: + context: "../../" + dockerfile: "Dockerfile.compiled" + args: + CARDANO_NODE_VERSION: "10.4.1" + +x-tracer-base: &tracerbase + image: ${registry}${testnet}_tracer:latest + restart: on-failure + build: + context: "../../tracer/" + # ideally we would like to use a precompiled version of the tracer + # but unfortunately it's not yet packaged in archives + # https://github.com/IntersectMBO/cardano-node/issues/6228 + dockerfile: "Dockerfile.compiled" + args: + CARDANO_NODE_REF: "10.4.1" + +x-env: &env + POOL_ID: "0" # Placeholder required for override + UTXO_HD_WITH: "mem" + +services: + tracer: + <<: *tracerbase + hostname: tracer.example + container_name: tracer + volumes: + - tracer:/opt/cardano-tracer + ports: + - "4000:4000" + command: + - "--config" + - "tracer-config.yaml" + + d1: + <<: *base + image: ${registry}${testnet}_dingo:latest + restart: on-failure + hostname: d1.example + container_name: d1 + build: + context: "../../" + dockerfile: "Dockerfile.dingo" + args: + DINGO_VERSION: '0.12.0' + volumes: + - d1:/data/db + ports: + - "3000:3001" + - "9090:9090" + environment: + <<: *env + + p1: + <<: *base + container_name: p1 + hostname: p1.example + volumes: + - p1:/opt/cardano-node/data + - tracer:/opt/cardano-tracer + ports: + - "3001:3001" + environment: + <<: *env + POOL_ID: "1" + UTXO_HD_WITH: "hd" + + p2: + <<: *base + container_name: p2 + hostname: p2.example + volumes: + - p2:/opt/cardano-node/data + - tracer:/opt/cardano-tracer + ports: + - "3002:3001" + environment: + <<: *env + POOL_ID: "2" + + p3: + <<: *base + container_name: p3 + hostname: p3.example + volumes: + - p3:/opt/cardano-node/data + - tracer:/opt/cardano-tracer + ports: + - "3003:3001" + environment: + <<: *env + POOL_ID: "3" + + p4: + <<: *base + container_name: p4 + hostname: p4.example + volumes: + - p4:/opt/cardano-node/data + - tracer:/opt/cardano-tracer + ports: + - "3004:3001" + environment: + <<: *env + POOL_ID: "4" + UTXO_HD_WITH: "hd" + + + p5: + <<: *base + container_name: p5 + hostname: p5.example + volumes: + - p5:/opt/cardano-node/data + - tracer:/opt/cardano-tracer + ports: + - "3005:3001" + environment: + <<: *env + POOL_ID: "5" + + s1: + image: ${registry}${testnet}_sidecar:latest + restart: on-failure + container_name: s1 + hostname: s1.example + environment: + POOLS: "5" + + tracer-sidecar: + image: ${registry}${testnet}_tracer-sidecar:latest + restart: on-failure + container_name: tracer-sidecar + hostname: tracer-sidecar.example + environment: + POOLS: "5" + volumes: + - tracer:/opt/cardano-tracer + +volumes: + tracer: + d1: + p1: + p2: + p3: + p4: + p5: diff --git a/compose/testnets/cardano_node_10.4.1_dingo_0.12.0/testnet.yaml b/compose/testnets/cardano_node_10.4.1_dingo_0.12.0/testnet.yaml new file mode 100644 index 0000000..851e570 --- /dev/null +++ b/compose/testnets/cardano_node_10.4.1_dingo_0.12.0/testnet.yaml @@ -0,0 +1,134 @@ +--- # Required Testnet Parameters +poolCount: 5 +poolCost: 340000000 +poolMargin: 0.0 +poolPledge: 0 +delegatedSupply: 600000000000000 +systemStart: 'now' +systemStartDelay: 5 +networkMagic: 42 +testnetDomain: example + +--- # Optional Byron Genesis Overide +protocolConsts: + k: 432 + +--- # Optional Shelley Genesis Overide +epochLength: 86400 +securityParam: 432 +maxLovelaceSupply: 45000000000000000 +protocolParams: + decentralisationParam: 0 + protocolVersion: + major: 10 + minor: 0 + +--- # Optional Alonzo Genesis Overide + +--- # Optional Conway Genesis Overide + +--- # Optional Node Config Overide +ExperimentalHardForksEnabled: true +ExperimentalProtocolsEnabled: true +LastKnownBlockVersion-Alt: 0 +LastKnownBlockVersion-Major: 6 +LastKnownBlockVersion-Minor: 0 +MaxConcurrencyBulkSync: 2 +MaxConcurrencyDeadline: 4 +MaxKnownMajorProtocolVersion: 2 +PeerSharing: true +TargetNumberOfActiveBigLedgerPeers: 2 +TargetNumberOfActivePeers: 3 +TargetNumberOfEstablishedBigLedgerPeers: 3 +TargetNumberOfEstablishedPeers: 3 +TargetNumberOfKnownBigLedgerPeers: 10 +TargetNumberOfKnownPeers: 30 +TargetNumberOfRootPeers: 10 +TestAllegraHardForkAtEpoch: 0 +TestAlonzoHardForkAtEpoch: 0 +TestBabbageHardForkAtEpoch: 0 +TestConwayHardForkAtEpoch: 0 +TestMaryHardForkAtEpoch: 0 +TestShelleyHardForkAtEpoch: 0 +TraceConnectionManager: true +TraceConnectionManagerTransitions: true +TraceDNSResolver: true +TraceDNSSubscription: true +TraceDebugPeerSelection: true +TraceForge: true +TraceForgeStateInfo: true +TraceHandshake: true +TraceInboundGovernor: true +TraceIpSubscription: true +TraceLedgerPeers: true +TraceLocalConnectionManager: true +TraceLocalHandshake: true +TraceLocalRootPeers: true +TracePeerSelection: true +TracePeerSelectionActions: true +TracePublicRootPeers: true +TraceServer: true +TurnOnLoggingMetrics: true +TurnOnLogging: true +UseTraceDispatcher: true +TraceOptionForwarder: + connQueueSize: 64 + disconnQueueSize: 128 + maxReconnectDeplay: 30 +TraceOptions: + '': + backends: + - EKGBackend + - Forwarder + detail: DNormal + severity: Notice + BlockFetch.Client.CompletedBlockFetch: + maxFrequency: 2 + BlockFetch.Decision: + severity: Silence + ChainDB: + severity: Info + ChainDB.AddBlockEvent.AddBlockValidation: + severity: Silence + ChainDB.AddBlockEvent.AddBlockValidation.ValidCandidate: + maxFrequency: 2 + ChainDB.AddBlockEvent.AddedBlockToQueue: + maxFrequency: 2 + ChainDB.AddBlockEvent.AddedBlockToVolatileDB: + maxFrequency: 2 + ChainDB.CopyToImmutableDBEvent.CopiedBlockToImmutableDB: + maxFrequency: 2 + ChainSync.Client: + severity: Warning + Forge.Loop: + severity: Info + Forge.StateInfo: + severity: Info + Mempool: + severity: Silence + Net.ConnectionManager.Remote: + severity: Info + Net.ConnectionManager.Remote.ConnectionManagerCounters: + severity: Silence + Net.ErrorPolicy: + severity: Info + Net.ErrorPolicy.Local: + severity: Info + Net.InboundGovernor: + severity: Warning + Net.InboundGovernor.Remote: + severity: Info + Net.Mux.Remote: + severity: Info + Net.PeerSelection: + severity: Silence + Net.PeerSelection.Actions: + severity: Info + Net.Subscription.DNS: + severity: Info + Net.Subscription.IP: + severity: Info + Resources: + severity: Silence + Startup.DiffusionInit: + severity: Info