Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Codec interface tests #967

Merged
merged 31 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
e723593
Connect codec interface tests and refactor codec to interface like EV…
ilija42 Dec 12, 2024
0250594
progress
ilija42 Dec 12, 2024
aaaee4b
Fully implement Codec interface tests
ilija42 Dec 13, 2024
1573a7f
Run codec tests in loop
ilija42 Dec 13, 2024
d028a40
Prettify codec and codec tests
ilija42 Dec 13, 2024
8fa6889
Refactor codec nil encoding handling
ilija42 Dec 13, 2024
9349fdb
Revert accidental changes to testIDL.json
ilija42 Dec 14, 2024
86baca9
Add sonar exclusion for codec test utils
ilija42 Dec 14, 2024
55f16db
Add sq exclusion for duplications in testutils, add decoder unit tests
ilija42 Dec 14, 2024
630d291
Add encoder unit test
ilija42 Dec 16, 2024
fa9efdd
Fix lint and rename codec to solanacodec to avoid types name collision
ilija42 Dec 16, 2024
3585398
Solana codec entry improvements
ilija42 Dec 16, 2024
7f4fd28
Fix Solana codec field casing
ilija42 Dec 16, 2024
17d3474
minor err messages improvements
ilija42 Dec 16, 2024
d795ae4
Code improvements
ilija42 Dec 16, 2024
4103493
Fix encoder unit tests
ilija42 Dec 16, 2024
68d704e
Fix sonar exclusions
ilija42 Dec 16, 2024
eca38ed
lint
ilija42 Dec 16, 2024
bfb7bbe
Reorder methods in Solana codec
ilija42 Dec 16, 2024
870f95a
Fix CR integration tests config
ilija42 Dec 17, 2024
c15c0d4
Revert TestNewIDLCodec_WithModifiers deletion
ilija42 Dec 17, 2024
5328645
Merge branch 'develop' into codec-interface
ilija42 Dec 17, 2024
aa89442
Add comments for codec entry includeDiscriminator option
ilija42 Dec 18, 2024
6bc1d31
Add discriminator value check in codec entry Decode
ilija42 Dec 18, 2024
44ce6ff
Reuse utils from interface tests for Solana codec interface tests
ilija42 Dec 18, 2024
3314b11
Merge branch 'develop' into codec-interface
ilija42 Dec 18, 2024
794787c
Fix comment
ilija42 Dec 18, 2024
52bbcb6
Fix comment
ilija42 Dec 18, 2024
546bddd
[Non-EVM-1062] Solana Codec events support, Hookup Fuzz tests and cle…
ilija42 Dec 19, 2024
07950d7
Merge branch 'develop' into codec-interface
ilija42 Dec 19, 2024
4f20c81
Merge branch 'develop' into codec-interface
jadepark-dev Dec 19, 2024
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
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ require (
github.com/stretchr/testify v1.9.0
go.uber.org/zap v1.27.0
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0
golang.org/x/sync v0.8.0
golang.org/x/text v0.18.0
golang.org/x/sync v0.10.0
golang.org/x/text v0.21.0
)

require (
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -682,8 +682,8 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
Expand Down Expand Up @@ -746,8 +746,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
Expand Down
4 changes: 2 additions & 2 deletions integration-tests/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ require (
github.com/stretchr/testify v1.9.0
github.com/testcontainers/testcontainers-go v0.34.0
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c
golang.org/x/sync v0.8.0
golang.org/x/text v0.19.0
golang.org/x/sync v0.10.0
golang.org/x/text v0.21.0
gopkg.in/guregu/null.v4 v4.0.0
)

Expand Down
8 changes: 4 additions & 4 deletions integration-tests/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1692,8 +1692,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
Expand Down Expand Up @@ -1804,8 +1804,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
Expand Down
6 changes: 3 additions & 3 deletions integration-tests/relayinterface/chain_components_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ func (it *SolanaChainComponentsInterfaceTester[T]) Setup(t T) {
Procedure: config.ChainReaderProcedure{
IDLAccount: "DataAccount",
OutputModifications: codec.ModifiersConfig{
&codec.PropertyExtractorConfig{FieldName: "U64value"},
&codec.PropertyExtractorConfig{FieldName: "U64Value"},
},
},
},
Expand All @@ -142,7 +142,7 @@ func (it *SolanaChainComponentsInterfaceTester[T]) Setup(t T) {
Procedure: config.ChainReaderProcedure{
IDLAccount: "DataAccount",
OutputModifications: codec.ModifiersConfig{
&codec.PropertyExtractorConfig{FieldName: "U64slice"},
&codec.PropertyExtractorConfig{FieldName: "U64Slice"},
},
},
},
Expand All @@ -156,7 +156,7 @@ func (it *SolanaChainComponentsInterfaceTester[T]) Setup(t T) {
Procedure: config.ChainReaderProcedure{
IDLAccount: "DataAccount",
OutputModifications: codec.ModifiersConfig{
&codec.PropertyExtractorConfig{FieldName: "U64value"},
&codec.PropertyExtractorConfig{FieldName: "U64Value"},
},
},
},
Expand Down
192 changes: 192 additions & 0 deletions pkg/solana/codec/codec_entry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
package codec

import (
"bytes"
"fmt"
"reflect"

"github.com/smartcontractkit/chainlink-common/pkg/codec"
commonencodings "github.com/smartcontractkit/chainlink-common/pkg/codec/encodings"
commontypes "github.com/smartcontractkit/chainlink-common/pkg/types"
)

type Entry interface {
Encode(value any, into []byte) ([]byte, error)
Decode(encoded []byte) (any, []byte, error)
GetCodecType() commonencodings.TypeCodec
GetType() reflect.Type
Modifier() codec.Modifier
Size(numItems int) (int, error)
FixedSize() (int, error)
}

type entry struct {
// TODO this might not be needed in the end, it was handy to make tests simpler
offchainName string
onchainName string
reflectType reflect.Type
typeCodec commonencodings.TypeCodec
mod codec.Modifier
// includeDiscriminator during Encode adds a discriminator to the encoded bytes under an assumption that the provided value didn't have a discriminator.
// During Decode includeDiscriminator removes discriminator from bytes under an assumption that the provided struct doesn't need a discriminator.
includeDiscriminator bool
discriminator Discriminator
}

func NewAccountEntry(offchainName string, idlAccount IdlTypeDef, idlTypes IdlTypeDefSlice, includeDiscriminator bool, mod codec.Modifier, builder commonencodings.Builder) (Entry, error) {
_, accCodec, err := createCodecType(idlAccount, createRefs(idlTypes, builder), false)
if err != nil {
return nil, err
}

return newEntry(
offchainName,
idlAccount.Name,
accCodec,
includeDiscriminator,
mod,
), nil
}

func NewInstructionArgsEntry(offChainName string, instructions IdlInstruction, idlTypes IdlTypeDefSlice, mod codec.Modifier, builder commonencodings.Builder) (Entry, error) {
_, instructionCodecArgs, err := asStruct(instructions.Args, createRefs(idlTypes, builder), instructions.Name, false, true)
if err != nil {
return nil, err
}

return newEntry(
offChainName,
instructions.Name,
instructionCodecArgs,
// Instruction arguments don't need a discriminator by default
false,
mod,
), nil
}

func NewEventArgsEntry(offChainName string, event IdlEvent, idlTypes IdlTypeDefSlice, includeDiscriminator bool, mod codec.Modifier, builder commonencodings.Builder) (Entry, error) {
_, eventCodec, err := asStruct(eventFieldsToFields(event.Fields), createRefs(idlTypes, builder), event.Name, false, false)
if err != nil {
return nil, err
}

return newEntry(
offChainName,
event.Name,
eventCodec,
includeDiscriminator,
mod,
), nil
}

func newEntry(
offchainName, onchainName string,
typeCodec commonencodings.TypeCodec,
includeDiscriminator bool,
mod codec.Modifier,
) Entry {
return &entry{
offchainName: offchainName,
onchainName: onchainName,
reflectType: typeCodec.GetType(),
typeCodec: typeCodec,
mod: ensureModifier(mod),
includeDiscriminator: includeDiscriminator,
discriminator: *NewDiscriminator(onchainName),
}
}

func createRefs(idlTypes IdlTypeDefSlice, builder commonencodings.Builder) *codecRefs {
return &codecRefs{
builder: builder,
codecs: make(map[string]commonencodings.TypeCodec),
typeDefs: idlTypes,
dependencies: make(map[string][]string),
}
}

func (e *entry) Encode(value any, into []byte) ([]byte, error) {
// Special handling for encoding a nil pointer to an empty struct.
t := e.reflectType
if value == nil {
if t.Kind() == reflect.Pointer {
elem := t.Elem()
if elem.Kind() == reflect.Struct && elem.NumField() == 0 {
return []byte{}, nil
}
}
return nil, fmt.Errorf("%w: cannot encode nil value for offchainName: %q, onchainName: %q",
commontypes.ErrInvalidType, e.offchainName, e.onchainName)
}

encodedVal, err := e.typeCodec.Encode(value, into)
if err != nil {
return nil, err
}

if e.includeDiscriminator {
var byt []byte
encodedDisc, err := e.discriminator.Encode(&e.discriminator.hashPrefix, byt)
if err != nil {
return nil, err
}
return append(encodedDisc, encodedVal...), nil
}

return encodedVal, nil
}

func (e *entry) Decode(encoded []byte) (any, []byte, error) {
if e.includeDiscriminator {
if len(encoded) < discriminatorLength {
return nil, nil, fmt.Errorf("%w: encoded data too short to contain discriminator for offchainName: %q, onchainName: %q",
commontypes.ErrInvalidType, e.offchainName, e.onchainName)
}

if !bytes.Equal(e.discriminator.hashPrefix, encoded[:discriminatorLength]) {
return nil, nil, fmt.Errorf("%w: encoded data has a bad discriminator %v for offchainName: %q, onchainName: %q",
commontypes.ErrInvalidType, encoded[:discriminatorLength], e.offchainName, e.onchainName)
}

encoded = encoded[discriminatorLength:]
}
return e.typeCodec.Decode(encoded)
}

func (e *entry) GetCodecType() commonencodings.TypeCodec {
return e.typeCodec
}

func (e *entry) GetType() reflect.Type {
return e.reflectType
}

func (e *entry) Modifier() codec.Modifier {
return e.mod
}

func (e *entry) Size(numItems int) (int, error) {
return e.typeCodec.Size(numItems)
}

func (e *entry) FixedSize() (int, error) {
return e.typeCodec.FixedSize()
}

func ensureModifier(mod codec.Modifier) codec.Modifier {
if mod == nil {
return codec.MultiModifier{}
}
return mod
}

func eventFieldsToFields(evFields []IdlEventField) []IdlField {
var idlFields []IdlField
for _, evField := range evFields {
idlFields = append(idlFields, IdlField{
Name: evField.Name,
Type: evField.Type,
})
}
return idlFields
}
Loading
Loading