Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/build_external.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,12 @@ jobs:
- name: Install Solana CLI
run: ./scripts/install-solana-ci.sh

- name: Update mocks
run: |
make mockery
make rm-mocked
mockery

- name: Build & Test
run: make test_relay_unit

Expand Down
18 changes: 18 additions & 0 deletions pkg/loop/internal/core/services/keystore/keystore.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,15 @@ func (k Client) Sign(ctx context.Context, account string, data []byte) ([]byte,
return resp.SignedData, nil
}

func (k Client) Decrypt(ctx context.Context, account string, data []byte) ([]byte, error) {
resp, err := k.grpc.Decrypt(ctx, &pb.DecryptRequest{Account: account, Data: data})
if err != nil {
return nil, fmt.Errorf("failed to decrypt data for account: %s: %w", account, err)
}

return resp.DecryptedData, nil
}

func NewClient(cc grpc.ClientConnInterface) *Client {
return &Client{pb.NewKeystoreClient(cc)}
}
Expand Down Expand Up @@ -66,3 +75,12 @@ func (s Server) Sign(ctx context.Context, req *pb.SignRequest) (*pb.SignReply, e

return &pb.SignReply{SignedData: signedData}, nil
}

func (s Server) Decrypt(ctx context.Context, req *pb.DecryptRequest) (*pb.DecryptReply, error) {
decryptedData, err := s.impl.Decrypt(ctx, req.Account, req.Data)
if err != nil {
return nil, fmt.Errorf("failed to decrypt data for account: %s: %w", req.Account, err)
}

return &pb.DecryptReply{DecryptedData: decryptedData}, nil
}
103 changes: 103 additions & 0 deletions pkg/loop/internal/core/services/keystore/keystore_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package keystore

import (
"context"
"testing"

"github.com/stretchr/testify/assert"
"google.golang.org/grpc"
"google.golang.org/protobuf/types/known/emptypb"

"github.com/smartcontractkit/chainlink-common/pkg/loop/internal/pb"
)

func Test_KeyStoreClient(t *testing.T) {
ctx := t.Context()

account := "testAccount"
signedData := []byte("signedData")
decryptedData := []byte("decryptedData")
client := Client{grpc: &testGrpcClient{
account: account,
signedData: signedData,
decryptedData: decryptedData,
}}
accounts, err := client.Accounts(ctx)
assert.NoError(t, err)
assert.Equal(t, []string{account}, accounts)

sig, err := client.Sign(ctx, account, []byte("123"))
assert.NoError(t, err)
assert.Equal(t, signedData, sig)

dec, err := client.Decrypt(ctx, account, sig)
assert.NoError(t, err)
assert.Equal(t, decryptedData, dec)
}

func Test_KeyValueStoreServer(t *testing.T) {
ctx := t.Context()

account := "testAccount"
signedData := []byte("signedData")
decryptedData := []byte("decryptedData")
server := Server{impl: &testKeyStore{
account: account,
signedData: signedData,
decryptedData: decryptedData,
}}

accounts, err := server.Accounts(ctx, &emptypb.Empty{})
assert.NoError(t, err)
assert.Equal(t, []string{account}, accounts.Accounts)

sig, err := server.Sign(ctx, &pb.SignRequest{Account: account, Data: []byte("123")})
assert.NoError(t, err)
assert.Equal(t, signedData, sig.SignedData)

dec, err := server.Decrypt(ctx, &pb.DecryptRequest{Account: account, Data: []byte("456")})
assert.NoError(t, err)
assert.Equal(t, decryptedData, dec.DecryptedData)
}

type testGrpcClient struct {
account string
signedData []byte
decryptedData []byte
}

func (t *testGrpcClient) Accounts(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*pb.AccountsReply, error) {
return &pb.AccountsReply{
Accounts: []string{t.account},
}, nil
}

func (t *testGrpcClient) Sign(ctx context.Context, req *pb.SignRequest, opts ...grpc.CallOption) (*pb.SignReply, error) {
return &pb.SignReply{
SignedData: t.signedData,
}, nil
}

func (t *testGrpcClient) Decrypt(ctx context.Context, req *pb.DecryptRequest, opts ...grpc.CallOption) (*pb.DecryptReply, error) {
return &pb.DecryptReply{
DecryptedData: t.decryptedData,
}, nil
}

type testKeyStore struct {
account string
signedData []byte
decryptedData []byte
}

func (t *testKeyStore) Accounts(ctx context.Context) ([]string, error) {
return []string{t.account}, nil
}

func (t *testKeyStore) Sign(ctx context.Context, account string, data []byte) ([]byte, error) {
return t.signedData, nil
}

func (t *testKeyStore) Decrypt(ctx context.Context, account string, data []byte) ([]byte, error) {
return t.decryptedData, nil
}
33 changes: 27 additions & 6 deletions pkg/loop/internal/core/services/keystore/test/keystore.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,21 @@ import (

var Keystore = staticKeystore{
staticKeystoreConfig: staticKeystoreConfig{
Account: libocr.Account("testaccount"),
encoded: []byte{5: 11},
signed: []byte{13: 37},
Account: libocr.Account("testaccount"),
encoded: []byte{5: 11},
signed: []byte{13: 37},
decrypted: []byte{17: 41},
},
}

var _ core.Keystore = (*staticKeystore)(nil)
var _ testtypes.Evaluator[core.Keystore] = (*staticKeystore)(nil)

type staticKeystoreConfig struct {
Account libocr.Account
encoded []byte
signed []byte
Account libocr.Account
encoded []byte
signed []byte
decrypted []byte
}

type staticKeystore struct {
Expand All @@ -46,6 +48,16 @@ func (s staticKeystore) Sign(ctx context.Context, id string, data []byte) ([]byt
return s.signed, nil
}

func (s staticKeystore) Decrypt(ctx context.Context, id string, encrypted []byte) ([]byte, error) {
if string(s.Account) != id {
return nil, fmt.Errorf("expected id %q but got %q", s.Account, id)
}
if !bytes.Equal(s.encoded, encrypted) {
return nil, fmt.Errorf("expected encoded data %x but got %x", s.encoded, encrypted)
}
return s.decrypted, nil
}

func (s staticKeystore) Evaluate(ctx context.Context, other core.Keystore) error {
accounts, err := s.Accounts(ctx)
if err != nil {
Expand All @@ -65,5 +77,14 @@ func (s staticKeystore) Evaluate(ctx context.Context, other core.Keystore) error
if !bytes.Equal(s.signed, signed) {
return fmt.Errorf("expected signed data %x but got %x", s.signed, signed)
}

decrypted, err := other.Decrypt(ctx, string(s.Account), s.encoded)
if err != nil {
return fmt.Errorf("failed to decrypt: %w", err)
}
if !bytes.Equal(s.decrypted, decrypted) {
return fmt.Errorf("expected decrypted data %x but got %x", s.decrypted, decrypted)
}

return nil
}
1 change: 1 addition & 0 deletions pkg/loop/internal/pb/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//go:generate protoc --proto_path=../../../ --go_out=../../../ --go_opt=paths=source_relative --go-grpc_out=../../../ --go-grpc_opt=paths=source_relative loop/internal/pb/contract_reader.proto
//go:generate go run ./generate_with_values contract_writer.proto capabilities_registry.proto
//go:generate protoc --proto_path=../../../ --go_out=../../../ --go_opt=paths=source_relative --go-grpc_out=../../../ --go-grpc_opt=paths=source_relative loop/internal/pb/median_datasource.proto
//go:generate protoc --proto_path=../../../ --go_out=../../../ --go_opt=paths=source_relative --go-grpc_out=../../../ --go-grpc_opt=paths=source_relative loop/internal/pb/keystore.proto
//go:generate protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative reporting_plugin_service.proto
//go:generate protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative telemetry.proto
//go:generate protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative pipeline_runner.proto
Expand Down
Loading
Loading