mirror of
https://github.com/luxfi/warp.git
synced 2026-10-30 15:13:04 +00:00
Lux Partners Limited is not the entity behind this work. Every place the old name stood — copyright lines, site footers, brand config, legal and compliance text — now names the company that actually holds it. lux.fund is the exception and is not renamed to match: that site belongs to Lux Assets Management LLC, a different company, and it says so. Two kinds of line were left for a person rather than rewritten. A dated news item recording that Lux Partners Limited was established in the Isle of Man is a historical fact, and renaming it would falsify the record. And a sentence asserting that the company is domiciled in the Isle of Man is a claim about a jurisdiction, not a name — an Inc or an LLC is not an Isle of Man company, so swapping the name there would assert something untrue. Co-authored-by: Hanzo Dev <[email protected]>
169 lines
4.4 KiB
Go
169 lines
4.4 KiB
Go
// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package signer
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/luxfi/crypto/bls"
|
|
"github.com/luxfi/warp"
|
|
)
|
|
|
|
// Signer is an interface for signing warp messages
|
|
type Signer interface {
|
|
// Sign signs a Message over the Beam domain (BeamSigningBytes(D)).
|
|
Sign(message *warp.Message) (*bls.Signature, error)
|
|
|
|
// GetPublicKey returns the public key
|
|
GetPublicKey() *bls.PublicKey
|
|
}
|
|
|
|
// LocalSigner signs messages with a local secret key
|
|
type LocalSigner struct {
|
|
sk *bls.SecretKey
|
|
pk *bls.PublicKey
|
|
}
|
|
|
|
// NewLocalSigner creates a new local signer
|
|
func NewLocalSigner(sk *bls.SecretKey) *LocalSigner {
|
|
return &LocalSigner{
|
|
sk: sk,
|
|
pk: sk.PublicKey(),
|
|
}
|
|
}
|
|
|
|
// Sign signs a message over the Beam domain.
|
|
func (s *LocalSigner) Sign(message *warp.Message) (*bls.Signature, error) {
|
|
return warp.Sign(warp.BeamSigningBytes(message.ID()), s.sk)
|
|
}
|
|
|
|
// GetPublicKey returns the public key
|
|
func (s *LocalSigner) GetPublicKey() *bls.PublicKey {
|
|
return s.pk
|
|
}
|
|
|
|
// Backend is an interface for signing backends
|
|
type Backend interface {
|
|
// Sign signs a message with multiple signers
|
|
Sign(ctx context.Context, message *warp.Message, signerIndices []int) (*warp.Envelope, error)
|
|
|
|
// GetValidators returns the current validator set
|
|
GetValidators(ctx context.Context) ([]*warp.Validator, error)
|
|
}
|
|
|
|
// SignerBackend manages multiple signers
|
|
type SignerBackend struct {
|
|
signers map[int]Signer
|
|
validators []*warp.Validator
|
|
}
|
|
|
|
// NewSignerBackend creates a new signer backend
|
|
func NewSignerBackend(validators []*warp.Validator) *SignerBackend {
|
|
return &SignerBackend{
|
|
signers: make(map[int]Signer),
|
|
validators: validators,
|
|
}
|
|
}
|
|
|
|
// AddSigner adds a signer for a validator
|
|
func (b *SignerBackend) AddSigner(index int, signer Signer) error {
|
|
if index < 0 || index >= len(b.validators) {
|
|
return fmt.Errorf("invalid validator index %d", index)
|
|
}
|
|
|
|
// Verify public key matches
|
|
expectedPK := b.validators[index].PublicKey
|
|
if expectedPK != signer.GetPublicKey() {
|
|
return errors.New("signer public key does not match validator")
|
|
}
|
|
|
|
b.signers[index] = signer
|
|
return nil
|
|
}
|
|
|
|
// Sign signs a message with multiple signers
|
|
func (b *SignerBackend) Sign(
|
|
ctx context.Context, message *warp.Message, signerIndices []int,
|
|
) (*warp.Envelope, error) {
|
|
if len(signerIndices) == 0 {
|
|
return nil, errors.New("no signers specified")
|
|
}
|
|
|
|
// Get signers
|
|
signers := make([]*bls.SecretKey, 0, len(signerIndices))
|
|
for _, idx := range signerIndices {
|
|
signer, ok := b.signers[idx]
|
|
if !ok {
|
|
return nil, fmt.Errorf("no signer for validator %d", idx)
|
|
}
|
|
|
|
// For local signers, we need the secret key
|
|
localSigner, ok := signer.(*LocalSigner)
|
|
if !ok {
|
|
return nil, fmt.Errorf("signer %d is not a local signer", idx)
|
|
}
|
|
|
|
signers = append(signers, localSigner.sk)
|
|
}
|
|
|
|
// Sign message
|
|
return warp.SignMessage(message, signers, b.validators)
|
|
}
|
|
|
|
// GetValidators returns the current validator set
|
|
func (b *SignerBackend) GetValidators(ctx context.Context) ([]*warp.Validator, error) {
|
|
return b.validators, nil
|
|
}
|
|
|
|
// RemoteSigner signs messages via RPC
|
|
type RemoteSigner struct {
|
|
client SignerClient
|
|
pk *bls.PublicKey
|
|
}
|
|
|
|
// SignerClient is an interface for remote signing
|
|
type SignerClient interface {
|
|
// Sign signs a message remotely
|
|
Sign(ctx context.Context, msg []byte) ([]byte, error)
|
|
|
|
// GetPublicKey gets the public key
|
|
GetPublicKey(ctx context.Context) ([]byte, error)
|
|
}
|
|
|
|
// NewRemoteSigner creates a new remote signer
|
|
func NewRemoteSigner(client SignerClient) (*RemoteSigner, error) {
|
|
// Get public key from remote
|
|
pkBytes, err := client.GetPublicKey(context.Background())
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get public key: %w", err)
|
|
}
|
|
|
|
pk, err := bls.PublicKeyFromCompressedBytes(pkBytes)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to parse public key: %w", err)
|
|
}
|
|
|
|
return &RemoteSigner{
|
|
client: client,
|
|
pk: pk,
|
|
}, nil
|
|
}
|
|
|
|
// Sign signs a message over the Beam domain via the remote signer.
|
|
func (s *RemoteSigner) Sign(message *warp.Message) (*bls.Signature, error) {
|
|
sigBytes, err := s.client.Sign(context.Background(), warp.BeamSigningBytes(message.ID()))
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to sign remotely: %w", err)
|
|
}
|
|
|
|
return bls.SignatureFromBytes(sigBytes)
|
|
}
|
|
|
|
// GetPublicKey returns the public key
|
|
func (s *RemoteSigner) GetPublicKey() *bls.PublicKey {
|
|
return s.pk
|
|
}
|