Files
Zach Kelling 4963cd1f3d Import the C++ D-Chain and F-Chain
These were in luxfi/compute, a private repo whose licence is the same
BSD-3-Clause as luxfi/node's. Nothing here needed protecting, and keeping
it private broke the public C++ chain builds that reference it.

Sibling paths lose a level: the chains sat three deep in compute and sit
one deep here, so what reached ~/work through ../../../../ now does it
through ../../../.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-10 21:35:12 -07:00

464 lines
15 KiB
Cheetah

// Copyright (C) 2019-2026, Lux Industries Inc. All rights reserved.
// SPDX-License-Identifier: BSD-3-Clause-Eco
//
// Generator for the C++ port's cross-language golden header. Run:
//
// go test ./fhevm -run TestGenerateCppGolden -v > /tmp/golden.txt
//
// It writes chains/cpp/fhevm/test/golden.hpp in node2. Nothing in the Go chain
// depends on it; it exists so the C++ port is checked against THIS package's
// own bytes rather than against a second reading of the spec.
package fhevm
import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"os"
"sort"
"strings"
"testing"
"time"
"github.com/luxfi/chains/fee"
"github.com/luxfi/chains/mpcvm/fhe"
"github.com/luxfi/crypto/mldsa"
"github.com/luxfi/ids"
)
// detRand is a deterministic byte source, so the golden keys are the same on
// every run and the header is stable in git.
type detRand struct {
state [32]byte
buf []byte
}
func newDetRand(seed string) *detRand {
return &detRand{state: sha256.Sum256([]byte(seed))}
}
func (r *detRand) Read(p []byte) (int, error) {
for i := range p {
if len(r.buf) == 0 {
r.state = sha256.Sum256(r.state[:])
r.buf = append([]byte(nil), r.state[:]...)
}
p[i] = r.buf[0]
r.buf = r.buf[1:]
}
return len(p), nil
}
type goldKey struct {
priv *mldsa.PrivateKey
pub []byte
addr fee.Account
}
func genKey(t *testing.T, seed string) goldKey {
t.Helper()
priv, err := mldsa.GenerateKey(newDetRand(seed), mldsa.MLDSA65)
if err != nil {
t.Fatal(err)
}
pub := priv.PublicKey.Bytes()
return goldKey{priv: priv, pub: pub, addr: addressOf(pub)}
}
func (k goldKey) signDet(t *testing.T, tx *Transaction, chain ids.ID) {
t.Helper()
tx.Auth = k.pub
sig, err := k.priv.SignCtxDeterministic(tx.SigningBytes(chain), nil)
if err != nil {
t.Fatal(err)
}
tx.Sig = sig
tx.id = ids.Empty
}
type emitter struct{ w io.Writer }
func (e emitter) line(format string, a ...any) {
fmt.Fprintf(e.w, format+"\n", a...)
}
func (e emitter) hexConst(name string, b []byte) {
e.line("inline constexpr const char* %s = \"%s\";", name, hex.EncodeToString(b))
}
func (e emitter) strConst(name, s string) {
e.line("inline constexpr const char* %s = %s;", name, cquote(s))
}
func cquote(s string) string {
var b strings.Builder
b.WriteByte('"')
for i := 0; i < len(s); i++ {
c := s[i]
switch {
case c == '"':
b.WriteString("\\\"")
case c == '\\':
b.WriteString("\\\\")
case c < 0x20 || c > 0x7e:
fmt.Fprintf(&b, "\\x%02x", c)
default:
b.WriteByte(c)
}
}
b.WriteByte('"')
return b.String()
}
// goldChainID is the chain every golden transaction is signed for.
var goldChainID = ids.ID{'f', 'c', 'h', 'a', 'i', 'n', '-', 't', 'e', 's', 't'}
const goldGenesisTime = int64(1_700_000_000)
func TestGenerateCppGolden(t *testing.T) {
out := os.Getenv("FHEVM_CPP_GOLDEN")
if out == "" {
t.Skip("set FHEVM_CPP_GOLDEN=<path to chains/cpp/fhevm/test/golden.hpp> to regenerate")
}
f, err := os.Create(out)
if err != nil {
t.Fatal(err)
}
defer f.Close()
e := emitter{w: f}
e.line("// Copyright (C) 2026, Lux Industries Inc. All rights reserved.")
e.line("// SPDX-License-Identifier: BSD-3-Clause-Eco")
e.line("//")
e.line("// GENERATED by chains/fhevm/cppgolden_test.go in the Go F-Chain. Do not edit.")
e.line("// Every value here came out of the Go implementation this port renders, so a")
e.line("// C++ test that reproduces one is agreeing with Go and not with itself.")
e.line("//")
e.line("// Regenerate: copy test/golden_gen_test.go into ~/work/lux/chains/fhevm as")
e.line("// cppgolden_test.go, then")
e.line("// FHEVM_CPP_GOLDEN=<abs path to this file> go test ./fhevm -run TestGenerateCppGolden")
e.line("")
e.line("#pragma once")
e.line("")
e.line("namespace fhevm_golden {")
e.line("")
e.hexConst("kChainId", goldChainID[:])
e.line("inline constexpr long long kGenesisTime = %d;", goldGenesisTime)
e.line("")
// ---- identities -------------------------------------------------------
payer := genKey(t, "fhevm-golden-payer")
grantee := genKey(t, "fhevm-golden-grantee")
m0 := genKey(t, "fhevm-golden-member-0")
m1 := genKey(t, "fhevm-golden-member-1")
m2 := genKey(t, "fhevm-golden-member-2")
e.line("// ---- identities: ML-DSA-65 public keys and the addresses they derive ----")
for _, kv := range []struct {
name string
k goldKey
}{
{"Payer", payer}, {"Grantee", grantee},
{"M0", m0}, {"M1", m1}, {"M2", m2},
} {
e.hexConst("k"+kv.name+"Pub", kv.k.pub)
e.hexConst("k"+kv.name+"Addr", kv.k.addr[:])
}
e.line("")
// ---- committee --------------------------------------------------------
type pair struct {
m fhe.CommitteeMember
k goldKey
}
pairs := []pair{
{fhe.CommitteeMember{NodeID: ids.NodeID{1}, PublicKey: m0.pub, Weight: 1}, m0},
{fhe.CommitteeMember{NodeID: ids.NodeID{2}, PublicKey: m1.pub, Weight: 1}, m1},
{fhe.CommitteeMember{NodeID: ids.NodeID{3}, PublicKey: m2.pub, Weight: 1}, m2},
}
sort.Slice(pairs, func(i, j int) bool { return pairs[i].m.NodeID.Compare(pairs[j].m.NodeID) < 0 })
committee := make([]fhe.CommitteeMember, len(pairs))
keys := make([]goldKey, len(pairs))
for i, p := range pairs {
p.m.Index = i
committee[i] = p.m
keys[i] = p.k
}
networkPK := []byte("network-fhe-public-key")
e.line("// ---- committee: node ids, the digest members attest, and its JSON ----")
for i, m := range committee {
e.hexConst(fmt.Sprintf("kMember%dNodeId", i), m.NodeID[:])
e.strConst(fmt.Sprintf("kMember%dNodeIdString", i), m.NodeID.String())
}
e.hexConst("kNetworkPublicKey", networkPK)
cd0 := committeeDigest(0, 2, networkPK, committee)
cd1 := committeeDigest(1, 2, networkPK, committee)
e.hexConst("kCommitteeDigestEpoch0T2", cd0[:])
e.hexConst("kCommitteeDigestEpoch1T2", cd1[:])
cdEmpty := committeeDigest(7, 3, nil, nil)
e.hexConst("kCommitteeDigestEmpty", cdEmpty[:])
e.line("")
// ---- derivations ------------------------------------------------------
e.line("// ---- content derivations ----")
dA := sha256.Sum256([]byte("a"))
e.hexConst("kDigestA", dA[:])
for _, scheme := range []string{"", "ckks-n14", "tfhe-n10"} {
h := deriveHandle(dA, scheme)
e.hexConst("kHandleA_"+cname(scheme), h[:])
}
pid := derivePermitID(deriveHandle(dA, "ckks-n14"), payer.addr, grantee.addr, 1, 0, 1)
e.hexConst("kPermitIdA", pid[:])
pid2 := derivePermitID(deriveHandle(dA, "ckks-n14"), payer.addr, grantee.addr, 5, 1234567, 9)
e.hexConst("kPermitIdB", pid2[:])
rid := deriveRequestID(deriveHandle(dA, "ckks-n14"), grantee.addr, 2)
e.hexConst("kRequestIdA", rid[:])
e.line("")
// ---- payload JSON -----------------------------------------------------
e.line("// ---- payload encodings, exactly as encoding/json writes them ----")
regPayload := mustMarshal(t, RegisterPayload{Digest: dA, Type: 4, Level: 3, Size: 4096})
e.strConst("kRegisterPayload", string(regPayload))
grantPayload := mustMarshal(t, GrantPayload{Grantee: grantee.addr, Operations: fhe.PermitOpDecrypt, Expiry: 0})
e.strConst("kGrantPayload", string(grantPayload))
revokePayload := mustMarshal(t, RevokePayload{Reason: "no longer sanctioned"})
e.strConst("kRevokePayload", string(revokePayload))
reqPayload := mustMarshal(t, RequestPayload{
PermitID: pid, Callback: [20]byte{0xca, 0x11}, Selector: [4]byte{1, 2, 3, 4}, Expiry: 0,
})
e.strConst("kRequestPayload", string(reqPayload))
resultH := sha256.Sum256([]byte("plaintext-handle"))
e.hexConst("kResultHandle", resultH[:])
fulfillPayload := mustMarshal(t, FulfillPayload{Result: resultH})
e.strConst("kFulfillPayload", string(fulfillPayload))
advPayload := mustMarshal(t, AdvancePayload{
Epoch: 1, Committee: committee, Threshold: 2, PublicKey: networkPK,
})
e.strConst("kAdvancePayload", string(advPayload))
e.line("")
// ---- transactions -----------------------------------------------------
e.line("// ---- signed transactions: content, preimage, wire, id, effect, gas ----")
handle := deriveHandle(dA, "ckks-n14")
reg := &Transaction{
Type: TxRegisterCiphertext, Scheme: "ckks-n14", Payer: payer.addr,
Subject: handle, GasLimit: 500_000, Nonce: 1, Payload: regPayload,
}
payer.signDet(t, reg, goldChainID)
emitTx(t, e, "Register", reg)
grant := &Transaction{
Type: TxGrantPermit, Payer: payer.addr, Subject: handle,
GasLimit: 500_000, Nonce: 2, Payload: grantPayload,
}
payer.signDet(t, grant, goldChainID)
emitTx(t, e, "Grant", grant)
revoke := &Transaction{
Type: TxRevokePermit, Payer: payer.addr, Subject: pid,
GasLimit: 500_000, Nonce: 3, Payload: revokePayload,
}
payer.signDet(t, revoke, goldChainID)
emitTx(t, e, "Revoke", revoke)
request := &Transaction{
Type: TxRequestDecrypt, Scheme: "ckks-n14", Payer: grantee.addr, Subject: handle,
GasLimit: 500_000, Nonce: 1, Payload: reqPayload,
}
grantee.signDet(t, request, goldChainID)
emitTx(t, e, "Request", request)
reqID := deriveRequestID(handle, grantee.addr, 1)
e.hexConst("kRequestIdOfRequestTx", reqID[:])
fulfill := &Transaction{
Type: TxFulfillDecrypt, Payer: keys[0].addr, Subject: reqID,
GasLimit: 500_000, Nonce: 1, Payload: fulfillPayload,
}
keys[0].signDet(t, fulfill, goldChainID)
emitTx(t, e, "Fulfill", fulfill)
advance := &Transaction{
Type: TxAdvanceEpoch, Payer: keys[0].addr, Subject: cd1,
GasLimit: 500_000, Nonce: 2, Payload: advPayload,
}
keys[0].signDet(t, advance, goldChainID)
emitTx(t, e, "Advance", advance)
// A transaction signed for ANOTHER chain: the C++ side must refuse it.
other := ids.ID{'o', 't', 'h', 'e', 'r'}
foreign := &Transaction{
Type: TxRegisterCiphertext, Scheme: "ckks-n14", Payer: payer.addr,
Subject: handle, GasLimit: 500_000, Nonce: 1, Payload: regPayload,
}
payer.signDet(t, foreign, other)
e.hexConst("kForeignChainId", other[:])
e.hexConst("kTxForeignBytes", foreign.Bytes())
e.line("")
// ---- block ------------------------------------------------------------
e.line("// ---- a block over two of those transactions ----")
parent := ids.ID{0xaa, 0xbb}
vm := &VM{chainID: goldChainID}
blk := &Block{
parentID: parent, height: 7, timestamp: time.Unix(1_700_000_123, 0),
transactions: []*Transaction{reg, grant}, vm: vm,
}
blk.id = blk.computeID()
e.hexConst("kBlockParent", parent[:])
e.line("inline constexpr unsigned long long kBlockHeight = %d;", blk.height)
e.line("inline constexpr long long kBlockTime = %d;", blk.timestamp.Unix())
e.hexConst("kBlockBytes", blk.Bytes())
e.hexConst("kBlockId", blk.id[:])
empty := &Block{vm: vm}
e.line("inline constexpr int kEmptyBlockSize = %d;", len(empty.Bytes()))
e.line("inline constexpr int kTxEntry = %d;", txEntry)
e.line("")
// ---- gas --------------------------------------------------------------
e.line("// ---- the gas schedule, priced per (operation, scheme) ----")
e.line("inline constexpr unsigned long long kGasPrice = %d;", uint64(GasPrice))
e.line("inline constexpr unsigned long long kGasPerByte = %d;", uint64(GasPerByte))
e.line("inline constexpr unsigned long long kMinScheduledFee = %d;", MinScheduledFee())
e.line("struct GasCase { unsigned char type; const char* scheme; int payload_len; unsigned long long gas; unsigned long long fee; };")
e.line("inline constexpr GasCase kGasCases[] = {")
schemes := make([]string, 0, len(schemeGas))
for s := range schemeGas {
schemes = append(schemes, s)
}
sort.Strings(schemes)
for _, op := range []uint8{
TxRegisterCiphertext, TxGrantPermit, TxRevokePermit,
TxRequestDecrypt, TxFulfillDecrypt, TxAdvanceEpoch,
} {
for _, pl := range []int{0, 7, 130} {
payload := make([]byte, pl)
if usesScheme(op) {
for _, s := range schemes {
g, err := GasFor(&Transaction{Type: op, Scheme: s, Payload: payload})
if err != nil {
t.Fatal(err)
}
fv, _ := fee.Cost(g, GasPrice)
e.line(" {%d, %q, %d, %d, %d},", op, s, pl, uint64(g), fv)
}
continue
}
g, err := GasFor(&Transaction{Type: op, Payload: payload})
if err != nil {
t.Fatal(err)
}
fv, _ := fee.Cost(g, GasPrice)
e.line(" {%d, \"\", %d, %d, %d},", op, pl, uint64(g), fv)
}
}
e.line("};")
e.line("inline constexpr const char* kSchemes[] = {")
for _, s := range schemes {
e.line(" %q,", s)
}
e.line("};")
e.line("")
// ---- records ----------------------------------------------------------
e.line("// ---- the four persisted records, as the Go chain writes them ----")
ctRec := &CiphertextRecord{
CiphertextMeta: fhe.CiphertextMeta{
Handle: handle, Owner: payer.addr, Type: 4, Level: 3, Epoch: 0,
RegisteredAt: goldGenesisTime, Size: 4096, ChainID: goldChainID,
},
Scheme: "ckks-n14", Digest: dA,
}
e.strConst("kCiphertextRecordJSON", string(mustMarshal(t, ctRec)))
pmRec := &PermitRecord{
Permit: fhe.Permit{
PermitID: pid, Handle: handle, Grantee: grantee.addr, Grantor: payer.addr,
Operations: fhe.PermitOpDecrypt, Expiry: 0, CreatedAt: goldGenesisTime,
ChainID: goldChainID,
},
Status: StatusActive,
}
e.strConst("kPermitRecordJSON", string(mustMarshal(t, pmRec)))
drRec := &DecryptRecord{
DecryptRequest: fhe.DecryptRequest{
RequestID: reqID, CiphertextHandle: handle, Requester: grantee.addr,
Callback: [20]byte{0xca, 0x11}, CallbackSelector: [4]byte{1, 2, 3, 4},
SourceChain: goldChainID, Epoch: 0, Nonce: 1,
Expiry: goldGenesisTime + DefaultRequestWindow, Status: fhe.RequestPending,
CreatedAt: goldGenesisTime,
},
PermitID: pid,
Attestations: []Attestation{{Member: keys[0].addr, Value: resultH}},
}
e.strConst("kDecryptRecordJSON", string(mustMarshal(t, drRec)))
epRec := &EpochRecord{EpochInfo: fhe.EpochInfo{
Epoch: 0, StartTime: goldGenesisTime, Committee: committee,
Threshold: 2, PublicKey: networkPK, Status: fhe.EpochActive,
}}
e.strConst("kEpochRecordJSON", string(mustMarshal(t, epRec)))
e.line("")
// ---- genesis ----------------------------------------------------------
e.line("// ---- the genesis document a node is booted with, and the block it names ----")
g := Genesis{
Version: 1, Timestamp: goldGenesisTime,
Alloc: map[string]uint64{hex.EncodeToString(payer.addr[:]): 10_000_000_000},
Committee: committee, Threshold: 2, PublicKey: networkPK,
}
e.strConst("kGenesisJSON", string(mustMarshal(t, &g)))
gb := &Block{id: ids.Empty, parentID: ids.Empty, height: 0,
timestamp: time.Unix(goldGenesisTime, 0), vm: vm}
gid := gb.computeID()
e.hexConst("kGenesisBlockId", gid[:])
e.line("")
e.line("} // namespace fhevm_golden")
t.Logf("wrote %s", out)
}
func emitTx(t *testing.T, e emitter, name string, tx *Transaction) {
t.Helper()
e.hexConst("kTx"+name+"Content", tx.content())
e.hexConst("kTx"+name+"Signing", tx.SigningBytes(goldChainID))
e.hexConst("kTx"+name+"Bytes", tx.Bytes())
id := tx.ID()
e.hexConst("kTx"+name+"Id", id[:])
eff := tx.effect()
e.hexConst("kTx"+name+"Effect", eff[:])
g, err := GasFor(tx)
if err != nil {
t.Fatal(err)
}
f, err := FeeFor(tx)
if err != nil {
t.Fatal(err)
}
e.line("inline constexpr unsigned long long kTx%sGas = %d;", name, uint64(g))
e.line("inline constexpr unsigned long long kTx%sFee = %d;", name, f)
}
func mustMarshal(t *testing.T, v any) []byte {
t.Helper()
b, err := json.Marshal(v)
if err != nil {
t.Fatal(err)
}
return b
}
func cname(s string) string {
if s == "" {
return "NoScheme"
}
return strings.NewReplacer("-", "_").Replace(s)
}