niko_trust/pkg/protocol/helpers_test.go
Niko Marmeladkov 3bf13fa488 Public SDK packages, proxy-aware rate limits, service login recipe
- internal/{address,identity,protocol,tce,transport,verify} -> pkg/ so
  external Go projects can import the verified core; invariant tests
  updated for the new paths
- Config.TrustProxy: key rate limiting by X-Forwarded-For when the relay
  sits behind a reverse proxy (off by default, header never trusted
  otherwise)
- examples/service + examples/approve: complete passwordless login round
  trip (mint request -> wallet approves -> local verify), run live in CI
- docs/SERVICE-GUIDE.md: the integration recipe
2026-08-26 12:49:54 +03:00

118 lines
2.8 KiB
Go

package protocol_test
import (
"encoding/hex"
"encoding/json"
"os"
"testing"
"git.n1ko.dev/Niko/niko_trust/pkg/identity/signer"
)
const vectorsPath = "../../testdata/vectors/tce_vectors.json"
// vectorFile mirrors the frozen reference file. Only the fields the protocol
// tests need are declared.
type vectorFile struct {
Parties map[string]struct {
SeedHex string `json:"seed_hex"`
PubkeyHex string `json:"pubkey_hex"`
Address string `json:"address"`
} `json:"parties"`
Vectors []vectorEntry `json:"vectors"`
Rejects []rejectEntry `json:"rejects"`
}
type vectorEntry struct {
Name string `json:"name"`
Description string `json:"description"`
TCEHex string `json:"tce_hex"`
TCELen int `json:"tce_len"`
ObjectIDHex string `json:"object_id_hex"`
SignerPubkey string `json:"signer_pubkey_hex"`
SignerAddress string `json:"signer_address"`
SignatureHex string `json:"signature_hex"`
RequestIDHex string `json:"request_id_hex"`
JSON json.RawMessage `json:"json"`
}
type rejectEntry struct {
Name string `json:"name"`
TCEHex *string `json:"tce_hex"`
}
func loadVectors(t *testing.T) *vectorFile {
t.Helper()
b, err := os.ReadFile(vectorsPath)
if err != nil {
t.Fatalf("read vectors: %v", err)
}
var vf vectorFile
if err := json.Unmarshal(b, &vf); err != nil {
t.Fatalf("parse vectors: %v", err)
}
return &vf
}
func mustHex(t *testing.T, s string) []byte {
t.Helper()
b, err := hex.DecodeString(s)
if err != nil {
t.Fatalf("bad hex %q: %v", s, err)
}
return b
}
func mustSigner(t *testing.T) *signer.Signer {
t.Helper()
s, err := signer.Generate()
if err != nil {
t.Fatal(err)
}
return s
}
// seedSigner builds a signer from a 32-byte seed.
func seedSigner(t *testing.T, seed []byte) *signer.Signer {
t.Helper()
s, err := signer.FromSeed(seed)
if err != nil {
t.Fatalf("FromSeed: %v", err)
}
return s
}
// nonce returns a 16-byte nonce filled with a repeating byte.
func nonce(b byte) []byte {
out := make([]byte, 16)
for i := range out {
out[i] = b
}
return out
}
// signerFixtures holds two independent signers for building and signing test
// objects. Signing lives in signer, which the package under test never
// imports; tests may.
type signerFixtures struct {
alice *signer.Signer
bob *signer.Signer
}
func newSignerFixtures(t *testing.T) *signerFixtures {
t.Helper()
return &signerFixtures{alice: mustSigner(t), bob: mustSigner(t)}
}
// byName returns the vector entry with the given name, failing the test if it
// is absent.
func byName(t *testing.T, vf *vectorFile, name string) *vectorEntry {
t.Helper()
for i := range vf.Vectors {
if vf.Vectors[i].Name == name {
return &vf.Vectors[i]
}
}
t.Fatalf("vector %q not found", name)
return nil
}