2020-10-28 17:35:56 +00:00
|
|
|
package consensus
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
|
2020-11-12 14:18:30 +00:00
|
|
|
"github.com/libp2p/go-libp2p-core/peer"
|
|
|
|
|
2020-10-28 17:35:56 +00:00
|
|
|
"github.com/Secured-Finance/dione/types"
|
|
|
|
"github.com/filecoin-project/go-state-types/crypto"
|
|
|
|
"golang.org/x/xerrors"
|
|
|
|
)
|
|
|
|
|
2020-11-12 14:18:30 +00:00
|
|
|
type SignFunc func(context.Context, peer.ID, []byte) (*types.Signature, error)
|
2020-10-28 17:35:56 +00:00
|
|
|
|
2020-11-12 14:18:30 +00:00
|
|
|
func ComputeVRF(ctx context.Context, sign SignFunc, worker peer.ID, sigInput []byte) ([]byte, error) {
|
2020-10-28 17:35:56 +00:00
|
|
|
sig, err := sign(ctx, worker, sigInput)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2020-11-12 14:18:30 +00:00
|
|
|
if sig.Type != types.SigTypeEd25519 {
|
|
|
|
return nil, fmt.Errorf("miner worker address was not a Ed25519 key")
|
2020-10-28 17:35:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return sig.Data, nil
|
|
|
|
}
|
|
|
|
|
2020-11-12 14:18:30 +00:00
|
|
|
func VerifyVRF(ctx context.Context, worker peer.ID, vrfBase, vrfproof []byte) error {
|
|
|
|
pKey, err := worker.ExtractPublicKey()
|
|
|
|
if err != nil {
|
|
|
|
return xerrors.Errorf("failed to extract public key from worker address: %w", err)
|
2020-10-28 17:35:56 +00:00
|
|
|
}
|
|
|
|
|
2020-11-12 14:18:30 +00:00
|
|
|
valid, err := pKey.Verify(vrfBase, vrfproof)
|
|
|
|
if err != nil || !valid {
|
2020-10-28 17:35:56 +00:00
|
|
|
return xerrors.Errorf("vrf was invalid: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-11-14 00:03:47 +00:00
|
|
|
func IsRoundWinner(ctx context.Context, round types.DrandRound,
|
2020-11-14 00:32:50 +00:00
|
|
|
worker peer.ID, brand types.BeaconEntry, minerStake, networkStake types.BigInt, a WalletAPI) (*types.ElectionProof, error) {
|
2020-10-28 17:35:56 +00:00
|
|
|
|
2020-11-12 14:18:30 +00:00
|
|
|
buf, err := worker.MarshalBinary()
|
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("failed to marshal address: %w", err)
|
2020-10-28 17:35:56 +00:00
|
|
|
}
|
|
|
|
|
2020-11-12 14:18:30 +00:00
|
|
|
electionRand, err := DrawRandomness(brand.Data, crypto.DomainSeparationTag_ElectionProofProduction, round, buf)
|
2020-10-28 17:35:56 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("failed to draw randomness: %w", err)
|
|
|
|
}
|
|
|
|
|
2020-11-14 00:03:47 +00:00
|
|
|
vrfout, err := ComputeVRF(ctx, a.WalletSign, worker, electionRand)
|
2020-10-28 17:35:56 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("failed to compute VRF: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
ep := &types.ElectionProof{VRFProof: vrfout}
|
2020-11-14 00:03:47 +00:00
|
|
|
j := ep.ComputeWinCount(minerStake, networkStake)
|
2020-10-28 17:35:56 +00:00
|
|
|
ep.WinCount = j
|
|
|
|
if j < 1 {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return ep, nil
|
|
|
|
}
|