Run gecko on a RaspberryPi and make it an AVA node and validator

otherPaco
10 min readJun 26, 2020

--

Raspberry Pi 4B in action

AVA announced the Denali Testnet Challenge Hardware requirements were:

  • 2 GHz or faster CPU, 3 GB RAM, 250 MB hard disk.
  • OS: Ubuntu >= 18.04 (works with Windows WSL) or macOS >= Catalina.

So I thought let’s use a RasPi for that. It is a little short GHz wise with only 1.5 but we will see.

So here is my buylist.

BUYLIST

  • Rapsberry Pi 4B 8GB RAM (2 and 4GB RAM should work, too)
  • Micro SD card 128GB SanDisk Ultra (64GB should be enough for now)
  • official Power Supply USB-C DC 5.1V 3A
  • network cable
  • Armor Case passive cooling
  • someday I might need an external SSD but not yet

INSTALL UBUNTU 20.04

First we need to install a 64bit system. Raspian is a 32bit system so we can not use it. Best choice is Ubuntu.
Download Ubuntu 20.04 LTS 64-bit for RasPi4
If you don’t know how to get the image on the SD-card follow the tutorial.

SET UP SSH

Because we don’t want to plug in a keyboard and screen all the time we will use ssh to connect to the RasPi. Therefore we have do create a file called ssh in the boot partion. Following this tutorial.

Now we can connect us to the Raspi from any computer in the same network with ssh ubuntu@ubuntu. The initial password is ubuntu.
Securing your RasPi, e.g. using keys for ssh or unattended-upgrades, is recommended but not part of this tutorial. You should update your RasPi with sudo apt update followed by sudo apt full-upgrade.

ADD SOME EXTRA GB MEMORY AKA SWAP

Especially when you use a RasPi with less than 3GB RAM you should give the system some swap, that is a kind of extra RAM on your SD-card. With the 8GB RasPi you can skip this part.

I used this tutorial to add 8GB. Normaly you should make it x1 to x2 the size of your RAM.

sudo fallocate -l 8G /swapfile #8G is the size here 8GB
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
sudo cp /etc/fstab /etc/fstab.bak #just in case a backup
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

BYOBU

sudo apt install byobu #should already be installed

byobu is the perfect shell if you want to use stuff like nohub, screen or tmux but the easy-way. It is the perfect shell when you connected via ssh, as it runs in the background even when your connection breaks down.

From here on I ALWAYS work in byobu on my RasPi. When I get disconnected the process keeps on running and when I come back and type byobu I am where I left, only exception is when the RasPi was rebooted in the meantime.

After you connect to your RasPi just type byobu. Here are some tips how to use it.

CREATE AN USER FOR GECKO

sudo adduser --gecos --disabled-password --home /opt/gecko gecko

Whenever we need this user we get it with sudo su gecko. The user itself has no password and can not login. So we login as ubuntu and switch to gecko when needed.

The $HOME folder for this user is /opt/gecko.

For the following steps I will use the user gecko with sudo su gecko.

INSTALL AVA/gecko

I used this tutorial.

First we install the language go with sudo apt install golang.

Check the version with go version we need go1.13.x or higher.

We continue with some stuff taken from ava-labs github.

$GOPATH

The GOPATH should already be set ( golang github) but somehow it is not.
We still use the gecko user.
Try echo $GOPATH if you see a blank line use the following commands to set the GOPATH.

  • cd ~
  • mkdir go
  • nano .bashrc
  • add export GOPATH=$HOME/go and an empty line to the end of the file
  • save the file and close nano
  • source .bashrc
  • echo $GOPATH should return /opt/gecko/go

GECKO

Still user gecko still using byobu.

Let’s build gecko from source.

sudo apt-get install libssl-dev libuv1-dev cmake make curl g++
go get -v -d github.com/ava-labs/gecko/...
cd $GOPATH/src/github.com/ava-labs/gecko
./scripts/build.sh

JOIN THE NETWORK

I follow mostly this article.

cd $GOPATH/src/github.com/ava-labs/gecko/build
./ava

While gecko is running, keep it running and open another window F2 in byobu ( F3 and F4 to switch windows, exit to close, F6 to detach byobu you can come back anytime just type byobu)

In the new window we make an API call to create an user.

CREATE AN USER

curl -X POST --data '{
"jsonrpc": "2.0",
"id": 1,
"method": "keystore.createUser",
"params": {
"username": "YOUR USERNAME",
"password": "YOUR PASSWORD"
}
}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/keystore

You will get a response like this:

response {"jsonrpc":"2.0","result":{"success":true},"id":1}

Documentation

NOW WE WAIT AND GET FRUSTRATED — DON’T … GET FRUSTRATED BUT BE PATIENT

Your node is bootstrapping and this may take a little while up to a few hours with bad luck. But this will only take so long on your very first start or when the node has been offline a long time.

What you will see after you entered ./ava
Some ASCII-Art and then:

WARN [06-05|19:20:35] /main/main.go#44: NAT traversal has failed. If this node becomes a staker, it may lose its reward due to being unreachable. 
...
INFO [06-05|19:20:35] /api/server.go#105: adding route /ext/admin INFO [06-05|19:20:35] /node/node.go#475: initializing Health API INFO [06-05|19:20:35] /api/server.go#105: adding route /ext/health INFO [06-05|19:20:35] /chains/manager.go#187: creating chain:
INFO [06-05|19:20:35] <chain 11111111111111111111111111111111LpoYY> /vms/platformvm/vm.go#695: next scheduled event is at 2020-10-31 00:00:00 +0000 UTC (3532h39m24.274439418s in the future)

Ignore the warning for the time beeing FAQ

INFO [06-05|20:28:56] <chain abcdefghfwrfgiogjtgojionevinviogoeghgeggebbbebehg> /snow/engine/snowman/transitive.go#47: Initializing Snowman consensus
...
INFO [06-05|20:28:56] <chain Hkfgk76fghvertfsQgmfhstTvneduifsdf5hGtuAsCYugdFgg> /snow/engine/avalanche/transitive.go#43: Initializing Avalanche consensus
...
INFO [06-05|20:28:56] <chain fgggfgdfgse5u46dfhtjxdHKTODIRsgegdgdfgt5fGERGCHrhg> /snow/engine/snowman/transitive.go#47: Initializing Snowman consensus
...
INFO [06-05|20:28:56] <chain amrghfgxct/ikgdrgujpgks5rsdgx325vdgdgKwfhgd5KHAhtM> /snow/engine/snowman/transitive.go#47: Initializing Snowman consensus

Some consensus mechanics were initialized — good

the something about bootstrapping

INFO [06-05|20:29:00] <chain 1GHaaPbg1YBR4qiATuFNfL2j9StJwmddwXiwm1s9ts5KXvMai> /snow/engine/avalanche/transitive.go#70: Bootstrapping finished with 0 vertices in the accepted frontier 
...
INFO [06-05|20:29:00] <chain zJytnh96Pc8rM337bBrtMvJDbEdDNjcXG3WkTNCiLp18ergm9> /snow/engine/snowman/transitive.go#99: Bootstrapping finished with BhdXsMYpJsjGdgk1wqUWcukurCovwv9hpKMuLv7bJ9jVeSZJj as the last accepted block

sometimes 0, sometimes more vertices — all good

How do you know your node finished bootsptrapping? FAQ

MONITOR STUFF

We can monitor stuff.

Open new windows in byobu F2, you can have a lot of them:

  • Temperature
    watch cat /sys/class/thermal/thermal_zone0/temp or in the byobu status bar (config it withF9)
  • DB folder
    watch ls -al ~/.gecko/db/denali/v0.5.0/
  • size of DB folder
    watch du -hs ~/.gecko/db/denali/v0.5.0/
  • ava process
    ps -aux | grep ava orps aux | sed -e '1b' -e '/ava/!d'
  • Memory
    watch free -h

In the ~/.gecko folder lives a lot of "personal" gecko stuff.

The watch command repeats the following command every 2 seconds, you can exit with Strg + c.

CREATE AN ADDRESS ON THE X-CHAIN

curl -X POST --data '{
"jsonrpc":"2.0",
"id" :2,
"method" :"avm.createAddress",
"params" :{
"username": "YOUR USERNAME",
"password": "YOUR PASSWORD"
}
}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/bc/X

Response is something like this:

{
"jsonrpc": "2.0",
"result": {
"address": "YOUR X-CHAIN ADDRESS"
},
"id": 1
}

Documentation

Write down your address.

But you can request it with:

curl -X POST --data '{
"jsonrpc": "2.0",
"method": "avm.listAddresses",
"params": {
"username":"myUsername",
"password":"myPassword"
},
"id": 1
}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/bc/X

Documentation

Now you should get yourself some AVA from faucet. Use your X-address.

CREATE AN ADDRESS ON THE P-CHAIN

curl -X POST --data '{
"jsonrpc": "2.0",
"method": "platform.createAccount",
"params": {
"username": "YOUR USERNAME",
"password": "YOUR PASSWORD"
},
"id": 1
}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/P

If you get a 404 your node is probably still bootstrapping FAQ

Response:

{
"jsonrpc": "2.0",
"result": {
"address": "YOUR P-CHAIN ADDRESS"
},
"id": 1
}

Documentation

Write it down.

But you can request it with:

curl -X POST --data '{
"jsonrpc":"2.0",
"id" :1,
"method" :"platform.listAccounts",
"params" :{
"username": "YOUR USERNAME",
"password": "YOUR PASSWORD"
}
}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/P

Documentation

SEND AVA TO THE PLATFORM P-CHAIN

Still using this article “how-to-join-avas-denali-test-network”

curl -X POST --data '{
"jsonrpc":"2.0",
"id" :1,
"method" :"avm.exportAVA",
"params" :{
"username": "YOUR USERNAME",
"password": "YOUR PASSWORD",
"to":"YOUR PLATFORM ADDRESS HERE",
"amount": 10000
}
}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/bc/X

Documentation

Write that txID down, too. The first time noting happened and when I checked the TxStatus it was “Unknown”.
I checked my balance and it was still 20.000.

I sent it a second time. It staid the same txID, this time after one second the status was “Processing”. After a few hours it was “Accepted”. Should be much faster now.

ACCEPT THE TRANSFER ON P-CHAIN

curl -X POST --data '{
"jsonrpc": "2.0",
"method": "platform.importAVA",
"params": {
"username": "YOUR USERNAME",
"password": "YOUR PASSWORD",
"to":"YOUR PLATFORM ADDRESS HERE",
"payerNonce":1
},
"id": 1
}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/bc/P

Documentation

Take a note of the returned tx value, a long string.

Whenever you send a request that has the field payerNonce it must be one up of your recent nonce for the account (P-Address).
How to check your nonce (platformgetaccount) or
How to check your nonce (platformlistaccounts)

Take the resulting transaction from importAVA and issue it to the P-Chain with API call issueTx.

curl -X POST --data '{
"jsonrpc": "2.0",
"method": "platform.issueTx",
"params": {
"tx":"THE ISSUE TRANSFER TX HERE"
},
"id": 1
}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/bc/P

Documentation

Took nearly a day but the funds arrived on the P-Chain. This should be faster, too now.
Check your AVA balance in the P-Chain account.

curl -X POST --data '{
"jsonrpc":"2.0",
"id" :1,
"method" :"platform.listAccounts",
"params" :{
"username": "YOUR USERNAME",
"password": "YOUR PASSWORD"
}
}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/P

Documentation

BECOME A VALIDATOR

You need your nodeID

curl -X POST --data '{
"jsonrpc":"2.0",
"id" :1,
"method" :"info.getNodeID"
}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/info

Documentation

Now add your nodeID to the network:

curl -X POST --data '{
"jsonrpc": "2.0",
"method": "platform.addDefaultSubnetValidator",
"params": {
"id":"YOUR NODEID HERE",
"payerNonce":2,
"destination":"YOUR PLATFORM ADDRESS HERE",
"startTime":'$(date --date="15 minutes" +%s)',
"endTime":'$(date --date="15 days" +%s)',
"stakeAmount":10000,
"delegationFeeRate":0
},
"id": 1
}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/P

Platform address is your P-address to where the money returns after staking.
Time is in Unix timestamp or in other words seconds sice Jan 1st 1970.
Here is a converter.
You can use a Timestamp for the startTime and endtime directly.
Now it will calculate start time 15 minutes in the future and end time 15 days in the future. Maximum staking duration is one year minimum one day, minimum will change to 14 days.
Because we start 15 minutes in the future we will validate for 14 days 23 hours and 45 minutes.

You’ll get an unsigned transaction as response like this:

{
"jsonrpc":"2.0",
"id" :1,
"result" :{
"unsignedTx": "1115K3sV5Yxr175wi6kEYpN1nPz3GEBkzG8mpF2s2959VsR54YGenLJrgdg3UEE7vFPNDE5n3Cq9Vs71HEjUUoVSyrt9Z3X9M9sKLCH5WScTcTocxj1XfFowZxFe4uH8iJU7jnCAgeKK5bAsfnWy2b9PbCQMN2uNLvwyKRp4ZxcgRptkuXRMCKHfhbHVKBYmr5e2VbABht19be57uFUP5yVdMxKnxecs"
}
}

We have to sign it:

curl -X POST --data '{
"jsonrpc": "2.0",
"method": "platform.sign",
"params": {
"username": "YOUR USERNAME HERE",
"password": "YOUR PASSWORD HERE",
"tx":"THE VALIDATION UNSIGNED TX HERE",
"signer":"YOUR PLATFORM ADDRESS HERE"
},
"id": 2
}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/P

Documentation

Response looks like this:

{
"jsonrpc": "2.0",
"result": {
"Tx": "111Bit7JNASbJyTLrd2kWkYRoc96swEWoWdmEhuGAFK3rCAyTnTzomuFwgx1SCUdUE71KbtXPnqj93KGr3CeftpPN37kVyqBaAQ5xaDjr7wVABCCi9iV7kYJnHF61yovViJF69mJJy7WWQKeRMDRTiDuii5gsd11gtNahCCsKbm9seJtk2h1wAPZn9M1eL84CGVPnLUiLP"
},
"id": 1
}

Last step is to issue it to the P-Chain:

curl -X POST --data '{
"jsonrpc": "2.0",
"method": "platform.issueTx",
"params": {
"tx":"YOUR VALIDATION SIGNED TX HERE"
},
"id": 3
}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/P

Documentation

When you call this:

curl -X POST --data '{
"jsonrpc": "2.0",
"method": "platform.getPendingValidators",
"params": {},
"id": 4
}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/P

Documentation

You should find your nodeID and P-address in the list of pending validators.

Or a little later this call:

curl -X POST --data '{
"jsonrpc": "2.0",
"method": "platform.getCurrentValidators",
"params": {},
"id": 1
}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/P

Documentation

Gives you the list of current validators. That is the list you want to be in.

You can check the network explorer there is a validator searchbar.

If the last steps are not working stop ./ava, restart it and repeat from platform.addDefaultSubnetValidator or maybe from the platform.issueTx that you did before that call.

Good luck have fun.

SYSTEMD

How to start gecko on every startup and keep it alive in the background.

Inspired by this article.

Check the article above for info how to monitor your node. I changed the name of the service to gecko. So you have to replace "denali" with "gecko" when you use commands from the article above.

We change back to our regular user ubuntu. When you are user gecko just type exit and you should be ubuntu again.

sudo touch /etc/systemd/system/gecko.service

as sudo enter the following lines to the file with the editor of your choice, e.g. sudo nano /etc/systemd/system/gecko.service

[Unit]
Description=gecko AVA node
After=network-online.target
Requires=network-online.target
StartLimitIntervalSec=0
[Service]
Type=simple
Restart=always
RestartSec=1
User=gecko
SyslogIdentifier=gecko.service
WorkingDirectory=/opt/gecko/go/src/github.com/ava-labs/gecko/build
ExecStart=/opt/gecko/go/src/github.com/ava-labs/gecko/build/ava
[Install]
WantedBy=multi-user.target

Start service and enable it so it starts after reboot.

sudo systemctl daemon-reload
sudo systemctl start gecko.service
sudo systemctl enable gecko.service

BACKUP YOUR STUFF

backup your node

API CALLS FROM ANOTHER MACHINE

We made all our API calls from the machine gecko is running on. When you want to do it from another machine in your local network you have to make sure your RasPi is getting the same local IP everytime and start gecko with this IP .ava --http-host=123.my.ip.45.
Documentation

If you use this method or other arguments and options make sure to add them to ExecStart in the systemd gecko.service.

...
ExecStart=/full/path/to/ava --http-host=123.my.ip.45
[Install]
...

You should sudo systemctl daemon-reload and restart the gecko.service.

It should be possible to do it with your public IP and some port forwarding but I did not try that. I would prefer to connect to my local network via VPN and make the calls “locally”. You have to use the http-host IP in your API calls from other machines.

You should be all set!

You can find me and some other people running a node on a RasPi in the AVA Discord channels.

--

--