AVA announced the Denali Testnet Challenge Required 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.
- 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
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.
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
.
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
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.
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
.
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.
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
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
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.
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}
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
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
.
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
}
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
Now you should get yourself some AVA from faucet. Use your X-address.
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
}
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
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
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.
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
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
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
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
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
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
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
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
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.
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
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
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
.
...
SyslogIdentifier=gecko.service
ExecStart=/opt/gecko/go/src/github.com/ava-labs/gecko/build/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 should be all set!
You can find me and some other people running a node on a RasPi in the AVA Discord channels.