From 0489ccf2f0e856a28e6220139190b0d2181d8f51 Mon Sep 17 00:00:00 2001 From: amirylm Date: Thu, 7 Mar 2024 18:55:02 +0200 Subject: [PATCH] block window utilities --- .../evmregistry/v21/logprovider/window.go | 39 +++++ .../v21/logprovider/window_test.go | 157 ++++++++++++++++++ 2 files changed, 196 insertions(+) create mode 100644 core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/window.go create mode 100644 core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/window_test.go diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/window.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/window.go new file mode 100644 index 00000000000..8042fe5cb05 --- /dev/null +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/window.go @@ -0,0 +1,39 @@ +package logprovider + +import ( + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" +) + +// BlockWindow returns the start and end block for the given window. +func BlockWindow(block int64, blockRate int) (start int64, end int64) { + windowSize := int64(blockRate) + if windowSize == 0 { + return block, block + } + start = block - (block % windowSize) + end = block + (windowSize - (block % windowSize) - 1) + return +} + +// LogSorter sorts the logs based on block number, tx hash and log index. +// returns true if b should come before a. +func LogSorter(a, b logpoller.Log) bool { + return LogComparator(a, b) > 0 +} + +// LogComparator compares the logs based on block number, tx hash and log index. +// +// Returns: +// +// -1 if a < b +// 0 if a == b +// +1 if a > b +func LogComparator(a, b logpoller.Log) int { + if b.BlockNumber != a.BlockNumber { + return int(a.BlockNumber - b.BlockNumber) + } + if txDiff := a.TxHash.Big().Cmp(b.TxHash.Big()); txDiff != 0 { + return txDiff + } + return int(a.LogIndex - b.LogIndex) +} diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/window_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/window_test.go new file mode 100644 index 00000000000..4a1dadfc410 --- /dev/null +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/window_test.go @@ -0,0 +1,157 @@ +package logprovider + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" +) + +func TestBlockWindow(t *testing.T) { + tests := []struct { + name string + block int64 + blockRate int + wantStart int64 + wantEnd int64 + }{ + { + name: "block 0, blockRate 1", + block: 0, + blockRate: 1, + wantStart: 0, + wantEnd: 0, + }, + { + name: "block 0, blockRate 4", + block: 0, + blockRate: 4, + wantStart: 0, + wantEnd: 3, + }, + { + name: "block 81, blockRate 4", + block: 81, + blockRate: 4, + wantStart: 80, + wantEnd: 83, + }, + { + name: "block 83, blockRate 4", + block: 83, + blockRate: 4, + wantStart: 80, + wantEnd: 83, + }, + { + name: "block 84, blockRate 4", + block: 84, + blockRate: 4, + wantStart: 84, + wantEnd: 87, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + start, end := BlockWindow(tc.block, tc.blockRate) + require.Equal(t, tc.wantStart, start) + require.Equal(t, tc.wantEnd, end) + }) + } +} + +func TestLogComparatorSorter(t *testing.T) { + tests := []struct { + name string + a logpoller.Log + b logpoller.Log + wantCmp int + wantSort bool + }{ + { + name: "a == b", + a: logpoller.Log{ + BlockNumber: 1, + TxHash: common.HexToHash("0x1"), + LogIndex: 1, + }, + b: logpoller.Log{ + BlockNumber: 1, + TxHash: common.HexToHash("0x1"), + LogIndex: 1, + }, + wantCmp: 0, + wantSort: false, + }, + { + name: "a < b: block number", + a: logpoller.Log{ + BlockNumber: 1, + TxHash: common.HexToHash("0x1"), + LogIndex: 1, + }, + b: logpoller.Log{ + BlockNumber: 2, + TxHash: common.HexToHash("0x1"), + LogIndex: 1, + }, + wantCmp: -1, + wantSort: false, + }, + { + name: "a < b: log index", + a: logpoller.Log{ + BlockNumber: 1, + TxHash: common.HexToHash("0x1"), + LogIndex: 1, + }, + b: logpoller.Log{ + BlockNumber: 1, + TxHash: common.HexToHash("0x1"), + LogIndex: 2, + }, + wantCmp: -1, + wantSort: false, + }, + { + name: "a > b: block number", + a: logpoller.Log{ + BlockNumber: 3, + TxHash: common.HexToHash("0x1"), + LogIndex: 1, + }, + b: logpoller.Log{ + BlockNumber: 2, + TxHash: common.HexToHash("0x1"), + LogIndex: 1, + }, + wantCmp: 1, + wantSort: true, + }, + { + name: "a > b: log index", + a: logpoller.Log{ + BlockNumber: 1, + TxHash: common.HexToHash("0x1"), + LogIndex: 3, + }, + b: logpoller.Log{ + BlockNumber: 1, + TxHash: common.HexToHash("0x1"), + LogIndex: 2, + }, + wantCmp: 1, + wantSort: true, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + require.Equal(t, tc.wantCmp, LogComparator(tc.a, tc.b)) + require.Equal(t, tc.wantSort, LogSorter(tc.a, tc.b)) + }) + } +}