Skip to content

Commit

Permalink
Remove pending from boundContract and use confidence instead for CR
Browse files Browse the repository at this point in the history
  • Loading branch information
ilija42 committed Jul 1, 2024
1 parent 7c11e2c commit 49b4030
Show file tree
Hide file tree
Showing 8 changed files with 279 additions and 259 deletions.
447 changes: 225 additions & 222 deletions pkg/loop/internal/pb/chain_reader.pb.go

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions pkg/loop/internal/pb/chain_reader.proto
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ service ChainReader {
message GetLatestValueRequest {
string contract_name = 1;
string method = 2;
VersionedBytes params = 3;
Confidence confidence = 3;
VersionedBytes params = 4;
}

// QueryKeyRequest has arguments for [github.com/smartcontractkit/chainlink-common/pkg/types.ChainReader.QueryKey].
Expand Down Expand Up @@ -60,7 +61,6 @@ message Sequence {
message BoundContract {
string address = 1;
string name = 2;
bool pending = 3;
}

enum ComparisonOperator {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,18 +130,25 @@ func DecodeVersionedBytes(res any, vData *pb.VersionedBytes) error {
return nil
}

func (c *Client) GetLatestValue(ctx context.Context, contractName, method string, params, retVal any) error {
func (c *Client) GetLatestValue(ctx context.Context, contractName, method string, confidenceLevel primitives.ConfidenceLevel, params, returnVal any) error {
versionedParams, err := EncodeVersionedBytes(params, c.encodeWith)
if err != nil {
return err
}

reply, err := c.grpc.GetLatestValue(ctx, &pb.GetLatestValueRequest{ContractName: contractName, Method: method, Params: versionedParams})
var pbConfidence pb.Confidence
if confidenceLevel == primitives.Finalized {
pbConfidence = pb.Confidence_Finalized
} else {
pbConfidence = pb.Confidence_Unconfirmed
}

reply, err := c.grpc.GetLatestValue(ctx, &pb.GetLatestValueRequest{ContractName: contractName, Method: method, Params: versionedParams, Confidence: pbConfidence})
if err != nil {
return net.WrapRPCErr(err)
}

return DecodeVersionedBytes(retVal, reply.RetVal)
return DecodeVersionedBytes(returnVal, reply.RetVal)
}

func (c *Client) QueryKey(ctx context.Context, contractName string, filter query.KeyFilter, limitAndSort query.LimitAndSort, sequenceDataType any) ([]types.Sequence, error) {
Expand All @@ -166,7 +173,7 @@ func (c *Client) QueryKey(ctx context.Context, contractName string, filter query
func (c *Client) Bind(ctx context.Context, bindings []types.BoundContract) error {
pbBindings := make([]*pb.BoundContract, len(bindings))
for i, b := range bindings {
pbBindings[i] = &pb.BoundContract{Address: b.Address, Name: b.Name, Pending: b.Pending}
pbBindings[i] = &pb.BoundContract{Address: b.Address, Name: b.Name}
}
_, err := c.grpc.Bind(ctx, &pb.BindRequest{Bindings: pbBindings})
return net.WrapRPCErr(err)
Expand Down Expand Up @@ -211,16 +218,24 @@ func (c *Server) GetLatestValue(ctx context.Context, request *pb.GetLatestValueR
return nil, err
}

retVal, err := getContractEncodedType(request.ContractName, request.Method, c.impl, false)
returnVal, err := getContractEncodedType(request.ContractName, request.Method, c.impl, false)
if err != nil {
return nil, err
}
err = c.impl.GetLatestValue(ctx, request.ContractName, request.Method, params, retVal)

var confidenceLevel primitives.ConfidenceLevel
if request.Confidence == pb.Confidence_Unconfirmed {
confidenceLevel = primitives.Unconfirmed
} else if request.Confidence == pb.Confidence_Finalized {
confidenceLevel = primitives.Finalized
}

err = c.impl.GetLatestValue(ctx, request.ContractName, request.Method, confidenceLevel, params, returnVal)
if err != nil {
return nil, err
}

encodedRetVal, err := EncodeVersionedBytes(retVal, EncodingVersion(request.Params.Version))
encodedRetVal, err := EncodeVersionedBytes(returnVal, EncodingVersion(request.Params.Version))
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -260,7 +275,7 @@ func (c *Server) QueryKey(ctx context.Context, request *pb.QueryKeyRequest) (*pb
func (c *Server) Bind(ctx context.Context, bindings *pb.BindRequest) (*emptypb.Empty, error) {
tBindings := make([]types.BoundContract, len(bindings.Bindings))
for i, b := range bindings.Bindings {
tBindings[i] = types.BoundContract{Address: b.Address, Name: b.Name, Pending: b.Pending}
tBindings[i] = types.BoundContract{Address: b.Address, Name: b.Name}
}

return &emptypb.Empty{}, c.impl.Bind(ctx, tBindings)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
chainreadertest "github.com/smartcontractkit/chainlink-common/pkg/loop/internal/relayer/pluginprovider/chainreader/test"
"github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink-common/pkg/types/query"
"github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives"
"github.com/smartcontractkit/chainlink-common/pkg/utils/tests"

. "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" //nolint
Expand Down Expand Up @@ -136,15 +137,15 @@ func TestGetLatestValue(t *testing.T) {
nilTester.Setup(t)
nilCr := nilTester.GetChainReader(t)

err := nilCr.GetLatestValue(ctx, "", "method", "anything", "anything")
err := nilCr.GetLatestValue(ctx, "", "method", "", "anything", "anything")
assert.Equal(t, codes.Unimplemented, status.Convert(err).Code())
})

for _, errorType := range errorTypes {
es.err = errorType
t.Run("GetLatestValue unwraps errors from server "+errorType.Error(), func(t *testing.T) {
ctx := tests.Context(t)
err := chainReader.GetLatestValue(ctx, "", "method", nil, "anything")
err := chainReader.GetLatestValue(ctx, "", "method", "", nil, "anything")
assert.True(t, errors.Is(err, errorType))
})
}
Expand All @@ -153,7 +154,7 @@ func TestGetLatestValue(t *testing.T) {
es.err = nil
t.Run("GetLatestValue returns error if type cannot be encoded in the wire format", func(t *testing.T) {
ctx := tests.Context(t)
err := chainReader.GetLatestValue(ctx, "", "method", &cannotEncode{}, &TestStruct{})
err := chainReader.GetLatestValue(ctx, "", "method", "", &cannotEncode{}, &TestStruct{})
assert.True(t, errors.Is(err, types.ErrInvalidType))
})
}
Expand Down Expand Up @@ -286,7 +287,7 @@ func (f *fakeChainReader) SetLatestValue(ts *TestStruct) {
f.stored = append(f.stored, *ts)
}

func (f *fakeChainReader) GetLatestValue(_ context.Context, contractName, method string, params, returnVal any) error {
func (f *fakeChainReader) GetLatestValue(_ context.Context, contractName, method string, _ primitives.ConfidenceLevel, params, returnVal any) error {
if method == MethodReturningUint64 {
r := returnVal.(*uint64)
if contractName == AnyContractName {
Expand Down Expand Up @@ -390,7 +391,7 @@ func (e *errChainReader) Name() string { panic("unimplemented") }

func (e *errChainReader) HealthReport() map[string]error { panic("unimplemented") }

func (e *errChainReader) GetLatestValue(_ context.Context, _, _ string, _, _ any) error {
func (e *errChainReader) GetLatestValue(_ context.Context, _, _ string, _ primitives.ConfidenceLevel, _, _ any) error {
return e.err
}

Expand Down Expand Up @@ -418,7 +419,7 @@ func (pc *protoConversionTestChainReader) Name() string { panic("unimplemented")

func (pc *protoConversionTestChainReader) HealthReport() map[string]error { panic("unimplemented") }

func (pc *protoConversionTestChainReader) GetLatestValue(_ context.Context, _, _ string, _, _ any) error {
func (pc *protoConversionTestChainReader) GetLatestValue(_ context.Context, _, _ string, _ primitives.ConfidenceLevel, _, _ any) error {
return nil
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
testtypes "github.com/smartcontractkit/chainlink-common/pkg/loop/internal/test/types"
"github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink-common/pkg/types/query"
"github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives"
)

var (
Expand Down Expand Up @@ -47,7 +48,7 @@ func (c staticChainReader) Bind(_ context.Context, _ []types.BoundContract) erro
return nil
}

func (c staticChainReader) GetLatestValue(_ context.Context, contractName, method string, params, returnVal any) error {
func (c staticChainReader) GetLatestValue(_ context.Context, contractName, method string, _ primitives.ConfidenceLevel, params, returnVal any) error {
if !assert.ObjectsAreEqual(contractName, c.contractName) {
return fmt.Errorf("%w: expected report context %v but got %v", types.ErrInvalidType, c.contractName, contractName)
}
Expand Down Expand Up @@ -80,7 +81,7 @@ func (c staticChainReader) QueryKey(_ context.Context, _ string, _ query.KeyFilt

func (c staticChainReader) Evaluate(ctx context.Context, cr types.ContractReader) error {
gotLatestValue := make(map[string]any)
err := cr.GetLatestValue(ctx, c.contractName, c.contractMethod, &c.params, &gotLatestValue)
err := cr.GetLatestValue(ctx, c.contractName, c.contractMethod, primitives.Unconfirmed, &c.params, &gotLatestValue)
if err != nil {
return fmt.Errorf("failed to call GetLatestValue(): %w", err)
}
Expand Down
5 changes: 2 additions & 3 deletions pkg/loop/internal/relayer/pluginprovider/ext/median/median.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,9 @@ import (
"google.golang.org/protobuf/types/known/timestamppb"

"github.com/smartcontractkit/chainlink-common/pkg/loop/internal/goplugin"
"github.com/smartcontractkit/chainlink-common/pkg/loop/internal/relayer/pluginprovider/chainreader"

"github.com/smartcontractkit/chainlink-common/pkg/loop/internal/net"
"github.com/smartcontractkit/chainlink-common/pkg/loop/internal/pb"
"github.com/smartcontractkit/chainlink-common/pkg/loop/internal/relayer/pluginprovider/chainreader"
"github.com/smartcontractkit/chainlink-common/pkg/loop/internal/relayer/pluginprovider/ocr2"
"github.com/smartcontractkit/chainlink-common/pkg/types"
)
Expand All @@ -46,7 +45,7 @@ func NewProviderClient(b *net.BrokerExt, cc grpc.ClientConnInterface) *ProviderC

maybeCr := chainreader.NewClient(b, cc)
var anyRetVal int
err := maybeCr.GetLatestValue(context.Background(), "", "", nil, &anyRetVal)
err := maybeCr.GetLatestValue(context.Background(), "", "", "", nil, &anyRetVal)
if status.Convert(err).Code() != codes.Unimplemented {
m.chainReader = maybeCr
}
Expand Down
8 changes: 4 additions & 4 deletions pkg/types/chain_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink-common/pkg/types/query"
"github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives"
)

// Errors exposed to product plugins
Expand All @@ -21,7 +22,7 @@ type ContractReader = ChainReader
// Deprecated: use ContractReader. New naming should clear up confusion around the usage of this interface which should strictly be contract reading related.
type ChainReader interface {
services.Service
// GetLatestValue gets the latest value....
// GetLatestValue gets the latest value with a certain confidence level that maps to blockchain finality....
// The params argument can be any object which maps a set of generic parameters into chain specific parameters defined in RelayConfig.
// It must encode as an object via [json.Marshal] and [github.com/fxamacker/cbor/v2.Marshal].
// Typically, would be either a struct with field names mapping to arguments, or anonymous map such as `map[string]any{"baz": 42, "test": true}}`
Expand All @@ -37,14 +38,14 @@ type ChainReader interface {
// Bar *big.Int `json:"bar"`
// }
// func do(ctx context.Context, cr ChainReader) (resp ProductReturn, err error) {
// err = cr.GetLatestValue(ctx, "FooContract", "GetProduct", ProductParams{ID:1}, &resp)
// err = cr.GetLatestValue(ctx, "FooContract", "GetProduct", primitives.Finalized, ProductParams{ID:1}, &resp)
// return
// }
//
// Note that implementations should ignore extra fields in params that are not expected in the call to allow easier
// use across chains and contract versions.
// Similarly, when using a struct for returnVal, fields in the return value that are not on-chain will not be set.
GetLatestValue(ctx context.Context, contractName, method string, params, returnVal any) error
GetLatestValue(ctx context.Context, contractName, method string, confidenceLevel primitives.ConfidenceLevel, params, returnVal any) error

// Bind will override current bindings for the same contract, if one has been set and will return an error if the
// contract is not known by the ChainReader, or if the Address is invalid
Expand All @@ -70,7 +71,6 @@ type Sequence struct {
type BoundContract struct {
Address string
Name string
Pending bool
}

func (bc BoundContract) Key() string {
Expand Down
25 changes: 13 additions & 12 deletions pkg/types/interfacetests/chain_reader_interface_tests.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink-common/pkg/types/query"
"github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives"
"github.com/smartcontractkit/chainlink-common/pkg/utils/tests"
)

Expand Down Expand Up @@ -65,12 +66,12 @@ func runChainReaderGetLatestValueInterfaceTests[T TestingT[T]](t T, tester Chain

actual := &TestStruct{}
params := &LatestParams{I: 1}
require.NoError(t, cr.GetLatestValue(ctx, AnyContractName, MethodTakingLatestParamsReturningTestStruct, params, actual))
require.NoError(t, cr.GetLatestValue(ctx, AnyContractName, MethodTakingLatestParamsReturningTestStruct, primitives.Unconfirmed, params, actual))
assert.Equal(t, &firstItem, actual)

params.I = 2
actual = &TestStruct{}
require.NoError(t, cr.GetLatestValue(ctx, AnyContractName, MethodTakingLatestParamsReturningTestStruct, params, actual))
require.NoError(t, cr.GetLatestValue(ctx, AnyContractName, MethodTakingLatestParamsReturningTestStruct, primitives.Unconfirmed, params, actual))
assert.Equal(t, &secondItem, actual)
},
},
Expand All @@ -82,7 +83,7 @@ func runChainReaderGetLatestValueInterfaceTests[T TestingT[T]](t T, tester Chain
require.NoError(t, cr.Bind(ctx, tester.GetBindings(t)))

var prim uint64
require.NoError(t, cr.GetLatestValue(ctx, AnyContractName, MethodReturningUint64, nil, &prim))
require.NoError(t, cr.GetLatestValue(ctx, AnyContractName, MethodReturningUint64, primitives.Unconfirmed, nil, &prim))

assert.Equal(t, AnyValueToReadWithoutAnArgument, prim)
},
Expand All @@ -95,13 +96,13 @@ func runChainReaderGetLatestValueInterfaceTests[T TestingT[T]](t T, tester Chain
require.NoError(t, cr.Bind(ctx, tester.GetBindings(t)))

var prim uint64
require.NoError(t, cr.GetLatestValue(ctx, AnyContractName, DifferentMethodReturningUint64, nil, &prim))
require.NoError(t, cr.GetLatestValue(ctx, AnyContractName, DifferentMethodReturningUint64, primitives.Unconfirmed, nil, &prim))

assert.Equal(t, AnyDifferentValueToReadWithoutAnArgument, prim)
},
},
{
name: "Get latest value allows multiple constract names to have the same function name",
name: "Get latest value allows multiple contract names to have the same function name",
test: func(t T) {
ctx := tests.Context(t)
cr := tester.GetChainReader(t)
Expand All @@ -115,7 +116,7 @@ func runChainReaderGetLatestValueInterfaceTests[T TestingT[T]](t T, tester Chain
require.NoError(t, cr.Bind(ctx, bindings))

var prim uint64
require.NoError(t, cr.GetLatestValue(ctx, AnySecondContractName, MethodReturningUint64, nil, &prim))
require.NoError(t, cr.GetLatestValue(ctx, AnySecondContractName, MethodReturningUint64, primitives.Unconfirmed, nil, &prim))

assert.Equal(t, AnyDifferentValueToReadWithoutAnArgument, prim)
},
Expand All @@ -128,7 +129,7 @@ func runChainReaderGetLatestValueInterfaceTests[T TestingT[T]](t T, tester Chain
require.NoError(t, cr.Bind(ctx, tester.GetBindings(t)))

var slice []uint64
require.NoError(t, cr.GetLatestValue(ctx, AnyContractName, MethodReturningUint64Slice, nil, &slice))
require.NoError(t, cr.GetLatestValue(ctx, AnyContractName, MethodReturningUint64Slice, primitives.Unconfirmed, nil, &slice))

assert.Equal(t, AnySliceToReadWithoutAnArgument, slice)
},
Expand All @@ -144,7 +145,7 @@ func runChainReaderGetLatestValueInterfaceTests[T TestingT[T]](t T, tester Chain
require.NoError(t, cr.Bind(ctx, tester.GetBindings(t)))

actual := &TestStructWithExtraField{}
require.NoError(t, cr.GetLatestValue(ctx, AnyContractName, MethodReturningSeenStruct, testStruct, actual))
require.NoError(t, cr.GetLatestValue(ctx, AnyContractName, MethodReturningSeenStruct, primitives.Unconfirmed, testStruct, actual))

expected := &TestStructWithExtraField{
ExtraField: AnyExtraValue,
Expand All @@ -167,7 +168,7 @@ func runChainReaderGetLatestValueInterfaceTests[T TestingT[T]](t T, tester Chain

result := &TestStruct{}
assert.Eventually(t, func() bool {
err := cr.GetLatestValue(ctx, AnyContractName, EventName, nil, &result)
err := cr.GetLatestValue(ctx, AnyContractName, EventName, primitives.Unconfirmed, nil, &result)
return err == nil && reflect.DeepEqual(result, &ts)
}, tester.MaxWaitTimeForEvents(), time.Millisecond*10)
},
Expand All @@ -180,7 +181,7 @@ func runChainReaderGetLatestValueInterfaceTests[T TestingT[T]](t T, tester Chain
require.NoError(t, cr.Bind(ctx, tester.GetBindings(t)))

result := &TestStruct{}
err := cr.GetLatestValue(ctx, AnyContractName, EventName, nil, &result)
err := cr.GetLatestValue(ctx, AnyContractName, EventName, primitives.Unconfirmed, nil, &result)
assert.True(t, errors.Is(err, types.ErrNotFound))
},
},
Expand All @@ -198,13 +199,13 @@ func runChainReaderGetLatestValueInterfaceTests[T TestingT[T]](t T, tester Chain
filterParams := &FilterEventParams{Field: *ts0.Field}
assert.Never(t, func() bool {
result := &TestStruct{}
err := cr.GetLatestValue(ctx, AnyContractName, EventWithFilterName, filterParams, &result)
err := cr.GetLatestValue(ctx, AnyContractName, EventWithFilterName, primitives.Unconfirmed, filterParams, &result)
return err == nil && reflect.DeepEqual(result, &ts1)
}, tester.MaxWaitTimeForEvents(), time.Millisecond*10)
// get the result one more time to verify it.
// Using the result from the Never statement by creating result outside the block is a data race
result := &TestStruct{}
err := cr.GetLatestValue(ctx, AnyContractName, EventWithFilterName, filterParams, &result)
err := cr.GetLatestValue(ctx, AnyContractName, EventWithFilterName, primitives.Unconfirmed, filterParams, &result)
require.NoError(t, err)
assert.Equal(t, &ts0, result)
},
Expand Down

0 comments on commit 49b4030

Please sign in to comment.