|
| 1 | +# Fhenix Foundry Development Container |
| 2 | +# Multi-stage build: extracts LocalFhenix components and combines with Foundry tooling |
| 3 | + |
| 4 | +# Stage 1: Extract components from Fhenix devnet image |
| 5 | +FROM ghcr.io/fhenixprotocol/fhenix-devnet:0.1.6 AS fhenix-source |
| 6 | + |
| 7 | +# Stage 2: Build on foundry base with all Fhenix components |
| 8 | +FROM foundry:latest |
| 9 | + |
| 10 | +ENV FHENIX_HOME=/opt/fhenix \ |
| 11 | + EVMOSD_HOME=/root/.evmosd \ |
| 12 | + FHENIX_RPC_PORT=8545 \ |
| 13 | + FHENIX_FAUCET_PORT=6000 \ |
| 14 | + FHENIX_CHAIN_ID=evmos_5432-1 \ |
| 15 | + FHENIX_HELIUM_RPC=https://api.helium.fhenix.zone \ |
| 16 | + PATH=/opt/fhenix/bin:$PATH |
| 17 | + |
| 18 | +USER root |
| 19 | + |
| 20 | +# Install runtime dependencies for Fhenix services |
| 21 | +RUN apt-get update && \ |
| 22 | + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ |
| 23 | + python3 python3-pip jq && \ |
| 24 | + rm -rf /var/lib/apt/lists/* |
| 25 | + |
| 26 | +# Create directory structure |
| 27 | +RUN mkdir -p /opt/fhenix/bin /opt/fhenix/config /opt/fhenix/scripts /res/ct |
| 28 | + |
| 29 | +# Copy Fhenix binaries from source image |
| 30 | +COPY --from=fhenix-source /usr/bin/evmosd /opt/fhenix/bin/evmosd |
| 31 | +COPY --from=fhenix-source /zbc-fhe-tool /opt/fhenix/bin/zbc-fhe-tool |
| 32 | +COPY --from=fhenix-source /zbc-oracle-db /opt/fhenix/bin/zbc-oracle-db |
| 33 | + |
| 34 | +# Copy Fhenix scripts and configs |
| 35 | +COPY --from=fhenix-source /run.sh /opt/fhenix/scripts/run-localfhenix.sh |
| 36 | +COPY --from=fhenix-source /faucet.js /opt/fhenix/scripts/faucet.js |
| 37 | +COPY --from=fhenix-source /encryption_server.py /opt/fhenix/scripts/encryption_server.py |
| 38 | +COPY --from=fhenix-source /requirements.txt /opt/fhenix/requirements.txt |
| 39 | +COPY --from=fhenix-source /Rocket.toml /opt/fhenix/Rocket.toml |
| 40 | +COPY --from=fhenix-source /config/ /opt/fhenix/config/ |
| 41 | + |
| 42 | +# Copy pre-configured evmosd home directory |
| 43 | +COPY --from=fhenix-source /root/.evmosd /root/.evmosd |
| 44 | + |
| 45 | +# Install Python dependencies for encryption server |
| 46 | +RUN pip3 install --no-cache-dir --break-system-packages -r /opt/fhenix/requirements.txt || \ |
| 47 | + pip3 install --no-cache-dir --break-system-packages flask || true |
| 48 | + |
| 49 | +# Create unified startup script |
| 50 | +RUN echo '#!/bin/bash\n\ |
| 51 | +set -e\n\ |
| 52 | +CHAIN_ID=${FHENIX_CHAIN_ID:-"evmos_5432-1"}\n\ |
| 53 | +\n\ |
| 54 | +echo "=== Starting LocalFhenix ===" \n\ |
| 55 | +echo "Chain ID: $CHAIN_ID"\n\ |
| 56 | +echo "RPC Port: $FHENIX_RPC_PORT"\n\ |
| 57 | +echo "Faucet Port: $FHENIX_FAUCET_PORT"\n\ |
| 58 | +echo ""\n\ |
| 59 | +\n\ |
| 60 | +mkdir -p /res/ct\n\ |
| 61 | +\n\ |
| 62 | +# Start FHE Oracle DB\n\ |
| 63 | +echo "Starting FHE Oracle DB..."\n\ |
| 64 | +/opt/fhenix/bin/zbc-oracle-db &\n\ |
| 65 | +\n\ |
| 66 | +# Start Faucet\n\ |
| 67 | +echo "Starting Faucet on port $FHENIX_FAUCET_PORT..."\n\ |
| 68 | +cd /opt/fhenix/scripts && node faucet.js &\n\ |
| 69 | +\n\ |
| 70 | +# Start Encryption Server\n\ |
| 71 | +echo "Starting Encryption Server..."\n\ |
| 72 | +cd /opt/fhenix/scripts && python3 encryption_server.py &\n\ |
| 73 | +\n\ |
| 74 | +# Configure evmosd\n\ |
| 75 | +/opt/fhenix/bin/evmosd config output json\n\ |
| 76 | +/opt/fhenix/bin/evmosd config chain-id $CHAIN_ID\n\ |
| 77 | +\n\ |
| 78 | +# Start evmosd\n\ |
| 79 | +echo "Starting Evmos daemon with FHE support..."\n\ |
| 80 | +/opt/fhenix/bin/evmosd start \\\n\ |
| 81 | + --chain-id $CHAIN_ID \\\n\ |
| 82 | + --home /root/.evmosd \\\n\ |
| 83 | + --minimum-gas-prices=0.000000000000000001aevmos \\\n\ |
| 84 | + --json-rpc.gas-cap=9999999999999999 \\\n\ |
| 85 | + --gas-prices=0.00000000000000000000000000000000001aevmos \\\n\ |
| 86 | + --json-rpc.api eth,txpool,personal,net,debug,web3\n\ |
| 87 | +' > /opt/fhenix/scripts/start-localfhenix.sh && chmod +x /opt/fhenix/scripts/start-localfhenix.sh |
| 88 | + |
| 89 | +# Create project initialization and info scripts |
| 90 | +RUN mkdir -p /home/project/.fhenix-foundry/scripts && \ |
| 91 | + echo '#!/bin/bash\n\ |
| 92 | +echo "=== Fhenix Foundry Project Setup ==="\n\ |
| 93 | +echo ""\n\ |
| 94 | +if [ -f foundry.toml ]; then\n\ |
| 95 | + echo "Foundry project already initialized"\n\ |
| 96 | +else\n\ |
| 97 | + forge init . --no-commit\n\ |
| 98 | + echo "Foundry project created"\n\ |
| 99 | +fi\n\ |
| 100 | +echo ""\n\ |
| 101 | +echo "Installing Fhenix dependencies..."\n\ |
| 102 | +forge install fhenixprotocol/fhenix-contracts --no-commit 2>/dev/null || echo "fhenix-contracts may already be installed"\n\ |
| 103 | +forge install fhenixprotocol/cofhe-foundry-mocks --no-commit 2>/dev/null || echo "cofhe-foundry-mocks may already be installed"\n\ |
| 104 | +forge install openzeppelin/openzeppelin-contracts --no-commit 2>/dev/null || echo "openzeppelin already installed"\n\ |
| 105 | +echo ""\n\ |
| 106 | +echo "Add these remappings to remappings.txt:"\n\ |
| 107 | +echo "@fhenixprotocol/contracts/=lib/fhenix-contracts/contracts/"\n\ |
| 108 | +echo "@fhenixprotocol/cofhe-foundry-mocks/=lib/cofhe-foundry-mocks/src/"\n\ |
| 109 | +echo "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/"\n\ |
| 110 | +echo ""\n\ |
| 111 | +echo "Done! See /home/project/.fhenix-foundry/scripts/show-info.sh for FHE development tips"\n\ |
| 112 | +' > /home/project/.fhenix-foundry/init-project.sh && \ |
| 113 | + echo '#!/bin/bash\n\ |
| 114 | +echo "=== Fhenix Foundry Development Environment ==="\n\ |
| 115 | +echo ""\n\ |
| 116 | +echo "LocalFhenix is bundled in this container - no Docker-in-Docker required!"\n\ |
| 117 | +echo ""\n\ |
| 118 | +echo "=== Start LocalFhenix ==="\n\ |
| 119 | +echo " /opt/fhenix/scripts/start-localfhenix.sh"\n\ |
| 120 | +echo ""\n\ |
| 121 | +echo "=== Endpoints (after starting) ==="\n\ |
| 122 | +echo " RPC: http://127.0.0.1:8545"\n\ |
| 123 | +echo " Faucet: curl http://127.0.0.1:6000/faucet?address=YOUR_ADDRESS"\n\ |
| 124 | +echo ""\n\ |
| 125 | +echo "=== Testing FHE Contracts ==="\n\ |
| 126 | +echo "The cofhe-foundry-mocks package provides mock FHE operations"\n\ |
| 127 | +echo "that simulate encryption without actual FHE computation."\n\ |
| 128 | +echo ""\n\ |
| 129 | +echo "Example test contract:"\n\ |
| 130 | +echo ""\n\ |
| 131 | +echo " import {CoFheTest} from \"@fhenixprotocol/cofhe-foundry-mocks/CoFheTest.sol\";"\n\ |
| 132 | +echo " import {FHE, euint32} from \"@fhenixprotocol/contracts/FHE.sol\";"\n\ |
| 133 | +echo ""\n\ |
| 134 | +echo " contract MyTest is CoFheTest {"\n\ |
| 135 | +echo " function testEncryptedAdd() public {"\n\ |
| 136 | +echo " euint32 a = FHE.asEuint32(10);"\n\ |
| 137 | +echo " euint32 b = FHE.asEuint32(20);"\n\ |
| 138 | +echo " euint32 result = FHE.add(a, b);"\n\ |
| 139 | +echo " assertEq(FHE.decrypt(result), 30);"\n\ |
| 140 | +echo " }"\n\ |
| 141 | +echo " }"\n\ |
| 142 | +echo ""\n\ |
| 143 | +echo "=== Encrypted Types ==="\n\ |
| 144 | +echo " euint8, euint16, euint32, euint64, euint128, euint256"\n\ |
| 145 | +echo " ebool, eaddress"\n\ |
| 146 | +echo ""\n\ |
| 147 | +echo "=== FHE Operations ==="\n\ |
| 148 | +echo " FHE.asEuint*() - Encrypt plaintext values"\n\ |
| 149 | +echo " FHE.add(), FHE.sub(), FHE.mul() - Arithmetic"\n\ |
| 150 | +echo " FHE.and(), FHE.or(), FHE.xor() - Bitwise"\n\ |
| 151 | +echo " FHE.eq(), FHE.ne(), FHE.lt(), FHE.gt() - Comparisons"\n\ |
| 152 | +echo " FHE.select() - Conditional selection"\n\ |
| 153 | +echo " FHE.decrypt() - Reveal encrypted value"\n\ |
| 154 | +echo ""\n\ |
| 155 | +echo "=== Deployment ==="\n\ |
| 156 | +echo " Local: forge script script/Deploy.s.sol --rpc-url http://127.0.0.1:8545 --broadcast"\n\ |
| 157 | +echo " Testnet: forge script script/Deploy.s.sol --rpc-url \$FHENIX_HELIUM_RPC --broadcast"\n\ |
| 158 | +echo ""\n\ |
| 159 | +echo "=== Notes ==="\n\ |
| 160 | +echo " 1. Mock operations do NOT reflect real FHE gas costs"\n\ |
| 161 | +echo " 2. Security zones are not enforced in mocks"\n\ |
| 162 | +echo " 3. Use LocalFhenix for integration testing with real FHE"\n\ |
| 163 | +echo ""\n\ |
| 164 | +echo "=== Docs ==="\n\ |
| 165 | +echo " https://docs.fhenix.zone"\n\ |
| 166 | +echo " https://github.com/FhenixProtocol/fhenix-foundry-template"\n\ |
| 167 | +echo " https://github.com/FhenixProtocol/cofhe-foundry-mocks"\n\ |
| 168 | +' > /home/project/.fhenix-foundry/scripts/show-info.sh && \ |
| 169 | + chmod +x /home/project/.fhenix-foundry/*.sh /home/project/.fhenix-foundry/scripts/*.sh && \ |
| 170 | + ln -s /opt/fhenix/scripts/start-localfhenix.sh /home/project/.fhenix-foundry/start-localfhenix.sh && \ |
| 171 | + chown -R project:project /home/project/.fhenix-foundry |
| 172 | + |
| 173 | +# Install minimal npm packages for Fhenix JS SDK |
| 174 | +RUN npm install -g fhenixjs ethers viem |
| 175 | + |
| 176 | +# Pre-warm npm cache |
| 177 | +RUN npm cache add fhenixjs@latest @openzeppelin/contracts@latest |
| 178 | + |
| 179 | +USER project |
| 180 | + |
| 181 | +LABEL description="Fhenix Foundry development with embedded LocalFhenix (no Docker-in-Docker required)" |
0 commit comments