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

albyhub: init at 1.12.0 #368929

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

albyhub: init at 1.12.0 #368929

wants to merge 1 commit into from

Conversation

bleetube
Copy link
Contributor

@bleetube bleetube commented Dec 28, 2024

#369196

This turns out to be yarn + Go + CGO + shared libraries Nix derivation.

I used the Dockerfile as a starting point for how this is supposed to be built.

I wasn't able to use autoPatchelfHook to clean the RPATHs, the resulting binary would still have forbidden references to /build/. To clean the RPATHs I had to add a postInstall step with patchelf --set-rpath "${lib.makeLibraryPath buildInputs}" $out/bin/http.

⚠️ I used buildGoModule for the shared library object derivations, and pulled them in with callPackage in package.nix. If that's abhorrent, I'm happy to change it. I dont' know what the best practice is for that.

I think it should build on aarch64, but I don't have a machine to test that on.

The hub/go.mod requires go 1.23.1, so if you're probably not building this on nixos24.05 or older.

The resulting binary name is http which is exceptionally ambiguous. Should it be renamed?

Progress:

  • prebuild frontend artifacts
  • buildinput for precompiled ldk_node
  • buildinput for precompiled breez_sdk
  • buildinput for precompiled "glalby_bindings"
  • clean RPATHs
  • build and run http
  • minor cleanup
  • [🤷] learn the right way to include build imports

Things done

  • Built on platform(s)
    • x86_64-linux
    • aarch64-linux
    • x86_64-darwin
    • aarch64-darwin
  • For non-Linux: Is sandboxing enabled in nix.conf? (See Nix manual)
    • sandbox = relaxed
    • sandbox = true
  • Tested, as applicable:
  • Tested compilation of all packages that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD". Note: all changes have to be committed, also see nixpkgs-review usage
  • Tested basic functionality of all binary files (usually in ./result/bin/)
  • 25.05 Release Notes (or backporting 24.11 and 25.05 Release notes)
    • (Package updates) Added a release notes entry if the change is major or breaking
    • (Module updates) Added a release notes entry if the change is significant
    • (Module addition) Added a release notes entry if adding a new NixOS module
  • Fits CONTRIBUTING.md.

Add a 👍 reaction to pull requests you find important.

@bleetube
Copy link
Contributor Author

Here's my discovery notes on ldk-node-go, which is "Experimental Go bindings for LDK-node"

repository at a glance:

$ tree
.
├── go.mod
├── ldk_node
│   ├── aarch64-unknown-linux-gnu
│   │   └── libldk_node.so
│   ├── arm-unknown-linux-gnueabihf
│   │   └── libldk_node.so
│   ├── cgo.go
│   ├── ldk_node.c
│   ├── ldk_node.go
│   ├── ldk_node.h
│   ├── universal-macos
│   │   └── libldk_node.dylib
│   ├── x86_64-pc-windows-gnu
│   │   └── ldk_node.dll
│   ├── x86_64-pc-windows-msvc
│   │   └── ldk_node.dll
│   └── x86_64-unknown-linux-gnu
│       └── libldk_node.so
└── README.md

8 directories, 12 files

The repository structure includes pre-compiled shared libraries (.so, .dll, .dylib) for different architectures and operating systems.
The cgo.go file sets up the necessary CGo directives to link against these pre-compiled libraries based on the target platform.
The ldk_node.c and ldk_node.h files provide the C interface to the Rust library.
The ldk_node.go file contains the Go code that wraps the C interface, making it usable from Go.

In github.com/getAlby/hub the ldk_node package is imported as follows

lnclient/ldk/ldk.go:

head -n37 /home/blee/src/hub/lnclient/ldk/ldk.go
package ldk

import (
        "context"
        "crypto/sha256"
        "database/sql"
        "errors"
        "fmt"
        "math"
        "os"
        "path/filepath"
        "slices"
        "sort"
        "strconv"
        "strings"
        "time"

        "github.com/getAlby/ldk-node-go/ldk_node"
        "github.com/tyler-smith/go-bip32"

        // "github.com/getAlby/hub/ldk_node"

        "encoding/hex"
        "encoding/json"

        decodepay "github.com/nbd-wtf/ln-decodepay"
        "github.com/sirupsen/logrus"

        "github.com/getAlby/hub/config"
        "github.com/getAlby/hub/events"
        "github.com/getAlby/hub/lnclient"
        "github.com/getAlby/hub/logger"
        "github.com/getAlby/hub/lsp"
        "github.com/getAlby/hub/service/keys"
        "github.com/getAlby/hub/utils"
)

Then in github.com/getAlby/hub there's a Dockerfile that essentially runs go build cmd/http/main.go and then runs build/docker/copy_dylibs.sh:

#!/usr/bin/env bash
if [[ "$ARCH" == "amd64" ]]; then
    cp "$(go list -m -f "{{.Dir}}" github.com/breez/breez-sdk-go)"/breez_sdk/lib/linux-amd64/libbreez_sdk_bindings.so ./
    cp "$(go list -m -f "{{.Dir}}" github.com/getAlby/glalby-go)"/glalby/x86_64-unknown-linux-gnu/libglalby_bindings.so ./
    cp "$(go list -m -f "{{.Dir}}" github.com/getAlby/ldk-node-go)"/ldk_node/x86_64-unknown-linux-gnu/libldk_node.so ./
elif [[ "$ARCH" == "arm64" ]]; then
    cp "$(go list -m -f "{{.Dir}}" github.com/breez/breez-sdk-go)"/breez_sdk/lib/linux-aarch64/libbreez_sdk_bindings.so ./
    cp "$(go list -m -f "{{.Dir}}" github.com/getAlby/glalby-go)"/glalby/aarch64-unknown-linux-gnu/libglalby_bindings.so ./
    cp "$(go list -m -f "{{.Dir}}" github.com/getAlby/ldk-node-go)"/ldk_node/aarch64-unknown-linux-gnu/libldk_node.so ./
else
    echo "Invalid ARCH value"
    exit 1
fi

It appears that the repository "github.com/getAlby/ldk-node-go" is providing Go bindings for a Rust library called LDK (Lightning Development Kit).

Thus, albyhub/ldk-node-go/default.nix is used as a buildinput for albyhub/package.nix

@bleetube
Copy link
Contributor Author

Here are my discovery notes on github.com/breez/breez-sdk-go

repository at a glance:

.
├── breez_sdk
│   ├── breez_sdk.go
│   ├── cgo.go
│   └── lib
...
│       ├── linux-aarch64
│       │   ├── dummy.go
│       │   └── libbreez_sdk_bindings.so
│       ├── linux-amd64
│       │   ├── dummy.go
│       │   └── libbreez_sdk_bindings.so
...
├── go.mod
├── LICENSE
└── README.md

12 directories, 28 files

The repository structure includes pre-compiled shared libraries (.so, .dll, .dylib) for different architectures and operating systems.
The cgo.go file sets up the necessary CGo directives to link against these pre-compiled libraries based on the target platform.
The breez_sdk.go file contains the Go code that wraps the C interface, making it usable from Go.

In github.com/getAlby/hub the breez_sdk package is imported as follows

lnclient/breez/breez.go:

//go:build !skip_breez

package breez

import (
	"context"
	"encoding/hex"
	"errors"
	"log"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/breez/breez-sdk-go/breez_sdk"
	decodepay "github.com/nbd-wtf/ln-decodepay"
	"github.com/sirupsen/logrus"

	"github.com/getAlby/hub/lnclient"
	"github.com/getAlby/hub/logger"
)
...

@bleetube bleetube force-pushed the albyhub branch 2 times, most recently from 4793875 to f30b509 Compare December 28, 2024 23:02
@bleetube
Copy link
Contributor Author

bleetube commented Dec 28, 2024

Here's my discovery notes on github.com/getAlby/glalby-go which provides Go bindings for Greenlight.

repository at a glance:

.
├── glalby
│   ├── aarch64-unknown-linux-gnu
│   │   └── libglalby_bindings.so
│   ├── arm-unknown-linux-gnueabihf
│   │   └── libglalby_bindings.so
│   ├── cgo.go
│   ├── glalby.c
│   ├── glalby.go
│   ├── glalby.h
│   ├── universal-macos
│   │   └── libglalby_bindings.dylib
│   ├── x86_64-pc-windows-gnu
│   │   └── glalby_bindings.dll
│   ├── x86_64-pc-windows-msvc
│   │   └── glalby_bindings.dll
│   └── x86_64-unknown-linux-gnu
│       └── libglalby_bindings.so
├── go.mod
└── README.md

8 directories, 12 files

The repository structure includes pre-compiled shared libraries (.so, .dll, .dylib) for different architectures and operating systems.
The cgo.go file sets up the necessary CGo directives to link against these pre-compiled libraries based on the target platform.
The glalby.c and glalby.h files provide the C interface to the Rust library.
The glalby.go file contains the Go code that wraps the C interface, making it usable from Go.

In github.com/getAlby/hub the glalby package is imported as follows

lnclient/greenlight/greenlight.go:

package greenlight

import (
	"context"
	"errors"
	"log"
	"math/rand"
	"os"
	"path/filepath"
	"sort"
	"strconv"
	"strings"
	"time"

	//"github.com/getAlby/hub/glalby" // for local development only

	"github.com/getAlby/glalby-go/glalby"
	decodepay "github.com/nbd-wtf/ln-decodepay"
	"github.com/sirupsen/logrus"

	"github.com/getAlby/hub/config"
	"github.com/getAlby/hub/lnclient"
	"github.com/getAlby/hub/logger"
)

...

@bleetube bleetube force-pushed the albyhub branch 5 times, most recently from 4936cdb to e55c6e2 Compare December 29, 2024 05:01
@bleetube
Copy link
Contributor Author

bleetube commented Dec 29, 2024

If I've fixed the shared library loading then this error seems to suggest that I have mismatched library versions:

blee@litten ~/s/n/p/b/a/albyhub (albyhub|✚1)> ./result/bin/http --version
./result/bin/http: symbol lookup error: ./result/bin/http: undefined symbol: breez_sdk_d6e4_BlockingBreezServices_lsp_info

breez_sdk.go has bindings generated by something called "uniffi"

blee@litten ~> grep lsp_info ~/src/breez-sdk-go/breez_sdk/breez_sdk.go
RustBuffer breez_sdk_a35c_BlockingBreezServices_fetch_lsp_info(
RustBuffer breez_sdk_a35c_BlockingBreezServices_lsp_info(
                return C.breez_sdk_a35c_BlockingBreezServices_fetch_lsp_info(
                return C.breez_sdk_a35c_BlockingBreezServices_lsp_info(

The notable difference here being d6e4 vs a35c.

Here's how we can find the commit (or version) that has d6e4:

cd ~/src/breez-sdk-go
git log -S 'breez_sdk_d6e4_BlockingBreezServices_lsp_info' -- breez_sdk/breez_sdk.go 
commit 8dbaaa24c13f37129d9900af89ca169ea21c54c4 (tag: v0.6.0-rc1)
commit cfb3d4b732f9ea4f0ade8510554ace412301f3a3 (tag: v0.5.2)

Actually, the smarter way to do this is probably to just look at go.mod

grep breez-sdk-go ~/src/hub/go.sum
github.com/breez/breez-sdk-go v0.5.2 h1:frqX14cKTM2egWP7C53u3SzBkYQrgx9P7si/Ig9Droo=
github.com/breez/breez-sdk-go v0.5.2/go.mod h1:EalYMEeQVwRzr6UXnF4QpLlpuWNwQQN9xwtDKNIutBo=

Which tells me I need to be using breez-sdk-go v0.5.2. I'll probably need to do this for all 3 shared libraries and for all updates moving forward so that we're shipping the same library versions as upstream.

One way to confirm this is to use nm -D

   nm -D /nix/store/your-new-store-path-breez-sdk-go-0.5.2/lib/libbreez_sdk_bindings.so | grep lsp_info
   # Expected output:
   # 000000000024761e T breez_sdk_d6e4_BlockingBreezServices_fetch_lsp_info
   # 00000000002477d5 T breez_sdk_d6e4_BlockingBreezServices_lsp_info
   # ... other functions

This pointed me to a different issue in my local environment where it wasn't rebuilding the libraries as expected.

@bleetube bleetube force-pushed the albyhub branch 2 times, most recently from 1f7e118 to e3e4277 Compare December 29, 2024 07:11
@bleetube bleetube marked this pull request as ready for review December 29, 2024 17:56
@ofborg ofborg bot added 8.has: package (new) This PR adds a new package 11.by: package-maintainer This PR was created by the maintainer of the package it changes 10.rebuild-darwin: 1 10.rebuild-linux: 1 labels Dec 30, 2024
@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/prs-ready-for-review/3032/5058

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

Successfully merging this pull request may close these issues.

2 participants