Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BM-102: Single BTC node in docker producing blocks #95

Merged
merged 11 commits into from
Aug 17, 2022
Merged

Conversation

aakoshh
Copy link
Contributor

@aakoshh aakoshh commented Aug 17, 2022

Created a new contrib/images/bitcoinsim docker setup, installing btcd, btcwallet and btcctl into a single container. When run, it creates a wallet with some default password, generates a mining address, and creates enough blocks for the miner to start having some balance. Then it produces blocks at a regular interval governed by the GENERATE_INTERVAL_SECS env var.

The btcsuite/btcd/rpcclient package can be used to connect to the wallet running in the container to do stuff like transfers from the miner to test accounts. The client can also invoke the generate endpoint at any point to create blocks outside the schedule. The schedule should be useful for demos, but too long for integration tests.

Later we can add different options to the wrapper script, as needed.

It has also been added to the main docker-compose.yml file, so it should come up in the local testnet. It takes some time to initialise, but those early sleeps can possibly be reduced.

Caveats

Initially I wanted to build the first 100 blocks during image building, and then only start the services, but for some reason that didn't work. The wallet could not sync after a restart, and it looked like btcd also forgot it ever created any blocks. That's why currently it does everything from scratch every time. Note that the script is too dumb to not try to create a wallet after a restart, so currently the container (not the image) has to be removed and recreated if a fresh state is needed, stop+start doesn't work.

@aakoshh
Copy link
Contributor Author

aakoshh commented Aug 17, 2022

Circle CI can't start the localnet. It seems like it actually starts the bitcoind container, and fails at the last babylond with Address already in use., but doesn't say which one.

I can't build the network locally:

$ make localnet-start
docker-compose down
Removing network babylon_localnet
WARNING: Network babylon_localnet not found.
make -C contrib/images babylond-env
make[1]: Entering directory '/home/aakoshh/projects/babylon/babylon/contrib/images'
docker rmi babylonchain/babylond 2>/dev/null; true
docker build --tag babylonchain/babylond -f babylond-env/Dockerfile \
    		/home/aakoshh/projects/babylon/babylon
Sending build context to Docker daemon  34.23MB
Step 1/17 : FROM golang:1.18-alpine AS build
 ---> bacc2f10e6e1
Step 2/17 : RUN apk add build-base git linux-headers
 ---> Using cache
 ---> 1394ee78b655
Step 3/17 : WORKDIR /work
 ---> Using cache
 ---> e75d7f1af1ff
Step 4/17 : COPY go.mod go.sum /work/
 ---> Using cache
 ---> f0b9eeba7a77
Step 5/17 : RUN go mod download
 ---> Using cache
 ---> d82def49b967
Step 6/17 : COPY ./ /work
 ---> d31d3382271a
Step 7/17 : RUN LEDGER_ENABLED=false make clean build
 ---> Running in 1208162b1ef9
make: /bin/sh: Operation not permitted
make: /bin/sh: Operation not permitted
make: git: Operation not permitted
make: which: Operation not permitted
make: /bin/sh: Operation not permitted
rm -rf \
    /work/build/ \
    artifacts/ \
    tmp-swagger-gen/
make: rm: Operation not permitted
make: *** [Makefile:125: clean] Error 127
The command '/bin/sh -c LEDGER_ENABLED=false make clean build' returned a non-zero code: 2
make[1]: *** [Makefile:4: babylond-env] Error 2
make[1]: Leaving directory '/home/aakoshh/projects/babylon/babylon/contrib/images'
make: *** [Makefile:431: localnet-build-env] Error 2

@aakoshh
Copy link
Contributor Author

aakoshh commented Aug 17, 2022

Regarding the previous error: I had to upgrade my docker version.

@aakoshh
Copy link
Contributor Author

aakoshh commented Aug 17, 2022

So now I have:

$ make localnet-start     
docker-compose down
Removing network babylon_localnet
...
+ /babylond/babylond --home /data/node0/babylond testnet init-files --v 4 -o /data --starting-ip-address 192.168.10.2 '--keyring-backend=test'
Successfully initialized 4 node directories
docker-compose up -d
Creating network "babylon_localnet" with driver "bridge"
Creating babylondnode3 ... 
Creating babylondnode0 ... error
Creating babylondnode3 ... done
Creating babylondnode1 ... 
Creating babylondnode2 ... done
Creating babylondnode1 ... done
Creating bitcoind      ... done

ERROR: for babylondnode0  Cannot start service babylondnode0: Address already in use
ERROR: Encountered errors while bringing up the project.
make: *** [Makefile:438: localnet-build-nodes] Error 1

@aakoshh
Copy link
Contributor Author

aakoshh commented Aug 17, 2022

Hopefully the IP address will fix it.

I noticed that it's not possible to run make localnet-stop then make localnet-start again because the files created by the containers in the .testnet directory can't be overwritten by the new start. Looks like we need to control the user ID, perhaps. I won't try to fix that in this PR.

Copy link
Member

@SebastianElvis SebastianElvis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work! You must have done much research in btcd. Automating everything in wrapper.sh is surely non-trivial to debug and implement. Most of my comments are minor and are about efficiency or naming, thus no blockers.

contrib/images/Makefile Outdated Show resolved Hide resolved
ENV RPCUSER=rpcuser
ENV RPCPASS=rpcpass
ENV PASSPHRASE=pass
ENV GENERATE_INTERVAL_SECS=30
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ENV GENERATE_INTERVAL_SECS=30
ARG GENERATE_INTERVAL_SECS=30

Not sure if making this an argument helps, since it will allow one to give it a different value in CLI.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't want to make these build arguments because it's not used during the build, but it's nice that it's present in the container and all the defaults are visible here, so even if we use docker exec to connect to a running container, the $RPCUSER is available. This one is just here so the default is visible, it's not useful with docker exec.

The way to override is is just to pass in e.g. -e GENERATE_INTERVAL_SECS=600 when the container is started.

Comment on lines 20 to 35
echo "Starting btcwallet..."
btcwallet --simnet -u $RPCUSER -P $RPCPASS --rpclisten=0.0.0.0:18554 2>&1 &
BTCWALLET_PID=$!

# Allow some time for the wallet to start
sleep 5

echo "Creating miner address..."
MINING_ADDR=$(btcctl --simnet --wallet -u $RPCUSER -P $RPCPASS getnewaddress)
echo $MINING_ADDR > mining.addr

echo "Restarting btcd with mining address $MINING_ADDR..."
kill -9 $BTCD_PID
sleep 1
btcd --simnet -u $RPCUSER -P $RPCPASS --rpclisten=0.0.0.0:18556 --listen=0.0.0.0:18555 --miningaddr=$MINING_ADDR 2>&1 &
BTCD_PID=$!
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice trick! I always did this in CLI interactively.

Copy link
Contributor Author

@aakoshh aakoshh Aug 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could have done it with 3 containers in docker-compose as well: btcd, btcwallet and the time loop. Just wanted something simple and self-contained for demos and tests.

Although I'm not sure how I could have managed restarts with different containers 🤔

context: ./
dockerfile: ./contrib/images/bitcoind/Dockerfile
image: babylonchain/bitcoind:latest
container_name: bitcoind
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this line necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without this the container name becomes babylon_bitcoind_1 which is not as intuitive if you want to connect to it from the other containers. All the others specify the container name, so I thought why not be consistent, and it also makes it easier to use docker exec if one wants to poke around in it.

Comment on lines 9 to 13
RUN git clone https://github.com/btcsuite/btcd.git
RUN cd btcd && go install -v . ./cmd/... && cd -

RUN git clone https://github.com/btcsuite/btcwallet.git
RUN cd btcwallet && go install -v . ./cmd/... && cd -
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible or beneficial to use their released binaries directly rather than building from scratch? since we won't modify their code anyway. It will reduce the image size and make building images faster as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just wanted to get it done quickly, and this was how the READMEs instructions went. The final image size is not affected, although you are right that the builder probably sticks around. It would be better to just grab the binaries but I really don't have more time to spend on it now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I'm not entirely clear about for example is Alpine supports multi-arch as we discussed, yet I would have to pick one specific binary release to download. Which one is the default? Don't really want to cross build something as simple as this container.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree. I guess in the short term we will not mess up with the multiarch stuff. We won't deploy Babylon in RPi at the moment anyway.

Which one is the default?

IIRC it follows the arch of the laptop, which is usually amd64.

contrib/images/bitcoind/Dockerfile Outdated Show resolved Hide resolved
@aakoshh aakoshh merged commit 5b77d2f into main Aug 17, 2022
@aakoshh aakoshh deleted the bm-102-btc-docker branch August 17, 2022 13:18
vitsalis pushed a commit that referenced this pull request Jan 21, 2024
* proto def

* proto def

* genesis setup

* fix

* more comments

* comprehensive comments

* improve checks

* fix checks

* change slashing_percentage data type to cosmos.Dec

* fix slashing_percentage usages to cosmos.Dec

* fix validation check for default params

* fix checks and tests

* change default percentage to 10

* fix template

* change slashing percentage to slashing rate in proto

* replace usages with slashingRate

* fix comments and checks

* fix error message
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants