Skip to content

Commit

Permalink
refactor(workflows): hash is owner+URL
Browse files Browse the repository at this point in the history
  • Loading branch information
MStreet3 committed Nov 17, 2024
1 parent ac9040d commit 9bb688c
Show file tree
Hide file tree
Showing 10 changed files with 380 additions and 113 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package workflow_registry_syncer_test
import (
"context"
"crypto/rand"
"encoding/hex"
"encoding/json"
"testing"
"time"
Expand All @@ -18,6 +19,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/capabilities/testutils"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types"
"github.com/smartcontractkit/chainlink/v2/core/services/workflows/syncer"
"github.com/smartcontractkit/chainlink/v2/core/utils/crypto"
"github.com/smartcontractkit/chainlink/v2/core/utils/signalers"

"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -88,7 +90,11 @@ func Test_SecretsWorker(t *testing.T) {
require.NoError(t, err)

// Seed the DB
gotID, err := orm.Update(ctx, giveSecretsURL, giveContents)
hash, err := crypto.Keccak256(append(backendTH.ContractsOwner.From[:], []byte(giveSecretsURL)...))
require.NoError(t, err)
giveHash := hex.EncodeToString(hash)

gotID, err := orm.Create(ctx, giveSecretsURL, giveHash, giveContents)
require.NoError(t, err)

gotSecretsURL, err := orm.GetSecretsURLByID(ctx, gotID)
Expand All @@ -110,7 +116,7 @@ func Test_SecretsWorker(t *testing.T) {
)

// generate a log event
updateAuthorizedAddress(t, backendTH, wfRegistryC, donID, []common.Address{backendTH.ContractsOwner.From}, true)
updateAuthorizedAddress(t, backendTH, wfRegistryC, []common.Address{backendTH.ContractsOwner.From}, true)
updateAllowedDONs(t, backendTH, wfRegistryC, []uint32{1}, true)
registerWorkflow(t, backendTH, wfRegistryC, giveWorkflow)

Expand All @@ -137,12 +143,11 @@ func updateAuthorizedAddress(
t *testing.T,
th *testutils.EVMBackendTH,
wfRegC *workflow_registry_wrapper.WorkflowRegistry,
donID uint32,
addresses []common.Address,
allowed bool,
) {
t.Helper()
_, err := wfRegC.UpdateDONPermissions(th.ContractsOwner, donID, addresses, allowed)
_, err := wfRegC.UpdateAuthorizedAddresses(th.ContractsOwner, addresses, allowed)
require.NoError(t, err, "failed to update authorised addresses")
th.Backend.Commit()
th.Backend.Commit()
Expand Down
37 changes: 15 additions & 22 deletions core/services/workflows/syncer/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,21 @@ package syncer

import (
"context"
"encoding/hex"
"fmt"

"github.com/smartcontractkit/chainlink/v2/core/logger"
)

type handler interface {
Handle(ctx context.Context, event WorkflowRegistryEvent) error
}

// eventHandler is a map of event types to their respective handlers that implements Handler.
// eventHandler is a handler for WorkflowRegistryEvent events. Each event type has a corresponding
// method that handles the event.
type eventHandler struct {
lggr logger.Logger
orm ORM
fetcher FetcherFunc
}

// newEventHandler returns a new eventHandler with a map of event types to their respective handlers.
// newEventHandler returns a new eventHandler instance.
func newEventHandler(
lggr logger.Logger,
orm ORM,
Expand All @@ -40,16 +38,22 @@ func (h *eventHandler) Handle(ctx context.Context, event WorkflowRegistryEvent)
}
}

// Handle processes the ForceUpdateSecretsEvent by fetching the secrets from the URL for a given event
// and updating the local state.
// forceUpdateSecretsEvent handles the ForceUpdateSecretsEvent event type.
func (h *eventHandler) forceUpdateSecretsEvent(
ctx context.Context,
event WorkflowRegistryEvent,
) error {
// Get the URL of the secrets file from the event data
url, err := getSecretsURL(event)
data, ok := event.Data.(WorkflowRegistryForceUpdateSecretsRequestedV1)
if !ok {
return fmt.Errorf("invalid data type %T for event", event.Data)
}

hash := hex.EncodeToString(data.SecretsURLHash)

url, err := h.orm.GetSecretsURLByHash(ctx, hash)
if err != nil {
h.lggr.Errorf("failed to get URL hash", err)
h.lggr.Errorf("failed to get URL by hash %s : %w", hash, err)
return err
}

Expand All @@ -60,20 +64,9 @@ func (h *eventHandler) forceUpdateSecretsEvent(
}

// Update the secrets in the ORM
if _, err := h.orm.Update(ctx, url, string(secrets)); err != nil {
if _, err := h.orm.Update(ctx, hash, string(secrets)); err != nil {
return err
}

return nil
}

// getSecretsURL returns the URL of the secrets contents from the event data and fails
// if the URL is not found or is not a string.
func getSecretsURL(event WorkflowRegistryEvent) (string, error) {
data, ok := event.Data.(WorkflowRegistryForceUpdateSecretsRequestedV1)
if !ok {
return "", fmt.Errorf("invalid data type %T for event", event.Data)
}

return data.SecretsURL, nil
}
98 changes: 50 additions & 48 deletions core/services/workflows/syncer/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ package syncer

import (
"context"
"encoding/hex"
"testing"

"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/workflows/syncer/mocks"
"github.com/smartcontractkit/chainlink/v2/core/utils/crypto"
"github.com/smartcontractkit/chainlink/v2/core/utils/matches"

"github.com/stretchr/testify/assert"
Expand All @@ -19,19 +21,25 @@ func Test_Handler(t *testing.T) {
mockORM := mocks.NewORM(t)
ctx := testutils.Context(t)
giveURL := "https://original-url.com"
giveBytes, err := crypto.Keccak256([]byte(giveURL))
require.NoError(t, err)

giveHash := hex.EncodeToString(giveBytes)

giveEvent := WorkflowRegistryEvent{
EventType: ForceUpdateSecretsEvent,
Data: map[string]any{
"SecretsURL": giveURL,
Data: WorkflowRegistryForceUpdateSecretsRequestedV1{
SecretsURLHash: giveBytes,
},
}

fetcher := func(_ context.Context, _ string) ([]byte, error) {
return []byte("contents"), nil
}
mockORM.EXPECT().Update(matches.AnyContext, giveURL, "contents").Return(int64(1), nil)
mockORM.EXPECT().GetSecretsURLByHash(matches.AnyContext, giveHash).Return(giveURL, nil)
mockORM.EXPECT().Update(matches.AnyContext, giveHash, "contents").Return(int64(1), nil)
h := newEventHandler(lggr, mockORM, fetcher)
err := h.Handle(ctx, giveEvent)
err = h.Handle(ctx, giveEvent)
require.NoError(t, err)
})

Expand All @@ -54,12 +62,20 @@ func Test_Handler(t *testing.T) {
mockORM := mocks.NewORM(t)
ctx := testutils.Context(t)
h := newEventHandler(lggr, mockORM, nil)
err := h.Handle(ctx, WorkflowRegistryEvent{
giveURL := "https://original-url.com"
giveBytes, err := crypto.Keccak256([]byte(giveURL))
require.NoError(t, err)

giveHash := hex.EncodeToString(giveBytes)

giveEvent := WorkflowRegistryEvent{
EventType: ForceUpdateSecretsEvent,
Data: map[string]any{
"SecretsURL": assert.AnError,
Data: WorkflowRegistryForceUpdateSecretsRequestedV1{
SecretsURLHash: giveBytes,
},
})
}
mockORM.EXPECT().GetSecretsURLByHash(matches.AnyContext, giveHash).Return("", assert.AnError)
err = h.Handle(ctx, giveEvent)
require.Error(t, err)
require.ErrorContains(t, err, assert.AnError.Error())
})
Expand All @@ -69,17 +85,24 @@ func Test_Handler(t *testing.T) {
ctx := testutils.Context(t)
giveURL := "http://example.com"

giveBytes, err := crypto.Keccak256([]byte(giveURL))
require.NoError(t, err)

giveHash := hex.EncodeToString(giveBytes)

giveEvent := WorkflowRegistryEvent{
EventType: ForceUpdateSecretsEvent,
Data: WorkflowRegistryForceUpdateSecretsRequestedV1{
SecretsURLHash: giveBytes,
},
}

fetcher := func(_ context.Context, _ string) ([]byte, error) {
return nil, assert.AnError
}

mockORM.EXPECT().GetSecretsURLByHash(matches.AnyContext, giveHash).Return(giveURL, nil)
h := newEventHandler(lggr, mockORM, fetcher)
err := h.Handle(ctx, WorkflowRegistryEvent{
EventType: ForceUpdateSecretsEvent,
Data: map[string]any{
"SecretsURL": giveURL,
},
})
err = h.Handle(ctx, giveEvent)
require.Error(t, err)
require.ErrorIs(t, err, assert.AnError)
})
Expand All @@ -88,47 +111,26 @@ func Test_Handler(t *testing.T) {
mockORM := mocks.NewORM(t)
ctx := testutils.Context(t)
giveURL := "http://example.com"
giveBytes, err := crypto.Keccak256([]byte(giveURL))
require.NoError(t, err)

fetcher := func(_ context.Context, _ string) ([]byte, error) {
return []byte("contents"), nil
}
mockORM.EXPECT().Update(matches.AnyContext, giveURL, "contents").Return(0, assert.AnError)
h := newEventHandler(lggr, mockORM, fetcher)
err := h.Handle(ctx, WorkflowRegistryEvent{
EventType: ForceUpdateSecretsEvent,
Data: map[string]any{
"SecretsURL": giveURL,
},
})
require.Error(t, err)
require.ErrorIs(t, err, assert.AnError)
})
}

func Test_getURLHash(t *testing.T) {
t.Run("success", func(t *testing.T) {
giveURL := "http://example.com"
giveHash := hex.EncodeToString(giveBytes)

giveEvent := WorkflowRegistryEvent{
EventType: ForceUpdateSecretsEvent,
Data: WorkflowRegistryForceUpdateSecretsRequestedV1{
SecretsURL: giveURL,
SecretsURLHash: giveBytes,
},
}
gotURL, err := getSecretsURL(giveEvent)
require.NoError(t, err)

assert.Equal(t, giveURL, gotURL)
})

t.Run("fail with incorrect type", func(t *testing.T) {
giveURL := "http://example.com"

giveEvent := WorkflowRegistryEvent{
Data: map[string]any{
"SecretsURL": giveURL,
},
fetcher := func(_ context.Context, _ string) ([]byte, error) {
return []byte("contents"), nil
}
_, err := getSecretsURL(giveEvent)
mockORM.EXPECT().GetSecretsURLByHash(matches.AnyContext, giveHash).Return(giveURL, nil)
mockORM.EXPECT().Update(matches.AnyContext, giveHash, "contents").Return(0, assert.AnError)
h := newEventHandler(lggr, mockORM, fetcher)
err = h.Handle(ctx, giveEvent)
require.Error(t, err)
require.ErrorIs(t, err, assert.AnError)
})
}
Loading

0 comments on commit 9bb688c

Please sign in to comment.