# https://taskfile.dev

version: '3'

dotenv:
  - '.env'

env:
  GOEXPERIMENT: arenas

vars:
  VERSION:
    sh: cat ../node/config/version.go | grep -A 1 "func GetVersion() \[\]byte {" | grep -Eo '0x[0-9a-fA-F]+' | xargs printf "%d.%d.%d"
  MAX_KEY_ID: 15
  QUILIBRIUM_SIGNERS_IMAGE_NAME: 'quilibrium-signers'
  USER_NAME:
    sh: whoami
  PARENT_FOLDER:
    sh: dirname $(pwd)
  SIGNING_KEYS_PEM_DIR: 'pems'

tasks:
  status:
    desc: Display configuration info.
    cmds:
      - echo -n "Version       :" && echo " {{.VERSION}}"
      - echo -n "Priv Key Path :" && echo " {{.SIGNING_KEY_PATH}}"
      - echo -n "Pub  Key Path :" && echo " {{.SIGNING_PUB_KEY_PATH}}"
      - echo -n "Key ID        :" && echo " {{.SIGNING_KEY_ID}}"
    silent: true

  hex:
    desc: Print the hex representation of your public key.
    cmds:
      - cat {{.SIGNING_PUB_KEY_PATH}} | openssl ec -inform pem -pubin -noout -text

  docker:build_image:
    desc: Build the Quilibrium Signers docker image, unless it is already built.
    aliases:
      - image
    preconditions:
      - sh: 'test -z "$QUILIBRIUM_DOCKER_CONTAINER"'
        msg: 'This command cannot be run inside the container'
    cmds:
      - |
        docker build \
        --build-arg USER_NAME={{.USER_NAME}} \
        --build-arg UID=$(id -u) \
        --build-arg GID=$(id -g) \
        -t {{.QUILIBRIUM_SIGNERS_IMAGE_NAME}}:latest \
        .
    status:
      - |
        docker image inspect \
        {{.QUILIBRIUM_SIGNERS_IMAGE_NAME}} \
        >/dev/null 2>/dev/null

  build:
    desc: Build the Quilibrium node binaries by starting a container and starting the build inside the container.
    preconditions:
      - sh: 'test -z "$QUILIBRIUM_DOCKER_CONTAINER"'
        msg: 'This command cannot be run inside the container'
    deps:
      - docker:build_image
    cmds:
      - docker run --name signers --rm -it -v {{.PARENT_FOLDER}}:/home/{{.USER_NAME}}/ceremonyclient -u {{.USER_NAME}} -w /home/{{.USER_NAME}}/ceremonyclient/signers {{.QUILIBRIUM_SIGNERS_IMAGE_NAME}} task build:container

  build:shell:
    desc: Start a shell in a build container.
    aliases:
      - shell
    preconditions:
      - sh: 'test -z "$QUILIBRIUM_DOCKER_CONTAINER"'
        msg: 'This command cannot be run inside the container'
    deps:
      - docker:build_image
    cmds:
      - docker run --name signers --rm -it -v {{.PARENT_FOLDER}}:/home/{{.USER_NAME}}/ceremonyclient -u {{.USER_NAME}} -w /home/{{.USER_NAME}}/ceremonyclient/signers {{.QUILIBRIUM_SIGNERS_IMAGE_NAME}} bash

  build:container:
    desc: Build the Quilibrium node binaries, inside the Docker container.
    dir: ../node
    sources:
      - '**/*.go'
    generates:
      - node-{{.VERSION}}-*.bin
    cmds:
      - GOOS=darwin go build -ldflags "-s -w" -o node-{{.VERSION}}-darwin-arm64.bin
      - GOOS=linux GOARCH=amd64 go build -ldflags "-s -w" -o node-{{.VERSION}}-linux-amd64.bin
      - GOOS=linux GOARCH=arm64 go build -ldflags "-s -w" -o node-{{.VERSION}}-linux-arm64.bin

  digest:
    desc: Generate digests for node binaries.
    deps: [build]
    dir: ../node
    sources:
      - node-{{.VERSION}}-*.bin
    generates:
      - node-{{.VERSION}}-*.dgst
    cmds:
      - openssl sha3-256 -out node-{{.VERSION}}-darwin-arm64.dgst node-{{.VERSION}}-darwin-arm64.bin   
      - openssl sha3-256 -out node-{{.VERSION}}-linux-amd64.dgst node-{{.VERSION}}-linux-amd64.bin
      - openssl sha3-256 -out node-{{.VERSION}}-linux-arm64.dgst node-{{.VERSION}}-linux-arm64.bin

  sign:
    desc: Generate signatures for node binaries.
    deps: [digest]
    dir: ../node
    preconditions:
      - sh: 'test -n "$SIGNING_KEY_PATH"'
        msg: 'The path to the signing key must be set in SIGNING_KEY_PATH'
      - sh: 'test -n "$SIGNING_KEY_ID"'
        msg: 'The signing key id must be set in SIGNING_KEY_ID'
    sources:
      - node-{{.VERSION}}-*.dgst
    generates:
      - node-{{.VERSION}}-*.dgst.sig.{{.SIGNING_KEY_ID}}
    cmds:
      - openssl pkeyutl -sign -inkey {{.SIGNING_KEY_PATH}} -rawin -in node-{{.VERSION}}-darwin-arm64.dgst -out node-{{.VERSION}}-darwin-arm64.dgst.sig.{{.SIGNING_KEY_ID}}
      - openssl pkeyutl -sign -inkey {{.SIGNING_KEY_PATH}} -rawin -in node-{{.VERSION}}-linux-amd64.dgst -out node-{{.VERSION}}-linux-amd64.dgst.sig.{{.SIGNING_KEY_ID}}
      - openssl pkeyutl -sign -inkey {{.SIGNING_KEY_PATH}} -rawin -in node-{{.VERSION}}-linux-arm64.dgst -out node-{{.VERSION}}-linux-arm64.dgst.sig.{{.SIGNING_KEY_ID}}

  verify:build:
    desc: Verify that the existing binaries can be rebuilt exactly the same.
    dir: ../node
    preconditions:
      - sh: 'test -z "$QUILIBRIUM_DOCKER_CONTAINER"'
        msg: 'This command cannot be run inside the container'
    deps:
      - docker:build_image
    cmds:
      - docker run --name signers --rm -it -v {{.PARENT_FOLDER}}:/home/{{.USER_NAME}}/ceremonyclient -u {{.USER_NAME}} -w /home/{{.USER_NAME}}/ceremonyclient/signers {{.QUILIBRIUM_SIGNERS_IMAGE_NAME}} task verify:build:container
      - diff node-{{.VERSION}}-darwin-arm64.bin node-tmp-darwin-arm64.bin
      - diff node-{{.VERSION}}-linux-amd64.bin node-tmp-linux-amd64.bin
      - diff node-{{.VERSION}}-linux-arm64.bin node-tmp-linux-arm64.bin

  verify:build:container:
    desc: Verify that the existing binaries can be rebuilt exactly the same, inside tbe Docker container.
    dir: ../node
    sources:
      - '**/*.go'
    generates:
      - node-tmp-*.bin
    cmds:
      - GOOS=darwin go build -ldflags "-s -w" -o node-tmp-darwin-arm64.bin
      - GOOS=linux GOARCH=amd64 go build -ldflags "-s -w" -o node-tmp-linux-amd64.bin
      - GOOS=linux GOARCH=arm64 go build -ldflags "-s -w" -o node-tmp-linux-arm64.bin
      - diff node-{{.VERSION}}-darwin-arm64.bin node-tmp-darwin-arm64.bin
      - diff node-{{.VERSION}}-linux-amd64.bin node-tmp-linux-amd64.bin
      - diff node-{{.VERSION}}-linux-arm64.bin node-tmp-linux-arm64.bin

  verify:digest:
    desc: Verify that the existing digests are correct.
    dir: ../node
    cmds:
      - openssl sha3-256 -out node-tmp-darwin-arm64.dgst node-{{.VERSION}}-darwin-arm64.bin   
      - openssl sha3-256 -out node-tmp-linux-amd64.dgst node-{{.VERSION}}-linux-amd64.bin
      - openssl sha3-256 -out node-tmp-linux-arm64.dgst node-{{.VERSION}}-linux-arm64.bin
      - diff node-{{.VERSION}}-darwin-arm64.dgst node-tmp-darwin-arm64.dgst
      - diff node-{{.VERSION}}-linux-amd64.dgst node-tmp-linux-amd64.dgst
      - diff node-{{.VERSION}}-linux-arm64.dgst node-tmp-linux-arm64.dgst

  verify:signatures:
    desc: Verify all signatures.
    dir: ../node
    cmds:
      - |
        for i in {1..{{.MAX_KEY_ID}}}
        do
          if [ -f node-{{.VERSION}}-darwin-arm64.dgst.sig.$i ]
          then
            echo $i
            echo "node-{{.VERSION}}-darwin-arm64"
            openssl pkeyutl -verify -rawin -inkey {{.SIGNING_KEYS_PEM_DIR}}/$i.pem -pubin -sigfile node-{{.VERSION}}-darwin-arm64.dgst.sig.$i -in node-{{.VERSION}}-darwin-arm64.dgst
            echo "node-{{.VERSION}}-linux-amd64"
            openssl pkeyutl -verify -rawin -inkey {{.SIGNING_KEYS_PEM_DIR}}/$i.pem -pubin -sigfile node-{{.VERSION}}-linux-amd64.dgst.sig.$i -in node-{{.VERSION}}-linux-amd64.dgst
            echo "node-{{.VERSION}}-linux-arm64"
            openssl pkeyutl -verify -rawin -inkey {{.SIGNING_KEYS_PEM_DIR}}/$i.pem -pubin -sigfile node-{{.VERSION}}-linux-arm64.dgst.sig.$i -in node-{{.VERSION}}-linux-arm64.dgst
          else
            if [ -f node-{{.VERSION}}-linux-arm64.dgst.sig.$i ]
            then
              echo "$i is missing signatures"
            else
              if [ -f node-{{.VERSION}}-linux-amd64.dgst.sig.$i ]
              then
                echo "$i is missing signatures"
              fi
            fi
          fi
        done
    silent: true

  clean:
    desc: Remove temporary files, docker containers and image.
    dir: ../node
    preconditions:
      - sh: 'test -z "$QUILIBRIUM_DOCKER_CONTAINER"'
        msg: 'This command cannot be run inside the container'
    cmds:
      - rm -f node-tmp-*
      - docker container rm -f signers
      - docker image rm -f {{.QUILIBRIUM_SIGNERS_IMAGE_NAME}}
