2023-04-10 18:36:45 +08:00
|
|
|
package vote
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2023-09-08 16:36:16 +08:00
|
|
|
"os"
|
2023-04-10 18:36:45 +08:00
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
|
2024-04-11 14:11:15 +08:00
|
|
|
"github.com/prysmaticlabs/prysm/v5/crypto/bls"
|
|
|
|
validatorpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/validator-client"
|
|
|
|
"github.com/prysmaticlabs/prysm/v5/validator/accounts/iface"
|
|
|
|
"github.com/prysmaticlabs/prysm/v5/validator/accounts/wallet"
|
|
|
|
"github.com/prysmaticlabs/prysm/v5/validator/keymanager"
|
2023-04-10 18:36:45 +08:00
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/core/types"
|
|
|
|
"github.com/ethereum/go-ethereum/log"
|
|
|
|
"github.com/ethereum/go-ethereum/metrics"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
voteSignerTimeout = time.Second * 5
|
|
|
|
)
|
|
|
|
|
2023-05-05 14:15:43 +08:00
|
|
|
var votesSigningErrorCounter = metrics.NewRegisteredCounter("votesSigner/error", nil)
|
|
|
|
|
2023-04-10 18:36:45 +08:00
|
|
|
type VoteSigner struct {
|
|
|
|
km *keymanager.IKeymanager
|
2023-09-08 10:20:07 +08:00
|
|
|
PubKey [48]byte
|
2023-04-10 18:36:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func NewVoteSigner(blsPasswordPath, blsWalletPath string) (*VoteSigner, error) {
|
|
|
|
dirExists, err := wallet.Exists(blsWalletPath)
|
|
|
|
if err != nil {
|
|
|
|
log.Error("Check BLS wallet exists", "err", err)
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if !dirExists {
|
|
|
|
log.Error("BLS wallet did not exists.")
|
2024-03-11 14:52:33 +08:00
|
|
|
return nil, errors.New("BLS wallet did not exists")
|
2023-04-10 18:36:45 +08:00
|
|
|
}
|
|
|
|
|
2023-09-08 16:36:16 +08:00
|
|
|
walletPassword, err := os.ReadFile(blsPasswordPath)
|
2023-04-10 18:36:45 +08:00
|
|
|
if err != nil {
|
|
|
|
log.Error("Read BLS wallet password", "err", err)
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
log.Info("Read BLS wallet password successfully")
|
|
|
|
|
|
|
|
w, err := wallet.OpenWallet(context.Background(), &wallet.Config{
|
|
|
|
WalletDir: blsWalletPath,
|
|
|
|
WalletPassword: string(walletPassword),
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
log.Error("Open BLS wallet failed", "err", err)
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
log.Info("Open BLS wallet successfully")
|
|
|
|
|
|
|
|
km, err := w.InitializeKeymanager(context.Background(), iface.InitKeymanagerConfig{ListenForChanges: false})
|
|
|
|
if err != nil {
|
|
|
|
log.Error("Initialize key manager failed", "err", err)
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
log.Info("Initialized keymanager successfully")
|
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), voteSignerTimeout)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
pubKeys, err := km.FetchValidatingPublicKeys(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "could not fetch validating public keys")
|
|
|
|
}
|
|
|
|
|
|
|
|
return &VoteSigner{
|
|
|
|
km: &km,
|
2023-09-08 10:20:07 +08:00
|
|
|
PubKey: pubKeys[0],
|
2023-04-10 18:36:45 +08:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (signer *VoteSigner) SignVote(vote *types.VoteEnvelope) error {
|
|
|
|
// Sign the vote, fetch the first pubKey as validator's bls public key.
|
2023-09-08 10:20:07 +08:00
|
|
|
pubKey := signer.PubKey
|
2023-04-10 18:36:45 +08:00
|
|
|
blsPubKey, err := bls.PublicKeyFromBytes(pubKey[:])
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "convert public key from bytes to bls failed")
|
|
|
|
}
|
|
|
|
|
|
|
|
voteDataHash := vote.Data.Hash()
|
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), voteSignerTimeout)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
signature, err := (*signer.km).Sign(ctx, &validatorpb.SignRequest{
|
|
|
|
PublicKey: pubKey[:],
|
|
|
|
SigningRoot: voteDataHash[:],
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
copy(vote.VoteAddress[:], blsPubKey.Marshal()[:])
|
|
|
|
copy(vote.Signature[:], signature.Marshal()[:])
|
|
|
|
return nil
|
|
|
|
}
|