Skip to content

Commit

Permalink
Add version control
Browse files Browse the repository at this point in the history
  • Loading branch information
0Tech committed Jul 5, 2023
1 parent faf0108 commit 3f5d239
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 39 deletions.
113 changes: 81 additions & 32 deletions crypto/ed25519/migration.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,78 +10,127 @@ import (
)

// vrf w/o prove
type vrfNoProve interface {
type VrfNoProve interface {
Verify(pubKey ed25519.PublicKey, proof []byte, message []byte) (bool, []byte)
ProofToHash(proof []byte) ([]byte, error)
ValidateProof(proof []byte) error
}

var vrfs = map[int]vrfNoProve{
voivrf.ProofSize: &voi{},
r2vrf.ProofSize: &r2{},
var globalVrf = NewVersionedVrfNoProve()

func VRFVerify(pubKey ed25519.PublicKey, proof []byte, message []byte) (bool, []byte) {
return globalVrf.Verify(pubKey, proof, message)
}

func ProofToHash(proof []byte) ([]byte, error) {
return globalVrf.ProofToHash(proof)
}

// ValidateProof returns an error if the proof is not empty, but its
// size != vrf.ProofSize.
func ValidateProof(h []byte) error {
if len(h) > 0 {
if err := globalVrf.ValidateProof(h); err != nil {
return fmt.Errorf("expected size to be %d bytes, got %d bytes",
voivrf.ProofSize,
len(h),
)
}
}
return nil
}

func getVrf(proof []byte) (vrfNoProve, error) {
// versioned vrf
var _ VrfNoProve = (*versionedVrfNoProve)(nil)

type versionedVrfNoProve struct {
version int
}

func NewVersionedVrfNoProve() VrfNoProve {
return &versionedVrfNoProve{}
}

func (v versionedVrfNoProve) getVrf(proof []byte) (VrfNoProve, error) {
vrfs := map[int]VrfNoProve{
0: &r2VrfNoProve{},
1: &voiVrfNoProve{},
}
proofSizeToVersion := map[int]int{
r2vrf.ProofSize: 0,
voivrf.ProofSize: 1,
}

proofSize := len(proof)
if vrf, exists := vrfs[proofSize]; exists {
return vrf, nil
if version, exists := proofSizeToVersion[proofSize]; exists && version >= v.version {
v.version = version

Check failure on line 66 in crypto/ed25519/migration.go

View workflow job for this annotation

GitHub Actions / golangci-lint

SA4005: ineffective assignment to field versionedVrfNoProve.version (staticcheck)
return vrfs[version], nil
}
return nil, fmt.Errorf("invalid proof size: %d", proofSize)
}

func VRFVerify(pubKey ed25519.PublicKey, proof []byte, message []byte) (bool, []byte) {
vrf, err := getVrf(proof)
func (v versionedVrfNoProve) Verify(pubKey ed25519.PublicKey, proof []byte, message []byte) (bool, []byte) {
vrf, err := v.getVrf(proof)
if err != nil {
return false, nil
}

return vrf.Verify(pubKey, proof, message)
}

func ProofToHash(proof []byte) ([]byte, error) {
vrf, err := getVrf(proof)
func (v versionedVrfNoProve) ProofToHash(proof []byte) ([]byte, error) {
vrf, err := v.getVrf(proof)
if err != nil {
return nil, err
}

return vrf.ProofToHash(proof)
}

// ValidateProof returns an error if the proof is not empty, but its
// size != vrf.ProofSize.
func ValidateProof(h []byte) error {
if len(h) > 0 {
if _, err := getVrf(h); err != nil {
return fmt.Errorf("expected size to be %d bytes, got %d bytes",
voivrf.ProofSize,
len(h),
)
}
func (v versionedVrfNoProve) ValidateProof(proof []byte) error {
vrf, err := v.getVrf(proof)
if err != nil {
return err
}
return nil
return vrf.ValidateProof(proof)
}

// github.com/oasisprotocol/curve25519-voi
var _ vrfNoProve = (*voi)(nil)
var _ VrfNoProve = (*voiVrfNoProve)(nil)

type voi struct{}
type voiVrfNoProve struct{}

func (_ voi) Verify(pubKey ed25519.PublicKey, proof []byte, message []byte) (bool, []byte) {
func (_ voiVrfNoProve) Verify(pubKey ed25519.PublicKey, proof []byte, message []byte) (bool, []byte) {
return voivrf.Verify(pubKey, proof, message)
}

func (_ voi) ProofToHash(proof []byte) ([]byte, error) {
func (_ voiVrfNoProve) ProofToHash(proof []byte) ([]byte, error) {
return voivrf.ProofToHash(proof)
}

func (_ voiVrfNoProve) ValidateProof(proof []byte) error {
proofSize := len(proof)
if proofSize != voivrf.ProofSize {
return fmt.Errorf("invalid proof size: %d", proofSize)
}
return nil
}

// github.com/r2ishiguro/vrf
var _ vrfNoProve = (*r2)(nil)
var _ VrfNoProve = (*r2VrfNoProve)(nil)

type r2 struct{}
type r2VrfNoProve struct{}

func (_ r2) Verify(pubKey ed25519.PublicKey, proof []byte, message []byte) (bool, []byte) {
func (_ r2VrfNoProve) Verify(pubKey ed25519.PublicKey, proof []byte, message []byte) (bool, []byte) {
return r2vrf.Verify(pubKey, proof, message)
}

func (_ r2) ProofToHash(proof []byte) ([]byte, error) {
func (_ r2VrfNoProve) ProofToHash(proof []byte) ([]byte, error) {
return r2vrf.ProofToHash(proof)
}

func (_ r2VrfNoProve) ValidateProof(proof []byte) error {
proofSize := len(proof)
if proofSize != r2vrf.ProofSize {
return fmt.Errorf("invalid proof size: %d", proofSize)
}
return nil
}
40 changes: 33 additions & 7 deletions crypto/ed25519/migration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ import (
r2vrf "github.com/Finschia/ostracon/crypto/ed25519/internal/r2ishiguro"
)

func TestVRFVerify(t *testing.T) {
func TestVerify(t *testing.T) {
pubkey, message := []byte("pubkey"), []byte("message")
valid, _ := ed25519.VRFVerify(pubkey, make([]byte, 1), message)
require.False(t, valid)

cases := map[string]struct {
proof []byte
valid bool
Expand All @@ -29,14 +33,16 @@ func TestVRFVerify(t *testing.T) {

for name, tc := range cases {
t.Run(name, func(t *testing.T) {
pubkey, message := []byte("pubkey"), []byte("message")
valid, _ := ed25519.VRFVerify(pubkey, tc.proof, message)
valid, _ := ed25519.NewVersionedVrfNoProve().Verify(pubkey, tc.proof, message)
require.Equal(t, tc.valid, valid)
})
}
}

func TestProofToHash(t *testing.T) {
_, err := ed25519.ProofToHash(make([]byte, 1))
require.Error(t, err)

cases := map[string]struct {
proof []byte
valid bool
Expand All @@ -55,7 +61,7 @@ func TestProofToHash(t *testing.T) {

for name, tc := range cases {
t.Run(name, func(t *testing.T) {
_, err := ed25519.ProofToHash(tc.proof)
_, err := ed25519.NewVersionedVrfNoProve().ProofToHash(tc.proof)
if !tc.valid {
require.Error(t, err)
return
Expand All @@ -66,14 +72,19 @@ func TestProofToHash(t *testing.T) {
}

func TestValidateProof(t *testing.T) {
err := ed25519.ValidateProof(make([]byte, 1))
require.Error(t, err)
err = ed25519.ValidateProof(make([]byte, 0))
require.NoError(t, err)

cases := map[string]struct {
proof []byte
valid bool
}{
"invalid": {
"invalid format": {
proof: make([]byte, 1),
},
"voi proof": {
"voi invalid proof": {
proof: make([]byte, voivrf.ProofSize),
valid: true,
},
Expand All @@ -85,7 +96,7 @@ func TestValidateProof(t *testing.T) {

for name, tc := range cases {
t.Run(name, func(t *testing.T) {
err := ed25519.ValidateProof(tc.proof)
err := ed25519.NewVersionedVrfNoProve().ValidateProof(tc.proof)
if !tc.valid {
require.Error(t, err)
return
Expand All @@ -94,3 +105,18 @@ func TestValidateProof(t *testing.T) {
})
}
}

func TestVersionControl(t *testing.T) {
vrf := ed25519.NewVersionedVrfNoProve()

// old one is valid for now
oldProof := make([]byte, r2vrf.ProofSize)
require.NoError(t, vrf.ValidateProof(oldProof))

// new one is valid
newProof := make([]byte, voivrf.ProofSize)
require.NoError(t, vrf.ValidateProof(newProof))

// old one is not valid anymore
require.NoError(t, vrf.ValidateProof(oldProof))
}

0 comments on commit 3f5d239

Please sign in to comment.