forked from ethereum/go-ethereum
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Add Foundry for Manual Integration Testing
- Loading branch information
Showing
14 changed files
with
445 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
# Foundry README | ||
|
||
# Overview | ||
|
||
This document will go through the steps needed to test using Foundry. Currently, we use Foundry in the following capacity. | ||
|
||
1. Create a private network with our internal version of Geth. | ||
2. Deploy a smart contract to the private network. | ||
3. Test the smart contract on the private network. | ||
4. Create a transaction on the private network. | ||
|
||
# Steps | ||
|
||
The steps to create a new project are as follows. | ||
|
||
## 1. Creating New Project | ||
|
||
1. `cd foundry/projects`. | ||
2. Create a directory that captures your project: `mkdir local-private-network; cd local-private-network`. | ||
3. Create a [new foundry project](https://onbjerg.github.io/foundry-book/forge/creating-a-new-project.html): `forge init stateful`. | ||
4. Follow the foundry [documentation](https://onbjerg.github.io/foundry-book/forge/tests.html) for writing smart contract tests. | ||
|
||
## 2. Deployments | ||
|
||
You can choose to have custom deployments for your workflow. However, it is recommended to utilize Docker. | ||
|
||
# Existing Projects | ||
|
||
Below, you can find existing projects and their descriptions. | ||
|
||
## `local-private-network` | ||
|
||
The purpose of this project is as follows: | ||
|
||
1. Compile the geth from the local source. | ||
2. Build a docker container with `ipld-eth-db` and another container for the `local-private-network`. | ||
3. Run the compiled version of geth. | ||
4. Deploy a smart contract to the private blockchain. | ||
5. Trigger a transaction on the newly deployed smart contract. | ||
|
||
## Using This Project | ||
|
||
If you want to test your local geth code, do the following: | ||
|
||
1. cd `foundry/projects/local-private-network`. | ||
2. `./wrapper.sh` - This script will do all the heavy lifting for you. | ||
3. Keep an eye out for the outputs from the docker container. | ||
4. Enter the docker container and do as you please. | ||
5. If you want to change your geth code, you will have to run `./wrapper.sh` for subsequent runs. | ||
6. If you do not change your geth code, you have to run: `docker-compose up --build`. | ||
|
||
### Key Notes: | ||
|
||
- The command to [deploy](https://onbjerg.github.io/foundry-book/forge/deploying.html) the smart contract is: `forge create --keystore $ETH_KEYSTORE_FILE --rpc-url [http://127.0.0.1:8545](http://127.0.0.1:8545/) --constructor-args 1 --password "" --legacy /root/stateful/src/Stateful.sol:Stateful` | ||
- The command to interact create a [transaction](https://onbjerg.github.io/foundry-book/reference/cast.html) is: `cast send --keystore $ETH_KEYSTORE_FILE --rpc-url [http://127.0.0.1:8545](http://127.0.0.1:8545/) --password "" --legacy $DEPLOYED_ADDRESS "off()"` | ||
- The `Dockerfile` compiles `cast` and `forge`. | ||
- The `foundry/projects/local-private-network/deploy-local-network.sh` file does most heavy lifting. It spins up geth and triggers various events. | ||
- The `foundry/projects/local-private-network/start-private-network.sh` file triggers `deploy-local-network.sh`. This file runs all the tests. | ||
- The `geth` node will stay running even after the tests are terminated. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
FROM frolvlad/alpine-bash | ||
|
||
# copy all files | ||
|
||
RUN apk update ; apk add --no-cache --allow-untrusted ca-certificates curl bash git jq | ||
|
||
ENV GLIBC_REPO=https://github.com/sgerrand/alpine-pkg-glibc | ||
ENV GLIBC_VERSION=2.35-r0 | ||
|
||
RUN set -ex && \ | ||
apk --update add libstdc++ curl ca-certificates && \ | ||
for pkg in glibc-${GLIBC_VERSION} glibc-bin-${GLIBC_VERSION}; \ | ||
do curl -sSL ${GLIBC_REPO}/releases/download/${GLIBC_VERSION}/${pkg}.apk -o /tmp/${pkg}.apk; done && \ | ||
apk add --allow-untrusted /tmp/*.apk ; \ | ||
rm -v /tmp/*.apk ;/usr/glibc-compat/sbin/ldconfig /lib /usr/glibc-compat/lib | ||
|
||
RUN apk add gcompat; echo "Sorry" | ||
WORKDIR /root | ||
|
||
COPY stateful ./stateful | ||
ADD ./start-private-network.sh . | ||
ADD ./deploy-local-network.sh . | ||
ADD ../../geth-linux-amd64 /bin/geth | ||
|
||
RUN curl -L https://foundry.paradigm.xyz | bash; \ | ||
/bin/bash -c 'source $HOME/.bashrc'; \ | ||
/root/.foundry/bin/foundryup | ||
|
||
ENV PATH "$PATH:/root/.foundry/bin/" | ||
RUN echo "export PATH=${PATH}" >> $HOME/.bashrc; | ||
|
||
RUN chmod +x /bin/geth | ||
|
||
|
||
EXPOSE 8545 | ||
EXPOSE 8546 | ||
ENTRYPOINT ["./start-private-network.sh"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#!/bin/bash | ||
set -e | ||
|
||
GREEN='\033[0;32m' | ||
RED='\033[0;31m' | ||
NC='\033[0m' | ||
|
||
start_path=$(pwd) | ||
cd ../../../ | ||
echo -e "${GREEN}Building geth!${NC}" | ||
docker build -t vulcanize/go-ethereum -f Dockerfile . | ||
docker run --rm --entrypoint cat vulcanize/go-ethereum /usr/local/bin/geth > foundry/projects/local-private-network/geth-linux-amd64 | ||
chmod +x foundry/projects/local-private-network/geth-linux-amd64 | ||
|
||
echo -e "${GREEN}geth build complete!${NC}" | ||
cd $start_path |
187 changes: 187 additions & 0 deletions
187
foundry/projects/local-private-network/deploy-local-network.sh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,187 @@ | ||
#!/bin/bash | ||
set -e | ||
|
||
OPTS="./deploy-local-network.sh [<options>] <args>... | ||
./deploy-local-network.sh --help | ||
-- | ||
db-user=name database user | ||
db-password=password database password | ||
db-name=name database name | ||
db-host=address database host | ||
db-port=port database port | ||
db-write=bool turn on database write mode | ||
db-type=name the type of database | ||
db-driver=name the driver used for the database | ||
db-waitforsync=bool Should the statediff service start once geth has synced to head (default: false) | ||
rpc-port=port change RPC port (default: 8545) | ||
rpc-addr=address change RPC address (default: 127.0.0.1) | ||
chain-id=number change chain ID (default: 99) | ||
period=seconds use a block time instead of instamine | ||
accounts=number create multiple accounts (default: 1) | ||
address=address eth address to add to genesis | ||
save=name after finishing, save snapshot | ||
load=name start from a previously saved snapshot | ||
dir=directory testnet directory | ||
" | ||
|
||
eval "$( | ||
git rev-parse --parseopt -- "$@" <<<"$OPTS" || echo exit $? | ||
)" | ||
|
||
DB_USER=vdbm | ||
DB_PASSWORD=password | ||
DB_NAME=vulcanize_public | ||
DB_HOST=127.0.0.1 | ||
DB_PORT=5432 | ||
DB_TYPE=postgres | ||
DB_DRIVER=sqlx | ||
DB_WAIT_FOR_SYNC=false | ||
RPC_PORT=8545 | ||
RPC_ADDRESS=127.0.0.1 | ||
PERIOD=0 | ||
CHAINID=99 | ||
ACCOUNTS=0 | ||
ADDRESS= | ||
gethdir=$HOME/testnet | ||
|
||
while [[ $1 ]]; do | ||
case $1 in | ||
--) shift; break;; | ||
--db-user) shift; DB_USER=$1;; | ||
--db-password) shift; DB_PASSWORD=$1;; | ||
--db-name) shift; DB_NAME=$1;; | ||
--db-host) shift; DB_HOST=$1;; | ||
--db-port) shift; DB_PORT=$1;; | ||
--db-write) shift; DB_WRITE=$1;; | ||
--db-type) shift; DB_TYPE=$1;; | ||
--db-driver) shift; DB_DRIVER=$1;; | ||
--db-waitforsync) shift; DB_WAIT_FOR_SYNC=$1;; | ||
--rpc-port) shift; RPC_PORT=$1;; | ||
--rpc-addr) shift; RPC_ADDRESS=$1;; | ||
--chain-id) shift; CHAINID=$1;; | ||
--period) shift; PERIOD=$1;; | ||
--accounts) shift; ACCOUNTS=$1;; | ||
--save) shift; SAVE=$1;; | ||
--address) shift; ADDRESS=$1;; | ||
--load) shift; LOAD=$1;; | ||
--dir) shift; gethdir=$1;; | ||
*) printf "${0##*/}: internal error: %q\\n" "$1"; exit 1 | ||
esac; shift | ||
done | ||
|
||
chaindir=$gethdir/$RPC_PORT | ||
#while true; do | ||
# if [[ ! -d "$gethdir/$CHAINID" ]]; then break; fi | ||
# CHAINID=$((CHAINID + 1)) | ||
#done | ||
|
||
mkdir -p "$chaindir/config" | ||
#if [ -n "$ADDRESS" ]; then | ||
# balance+=(-n {} -s "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" -i balance \ | ||
# -i "$ADDRESS") | ||
#fi | ||
for i in $(seq 0 "$ACCOUNTS"); do | ||
address+=( "$( | ||
geth 2>/dev/null account new --datadir "$chaindir" --password=<(exit) 2>/dev/null \ | ||
| grep -o -E "0x[A-Fa-f0-9]*" )" ) | ||
# balance+=(-n {} -s "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" -i balance \ | ||
# -i "${address[i]}") | ||
balance+=(' "'"${address[i]}"'": { "balance": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}') | ||
done | ||
|
||
#ALLOC_CLEAN=$(echo ${ALLOC} | jq .) | ||
EXTRA_DATA="0x3132333400000000000000000000000000000000000000000000000000000000${address[0]#0x}0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" | ||
JSON_VAL='{ | ||
"config": { | ||
"chainId": '"$CHAINID"', | ||
"homesteadBlock": 0, | ||
"eip150Block": 0, | ||
"eip155Block": 0, | ||
"eip158Block": 0, | ||
"byzantiumBlock": 0, | ||
"constantinopleBlock": 0, | ||
"petersburgBlock": 0, | ||
"istanbulBlock": 0, | ||
"clique": { | ||
"period": '"$PERIOD"', | ||
"epoch": 3000 | ||
} | ||
}, | ||
"difficulty": "0x1", | ||
"gaslimit": "0xffffffffffff", | ||
"extraData": "'"$EXTRA_DATA"'", | ||
"alloc": {'"$balance"'} | ||
}' | ||
echo $JSON_VAL | jq . > $chaindir/config/genesis.json | ||
|
||
geth 2>/dev/null --datadir "$chaindir" init "$chaindir/config/genesis.json" | ||
|
||
export ETH_RPC_URL=http://$RPC_ADDRESS:$RPC_PORT | ||
|
||
port=$((RPC_PORT + 30000)) | ||
|
||
geth version | ||
echo >&2 "dapp-testnet: RPC URL: $ETH_RPC_URL" | ||
echo >&2 "dapp-testnet: TCP port: $port" | ||
echo >&2 "dapp-testnet: Chain ID: $CHAINID" | ||
echo >&2 "dapp-testnet: Database: $chaindir" | ||
echo >&2 "dapp-testnet: Geth log: $chaindir/geth.log" | ||
|
||
printf "%s\n" "${address[@]}" > "$chaindir/config/account" | ||
echo "$ETH_RPC_URL" > "$chaindir/config/rpc-url" | ||
echo "$port" > "$chaindir/config/node-port" | ||
|
||
set +m | ||
# Uncomment below once waitforsync has been merged | ||
# geth \ | ||
# 2> >(tee "$chaindir/geth.log" | grep --line-buffered Success | sed 's/^/geth: /' >&2) \ | ||
# --datadir "$chaindir" --networkid "$CHAINID" --port="$port" \ | ||
# --mine --miner.threads=1 --allow-insecure-unlock \ | ||
# --http --http.api "web3,eth,net,debug,personal,statediff" --http.corsdomain '*' --http.vhosts '*' --nodiscover \ | ||
# --http.addr="$RPC_ADDRESS" --http.port="$RPC_PORT" --syncmode=full --gcmode=archive \ | ||
# --statediff --statediff.db.host="$DB_HOST" --statediff.db.port="$DB_PORT" --statediff.db.user="$DB_USER" \ | ||
# --statediff.db.password="$DB_PASSWORD" --statediff.db.name="$DB_NAME" \ | ||
# --statediff.db.nodeid 1 --statediff.db.clientname test1 --statediff.writing="$DB_WRITE" \ | ||
# --statediff.db.type="$DB_TYPE" --statediff.db.driver="$DB_DRIVER" --statediff.waitforsync="$DB_WAIT_FOR_SYNC" \ | ||
# --ws --ws.addr="0.0.0.0" --unlock="$(IFS=,; echo "${address[*]}")" --password=<(exit) & | ||
|
||
geth \ | ||
2> >(tee "$chaindir/geth.log" | grep --line-buffered Success | sed 's/^/geth: /' >&2) \ | ||
--datadir "$chaindir" --networkid "$CHAINID" --port="$port" \ | ||
--mine --miner.threads=1 --allow-insecure-unlock \ | ||
--http --http.api "web3,eth,net,debug,personal,statediff" --http.corsdomain '*' --http.vhosts '*' --nodiscover \ | ||
--http.addr="$RPC_ADDRESS" --http.port="$RPC_PORT" --syncmode=full --gcmode=archive \ | ||
--statediff --statediff.db.host="$DB_HOST" --statediff.db.port="$DB_PORT" --statediff.db.user="$DB_USER" \ | ||
--statediff.db.password="$DB_PASSWORD" --statediff.db.name="$DB_NAME" \ | ||
--statediff.db.nodeid 1 --statediff.db.clientname test1 --statediff.writing="$DB_WRITE" \ | ||
--statediff.db.type="$DB_TYPE" --statediff.db.driver="$DB_DRIVER" \ | ||
--ws --ws.addr="0.0.0.0" --unlock="$(IFS=,; echo "${address[*]}")" --password=<(exit) & | ||
|
||
gethpid=$! | ||
|
||
clean() { | ||
( set -x; kill -INT $gethpid; wait ) | ||
if [[ $SAVE ]]; then | ||
echo >&2 "dapp-testnet: saving $gethdir/snapshots/$SAVE" | ||
mkdir -p "$gethdir/snapshots/$SAVE" | ||
cp -r "$chaindir/keystore" "$gethdir/snapshots/$SAVE" | ||
cp -r "$chaindir/config" "$gethdir/snapshots/$SAVE" | ||
geth >/dev/null 2>&1 --datadir "$chaindir" \ | ||
export "$gethdir/snapshots/$SAVE/backup" | ||
fi | ||
( set -x; rm -rf "$chaindir" ) | ||
} | ||
trap clean EXIT | ||
|
||
until curl -s "$ETH_RPC_URL"; do sleep 1; done | ||
|
||
# UPDATE | ||
#ETH_FROM=$(seth --rpc-url="$ETH_RPC_URL" rpc eth_coinbase) | ||
#export ETH_FROM | ||
export ETH_KEYSTORE=$chaindir/keystore | ||
export ETH_PASSWORD=/dev/null | ||
printf 'dapp-testnet: Account: %s (default)\n' "${address[0]}" >&2 | ||
|
||
[[ "${#address[@]}" -gt 1 ]] && printf 'dapp-testnet: Account: %s\n' "${address[@]:1}" >&2 | ||
|
||
while true; do sleep 3600; done |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
version: "3.2" | ||
|
||
services: | ||
foundry: | ||
restart: unless-stopped | ||
depends_on: | ||
- ipld-eth-db | ||
build: ./ | ||
environment: | ||
DB_USER: vdbm | ||
DB_NAME: vulcanize_testing | ||
DB_HOST: ipld-eth-db | ||
DB_PORT: 5432 | ||
DB_PASSWORD: password | ||
DB_WRITE: "true" | ||
DB_TYPE: postgres | ||
DB_DRIVER: sqlx | ||
DB_WAIT_FOR_SYNC: "true" | ||
ports: | ||
- "127.0.0.1:8545:8545" | ||
- "127.0.0.1:8546:8546" | ||
|
||
ipld-eth-db: | ||
restart: always | ||
image: vulcanize/ipld-eth-db:v3.0.6 | ||
environment: | ||
POSTGRES_USER: "vdbm" | ||
POSTGRES_DB: "vulcanize_testing" | ||
POSTGRES_PASSWORD: "password" | ||
volumes: | ||
- vdb_db_eth_server:/var/lib/postgresql/data | ||
ports: | ||
- "127.0.0.1:8077:5432" | ||
command: ["postgres", "-c", "log_statement=all"] | ||
|
||
volumes: | ||
vdb_db_eth_server: |
Oops, something went wrong.