Backyard

Login Signup

Posts:

Hello Gno

By sborrazas on 2024-06-22

2024-06-22: This post is a draft and there is incorrect information.

Yesterday at Gophercon EU I learned about the Gno project. This blog post offers a quick dive into the project without going too deep.

I’m going to write my take on the project and how to build a very basic app (a counter). I will write everything with my own words in the hope that it will help to grasp the concepts better. You can just go to https://gno.land/ to get the precise and correct information.

Gno is many things:

  • A project written in Go
  • A language that looks exactly like Go, called Gno (they made they own Go flavor)
  • A VM that runs Gno code
  • A web server that serves the result of the Render() function in those Gno files
  • A network of nodes with CPUs where the VM executes the code (the results will be propagated)
  • A blockchain where the code and data lives (storage)
  • A cryptocurrency (the stuff exchanged to push code and data into the blockchain)
  • A wallet to hold and exchange your cryptocurrency

All these things have different names, but those are the main concepts. This platform/ecosystem is a new paradigm because by storing your code and data in a decentralized way you don’t need to deal with a database or infra anymore (but you will have to start thinking about gas fees, and your users need a wallet to call endpoints).

Enough introduction! Just follow the steps below to get a familiar with the concepts. At the end of the post I will share more details.

Building and deploying a counter app from scratch

To deploy and interact with the app in your local development environment:

  1. Write down the app code
  2. Create a wallet (in gno they call it key). You need a wallet with some balance to deploy and perform actions, so let’s first create the wallet.
  3. Start development server and add some funds to the wallet
  4. Deploy app
  5. Increment and Decrement the counter

Step 1: Write the app

The app it’s a few lines of code:

# For this guide we assume the app source is at ~/go/src/gno-tutorial
# feel free to put the code somewhere else.
# mkdir -p ~/go/src/github.com/gno-tutorial/r/counter/
# cd ~/go/src/github.com/gno-tutorial/r/counter/
# touch counter.gno
# vim counter.gno

package counter

import (
    "gno.land/p/demo/ufmt"
)

var count int

func Increment() {
    count++
}

func Decrement() {
    count--
}

func Render(_ string) string {
    return ufmt.Sprintf("Count: %d", count)
}

Step 2: Create wallet to pay for deployment

In Gno wallets are called “keys”. My preference is the concept of a wallet, so you will see the term key/wallet interchangeably.

Clone repo with Gno tools

# For this guide I assume the code is at ~/go/src/github.com/gnolang
# feel free to put the code somewhere else.
# mkdir -p ~/go/src/github.com/gnolang
# cd ~/go/src/github.com/gnolang
git clone https://github.com/gnolang/gno.git

Run executable to create a key which we will use for testing

cd ~/go/src/github.com/gnolang/gno/gno.land
go run ./cmd/gnokey add MyKey

# Just press enter twice times to create the key
# with no password.
# We will use this key for testing
# Run the same command again to override this key
# Enter a passphrase to encrypt your key to disk:
# <just press enter>
# Repeat the passphrase:
# <just press enter>

# * MyKey (local) - addr: g1hndc2m7qfzj2dyn2ddcxced9w3rv0vvrpfzlcj pub: 
# gpub1pgfj7ard9eg82cjtv4u4xetrwqer2dntxyfzxz3pqv0sse4stv9rmu2f6nkrz2vcml
# 8m0acldwxmpf0anwlyrnxsegnwwgclw4v, path: <nil>

# **IMPORTANT** write this mnemonic phrase in a safe place.
# It is the only way to recover your account if you ever forget your password.
# acoustic digital enact hedgehog recycle village face ketchup ceiling bind menu
# output slight tragic stove helmet furnace fun adjust train couch
# insane defense topple

Step 3: Start development server and add some funds to the wallet

Run dev server binary, and add 1000000000000000ugnot to the key we just created

cd ~/go/src/github.com/gnolang/gno/contribs/gnodev
go run ./cmd/gnodev --add-account MyKey=1000000000000000ugnot

Go to http://localhost:8888 and you should see a nice website that says Welcome to Gno.land, among other things.

Step 4: Deploy to the dev server we just started

Use the gnokey tool to deploy the app using funds from our wallet MyKey

cd ~/go/src/github.com/gnolang/gno/gno.land
go run ./cmd/gnokey maketx addpkg \
                  --pkgpath "gno.land/r/demo/counter" \
                  --pkgdir ~/go/src/github.com/gno-tutorial/r/counter \
                  --gas-fee    1000000ugnot \
                  --gas-wanted 2000000 \
                  --broadcast \
                  --chainid dev \
                  --remote localhost:26657 \
                  MyKey
# Enter password.
# <just press enter>
# OK!
# GAS WANTED: 2000000
# GAS USED:   1464550
# HEIGHT:     132
# EVENTS:     []

Go to http://localhost:8888/r/demo/counter and check out your app! You should see Count: 0 Well done!

Step 5: Increment the counter We will use gnokey again to call Increment function using the funds in MyKey. As you can guess, this is because performing this action will drain more funds from the wallet.

cd ~/go/src/github.com/gnolang/gno/gno.land
go run ./cmd/gnokey maketx call \
                  -pkgpath "gno.land/r/demo/counter" \
                  -func "Increment" \
                  -gas-fee 1000000ugnot \
                  -gas-wanted 2000000 \
                  -send "" \
                  -broadcast \
                  -chainid "dev" \
                  -remote "tcp://127.0.0.1:26657" \
                  MyKey
# Enter password.
# <just press enter>
# OK!
# GAS WANTED: 2000000
# GAS USED:   98103
# HEIGHT:     1936
# EVENTS:     []

Visit http://localhost:8888/r/demo/counter and now you will see Count: 1 🎉

Now let’s do the same but calling Decrement instead:

cd ~/go/src/github.com/gnolang/gno/gno.land
go run ./cmd/gnokey maketx call \
                  -pkgpath "gno.land/r/demo/counter" \
                  -func "Increment" \
                  -gas-fee 1000000ugnot \
                  -gas-wanted 2000000 \
                  -send "" \
                  -broadcast \
                  -chainid "dev" \
                  -remote "tcp://127.0.0.1:26657" \
                  MyKey
# Enter password.
# <just press enter>
# OK!
# GAS WANTED: 2000000
# GAS USED:   98109
# HEIGHT:     3408
# EVENTS:     []

Visit http://localhost:8888/r/demo/counter and now you will see Count: 0 🎉

You wrote, deployed, and interacted with your first Gno app in your computer. Congratulations!

To bring this app to production, and to make it more user friendly, you would deploy your code in https://gno.land and ask your users to use the Adena wallet

There many gotchas related to the Gno project:

  1. You have global variables, and when you change the value of the global variable, the value will be propagated in the network
    1. This is thanks to abstractions provided by the VM
    2. This has many implications, suddenly you don’t need a database anymore!
    3. This is running in a blockchain so there is a consensus mechanism
  2. To deploy code you have to use funds from the wallet in this blockchain.
  3. To perform actions (such as submit a comment to a blog post) your users will need a wallet and a spend some funds. Not as straightforward as calling an endpoint in the web2, but the trade-off has other benefits (spam is expensive, you don’t need accounts because you have wallet keys, decentralization, resilience, etc.)
  4. The more data you send to the block chain, the more funds you use. Sending 100kb of data it’s going to be expensive, so forget about sending images. This is the same problem of storing images in the Bitcoin blockchain. Just store a URL instead or use something like IPFS which is intended to deal with large amounts of data in a decentralized context.
  5. These are the early days of the project so many things might change, and the documentation is being worked on.
  6. They’re looking forward to contributors. They have a “good first issue” label in the bug tracker.

Setup Java JDK in macOS

By sborrazas on 2024-06-12

Updated version:

I use mise now. So I just have to do brew install mise && mise install java@23 to get java 23.

Old post:

I use fish shell and VSCodium (a fork of VS Code without telemetry).

  1. Install Homebrew https://brew.sh/
  2. Install fish with brew install fish
  3. This guide is for fish shell, so be sure to continue in fish shell by running fish. Optionally, you can set fish as your default shell on macOS
  4. Install openjdk with brew install openjdk
  5. After installing openjdk, I get the following caveat text from Homebrew (which you can read again by running brew info openjdk):
For the system Java wrappers to find this JDK, symlink it with
sudo ln -sfn /opt/homebrew/opt/openjdk/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk.jdk

openjdk is keg-only, which means it was not symlinked into /opt/homebrew,
because macOS provides similar software and installing this software in
parallel can cause all kinds of trouble.

If you need to have openjdk first in your PATH, run:
fish_add_path /opt/homebrew/opt/openjdk/bin

For compilers to find openjdk you may need to set:
set -gx CPPFLAGS "-I/opt/homebrew/opt/openjdk/include"
  1. Run fish_add_path /opt/homebrew/opt/openjdk/bin to be able to run javac
  2. Run /usr/libexec/java_home -V to get the JAVA_HOME of the installed jdks. Mine returns:
Matching Java Virtual Machines (1):
    21.0.2 (arm64) "Homebrew" - "OpenJDK 21.0.2" /opt/homebrew/Cellar/openjdk/21.0.2/libexec/openjdk.jdk/Contents/Home
/opt/homebrew/Cellar/openjdk/21.0.2/libexec/openjdk.jdk/Contents/Home
  1. To set JAVA_HOME environment variable, run set -Ux JAVA_HOME /opt/homebrew/opt/openjdk/libexec/openjdk.jdk/Contents/Home. You can check this is a symlink to the installed jdk with ls -lart /opt/homebrew/opt/openjdk
  2. Create a file called Hello.java with the following content:
public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}
  1. Run javac Hello.java which will create a file called Hellow.class. Then you can run java Hello to run your new class (beware this command takes the class name, not the filename). The output of the command is Hello, World!
  2. Now that you have the java development kit up and running in your computer, it’s time to get some IDE support to get auto-completion, auto-import, etc. You can choose between Eclipse, IntelliJ, VS Code, etc. In my personal computer I use VSCodium. Install VSCodium with brew install vscodium (or visual-studio-code if you prefer)
  3. You can open VSCodium from the terminal with codium .. Search for extensions in VSCodium and install Extension Pack for Java which installs several convenient extensions for working with Java. I started with Language Support for Java™ by Red Hat but it misses some functionality, so my recommendation is to go for the extension pack
  4. Congratulations! You got your Java development environment ready. You might want to install maven with brew install maven

Set Fish shell as default shell in macOS

By sborrazas on 2024-06-12

How to set fish shell as default shell in macOS.

  1. Install fish with brew install fish
  2. Test the installation by running fish
  3. Add the path fish to /etc/shells. First, get the path with which fish. In my case the path is /opt/homebrew/bin/fish. You can append the path with the command sudo sh -c 'echo /opt/homebrew/bin/fish >> /etc/shells'
  4. Set the shell with chsh -s /opt/homebrew/bin/fish
  5. Log out of your current shell

Alternative to Pi-hole in NixOS

By sborrazas on 2024-06-12

Now that my son has some internet access, I decided to make internet a bit safer at home.

I try to use NixOS in most of my devices. I have an old computer serving borrazas.org. I have another old computer serving as a “media center” where we watch the News for kids in Dutch. NixOS allows me to have all system configuration in one file: /etc/nixos/configuration.nix. If for some reason I have to reinstall the computer, I only have to backup that one file.

I have seen Pi-Hole recommended in Hacker News a couple times, and I checked myself and it looked like the right tool to make internet a bit more child-friendly.

My goal:

  • Block ads, trackers, malware, adult, and gambling sites on my wifi
  • Use DNS over HTTPS base.dns.mullvad.net
  • If a website is broken because of DNS blocks, have a web UI to easily check logs and tweak the DNS configuration

I searched for instructions how to install Pi-Hole in NixOS, but seems that nobody has packaged it yet 12. One of the comments in the thread requesting Pi-Hole for NixOS mentioned that AdGuard Home and blocky are packaged for NixOS.

I prefer to avoid for-profit companies for blocking stuff because there are several bad examples such as Adblock Plus, and free VPN companies with fishy terms of service.

Anyway, I checked the AdGuard Home Github repo looks like a nice project in Go, with a GNUv3 license. It looks trustworthy enough for me.

Changes in /etc/nixos/configuration.nix:

(1). Add adguardhome to the list of packages

packages = with pkgs; [
    neovim  
    wget
    curl  
    # ...
    go
    tmux
    adguardhome
    ];
};

(2). Open up Firewall ports

  # Open ports in the firewall.
  networking.firewall.allowedTCPPorts = [ 3000 80 ];
  networking.firewall.allowedUDPPorts = [ 53 ];

(3). Enable the service (I had to search for available options on NixOS Option Search). I used the following

  # Adguard home
  services.adguardhome = {
    enable = true;
    openFirewall = true;
    settings = {
      bind_port = 3000;
    };
  };

I tried to add a password but currently it’s not possible with the current options.

Assuming the IP of your machine is 192.168.1.123, go to http://192.168.1.123:3000/ and you should see the AdGuard Home Dashboard.

In Settings, DNS Settings I added “https://base.dns.mullvad.net/dns-query” which blocks ads, malware and phishing. Here is a list of more DNS options. I personally trust Mullvad. I wanted something like all.dns.mullvad.net, so I looked up Mullvad block lists in https://github.com/mullvad/dns-blocklists and added the lists in Filters, DNS blocklists.

I had to follow Pi-Hole guide to setup my Fritzbox internet router. The trick was to use the same IP in preferred and alternative, and to disable “Fallback to public DNS servers when DNS disrupted”.

https://docs.Pi-Hole.net/routers/fritzbox/#optional-increasing-the-priority-of-dns-requests

I have been using it for around a week and it works fine.