mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-30 18:25:19 +00:00
195 lines
5.2 KiB
Go
195 lines
5.2 KiB
Go
package vrf
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/subtle"
|
|
"fmt"
|
|
|
|
errorsmod "cosmossdk.io/errors"
|
|
vrfalgo "github.com/coniks-sys/coniks-go/crypto/vrf"
|
|
"github.com/cosmos/cosmos-sdk/codec"
|
|
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
|
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
|
|
"github.com/ethereum/go-ethereum/common"
|
|
tmcrypto "github.com/tendermint/tendermint/crypto"
|
|
)
|
|
|
|
const (
|
|
// PrivKeySize defines the size of the PrivKey bytes
|
|
PrivKeySize = 64
|
|
// PubKeySize defines the size of the PubKey bytes
|
|
PubKeySize = 32
|
|
// KeyType is the string constant for the vrf algorithm
|
|
KeyType = "vrf"
|
|
)
|
|
|
|
// Amino encoding names
|
|
const (
|
|
// PrivKeyName defines the amino encoding name for the vrf private key
|
|
PrivKeyName = "vrf/PrivKey"
|
|
// PubKeyName defines the amino encoding name for the vrf public key
|
|
PubKeyName = "vrf/PubKey"
|
|
)
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// vrf Private Key
|
|
|
|
var (
|
|
_ cryptotypes.PrivKey = &PrivKey{}
|
|
_ codec.AminoMarshaler = &PrivKey{}
|
|
)
|
|
|
|
// GenerateKey generates a new random private key. It returns an error upon
|
|
// failure.
|
|
func GenerateKey() (*PrivKey, error) {
|
|
priv, err := vrfalgo.GenerateKey(nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &PrivKey{
|
|
Key: priv,
|
|
}, nil
|
|
}
|
|
|
|
func (privKey PrivKey) getVrfPrivateKey() vrfalgo.PrivateKey {
|
|
return vrfalgo.PrivateKey(privKey.Key)
|
|
}
|
|
|
|
// Bytes returns the byte representation of the Private Key.
|
|
func (privKey PrivKey) Bytes() []byte {
|
|
bz := make([]byte, len(privKey.Key))
|
|
copy(bz, privKey.Key)
|
|
|
|
return bz
|
|
}
|
|
|
|
// PubKey returns the private key's public key. If the privkey is not valid
|
|
// it returns a nil value.
|
|
func (privKey PrivKey) PubKey() cryptotypes.PubKey {
|
|
pk, _ := vrfalgo.PrivateKey(privKey.Key).Public()
|
|
|
|
return &PubKey{
|
|
Key: pk,
|
|
}
|
|
}
|
|
|
|
// Equals returns true if two private keys are equal and false otherwise.
|
|
func (privKey PrivKey) Equals(other cryptotypes.LedgerPrivKey) bool {
|
|
return privKey.Type() == other.Type() && subtle.ConstantTimeCompare(privKey.Bytes(), other.Bytes()) == 1
|
|
}
|
|
|
|
// Type returns vrf
|
|
func (privKey PrivKey) Type() string {
|
|
return KeyType
|
|
}
|
|
|
|
// Compute generates the vrf value for the byte slice m using the
|
|
// underlying private key sk.
|
|
func (privKey PrivKey) Sign(digestBz []byte) ([]byte, error) {
|
|
sk := privKey.getVrfPrivateKey()
|
|
|
|
return sk.Compute(digestBz), nil
|
|
}
|
|
|
|
// MarshalAmino overrides Amino binary marshaling.
|
|
func (privKey PrivKey) MarshalAmino() ([]byte, error) {
|
|
return privKey.Key, nil
|
|
}
|
|
|
|
// UnmarshalAmino overrides Amino binary marshaling.
|
|
func (privKey *PrivKey) UnmarshalAmino(bz []byte) error {
|
|
if len(bz) != PrivKeySize {
|
|
return fmt.Errorf("invalid privkey size, expected %d got %d", PrivKeySize, len(bz))
|
|
}
|
|
privKey.Key = bz
|
|
|
|
return nil
|
|
}
|
|
|
|
// MarshalAminoJSON overrides Amino JSON marshaling.
|
|
func (privKey PrivKey) MarshalAminoJSON() ([]byte, error) {
|
|
// When we marshal to Amino JSON, we don't marshal the "key" field itself,
|
|
// just its contents (i.e. the key bytes).
|
|
return privKey.MarshalAmino()
|
|
}
|
|
|
|
// UnmarshalAminoJSON overrides Amino JSON marshaling.
|
|
func (privKey *PrivKey) UnmarshalAminoJSON(bz []byte) error {
|
|
return privKey.UnmarshalAmino(bz)
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// vrf Public Key
|
|
|
|
var (
|
|
_ cryptotypes.PubKey = &PubKey{}
|
|
_ codec.AminoMarshaler = &PubKey{}
|
|
)
|
|
|
|
// func (pubKey PubKey) getVrfPublicKey() vrfalgo.PublicKey {
|
|
// return vrfalgo.PublicKey(pubKey.Key)
|
|
// }
|
|
|
|
// Address returns the address of the ECDSA public key.
|
|
// The function will return an empty address if the public key is invalid.
|
|
func (pubKey PubKey) Address() tmcrypto.Address {
|
|
return tmcrypto.Address(common.BytesToAddress(pubKey.Key).Bytes())
|
|
}
|
|
|
|
// Bytes returns the raw bytes of the ECDSA public key.
|
|
func (pubKey PubKey) Bytes() []byte {
|
|
bz := make([]byte, len(pubKey.Key))
|
|
copy(bz, pubKey.Key)
|
|
|
|
return bz
|
|
}
|
|
|
|
// String implements the fmt.Stringer interface.
|
|
func (pubKey PubKey) String() string {
|
|
return fmt.Sprintf("vrf{%X}", pubKey.Key)
|
|
}
|
|
|
|
// Type returns vrf
|
|
func (pubKey PubKey) Type() string {
|
|
return KeyType
|
|
}
|
|
|
|
// Equals returns true if the pubkey type is the same and their bytes are deeply equal.
|
|
func (pubKey PubKey) Equals(other cryptotypes.PubKey) bool {
|
|
return pubKey.Type() == other.Type() && bytes.Equal(pubKey.Bytes(), other.Bytes())
|
|
}
|
|
|
|
// Verify returns true iff vrf=Compute(m) for the sk that
|
|
// corresponds to pk.
|
|
func (pubKey PubKey) VerifySignature(msg, sig []byte) bool {
|
|
panic("not implement")
|
|
}
|
|
|
|
// MarshalAmino overrides Amino binary marshaling.
|
|
func (pubKey PubKey) MarshalAmino() ([]byte, error) {
|
|
return pubKey.Key, nil
|
|
}
|
|
|
|
// UnmarshalAmino overrides Amino binary marshaling.
|
|
func (pubKey *PubKey) UnmarshalAmino(bz []byte) error {
|
|
if len(bz) != PubKeySize {
|
|
return errorsmod.Wrapf(errortypes.ErrInvalidPubKey, "invalid pubkey size, expected %d, got %d", PubKeySize, len(bz))
|
|
}
|
|
pubKey.Key = bz
|
|
|
|
return nil
|
|
}
|
|
|
|
// MarshalAminoJSON overrides Amino JSON marshaling.
|
|
func (pubKey PubKey) MarshalAminoJSON() ([]byte, error) {
|
|
// When we marshal to Amino JSON, we don't marshal the "key" field itself,
|
|
// just its contents (i.e. the key bytes).
|
|
return pubKey.MarshalAmino()
|
|
}
|
|
|
|
// UnmarshalAminoJSON overrides Amino JSON marshaling.
|
|
func (pubKey *PubKey) UnmarshalAminoJSON(bz []byte) error {
|
|
return pubKey.UnmarshalAmino(bz)
|
|
}
|