Skip to content

Commit

Permalink
Feature/ch7211: VRF jpv2 crud (#4422)
Browse files Browse the repository at this point in the history
VRF jpv2 crud
  • Loading branch information
connorwstein authored May 19, 2021
1 parent 292b42f commit 186289a
Show file tree
Hide file tree
Showing 39 changed files with 969 additions and 547 deletions.
18 changes: 9 additions & 9 deletions core/adapters/random.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import (
"fmt"

"github.com/smartcontractkit/chainlink/core/internal/gethwrappers/generated/solidity_vrf_coordinator_interface"
"github.com/smartcontractkit/chainlink/core/services/signatures/secp256k1"
"github.com/smartcontractkit/chainlink/core/services/vrf"
"github.com/smartcontractkit/chainlink/core/store"
"github.com/smartcontractkit/chainlink/core/store/models"
"github.com/smartcontractkit/chainlink/core/store/models/vrfkey"
"github.com/smartcontractkit/chainlink/core/utils"

"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -102,20 +102,20 @@ func (ra *Random) Perform(input models.RunInput, store *store.Store) models.RunO
// getInputs parses the JSON input for the values needed by the random adapter,
// or returns an error.
func getInputs(ra *Random, input models.RunInput, store *store.Store) (
vrfkey.PublicKey, vrf.PreSeedData, error) {
secp256k1.PublicKey, vrf.PreSeedData, error) {
key, err := getKey(ra, input)
if err != nil {
return vrfkey.PublicKey{}, vrf.PreSeedData{}, errors.Wrapf(err,
return secp256k1.PublicKey{}, vrf.PreSeedData{}, errors.Wrapf(err,
"bad key for vrf task")
}
preSeed, err := getPreSeed(input)
if err != nil {
return vrfkey.PublicKey{}, vrf.PreSeedData{}, errors.Wrap(err,
return secp256k1.PublicKey{}, vrf.PreSeedData{}, errors.Wrap(err,
"bad seed for vrf task")
}
block, err := getBlockData(input)
if err != nil {
return vrfkey.PublicKey{}, vrf.PreSeedData{}, err
return secp256k1.PublicKey{}, vrf.PreSeedData{}, err
}
s := vrf.PreSeedData{PreSeed: preSeed, BlockHash: block.hash, BlockNum: block.num}
return key, s, nil
Expand Down Expand Up @@ -175,7 +175,7 @@ func getPreSeed(input models.RunInput) (vrf.Seed, error) {
return *rv, nil
}

func checkKeyHash(key vrfkey.PublicKey, inputKeyHash []byte) error {
func checkKeyHash(key secp256k1.PublicKey, inputKeyHash []byte) error {
keyHash, err := key.Hash()
if err != nil {
return errors.Wrapf(err, "could not compute %v' hash", key)
Expand All @@ -188,11 +188,11 @@ func checkKeyHash(key vrfkey.PublicKey, inputKeyHash []byte) error {
return nil
}

var failedKey = vrfkey.PublicKey{}
var failedKey = secp256k1.PublicKey{}

// getKey returns the public key for the VRF, or an error.
func getKey(ra *Random, input models.RunInput) (vrfkey.PublicKey, error) {
key, err := vrfkey.NewPublicKeyFromHex(ra.PublicKey)
func getKey(ra *Random, input models.RunInput) (secp256k1.PublicKey, error) {
key, err := secp256k1.NewPublicKeyFromHex(ra.PublicKey)
if err != nil {
return failedKey, errors.Wrapf(err, "could not parse %v as public key",
ra.PublicKey)
Expand Down
3 changes: 1 addition & 2 deletions core/adapters/random_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (

"github.com/smartcontractkit/chainlink/core/adapters"
"github.com/smartcontractkit/chainlink/core/internal/cltest"
tvrf "github.com/smartcontractkit/chainlink/core/internal/cltest/vrf"
"github.com/smartcontractkit/chainlink/core/internal/gethwrappers/generated/solidity_vrf_coordinator_interface"
"github.com/smartcontractkit/chainlink/core/internal/mocks"
"github.com/smartcontractkit/chainlink/core/services/eth"
Expand Down Expand Up @@ -55,7 +54,7 @@ func TestRandom_Perform(t *testing.T) {
vrf.OnChainResponseLength, "wrong response length")
response, err := vrf.UnmarshalProofResponse(onChainResponse)
require.NoError(t, err, "random adapter produced bad proof response")
actualProof, err := response.CryptoProof(tvrf.SeedData(t, seed, hash, blockNum))
actualProof, err := response.CryptoProof(vrf.TestXXXSeedData(t, seed, hash, blockNum))
require.NoError(t, err, "could not extract proof from random adapter response")
expected := common.HexToHash(
"0x71a7c50918feaa753485ae039cb84ddd70c5c85f66b236138dea453a23d0f27e")
Expand Down
8 changes: 8 additions & 0 deletions core/cmd/jobs_commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,14 @@ func (p JobPresenter) FriendlyCreatedAt() string {
if p.KeeperSpec != nil {
return p.KeeperSpec.CreatedAt.Format(time.RFC3339)
}
case presenters.CronJobSpec:
if p.CronSpec != nil {
return p.CronSpec.CreatedAt.Format(time.RFC3339)
}
case presenters.VRFJobSpec:
if p.VRFSpec != nil {
return p.VRFSpec.CreatedAt.Format(time.RFC3339)
}
default:
return "unknown"
}
Expand Down
24 changes: 24 additions & 0 deletions core/cmd/jobs_commands_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,30 @@ func TestJob_FriendlyCreatedAt(t *testing.T) {
},
now.Format(time.RFC3339),
},
{
"gets the cron spec created at timestamp",
&cmd.JobPresenter{
JobResource: presenters.JobResource{
Type: presenters.CronJobSpec,
CronSpec: &presenters.CronSpec{
CreatedAt: now,
},
},
},
now.Format(time.RFC3339),
},
{
"gets the vrf spec created at timestamp",
&cmd.JobPresenter{
JobResource: presenters.JobResource{
Type: presenters.VRFJobSpec,
VRFSpec: &presenters.VRFSpec{
CreatedAt: now,
},
},
},
now.Format(time.RFC3339),
},
{
"gets the off chain reporting spec created at timestamp",
&cmd.JobPresenter{
Expand Down
21 changes: 11 additions & 10 deletions core/cmd/local_client_vrf.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ import (
"os"
"time"

"github.com/smartcontractkit/chainlink/core/services/signatures/secp256k1"
"github.com/smartcontractkit/chainlink/core/services/vrf"

"github.com/pkg/errors"
"github.com/smartcontractkit/chainlink/core/logger"
"github.com/smartcontractkit/chainlink/core/store"
"github.com/smartcontractkit/chainlink/core/store/dialects"
"github.com/smartcontractkit/chainlink/core/store/models/vrfkey"
"github.com/smartcontractkit/chainlink/core/utils"
"github.com/urfave/cli"
)
Expand Down Expand Up @@ -193,7 +194,7 @@ func (cli *Client) ImportVRFKey(c *cli.Context) error {
}
vrfKeyStore := app.GetStore().VRFKeyStore
if err := vrfKeyStore.Import(keyjson, string(password)); err != nil {
if err == store.MatchingVRFKeyError {
if err == vrf.MatchingVRFKeyError {
fmt.Println(`The database already has an entry for that public key.`)
var key struct{ PublicKey string }
if e := json.Unmarshal(keyjson, &key); e != nil {
Expand Down Expand Up @@ -243,7 +244,7 @@ func (cli *Client) ExportVRFKey(c *cli.Context) error {
}

// getKeys retrieves the keys for an ExportVRFKey request
func getKeys(cli *Client, c *cli.Context) (*vrfkey.EncryptedVRFKey, error) {
func getKeys(cli *Client, c *cli.Context) (*vrf.EncryptedVRFKey, error) {
publicKey, err := getPublicKey(c)
if err != nil {
return nil, err
Expand Down Expand Up @@ -284,14 +285,14 @@ func (cli *Client) DeleteVRFKey(c *cli.Context) error {
hardDelete := c.Bool("hard")
if hardDelete {
if err := vrfKeyStore.Delete(publicKey); err != nil {
if err == store.AttemptToDeleteNonExistentKeyFromDB {
if err == vrf.AttemptToDeleteNonExistentKeyFromDB {
fmt.Printf("There is already no entry in the DB for %s\n", publicKey)
}
return err
}
} else {
if err := vrfKeyStore.Archive(publicKey); err != nil {
if err == store.AttemptToDeleteNonExistentKeyFromDB {
if err == vrf.AttemptToDeleteNonExistentKeyFromDB {
fmt.Printf("There is already no entry in the DB for %s\n", publicKey)
}
return err
Expand All @@ -300,13 +301,13 @@ func (cli *Client) DeleteVRFKey(c *cli.Context) error {
return nil
}

func getPublicKey(c *cli.Context) (vrfkey.PublicKey, error) {
func getPublicKey(c *cli.Context) (secp256k1.PublicKey, error) {
if c.String("publicKey") == "" {
return vrfkey.PublicKey{}, fmt.Errorf("must specify public key")
return secp256k1.PublicKey{}, fmt.Errorf("must specify public key")
}
publicKey, err := vrfkey.NewPublicKeyFromHex(c.String("publicKey"))
publicKey, err := secp256k1.NewPublicKeyFromHex(c.String("publicKey"))
if err != nil {
return vrfkey.PublicKey{}, errors.Wrap(err, "failed to parse public key")
return secp256k1.PublicKey{}, errors.Wrap(err, "failed to parse public key")
}
return publicKey, nil
}
Expand Down
12 changes: 7 additions & 5 deletions core/cmd/local_client_vrf_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ import (
"testing"
"time"

"github.com/smartcontractkit/chainlink/core/services/signatures/secp256k1"
"github.com/smartcontractkit/chainlink/core/services/vrf"

"github.com/smartcontractkit/chainlink/core/cmd"
"github.com/smartcontractkit/chainlink/core/internal/cltest"
"github.com/smartcontractkit/chainlink/core/internal/mocks"
"github.com/smartcontractkit/chainlink/core/store"
"github.com/smartcontractkit/chainlink/core/store/models/vrfkey"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/urfave/cli"
Expand Down Expand Up @@ -174,11 +176,11 @@ func TestLocalClientVRF_ImportVRFKey(t *testing.T) {
c = cli.NewContext(nil, set, nil)
require.NoError(t, client.ImportVRFKey(c))

keys := []vrfkey.EncryptedVRFKey{}
keys := []vrf.EncryptedVRFKey{}
app.GetStore().DB.Find(&keys)
assert.Len(t, keys, 1)

pubKey, err := vrfkey.NewPublicKeyFromHex(vrfPublicKey)
pubKey, err := secp256k1.NewPublicKeyFromHex(vrfPublicKey)
require.NoError(t, err)
assert.Equal(t, pubKey, keys[0].PublicKey)

Expand Down Expand Up @@ -280,12 +282,12 @@ func TestLocalClientVRF_DeleteVRFKey(t *testing.T) {
c = cli.NewContext(nil, set, nil)
require.NoError(t, client.DeleteVRFKey(c))

keys := []vrfkey.EncryptedVRFKey{}
keys := []vrf.EncryptedVRFKey{}
app.GetStore().DB.Find(&keys)
assert.Len(t, keys, 0)
}

func requireVRFKeysCount(t *testing.T, store *store.Store, length int) []*vrfkey.PublicKey {
func requireVRFKeysCount(t *testing.T, store *store.Store, length int) []*secp256k1.PublicKey {
keys, err := store.VRFKeyStore.ListKeys()
require.NoError(t, err)
require.Len(t, keys, length)
Expand Down
9 changes: 6 additions & 3 deletions core/internal/cltest/vrf.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@ import (
"strings"
"testing"

"github.com/smartcontractkit/chainlink/core/services/signatures/secp256k1"
"github.com/smartcontractkit/chainlink/core/services/vrf"
"github.com/smartcontractkit/chainlink/core/utils"

"github.com/stretchr/testify/require"

strpkg "github.com/smartcontractkit/chainlink/core/store"
"github.com/smartcontractkit/chainlink/core/store/models/vrfkey"
)

// StoredVRFKey creates a VRFKeyStore on store, imports a known VRF key into it,
// and returns the corresponding public key.
func StoredVRFKey(t *testing.T, store *strpkg.Store) *vrfkey.PublicKey {
store.VRFKeyStore = strpkg.NewVRFKeyStore(store)
func StoredVRFKey(t *testing.T, store *strpkg.Store) *secp256k1.PublicKey {
store.VRFKeyStore = vrf.NewVRFKeyStore(vrf.NewORM(store.DB), utils.GetScryptParams(store.Config))
keyFile, err := ioutil.ReadFile("../../tools/clroot/vrfkey.json")
require.NoError(t, err)
rawPassword, err := ioutil.ReadFile("../../tools/clroot/password.txt")
Expand Down
24 changes: 0 additions & 24 deletions core/internal/cltest/vrf/vrf.go

This file was deleted.

3 changes: 3 additions & 0 deletions core/services/chainlink/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
"syscall"
"time"

"github.com/smartcontractkit/chainlink/core/services/vrf"

"github.com/pkg/errors"
"github.com/smartcontractkit/chainlink/core/services/fluxmonitorv2"
"github.com/smartcontractkit/chainlink/core/services/gasupdater"
Expand Down Expand Up @@ -240,6 +242,7 @@ func NewApplication(config *orm.Config, ethClient eth.Client, advisoryLocker pos
config,
),
job.Keeper: keeper.NewDelegate(store.DB, jobORM, pipelineRunner, store.EthClient, headBroadcaster, logBroadcaster, config),
job.VRF: vrf.NewDelegate(vrf.NewORM(store.DB), pipelineRunner, pipelineORM),
}
)

Expand Down
14 changes: 14 additions & 0 deletions core/services/job/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"strconv"
"time"

"github.com/smartcontractkit/chainlink/core/services/signatures/secp256k1"

"github.com/ethereum/go-ethereum/common"
"github.com/lib/pq"
"github.com/smartcontractkit/chainlink/core/assets"
Expand All @@ -21,6 +23,7 @@ const (
FluxMonitor Type = "fluxmonitor"
OffchainReporting Type = "offchainreporting"
Keeper Type = "keeper"
VRF Type = "vrf"
)

type Job struct {
Expand All @@ -35,6 +38,8 @@ type Job struct {
FluxMonitorSpec *FluxMonitorSpec
KeeperSpecID *int32
KeeperSpec *KeeperSpec
VRFSpecID *int32
VRFSpec *VRFSpec
PipelineSpecID int32
PipelineSpec *pipeline.Spec
JobSpecErrors []SpecError `gorm:"foreignKey:JobID"`
Expand Down Expand Up @@ -210,3 +215,12 @@ type KeeperSpec struct {
CreatedAt time.Time `toml:"-"`
UpdatedAt time.Time `toml:"-"`
}

type VRFSpec struct {
ID int32
CoordinatorAddress models.EIP55Address `toml:"coordinatorAddress"`
PublicKey secp256k1.PublicKey `toml:"publicKey"`
Confirmations uint32 `toml:"confirmations"`
CreatedAt time.Time `toml:"-"`
UpdatedAt time.Time `toml:"-"`
}
Loading

0 comments on commit 186289a

Please sign in to comment.