All articles
solanagobase58fluxrpcperformancerpcbuilders

fluxrpc/base58: fast Base58 for Solana-shaped Go

Technical guide to github.com/fluxrpc/base58 — optimized Go Base58 encode/decode for 32-byte pubkeys and 64-byte signatures (Firedancer-style matmul/AVX2), Append* zero-alloc paths, batch encode, EncodeCached32. API, perf vs solana-go, when to use it.

devrels.xyz/a/232short link

fluxrpc/base58 is a Go library for Base58 encode/decode tuned for Solana-shaped payloads: 32-byte public keys and 64-byte signatures. Built and used at FluxRPC for high-volume RPC rendering. Generic lengths use a limb-based codec; 32/64 use Firedancer-style matrix-multiply fast paths (AVX2 on amd64, with scalar assembly and pure-Go fallbacks).

Part of the FluxRPC stack (org fluxrpc, founder @CloakdDev).

People and links

Attribution
RoleHandle / URL
Repogithub.com/fluxrpc/base58
OrgFluxRPC · github.com/fluxrpc · @fluxrpc
FounderScott · CloakdDev · @CloakdDev · github.com/cloakd

Install

bash
go get github.com/fluxrpc/base58@latest

API surface

go
import "github.com/fluxrpc/base58"

// Variable length (dispatches to 32/64 fast paths when applicable)
s := base58.Encode(buf)
raw, err := base58.Decode(s)

// Fixed-size (pubkeys / signatures)
s = base58.Encode32(&pk)      // *[32]byte
s = base58.Encode64(&sig)     // *[64]byte
err = base58.Decode32(s, &pk)
err = base58.Decode64(s, &sig)

// Zero-alloc append (reuse buffer in hot loops)
buf = base58.AppendEncode32(buf[:0], &pk)
buf = base58.AppendEncode64(buf[:0], &sig)
buf, err = base58.AppendDecode(buf[:0], s)
buf = base58.AppendEncode(buf[:0], raw)

// Batch: four keys at a time; strings share one backing buffer
strs := base58.Encode32Batch(pks)
strs = base58.Encode64Batch(sigs)

// Interning cache for hot repeated keys (program IDs, sysvars, mints)
s = base58.EncodeCached32(&programId) // ~6 ns hit, 0 alloc — read collision caveat in docs

Upstream notes: Decode32/Decode64 and Append* are zero heap allocations. Plain Encode/Encode32/Encode64 allocate once for the returned string. For RPC JSON assembly, prefer AppendEncode* with a reused buffer.

go
buf := make([]byte, 0, base58.EncodedMaxLen32) // see package for max lens
for i := range pubkeys {
    buf = base58.AppendEncode32(buf[:0], &pubkeys[i]) // 0 allocs/op
    writeJSONString(w, buf)
}

Why it is fast (architecture)

  • 32/64 fixed paths — matrix-multiply style encode (Firedancer / fd_base58 lineage), not classic byte-at-a-time long division
  • AVX2 on amd64 when CPUID allows; scalar asm (amd64/arm64) + pure Go otherwise
  • Variable lengths — limb-based codec claimed ~10–30× vs naive long division on longer inputs
  • Batch — interleaved carry chains, shared string backing (~35% less CPU/key vs looping Encode32 in upstream notes)
  • EncodeCached32 — optional intern for repeated keys; document collision tradeoff before enabling in security-sensitive contexts

Correctness: cross-checked against Bitcoin Core / bs58 / fd_base58 / five8 vectors, randomized round-trips, and go test -fuzz. Fallbacks exercised via dedicated tests and multi-arch builds.

Performance (upstream published)

Same machine, Go 1.26, i7-9700K AVX2, single core — generic Encode/Decode vs solana-foundation/solana-go base58 (averages of 5 runs; comparison bench not vendored to stay dependency-free):

vs solana-go base58 (upstream README)
Opsolana-gofluxrpc/base58Speedup
Encode 32B364 ns · 2 alloc68 ns · 1 alloc~5.3×
Decode 32B142 ns · 2 alloc60 ns · 1 alloc~2.4×
Encode 64B1,116 ns · 2 alloc153 ns · 1 alloc~7.3×
Decode 64B296 ns · 3 alloc128 ns · 1 alloc~2.3×
Encode 100B2,378 ns · 5 alloc541 ns · 1 alloc~4.4×

Typed paths (indicative): Encode32 ~63 ns/1 alloc; AppendEncode32 ~41 ns/0; Decode32 ~34 ns/0; EncodeCached32 hit ~5.7 ns/0. Re-bench on your hardware before citing in SLOs.

When to use it

Fit
UseSkip / careful
Go RPC, indexer, or bot encoding many pubkeys/sigsNon-Go stacks (use native crates / five8 / bs58)
JSON/log pipelines where Base58 is a measurable hotspotCold paths where stdlib-adjacent deps already fine
Append* into reused buffersEncodeCached32 without reading collision caveats for adversarial inputs

Related

Summary

fluxrpc/base58 is a dependency-light Go Base58 codec optimized for Solana’s 32/64-byte encode storm: fixed-size kernels, AVX2 when available, zero-alloc append/decode paths, batch and optional key interning. Drop it into Go services that mint Base58 strings at RPC scale; keep verifying benches on your CPU and prefer AppendEncode* in the hottest loops.

Keep reading

Get new articles in your inbox

Technical deep-dives on Solana tooling, infrastructure, and ecosystem. No noise.