86 lines
2.2 KiB
Go
86 lines
2.2 KiB
Go
package consensus
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/Secured-Finance/dione/types"
|
|
"github.com/filecoin-project/go-address"
|
|
"github.com/filecoin-project/go-state-types/crypto"
|
|
"github.com/filecoin-project/lotus/lib/sigs"
|
|
"go.opencensus.io/trace"
|
|
"golang.org/x/xerrors"
|
|
)
|
|
|
|
type MinerWallet interface {
|
|
WalletSign(context.Context, address.Address, []byte) (*crypto.Signature, error)
|
|
}
|
|
|
|
type MinerBase struct {
|
|
MinerStake types.BigInt
|
|
NetworkStake types.BigInt
|
|
WorkerKey address.Address
|
|
PrevBeaconEntry types.BeaconEntry
|
|
BeaconEntries []types.BeaconEntry
|
|
}
|
|
|
|
type SignFunc func(context.Context, address.Address, []byte) (*crypto.Signature, error)
|
|
|
|
func ComputeVRF(ctx context.Context, sign SignFunc, worker address.Address, sigInput []byte) ([]byte, error) {
|
|
sig, err := sign(ctx, worker, sigInput)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if sig.Type != crypto.SigTypeBLS {
|
|
return nil, fmt.Errorf("miner worker address was not a BLS key")
|
|
}
|
|
|
|
return sig.Data, nil
|
|
}
|
|
|
|
func VerifyVRF(ctx context.Context, worker address.Address, vrfBase, vrfproof []byte) error {
|
|
_, span := trace.StartSpan(ctx, "VerifyVRF")
|
|
defer span.End()
|
|
|
|
sig := &crypto.Signature{
|
|
Type: crypto.SigTypeBLS,
|
|
Data: vrfproof,
|
|
}
|
|
|
|
if err := sigs.Verify(sig, worker, vrfBase); err != nil {
|
|
return xerrors.Errorf("vrf was invalid: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func IsRoundWinner(ctx context.Context, round types.TaskEpoch,
|
|
worker address.Address, brand types.BeaconEntry, mbi *MinerBase, a MinerWallet) (*types.ElectionProof, error) {
|
|
|
|
buf := new(bytes.Buffer)
|
|
if err := worker.MarshalCBOR(buf); err != nil {
|
|
return nil, xerrors.Errorf("failed to cbor marshal address: %w", err)
|
|
}
|
|
|
|
electionRand, err := DrawRandomness(brand.Data, crypto.DomainSeparationTag_ElectionProofProduction, round, buf.Bytes())
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("failed to draw randomness: %w", err)
|
|
}
|
|
|
|
vrfout, err := ComputeVRF(ctx, a.WalletSign, mbi.WorkerKey, electionRand)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("failed to compute VRF: %w", err)
|
|
}
|
|
|
|
ep := &types.ElectionProof{VRFProof: vrfout}
|
|
j := ep.ComputeWinCount(mbi.MinerStake, mbi.NetworkStake)
|
|
ep.WinCount = j
|
|
if j < 1 {
|
|
return nil, nil
|
|
}
|
|
|
|
return ep, nil
|
|
}
|