bsc/core/vote/vote_signer.go

112 lines
2.9 KiB
Go

package vote
import (
"bytes"
"context"
"fmt"
"io/ioutil"
"time"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v4/crypto/bls"
validatorpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1/validator-client"
"github.com/prysmaticlabs/prysm/v4/validator/accounts/iface"
"github.com/prysmaticlabs/prysm/v4/validator/accounts/wallet"
"github.com/prysmaticlabs/prysm/v4/validator/keymanager"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
)
const (
voteSignerTimeout = time.Second * 5
)
var votesSigningErrorCounter = metrics.NewRegisteredCounter("votesSigner/error", nil)
type VoteSigner struct {
km *keymanager.IKeymanager
pubKey [48]byte
}
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.")
return nil, fmt.Errorf("BLS wallet did not exists.")
}
walletPassword, err := ioutil.ReadFile(blsPasswordPath)
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,
pubKey: pubKeys[0],
}, nil
}
func (signer *VoteSigner) SignVote(vote *types.VoteEnvelope) error {
// Sign the vote, fetch the first pubKey as validator's bls public key.
pubKey := signer.pubKey
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
}
func (signer *VoteSigner) UsingKey(bLSPublicKey *types.BLSPublicKey) bool {
return bytes.Equal(signer.pubKey[:], bLSPublicKey[:])
}