mirror of
https://github.com/luxfi/evm.git
synced 2026-09-24 00:27:44 +00:00
- cmd/vmid prints constants.EVMID — Go source of truth for the C-Chain VM ID. Build scripts and Makefile now call this instead of hardcoding the base58 string. Drops a stale subnet-evm ID (ag3GReYP…) from the Makefile. - scripts/build.sh: default output is build/evm; INSTALL=1 installs under the derived VMID at \$LUX_PLUGIN_DIR. Codesigns on darwin in-line so a fresh binary doesn't get SIGKILLed by gatekeeper post-cp. - core/parallel/gpu_bridge.go: build tag flipped from \`!nogpu\` (opt-out) to \`gpu\` (opt-in) so default builds don't drag in luxfi/gpu cgo. - go.mod: luxfi/gpu v0.30.0 → v1.0.1. v0.30.0 referenced removed MLX symbols (mlx_from_slice_int64 etc.); v1.0.1 migrated to lux/gpu.h and builds cleanly with -tags gpu and -tags \"cevm gpu\". - LLM.md: build commands updated; \"no canonical / no aliases\" reflects reality (single VMID, one filename, derived from Go).
154 lines
4.0 KiB
Go
154 lines
4.0 KiB
Go
// Copyright (C) 2025-2026, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
//go:build cgo && darwin && gpu
|
|
|
|
package parallel
|
|
|
|
import (
|
|
"math/big"
|
|
"testing"
|
|
)
|
|
|
|
// TestRecoverV_LegacyValid verifies valid legacy V values (27, 28).
|
|
func TestRecoverV_LegacyValid(t *testing.T) {
|
|
tests := []struct {
|
|
v uint64
|
|
wantID uint8
|
|
wantOK bool
|
|
}{
|
|
{27, 0, true},
|
|
{28, 1, true},
|
|
}
|
|
for _, tt := range tests {
|
|
id, ok := recoverV(big.NewInt(int64(tt.v)), nil)
|
|
if ok != tt.wantOK || id != tt.wantID {
|
|
t.Errorf("recoverV(%d, nil) = (%d, %v), want (%d, %v)",
|
|
tt.v, id, ok, tt.wantID, tt.wantOK)
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestRecoverV_InvalidV verifies that V=0 is rejected.
|
|
func TestRecoverV_InvalidV(t *testing.T) {
|
|
_, ok := recoverV(big.NewInt(0), nil)
|
|
if ok {
|
|
t.Fatal("V=0 must be rejected for legacy transactions")
|
|
}
|
|
|
|
_, ok = recoverV(big.NewInt(1), nil)
|
|
if ok {
|
|
t.Fatal("V=1 must be rejected for legacy transactions (not 27 or 28)")
|
|
}
|
|
|
|
_, ok = recoverV(big.NewInt(26), nil)
|
|
if ok {
|
|
t.Fatal("V=26 must be rejected for legacy transactions")
|
|
}
|
|
|
|
_, ok = recoverV(big.NewInt(29), nil)
|
|
if ok {
|
|
t.Fatal("V=29 must be rejected for legacy transactions")
|
|
}
|
|
}
|
|
|
|
// TestRecoverV_EIP155 verifies EIP-155 V values for chain ID 1.
|
|
func TestRecoverV_EIP155(t *testing.T) {
|
|
chainID := big.NewInt(1)
|
|
// EIP-155: v = chainId * 2 + 35 + recovery_id
|
|
// Chain 1: v=37 => recovery 0, v=38 => recovery 1
|
|
id, ok := recoverV(big.NewInt(37), chainID)
|
|
if !ok || id != 0 {
|
|
t.Fatalf("recoverV(37, chainID=1): got (%d, %v), want (0, true)", id, ok)
|
|
}
|
|
|
|
id, ok = recoverV(big.NewInt(38), chainID)
|
|
if !ok || id != 1 {
|
|
t.Fatalf("recoverV(38, chainID=1): got (%d, %v), want (1, true)", id, ok)
|
|
}
|
|
}
|
|
|
|
// TestRecoverV_OverflowChainID verifies that a chain ID with >63 bits
|
|
// is rejected (prevents uint64 overflow).
|
|
func TestRecoverV_OverflowChainID(t *testing.T) {
|
|
// 64-bit chain ID: BitLen > 63
|
|
bigChainID := new(big.Int).Lsh(big.NewInt(1), 64) // 2^64
|
|
_, ok := recoverV(big.NewInt(37), bigChainID)
|
|
if ok {
|
|
t.Fatal("chain ID with >63 bits must be rejected")
|
|
}
|
|
}
|
|
|
|
// TestRecoverV_OverflowV verifies that a V value with >63 bits is rejected.
|
|
func TestRecoverV_OverflowV(t *testing.T) {
|
|
bigV := new(big.Int).Lsh(big.NewInt(1), 64) // 2^64
|
|
_, ok := recoverV(bigV, big.NewInt(1))
|
|
if ok {
|
|
t.Fatal("V with >63 bits must be rejected")
|
|
}
|
|
}
|
|
|
|
// TestPadTo32_Normal verifies padding of normal values.
|
|
func TestPadTo32_Normal(t *testing.T) {
|
|
n := big.NewInt(0xFF)
|
|
padded := padTo32(n)
|
|
if len(padded) != 32 {
|
|
t.Fatalf("expected 32 bytes, got %d", len(padded))
|
|
}
|
|
if padded[31] != 0xFF {
|
|
t.Fatalf("expected last byte 0xFF, got 0x%x", padded[31])
|
|
}
|
|
// All leading bytes should be zero
|
|
for i := 0; i < 31; i++ {
|
|
if padded[i] != 0 {
|
|
t.Fatalf("byte %d should be 0, got 0x%x", i, padded[i])
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestPadTo32_Exactly32 verifies that a 32-byte value is returned as-is.
|
|
func TestPadTo32_Exactly32(t *testing.T) {
|
|
n := new(big.Int).Lsh(big.NewInt(1), 248) // 32 bytes
|
|
b := n.Bytes()
|
|
if len(b) > 32 {
|
|
t.Skip("test precondition: value is exactly 32 bytes")
|
|
}
|
|
padded := padTo32(n)
|
|
if len(padded) != 32 {
|
|
t.Fatalf("expected 32 bytes, got %d", len(padded))
|
|
}
|
|
}
|
|
|
|
// TestPadTo32_Oversized verifies that values >32 bytes return nil.
|
|
func TestPadTo32_Oversized(t *testing.T) {
|
|
// 33 bytes: 2^264
|
|
n := new(big.Int).Lsh(big.NewInt(1), 264)
|
|
padded := padTo32(n)
|
|
if padded != nil {
|
|
t.Fatal("oversized value (>32 bytes) must return nil")
|
|
}
|
|
}
|
|
|
|
// TestPadTo32_Zero verifies zero value.
|
|
func TestPadTo32_Zero(t *testing.T) {
|
|
padded := padTo32(big.NewInt(0))
|
|
if len(padded) != 32 {
|
|
t.Fatalf("expected 32 bytes, got %d", len(padded))
|
|
}
|
|
for i, b := range padded {
|
|
if b != 0 {
|
|
t.Fatalf("byte %d should be 0, got 0x%x", i, b)
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestSecp256k1HalfN_IsPositive ensures the half-N constant is computed.
|
|
func TestSecp256k1HalfN_IsPositive(t *testing.T) {
|
|
if secp256k1halfN.Sign() <= 0 {
|
|
t.Fatal("secp256k1halfN must be positive")
|
|
}
|
|
if secp256k1halfN.BitLen() < 200 {
|
|
t.Fatalf("secp256k1halfN seems too small: %d bits", secp256k1halfN.BitLen())
|
|
}
|
|
}
|