Files
proto/p/signer/bls_k1_test.go
zeekayandHanzo Dev 920d56f2ec Carry the P and X chain packages the node still held
The platform and exchange VMs are the last chain code living in luxfi/node
and the reason the node cannot be retired. This brings over the part of them
proto did not already have: the adopt registry, the ZAP wire generators for
signer, warp and validator fees, the hybrid and runtime proof-of-possession
signers, the native admission check, the zwarp client and server, the
X-chain network layer, the xvmroot state root, the batch verifier and owner
root, and the credential policy the P and X mempools share, which lands
beside the mempool it gates as proto/txs/auth.

The X-chain genesis builder moves into proto/x/genesis, where the codec it
calls already lives, so it no longer reaches for the xvm package to build
primary-asset bytes.

Imports point at the packages that already have homes: cache, upgrade,
version and util as their own modules, and gas, verify and index in
luxfi/vm. The three generated files bring github.com/zap-proto/go with them,
which requires go 1.26.5.

Most of the remaining difference between the node's trees and proto is not a
backlog. proto restructured this code in August and the node's copies predate
it, so files that look absent are largely present here under other names.
What genuinely cannot come yet is anything reaching for node/server/http,
node/vms or node/wallet, and the tests written against tx constructors
proto's tx layer no longer exports.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-06 11:46:03 -07:00

144 lines
3.9 KiB
Go

// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package signer
import (
"github.com/luxfi/crypto/bls/signer/localsigner"
"testing"
"github.com/stretchr/testify/require"
"github.com/luxfi/crypto/bls"
)
// TestBLSSingleNodeProofOfPossession tests BLS PoP for single node BFT
func TestBLSSingleNodeProofOfPossession(t *testing.T) {
require := require.New(t)
// Generate BLS key
sk, err := bls.NewSecretKey()
require.NoError(err)
// Create proof of possession
pop, err := NewProofOfPossession(func() bls.Signer { s, _ := localsigner.FromBytes(bls.SecretKeyToBytes(sk)); return s }())
require.NotNil(pop)
// Verify proof of possession
err = pop.Verify()
require.NoError(err, "Single node BLS proof of possession must be valid")
// Get public key
pk := pop.Key()
require.NotNil(pk)
// Verify it's the same as original
originalPk := sk.PublicKey()
require.Equal(bls.PublicKeyToCompressedBytes(originalPk), pop.PublicKey[:])
}
// TestBLSAggregateOfOne tests BLS aggregate signature with single validator
func TestBLSAggregateOfOne(t *testing.T) {
require := require.New(t)
// Generate key
sk, err := bls.NewSecretKey()
require.NoError(err)
// Message to sign
msg := []byte("consensus block data")
// Sign
sig, err := sk.Sign(msg)
require.NoError(err)
require.NotNil(sig)
// Create aggregate of 1
aggSig, err := bls.AggregateSignatures([]*bls.Signature{sig})
require.NoError(err, "Must support aggregate signature of 1")
// Aggregate public key of 1
pk := sk.PublicKey()
aggPk, err := bls.AggregatePublicKeys([]*bls.PublicKey{pk})
require.NoError(err, "Must support aggregate public key of 1")
// Verify
valid := bls.Verify(aggPk, aggSig, msg)
require.True(valid, "Aggregate signature of 1 must verify")
}
// TestInvalidProofOfPossession tests invalid PoP scenarios
func TestInvalidProofOfPossession(t *testing.T) {
tests := []struct {
name string
setupPoP func() *ProofOfPossession
expectErr bool
}{
{
name: "valid PoP",
setupPoP: func() *ProofOfPossession {
sk, _ := bls.NewSecretKey()
pop, _ := NewProofOfPossession(func() bls.Signer { s, _ := localsigner.FromBytes(bls.SecretKeyToBytes(sk)); return s }())
return pop
},
expectErr: false,
},
{
name: "corrupted signature",
setupPoP: func() *ProofOfPossession {
sk, _ := bls.NewSecretKey()
pop, _ := NewProofOfPossession(func() bls.Signer { s, _ := localsigner.FromBytes(bls.SecretKeyToBytes(sk)); return s }())
// Corrupt signature
pop.ProofOfPossession[0] ^= 0xFF
return pop
},
expectErr: true,
},
{
name: "corrupted public key",
setupPoP: func() *ProofOfPossession {
sk, _ := bls.NewSecretKey()
pop, _ := NewProofOfPossession(func() bls.Signer { s, _ := localsigner.FromBytes(bls.SecretKeyToBytes(sk)); return s }())
// Corrupt public key
pop.PublicKey[0] ^= 0xFF
return pop
},
expectErr: true,
},
{
name: "mismatched signature",
setupPoP: func() *ProofOfPossession {
sk1, _ := bls.NewSecretKey()
sk2, _ := bls.NewSecretKey()
// Use pk from sk1 but signature from sk2
pop, _ := NewProofOfPossession(func() bls.Signer { s, _ := localsigner.FromBytes(bls.SecretKeyToBytes(sk1)); return s }())
pk2 := sk2.PublicKey()
pk2Bytes := bls.PublicKeyToCompressedBytes(pk2)
sig2, _ := sk2.SignProofOfPossession(pk2Bytes)
copy(pop.ProofOfPossession[:], bls.SignatureToBytes(sig2))
return pop
},
expectErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
require := require.New(t)
pop := tt.setupPoP()
err := pop.Verify()
if tt.expectErr {
require.Error(err, "Invalid PoP must fail verification")
// Different corruption types can cause different errors
// from the BLS library or from our validation
} else {
require.NoError(err, "Valid PoP must pass verification")
}
})
}
}