Skip to content

Commit 02b5e91

Browse files
authored
Basic API validation for aggregator (#12)
1 parent f2562f2 commit 02b5e91

File tree

6 files changed

+107
-7
lines changed

6 files changed

+107
-7
lines changed

aggregator/functional-tests/commit_verification_api_test.go

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,61 @@
22
package functionaltests
33

44
import (
5+
"crypto/rand"
6+
"encoding/hex"
57
"testing"
68

79
"github.com/smartcontractkit/chainlink-ccv/aggregator/pb/aggregator"
810
"github.com/stretchr/testify/require"
911
)
1012

13+
func createRandomBytes(t *testing.T, n int) []byte {
14+
b := make([]byte, n)
15+
_, err := rand.Read(b)
16+
require.NoError(t, err)
17+
return b
18+
}
19+
1120
func TestReadWriteCommitVerification(t *testing.T) {
1221
client, cleanup, err := CreateServerAndClient(t)
1322
if err != nil {
1423
t.Fatalf("failed to create server and client: %v", err)
1524
}
1625
t.Cleanup(cleanup)
1726

27+
participantID := hex.EncodeToString(createRandomBytes(t, 32))
28+
committeeID := hex.EncodeToString(createRandomBytes(t, 32))
29+
messageID := createRandomBytes(t, 32)
30+
destVerifierAddr := createRandomBytes(t, 20)
31+
sourceVerifierAddr := createRandomBytes(t, 20)
32+
1833
writeResp, err := client.WriteCommitVerification(t.Context(), &aggregator.WriteCommitVerificationRequest{
19-
ParticipantId: "participant1",
20-
CommitteeId: "committee1",
34+
ParticipantId: participantID,
35+
CommitteeId: committeeID,
2136
CommitVerificationRecord: &aggregator.CommitVerificationRecord{
22-
MessageId: []byte("message1"),
37+
MessageId: messageID,
38+
BlobData: []byte("test blob data"),
39+
CcvData: []byte("test ccv data"),
40+
DestChainSelector: uint64(1),
41+
DestVerifierAddress: destVerifierAddr,
42+
SequenceNumber: uint64(1),
43+
SourceChainSelector: uint64(2),
44+
SourceVerifierAddress: sourceVerifierAddr,
45+
Timestamp: uint32(1234567890),
46+
Message: &aggregator.Any2AnyMessage{},
2347
},
2448
})
2549

2650
require.NoError(t, err, "WriteCommitVerification failed")
2751
require.Equal(t, aggregator.WriteStatus_SUCCESS, writeResp.Status, "expected WriteStatus_SUCCESS")
2852

2953
readResp, err := client.ReadCommitVerification(t.Context(), &aggregator.ReadCommitVerificationRequest{
30-
ParticipantId: "participant1",
31-
CommitteeId: "committee1",
32-
MessageId: []byte("message1"),
54+
ParticipantId: participantID,
55+
CommitteeId: committeeID,
56+
MessageId: messageID,
3357
})
3458

3559
require.NoError(t, err, "ReadCommitVerification failed")
3660
require.NotNil(t, readResp, "expected non-nil response")
37-
require.Equal(t, []byte("message1"), readResp.CommitVerificationRecord.MessageId, "expected MessageId to match")
61+
require.Equal(t, messageID, readResp.CommitVerificationRecord.MessageId, "expected MessageId to match")
3862
}

aggregator/go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ go 1.24.6
44

55
require (
66
github.com/BurntSushi/toml v1.5.0
7+
github.com/go-ozzo/ozzo-validation/v4 v4.3.0
78
github.com/rs/zerolog v1.34.0
89
github.com/stretchr/testify v1.11.1
910
google.golang.org/grpc v1.75.0

aggregator/go.sum

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
22
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
3+
github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496 h1:zV3ejI06GQ59hwDQAvmK1qxOQGB3WuVTRoY0okPTAv0=
4+
github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
35
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
6+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
47
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
58
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
69
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
710
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
811
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
912
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
13+
github.com/go-ozzo/ozzo-validation/v4 v4.3.0 h1:byhDUpfEwjsVQb1vBunvIjh2BHQ9ead57VkAEY4V+Es=
14+
github.com/go-ozzo/ozzo-validation/v4 v4.3.0/go.mod h1:2NKgrcHl3z6cJs+3Oo940FPRiTzuqKbvfrL2RxCj6Ew=
1015
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
1116
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
1217
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
@@ -25,6 +30,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
2530
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
2631
github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
2732
github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
33+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
34+
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
2835
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
2936
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
3037
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
@@ -58,5 +65,6 @@ google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyM
5865
google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
5966
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
6067
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
68+
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
6169
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
6270
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

aggregator/pkg/handlers/read_commit_verification_record.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ type ReadCommitVerificationRecordHandler struct {
1616

1717
// Handle processes the read request and retrieves the corresponding commit verification record.
1818
func (h *ReadCommitVerificationRecordHandler) Handle(ctx context.Context, req *aggregator.ReadCommitVerificationRequest) (*aggregator.ReadCommitVerificationResponse, error) {
19+
if err := validateReadRequest(req); err != nil {
20+
return &aggregator.ReadCommitVerificationResponse{}, err
21+
}
22+
1923
id := model.CommitVerificationRecordIdentifier{
2024
ParticipantID: req.GetParticipantId(),
2125
CommitteeID: req.GetCommitteeId(),
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package handlers
2+
3+
import (
4+
"regexp"
5+
6+
validation "github.com/go-ozzo/ozzo-validation/v4"
7+
"github.com/smartcontractkit/chainlink-ccv/aggregator/pb/aggregator"
8+
)
9+
10+
var bytes32HexStringValidation = validation.Match(regexp.MustCompile(`^[a-fA-F0-9]{64}$`))
11+
12+
func validateWriteRequest(req *aggregator.WriteCommitVerificationRequest) error {
13+
err := validation.ValidateStruct(
14+
req,
15+
validation.Field(&req.ParticipantId, validation.Required, bytes32HexStringValidation),
16+
validation.Field(&req.CommitteeId, validation.Required, bytes32HexStringValidation),
17+
validation.Field(&req.CommitVerificationRecord, validation.Required))
18+
if err != nil {
19+
return err
20+
}
21+
22+
verificationRecord := req.GetCommitVerificationRecord()
23+
24+
err = validation.ValidateStruct(
25+
verificationRecord,
26+
validation.Field(&verificationRecord.MessageId, validation.Required, validation.Length(32, 32)),
27+
validation.Field(&verificationRecord.BlobData, validation.Required),
28+
validation.Field(&verificationRecord.CcvData, validation.Required),
29+
// TODO: Check valid selector (needs to be in our configuration)
30+
validation.Field(&verificationRecord.DestChainSelector, validation.Required),
31+
validation.Field(&verificationRecord.DestVerifierAddress, validation.Required, validation.Length(20, 20)),
32+
validation.Field(&verificationRecord.SequenceNumber, validation.Required),
33+
validation.Field(&verificationRecord.SourceChainSelector, validation.Required),
34+
validation.Field(&verificationRecord.SourceVerifierAddress, validation.Required, validation.Length(20, 20)),
35+
validation.Field(&verificationRecord.Timestamp, validation.Required),
36+
// TODO: Do deeper validation once format is finalized
37+
validation.Field(&verificationRecord.Message, validation.Required),
38+
)
39+
40+
if err != nil {
41+
return err
42+
}
43+
return nil
44+
}
45+
46+
func validateReadRequest(req *aggregator.ReadCommitVerificationRequest) error {
47+
err := validation.ValidateStruct(
48+
req,
49+
validation.Field(&req.ParticipantId, validation.Required, bytes32HexStringValidation),
50+
validation.Field(&req.CommitteeId, validation.Required, bytes32HexStringValidation),
51+
validation.Field(&req.MessageId, validation.Required, validation.Length(32, 32)),
52+
)
53+
if err != nil {
54+
return err
55+
}
56+
return nil
57+
}

aggregator/pkg/handlers/write_commit_verification_record.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ type WriteCommitVerificationRecordHandler struct {
2121

2222
// Handle processes the write request and saves the commit verification record.
2323
func (h *WriteCommitVerificationRecordHandler) Handle(ctx context.Context, req *aggregator.WriteCommitVerificationRequest) (*aggregator.WriteCommitVerificationResponse, error) {
24+
if err := validateWriteRequest(req); err != nil {
25+
return &aggregator.WriteCommitVerificationResponse{
26+
Status: aggregator.WriteStatus_FAILED,
27+
}, err
28+
}
29+
2430
record := model.CommitVerificationRecord{
2531
CommitVerificationRecord: *req.GetCommitVerificationRecord(),
2632
ParticipantID: req.GetParticipantId(),

0 commit comments

Comments
 (0)