Skip to content

Commit

Permalink
Change Confirmations to Confidence
Browse files Browse the repository at this point in the history
`Confidence` is a different approach to mapping a chain agnostic concept of confidence that
an event or transaction can or should be acted on. `Confidence` is intended to map to defined
levels of confirmations on EVM chains and other states on other chains.

Only two levels of `Confidence` exist by default to define the boundaries: `Highest` and
`Lowest`. This creates an inclusive range for all chain configurable `Confidence` levels and
can be treated as % confidence that an event or transaction can or should be acted on.
  • Loading branch information
EasterTheBunny committed May 9, 2024
1 parent 3da40ac commit 610c769
Show file tree
Hide file tree
Showing 19 changed files with 212 additions and 81 deletions.
29 changes: 10 additions & 19 deletions core/chains/evm/logpoller/orm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -613,13 +613,14 @@ func TestORM_IndexedLogs(t *testing.T) {
}

limiter := query.NewLimitAndSort(query.Limit{}, query.NewSortBySequence(query.Asc))
confidence, _ := query.Confidence(primitives.Lowest)
standardFilter := func(topicIdx uint64, topicValues []uint64) query.KeyFilter {
return query.KeyFilter{
Expressions: []query.Expression{
logpoller.NewAddressFilter(addr),
logpoller.NewEventSigFilter(eventSig),
filtersForTopics(topicIdx, topicValues),
query.Confirmation(primitives.Unconfirmed),
confidence,
},
}
}
Expand Down Expand Up @@ -705,7 +706,7 @@ func TestORM_IndexedLogs(t *testing.T) {
logpoller.NewEventByTopicFilter(1, []primitives.ValueComparator{
{Value: logpoller.EvmWord(2).Hex(), Operator: primitives.Gte},
}),
query.Confirmation(primitives.Unconfirmed),
confidence,
},
}

Expand All @@ -724,7 +725,7 @@ func TestORM_IndexedLogs(t *testing.T) {
logpoller.NewEventByTopicFilter(topicIdx, []primitives.ValueComparator{
{Value: logpoller.EvmWord(max).Hex(), Operator: primitives.Lte},
}),
query.Confirmation(primitives.Unconfirmed),
confidence,
},
}
}
Expand Down Expand Up @@ -874,6 +875,7 @@ func TestORM_DataWords(t *testing.T) {
},
}))

confidence, _ := query.Confidence(primitives.Lowest)
wordFilter := func(wordIdx uint8, word1, word2 uint64) query.KeyFilter {
return query.KeyFilter{
Expressions: []query.Expression{
Expand All @@ -885,7 +887,7 @@ func TestORM_DataWords(t *testing.T) {
logpoller.NewEventByWordFilter(eventSig, wordIdx, []primitives.ValueComparator{
{Value: logpoller.EvmWord(word2).Hex(), Operator: primitives.Lte},
}),
query.Confirmation(primitives.Unconfirmed),
confidence,
},
}
}
Expand Down Expand Up @@ -952,7 +954,7 @@ func TestORM_DataWords(t *testing.T) {
logpoller.NewEventByWordFilter(eventSig, 0, []primitives.ValueComparator{
{Value: logpoller.EvmWord(1).Hex(), Operator: primitives.Gte},
}),
query.Confirmation(primitives.Unconfirmed),
confidence,
},
}

Expand Down Expand Up @@ -1668,18 +1670,6 @@ func TestSelectLogsCreatedAfter(t *testing.T) {
}

filter := func(timestamp time.Time, confs evmtypes.Confirmations, topicIdx int, topicVals []common.Hash) query.KeyFilter {
var queryConfs primitives.ConfirmationLevel

switch confs {
case evmtypes.Finalized:
queryConfs = primitives.Finalized
case evmtypes.Unconfirmed:
queryConfs = primitives.Unconfirmed
default:
fmt.Println("default")
queryConfs = primitives.ConfirmationLevel(confs)
}

filters := []query.Expression{
logpoller.NewAddressFilter(address),
logpoller.NewEventSigFilter(event),
Expand All @@ -1703,7 +1693,7 @@ func TestSelectLogsCreatedAfter(t *testing.T) {

filters = append(filters, []query.Expression{
query.Timestamp(uint64(timestamp.Unix()), primitives.Gt),
query.Confirmation(queryConfs),
logpoller.NewConfirmationsFilter(int(confs)),
}...)

return query.KeyFilter{
Expand Down Expand Up @@ -1971,6 +1961,7 @@ func TestSelectLogsDataWordBetween(t *testing.T) {
},
}

low, _ := query.Confidence(primitives.Lowest)
wordFilter := func(word uint64) query.KeyFilter {
return query.KeyFilter{
Expressions: []query.Expression{
Expand All @@ -1982,7 +1973,7 @@ func TestSelectLogsDataWordBetween(t *testing.T) {
logpoller.NewEventByWordFilter(eventSig, 1, []primitives.ValueComparator{
{Value: logpoller.EvmWord(word).Hex(), Operator: primitives.Gte},
}),
query.Confirmation(primitives.Unconfirmed),
low,
},
}
}
Expand Down
48 changes: 36 additions & 12 deletions core/chains/evm/logpoller/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (

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

evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
)

Expand Down Expand Up @@ -60,19 +59,17 @@ func (v *pgDSLParser) Block(p primitives.Block) {
)
}

func (v *pgDSLParser) Confirmations(p primitives.Confirmations) {
switch p.ConfirmationLevel {
case primitives.Finalized:
func (v *pgDSLParser) Confidence(p primitives.Confidence) {
switch p.ConfidenceLevel {
case primitives.Highest:
// the highest level of confidence maps to finalized
v.expression = v.nestedConfQuery(true, 0)
case primitives.Unconfirmed:
// Unconfirmed in the evm relayer is an alias to the case of 0 confirmations
// set the level to the number 0 and fallthrough to the default case
p.ConfirmationLevel = primitives.ConfirmationLevel(0)

fallthrough
case primitives.Lowest:
v.expression = v.nestedConfQuery(false, 0)
default:
// the default case passes the confirmation level as a number directly to a subquery
v.expression = v.nestedConfQuery(false, uint64(evmtypes.Confirmations(p.ConfirmationLevel)))
v.err = errors.New("unrecognized confidence level; use confidence to confirmations mappings instead")

return
}
}

Expand Down Expand Up @@ -193,6 +190,16 @@ func (v *pgDSLParser) VisitEventTopicsByValueFilter(p *eventByTopicFilter) {
}
}

func (v *pgDSLParser) VisitConfirmationsFilter(p *confirmationsFilter) {
switch p.Confirmations {
case int(evmtypes.Finalized):
// the highest level of confidence maps to finalized
v.expression = v.nestedConfQuery(true, 0)
default:
v.expression = v.nestedConfQuery(false, uint64(p.Confirmations))
}
}

func makeComp(comp primitives.ValueComparator, args *queryArgs, field, subfield, pattern string) (string, error) {
cmp, err := cmpOpToString(comp.Operator)
if err != nil {
Expand Down Expand Up @@ -502,3 +509,20 @@ func (f *eventByTopicFilter) Accept(visitor primitives.Visitor) {
v.VisitEventTopicsByValueFilter(f)
}
}

type confirmationsFilter struct {
Confirmations int
}

func NewConfirmationsFilter(confirmations int) query.Expression {
return query.Expression{Primitive: &confirmationsFilter{
Confirmations: confirmations,
}}
}

func (f *confirmationsFilter) Accept(visitor primitives.Visitor) {
switch v := visitor.(type) {
case *pgDSLParser:
v.VisitConfirmationsFilter(f)
}
}
47 changes: 41 additions & 6 deletions core/chains/evm/logpoller/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,14 +131,17 @@ func TestDSLParser(t *testing.T) {
t.Run("basic query with default primitives no order by and cursor", func(t *testing.T) {
t.Parallel()

high, _ := query.Confidence(primitives.Highest)
low, _ := query.Confidence(primitives.Lowest)

parser := &pgDSLParser{}
chainID := big.NewInt(1)
expressions := []query.Expression{
query.Timestamp(10, primitives.Eq),
query.TxHash(common.HexToHash("0x84").String()),
query.Block(99, primitives.Neq),
query.Confirmation(primitives.Finalized),
query.Confirmation(primitives.Unconfirmed),
high,
low,
}
limiter := query.NewLimitAndSort(query.CursorLimit("10-0x42-20", query.CursorPrevious, 20))

Expand Down Expand Up @@ -167,7 +170,9 @@ func TestDSLParser(t *testing.T) {
t.Run("finalized", func(t *testing.T) {
parser := &pgDSLParser{}
chainID := big.NewInt(1)
expressions := []query.Expression{query.Confirmation(primitives.Finalized)}

high, _ := query.Confidence(primitives.Highest)
expressions := []query.Expression{high}
limiter := query.LimitAndSort{}

result, args, err := parser.buildQuery(chainID, expressions, limiter)
Expand All @@ -185,7 +190,28 @@ func TestDSLParser(t *testing.T) {
t.Run("unconfirmed", func(t *testing.T) {
parser := &pgDSLParser{}
chainID := big.NewInt(1)
expressions := []query.Expression{query.Confirmation(primitives.Unconfirmed)}

low, _ := query.Confidence(primitives.Lowest)
expressions := []query.Expression{low}
limiter := query.LimitAndSort{}

result, args, err := parser.buildQuery(chainID, expressions, limiter)
expected := "SELECT evm.logs.* " +
"FROM evm.logs " +
"WHERE evm_chain_id = :evm_chain_id " +
"AND block_number <= (SELECT greatest(block_number - :confs_0, 0) FROM evm.log_poller_blocks WHERE evm_chain_id = :evm_chain_id ORDER BY block_number DESC LIMIT 1)"

require.NoError(t, err)
assert.Equal(t, expected, result)

assertArgs(t, args, 2)
})

t.Run("exact confirmations", func(t *testing.T) {
parser := &pgDSLParser{}
chainID := big.NewInt(1)

expressions := []query.Expression{NewConfirmationsFilter(25)}
limiter := query.LimitAndSort{}

result, args, err := parser.buildQuery(chainID, expressions, limiter)
Expand All @@ -197,6 +223,11 @@ func TestDSLParser(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, expected, result)

confirmations, ok := args.args["confs_0"]

require.True(t, ok)
require.Equal(t, uint64(25), confirmations)

assertArgs(t, args, 2)
})
})
Expand Down Expand Up @@ -256,14 +287,16 @@ func TestDSLParser(t *testing.T) {

parser := &pgDSLParser{}
chainID := big.NewInt(1)

low, _ := query.Confidence(primitives.Lowest)
expressions := []query.Expression{
{BoolExpression: query.BoolExpression{
Expressions: []query.Expression{
query.Timestamp(10, primitives.Gte),
{BoolExpression: query.BoolExpression{
Expressions: []query.Expression{
query.TxHash(common.HexToHash("0x84").Hex()),
query.Confirmation(primitives.Unconfirmed),
low,
},
BoolOperator: query.OR,
}},
Expand Down Expand Up @@ -298,6 +331,8 @@ func TestDSLParser(t *testing.T) {

parser := &pgDSLParser{}
chainID := big.NewInt(1)

low, _ := query.Confidence(primitives.Lowest)
expressions := []query.Expression{
{BoolExpression: query.BoolExpression{
Expressions: []query.Expression{
Expand All @@ -307,7 +342,7 @@ func TestDSLParser(t *testing.T) {
query.TxHash(common.HexToHash("0x84").Hex()),
{BoolExpression: query.BoolExpression{
Expressions: []query.Expression{
query.Confirmation(primitives.Unconfirmed),
low,
wordFilter,
},
BoolOperator: query.AND,
Expand Down
2 changes: 1 addition & 1 deletion core/scripts/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ require (
github.com/prometheus/client_golang v1.17.0
github.com/shopspring/decimal v1.3.1
github.com/smartcontractkit/chainlink-automation v1.0.3
github.com/smartcontractkit/chainlink-common v0.1.7-0.20240507142850-569a909ad3b4
github.com/smartcontractkit/chainlink-common v0.1.7-0.20240508145405-e8e6027d92a7
github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772
github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000
github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c
Expand Down
4 changes: 2 additions & 2 deletions core/scripts/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1185,8 +1185,8 @@ github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCq
github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE=
github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs=
github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU=
github.com/smartcontractkit/chainlink-common v0.1.7-0.20240507142850-569a909ad3b4 h1:6PP8T5py2K+0Vd+8LP0DlDvPKhyXXhz1i2RwKoFhKPI=
github.com/smartcontractkit/chainlink-common v0.1.7-0.20240507142850-569a909ad3b4/go.mod h1:sj0pjL+METqeYL9ibp0T8SXquymlaQsofa6bdfLgXX8=
github.com/smartcontractkit/chainlink-common v0.1.7-0.20240508145405-e8e6027d92a7 h1:a/c/ge5tIJN2bPQRxgDjUyXvwtfxnTduqLMOSNHKZK8=
github.com/smartcontractkit/chainlink-common v0.1.7-0.20240508145405-e8e6027d92a7/go.mod h1:sj0pjL+METqeYL9ibp0T8SXquymlaQsofa6bdfLgXX8=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee h1:eFuBKyEbL2b+eyfgV/Eu9+8HuCEev+IcBi+K9l1dG7g=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee/go.mod h1:uATrrJ8IsuBkOBJ46USuf73gz9gZy5k5bzGE5/ji/rc=
github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo=
Expand Down
Loading

0 comments on commit 610c769

Please sign in to comment.