From 0c63446ae535671b67a253ac1c1d43860ebeb653 Mon Sep 17 00:00:00 2001 From: Cedric Date: Tue, 12 Dec 2023 10:52:16 +0000 Subject: [PATCH 01/29] [BCF-2760] Flakey test detection improvements (#11470) * [BCF-2760] Flakey test detection improvements * [BCF-2760] Dedupe test and subtest entries --- tools/flakeytests/reporter.go | 69 +++++++-- tools/flakeytests/reporter_test.go | 103 ++++++++++--- tools/flakeytests/runner.go | 222 ++++++++++++++++++++++------- tools/flakeytests/runner_test.go | 106 +++++++++++--- 4 files changed, 399 insertions(+), 101 deletions(-) diff --git a/tools/flakeytests/reporter.go b/tools/flakeytests/reporter.go index 6696ec29a40..f17a44ef9f1 100644 --- a/tools/flakeytests/reporter.go +++ b/tools/flakeytests/reporter.go @@ -11,6 +11,12 @@ import ( "time" ) +const ( + messageType_flakeyTest = "flakey_test" + messageType_runReport = "run_report" + messageType_packagePanic = "package_panic" +) + type pushRequest struct { Streams []stream `json:"streams"` } @@ -20,16 +26,28 @@ type stream struct { Values [][]string `json:"values"` } +type BaseMessage struct { + MessageType string `json:"message_type"` + Context +} + type flakeyTest struct { + BaseMessage Package string `json:"package"` TestName string `json:"test_name"` FQTestName string `json:"fq_test_name"` - Context } -type numFlakes struct { - NumFlakes int `json:"num_flakes"` - Context +type packagePanic struct { + BaseMessage + Package string `json:"package"` +} + +type runReport struct { + BaseMessage + NumPackagePanics int `json:"num_package_panics"` + NumFlakes int `json:"num_flakes"` + NumCombined int `json:"num_combined"` } type Context struct { @@ -48,17 +66,21 @@ type LokiReporter struct { ctx Context } -func (l *LokiReporter) createRequest(flakeyTests map[string]map[string]struct{}) (pushRequest, error) { +func (l *LokiReporter) createRequest(report *Report) (pushRequest, error) { vs := [][]string{} now := l.now() nows := fmt.Sprintf("%d", now.UnixNano()) - for pkg, tests := range flakeyTests { + + for pkg, tests := range report.tests { for t := range tests { d, err := json.Marshal(flakeyTest{ + BaseMessage: BaseMessage{ + MessageType: messageType_flakeyTest, + Context: l.ctx, + }, Package: pkg, TestName: t, FQTestName: fmt.Sprintf("%s:%s", pkg, t), - Context: l.ctx, }) if err != nil { return pushRequest{}, err @@ -67,10 +89,35 @@ func (l *LokiReporter) createRequest(flakeyTests map[string]map[string]struct{}) } } - // Flakes are store in a map[string][]string, so to count them, we can't just do len(flakeyTests), + // Flakes are stored in a map[string][]string, so to count them, we can't just do len(flakeyTests), // as that will get us the number of flakey packages, not the number of flakes tests. // However, we do emit one log line per flakey test above, so use that to count our flakes. - f, err := json.Marshal(numFlakes{NumFlakes: len(vs), Context: l.ctx}) + numFlakes := len(vs) + + for pkg := range report.packagePanics { + d, err := json.Marshal(packagePanic{ + BaseMessage: BaseMessage{ + MessageType: messageType_packagePanic, + Context: l.ctx, + }, + Package: pkg, + }) + if err != nil { + return pushRequest{}, err + } + + vs = append(vs, []string{nows, string(d)}) + } + + f, err := json.Marshal(runReport{ + BaseMessage: BaseMessage{ + MessageType: messageType_runReport, + Context: l.ctx, + }, + NumFlakes: numFlakes, + NumPackagePanics: len(report.packagePanics), + NumCombined: numFlakes + len(report.packagePanics), + }) if err != nil { return pushRequest{}, nil } @@ -120,8 +167,8 @@ func (l *LokiReporter) makeRequest(pushReq pushRequest) error { return err } -func (l *LokiReporter) Report(flakeyTests map[string]map[string]struct{}) error { - pushReq, err := l.createRequest(flakeyTests) +func (l *LokiReporter) Report(report *Report) error { + pushReq, err := l.createRequest(report) if err != nil { return err } diff --git a/tools/flakeytests/reporter_test.go b/tools/flakeytests/reporter_test.go index 9cb2c8e9f7d..15650fc7bd1 100644 --- a/tools/flakeytests/reporter_test.go +++ b/tools/flakeytests/reporter_test.go @@ -12,68 +12,131 @@ import ( func TestMakeRequest_SingleTest(t *testing.T) { now := time.Now() ts := fmt.Sprintf("%d", now.UnixNano()) - ft := map[string]map[string]struct{}{ - "core/assets": map[string]struct{}{ - "TestLink": struct{}{}, + r := &Report{ + tests: map[string]map[string]int{ + "core/assets": map[string]int{ + "TestLink": 1, + }, }, } lr := &LokiReporter{auth: "bla", host: "bla", command: "go_core_tests", now: func() time.Time { return now }} - pr, err := lr.createRequest(ft) + pr, err := lr.createRequest(r) require.NoError(t, err) assert.Len(t, pr.Streams, 1) assert.Equal(t, pr.Streams[0].Stream, map[string]string{"command": "go_core_tests", "app": "flakey-test-reporter"}) assert.ElementsMatch(t, pr.Streams[0].Values, [][]string{ - {ts, `{"package":"core/assets","test_name":"TestLink","fq_test_name":"core/assets:TestLink","commit_sha":"","repository":"","event_type":""}`}, - {ts, `{"num_flakes":1,"commit_sha":"","repository":"","event_type":""}`}, + {ts, `{"message_type":"flakey_test","commit_sha":"","repository":"","event_type":"","package":"core/assets","test_name":"TestLink","fq_test_name":"core/assets:TestLink"}`}, + {ts, `{"message_type":"run_report","commit_sha":"","repository":"","event_type":"","num_package_panics":0,"num_flakes":1,"num_combined":1}`}, }) } func TestMakeRequest_MultipleTests(t *testing.T) { now := time.Now() ts := fmt.Sprintf("%d", now.UnixNano()) - ft := map[string]map[string]struct{}{ - "core/assets": map[string]struct{}{ - "TestLink": struct{}{}, - "TestCore": struct{}{}, + r := &Report{ + tests: map[string]map[string]int{ + "core/assets": map[string]int{ + "TestLink": 1, + "TestCore": 1, + }, }, } lr := &LokiReporter{auth: "bla", host: "bla", command: "go_core_tests", now: func() time.Time { return now }} - pr, err := lr.createRequest(ft) + pr, err := lr.createRequest(r) require.NoError(t, err) assert.Len(t, pr.Streams, 1) assert.Equal(t, pr.Streams[0].Stream, map[string]string{"command": "go_core_tests", "app": "flakey-test-reporter"}) assert.ElementsMatch(t, pr.Streams[0].Values, [][]string{ - {ts, `{"package":"core/assets","test_name":"TestLink","fq_test_name":"core/assets:TestLink","commit_sha":"","repository":"","event_type":""}`}, - {ts, `{"package":"core/assets","test_name":"TestCore","fq_test_name":"core/assets:TestCore","commit_sha":"","repository":"","event_type":""}`}, - {ts, `{"num_flakes":2,"commit_sha":"","repository":"","event_type":""}`}, + {ts, `{"message_type":"flakey_test","commit_sha":"","repository":"","event_type":"","package":"core/assets","test_name":"TestLink","fq_test_name":"core/assets:TestLink"}`}, + {ts, `{"message_type":"flakey_test","commit_sha":"","repository":"","event_type":"","package":"core/assets","test_name":"TestCore","fq_test_name":"core/assets:TestCore"}`}, + {ts, `{"message_type":"run_report","commit_sha":"","repository":"","event_type":"","num_package_panics":0,"num_flakes":2,"num_combined":2}`}, }) } func TestMakeRequest_NoTests(t *testing.T) { now := time.Now() ts := fmt.Sprintf("%d", now.UnixNano()) - ft := map[string]map[string]struct{}{} + r := NewReport() lr := &LokiReporter{auth: "bla", host: "bla", command: "go_core_tests", now: func() time.Time { return now }} - pr, err := lr.createRequest(ft) + pr, err := lr.createRequest(r) require.NoError(t, err) assert.Len(t, pr.Streams, 1) assert.Equal(t, pr.Streams[0].Stream, map[string]string{"command": "go_core_tests", "app": "flakey-test-reporter"}) assert.ElementsMatch(t, pr.Streams[0].Values, [][]string{ - {ts, `{"num_flakes":0,"commit_sha":"","repository":"","event_type":""}`}, + {ts, `{"message_type":"run_report","commit_sha":"","repository":"","event_type":"","num_package_panics":0,"num_flakes":0,"num_combined":0}`}, }) } func TestMakeRequest_WithContext(t *testing.T) { now := time.Now() ts := fmt.Sprintf("%d", now.UnixNano()) - ft := map[string]map[string]struct{}{} + r := NewReport() lr := &LokiReporter{auth: "bla", host: "bla", command: "go_core_tests", now: func() time.Time { return now }, ctx: Context{CommitSHA: "42"}} - pr, err := lr.createRequest(ft) + pr, err := lr.createRequest(r) require.NoError(t, err) assert.Len(t, pr.Streams, 1) assert.Equal(t, pr.Streams[0].Stream, map[string]string{"command": "go_core_tests", "app": "flakey-test-reporter"}) assert.ElementsMatch(t, pr.Streams[0].Values, [][]string{ - {ts, `{"num_flakes":0,"commit_sha":"42","repository":"","event_type":""}`}, + {ts, `{"message_type":"run_report","commit_sha":"42","repository":"","event_type":"","num_package_panics":0,"num_flakes":0,"num_combined":0}`}, }) } + +func TestMakeRequest_Panics(t *testing.T) { + now := time.Now() + ts := fmt.Sprintf("%d", now.UnixNano()) + r := &Report{ + tests: map[string]map[string]int{ + "core/assets": map[string]int{ + "TestLink": 1, + }, + }, + packagePanics: map[string]int{ + "core/assets": 1, + }, + } + lr := &LokiReporter{auth: "bla", host: "bla", command: "go_core_tests", now: func() time.Time { return now }} + pr, err := lr.createRequest(r) + require.NoError(t, err) + assert.Len(t, pr.Streams, 1) + assert.Equal(t, pr.Streams[0].Stream, map[string]string{"command": "go_core_tests", "app": "flakey-test-reporter"}) + + assert.ElementsMatch(t, pr.Streams[0].Values, [][]string{ + {ts, `{"message_type":"flakey_test","commit_sha":"","repository":"","event_type":"","package":"core/assets","test_name":"TestLink","fq_test_name":"core/assets:TestLink"}`}, + {ts, `{"message_type":"package_panic","commit_sha":"","repository":"","event_type":"","package":"core/assets"}`}, + {ts, `{"message_type":"run_report","commit_sha":"","repository":"","event_type":"","num_package_panics":1,"num_flakes":1,"num_combined":2}`}, + }) +} + +func TestDedupeEntries(t *testing.T) { + r := &Report{ + tests: map[string]map[string]int{ + "core/assets": map[string]int{ + "TestSomethingAboutAssets/test_1": 2, + "TestSomethingAboutAssets": 4, + "TestSomeOtherTest": 1, + "TestSomethingAboutAssets/test_2": 2, + "TestFinalTest/test_1": 1, + }, + "core/services/important_service": map[string]int{ + "TestAnImportantService/a_subtest": 1, + }, + }, + } + + otherReport, err := dedupeEntries(r) + require.NoError(t, err) + + expectedMap := map[string]map[string]int{ + "core/assets": map[string]int{ + "TestSomethingAboutAssets/test_1": 2, + "TestSomeOtherTest": 1, + "TestSomethingAboutAssets/test_2": 2, + "TestFinalTest/test_1": 1, + }, + "core/services/important_service": map[string]int{ + "TestAnImportantService/a_subtest": 1, + }, + } + assert.Equal(t, expectedMap, otherReport.tests) +} diff --git a/tools/flakeytests/runner.go b/tools/flakeytests/runner.go index d935000222f..97402633f38 100644 --- a/tools/flakeytests/runner.go +++ b/tools/flakeytests/runner.go @@ -11,6 +11,7 @@ import ( "os" "os/exec" "regexp" + "sort" "strings" "time" ) @@ -32,10 +33,10 @@ type tester interface { } type reporter interface { - Report(map[string]map[string]struct{}) error + Report(r *Report) error } -type parseFn func(readers ...io.Reader) (map[string]map[string]int, error) +type parseFn func(readers ...io.Reader) (*Report, error) func NewRunner(readers []io.Reader, reporter reporter, numReruns int) *Runner { tc := &testCommand{ @@ -60,9 +61,14 @@ type testCommand struct { func (t *testCommand) test(pkg string, tests []string, w io.Writer) error { replacedPkg := strings.Replace(pkg, t.repo, "", -1) - testFilter := strings.Join(tests, "|") cmd := exec.Command(t.command, fmt.Sprintf(".%s", replacedPkg)) //#nosec - cmd.Env = append(os.Environ(), fmt.Sprintf("TEST_FLAGS=-run %s", testFilter)) + cmd.Env = os.Environ() + + if len(tests) > 0 { + testFilter := strings.Join(tests, "|") + cmd.Env = append(cmd.Env, fmt.Sprintf("TEST_FLAGS=-run %s", testFilter)) + } + cmd.Stdout = io.MultiWriter(os.Stdout, w) cmd.Stderr = io.MultiWriter(os.Stderr, w) t.overrides(cmd) @@ -84,8 +90,8 @@ func newEvent(b []byte) (*TestEvent, error) { return e, err } -func parseOutput(readers ...io.Reader) (map[string]map[string]int, error) { - tests := map[string]map[string]int{} +func parseOutput(readers ...io.Reader) (*Report, error) { + report := NewReport() for _, r := range readers { s := bufio.NewScanner(r) for s.Scan() { @@ -105,24 +111,32 @@ func parseOutput(readers ...io.Reader) (map[string]map[string]int, error) { return nil, err } - // We're only interested in test failures, for which - // both Package and Test would be present. - if e.Package == "" || e.Test == "" { - continue - } - switch e.Action { case "fail": - if tests[e.Package] == nil { - tests[e.Package] = map[string]int{} + // Fail logs come in two forms: + // - with e.Package && e.Test, in which case it indicates a test failure. + // - with e.Package only, which indicates that the package test has failed, + // or possible that there has been a panic in an out-of-process goroutine running + // as part of the tests. + // + // We can ignore the last case because a package failure will be accounted elsewhere, either + // in the form of a failing test entry, or in the form of a panic output log, covered below. + if e.Test == "" { + continue } - tests[e.Package][e.Test]++ + + report.IncTest(e.Package, e.Test) case "output": if panicRe.MatchString(e.Output) { - if tests[e.Package] == nil { - tests[e.Package] = map[string]int{} + // Similar to the above, a panic can come in two forms: + // - attached to a test (i.e. with e.Test != ""), in which case + // we'll treat it like a failing test. + // - package-scoped, in which case we'll treat it as a package panic. + if e.Test != "" { + report.IncTest(e.Package, e.Test) + } else { + report.IncPackagePanic(e.Package) } - tests[e.Package][e.Test]++ } } } @@ -131,75 +145,183 @@ func parseOutput(readers ...io.Reader) (map[string]map[string]int, error) { return nil, err } } - return tests, nil + + return report, nil } type exitCoder interface { ExitCode() int } -func (r *Runner) runTests(failedTests map[string]map[string]int) (map[string]map[string]struct{}, error) { - suspectedFlakes := map[string]map[string]struct{}{} +type Report struct { + tests map[string]map[string]int + packagePanics map[string]int +} + +func NewReport() *Report { + return &Report{ + tests: map[string]map[string]int{}, + packagePanics: map[string]int{}, + } +} + +func (r *Report) HasFlakes() bool { + return len(r.tests) > 0 || len(r.packagePanics) > 0 +} + +func (r *Report) SetTest(pkg, test string, val int) { + if r.tests[pkg] == nil { + r.tests[pkg] = map[string]int{} + } + r.tests[pkg][test] = val +} + +func (r *Report) IncTest(pkg string, test string) { + if r.tests[pkg] == nil { + r.tests[pkg] = map[string]int{} + } + r.tests[pkg][test]++ +} - for pkg, tests := range failedTests { +func (r *Report) IncPackagePanic(pkg string) { + r.packagePanics[pkg]++ +} + +func (r *Runner) runTest(pkg string, tests []string) (*Report, error) { + var out bytes.Buffer + err := r.testCommand.test(pkg, tests, &out) + if err != nil { + log.Printf("Test command errored: %s\n", err) + // There was an error because the command failed with a non-zero + // exit code. This could just mean that the test failed again, so let's + // keep going. + var exErr exitCoder + if errors.As(err, &exErr) && exErr.ExitCode() > 0 { + return r.parse(&out) + } + return nil, err + } + + return r.parse(&out) +} + +func (r *Runner) runTests(rep *Report) (*Report, error) { + report := NewReport() + + // We need to deal with two types of flakes here: + // - flakes where we know the test that failed; in this case, we just rerun the failing test in question + // - flakes where we don't know what test failed. These are flakes where a panic occurred in an out-of-process goroutine, + // thus failing the package as a whole. For these, we'll rerun the whole package again. + for pkg, tests := range rep.tests { ts := []string{} for test := range tests { ts = append(ts, test) } - log.Printf("Executing test command with parameters: pkg=%s, tests=%+v, numReruns=%d\n", pkg, ts, r.numReruns) + log.Printf("[FLAKEY_TEST] Executing test command with parameters: pkg=%s, tests=%+v, numReruns=%d\n", pkg, ts, r.numReruns) for i := 0; i < r.numReruns; i++ { - var out bytes.Buffer - - err := r.testCommand.test(pkg, ts, &out) + pr, err := r.runTest(pkg, ts) if err != nil { - log.Printf("Test command errored: %s\n", err) - // There was an error because the command failed with a non-zero - // exit code. This could just mean that the test failed again, so let's - // keep going. - var exErr exitCoder - if errors.As(err, &exErr) && exErr.ExitCode() > 0 { - continue + return report, err + } + + for t := range tests { + failures := pr.tests[pkg][t] + if failures == 0 { + report.SetTest(pkg, t, 1) } - return suspectedFlakes, err } - fr, err := r.parse(&out) + } + } + + for pkg := range rep.packagePanics { + log.Printf("[PACKAGE_PANIC]: Executing test command with parameters: pkg=%s, numReruns=%d\n", pkg, r.numReruns) + for i := 0; i < r.numReruns; i++ { + pr, err := r.runTest(pkg, []string{}) if err != nil { - return nil, err + return report, err } - for t := range tests { - failures := fr[pkg][t] - if failures == 0 { - if suspectedFlakes[pkg] == nil { - suspectedFlakes[pkg] = map[string]struct{}{} - } - suspectedFlakes[pkg][t] = struct{}{} - } + if pr.packagePanics[pkg] == 0 { + report.IncPackagePanic(pkg) + } + } + } + + return report, nil +} + +func isSubtest(tn string) bool { + return strings.Contains(tn, "/") +} + +func isSubtestOf(st, mt string) bool { + return isSubtest(st) && strings.Contains(st, mt) +} + +func dedupeEntries(report *Report) (*Report, error) { + out := NewReport() + out.packagePanics = report.packagePanics + for pkg, tests := range report.tests { + // Sort the test names + testNames := make([]string, 0, len(tests)) + for t := range tests { + testNames = append(testNames, t) + } + + sort.Strings(testNames) + + for i, tn := range testNames { + // Is this the last element? If it is, then add it to the deduped set. + // This is because a) it's a main test, in which case we add it because + // it has no subtests following it, or b) it's a subtest, which we always add. + if i == len(testNames)-1 { + out.SetTest(pkg, tn, report.tests[pkg][tn]) + continue } + + // Next, let's compare the current item to the next one in the alphabetical order. + // In all cases we want to add the current item, UNLESS the current item is a main test, + // and the following one is a subtest of the current item. + nextItem := testNames[i+1] + if !isSubtest(tn) && isSubtestOf(nextItem, tn) { + continue + } + + out.SetTest(pkg, tn, report.tests[pkg][tn]) } + } - return suspectedFlakes, nil + return out, nil } func (r *Runner) Run() error { - failedTests, err := r.parse(r.readers...) + parseReport, err := r.parse(r.readers...) if err != nil { return err } - suspectedFlakes, err := r.runTests(failedTests) + report, err := r.runTests(parseReport) if err != nil { return err } - if len(suspectedFlakes) > 0 { - log.Printf("ERROR: Suspected flakes found: %+v\n", suspectedFlakes) + if report.HasFlakes() { + log.Printf("ERROR: Suspected flakes found: %+v\n", report) } else { log.Print("SUCCESS: No suspected flakes detected") } - return r.reporter.Report(suspectedFlakes) + // Before reporting the errors, let's dedupe some entries: + // In actuality, a failing subtest will produce two failing test entries, + // namely one for the test as a whole, and one for the subtest. + // This leads to inaccurate metrics since a failing subtest is double-counted. + report, err = dedupeEntries(report) + if err != nil { + return err + } + + return r.reporter.Report(report) } diff --git a/tools/flakeytests/runner_test.go b/tools/flakeytests/runner_test.go index 31f300dcbee..64e2a6c968a 100644 --- a/tools/flakeytests/runner_test.go +++ b/tools/flakeytests/runner_test.go @@ -12,16 +12,16 @@ import ( ) type mockReporter struct { - entries map[string]map[string]struct{} + report *Report } -func (m *mockReporter) Report(entries map[string]map[string]struct{}) error { - m.entries = entries +func (m *mockReporter) Report(report *Report) error { + m.report = report return nil } func newMockReporter() *mockReporter { - return &mockReporter{entries: map[string]map[string]struct{}{}} + return &mockReporter{report: NewReport()} } func TestParser(t *testing.T) { @@ -29,9 +29,10 @@ func TestParser(t *testing.T) { ` r := strings.NewReader(output) - ts, err := parseOutput(r) + pr, err := parseOutput(r) require.NoError(t, err) + ts := pr.tests assert.Len(t, ts, 1) assert.Len(t, ts["github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"], 1) assert.Equal(t, ts["github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"]["TestLink"], 1) @@ -44,9 +45,10 @@ func TestParser_SkipsNonJSON(t *testing.T) { ` r := strings.NewReader(output) - ts, err := parseOutput(r) + pr, err := parseOutput(r) require.NoError(t, err) + ts := pr.tests assert.Len(t, ts, 1) assert.Len(t, ts["github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"], 1) assert.Equal(t, ts["github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"]["TestLink"], 1) @@ -58,9 +60,10 @@ func TestParser_PanicDueToLogging(t *testing.T) { ` r := strings.NewReader(output) - ts, err := parseOutput(r) + pr, err := parseOutput(r) require.NoError(t, err) + ts := pr.tests assert.Len(t, ts, 1) assert.Len(t, ts["github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"], 1) assert.Equal(t, ts["github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"]["TestAssets_LinkScanValue"], 1) @@ -85,7 +88,7 @@ func TestParser_SuccessfulOutput(t *testing.T) { r := strings.NewReader(output) ts, err := parseOutput(r) require.NoError(t, err) - assert.Len(t, ts, 0) + assert.Len(t, ts.tests, 0) } type testAdapter func(string, []string, io.Writer) error @@ -119,8 +122,8 @@ func TestRunner_WithFlake(t *testing.T) { // to only report one failure (not two as expected). err := r.Run() require.NoError(t, err) - assert.Len(t, m.entries, 1) - _, ok := m.entries["github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"]["TestLink"] + assert.Len(t, m.report.tests, 1) + _, ok := m.report.tests["github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"]["TestLink"] assert.True(t, ok) } @@ -154,8 +157,8 @@ func TestRunner_WithFailedPackage(t *testing.T) { // to only report one failure (not two as expected). err := r.Run() require.NoError(t, err) - assert.Len(t, m.entries, 1) - _, ok := m.entries["github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"]["TestLink"] + assert.Len(t, m.report.tests, 1) + _, ok := m.report.tests["github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"]["TestLink"] assert.True(t, ok) } @@ -180,7 +183,7 @@ func TestRunner_AllFailures(t *testing.T) { err := r.Run() require.NoError(t, err) - assert.Len(t, m.entries, 0) + assert.Len(t, m.report.tests, 0) } func TestRunner_RerunSuccessful(t *testing.T) { @@ -206,7 +209,7 @@ func TestRunner_RerunSuccessful(t *testing.T) { err := r.Run() require.NoError(t, err) - _, ok := m.entries["github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"]["TestLink"] + _, ok := m.report.tests["github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"]["TestLink"] assert.True(t, ok) } @@ -228,7 +231,7 @@ func TestRunner_RootLevelTest(t *testing.T) { err := r.Run() require.NoError(t, err) - _, ok := m.entries["github.com/smartcontractkit/chainlink/v2/"]["TestConfigDocs"] + _, ok := m.report.tests["github.com/smartcontractkit/chainlink/v2/"]["TestConfigDocs"] assert.True(t, ok) } @@ -255,7 +258,7 @@ func TestRunner_RerunFailsWithNonzeroExitCode(t *testing.T) { err := r.Run() require.NoError(t, err) - _, ok := m.entries["github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"]["TestLink"] + _, ok := m.report.tests["github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"]["TestLink"] assert.True(t, ok) } @@ -295,10 +298,25 @@ func TestRunner_RerunWithNonZeroExitCodeDoesntStopCommand(t *testing.T) { calls := index assert.Equal(t, 4, calls) - _, ok := m.entries["github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"]["TestLink"] + _, ok := m.report.tests["github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"]["TestLink"] assert.True(t, ok) } +// Used for integration tests +func TestSkippedForTests_Subtests(t *testing.T) { + if os.Getenv("FLAKEY_TEST_RUNNER_RUN_FIXTURE_TEST") != "1" { + t.Skip() + } + + t.Run("1: should fail", func(t *testing.T) { + assert.False(t, true) + }) + + t.Run("2: should fail", func(t *testing.T) { + assert.False(t, true) + }) +} + // Used for integration tests func TestSkippedForTests(t *testing.T) { if os.Getenv("FLAKEY_TEST_RUNNER_RUN_FIXTURE_TEST") != "1" { @@ -319,7 +337,51 @@ func TestSkippedForTests_Success(t *testing.T) { assert.True(t, true) } -func TestParsesPanicCorrectly(t *testing.T) { +func TestIntegration_DealsWithSubtests(t *testing.T) { + if testing.Short() { + t.Skip() + } + + output := ` +{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/tools/flakeytests/","Test":"TestSkippedForTests_Subtests/1:_should_fail","Elapsed":0} +{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/tools/flakeytests/","Test":"TestSkippedForTests_Subtests","Elapsed":0} +{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/tools/flakeytests/","Test":"TestSkippedForTests_Subtests/2:_should_fail","Elapsed":0} +` + + m := newMockReporter() + tc := &testCommand{ + repo: "github.com/smartcontractkit/chainlink/v2/tools/flakeytests", + command: "../bin/go_core_tests", + overrides: func(cmd *exec.Cmd) { + cmd.Env = append(cmd.Env, "FLAKEY_TESTRUNNER_RUN_FIXTURE_TEST=1") + cmd.Stdout = io.Discard + cmd.Stderr = io.Discard + }, + } + r := &Runner{ + numReruns: 2, + readers: []io.Reader{strings.NewReader(output)}, + testCommand: tc, + parse: parseOutput, + reporter: m, + } + + err := r.Run() + require.NoError(t, err) + expectedTests := map[string]map[string]int{ + "github.com/smartcontractkit/chainlink/v2/tools/flakeytests/": { + "TestSkippedForTests_Subtests/1:_should_fail": 1, + "TestSkippedForTests_Subtests/2:_should_fail": 1, + }, + } + assert.Equal(t, expectedTests, m.report.tests) +} + +func TestIntegration_ParsesPanics(t *testing.T) { + if testing.Short() { + t.Skip() + } + output := `{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/tools/flakeytests/","Test":"TestSkippedForTests","Elapsed":0}` m := newMockReporter() @@ -342,11 +404,15 @@ func TestParsesPanicCorrectly(t *testing.T) { err := r.Run() require.NoError(t, err) - _, ok := m.entries["github.com/smartcontractkit/chainlink/v2/tools/flakeytests"]["TestSkippedForTests"] + _, ok := m.report.tests["github.com/smartcontractkit/chainlink/v2/tools/flakeytests"]["TestSkippedForTests"] assert.False(t, ok) } func TestIntegration(t *testing.T) { + if testing.Short() { + t.Skip() + } + output := `{"Time":"2023-09-07T15:39:46.378315+01:00","Action":"fail","Package":"github.com/smartcontractkit/chainlink/v2/tools/flakeytests/","Test":"TestSkippedForTests_Success","Elapsed":0}` m := newMockReporter() @@ -369,6 +435,6 @@ func TestIntegration(t *testing.T) { err := r.Run() require.NoError(t, err) - _, ok := m.entries["github.com/smartcontractkit/chainlink/v2/tools/flakeytests"]["TestSkippedForTests_Success"] + _, ok := m.report.tests["github.com/smartcontractkit/chainlink/v2/tools/flakeytests"]["TestSkippedForTests_Success"] assert.False(t, ok) } From 306eadcf505b54502b7112efc395457d4bd0f3c5 Mon Sep 17 00:00:00 2001 From: Dimitris Grigoriou Date: Tue, 12 Dec 2023 14:35:33 +0200 Subject: [PATCH 02/29] Remove core utils dependencies from common (#11425) * Change difficulty from Big to BigInt * Fix headtracker mock head * Remove EsnureClosed * Fix mock heads * Migrate to common Mailbox * Fix Tracker close on txm * Change to EnsureHexPrefix * Change names to mailbox * Remove core/null dependency from common * Remove core mailbox * Fix dependencies * Tidy * Fix dependencies * Change path to internal utils * Minor fixes * Rename MinKey function * Update MinFunc * Fix utils conflicts --- common/client/node_lifecycle.go | 7 +- common/client/send_only_node_lifecycle.go | 2 +- common/headtracker/head_broadcaster.go | 6 +- common/headtracker/head_listener.go | 2 +- common/headtracker/head_tracker.go | 14 +- common/internal/utils/utils.go | 36 ++++ common/txmgr/broadcaster.go | 2 +- common/txmgr/confirmer.go | 14 +- common/txmgr/reaper.go | 2 +- common/txmgr/resender.go | 2 +- common/txmgr/tracker.go | 8 +- common/txmgr/txmgr.go | 8 +- common/txmgr/types/tx.go | 3 +- .../chains/evm/gas/block_history_estimator.go | 6 +- .../evm/headtracker/head_broadcaster_test.go | 3 +- core/chains/evm/headtracker/head_tracker.go | 5 +- .../evm/headtracker/head_tracker_test.go | 9 +- core/chains/evm/log/broadcaster.go | 13 +- core/chains/evm/log/helpers_internal_test.go | 5 +- core/chains/evm/log/helpers_test.go | 4 +- core/chains/evm/log/integration_test.go | 3 +- core/chains/evm/txmgr/evm_tx_store.go | 3 +- core/chains/legacyevm/chain.go | 3 +- core/chains/legacyevm/chain_test.go | 7 +- core/cmd/shell.go | 3 +- core/cmd/shell_local_test.go | 6 +- core/internal/cltest/cltest.go | 3 +- core/internal/testutils/evmtest/evmtest.go | 5 +- core/services/chainlink/application.go | 3 +- .../relayer_chain_interoperators_test.go | 6 +- core/services/directrequest/delegate.go | 18 +- core/services/directrequest/delegate_test.go | 5 +- core/services/functions/listener_test.go | 4 +- core/services/job/runner_integration_test.go | 12 +- core/services/job/spawner_test.go | 9 +- core/services/keeper/delegate.go | 6 +- .../keeper/registry_synchronizer_core.go | 10 +- .../registry_synchronizer_helper_test.go | 4 +- core/services/keeper/upkeep_executer.go | 7 +- core/services/ocr/contract_tracker.go | 10 +- core/services/ocr/contract_tracker_test.go | 4 +- core/services/ocr/delegate.go | 5 +- core/services/ocr2/delegate.go | 6 +- .../services/ocr2/plugins/functions/plugin.go | 3 +- core/services/pipeline/task.eth_tx.go | 2 +- core/services/pipeline/task.eth_tx_test.go | 2 +- core/services/promreporter/prom_reporter.go | 7 +- core/services/vrf/delegate.go | 8 +- core/services/vrf/delegate_test.go | 5 +- core/services/vrf/v1/listener_v1.go | 5 +- core/services/vrf/v2/listener_v2.go | 1 + core/services/vrf/v2/listener_v2_test.go | 3 +- core/utils/mailbox.go | 126 ------------ core/utils/mailbox_prom.go | 93 --------- core/utils/mailbox_test.go | 181 ------------------ core/utils/utils.go | 21 -- 56 files changed, 200 insertions(+), 550 deletions(-) create mode 100644 common/internal/utils/utils.go delete mode 100644 core/utils/mailbox.go delete mode 100644 core/utils/mailbox_prom.go delete mode 100644 core/utils/mailbox_test.go diff --git a/common/client/node_lifecycle.go b/common/client/node_lifecycle.go index 5ba0bff3238..eda137d5100 100644 --- a/common/client/node_lifecycle.go +++ b/common/client/node_lifecycle.go @@ -12,9 +12,10 @@ import ( "github.com/prometheus/client_golang/prometheus/promauto" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/utils" bigmath "github.com/smartcontractkit/chainlink-common/pkg/utils/big_math" - "github.com/smartcontractkit/chainlink/v2/core/utils" + iutils "github.com/smartcontractkit/chainlink/v2/common/internal/utils" ) var ( @@ -360,7 +361,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) unreachableLoop() { lggr := logger.Named(n.lfcLog, "Unreachable") lggr.Debugw("Trying to revive unreachable RPC node", "nodeState", n.State()) - dialRetryBackoff := utils.NewRedialBackoff() + dialRetryBackoff := iutils.NewRedialBackoff() for { select { @@ -416,7 +417,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) invalidChainIDLoop() { lggr := logger.Named(n.lfcLog, "InvalidChainID") lggr.Debugw(fmt.Sprintf("Periodically re-checking RPC node %s with invalid chain ID", n.String()), "nodeState", n.State()) - chainIDRecheckBackoff := utils.NewRedialBackoff() + chainIDRecheckBackoff := iutils.NewRedialBackoff() for { select { diff --git a/common/client/send_only_node_lifecycle.go b/common/client/send_only_node_lifecycle.go index 4d5b102b5bd..c66d267ed42 100644 --- a/common/client/send_only_node_lifecycle.go +++ b/common/client/send_only_node_lifecycle.go @@ -4,7 +4,7 @@ import ( "fmt" "time" - "github.com/smartcontractkit/chainlink/v2/core/utils" + "github.com/smartcontractkit/chainlink/v2/common/internal/utils" ) // verifyLoop may only be triggered once, on Start, if initial chain ID check diff --git a/common/headtracker/head_broadcaster.go b/common/headtracker/head_broadcaster.go index 0e676f864fa..758a7713846 100644 --- a/common/headtracker/head_broadcaster.go +++ b/common/headtracker/head_broadcaster.go @@ -9,9 +9,9 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" "github.com/smartcontractkit/chainlink/v2/common/types" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) const TrackableCallbackTimeout = 2 * time.Second @@ -30,7 +30,7 @@ type HeadBroadcaster[H types.Head[BLOCK_HASH], BLOCK_HASH types.Hashable] struct services.StateMachine logger logger.Logger callbacks callbackSet[H, BLOCK_HASH] - mailbox *utils.Mailbox[H] + mailbox *mailbox.Mailbox[H] mutex sync.Mutex chClose services.StopChan wgDone sync.WaitGroup @@ -48,7 +48,7 @@ func NewHeadBroadcaster[ return &HeadBroadcaster[H, BLOCK_HASH]{ logger: logger.Named(lggr, "HeadBroadcaster"), callbacks: make(callbackSet[H, BLOCK_HASH]), - mailbox: utils.NewSingleMailbox[H](), + mailbox: mailbox.NewSingle[H](), chClose: make(chan struct{}), } } diff --git a/common/headtracker/head_listener.go b/common/headtracker/head_listener.go index 0aebf606634..e7ea4fb51ae 100644 --- a/common/headtracker/head_listener.go +++ b/common/headtracker/head_listener.go @@ -14,8 +14,8 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/services" htrktypes "github.com/smartcontractkit/chainlink/v2/common/headtracker/types" + "github.com/smartcontractkit/chainlink/v2/common/internal/utils" "github.com/smartcontractkit/chainlink/v2/common/types" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) var ( diff --git a/common/headtracker/head_tracker.go b/common/headtracker/head_tracker.go index c977eb023cc..373aa5a958f 100644 --- a/common/headtracker/head_tracker.go +++ b/common/headtracker/head_tracker.go @@ -12,10 +12,10 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" htrktypes "github.com/smartcontractkit/chainlink/v2/common/headtracker/types" "github.com/smartcontractkit/chainlink/v2/common/types" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) var ( @@ -43,14 +43,14 @@ type HeadTracker[ log logger.Logger headBroadcaster types.HeadBroadcaster[HTH, BLOCK_HASH] headSaver types.HeadSaver[HTH, BLOCK_HASH] - mailMon *utils.MailboxMonitor + mailMon *mailbox.Monitor client htrktypes.Client[HTH, S, ID, BLOCK_HASH] chainID ID config htrktypes.Config htConfig htrktypes.HeadTrackerConfig - backfillMB *utils.Mailbox[HTH] - broadcastMB *utils.Mailbox[HTH] + backfillMB *mailbox.Mailbox[HTH] + broadcastMB *mailbox.Mailbox[HTH] headListener types.HeadListener[HTH, BLOCK_HASH] chStop services.StopChan wgDone sync.WaitGroup @@ -70,7 +70,7 @@ func NewHeadTracker[ htConfig htrktypes.HeadTrackerConfig, headBroadcaster types.HeadBroadcaster[HTH, BLOCK_HASH], headSaver types.HeadSaver[HTH, BLOCK_HASH], - mailMon *utils.MailboxMonitor, + mailMon *mailbox.Monitor, getNilHead func() HTH, ) types.HeadTracker[HTH, BLOCK_HASH] { chStop := make(chan struct{}) @@ -82,8 +82,8 @@ func NewHeadTracker[ config: config, htConfig: htConfig, log: lggr, - backfillMB: utils.NewSingleMailbox[HTH](), - broadcastMB: utils.NewMailbox[HTH](HeadsBufferSize), + backfillMB: mailbox.NewSingle[HTH](), + broadcastMB: mailbox.New[HTH](HeadsBufferSize), chStop: chStop, headListener: NewHeadListener[HTH, S, ID, BLOCK_HASH](lggr, client, config, chStop), headSaver: headSaver, diff --git a/common/internal/utils/utils.go b/common/internal/utils/utils.go new file mode 100644 index 00000000000..1e285868c53 --- /dev/null +++ b/common/internal/utils/utils.go @@ -0,0 +1,36 @@ +package utils + +import ( + "cmp" + "slices" + "time" + + "github.com/jpillora/backoff" + "golang.org/x/exp/constraints" +) + +// NewRedialBackoff is a standard backoff to use for redialling or reconnecting to +// unreachable network endpoints +func NewRedialBackoff() backoff.Backoff { + return backoff.Backoff{ + Min: 1 * time.Second, + Max: 15 * time.Second, + Jitter: true, + } + +} + +// MinFunc returns the minimum value of the given element array with respect +// to the given key function. In the event U is not a compound type (e.g a +// struct) an identity function can be provided. +func MinFunc[U any, T constraints.Ordered](elems []U, f func(U) T) T { + var min T + if len(elems) == 0 { + return min + } + + e := slices.MinFunc(elems, func(a, b U) int { + return cmp.Compare(f(a), f(b)) + }) + return f(e) +} diff --git a/common/txmgr/broadcaster.go b/common/txmgr/broadcaster.go index f10ecafc670..dba2b976c33 100644 --- a/common/txmgr/broadcaster.go +++ b/common/txmgr/broadcaster.go @@ -18,12 +18,12 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/chains/label" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/common/client" feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" "github.com/smartcontractkit/chainlink/v2/common/types" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) const ( diff --git a/common/txmgr/confirmer.go b/common/txmgr/confirmer.go index 95be9ad23e6..aabdf45ae32 100644 --- a/common/txmgr/confirmer.go +++ b/common/txmgr/confirmer.go @@ -17,13 +17,15 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/chains/label" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" "github.com/smartcontractkit/chainlink/v2/common/client" commonfee "github.com/smartcontractkit/chainlink/v2/common/fee" feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" + iutils "github.com/smartcontractkit/chainlink/v2/common/internal/utils" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" "github.com/smartcontractkit/chainlink/v2/common/types" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) const ( @@ -129,7 +131,7 @@ type Confirmer[ ks txmgrtypes.KeyStore[ADDR, CHAIN_ID, SEQ] enabledAddresses []ADDR - mb *utils.Mailbox[HEAD] + mb *mailbox.Mailbox[HEAD] ctx context.Context ctxCancel context.CancelFunc wg sync.WaitGroup @@ -174,7 +176,7 @@ func NewConfirmer[ dbConfig: dbConfig, chainID: client.ConfiguredChainID(), ks: keystore, - mb: utils.NewSingleMailbox[HEAD](), + mb: mailbox.NewSingle[HEAD](), isReceiptNil: isReceiptNil, } } @@ -223,7 +225,7 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) clo ec.initSync.Lock() defer ec.initSync.Unlock() if !ec.isStarted { - return fmt.Errorf("Confirmer is not started: %w", utils.ErrAlreadyStopped) + return fmt.Errorf("Confirmer is not started: %w", services.ErrAlreadyStopped) } ec.ctxCancel() ec.wg.Wait() @@ -869,7 +871,7 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) han "err", sendError, "fee", attempt.TxFee, "feeLimit", etx.FeeLimit, - "signedRawTx", utils.AddHexPrefix(hex.EncodeToString(attempt.SignedRawTx)), + "signedRawTx", utils.EnsureHexPrefix(hex.EncodeToString(attempt.SignedRawTx)), "blockHeight", blockHeight, ) ec.SvcErrBuffer.Append(sendError) @@ -1147,7 +1149,7 @@ func observeUntilTxConfirmed[ // Since a tx can have many attempts, we take the number of blocks to confirm as the block number // of the receipt minus the block number of the first ever broadcast for this transaction. - broadcastBefore := utils.MinKey(attempt.Tx.TxAttempts, func(attempt txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) int64 { + broadcastBefore := iutils.MinFunc(attempt.Tx.TxAttempts, func(attempt txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) int64 { if attempt.BroadcastBeforeBlockNum != nil { return *attempt.BroadcastBeforeBlockNum } diff --git a/common/txmgr/reaper.go b/common/txmgr/reaper.go index 385a9a17c3d..3ed05b2caee 100644 --- a/common/txmgr/reaper.go +++ b/common/txmgr/reaper.go @@ -7,10 +7,10 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" "github.com/smartcontractkit/chainlink/v2/common/types" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) // Reaper handles periodic database cleanup for Txm diff --git a/common/txmgr/resender.go b/common/txmgr/resender.go index 06c466e1730..74cf3d1389c 100644 --- a/common/txmgr/resender.go +++ b/common/txmgr/resender.go @@ -8,12 +8,12 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/chains/label" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/common/client" feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" "github.com/smartcontractkit/chainlink/v2/common/types" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) const ( diff --git a/common/txmgr/tracker.go b/common/txmgr/tracker.go index 1a24dd5b5fe..3ef2fc07208 100644 --- a/common/txmgr/tracker.go +++ b/common/txmgr/tracker.go @@ -8,11 +8,11 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" "github.com/smartcontractkit/chainlink/v2/common/types" - - "github.com/smartcontractkit/chainlink/v2/core/utils" ) const ( @@ -56,7 +56,7 @@ type Tracker[ txCache map[int64]AbandonedTx[ADDR] ttl time.Duration lock sync.Mutex - mb *utils.Mailbox[int64] + mb *mailbox.Mailbox[int64] wg sync.WaitGroup isStarted bool ctx context.Context @@ -85,7 +85,7 @@ func NewTracker[ enabledAddrs: map[ADDR]bool{}, txCache: map[int64]AbandonedTx[ADDR]{}, ttl: defaultTTL, - mb: utils.NewSingleMailbox[int64](), + mb: mailbox.NewSingle[int64](), lock: sync.Mutex{}, wg: sync.WaitGroup{}, } diff --git a/common/txmgr/txmgr.go b/common/txmgr/txmgr.go index 228ab4ec8bf..e43a16b29ef 100644 --- a/common/txmgr/txmgr.go +++ b/common/txmgr/txmgr.go @@ -14,10 +14,12 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils" + feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" + iutils "github.com/smartcontractkit/chainlink/v2/common/internal/utils" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" "github.com/smartcontractkit/chainlink/v2/common/types" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) // For more information about the Txm architecture, see the design doc: @@ -342,7 +344,7 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) runLoop() ctx, cancel := b.chStop.NewCtx() defer cancel() // Retry indefinitely on failure - backoff := utils.NewRedialBackoff() + backoff := iutils.NewRedialBackoff() for { select { case <-time.After(backoff.Duration()): @@ -361,7 +363,7 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) runLoop() go func() { defer wg.Done() // Retry indefinitely on failure - backoff := utils.NewRedialBackoff() + backoff := iutils.NewRedialBackoff() for { select { case <-time.After(backoff.Duration()): diff --git a/common/txmgr/types/tx.go b/common/txmgr/types/tx.go index 3af43b19617..caac763fc0f 100644 --- a/common/txmgr/types/tx.go +++ b/common/txmgr/types/tx.go @@ -15,9 +15,10 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" + clnull "github.com/smartcontractkit/chainlink-common/pkg/utils/null" + feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" "github.com/smartcontractkit/chainlink/v2/common/types" - clnull "github.com/smartcontractkit/chainlink/v2/core/null" ) // TxStrategy controls how txes are queued and sent diff --git a/core/chains/evm/gas/block_history_estimator.go b/core/chains/evm/gas/block_history_estimator.go index 0ec4721b797..844b9e547f2 100644 --- a/core/chains/evm/gas/block_history_estimator.go +++ b/core/chains/evm/gas/block_history_estimator.go @@ -17,6 +17,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" "github.com/smartcontractkit/chainlink-common/pkg/utils/mathutil" "github.com/smartcontractkit/chainlink/v2/common/config" @@ -25,7 +26,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) // MaxStartTime is the maximum amount of time we are allowed to spend @@ -109,7 +109,7 @@ type ( blocks []evmtypes.Block blocksMu sync.RWMutex size int64 - mb *utils.Mailbox[*evmtypes.Head] + mb *mailbox.Mailbox[*evmtypes.Head] wg *sync.WaitGroup ctx context.Context ctxCancel context.CancelFunc @@ -139,7 +139,7 @@ func NewBlockHistoryEstimator(lggr logger.Logger, ethClient evmclient.Client, cf blocks: make([]evmtypes.Block, 0), // Must have enough blocks for both estimator and connectivity checker size: int64(mathutil.Max(bhCfg.BlockHistorySize(), bhCfg.CheckInclusionBlocks())), - mb: utils.NewSingleMailbox[*evmtypes.Head](), + mb: mailbox.NewSingle[*evmtypes.Head](), wg: new(sync.WaitGroup), ctx: ctx, ctxCancel: cancel, diff --git a/core/chains/evm/headtracker/head_broadcaster_test.go b/core/chains/evm/headtracker/head_broadcaster_test.go index ac43c08fe87..b9fab9cdd48 100644 --- a/core/chains/evm/headtracker/head_broadcaster_test.go +++ b/core/chains/evm/headtracker/head_broadcaster_test.go @@ -12,6 +12,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" commonhtrk "github.com/smartcontractkit/chainlink/v2/common/headtracker" commonmocks "github.com/smartcontractkit/chainlink/v2/common/types/mocks" @@ -71,7 +72,7 @@ func TestHeadBroadcaster_Subscribe(t *testing.T) { orm := headtracker.NewORM(db, logger, cfg.Database(), *ethClient.ConfiguredChainID()) hs := headtracker.NewHeadSaver(logger, orm, evmCfg.EVM(), evmCfg.EVM().HeadTracker()) - mailMon := utils.NewMailboxMonitor(t.Name()) + mailMon := mailbox.NewMonitor(t.Name()) servicetest.Run(t, mailMon) hb := headtracker.NewHeadBroadcaster(logger) servicetest.Run(t, hb) diff --git a/core/chains/evm/headtracker/head_tracker.go b/core/chains/evm/headtracker/head_tracker.go index b86a6b5fe22..3cddfb71d09 100644 --- a/core/chains/evm/headtracker/head_tracker.go +++ b/core/chains/evm/headtracker/head_tracker.go @@ -9,12 +9,13 @@ import ( "go.uber.org/zap/zapcore" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + "github.com/smartcontractkit/chainlink/v2/common/headtracker" commontypes "github.com/smartcontractkit/chainlink/v2/common/types" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) type headTracker = headtracker.HeadTracker[*evmtypes.Head, ethereum.Subscription, *big.Int, common.Hash] @@ -28,7 +29,7 @@ func NewHeadTracker( htConfig HeadTrackerConfig, headBroadcaster httypes.HeadBroadcaster, headSaver httypes.HeadSaver, - mailMon *utils.MailboxMonitor, + mailMon *mailbox.Monitor, ) httypes.HeadTracker { return headtracker.NewHeadTracker[*evmtypes.Head, ethereum.Subscription, *big.Int, common.Hash]( lggr, diff --git a/core/chains/evm/headtracker/head_tracker_test.go b/core/chains/evm/headtracker/head_tracker_test.go index 4d3cebd24e2..d8abb1328ac 100644 --- a/core/chains/evm/headtracker/head_tracker_test.go +++ b/core/chains/evm/headtracker/head_tracker_test.go @@ -22,6 +22,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" commonmocks "github.com/smartcontractkit/chainlink/v2/common/types/mocks" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" @@ -992,7 +993,7 @@ func createHeadTracker(t *testing.T, ethClient evmclient.Client, config headtrac lggr := logger.Test(t) hb := headtracker.NewHeadBroadcaster(lggr) hs := headtracker.NewHeadSaver(lggr, orm, config, htConfig) - mailMon := utils.NewMailboxMonitor(t.Name()) + mailMon := mailbox.NewMonitor(t.Name()) return &headTrackerUniverse{ mu: new(sync.Mutex), headTracker: headtracker.NewHeadTracker(lggr, ethClient, config, htConfig, hb, hs, mailMon), @@ -1007,7 +1008,7 @@ func createHeadTrackerWithNeverSleeper(t *testing.T, ethClient evmclient.Client, lggr := logger.Test(t) hb := headtracker.NewHeadBroadcaster(lggr) hs := headtracker.NewHeadSaver(lggr, orm, evmcfg.EVM(), evmcfg.EVM().HeadTracker()) - mailMon := utils.NewMailboxMonitor(t.Name()) + mailMon := mailbox.NewMonitor(t.Name()) ht := headtracker.NewHeadTracker(lggr, ethClient, evmcfg.EVM(), evmcfg.EVM().HeadTracker(), hb, hs, mailMon) _, err := hs.Load(testutils.Context(t)) require.NoError(t, err) @@ -1025,7 +1026,7 @@ func createHeadTrackerWithChecker(t *testing.T, ethClient evmclient.Client, conf hb := headtracker.NewHeadBroadcaster(lggr) hs := headtracker.NewHeadSaver(lggr, orm, config, htConfig) hb.Subscribe(checker) - mailMon := utils.NewMailboxMonitor(t.Name()) + mailMon := mailbox.NewMonitor(t.Name()) ht := headtracker.NewHeadTracker(lggr, ethClient, config, htConfig, hb, hs, mailMon) return &headTrackerUniverse{ mu: new(sync.Mutex), @@ -1042,7 +1043,7 @@ type headTrackerUniverse struct { headTracker httypes.HeadTracker headBroadcaster httypes.HeadBroadcaster headSaver httypes.HeadSaver - mailMon *utils.MailboxMonitor + mailMon *mailbox.Monitor } func (u *headTrackerUniverse) Backfill(ctx context.Context, head *evmtypes.Head, depth uint) error { diff --git a/core/chains/evm/log/broadcaster.go b/core/chains/evm/log/broadcaster.go index f4528396093..393d1c1b266 100644 --- a/core/chains/evm/log/broadcaster.go +++ b/core/chains/evm/log/broadcaster.go @@ -14,6 +14,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types" @@ -102,11 +103,11 @@ type ( registrations *registrations logPool *logPool - mailMon *utils.MailboxMonitor + mailMon *mailbox.Monitor // Use the same channel for subs/unsubs so ordering is preserved // (unsubscribe must happen after subscribe) - changeSubscriberStatus *utils.Mailbox[changeSubscriberStatus] - newHeads *utils.Mailbox[*evmtypes.Head] + changeSubscriberStatus *mailbox.Mailbox[changeSubscriberStatus] + newHeads *mailbox.Mailbox[*evmtypes.Head] utils.DependentAwaiter @@ -165,7 +166,7 @@ const ( var _ Broadcaster = (*broadcaster)(nil) // NewBroadcaster creates a new instance of the broadcaster -func NewBroadcaster(orm ORM, ethClient evmclient.Client, config Config, lggr logger.Logger, highestSavedHead *evmtypes.Head, mailMon *utils.MailboxMonitor) *broadcaster { +func NewBroadcaster(orm ORM, ethClient evmclient.Client, config Config, lggr logger.Logger, highestSavedHead *evmtypes.Head, mailMon *mailbox.Monitor) *broadcaster { chStop := make(chan struct{}) lggr = logger.Named(lggr, "LogBroadcaster") chainId := ethClient.ConfiguredChainID() @@ -178,8 +179,8 @@ func NewBroadcaster(orm ORM, ethClient evmclient.Client, config Config, lggr log registrations: newRegistrations(lggr, *chainId), logPool: newLogPool(lggr), mailMon: mailMon, - changeSubscriberStatus: utils.NewHighCapacityMailbox[changeSubscriberStatus](), - newHeads: utils.NewSingleMailbox[*evmtypes.Head](), + changeSubscriberStatus: mailbox.NewHighCapacity[changeSubscriberStatus](), + newHeads: mailbox.NewSingle[*evmtypes.Head](), DependentAwaiter: utils.NewDependentAwaiter(), chStop: chStop, highestSavedHead: highestSavedHead, diff --git a/core/chains/evm/log/helpers_internal_test.go b/core/chains/evm/log/helpers_internal_test.go index 38f40bd329e..4d4318cdf9d 100644 --- a/core/chains/evm/log/helpers_internal_test.go +++ b/core/chains/evm/log/helpers_internal_test.go @@ -4,13 +4,14 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) // NewTestBroadcaster creates a broadcaster with Pause/Resume enabled. -func NewTestBroadcaster(orm ORM, ethClient evmclient.Client, config Config, lggr logger.Logger, highestSavedHead *evmtypes.Head, mailMon *utils.MailboxMonitor) *broadcaster { +func NewTestBroadcaster(orm ORM, ethClient evmclient.Client, config Config, lggr logger.Logger, highestSavedHead *evmtypes.Head, mailMon *mailbox.Monitor) *broadcaster { b := NewBroadcaster(orm, ethClient, config, lggr, highestSavedHead, mailMon) b.testPause, b.testResume = make(chan struct{}), make(chan struct{}) return b diff --git a/core/chains/evm/log/helpers_test.go b/core/chains/evm/log/helpers_test.go index e41f08e8d20..13dfe1ffab6 100644 --- a/core/chains/evm/log/helpers_test.go +++ b/core/chains/evm/log/helpers_test.go @@ -22,6 +22,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" @@ -42,7 +43,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) type broadcasterHelper struct { @@ -90,7 +90,7 @@ func newBroadcasterHelperWithEthClient(t *testing.T, ethClient evmclient.Client, }) config := evmtest.NewChainScopedConfig(t, globalConfig) lggr := logger.Test(t) - mailMon := servicetest.Run(t, utils.NewMailboxMonitor(t.Name())) + mailMon := servicetest.Run(t, mailbox.NewMonitor(t.Name())) db := pgtest.NewSqlxDB(t) orm := log.NewORM(db, lggr, config.Database(), cltest.FixtureChainID) diff --git a/core/chains/evm/log/integration_test.go b/core/chains/evm/log/integration_test.go index e5b6ad3caf5..b26e87e668c 100644 --- a/core/chains/evm/log/integration_test.go +++ b/core/chains/evm/log/integration_test.go @@ -18,6 +18,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log" @@ -1325,7 +1326,7 @@ func TestBroadcaster_AppendLogChannel(t *testing.T) { ch3 := make(chan types.Log) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) - mailMon := servicetest.RunHealthy(t, utils.NewMailboxMonitor(t.Name())) + mailMon := servicetest.RunHealthy(t, mailbox.NewMonitor(t.Name())) lb := log.NewBroadcaster(nil, ethClient, nil, logger.Test(t), nil, mailMon) chCombined := lb.ExportedAppendLogChannel(ch1, ch2) chCombined = lb.ExportedAppendLogChannel(chCombined, ch3) diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go index 730809e8dda..1c9868741fa 100644 --- a/core/chains/evm/txmgr/evm_tx_store.go +++ b/core/chains/evm/txmgr/evm_tx_store.go @@ -20,13 +20,14 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" + "github.com/smartcontractkit/chainlink-common/pkg/utils/null" + "github.com/smartcontractkit/chainlink/v2/common/txmgr" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/label" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/null" "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/utils" ) diff --git a/core/chains/legacyevm/chain.go b/core/chains/legacyevm/chain.go index 4b4c69f1ab6..18277a55d03 100644 --- a/core/chains/legacyevm/chain.go +++ b/core/chains/legacyevm/chain.go @@ -16,6 +16,7 @@ import ( common "github.com/smartcontractkit/chainlink-common/pkg/chains" "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" commonclient "github.com/smartcontractkit/chainlink/v2/common/client" commonconfig "github.com/smartcontractkit/chainlink/v2/common/config" @@ -164,7 +165,7 @@ type ChainOpts struct { AppConfig AppConfig EventBroadcaster pg.EventBroadcaster - MailMon *utils.MailboxMonitor + MailMon *mailbox.Monitor GasEstimator gas.EvmFeeEstimator *sqlx.DB diff --git a/core/chains/legacyevm/chain_test.go b/core/chains/legacyevm/chain_test.go index 4fcd51c39d9..93332348aa0 100644 --- a/core/chains/legacyevm/chain_test.go +++ b/core/chains/legacyevm/chain_test.go @@ -8,12 +8,13 @@ import ( "github.com/jmoiron/sqlx" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/pg" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func TestLegacyChains(t *testing.T) { @@ -35,7 +36,7 @@ func TestChainOpts_Validate(t *testing.T) { type fields struct { AppConfig legacyevm.AppConfig EventBroadcaster pg.EventBroadcaster - MailMon *utils.MailboxMonitor + MailMon *mailbox.Monitor DB *sqlx.DB } tests := []struct { @@ -48,7 +49,7 @@ func TestChainOpts_Validate(t *testing.T) { fields: fields{ AppConfig: configtest.NewTestGeneralConfig(t), EventBroadcaster: pg.NewNullEventBroadcaster(), - MailMon: &utils.MailboxMonitor{}, + MailMon: &mailbox.Monitor{}, DB: pgtest.NewSqlxDB(t), }, }, diff --git a/core/cmd/shell.go b/core/cmd/shell.go index 2e382be4ccf..3810559cf34 100644 --- a/core/cmd/shell.go +++ b/core/cmd/shell.go @@ -32,6 +32,7 @@ import ( "github.com/jmoiron/sqlx" "github.com/smartcontractkit/chainlink-common/pkg/loop" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" "github.com/smartcontractkit/chainlink/v2/core/build" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" @@ -153,7 +154,7 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G } keyStore := keystore.New(db, utils.GetScryptParams(cfg), appLggr, cfg.Database()) - mailMon := utils.NewMailboxMonitor(cfg.AppID().String()) + mailMon := mailbox.NewMonitor(cfg.AppID().String()) dbListener := cfg.Database().Listener() eventBroadcaster := pg.NewEventBroadcaster(cfg.Database().URL(), dbListener.MinReconnectInterval(), dbListener.MaxReconnectDuration(), appLggr, cfg.AppID()) diff --git a/core/cmd/shell_local_test.go b/core/cmd/shell_local_test.go index fac2d7f040b..56da90d811c 100644 --- a/core/cmd/shell_local_test.go +++ b/core/cmd/shell_local_test.go @@ -8,6 +8,8 @@ import ( "testing" "time" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + "github.com/smartcontractkit/chainlink/v2/common/client" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/cmd" @@ -89,7 +91,7 @@ func TestShell_RunNodeWithPasswords(t *testing.T) { ChainOpts: legacyevm.ChainOpts{ AppConfig: cfg, EventBroadcaster: pg.NewNullEventBroadcaster(), - MailMon: &utils.MailboxMonitor{}, + MailMon: &mailbox.Monitor{}, DB: db, }, } @@ -194,7 +196,7 @@ func TestShell_RunNodeWithAPICredentialsFile(t *testing.T) { ChainOpts: legacyevm.ChainOpts{ AppConfig: cfg, EventBroadcaster: pg.NewNullEventBroadcaster(), - MailMon: &utils.MailboxMonitor{}, + MailMon: &mailbox.Monitor{}, DB: db, }, } diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go index 88abc3de5c6..dc90201890d 100644 --- a/core/internal/cltest/cltest.go +++ b/core/internal/cltest/cltest.go @@ -38,6 +38,7 @@ import ( ocrtypes "github.com/smartcontractkit/libocr/offchainreporting/types" "github.com/smartcontractkit/chainlink-common/pkg/loop" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" "github.com/smartcontractkit/chainlink/v2/common/client" commonmocks "github.com/smartcontractkit/chainlink/v2/common/types/mocks" @@ -339,7 +340,7 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn keyStore := keystore.NewInMemory(db, utils.FastScryptParams, lggr, cfg.Database()) - mailMon := utils.NewMailboxMonitor(cfg.AppID().String()) + mailMon := mailbox.NewMonitor(cfg.AppID().String()) loopRegistry := plugins.NewLoopRegistry(lggr, nil) mercuryPool := wsrpc.NewPool(lggr, cache.Config{ diff --git a/core/internal/testutils/evmtest/evmtest.go b/core/internal/testutils/evmtest/evmtest.go index e0a447a3274..095ea1a35c9 100644 --- a/core/internal/testutils/evmtest/evmtest.go +++ b/core/internal/testutils/evmtest/evmtest.go @@ -17,6 +17,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" commonmocks "github.com/smartcontractkit/chainlink/v2/common/types/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains" @@ -65,7 +66,7 @@ type TestChainOpts struct { DB *sqlx.DB TxManager txmgr.TxManager KeyStore keystore.Eth - MailMon *utils.MailboxMonitor + MailMon *mailbox.Monitor GasEstimator gas.EvmFeeEstimator } @@ -118,7 +119,7 @@ func NewChainRelayExtOpts(t testing.TB, testopts TestChainOpts) legacyevm.ChainR } } if opts.MailMon == nil { - opts.MailMon = servicetest.Run(t, utils.NewMailboxMonitor(t.Name())) + opts.MailMon = servicetest.Run(t, mailbox.NewMonitor(t.Name())) } if testopts.GasEstimator != nil { opts.GenGasEstimator = func(*big.Int) gas.EvmFeeEstimator { diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go index 5c204d693e9..ed043086586 100644 --- a/core/services/chainlink/application.go +++ b/core/services/chainlink/application.go @@ -20,6 +20,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/loop" commonservices "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" "github.com/smartcontractkit/chainlink/v2/core/static" "github.com/smartcontractkit/chainlink/v2/core/bridges" @@ -149,7 +150,7 @@ type ApplicationOpts struct { Config GeneralConfig Logger logger.Logger EventBroadcaster pg.EventBroadcaster - MailMon *utils.MailboxMonitor + MailMon *mailbox.Monitor SqlxDB *sqlx.DB KeyStore keystore.Master RelayerChainInteroperators *CoreRelayerChainInteroperators diff --git a/core/services/chainlink/relayer_chain_interoperators_test.go b/core/services/chainlink/relayer_chain_interoperators_test.go index 6a5445d9f21..a0754fa0139 100644 --- a/core/services/chainlink/relayer_chain_interoperators_test.go +++ b/core/services/chainlink/relayer_chain_interoperators_test.go @@ -11,6 +11,8 @@ import ( commoncfg "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/loop" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config" solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" stkcfg "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config" @@ -206,7 +208,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { ChainOpts: legacyevm.ChainOpts{ AppConfig: cfg, EventBroadcaster: pg.NewNullEventBroadcaster(), - MailMon: &utils.MailboxMonitor{}, + MailMon: &mailbox.Monitor{}, DB: db, }, CSAETHKeystore: keyStore, @@ -280,7 +282,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { ChainOpts: legacyevm.ChainOpts{ AppConfig: cfg, EventBroadcaster: pg.NewNullEventBroadcaster(), - MailMon: &utils.MailboxMonitor{}, + MailMon: &mailbox.Monitor{}, DB: db, }, CSAETHKeystore: keyStore, diff --git a/core/services/directrequest/delegate.go b/core/services/directrequest/delegate.go index a21029ea177..cfdf1eed116 100644 --- a/core/services/directrequest/delegate.go +++ b/core/services/directrequest/delegate.go @@ -11,6 +11,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/assets" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" @@ -21,7 +22,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/store/models" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) type ( @@ -31,7 +31,7 @@ type ( pipelineORM pipeline.ORM chHeads chan *evmtypes.Head legacyChains legacyevm.LegacyChainContainer - mailMon *utils.MailboxMonitor + mailMon *mailbox.Monitor } Config interface { @@ -47,7 +47,7 @@ func NewDelegate( pipelineRunner pipeline.Runner, pipelineORM pipeline.ORM, legacyChains legacyevm.LegacyChainContainer, - mailMon *utils.MailboxMonitor, + mailMon *mailbox.Monitor, ) *Delegate { return &Delegate{ logger: logger.Named("DirectRequest"), @@ -101,8 +101,8 @@ func (d *Delegate) ServicesForSpec(jb job.Job) ([]job.ServiceCtx, error) { pipelineORM: d.pipelineORM, mailMon: d.mailMon, job: jb, - mbOracleRequests: utils.NewHighCapacityMailbox[log.Broadcast](), - mbOracleCancelRequests: utils.NewHighCapacityMailbox[log.Broadcast](), + mbOracleRequests: mailbox.NewHighCapacity[log.Broadcast](), + mbOracleCancelRequests: mailbox.NewHighCapacity[log.Broadcast](), minIncomingConfirmations: concreteSpec.MinIncomingConfirmations.Uint32, requesters: concreteSpec.Requesters, minContractPayment: concreteSpec.MinContractPayment, @@ -127,12 +127,12 @@ type listener struct { oracle operator_wrapper.OperatorInterface pipelineRunner pipeline.Runner pipelineORM pipeline.ORM - mailMon *utils.MailboxMonitor + mailMon *mailbox.Monitor job job.Job runs sync.Map // map[string]services.StopChan shutdownWaitGroup sync.WaitGroup - mbOracleRequests *utils.Mailbox[log.Broadcast] - mbOracleCancelRequests *utils.Mailbox[log.Broadcast] + mbOracleRequests *mailbox.Mailbox[log.Broadcast] + mbOracleCancelRequests *mailbox.Mailbox[log.Broadcast] minIncomingConfirmations uint32 requesters models.AddressCollection minContractPayment *assets.Link @@ -238,7 +238,7 @@ func (l *listener) processCancelOracleRequests() { } } -func (l *listener) handleReceivedLogs(mailbox *utils.Mailbox[log.Broadcast]) { +func (l *listener) handleReceivedLogs(mailbox *mailbox.Mailbox[log.Broadcast]) { for { select { case <-l.chStop: diff --git a/core/services/directrequest/delegate_test.go b/core/services/directrequest/delegate_test.go index 2d5b9bef03b..865edb1b481 100644 --- a/core/services/directrequest/delegate_test.go +++ b/core/services/directrequest/delegate_test.go @@ -15,6 +15,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/assets" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log" @@ -44,7 +45,7 @@ func TestDelegate_ServicesForSpec(t *testing.T) { c.EVM[0].MinIncomingConfirmations = ptr[uint32](1) }) keyStore := cltest.NewKeyStore(t, db, cfg.Database()) - mailMon := servicetest.Run(t, utils.NewMailboxMonitor(t.Name())) + mailMon := servicetest.Run(t, mailbox.NewMonitor(t.Name())) relayerExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, Client: ethClient, MailMon: mailMon, KeyStore: keyStore.Eth()}) lggr := logger.TestLogger(t) @@ -81,7 +82,7 @@ func NewDirectRequestUniverseWithConfig(t *testing.T, cfg chainlink.GeneralConfi runner := pipeline_mocks.NewRunner(t) broadcaster.On("AddDependents", 1) - mailMon := servicetest.Run(t, utils.NewMailboxMonitor(t.Name())) + mailMon := servicetest.Run(t, mailbox.NewMonitor(t.Name())) db := pgtest.NewSqlxDB(t) keyStore := cltest.NewKeyStore(t, db, cfg.Database()) diff --git a/core/services/functions/listener_test.go b/core/services/functions/listener_test.go index 5020537bf61..07bd82ed288 100644 --- a/core/services/functions/listener_test.go +++ b/core/services/functions/listener_test.go @@ -20,6 +20,7 @@ import ( decryptionPlugin "github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" log_mocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" @@ -44,7 +45,6 @@ import ( sync_mocks "github.com/smartcontractkit/chainlink/v2/core/services/synchronization/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/synchronization/telem" "github.com/smartcontractkit/chainlink/v2/core/services/telemetry" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) type FunctionsListenerUniverse struct { @@ -82,7 +82,7 @@ func NewFunctionsListenerUniverse(t *testing.T, timeoutSec int, pruneFrequencySe ethClient := evmtest.NewEthClientMockWithDefaultChain(t) broadcaster := log_mocks.NewBroadcaster(t) broadcaster.On("AddDependents", 1) - mailMon := servicetest.Run(t, utils.NewMailboxMonitor(t.Name())) + mailMon := servicetest.Run(t, mailbox.NewMonitor(t.Name())) db := pgtest.NewSqlxDB(t) kst := cltest.NewKeyStore(t, db, cfg.Database()) diff --git a/core/services/job/runner_integration_test.go b/core/services/job/runner_integration_test.go index 0223f1a10d5..14a5c41b396 100644 --- a/core/services/job/runner_integration_test.go +++ b/core/services/job/runner_integration_test.go @@ -24,6 +24,7 @@ import ( "gopkg.in/guregu/null.v4" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" "github.com/smartcontractkit/chainlink/v2/core/auth" "github.com/smartcontractkit/chainlink/v2/core/bridges" @@ -45,7 +46,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/telemetry" "github.com/smartcontractkit/chainlink/v2/core/services/webhook" "github.com/smartcontractkit/chainlink/v2/core/store/models" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web" ) @@ -462,7 +462,7 @@ answer1 [type=median index=0]; legacyChains, lggr, config.Database(), - servicetest.Run(t, utils.NewMailboxMonitor(t.Name())), + servicetest.Run(t, mailbox.NewMonitor(t.Name())), ) _, err = sd.ServicesForSpec(jb) require.NoError(t, err) @@ -496,7 +496,7 @@ answer1 [type=median index=0]; legacyChains, lggr, config.Database(), - servicetest.Run(t, utils.NewMailboxMonitor(t.Name())), + servicetest.Run(t, mailbox.NewMonitor(t.Name())), ) _, err = sd.ServicesForSpec(jb) require.NoError(t, err) @@ -524,7 +524,7 @@ answer1 [type=median index=0]; legacyChains, lggr, config.Database(), - servicetest.Run(t, utils.NewMailboxMonitor(t.Name())), + servicetest.Run(t, mailbox.NewMonitor(t.Name())), ) _, err = sd.ServicesForSpec(jb) require.NoError(t, err) @@ -579,7 +579,7 @@ answer1 [type=median index=0]; legacyChains, lggr, config.Database(), - servicetest.Run(t, utils.NewMailboxMonitor(t.Name())), + servicetest.Run(t, mailbox.NewMonitor(t.Name())), ) jb.OCROracleSpec.CaptureEATelemetry = tc.jbCaptureEATelemetry @@ -623,7 +623,7 @@ answer1 [type=median index=0]; legacyChains, lggr, config.Database(), - servicetest.Run(t, utils.NewMailboxMonitor(t.Name())), + servicetest.Run(t, mailbox.NewMonitor(t.Name())), ) services, err := sd.ServicesForSpec(*jb) require.NoError(t, err) diff --git a/core/services/job/spawner_test.go b/core/services/job/spawner_test.go index d639ce859af..b82aa73c0b5 100644 --- a/core/services/job/spawner_test.go +++ b/core/services/job/spawner_test.go @@ -14,6 +14,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/loop" "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" "github.com/smartcontractkit/chainlink/v2/core/bridges" mocklp "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" @@ -128,7 +129,7 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { serviceA2 := mocks.NewServiceCtx(t) serviceA1.On("Start", mock.Anything).Return(nil).Once() serviceA2.On("Start", mock.Anything).Return(nil).Once().Run(func(mock.Arguments) { eventuallyA.ItHappened() }) - mailMon := servicetest.Run(t, utils.NewMailboxMonitor(t.Name())) + mailMon := servicetest.Run(t, mailbox.NewMonitor(t.Name())) dA := ocr.NewDelegate(nil, orm, nil, nil, nil, monitoringEndpoint, legacyChains, logger.TestLogger(t), config.Database(), mailMon) delegateA := &delegate{jobA.Type, []job.ServiceCtx{serviceA1, serviceA2}, 0, make(chan struct{}), dA} @@ -187,7 +188,7 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { lggr := logger.TestLogger(t) orm := NewTestORM(t, db, pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db, lggr, config.Database()), keyStore, config.Database()) - mailMon := servicetest.Run(t, utils.NewMailboxMonitor(t.Name())) + mailMon := servicetest.Run(t, mailbox.NewMonitor(t.Name())) d := ocr.NewDelegate(nil, orm, nil, nil, nil, monitoringEndpoint, legacyChains, logger.TestLogger(t), config.Database(), mailMon) delegateA := &delegate{jobA.Type, []job.ServiceCtx{serviceA1, serviceA2}, 0, nil, d} spawner := job.NewSpawner(orm, config.Database(), noopChecker{}, map[job.Type]job.Delegate{ @@ -221,7 +222,7 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { lggr := logger.TestLogger(t) orm := NewTestORM(t, db, pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db, lggr, config.Database()), keyStore, config.Database()) - mailMon := servicetest.Run(t, utils.NewMailboxMonitor(t.Name())) + mailMon := servicetest.Run(t, mailbox.NewMonitor(t.Name())) d := ocr.NewDelegate(nil, orm, nil, nil, nil, monitoringEndpoint, legacyChains, logger.TestLogger(t), config.Database(), mailMon) delegateA := &delegate{jobA.Type, []job.ServiceCtx{serviceA1, serviceA2}, 0, nil, d} spawner := job.NewSpawner(orm, config.Database(), noopChecker{}, map[job.Type]job.Delegate{ @@ -299,7 +300,7 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { jobOCR2VRF := makeOCR2VRFJobSpec(t, keyStore, config, address, chain.ID(), 2) orm := NewTestORM(t, db, pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db, lggr, config.Database()), keyStore, config.Database()) - mailMon := servicetest.Run(t, utils.NewMailboxMonitor(t.Name())) + mailMon := servicetest.Run(t, mailbox.NewMonitor(t.Name())) processConfig := plugins.NewRegistrarConfig(loop.GRPCOpts{}, func(name string) (*plugins.RegisteredLoop, error) { return nil, nil }) ocr2DelegateConfig := ocr2.NewDelegateConfig(config.OCR2(), config.Mercury(), config.Threshold(), config.Insecure(), config.JobPipeline(), config.Database(), processConfig) diff --git a/core/services/keeper/delegate.go b/core/services/keeper/delegate.go index 0dbf584c56f..4418bea670a 100644 --- a/core/services/keeper/delegate.go +++ b/core/services/keeper/delegate.go @@ -5,12 +5,12 @@ import ( "github.com/jmoiron/sqlx" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) // To make sure Delegate struct implements job.Delegate interface @@ -22,7 +22,7 @@ type Delegate struct { jrm job.ORM pr pipeline.Runner legacyChains legacyevm.LegacyChainContainer - mailMon *utils.MailboxMonitor + mailMon *mailbox.Monitor } // NewDelegate is the constructor of Delegate @@ -32,7 +32,7 @@ func NewDelegate( pr pipeline.Runner, logger logger.Logger, legacyChains legacyevm.LegacyChainContainer, - mailMon *utils.MailboxMonitor, + mailMon *mailbox.Monitor, ) *Delegate { return &Delegate{ logger: logger, diff --git a/core/services/keeper/registry_synchronizer_core.go b/core/services/keeper/registry_synchronizer_core.go index db7cca1763f..f26c38fc2e1 100644 --- a/core/services/keeper/registry_synchronizer_core.go +++ b/core/services/keeper/registry_synchronizer_core.go @@ -10,6 +10,8 @@ import ( "github.com/pkg/errors" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" @@ -28,7 +30,7 @@ type RegistrySynchronizerOptions struct { ORM ORM JRM job.ORM LogBroadcaster log.Broadcaster - MailMon *utils.MailboxMonitor + MailMon *mailbox.Monitor SyncInterval time.Duration MinIncomingConfirmations uint32 Logger logger.Logger @@ -44,14 +46,14 @@ type RegistrySynchronizer struct { job job.Job jrm job.ORM logBroadcaster log.Broadcaster - mbLogs *utils.Mailbox[log.Broadcast] + mbLogs *mailbox.Mailbox[log.Broadcast] minIncomingConfirmations uint32 effectiveKeeperAddress common.Address orm ORM logger logger.SugaredLogger wgDone sync.WaitGroup syncUpkeepQueueSize uint32 //Represents the max number of upkeeps that can be synced in parallel - mailMon *utils.MailboxMonitor + mailMon *mailbox.Monitor } // NewRegistrySynchronizer is the constructor of RegistrySynchronizer @@ -63,7 +65,7 @@ func NewRegistrySynchronizer(opts RegistrySynchronizerOptions) *RegistrySynchron job: opts.Job, jrm: opts.JRM, logBroadcaster: opts.LogBroadcaster, - mbLogs: utils.NewMailbox[log.Broadcast](5_000), // Arbitrary limit, better to have excess capacity + mbLogs: mailbox.New[log.Broadcast](5_000), // Arbitrary limit, better to have excess capacity minIncomingConfirmations: opts.MinIncomingConfirmations, orm: opts.ORM, effectiveKeeperAddress: opts.EffectiveKeeperAddress, diff --git a/core/services/keeper/registry_synchronizer_helper_test.go b/core/services/keeper/registry_synchronizer_helper_test.go index 5ba60db3962..dff97202f6c 100644 --- a/core/services/keeper/registry_synchronizer_helper_test.go +++ b/core/services/keeper/registry_synchronizer_helper_test.go @@ -11,6 +11,7 @@ import ( "github.com/jmoiron/sqlx" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log" @@ -23,7 +24,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keeper" evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) const syncInterval = 1000 * time.Hour // prevents sync timer from triggering during test @@ -73,7 +73,7 @@ func setupRegistrySync(t *testing.T, version keeper.RegistryVersion) ( })).Maybe().Return(func() {}) lbMock.On("IsConnected").Return(true).Maybe() - mailMon := servicetest.Run(t, utils.NewMailboxMonitor(t.Name())) + mailMon := servicetest.Run(t, mailbox.NewMonitor(t.Name())) orm := keeper.NewORM(db, logger.TestLogger(t), ch.Config().Database()) synchronizer := keeper.NewRegistrySynchronizer(keeper.RegistrySynchronizerOptions{ diff --git a/core/services/keeper/upkeep_executer.go b/core/services/keeper/upkeep_executer.go index 84349ba2dca..bab2f73edfc 100644 --- a/core/services/keeper/upkeep_executer.go +++ b/core/services/keeper/upkeep_executer.go @@ -13,6 +13,8 @@ import ( "github.com/prometheus/client_golang/prometheus/promauto" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" @@ -23,7 +25,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) const ( @@ -62,7 +63,7 @@ type UpkeepExecuter struct { headBroadcaster httypes.HeadBroadcasterRegistry gasEstimator gas.EvmFeeEstimator job job.Job - mailbox *utils.Mailbox[*evmtypes.Head] + mailbox *mailbox.Mailbox[*evmtypes.Head] orm ORM pr pipeline.Runner logger logger.Logger @@ -89,7 +90,7 @@ func NewUpkeepExecuter( headBroadcaster: headBroadcaster, gasEstimator: gasEstimator, job: job, - mailbox: utils.NewSingleMailbox[*evmtypes.Head](), + mailbox: mailbox.NewSingle[*evmtypes.Head](), config: config, orm: orm, pr: pr, diff --git a/core/services/ocr/contract_tracker.go b/core/services/ocr/contract_tracker.go index 4f79bcfc31a..1287e52e9b5 100644 --- a/core/services/ocr/contract_tracker.go +++ b/core/services/ocr/contract_tracker.go @@ -21,6 +21,7 @@ import ( ocrtypes "github.com/smartcontractkit/libocr/offchainreporting/types" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" "github.com/smartcontractkit/chainlink/v2/common/config" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" @@ -31,7 +32,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" "github.com/smartcontractkit/chainlink/v2/core/services/pg" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) // configMailboxSanityLimit is the maximum number of configs that can be held @@ -67,7 +67,7 @@ type ( q pg.Q blockTranslator ocrcommon.BlockTranslator cfg ocrcommon.Config - mailMon *utils.MailboxMonitor + mailMon *mailbox.Monitor // HeadBroadcaster headBroadcaster httypes.HeadBroadcaster @@ -83,7 +83,7 @@ type ( lrrMu sync.RWMutex // ContractConfig - configsMB *utils.Mailbox[ocrtypes.ContractConfig] + configsMB *mailbox.Mailbox[ocrtypes.ContractConfig] chConfigs chan ocrtypes.ContractConfig // LatestBlockHeight @@ -117,7 +117,7 @@ func NewOCRContractTracker( cfg ocrcommon.Config, q pg.QConfig, headBroadcaster httypes.HeadBroadcaster, - mailMon *utils.MailboxMonitor, + mailMon *mailbox.Monitor, ) (o *OCRContractTracker) { logger = logger.Named("OCRContractTracker") return &OCRContractTracker{ @@ -136,7 +136,7 @@ func NewOCRContractTracker( headBroadcaster: headBroadcaster, chStop: make(services.StopChan), latestRoundRequested: offchainaggregator.OffchainAggregatorRoundRequested{}, - configsMB: utils.NewMailbox[ocrtypes.ContractConfig](configMailboxSanityLimit), + configsMB: mailbox.New[ocrtypes.ContractConfig](configMailboxSanityLimit), chConfigs: make(chan ocrtypes.ContractConfig), latestBlockHeight: -1, } diff --git a/core/services/ocr/contract_tracker_test.go b/core/services/ocr/contract_tracker_test.go index af65f330d66..f7ebbe08481 100644 --- a/core/services/ocr/contract_tracker_test.go +++ b/core/services/ocr/contract_tracker_test.go @@ -16,6 +16,7 @@ import ( ocrtypes "github.com/smartcontractkit/libocr/offchainreporting/types" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" commonmocks "github.com/smartcontractkit/chainlink/v2/common/mocks" evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" @@ -31,7 +32,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr" ocrmocks "github.com/smartcontractkit/chainlink/v2/core/services/ocr/mocks" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func mustNewContract(t *testing.T, address gethCommon.Address) *offchain_aggregator_wrapper.OffchainAggregator { @@ -84,7 +84,7 @@ func newContractTrackerUni(t *testing.T, opts ...interface{}) (uni contractTrack uni.hb = commonmocks.NewHeadBroadcaster[*evmtypes.Head, common.Hash](t) uni.ec = evmtest.NewEthClientMock(t) - mailMon := servicetest.Run(t, utils.NewMailboxMonitor(t.Name())) + mailMon := servicetest.Run(t, mailbox.NewMonitor(t.Name())) db := pgtest.NewSqlxDB(t) uni.tracker = ocr.NewOCRContractTracker( contract, diff --git a/core/services/ocr/delegate.go b/core/services/ocr/delegate.go index d3d133e7121..0eed680a3d8 100644 --- a/core/services/ocr/delegate.go +++ b/core/services/ocr/delegate.go @@ -12,6 +12,7 @@ import ( "github.com/jmoiron/sqlx" commonlogger "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" "github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator" ocr "github.com/smartcontractkit/libocr/offchainreporting" @@ -43,7 +44,7 @@ type Delegate struct { legacyChains legacyevm.LegacyChainContainer lggr logger.Logger cfg Config - mailMon *utils.MailboxMonitor + mailMon *mailbox.Monitor } var _ job.Delegate = (*Delegate)(nil) @@ -60,7 +61,7 @@ func NewDelegate( legacyChains legacyevm.LegacyChainContainer, lggr logger.Logger, cfg Config, - mailMon *utils.MailboxMonitor, + mailMon *mailbox.Monitor, ) *Delegate { return &Delegate{ db: db, diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go index 16f02282afb..5200866e3af 100644 --- a/core/services/ocr2/delegate.go +++ b/core/services/ocr2/delegate.go @@ -34,6 +34,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/loop" "github.com/smartcontractkit/chainlink-common/pkg/loop/reportingplugins" "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" @@ -70,7 +71,6 @@ import ( evmrelaytypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" "github.com/smartcontractkit/chainlink/v2/core/services/synchronization" "github.com/smartcontractkit/chainlink/v2/core/services/telemetry" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/plugins" ) @@ -116,7 +116,7 @@ type Delegate struct { ethKs keystore.Eth RelayGetter isNewlyCreatedJob bool // Set to true if this is a new job freshly added, false if job was present already on node boot. - mailMon *utils.MailboxMonitor + mailMon *mailbox.Monitor legacyChains legacyevm.LegacyChainContainer // legacy: use relayers instead } @@ -226,7 +226,7 @@ func NewDelegate( dkgEncryptKs keystore.DKGEncrypt, ethKs keystore.Eth, relayers RelayGetter, - mailMon *utils.MailboxMonitor, + mailMon *mailbox.Monitor, eventBroadcaster pg.EventBroadcaster, ) *Delegate { return &Delegate{ diff --git a/core/services/ocr2/plugins/functions/plugin.go b/core/services/ocr2/plugins/functions/plugin.go index 61fa7f5d825..7e2b15bdccf 100644 --- a/core/services/ocr2/plugins/functions/plugin.go +++ b/core/services/ocr2/plugins/functions/plugin.go @@ -14,6 +14,7 @@ import ( libocr2 "github.com/smartcontractkit/libocr/offchainreporting2plus" "github.com/smartcontractkit/chainlink-common/pkg/assets" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" @@ -43,7 +44,7 @@ type FunctionsServicesConfig struct { Chain legacyevm.Chain ContractID string Logger logger.Logger - MailMon *utils.MailboxMonitor + MailMon *mailbox.Monitor URLsMonEndpoint commontypes.MonitoringEndpoint EthKeystore keystore.Eth ThresholdKeyShare []byte diff --git a/core/services/pipeline/task.eth_tx.go b/core/services/pipeline/task.eth_tx.go index c421b340c91..58e9f6f2c15 100644 --- a/core/services/pipeline/task.eth_tx.go +++ b/core/services/pipeline/task.eth_tx.go @@ -13,11 +13,11 @@ import ( "go.uber.org/multierr" "gopkg.in/guregu/null.v4" + clnull "github.com/smartcontractkit/chainlink-common/pkg/utils/null" txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/logger" - clnull "github.com/smartcontractkit/chainlink/v2/core/null" "github.com/smartcontractkit/chainlink/v2/core/utils" ) diff --git a/core/services/pipeline/task.eth_tx_test.go b/core/services/pipeline/task.eth_tx_test.go index a0ff54d4448..5f5019d1967 100644 --- a/core/services/pipeline/task.eth_tx_test.go +++ b/core/services/pipeline/task.eth_tx_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "gopkg.in/guregu/null.v4" + clnull "github.com/smartcontractkit/chainlink-common/pkg/utils/null" txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" "github.com/smartcontractkit/chainlink/v2/core/chains" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" @@ -19,7 +20,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" - clnull "github.com/smartcontractkit/chainlink/v2/core/null" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" keystoremocks "github.com/smartcontractkit/chainlink/v2/core/services/keystore/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" diff --git a/core/services/promreporter/prom_reporter.go b/core/services/promreporter/prom_reporter.go index 3e1444a6da1..a302a6fa220 100644 --- a/core/services/promreporter/prom_reporter.go +++ b/core/services/promreporter/prom_reporter.go @@ -17,10 +17,11 @@ import ( "go.uber.org/multierr" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) //go:generate mockery --quiet --name PrometheusBackend --output ../../internal/mocks/ --case=underscore @@ -31,7 +32,7 @@ type ( chains legacyevm.LegacyChainContainer lggr logger.Logger backend PrometheusBackend - newHeads *utils.Mailbox[*evmtypes.Head] + newHeads *mailbox.Mailbox[*evmtypes.Head] chStop services.StopChan wgDone sync.WaitGroup reportPeriod time.Duration @@ -109,7 +110,7 @@ func NewPromReporter(db *sql.DB, chainContainer legacyevm.LegacyChainContainer, chains: chainContainer, lggr: lggr.Named("PromReporter"), backend: backend, - newHeads: utils.NewSingleMailbox[*evmtypes.Head](), + newHeads: mailbox.NewSingle[*evmtypes.Head](), chStop: chStop, reportPeriod: period, } diff --git a/core/services/vrf/delegate.go b/core/services/vrf/delegate.go index a13df71d9a3..03e40614a10 100644 --- a/core/services/vrf/delegate.go +++ b/core/services/vrf/delegate.go @@ -12,6 +12,7 @@ import ( "github.com/jmoiron/sqlx" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" @@ -29,7 +30,6 @@ import ( v1 "github.com/smartcontractkit/chainlink/v2/core/services/vrf/v1" v2 "github.com/smartcontractkit/chainlink/v2/core/services/vrf/v2" "github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrfcommon" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) type Delegate struct { @@ -39,7 +39,7 @@ type Delegate struct { ks keystore.Master legacyChains legacyevm.LegacyChainContainer lggr logger.Logger - mailMon *utils.MailboxMonitor + mailMon *mailbox.Monitor } func NewDelegate( @@ -50,7 +50,7 @@ func NewDelegate( legacyChains legacyevm.LegacyChainContainer, lggr logger.Logger, cfg pg.QConfig, - mailMon *utils.MailboxMonitor) *Delegate { + mailMon *mailbox.Monitor) *Delegate { return &Delegate{ q: pg.NewQ(db, lggr, cfg), ks: ks, @@ -250,7 +250,7 @@ func (d *Delegate) ServicesForSpec(jb job.Job) ([]job.ServiceCtx, error) { MailMon: d.mailMon, // Note the mailbox size effectively sets a limit on how many logs we can replay // in the event of a VRF outage. - ReqLogs: utils.NewHighCapacityMailbox[log.Broadcast](), + ReqLogs: mailbox.NewHighCapacity[log.Broadcast](), ChStop: make(chan struct{}), WaitOnStop: make(chan struct{}), NewHead: make(chan struct{}, 1), diff --git a/core/services/vrf/delegate_test.go b/core/services/vrf/delegate_test.go index d957e3c721e..3b643d19b0b 100644 --- a/core/services/vrf/delegate_test.go +++ b/core/services/vrf/delegate_test.go @@ -16,6 +16,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" @@ -149,7 +150,7 @@ func setup(t *testing.T) (vrfUniverse, *v1.Listener, job.Job) { cfg := configtest.NewTestGeneralConfig(t) vuni := buildVrfUni(t, db, cfg) - mailMon := servicetest.Run(t, utils.NewMailboxMonitor(t.Name())) + mailMon := servicetest.Run(t, mailbox.NewMonitor(t.Name())) vd := vrf.NewDelegate( db, @@ -673,7 +674,7 @@ func Test_VRFV2PlusServiceFailsWhenVRFOwnerProvided(t *testing.T) { cfg := configtest.NewTestGeneralConfig(t) vuni := buildVrfUni(t, db, cfg) - mailMon := servicetest.Run(t, utils.NewMailboxMonitor(t.Name())) + mailMon := servicetest.Run(t, mailbox.NewMonitor(t.Name())) vd := vrf.NewDelegate( db, diff --git a/core/services/vrf/v1/listener_v1.go b/core/services/vrf/v1/listener_v1.go index 66a8ddcd58c..f4e813d7d61 100644 --- a/core/services/vrf/v1/listener_v1.go +++ b/core/services/vrf/v1/listener_v1.go @@ -17,6 +17,7 @@ import ( "github.com/theodesp/go-heaps/pairing" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" "github.com/smartcontractkit/chainlink-common/pkg/utils/mathutil" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log" @@ -57,8 +58,8 @@ type Listener struct { Job job.Job Q pg.Q GethKs vrfcommon.GethKeyStore - MailMon *utils.MailboxMonitor - ReqLogs *utils.Mailbox[log.Broadcast] + MailMon *mailbox.Monitor + ReqLogs *mailbox.Mailbox[log.Broadcast] ChStop services.StopChan WaitOnStop chan struct{} NewHead chan struct{} diff --git a/core/services/vrf/v2/listener_v2.go b/core/services/vrf/v2/listener_v2.go index 5878bf54763..6556bbd2186 100644 --- a/core/services/vrf/v2/listener_v2.go +++ b/core/services/vrf/v2/listener_v2.go @@ -14,6 +14,7 @@ import ( "github.com/theodesp/go-heaps/pairing" "github.com/smartcontractkit/chainlink-common/pkg/services" + txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" diff --git a/core/services/vrf/v2/listener_v2_test.go b/core/services/vrf/v2/listener_v2_test.go index 6192db95dfe..d8bc0a6695b 100644 --- a/core/services/vrf/v2/listener_v2_test.go +++ b/core/services/vrf/v2/listener_v2_test.go @@ -17,6 +17,8 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrfcommon" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" + clnull "github.com/smartcontractkit/chainlink-common/pkg/utils/null" + txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" @@ -28,7 +30,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" - clnull "github.com/smartcontractkit/chainlink/v2/core/null" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/testdata/testspecs" "github.com/smartcontractkit/chainlink/v2/core/utils" diff --git a/core/utils/mailbox.go b/core/utils/mailbox.go deleted file mode 100644 index 87fe1627f37..00000000000 --- a/core/utils/mailbox.go +++ /dev/null @@ -1,126 +0,0 @@ -package utils - -import ( - "sync" - "sync/atomic" -) - -// Mailbox contains a notify channel, -// a mutual exclusive lock, -// a queue of interfaces, -// and a queue capacity. -type Mailbox[T any] struct { - mu sync.Mutex - chNotify chan struct{} - queue []T - queueLen atomic.Int64 // atomic so monitor can read w/o blocking the queue - - // capacity - number of items the mailbox can buffer - // NOTE: if the capacity is 1, it's possible that an empty Retrieve may occur after a notification. - capacity uint64 - // onCloseFn is a hook used to stop monitoring, if non-nil - onCloseFn func() -} - -// NewHighCapacityMailbox create a new mailbox with a capacity -// that is better able to handle e.g. large log replays. -func NewHighCapacityMailbox[T any]() *Mailbox[T] { - return NewMailbox[T](100_000) -} - -// NewSingleMailbox returns a new Mailbox with capacity one. -func NewSingleMailbox[T any]() *Mailbox[T] { return NewMailbox[T](1) } - -// NewMailbox creates a new mailbox instance. If name is non-empty, it must be unique and calling Start will launch -// prometheus metric monitor that periodically reports mailbox load until Close() is called. -func NewMailbox[T any](capacity uint64) *Mailbox[T] { - queueCap := capacity - if queueCap == 0 { - queueCap = 100 - } - return &Mailbox[T]{ - chNotify: make(chan struct{}, 1), - queue: make([]T, 0, queueCap), - capacity: capacity, - } -} - -// Notify returns the contents of the notify channel -func (m *Mailbox[T]) Notify() <-chan struct{} { - return m.chNotify -} - -func (m *Mailbox[T]) Close() error { - if m.onCloseFn != nil { - m.onCloseFn() - } - return nil -} - -func (m *Mailbox[T]) onClose(fn func()) { m.onCloseFn = fn } - -func (m *Mailbox[T]) load() (capacity uint64, loadPercent float64) { - capacity = m.capacity - loadPercent = 100 * float64(m.queueLen.Load()) / float64(capacity) - return -} - -// Deliver appends to the queue and returns true if the queue was full, causing a message to be dropped. -func (m *Mailbox[T]) Deliver(x T) (wasOverCapacity bool) { - m.mu.Lock() - defer m.mu.Unlock() - - m.queue = append([]T{x}, m.queue...) - if uint64(len(m.queue)) > m.capacity && m.capacity > 0 { - m.queue = m.queue[:len(m.queue)-1] - wasOverCapacity = true - } else { - m.queueLen.Add(1) - } - - select { - case m.chNotify <- struct{}{}: - default: - } - return -} - -// Retrieve fetches one element from the queue. -func (m *Mailbox[T]) Retrieve() (t T, ok bool) { - m.mu.Lock() - defer m.mu.Unlock() - if len(m.queue) == 0 { - return - } - t = m.queue[len(m.queue)-1] - m.queue = m.queue[:len(m.queue)-1] - m.queueLen.Add(-1) - ok = true - return -} - -// RetrieveAll fetches all elements from the queue. -func (m *Mailbox[T]) RetrieveAll() []T { - m.mu.Lock() - defer m.mu.Unlock() - queue := m.queue - m.queue = nil - m.queueLen.Store(0) - for i, j := 0, len(queue)-1; i < j; i, j = i+1, j-1 { - queue[i], queue[j] = queue[j], queue[i] - } - return queue -} - -// RetrieveLatestAndClear fetch the latest value (or nil), and clears the rest of the queue (if any). -func (m *Mailbox[T]) RetrieveLatestAndClear() (t T) { - m.mu.Lock() - defer m.mu.Unlock() - if len(m.queue) == 0 { - return - } - t = m.queue[0] - m.queue = nil - m.queueLen.Store(0) - return -} diff --git a/core/utils/mailbox_prom.go b/core/utils/mailbox_prom.go deleted file mode 100644 index 33cbb2357b1..00000000000 --- a/core/utils/mailbox_prom.go +++ /dev/null @@ -1,93 +0,0 @@ -package utils - -import ( - "context" - "strconv" - "strings" - "sync" - "time" - - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promauto" - - "github.com/smartcontractkit/chainlink-common/pkg/services" -) - -var mailboxLoad = promauto.NewGaugeVec(prometheus.GaugeOpts{ - Name: "mailbox_load_percent", - Help: "Percent of mailbox capacity used", -}, - []string{"appID", "name", "capacity"}, -) - -const mailboxPromInterval = 5 * time.Second - -type MailboxMonitor struct { - services.StateMachine - appID string - - mailboxes sync.Map - stop func() - done chan struct{} -} - -func NewMailboxMonitor(appID string) *MailboxMonitor { - return &MailboxMonitor{appID: appID} -} - -func (m *MailboxMonitor) Name() string { return "MailboxMonitor" } - -func (m *MailboxMonitor) Start(context.Context) error { - return m.StartOnce("MailboxMonitor", func() error { - t := time.NewTicker(WithJitter(mailboxPromInterval)) - ctx, cancel := context.WithCancel(context.Background()) - m.stop = func() { - t.Stop() - cancel() - } - m.done = make(chan struct{}) - go m.monitorLoop(ctx, t.C) - return nil - }) -} - -func (m *MailboxMonitor) Close() error { - return m.StopOnce("MailboxMonitor", func() error { - m.stop() - <-m.done - return nil - }) -} - -func (m *MailboxMonitor) HealthReport() map[string]error { - return map[string]error{m.Name(): m.Healthy()} -} - -func (m *MailboxMonitor) monitorLoop(ctx context.Context, c <-chan time.Time) { - defer close(m.done) - for { - select { - case <-ctx.Done(): - return - case <-c: - m.mailboxes.Range(func(k, v any) bool { - name, mb := k.(string), v.(mailbox) - c, p := mb.load() - capacity := strconv.FormatUint(c, 10) - mailboxLoad.WithLabelValues(m.appID, name, capacity).Set(p) - return true - }) - } - } -} - -type mailbox interface { - load() (capacity uint64, percent float64) - onClose(func()) -} - -func (m *MailboxMonitor) Monitor(mb mailbox, name ...string) { - n := strings.Join(name, ".") - m.mailboxes.Store(n, mb) - mb.onClose(func() { m.mailboxes.Delete(n) }) -} diff --git a/core/utils/mailbox_test.go b/core/utils/mailbox_test.go deleted file mode 100644 index c83d0035baa..00000000000 --- a/core/utils/mailbox_test.go +++ /dev/null @@ -1,181 +0,0 @@ -package utils - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestMailbox(t *testing.T) { - var ( - expected = []int{2, 3, 4, 5, 6, 7, 8, 9, 10, 11} - toDeliver = []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11} - ) - - const capacity = 10 - m := NewMailbox[int](capacity) - - // Queue deliveries - for i, d := range toDeliver { - atCapacity := m.Deliver(d) - if atCapacity && i < capacity { - t.Errorf("mailbox at capacity %d", i) - } else if !atCapacity && i >= capacity { - t.Errorf("mailbox below capacity %d", i) - } - } - - // Retrieve them - var recvd []int - chDone := make(chan struct{}) - go func() { - defer close(chDone) - for range m.Notify() { - for { - x, exists := m.Retrieve() - if !exists { - break - } - recvd = append(recvd, x) - } - } - }() - - close(m.chNotify) - <-chDone - - require.Equal(t, expected, recvd) -} - -func TestMailbox_RetrieveAll(t *testing.T) { - var ( - expected = []int{2, 3, 4, 5, 6, 7, 8, 9, 10, 11} - toDeliver = []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11} - ) - - const capacity = 10 - m := NewMailbox[int](capacity) - - // Queue deliveries - for i, d := range toDeliver { - atCapacity := m.Deliver(d) - if atCapacity && i < capacity { - t.Errorf("mailbox at capacity %d", i) - } else if !atCapacity && i >= capacity { - t.Errorf("mailbox below capacity %d", i) - } - } - - require.Equal(t, expected, m.RetrieveAll()) -} - -func TestMailbox_RetrieveLatestAndClear(t *testing.T) { - var ( - expected = 11 - toDeliver = []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11} - ) - - const capacity = 10 - m := NewMailbox[int](capacity) - - // Queue deliveries - for i, d := range toDeliver { - atCapacity := m.Deliver(d) - if atCapacity && i < capacity { - t.Errorf("mailbox at capacity %d", i) - } else if !atCapacity && i >= capacity { - t.Errorf("mailbox below capacity %d", i) - } - } - - require.Equal(t, expected, m.RetrieveLatestAndClear()) - require.Len(t, m.RetrieveAll(), 0) -} - -func TestMailbox_NoEmptyReceivesWhenCapacityIsTwo(t *testing.T) { - m := NewMailbox[int](2) - - var ( - recvd []int - emptyReceives []int - ) - - chDone := make(chan struct{}) - go func() { - defer close(chDone) - for range m.Notify() { - x, exists := m.Retrieve() - if !exists { - emptyReceives = append(emptyReceives, recvd[len(recvd)-1]) - } else { - recvd = append(recvd, x) - } - } - }() - - for i := 0; i < 100000; i++ { - m.Deliver(i) - } - close(m.chNotify) - - <-chDone - require.Len(t, emptyReceives, 0) -} - -func TestMailbox_load(t *testing.T) { - for _, tt := range []struct { - name string - capacity uint64 - deliver []int - exp float64 - - retrieve int - exp2 float64 - - all bool - }{ - {"single-all", 1, []int{1}, 100, 0, 100, true}, - {"single-latest", 1, []int{1}, 100, 0, 100, false}, - {"ten-low", 10, []int{1}, 10, 1, 0.0, false}, - {"ten-full-all", 10, []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 100, 5, 50, true}, - {"ten-full-latest", 10, []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 100, 5, 50, false}, - {"ten-overflow", 10, []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 100, 5, 50, false}, - {"nine", 9, []int{1, 2, 3}, 100.0 / 3.0, 2, 100.0 / 9.0, true}, - } { - t.Run(tt.name, func(t *testing.T) { - m := NewMailbox[int](tt.capacity) - - // Queue deliveries - for i, d := range tt.deliver { - atCapacity := m.Deliver(d) - if atCapacity && i < int(tt.capacity) { - t.Errorf("mailbox at capacity %d", i) - } else if !atCapacity && i >= int(tt.capacity) { - t.Errorf("mailbox below capacity %d", i) - } - } - gotCap, gotLoad := m.load() - require.Equal(t, gotCap, tt.capacity) - require.Equal(t, gotLoad, tt.exp) - - // Retrieve some - for i := 0; i < tt.retrieve; i++ { - _, ok := m.Retrieve() - require.True(t, ok) - } - gotCap, gotLoad = m.load() - require.Equal(t, gotCap, tt.capacity) - require.Equal(t, gotLoad, tt.exp2) - - // Drain it - if tt.all { - m.RetrieveAll() - } else { - m.RetrieveLatestAndClear() - } - gotCap, gotLoad = m.load() - require.Equal(t, gotCap, tt.capacity) - require.Equal(t, gotLoad, 0.0) - }) - } -} diff --git a/core/utils/utils.go b/core/utils/utils.go index b887fe9a800..4f3f9212337 100644 --- a/core/utils/utils.go +++ b/core/utils/utils.go @@ -27,7 +27,6 @@ import ( "github.com/robfig/cron/v3" "golang.org/x/crypto/bcrypt" "golang.org/x/crypto/sha3" - "golang.org/x/exp/constraints" ragep2ptypes "github.com/smartcontractkit/libocr/ragep2p/types" @@ -879,26 +878,6 @@ func TryParseHex(s string) (b []byte, err error) { return } -// MinKey returns the minimum value of the given element array with respect -// to the given key function. In the event U is not a compound type (e.g a -// struct) an identity function can be provided. -func MinKey[U any, T constraints.Ordered](elems []U, key func(U) T) T { - var min T - if len(elems) == 0 { - return min - } - - min = key(elems[0]) - for i := 1; i < len(elems); i++ { - v := key(elems[i]) - if v < min { - min = v - } - } - - return min -} - // ErrorBuffer uses joinedErrors interface to join multiple errors into a single error. // This is useful to track the most recent N errors in a service and flush them as a single error. type ErrorBuffer struct { From cf74cd0c9e9601c213b03c9d076339464a634291 Mon Sep 17 00:00:00 2001 From: Bartek Tofel Date: Tue, 12 Dec 2023 11:50:40 -0300 Subject: [PATCH 03/29] Use multiple EL clients with ocrv2 median smoke test (#11399) * use multiple EL clients with ocrv2 median test * update ethereum network component to latest * try with latest implementation of eth clients * change WithTestLogger() to WithTestInstance() * fix geth backward compatibility * run ocrv2 eth2 tests in parallel * run also ocr1 and 2 vrf tests iwth multiple clients * try running multipl el client tests in parallel * fix go.sum * fix lint * 1. add matrix for running 4 smoke tests on different execution clients, 2. if for these tests no client is set in env var use geth * comment out failing nethermind & besu vrf tests in the CI * fix go.sum * do not use negative lookahead with go test * use faster eth2 network config * add comment to integration tests workflow * run only OCR and OCRv2 jobs with multiple clients, add on-demand jobs for VRF * use latest ctf with increased network timeout * slow down private eth networks a bit * update CTF dep to tagged version * disable nethermind ocr smoke tests in CI * fix compilation errors --- .github/workflows/integration-tests.yml | 67 +++++++++++++++++- .../on-demand-vrfv2-eth2-clients-test.yml | 70 +++++++++++++++++++ .../on-demand-vrfv2plus-eth2-clients-test.yml | 70 +++++++++++++++++++ .gitignore | 2 +- integration-tests/actions/private_network.go | 33 +++++++++ integration-tests/docker/test_env/cl_node.go | 2 +- integration-tests/docker/test_env/test_env.go | 6 +- .../docker/test_env/test_env_builder.go | 10 ++- integration-tests/go.mod | 2 +- integration-tests/go.sum | 5 +- integration-tests/load/vrfv2/vrfv2_test.go | 4 +- .../load/vrfv2plus/vrfv2plus_test.go | 4 +- .../migration/upgrade_version_test.go | 2 +- integration-tests/smoke/automation_test.go | 4 +- integration-tests/smoke/cron_test.go | 4 +- integration-tests/smoke/flux_test.go | 2 +- integration-tests/smoke/forwarder_ocr_test.go | 2 +- .../smoke/forwarders_ocr2_test.go | 2 +- integration-tests/smoke/keeper_test.go | 2 +- integration-tests/smoke/ocr2_test.go | 10 ++- integration-tests/smoke/ocr_test.go | 9 ++- integration-tests/smoke/runlog_test.go | 2 +- integration-tests/smoke/vrf_test.go | 4 +- integration-tests/smoke/vrfv2_test.go | 11 +-- integration-tests/smoke/vrfv2plus_test.go | 14 ++-- .../universal/log_poller/helpers.go | 5 +- 26 files changed, 303 insertions(+), 45 deletions(-) create mode 100644 .github/workflows/on-demand-vrfv2-eth2-clients-test.yml create mode 100644 .github/workflows/on-demand-vrfv2plus-eth2-clients-test.yml create mode 100644 integration-tests/actions/private_network.go diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 37a2718be46..6ffd1a14ff2 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -325,11 +325,73 @@ jobs: - name: ocr nodes: 1 os: ubuntu20.04-8cores-32GB + run: -run TestOCRJobReplacement + file: ocr pyroscope_env: ci-smoke-ocr-evm-simulated + - name: ocr-geth + nodes: 1 + os: ubuntu20.04-8cores-32GB + run: -run TestOCRBasic + file: ocr + client: geth + pyroscope_env: ci-smoke-ocr-evm-simulated + # Uncomment, when https://smartcontract-it.atlassian.net/browse/TT-753 is DONE + # - name: ocr-nethermind + # nodes: 1 + # os: ubuntu20.04-8cores-32GB + # run: -run TestOCRBasic + # file: ocr + # client: nethermind + # pyroscope_env: ci-smoke-ocr-evm-simulated + - name: ocr-besu + nodes: 1 + os: ubuntu20.04-8cores-32GB + run: -run TestOCRBasic + file: ocr + client: besu + pyroscope_env: ci-smoke-ocr-evm-simulated + - name: ocr-erigon + nodes: 1 + os: ubuntu20.04-8cores-32GB + run: -run TestOCRBasic + file: ocr + client: erigon + pyroscope_env: ci-smoke-ocr-evm-simulated - name: ocr2 nodes: 1 os: ubuntu20.04-8cores-32GB + run: -run TestOCRv2JobReplacement + file: ocr2 pyroscope_env: ci-smoke-ocr2-evm-simulated + - name: ocr2-geth + nodes: 1 + os: ubuntu20.04-8cores-32GB + run: -run TestOCRv2Basic + file: ocr2 + client: geth + pyroscope_env: ci-smoke-ocr2-evm-simulated + # Uncomment, when https://smartcontract-it.atlassian.net/browse/TT-753 is DONE + # - name: ocr2-nethermind + # nodes: 1 + # os: ubuntu20.04-8cores-32GB + # run: -run TestOCRv2Basic + # file: ocr2 + # client: nethermind + # pyroscope_env: ci-smoke-ocr2-evm-simulated + - name: ocr2-besu + nodes: 1 + os: ubuntu20.04-8cores-32GB + run: -run TestOCRv2Basic + file: ocr2 + client: besu + pyroscope_env: ci-smoke-ocr2-evm-simulated + - name: ocr2-erigon + nodes: 1 + os: ubuntu20.04-8cores-32GB + run: -run TestOCRv2Basic + file: ocr2 + client: erigon + pyroscope_env: ci-smoke-ocr2-evm-simulated - name: ocr2 nodes: 1 os: ubuntu20.04-8cores-32GB @@ -345,12 +407,14 @@ jobs: pyroscope_env: ci-smoke-vrf-evm-simulated - name: vrfv2 nodes: 1 + run: -run TestVRFv2MultipleSendingKeys + file: vrfv2 os: ubuntu20.04-8cores-32GB pyroscope_env: ci-smoke-vrf2-evm-simulated - name: vrfv2plus nodes: 1 os: ubuntu20.04-8cores-32GB - pyroscope_env: ci-smoke-vrf2plus-evm-simulated + pyroscope_env: ci-smoke-vrf2plus-evm-simulated - name: forwarder_ocr nodes: 1 os: ubuntu20.04-8cores-32GB @@ -435,6 +499,7 @@ jobs: PYROSCOPE_SERVER: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 PYROSCOPE_ENVIRONMENT: ${{ matrix.product.pyroscope_env }} PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} + ETH2_EL_CLIENT: ${{matrix.product.client}} LOKI_TENANT_ID: ${{ vars.LOKI_TENANT_ID }} LOKI_URL: ${{ secrets.LOKI_URL }} LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} diff --git a/.github/workflows/on-demand-vrfv2-eth2-clients-test.yml b/.github/workflows/on-demand-vrfv2-eth2-clients-test.yml new file mode 100644 index 00000000000..3b27e4519c8 --- /dev/null +++ b/.github/workflows/on-demand-vrfv2-eth2-clients-test.yml @@ -0,0 +1,70 @@ +name: On Demand VRFV2 Smoke Test (Ethereum clients) +on: + workflow_dispatch: + inputs: + client: + description: Execution client to use + type: choice + options: + - "geth" + - "nethermind" + - "besu" + - "erigon" + chainlinkImage: + description: Container image location for the Chainlink nodes + required: true + default: public.ecr.aws/chainlink/chainlink + chainlinkVersion: + description: Container image version for the Chainlink nodes + required: true + default: "2.6.0" + configBase64: + description: TOML config in base64 (Needed when overriding config or providing contract addresses for existing env) + required: false +jobs: + vrfv2_smoke_test: + name: VRFV2 Smoke Test with ${{ inputs.client }} client + environment: integration + runs-on: ubuntu20.04-8cores-32GB + permissions: + checks: write + pull-requests: write + id-token: write + contents: read + env: + SELECTED_NETWORKS: "SIMULATED" + CONFIG: ${{ inputs.configBase64 }} + TEST_LOG_LEVEL: debug + REF_NAME: ${{ github.head_ref || github.ref_name }} + CHAINLINK_IMAGE: ${{ inputs.chainlinkImage }} + CHAINLINK_VERSION: ${{ inputs.chainlinkVersion }} + steps: + - name: Setup Push Tag + shell: bash + run: | + echo "### chainlink image used for this test run :link:" >>$GITHUB_STEP_SUMMARY + echo "\`${{ inputs.chainlinkVersion }}\`" >>$GITHUB_STEP_SUMMARY + echo "### chainlink-tests image tag for this test run :ship:" >>$GITHUB_STEP_SUMMARY + echo "\`${GITHUB_SHA}\`" >>$GITHUB_STEP_SUMMARY + - name: Checkout code + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + fetch-depth: 0 + - name: Run Tests + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15 + with: + test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -run TestVRFv2Basic ./smoke/vrfv2_test.go 2>&1 | tee /tmp/gotest.log | gotestfmt + test_download_vendor_packages_command: cd ./integration-tests && go mod download + cl_repo: ${{ inputs.chainlinkImage }} + cl_image_tag: ${{ inputs.chainlinkVersion }} + aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} + artifacts_name: vrf-test-logs + artifacts_location: ./integration-tests/smoke/logs/ + token: ${{ secrets.GITHUB_TOKEN }} + go_mod_path: ./integration-tests/go.mod + should_cleanup: false + QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} + QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + QA_KUBECONFIG: "" + env: + ETH2_EL_CLIENT: ${{ inputs.client }} diff --git a/.github/workflows/on-demand-vrfv2plus-eth2-clients-test.yml b/.github/workflows/on-demand-vrfv2plus-eth2-clients-test.yml new file mode 100644 index 00000000000..331c626ba9c --- /dev/null +++ b/.github/workflows/on-demand-vrfv2plus-eth2-clients-test.yml @@ -0,0 +1,70 @@ +name: On Demand VRFV2Plus Smoke Test (Ethereum clients) +on: + workflow_dispatch: + inputs: + client: + description: Execution client to use + type: choice + options: + - "geth" + - "nethermind" + - "besu" + - "erigon" + chainlinkImage: + description: Container image location for the Chainlink nodes + required: true + default: public.ecr.aws/chainlink/chainlink + chainlinkVersion: + description: Container image version for the Chainlink nodes + required: true + default: "2.6.0" + configBase64: + description: TOML config in base64 (Needed when overriding config or providing contract addresses for existing env) + required: false +jobs: + vrfv2plus_smoke_test: + name: VRFV2Plus Smoke Test with ${{ inputs.client }} client + environment: integration + runs-on: ubuntu20.04-8cores-32GB + permissions: + checks: write + pull-requests: write + id-token: write + contents: read + env: + SELECTED_NETWORKS: "SIMULATED" + CONFIG: ${{ inputs.configBase64 }} + TEST_LOG_LEVEL: debug + REF_NAME: ${{ github.head_ref || github.ref_name }} + CHAINLINK_IMAGE: ${{ inputs.chainlinkImage }} + CHAINLINK_VERSION: ${{ inputs.chainlinkVersion }} + steps: + - name: Setup Push Tag + shell: bash + run: | + echo "### chainlink image used for this test run :link:" >>$GITHUB_STEP_SUMMARY + echo "\`${{ inputs.chainlinkVersion }}\`" >>$GITHUB_STEP_SUMMARY + echo "### chainlink-tests image tag for this test run :ship:" >>$GITHUB_STEP_SUMMARY + echo "\`${GITHUB_SHA}\`" >>$GITHUB_STEP_SUMMARY + - name: Checkout code + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + fetch-depth: 0 + - name: Run Tests + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15 + with: + test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -run ^TestVRFv2Plus$/^Link_Billing$ ./smoke/vrfv2plus_test.go 2>&1 | tee /tmp/gotest.log | gotestfmt + test_download_vendor_packages_command: cd ./integration-tests && go mod download + cl_repo: ${{ inputs.chainlinkImage }} + cl_image_tag: ${{ inputs.chainlinkVersion }} + aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} + artifacts_name: vrfplus-test-logs + artifacts_location: ./integration-tests/smoke/logs/ + token: ${{ secrets.GITHUB_TOKEN }} + go_mod_path: ./integration-tests/go.mod + should_cleanup: false + QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} + QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + QA_KUBECONFIG: "" + env: + ETH2_EL_CLIENT: ${{ inputs.client }} diff --git a/.gitignore b/.gitignore index 8d127dbb728..2f68ec2c945 100644 --- a/.gitignore +++ b/.gitignore @@ -84,4 +84,4 @@ go.work* tools/flakeytests/coverage.txt .test_summary/ -.run.id \ No newline at end of file +.run.id diff --git a/integration-tests/actions/private_network.go b/integration-tests/actions/private_network.go new file mode 100644 index 00000000000..c7556f8061b --- /dev/null +++ b/integration-tests/actions/private_network.go @@ -0,0 +1,33 @@ +package actions + +import ( + "errors" + + "github.com/rs/zerolog" + + ctf_test_env "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" +) + +func EthereumNetworkConfigFromEnvOrDefault(l zerolog.Logger) (network ctf_test_env.EthereumNetwork, err error) { + chainConfig := ctf_test_env.EthereumChainConfig{ + SecondsPerSlot: 8, + SlotsPerEpoch: 4, + } + + ethBuilder := ctf_test_env.NewEthereumNetworkBuilder() + network, err = ethBuilder. + WithExecClientFromEnvVar(). + WithEthereumChainConfig(chainConfig). + Build() + + if errors.Is(err, ctf_test_env.ErrMissingExecClientEnvVar) { + l.Warn().Msg("No exec client env var set, will use old geth") + ethBuilder = ctf_test_env.NewEthereumNetworkBuilder() + network, err = ethBuilder. + WithConsensusType(ctf_test_env.ConsensusType_PoW). + WithExecutionLayer(ctf_test_env.ExecutionLayer_Geth). + Build() + } + + return +} diff --git a/integration-tests/docker/test_env/cl_node.go b/integration-tests/docker/test_env/cl_node.go index 60394256334..b79bb91c70e 100644 --- a/integration-tests/docker/test_env/cl_node.go +++ b/integration-tests/docker/test_env/cl_node.go @@ -112,7 +112,7 @@ func NewClNode(networks []string, imageName, imageVersion string, nodeConfig *ch func (n *ClNode) SetTestLogger(t *testing.T) { n.l = logging.GetTestLogger(t) n.t = t - n.PostgresDb.WithTestLogger(t) + n.PostgresDb.WithTestInstance(t) } // Restart restarts only CL node, DB container is reused diff --git a/integration-tests/docker/test_env/test_env.go b/integration-tests/docker/test_env/test_env.go index 15bf6641bf4..20e231e5985 100644 --- a/integration-tests/docker/test_env/test_env.go +++ b/integration-tests/docker/test_env/test_env.go @@ -71,11 +71,11 @@ func (te *CLClusterTestEnv) WithTestEnvConfig(cfg *TestEnvConfig) *CLClusterTest return te } -func (te *CLClusterTestEnv) WithTestLogger(t *testing.T) *CLClusterTestEnv { +func (te *CLClusterTestEnv) WithTestInstance(t *testing.T) *CLClusterTestEnv { te.t = t te.l = logging.GetTestLogger(t) if te.MockAdapter != nil { - te.MockAdapter.WithTestLogger(t) + te.MockAdapter.WithTestInstance(t) } return te } @@ -90,7 +90,7 @@ func (te *CLClusterTestEnv) WithPrivateChain(evmNetworks []blockchain.EVMNetwork n := evmNetwork pgc := test_env.NewPrivateGethChain(&n, []string{te.Network.Name}) if te.t != nil { - pgc.GetPrimaryNode().WithTestLogger(te.t) + pgc.GetPrimaryNode().WithTestInstance(te.t) } chains = append(chains, pgc) var privateChain test_env.PrivateChain diff --git a/integration-tests/docker/test_env/test_env_builder.go b/integration-tests/docker/test_env/test_env_builder.go index cc0499ea0ce..7358d76f2af 100644 --- a/integration-tests/docker/test_env/test_env_builder.go +++ b/integration-tests/docker/test_env/test_env_builder.go @@ -95,7 +95,7 @@ func (b *CLTestEnvBuilder) WithTestEnv(te *CLClusterTestEnv) (*CLTestEnvBuilder, // WithTestLogger sets the test logger to use for the test. // Useful for parallel tests so the logging will be separated correctly in the results views. -func (b *CLTestEnvBuilder) WithTestLogger(t *testing.T) *CLTestEnvBuilder { +func (b *CLTestEnvBuilder) WithTestInstance(t *testing.T) *CLTestEnvBuilder { b.t = t b.l = logging.GetTestLogger(t) return b @@ -220,8 +220,12 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { } var err error + if b.t != nil { + b.te.WithTestInstance(b.t) + } + if b.hasLogStream { - b.te.LogStream, err = logstream.NewLogStream(b.t, nil) + b.te.LogStream, err = logstream.NewLogStream(b.te.t, nil) if err != nil { return nil, err } @@ -241,7 +245,7 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { } if b.t != nil { - b.te.WithTestLogger(b.t) + b.te.WithTestInstance(b.t) } switch b.cleanUpType { diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 72c15a89669..c080f617552 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -25,7 +25,7 @@ require ( github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.1 github.com/smartcontractkit/chainlink-common v0.1.7-0.20231206181640-faad3f11cfad - github.com/smartcontractkit/chainlink-testing-framework v1.21.0 + github.com/smartcontractkit/chainlink-testing-framework v1.22.0 github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/libocr v0.0.0-20231130143053-c5102a9c0fb7 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 494e5c21ec9..e8cefd67d6d 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1411,6 +1411,7 @@ github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMT github.com/shirou/gopsutil/v3 v3.23.11 h1:i3jP9NjCPUz7FiZKxlMnODZkdSIp2gnzfrvsu9CuWEQ= github.com/shirou/gopsutil/v3 v3.23.11/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= +github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= @@ -1444,8 +1445,8 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231206154215-ec1718b7df3 github.com/smartcontractkit/chainlink-solana v1.0.3-0.20231206154215-ec1718b7df3e/go.mod h1:9YIi413QRRytafTzpWm+Z+5NWBNxSqokhKyeEZ3ynlA= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231205180940-ea2e3e916725 h1:NbhPVwxx+53WN/Uld1V6c4iLgoGvUYFOsVd2kfcexe8= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20231205180940-ea2e3e916725/go.mod h1:vHrPBipRL52NdPp77KXNU2k1IoCUa1B33N9otZQPYko= -github.com/smartcontractkit/chainlink-testing-framework v1.21.0 h1:MrtpGMgPpcRX06FtDEj14Vokoo6Sx8e0/D6AA9LxCgM= -github.com/smartcontractkit/chainlink-testing-framework v1.21.0/go.mod h1:9SCqZ+lcWZNEofpPgasQ+wUF6A6fFgZvWmhqQJwFYV0= +github.com/smartcontractkit/chainlink-testing-framework v1.22.0 h1:Lur628wkrceWgcLmxGZe7Mauwxht4YO71hX9Jj5YslE= +github.com/smartcontractkit/chainlink-testing-framework v1.22.0/go.mod h1:yu6qqrppNJfutQV37fiSs4eS0uQP5QT0ebi3tlIgWN0= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 h1:FFdvEzlYwcuVHkdZ8YnZR/XomeMGbz5E2F2HZI3I3w8= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868/go.mod h1:Kn1Hape05UzFZ7bOUnm3GVsHzP0TNrVmpfXYNHdqGGs= github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306 h1:ko88+ZznniNJZbZPWAvHQU8SwKAdHngdDZ+pvVgB5ss= diff --git a/integration-tests/load/vrfv2/vrfv2_test.go b/integration-tests/load/vrfv2/vrfv2_test.go index 8a0faeabb29..86f9b8d61f6 100644 --- a/integration-tests/load/vrfv2/vrfv2_test.go +++ b/integration-tests/load/vrfv2/vrfv2_test.go @@ -87,7 +87,7 @@ func TestVRFV2Performance(t *testing.T) { vrfv2Config.KeyHash = cfg.ExistingEnvConfig.KeyHash env, err = test_env.NewCLTestEnvBuilder(). - WithTestLogger(t). + WithTestInstance(t). WithCustomCleanup( func() { teardown(t, vrfv2Contracts.LoadTestConsumers[0], lc, updatedLabels, testReporter, testType, vrfv2Config) @@ -156,7 +156,7 @@ func TestVRFV2Performance(t *testing.T) { vrfv2Config.ChainlinkNodeFunding = cfg.NewEnvConfig.NodeSendingKeyFunding vrfv2Config.SubscriptionFundingAmountLink = cfg.NewEnvConfig.Funding.SubFundsLink env, err = test_env.NewCLTestEnvBuilder(). - WithTestLogger(t). + WithTestInstance(t). WithGeth(). WithCLNodes(1). WithFunding(big.NewFloat(vrfv2Config.ChainlinkNodeFunding)). diff --git a/integration-tests/load/vrfv2plus/vrfv2plus_test.go b/integration-tests/load/vrfv2plus/vrfv2plus_test.go index 68c1012987d..6fe0d06e7da 100644 --- a/integration-tests/load/vrfv2plus/vrfv2plus_test.go +++ b/integration-tests/load/vrfv2plus/vrfv2plus_test.go @@ -89,7 +89,7 @@ func TestVRFV2PlusPerformance(t *testing.T) { vrfv2PlusConfig.KeyHash = cfg.ExistingEnvConfig.KeyHash env, err = test_env.NewCLTestEnvBuilder(). - WithTestLogger(t). + WithTestInstance(t). WithCustomCleanup( func() { teardown(t, vrfv2PlusContracts.LoadTestConsumers[0], lc, updatedLabels, testReporter, testType, vrfv2PlusConfig) @@ -162,7 +162,7 @@ func TestVRFV2PlusPerformance(t *testing.T) { vrfv2PlusConfig.SubscriptionFundingAmountLink = cfg.NewEnvConfig.Funding.SubFundsLink vrfv2PlusConfig.SubscriptionFundingAmountNative = cfg.NewEnvConfig.Funding.SubFundsNative env, err = test_env.NewCLTestEnvBuilder(). - WithTestLogger(t). + WithTestInstance(t). WithGeth(). WithCLNodes(1). WithFunding(big.NewFloat(vrfv2PlusConfig.ChainlinkNodeFunding)). diff --git a/integration-tests/migration/upgrade_version_test.go b/integration-tests/migration/upgrade_version_test.go index d1f07a52b74..97db2374bf3 100644 --- a/integration-tests/migration/upgrade_version_test.go +++ b/integration-tests/migration/upgrade_version_test.go @@ -13,7 +13,7 @@ import ( func TestVersionUpgrade(t *testing.T) { t.Parallel() env, err := test_env.NewCLTestEnvBuilder(). - WithTestLogger(t). + WithTestInstance(t). WithGeth(). WithCLNodes(1). Build() diff --git a/integration-tests/smoke/automation_test.go b/integration-tests/smoke/automation_test.go index bc9f1308452..1dbfc78ec87 100644 --- a/integration-tests/smoke/automation_test.go +++ b/integration-tests/smoke/automation_test.go @@ -1092,7 +1092,7 @@ func setupAutomationTestDocker( clNodesCount := 5 if isMercuryV02 || isMercuryV03 { env, err = test_env.NewCLTestEnvBuilder(). - WithTestLogger(t). + WithTestInstance(t). WithGeth(). WithMockAdapter(). WithFunding(big.NewFloat(testConfig.ChainlinkNodeFunding)). @@ -1129,7 +1129,7 @@ func setupAutomationTestDocker( } else { env, err = test_env.NewCLTestEnvBuilder(). - WithTestLogger(t). + WithTestInstance(t). WithGeth(). WithMockAdapter(). WithCLNodes(clNodesCount). diff --git a/integration-tests/smoke/cron_test.go b/integration-tests/smoke/cron_test.go index 3eebc19f8bf..751c2867676 100644 --- a/integration-tests/smoke/cron_test.go +++ b/integration-tests/smoke/cron_test.go @@ -20,7 +20,7 @@ func TestCronBasic(t *testing.T) { l := logging.GetTestLogger(t) env, err := test_env.NewCLTestEnvBuilder(). - WithTestLogger(t). + WithTestInstance(t). WithGeth(). WithMockAdapter(). WithCLNodes(1). @@ -67,7 +67,7 @@ func TestCronJobReplacement(t *testing.T) { l := logging.GetTestLogger(t) env, err := test_env.NewCLTestEnvBuilder(). - WithTestLogger(t). + WithTestInstance(t). WithGeth(). WithMockAdapter(). WithCLNodes(1). diff --git a/integration-tests/smoke/flux_test.go b/integration-tests/smoke/flux_test.go index 5b35b0d2484..828350a9422 100644 --- a/integration-tests/smoke/flux_test.go +++ b/integration-tests/smoke/flux_test.go @@ -26,7 +26,7 @@ func TestFluxBasic(t *testing.T) { l := logging.GetTestLogger(t) env, err := test_env.NewCLTestEnvBuilder(). - WithTestLogger(t). + WithTestInstance(t). WithGeth(). WithMockAdapter(). WithCLNodes(3). diff --git a/integration-tests/smoke/forwarder_ocr_test.go b/integration-tests/smoke/forwarder_ocr_test.go index 923ca046ece..c71c6e31516 100644 --- a/integration-tests/smoke/forwarder_ocr_test.go +++ b/integration-tests/smoke/forwarder_ocr_test.go @@ -19,7 +19,7 @@ func TestForwarderOCRBasic(t *testing.T) { l := logging.GetTestLogger(t) env, err := test_env.NewCLTestEnvBuilder(). - WithTestLogger(t). + WithTestInstance(t). WithGeth(). WithMockAdapter(). WithForwarders(). diff --git a/integration-tests/smoke/forwarders_ocr2_test.go b/integration-tests/smoke/forwarders_ocr2_test.go index bdfd65c767e..c2e2b12e51d 100644 --- a/integration-tests/smoke/forwarders_ocr2_test.go +++ b/integration-tests/smoke/forwarders_ocr2_test.go @@ -24,7 +24,7 @@ func TestForwarderOCR2Basic(t *testing.T) { l := logging.GetTestLogger(t) env, err := test_env.NewCLTestEnvBuilder(). - WithTestLogger(t). + WithTestInstance(t). WithGeth(). WithMockAdapter(). WithCLNodeConfig(node.NewConfig(node.NewBaseConfig(), diff --git a/integration-tests/smoke/keeper_test.go b/integration-tests/smoke/keeper_test.go index 336223b7a4c..1bc416f0456 100644 --- a/integration-tests/smoke/keeper_test.go +++ b/integration-tests/smoke/keeper_test.go @@ -1107,7 +1107,7 @@ func setupKeeperTest(t *testing.T) ( clNodeConfig.Keeper.Registry.PerformGasOverhead = &performGasOverhead env, err := test_env.NewCLTestEnvBuilder(). - WithTestLogger(t). + WithTestInstance(t). WithGeth(). WithCLNodes(5). WithCLNodeConfig(clNodeConfig). diff --git a/integration-tests/smoke/ocr2_test.go b/integration-tests/smoke/ocr2_test.go index 8f0fbd76053..a1a37c3b18e 100644 --- a/integration-tests/smoke/ocr2_test.go +++ b/integration-tests/smoke/ocr2_test.go @@ -19,11 +19,15 @@ import ( // Tests a basic OCRv2 median feed func TestOCRv2Basic(t *testing.T) { + t.Parallel() l := logging.GetTestLogger(t) + network, err := actions.EthereumNetworkConfigFromEnvOrDefault(l) + require.NoError(t, err, "Error building ethereum network config") + env, err := test_env.NewCLTestEnvBuilder(). - WithTestLogger(t). - WithGeth(). + WithTestInstance(t). + WithPrivateEthereumNetwork(network). WithMockAdapter(). WithCLNodeConfig(node.NewConfig(node.NewBaseConfig(), node.WithOCR2(), @@ -97,7 +101,7 @@ func TestOCRv2JobReplacement(t *testing.T) { l := logging.GetTestLogger(t) env, err := test_env.NewCLTestEnvBuilder(). - WithTestLogger(t). + WithTestInstance(t). WithGeth(). WithMockAdapter(). WithCLNodeConfig(node.NewConfig(node.NewBaseConfig(), diff --git a/integration-tests/smoke/ocr_test.go b/integration-tests/smoke/ocr_test.go index 25192248c46..ba158923812 100644 --- a/integration-tests/smoke/ocr_test.go +++ b/integration-tests/smoke/ocr_test.go @@ -17,9 +17,12 @@ func TestOCRBasic(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) + network, err := actions.EthereumNetworkConfigFromEnvOrDefault(l) + require.NoError(t, err, "Error building ethereum network config") + env, err := test_env.NewCLTestEnvBuilder(). - WithTestLogger(t). - WithGeth(). + WithTestInstance(t). + WithPrivateEthereumNetwork(network). WithMockAdapter(). WithCLNodes(6). WithFunding(big.NewFloat(.5)). @@ -66,7 +69,7 @@ func TestOCRJobReplacement(t *testing.T) { l := logging.GetTestLogger(t) env, err := test_env.NewCLTestEnvBuilder(). - WithTestLogger(t). + WithTestInstance(t). WithGeth(). WithMockAdapter(). WithCLNodes(6). diff --git a/integration-tests/smoke/runlog_test.go b/integration-tests/smoke/runlog_test.go index 2fc771fb9bf..5cc21a28c2c 100644 --- a/integration-tests/smoke/runlog_test.go +++ b/integration-tests/smoke/runlog_test.go @@ -23,7 +23,7 @@ func TestRunLogBasic(t *testing.T) { l := logging.GetTestLogger(t) env, err := test_env.NewCLTestEnvBuilder(). - WithTestLogger(t). + WithTestInstance(t). WithGeth(). WithMockAdapter(). WithCLNodes(1). diff --git a/integration-tests/smoke/vrf_test.go b/integration-tests/smoke/vrf_test.go index 04120053745..0554bd34760 100644 --- a/integration-tests/smoke/vrf_test.go +++ b/integration-tests/smoke/vrf_test.go @@ -24,7 +24,7 @@ func TestVRFBasic(t *testing.T) { l := logging.GetTestLogger(t) env, err := test_env.NewCLTestEnvBuilder(). - WithTestLogger(t). + WithTestInstance(t). WithGeth(). WithCLNodes(1). WithFunding(big.NewFloat(.1)). @@ -114,7 +114,7 @@ func TestVRFJobReplacement(t *testing.T) { l := logging.GetTestLogger(t) env, err := test_env.NewCLTestEnvBuilder(). - WithTestLogger(t). + WithTestInstance(t). WithGeth(). WithCLNodes(1). WithFunding(big.NewFloat(.1)). diff --git a/integration-tests/smoke/vrfv2_test.go b/integration-tests/smoke/vrfv2_test.go index 9976de03954..a8edb2c51d9 100644 --- a/integration-tests/smoke/vrfv2_test.go +++ b/integration-tests/smoke/vrfv2_test.go @@ -24,13 +24,16 @@ func TestVRFv2Basic(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) + network, err := actions.EthereumNetworkConfigFromEnvOrDefault(l) + require.NoError(t, err, "Error building ethereum network config") + var vrfv2Config vrfv2_config.VRFV2Config - err := envconfig.Process("VRFV2", &vrfv2Config) + err = envconfig.Process("VRFV2", &vrfv2Config) require.NoError(t, err) env, err := test_env.NewCLTestEnvBuilder(). - WithTestLogger(t). - WithGeth(). + WithTestInstance(t). + WithPrivateEthereumNetwork(network). WithCLNodes(1). WithFunding(big.NewFloat(vrfv2Config.ChainlinkNodeFunding)). WithStandardCleanup(). @@ -121,7 +124,7 @@ func TestVRFv2MultipleSendingKeys(t *testing.T) { require.NoError(t, err) env, err := test_env.NewCLTestEnvBuilder(). - WithTestLogger(t). + WithTestInstance(t). WithGeth(). WithCLNodes(1). WithFunding(big.NewFloat(vrfv2Config.ChainlinkNodeFunding)). diff --git a/integration-tests/smoke/vrfv2plus_test.go b/integration-tests/smoke/vrfv2plus_test.go index 69e1eb7ebde..a850cb4fe15 100644 --- a/integration-tests/smoke/vrfv2plus_test.go +++ b/integration-tests/smoke/vrfv2plus_test.go @@ -29,13 +29,16 @@ func TestVRFv2Plus(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) + network, err := actions.EthereumNetworkConfigFromEnvOrDefault(l) + require.NoError(t, err, "Error building ethereum network config") + var vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig - err := envconfig.Process("VRFV2PLUS", &vrfv2PlusConfig) + err = envconfig.Process("VRFV2PLUS", &vrfv2PlusConfig) require.NoError(t, err) env, err := test_env.NewCLTestEnvBuilder(). - WithTestLogger(t). - WithGeth(). + WithTestInstance(t). + WithPrivateEthereumNetwork(network). WithCLNodes(1). WithFunding(big.NewFloat(vrfv2PlusConfig.ChainlinkNodeFunding)). WithStandardCleanup(). @@ -118,6 +121,7 @@ func TestVRFv2Plus(t *testing.T) { require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0") } }) + t.Run("Native Billing", func(t *testing.T) { testConfig := vrfv2PlusConfig var isNativeBilling = true @@ -612,7 +616,7 @@ func TestVRFv2PlusMultipleSendingKeys(t *testing.T) { require.NoError(t, err) env, err := test_env.NewCLTestEnvBuilder(). - WithTestLogger(t). + WithTestInstance(t). WithGeth(). WithCLNodes(1). WithFunding(big.NewFloat(vrfv2PlusConfig.ChainlinkNodeFunding)). @@ -703,7 +707,7 @@ func TestVRFv2PlusMigration(t *testing.T) { require.NoError(t, err) env, err := test_env.NewCLTestEnvBuilder(). - WithTestLogger(t). + WithTestInstance(t). WithGeth(). WithCLNodes(1). WithFunding(big.NewFloat(vrfv2PlusConfig.ChainlinkNodeFunding)). diff --git a/integration-tests/universal/log_poller/helpers.go b/integration-tests/universal/log_poller/helpers.go index 48f34e6827c..1abd98632f1 100644 --- a/integration-tests/universal/log_poller/helpers.go +++ b/integration-tests/universal/log_poller/helpers.go @@ -1043,7 +1043,8 @@ func setupLogPollerTestDocker( WithConsensusType(ctf_test_env.ConsensusType_PoS). WithConsensusLayer(ctf_test_env.ConsensusLayer_Prysm). WithExecutionLayer(ctf_test_env.ExecutionLayer_Geth). - WithBeaconChainConfig(ctf_test_env.BeaconChainConfig{ + WithWaitingForFinalization(). + WithEthereumChainConfig(ctf_test_env.EthereumChainConfig{ SecondsPerSlot: 8, SlotsPerEpoch: 2, }). @@ -1051,7 +1052,7 @@ func setupLogPollerTestDocker( require.NoError(t, err, "Error building ethereum network config") env, err = test_env.NewCLTestEnvBuilder(). - WithTestLogger(t). + WithTestInstance(t). WithPrivateEthereumNetwork(cfg). WithCLNodes(clNodesCount). WithCLNodeConfig(clNodeConfig). From dfc62cc51035f1dd7a555a6797fe305cd1b09bc6 Mon Sep 17 00:00:00 2001 From: Sergey Kudasov Date: Wed, 13 Dec 2023 00:01:58 +0300 Subject: [PATCH 04/29] disable kaniko fallback, increase deploy wait timeout (#11548) --- charts/chainlink-cluster/devspace.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/charts/chainlink-cluster/devspace.yaml b/charts/chainlink-cluster/devspace.yaml index 186e49257a1..bd50a469ded 100644 --- a/charts/chainlink-cluster/devspace.yaml +++ b/charts/chainlink-cluster/devspace.yaml @@ -37,11 +37,14 @@ images: image: ${DEVSPACE_IMAGE} dockerfile: ../../core/chainlink.devspace.Dockerfile context: ../.. + docker: + disableFallback: true hooks: - wait: running: true terminatedWithCode: 0 + timeout: 600 container: labelSelector: # vars don't work here, = releaseName From 82faf5d4ca91706fa8fdf9fdc9893f97a4449548 Mon Sep 17 00:00:00 2001 From: chris-de-leon-cll <147140544+chris-de-leon-cll@users.noreply.github.com> Date: Tue, 12 Dec 2023 13:07:37 -0800 Subject: [PATCH 05/29] [DEPLOY-178]: Adds Scroll L2EP Contracts (#11405) * Adds scroll L2EP contracts and tests * fixes comments, adds fixed solidity compiler version, and adds scroll tech contracts as a dev dependency * renames SCROLL_CROSS_DOMAIN_MESSENGER to i_SCROLL_CROSS_DOMAIN_MESSENGER for solhint * removes unnecessary solhint disable rule * moves scroll mocks from tests folder to l2ep folder * resolve solhint errors for scroll * proposed restructure to reduce inheritance * removes extraneous comments from scroll contracts and refactors typeAndVersion * use named parameters in mappings for scroll contracts * removes extraneous empty comments from scroll contracts (again) * removes unnecessary comment from scroll cross domain governor * adds minor formatting updates to scroll mocks * adds onlyL1Owner modifier back to ScrollCrossDomainGovernor * adds style and formatting improvements * adds formatting updates * refactors scroll sequencer uptime feed to reduce gas and updates test suites --------- Co-authored-by: Rens Rooimans --- contracts/foundry.toml | 2 +- contracts/package.json | 1 + contracts/pnpm-lock.yaml | 17 +- .../ScrollSequencerUptimeFeedInterface.sol | 6 + .../dev/scroll/ScrollCrossDomainForwarder.sol | 65 +++ .../dev/scroll/ScrollCrossDomainGovernor.sol | 92 ++++ .../dev/scroll/ScrollSequencerUptimeFeed.sol | 231 +++++++++ .../v0.8/l2ep/dev/scroll/ScrollValidator.sol | 77 +++ .../MockScrollL1CrossDomainMessenger.sol | 60 +++ .../MockScrollL2CrossDomainMessenger.sol | 50 ++ .../vendor/MockScrollCrossDomainMessenger.sol | 101 ++++ .../dev/ScrollCrossDomainForwarder.test.ts | 259 ++++++++++ .../dev/ScrollCrossDomainGovernor.test.ts | 459 ++++++++++++++++++ .../dev/ScrollSequencerUptimeFeed.test.ts | 426 ++++++++++++++++ .../test/v0.8/dev/ScrollValidator.test.ts | 118 +++++ 15 files changed, 1961 insertions(+), 3 deletions(-) create mode 100644 contracts/src/v0.8/l2ep/dev/interfaces/ScrollSequencerUptimeFeedInterface.sol create mode 100644 contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainForwarder.sol create mode 100644 contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainGovernor.sol create mode 100644 contracts/src/v0.8/l2ep/dev/scroll/ScrollSequencerUptimeFeed.sol create mode 100644 contracts/src/v0.8/l2ep/dev/scroll/ScrollValidator.sol create mode 100644 contracts/src/v0.8/l2ep/test/mocks/MockScrollL1CrossDomainMessenger.sol create mode 100644 contracts/src/v0.8/l2ep/test/mocks/MockScrollL2CrossDomainMessenger.sol create mode 100644 contracts/src/v0.8/vendor/MockScrollCrossDomainMessenger.sol create mode 100644 contracts/test/v0.8/dev/ScrollCrossDomainForwarder.test.ts create mode 100644 contracts/test/v0.8/dev/ScrollCrossDomainGovernor.test.ts create mode 100644 contracts/test/v0.8/dev/ScrollSequencerUptimeFeed.test.ts create mode 100644 contracts/test/v0.8/dev/ScrollValidator.test.ts diff --git a/contracts/foundry.toml b/contracts/foundry.toml index cf27c0f2a8b..003c836b1f3 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -37,7 +37,7 @@ test = 'src/v0.8/automation/test' optimizer_runs = 1000000 src = 'src/v0.8/l2ep' test = 'src/v0.8/l2ep/test' - +solc_version = '0.8.19' [profile.llo-feeds] optimizer_runs = 1000000 diff --git a/contracts/package.json b/contracts/package.json index 2604a12bea3..abbf722140c 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -43,6 +43,7 @@ "@nomiclabs/hardhat-etherscan": "^3.1.7", "@nomiclabs/hardhat-waffle": "2.0.6", "@openzeppelin/hardhat-upgrades": "1.28.0", + "@scroll-tech/contracts": "0.1.0", "@openzeppelin/test-helpers": "^0.5.16", "@typechain/ethers-v5": "^7.2.0", "@typechain/hardhat": "^7.0.0", diff --git a/contracts/pnpm-lock.yaml b/contracts/pnpm-lock.yaml index fbae71fb3d4..dffcb0a7c7c 100644 --- a/contracts/pnpm-lock.yaml +++ b/contracts/pnpm-lock.yaml @@ -55,6 +55,9 @@ devDependencies: '@openzeppelin/test-helpers': specifier: ^0.5.16 version: 0.5.16(bn.js@4.12.0) + '@scroll-tech/contracts': + specifier: 0.1.0 + version: 0.1.0 '@typechain/ethers-v5': specifier: ^7.2.0 version: 7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@5.2.2) @@ -1387,6 +1390,10 @@ packages: - supports-color dev: true + /@scroll-tech/contracts@0.1.0: + resolution: {integrity: sha512-aBbDOc3WB/WveZdpJYcrfvMYMz7ZTEiW8M9XMJLba8p9FAR5KGYB/cV+8+EUsq3MKt7C1BfR+WnXoTVdvwIY6w==} + dev: true + /@scure/base@1.1.1: resolution: {integrity: sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==} dev: true @@ -5861,7 +5868,7 @@ packages: heap: 0.2.6 level-sublevel: 6.6.4 levelup: 3.1.1 - lodash: 4.17.21 + lodash: 4.17.20 lru-cache: 5.1.1 merkle-patricia-tree: 3.0.0 patch-package: 6.2.2 @@ -7919,6 +7926,12 @@ packages: /minimalistic-crypto-utils@1.0.1: resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} + /minimatch@3.0.4: + resolution: {integrity: sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==} + dependencies: + brace-expansion: 1.1.11 + dev: true + /minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} dependencies: @@ -9232,7 +9245,7 @@ packages: resolution: {integrity: sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==} engines: {node: '>=0.10.0'} dependencies: - minimatch: 3.1.2 + minimatch: 3.0.4 dev: true /reduce-flatten@2.0.0: diff --git a/contracts/src/v0.8/l2ep/dev/interfaces/ScrollSequencerUptimeFeedInterface.sol b/contracts/src/v0.8/l2ep/dev/interfaces/ScrollSequencerUptimeFeedInterface.sol new file mode 100644 index 00000000000..f0f716d6f02 --- /dev/null +++ b/contracts/src/v0.8/l2ep/dev/interfaces/ScrollSequencerUptimeFeedInterface.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +interface ScrollSequencerUptimeFeedInterface { + function updateStatus(bool status, uint64 timestamp) external; +} diff --git a/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainForwarder.sol b/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainForwarder.sol new file mode 100644 index 00000000000..f18f7c3270b --- /dev/null +++ b/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainForwarder.sol @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {TypeAndVersionInterface} from "../../../interfaces/TypeAndVersionInterface.sol"; +import {ForwarderInterface} from "../interfaces/ForwarderInterface.sol"; + +import {CrossDomainForwarder} from "../CrossDomainForwarder.sol"; +import {CrossDomainOwnable} from "../CrossDomainOwnable.sol"; + +import {IScrollMessenger} from "@scroll-tech/contracts/libraries/IScrollMessenger.sol"; +import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; + +/// @title ScrollCrossDomainForwarder - L1 xDomain account representation +/// @notice L2 Contract which receives messages from a specific L1 address and transparently forwards them to the destination. +/// @dev Any other L2 contract which uses this contract's address as a privileged position, +/// can be considered to be owned by the `l1Owner` +contract ScrollCrossDomainForwarder is TypeAndVersionInterface, CrossDomainForwarder { + // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables + string public constant override typeAndVersion = "ScrollCrossDomainForwarder 1.0.0"; + + address internal immutable i_scrollCrossDomainMessenger; + + /// @param crossDomainMessengerAddr the xDomain bridge messenger (Scroll bridge L2) contract address + /// @param l1OwnerAddr the L1 owner address that will be allowed to call the forward fn + constructor(IScrollMessenger crossDomainMessengerAddr, address l1OwnerAddr) CrossDomainOwnable(l1OwnerAddr) { + // solhint-disable-next-line custom-errors + require(address(crossDomainMessengerAddr) != address(0), "Invalid xDomain Messenger address"); + i_scrollCrossDomainMessenger = address(crossDomainMessengerAddr); + } + + /// @dev forwarded only if L2 Messenger calls with `xDomainMessageSender` being the L1 owner address + /// @inheritdoc ForwarderInterface + function forward(address target, bytes memory data) external override onlyL1Owner { + Address.functionCall(target, data, "Forwarder call reverted"); + } + + /// @notice This is always the address of the Scroll Cross Domain Messenger contract + function crossDomainMessenger() external view returns (address) { + return address(i_scrollCrossDomainMessenger); + } + + /// @notice The call MUST come from the L1 owner (via cross-chain message.) Reverts otherwise. + modifier onlyL1Owner() override { + // solhint-disable-next-line custom-errors + require(msg.sender == i_scrollCrossDomainMessenger, "Sender is not the L2 messenger"); + // solhint-disable-next-line custom-errors + require( + IScrollMessenger(i_scrollCrossDomainMessenger).xDomainMessageSender() == l1Owner(), + "xDomain sender is not the L1 owner" + ); + _; + } + + /// @notice The call MUST come from the proposed L1 owner (via cross-chain message.) Reverts otherwise. + modifier onlyProposedL1Owner() override { + // solhint-disable-next-line custom-errors + require(msg.sender == i_scrollCrossDomainMessenger, "Sender is not the L2 messenger"); + // solhint-disable-next-line custom-errors + require( + IScrollMessenger(i_scrollCrossDomainMessenger).xDomainMessageSender() == s_l1PendingOwner, + "Must be proposed L1 owner" + ); + _; + } +} diff --git a/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainGovernor.sol b/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainGovernor.sol new file mode 100644 index 00000000000..00ef9219b26 --- /dev/null +++ b/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainGovernor.sol @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {TypeAndVersionInterface} from "../../../interfaces/TypeAndVersionInterface.sol"; +import {DelegateForwarderInterface} from "../interfaces/DelegateForwarderInterface.sol"; +// solhint-disable-next-line no-unused-import +import {ForwarderInterface} from "../interfaces/ForwarderInterface.sol"; + +import {CrossDomainForwarder} from "../CrossDomainForwarder.sol"; +import {CrossDomainOwnable} from "../CrossDomainOwnable.sol"; + +import {IScrollMessenger} from "@scroll-tech/contracts/libraries/IScrollMessenger.sol"; +import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; + +/// @title ScrollCrossDomainGovernor - L1 xDomain account representation (with delegatecall support) for Scroll +/// @notice L2 Contract which receives messages from a specific L1 address and transparently forwards them to the destination. +/// @dev Any other L2 contract which uses this contract's address as a privileged position, +/// can be considered to be simultaneously owned by the `l1Owner` and L2 `owner` +contract ScrollCrossDomainGovernor is DelegateForwarderInterface, TypeAndVersionInterface, CrossDomainForwarder { + // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables + string public constant override typeAndVersion = "ScrollCrossDomainGovernor 1.0.0"; + + address internal immutable i_scrollCrossDomainMessenger; + + /// @param crossDomainMessengerAddr the xDomain bridge messenger (Scroll bridge L2) contract address + /// @param l1OwnerAddr the L1 owner address that will be allowed to call the forward fn + constructor(IScrollMessenger crossDomainMessengerAddr, address l1OwnerAddr) CrossDomainOwnable(l1OwnerAddr) { + // solhint-disable-next-line custom-errors + require(address(crossDomainMessengerAddr) != address(0), "Invalid xDomain Messenger address"); + i_scrollCrossDomainMessenger = address(crossDomainMessengerAddr); + } + + /// @inheritdoc ForwarderInterface + /// @dev forwarded only if L2 Messenger calls with `msg.sender` being the L1 owner address, or called by the L2 owner + function forward(address target, bytes memory data) external override onlyLocalOrCrossDomainOwner { + Address.functionCall(target, data, "Governor call reverted"); + } + + /// @inheritdoc DelegateForwarderInterface + /// @dev forwarded only if L2 Messenger calls with `msg.sender` being the L1 owner address, or called by the L2 owner + function forwardDelegate(address target, bytes memory data) external override onlyLocalOrCrossDomainOwner { + Address.functionDelegateCall(target, data, "Governor delegatecall reverted"); + } + + /// @notice The address of the Scroll Cross Domain Messenger contract + function crossDomainMessenger() external view returns (address) { + return address(i_scrollCrossDomainMessenger); + } + + /// @notice The call MUST come from the L1 owner (via cross-chain message.) Reverts otherwise. + modifier onlyL1Owner() override { + // solhint-disable-next-line custom-errors + require(msg.sender == i_scrollCrossDomainMessenger, "Sender is not the L2 messenger"); + // solhint-disable-next-line custom-errors + require( + IScrollMessenger(i_scrollCrossDomainMessenger).xDomainMessageSender() == l1Owner(), + "xDomain sender is not the L1 owner" + ); + _; + } + + /// @notice The call MUST come from either the L1 owner (via cross-chain message) or the L2 owner. Reverts otherwise. + modifier onlyLocalOrCrossDomainOwner() { + // 1. The delegatecall MUST come from either the L1 owner (via cross-chain message) or the L2 owner + // solhint-disable-next-line custom-errors + require( + msg.sender == i_scrollCrossDomainMessenger || msg.sender == owner(), + "Sender is not the L2 messenger or owner" + ); + // 2. The L2 Messenger's caller MUST be the L1 Owner + if (msg.sender == i_scrollCrossDomainMessenger) { + // solhint-disable-next-line custom-errors + require( + IScrollMessenger(i_scrollCrossDomainMessenger).xDomainMessageSender() == l1Owner(), + "xDomain sender is not the L1 owner" + ); + } + _; + } + + /// @notice The call MUST come from the proposed L1 owner (via cross-chain message.) Reverts otherwise. + modifier onlyProposedL1Owner() override { + // solhint-disable-next-line custom-errors + require(msg.sender == i_scrollCrossDomainMessenger, "Sender is not the L2 messenger"); + // solhint-disable-next-line custom-errors + require( + IScrollMessenger(i_scrollCrossDomainMessenger).xDomainMessageSender() == s_l1PendingOwner, + "Must be proposed L1 owner" + ); + _; + } +} diff --git a/contracts/src/v0.8/l2ep/dev/scroll/ScrollSequencerUptimeFeed.sol b/contracts/src/v0.8/l2ep/dev/scroll/ScrollSequencerUptimeFeed.sol new file mode 100644 index 00000000000..22b5ed1e2b6 --- /dev/null +++ b/contracts/src/v0.8/l2ep/dev/scroll/ScrollSequencerUptimeFeed.sol @@ -0,0 +1,231 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ScrollSequencerUptimeFeedInterface} from "../interfaces/ScrollSequencerUptimeFeedInterface.sol"; +import {AggregatorInterface} from "../../../shared/interfaces/AggregatorInterface.sol"; +import {AggregatorV3Interface} from "../../../shared/interfaces/AggregatorV3Interface.sol"; +import {AggregatorV2V3Interface} from "../../../shared/interfaces/AggregatorV2V3Interface.sol"; +import {TypeAndVersionInterface} from "../../../interfaces/TypeAndVersionInterface.sol"; + +import {SimpleReadAccessController} from "../../../shared/access/SimpleReadAccessController.sol"; + +import {IL2ScrollMessenger} from "@scroll-tech/contracts/L2/IL2ScrollMessenger.sol"; + +/// @title ScrollSequencerUptimeFeed - L2 sequencer uptime status aggregator +/// @notice L2 contract that receives status updates, and records a new answer if the status changed +contract ScrollSequencerUptimeFeed is + AggregatorV2V3Interface, + ScrollSequencerUptimeFeedInterface, + TypeAndVersionInterface, + SimpleReadAccessController +{ + // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables + string public constant override typeAndVersion = "ScrollSequencerUptimeFeed 1.0.0"; + + /// @dev Round info (for uptime history) + struct Round { + bool status; + uint64 startedAt; + uint64 updatedAt; + } + + /// @dev Packed state struct to save sloads + struct FeedState { + uint80 latestRoundId; + bool latestStatus; + uint64 startedAt; + uint64 updatedAt; + } + + /// @notice Sender is not the L2 messenger + error InvalidSender(); + /// @notice Replacement for AggregatorV3Interface "No data present" + error NoDataPresent(); + + event L1SenderTransferred(address indexed from, address indexed to); + /// @dev Emitted when an `updateStatus` call is ignored due to unchanged status or stale timestamp + event UpdateIgnored(bool latestStatus, uint64 latestTimestamp, bool incomingStatus, uint64 incomingTimestamp); + /// @dev Emitted when a updateStatus is called without the status changing + event RoundUpdated(int256 status, uint64 updatedAt); + + // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables + uint8 public constant override decimals = 0; + // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables + string public constant override description = "L2 Sequencer Uptime Status Feed"; + // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables + uint256 public constant override version = 1; + + /// @dev L1 address + address private s_l1Sender; + /// @dev s_latestRoundId == 0 means this contract is uninitialized. + FeedState private s_feedState = FeedState({latestRoundId: 0, latestStatus: false, startedAt: 0, updatedAt: 0}); + mapping(uint80 roundId => Round round) private s_rounds; + + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + IL2ScrollMessenger private immutable s_l2CrossDomainMessenger; + + /// @param l1SenderAddress Address of the L1 contract that is permissioned to call this contract + /// @param l2CrossDomainMessengerAddr Address of the L2CrossDomainMessenger contract + /// @param initialStatus The initial status of the feed + constructor(address l1SenderAddress, address l2CrossDomainMessengerAddr, bool initialStatus) { + _setL1Sender(l1SenderAddress); + s_l2CrossDomainMessenger = IL2ScrollMessenger(l2CrossDomainMessengerAddr); + + // Initialise roundId == 1 as the first round + _recordRound(1, initialStatus, uint64(block.timestamp)); + } + + /// @notice Check if a roundId is valid in this current contract state + /// @dev Mainly used for AggregatorV2V3Interface functions + /// @param roundId Round ID to check + function _isValidRound(uint256 roundId) private view returns (bool) { + return roundId > 0 && roundId <= type(uint80).max && s_feedState.latestRoundId >= roundId; + } + + /// @return L1 sender address + function l1Sender() public view virtual returns (address) { + return s_l1Sender; + } + + /// @notice Set the allowed L1 sender for this contract to a new L1 sender + /// @dev Can be disabled by setting the L1 sender as `address(0)`. Accessible only by owner. + /// @param to new L1 sender that will be allowed to call `updateStatus` on this contract + function transferL1Sender(address to) external virtual onlyOwner { + _setL1Sender(to); + } + + /// @notice internal method that stores the L1 sender + function _setL1Sender(address to) private { + address from = s_l1Sender; + if (from != to) { + s_l1Sender = to; + emit L1SenderTransferred(from, to); + } + } + + /// @dev Returns an AggregatorV2V3Interface compatible answer from status flag + /// @param status The status flag to convert to an aggregator-compatible answer + function _getStatusAnswer(bool status) private pure returns (int256) { + return status ? int256(1) : int256(0); + } + + /// @notice Helper function to record a round and set the latest feed state. + /// @param roundId The round ID to record + /// @param status Sequencer status + /// @param timestamp The L1 block timestamp of status update + function _recordRound(uint80 roundId, bool status, uint64 timestamp) private { + s_feedState = FeedState(roundId, status, timestamp, uint64(block.timestamp)); + s_rounds[roundId] = Round(status, timestamp, uint64(block.timestamp)); + + emit NewRound(roundId, msg.sender, timestamp); + emit AnswerUpdated(_getStatusAnswer(status), roundId, timestamp); + } + + /// @notice Helper function to update when a round was last updated + /// @param roundId The round ID to update + /// @param status Sequencer status + function _updateRound(uint80 roundId, bool status) private { + s_feedState.updatedAt = uint64(block.timestamp); + s_rounds[roundId].updatedAt = uint64(block.timestamp); + emit RoundUpdated(_getStatusAnswer(status), uint64(block.timestamp)); + } + + /// @notice Record a new status and timestamp if it has changed since the last round. + /// @dev This function will revert if not called from `l1Sender` via the L1->L2 messenger. + /// + /// @param status Sequencer status + /// @param timestamp Block timestamp of status update + function updateStatus(bool status, uint64 timestamp) external override { + FeedState memory feedState = s_feedState; + + if ( + msg.sender != address(s_l2CrossDomainMessenger) || s_l2CrossDomainMessenger.xDomainMessageSender() != s_l1Sender + ) { + revert InvalidSender(); + } + + // Ignore if latest recorded timestamp is newer + if (feedState.startedAt > timestamp) { + emit UpdateIgnored(feedState.latestStatus, feedState.startedAt, status, timestamp); + return; + } + + if (feedState.latestStatus == status) { + _updateRound(feedState.latestRoundId, status); + } else { + feedState.latestRoundId += 1; + _recordRound(feedState.latestRoundId, status, timestamp); + } + } + + /// @inheritdoc AggregatorInterface + function latestAnswer() external view override checkAccess returns (int256) { + return _getStatusAnswer(s_feedState.latestStatus); + } + + /// @inheritdoc AggregatorInterface + function latestTimestamp() external view override checkAccess returns (uint256) { + return s_feedState.startedAt; + } + + /// @inheritdoc AggregatorInterface + function latestRound() external view override checkAccess returns (uint256) { + return s_feedState.latestRoundId; + } + + /// @inheritdoc AggregatorInterface + function getAnswer(uint256 roundId) external view override checkAccess returns (int256) { + if (!_isValidRound(roundId)) { + revert NoDataPresent(); + } + + return _getStatusAnswer(s_rounds[uint80(roundId)].status); + } + + /// @inheritdoc AggregatorInterface + function getTimestamp(uint256 roundId) external view override checkAccess returns (uint256) { + if (!_isValidRound(roundId)) { + revert NoDataPresent(); + } + + return s_rounds[uint80(roundId)].startedAt; + } + + /// @inheritdoc AggregatorV3Interface + function getRoundData( + uint80 _roundId + ) + public + view + override + checkAccess + returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) + { + if (!_isValidRound(_roundId)) { + revert NoDataPresent(); + } + + Round memory round = s_rounds[_roundId]; + + return (_roundId, _getStatusAnswer(round.status), uint256(round.startedAt), uint256(round.updatedAt), _roundId); + } + + /// @inheritdoc AggregatorV3Interface + function latestRoundData() + external + view + override + checkAccess + returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) + { + FeedState memory feedState = s_feedState; + + return ( + feedState.latestRoundId, + _getStatusAnswer(feedState.latestStatus), + feedState.startedAt, + feedState.updatedAt, + feedState.latestRoundId + ); + } +} diff --git a/contracts/src/v0.8/l2ep/dev/scroll/ScrollValidator.sol b/contracts/src/v0.8/l2ep/dev/scroll/ScrollValidator.sol new file mode 100644 index 00000000000..31a5f0764ef --- /dev/null +++ b/contracts/src/v0.8/l2ep/dev/scroll/ScrollValidator.sol @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {AggregatorValidatorInterface} from "../../../shared/interfaces/AggregatorValidatorInterface.sol"; +import {TypeAndVersionInterface} from "../../../interfaces/TypeAndVersionInterface.sol"; +import {ScrollSequencerUptimeFeedInterface} from "../interfaces/ScrollSequencerUptimeFeedInterface.sol"; + +import {SimpleWriteAccessController} from "../../../shared/access/SimpleWriteAccessController.sol"; + +import {IL1ScrollMessenger} from "@scroll-tech/contracts/L1/IL1ScrollMessenger.sol"; + +/// @title ScrollValidator - makes cross chain call to update the Sequencer Uptime Feed on L2 +contract ScrollValidator is TypeAndVersionInterface, AggregatorValidatorInterface, SimpleWriteAccessController { + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + address public immutable L1_CROSS_DOMAIN_MESSENGER_ADDRESS; + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + address public immutable L2_UPTIME_FEED_ADDR; + + // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables + string public constant override typeAndVersion = "ScrollValidator 1.0.0"; + int256 private constant ANSWER_SEQ_OFFLINE = 1; + uint32 private s_gasLimit; + + /// @notice emitted when gas cost to spend on L2 is updated + /// @param gasLimit updated gas cost + event GasLimitUpdated(uint32 gasLimit); + + /// @param l1CrossDomainMessengerAddress address the L1CrossDomainMessenger contract address + /// @param l2UptimeFeedAddr the address of the ScrollSequencerUptimeFeed contract address + /// @param gasLimit the gasLimit to use for sending a message from L1 to L2 + constructor(address l1CrossDomainMessengerAddress, address l2UptimeFeedAddr, uint32 gasLimit) { + // solhint-disable-next-line custom-errors + require(l1CrossDomainMessengerAddress != address(0), "Invalid xDomain Messenger address"); + // solhint-disable-next-line custom-errors + require(l2UptimeFeedAddr != address(0), "Invalid ScrollSequencerUptimeFeed contract address"); + L1_CROSS_DOMAIN_MESSENGER_ADDRESS = l1CrossDomainMessengerAddress; + L2_UPTIME_FEED_ADDR = l2UptimeFeedAddr; + s_gasLimit = gasLimit; + } + + /// @notice sets the new gas cost to spend when sending cross chain message + /// @param gasLimit the updated gas cost + function setGasLimit(uint32 gasLimit) external onlyOwner { + s_gasLimit = gasLimit; + emit GasLimitUpdated(gasLimit); + } + + /// @notice fetches the gas cost of sending a cross chain message + function getGasLimit() external view returns (uint32) { + return s_gasLimit; + } + + /// @notice validate method sends an xDomain L2 tx to update Uptime Feed contract on L2. + /// @dev A message is sent using the L1CrossDomainMessenger. This method is accessed controlled. + /// @param currentAnswer new aggregator answer - value of 1 considers the sequencer offline. + function validate( + uint256 /* previousRoundId */, + int256 /* previousAnswer */, + uint256 /* currentRoundId */, + int256 currentAnswer + ) external override checkAccess returns (bool) { + // Make the xDomain call + IL1ScrollMessenger(L1_CROSS_DOMAIN_MESSENGER_ADDRESS).sendMessage( + L2_UPTIME_FEED_ADDR, + 0, + abi.encodeWithSelector( + ScrollSequencerUptimeFeedInterface.updateStatus.selector, + currentAnswer == ANSWER_SEQ_OFFLINE, + uint64(block.timestamp) + ), + s_gasLimit + ); + + // return success + return true; + } +} diff --git a/contracts/src/v0.8/l2ep/test/mocks/MockScrollL1CrossDomainMessenger.sol b/contracts/src/v0.8/l2ep/test/mocks/MockScrollL1CrossDomainMessenger.sol new file mode 100644 index 00000000000..e63847d6557 --- /dev/null +++ b/contracts/src/v0.8/l2ep/test/mocks/MockScrollL1CrossDomainMessenger.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +import {IL1ScrollMessenger} from "@scroll-tech/contracts/L1/IL1ScrollMessenger.sol"; + +contract MockScrollL1CrossDomainMessenger is IL1ScrollMessenger { + uint256 private s_nonce; + + function xDomainMessageSender() public pure returns (address) { + return address(0); + } + + function sendMessage( + address _target, + uint256 _value, + bytes calldata _message, + uint256 _gasLimit + ) external payable override { + emit SentMessage(msg.sender, _target, _value, s_nonce, _gasLimit, _message); + s_nonce++; + } + + function sendMessage( + address _target, + uint256 _value, + bytes calldata _message, + uint256 _gasLimit, + address + ) external payable override { + emit SentMessage(msg.sender, _target, _value, s_nonce, _gasLimit, _message); + s_nonce++; + } + + function relayMessageWithProof( + address from, + address to, + uint256 value, + uint256 nonce, + bytes memory message, + L2MessageProof memory proof + ) external override {} + + function replayMessage( + address from, + address to, + uint256 value, + uint256 messageNonce, + bytes memory message, + uint32 newGasLimit, + address refundAddress + ) external payable override {} + + function dropMessage( + address from, + address to, + uint256 value, + uint256 messageNonce, + bytes memory message + ) external override {} +} diff --git a/contracts/src/v0.8/l2ep/test/mocks/MockScrollL2CrossDomainMessenger.sol b/contracts/src/v0.8/l2ep/test/mocks/MockScrollL2CrossDomainMessenger.sol new file mode 100644 index 00000000000..f63faa35179 --- /dev/null +++ b/contracts/src/v0.8/l2ep/test/mocks/MockScrollL2CrossDomainMessenger.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +import {IL2ScrollMessenger} from "@scroll-tech/contracts/L2/IL2ScrollMessenger.sol"; + +contract MockScrollL2CrossDomainMessenger is IL2ScrollMessenger { + uint256 private s_nonce; + address private s_sender; + + function xDomainMessageSender() public view returns (address) { + return s_sender; + } + + function sendMessage( + address _target, + uint256 _value, + bytes calldata _message, + uint256 _gasLimit + ) external payable override { + emit SentMessage(msg.sender, _target, _value, s_nonce, _gasLimit, _message); + s_nonce++; + } + + function sendMessage( + address _target, + uint256 _value, + bytes calldata _message, + uint256 _gasLimit, + address + ) external payable override { + emit SentMessage(msg.sender, _target, _value, s_nonce, _gasLimit, _message); + s_nonce++; + } + + function relayMessage( + address from, + address to, + uint256 value, + uint256 nonce, + bytes calldata message + ) external override {} + + /// Needed for testing + function setSender(address newSender) external { + s_sender = newSender; + } + + /// Needed for testing + receive() external payable {} +} diff --git a/contracts/src/v0.8/vendor/MockScrollCrossDomainMessenger.sol b/contracts/src/v0.8/vendor/MockScrollCrossDomainMessenger.sol new file mode 100644 index 00000000000..bb5390b945d --- /dev/null +++ b/contracts/src/v0.8/vendor/MockScrollCrossDomainMessenger.sol @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.16; + +import "./openzeppelin-solidity/v4.8.3/contracts/utils/Address.sol"; + +/// sourced from: https://github.com/scroll-tech/scroll/blob/develop/contracts/src/libraries/IScrollMessenger.sol +interface IScrollMessenger { + /// ********** + /// * Events * + /// ********** + + /// @notice Emitted when a cross domain message is sent. + /// @param sender The address of the sender who initiates the message. + /// @param target The address of target contract to call. + /// @param value The amount of value passed to the target contract. + /// @param messageNonce The nonce of the message. + /// @param gasLimit The optional gas limit passed to L1 or L2. + /// @param message The calldata passed to the target contract. + event SentMessage( + address indexed sender, + address indexed target, + uint256 value, + uint256 messageNonce, + uint256 gasLimit, + bytes message + ); + + /// @notice Emitted when a cross domain message is relayed successfully. + /// @param messageHash The hash of the message. + event RelayedMessage(bytes32 indexed messageHash); + + /// @notice Emitted when a cross domain message is failed to relay. + /// @param messageHash The hash of the message. + event FailedRelayedMessage(bytes32 indexed messageHash); + + /// ************************* + /// * Public View Functions * + /// ************************* + + /// @notice Return the sender of a cross domain message. + function xDomainMessageSender() external view returns (address); + + /// ***************************** + /// * Public Mutating Functions * + /// ***************************** + + /// @notice Send cross chain message from L1 to L2 or L2 to L1. + /// @param target The address of account who receive the message. + /// @param value The amount of ether passed when call target contract. + /// @param message The content of the message. + /// @param gasLimit Gas limit required to complete the message relay on corresponding chain. + function sendMessage(address target, uint256 value, bytes calldata message, uint256 gasLimit) external payable; + + /// @notice Send cross chain message from L1 to L2 or L2 to L1. + /// @param target The address of account who receive the message. + /// @param value The amount of ether passed when call target contract. + /// @param message The content of the message. + /// @param gasLimit Gas limit required to complete the message relay on corresponding chain. + /// @param refundAddress The address of account who will receive the refunded fee. + function sendMessage( + address target, + uint256 value, + bytes calldata message, + uint256 gasLimit, + address refundAddress + ) external payable; +} + +contract MockScrollCrossDomainMessenger is IScrollMessenger { + address internal mockMessageSender; + + constructor(address sender) { + mockMessageSender = sender; + } + + function xDomainMessageSender() external view override returns (address) { + return mockMessageSender; + } + + function _setMockMessageSender(address sender) external { + mockMessageSender = sender; + } + + /// ***************************** + /// * Public Mutating Functions * + /// ***************************** + + /// @notice Send cross chain message from L1 to L2 or L2 to L1. + /// @param _target The address of account who receive the message. + /// @param _message The content of the message. + function sendMessage(address _target, uint256, bytes calldata _message, uint256) external payable override { + Address.functionCall(_target, _message, "sendMessage reverted"); + } + + /// @notice Send cross chain message from L1 to L2 or L2 to L1. + /// @param _target The address of account who receive the message. + /// @param _message The content of the message. + function sendMessage(address _target, uint256, bytes calldata _message, uint256, address) external payable override { + Address.functionCall(_target, _message, "sendMessage reverted"); + } +} diff --git a/contracts/test/v0.8/dev/ScrollCrossDomainForwarder.test.ts b/contracts/test/v0.8/dev/ScrollCrossDomainForwarder.test.ts new file mode 100644 index 00000000000..923d41326ae --- /dev/null +++ b/contracts/test/v0.8/dev/ScrollCrossDomainForwarder.test.ts @@ -0,0 +1,259 @@ +import { ethers } from 'hardhat' +import { assert, expect } from 'chai' +import { Contract, ContractFactory } from 'ethers' +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' +import { publicAbi } from '../../test-helpers/helpers' + +let owner: SignerWithAddress +let stranger: SignerWithAddress +let l1OwnerAddress: string +let newL1OwnerAddress: string +let forwarderFactory: ContractFactory +let greeterFactory: ContractFactory +let crossDomainMessengerFactory: ContractFactory +let crossDomainMessenger: Contract +let forwarder: Contract +let greeter: Contract + +before(async () => { + const accounts = await ethers.getSigners() + owner = accounts[0] + stranger = accounts[1] + + // forwarder config + l1OwnerAddress = owner.address + newL1OwnerAddress = stranger.address + + // Contract factories + forwarderFactory = await ethers.getContractFactory( + 'src/v0.8/l2ep/dev/scroll/ScrollCrossDomainForwarder.sol:ScrollCrossDomainForwarder', + owner, + ) + greeterFactory = await ethers.getContractFactory( + 'src/v0.8/tests/Greeter.sol:Greeter', + owner, + ) + crossDomainMessengerFactory = await ethers.getContractFactory( + 'src/v0.8/vendor/MockScrollCrossDomainMessenger.sol:MockScrollCrossDomainMessenger', + ) +}) + +describe('ScrollCrossDomainForwarder', () => { + beforeEach(async () => { + crossDomainMessenger = + await crossDomainMessengerFactory.deploy(l1OwnerAddress) + forwarder = await forwarderFactory.deploy( + crossDomainMessenger.address, + l1OwnerAddress, + ) + greeter = await greeterFactory.deploy(forwarder.address) + }) + + it('has a limited public interface [ @skip-coverage ]', async () => { + publicAbi(forwarder, [ + 'typeAndVersion', + 'crossDomainMessenger', + 'forward', + 'l1Owner', + 'transferL1Ownership', + 'acceptL1Ownership', + // ConfirmedOwner methods: + 'owner', + 'transferOwnership', + 'acceptOwnership', + ]) + }) + + describe('#constructor', () => { + it('should set the owner correctly', async () => { + const response = await forwarder.owner() + assert.equal(response, owner.address) + }) + + it('should set the l1Owner correctly', async () => { + const response = await forwarder.l1Owner() + assert.equal(response, l1OwnerAddress) + }) + + it('should set the crossdomain messenger correctly', async () => { + const response = await forwarder.crossDomainMessenger() + assert.equal(response, crossDomainMessenger.address) + }) + + it('should set the typeAndVersion correctly', async () => { + const response = await forwarder.typeAndVersion() + assert.equal(response, 'ScrollCrossDomainForwarder 1.0.0') + }) + }) + + describe('#forward', () => { + it('should not be callable by unknown address', async () => { + await expect( + forwarder.connect(stranger).forward(greeter.address, '0x'), + ).to.be.revertedWith('Sender is not the L2 messenger') + }) + + it('should be callable by crossdomain messenger address / L1 owner', async () => { + const newGreeting = 'hello' + const setGreetingData = greeterFactory.interface.encodeFunctionData( + 'setGreeting', + [newGreeting], + ) + const forwardData = forwarderFactory.interface.encodeFunctionData( + 'forward', + [greeter.address, setGreetingData], + ) + await crossDomainMessenger // Simulate cross-chain message + .connect(stranger) + ['sendMessage(address,uint256,bytes,uint256)']( + forwarder.address, // target + 0, // value + forwardData, // message + 0, // gasLimit + ) + + const updatedGreeting = await greeter.greeting() + assert.equal(updatedGreeting, newGreeting) + }) + + it('should revert when contract call reverts', async () => { + const setGreetingData = greeterFactory.interface.encodeFunctionData( + 'setGreeting', + [''], + ) + const forwardData = forwarderFactory.interface.encodeFunctionData( + 'forward', + [greeter.address, setGreetingData], + ) + await expect( + crossDomainMessenger // Simulate cross-chain message + .connect(stranger) + ['sendMessage(address,uint256,bytes,uint256)']( + forwarder.address, // target + 0, // value + forwardData, // message + 0, // gasLimit + ), + ).to.be.revertedWith('Invalid greeting length') + }) + }) + + describe('#transferL1Ownership', () => { + it('should not be callable by non-owners', async () => { + await expect( + forwarder.connect(stranger).transferL1Ownership(stranger.address), + ).to.be.revertedWith('Sender is not the L2 messenger') + }) + + it('should not be callable by L2 owner', async () => { + const forwarderOwner = await forwarder.owner() + assert.equal(forwarderOwner, owner.address) + + await expect( + forwarder.connect(owner).transferL1Ownership(stranger.address), + ).to.be.revertedWith('Sender is not the L2 messenger') + }) + + it('should be callable by current L1 owner', async () => { + const currentL1Owner = await forwarder.l1Owner() + const forwardData = forwarderFactory.interface.encodeFunctionData( + 'transferL1Ownership', + [newL1OwnerAddress], + ) + + await expect( + crossDomainMessenger // Simulate cross-chain message + .connect(stranger) + ['sendMessage(address,uint256,bytes,uint256)']( + forwarder.address, // target + 0, // value + forwardData, // message + 0, // gasLimit + ), + ) + .to.emit(forwarder, 'L1OwnershipTransferRequested') + .withArgs(currentL1Owner, newL1OwnerAddress) + }) + + it('should be callable by current L1 owner to zero address', async () => { + const currentL1Owner = await forwarder.l1Owner() + const forwardData = forwarderFactory.interface.encodeFunctionData( + 'transferL1Ownership', + [ethers.constants.AddressZero], + ) + + await expect( + crossDomainMessenger // Simulate cross-chain message + .connect(stranger) + ['sendMessage(address,uint256,bytes,uint256)']( + forwarder.address, // target + 0, // value + forwardData, // message + 0, // gasLimit + ), + ) + .to.emit(forwarder, 'L1OwnershipTransferRequested') + .withArgs(currentL1Owner, ethers.constants.AddressZero) + }) + }) + + describe('#acceptL1Ownership', () => { + it('should not be callable by non pending-owners', async () => { + const forwardData = forwarderFactory.interface.encodeFunctionData( + 'acceptL1Ownership', + [], + ) + await expect( + crossDomainMessenger // Simulate cross-chain message + .connect(stranger) + ['sendMessage(address,uint256,bytes,uint256)']( + forwarder.address, // target + 0, // value + forwardData, // message + 0, // gasLimit + ), + ).to.be.revertedWith('Must be proposed L1 owner') + }) + + it('should be callable by pending L1 owner', async () => { + const currentL1Owner = await forwarder.l1Owner() + + // Transfer ownership + const forwardTransferData = forwarderFactory.interface.encodeFunctionData( + 'transferL1Ownership', + [newL1OwnerAddress], + ) + await crossDomainMessenger // Simulate cross-chain message + .connect(stranger) + ['sendMessage(address,uint256,bytes,uint256)']( + forwarder.address, // target + 0, // value + forwardTransferData, // message + 0, // gasLimit + ) + + const forwardAcceptData = forwarderFactory.interface.encodeFunctionData( + 'acceptL1Ownership', + [], + ) + // Simulate cross-chain message from another sender + await crossDomainMessenger._setMockMessageSender(newL1OwnerAddress) + + await expect( + crossDomainMessenger // Simulate cross-chain message + .connect(stranger) + ['sendMessage(address,uint256,bytes,uint256)']( + forwarder.address, // target + 0, // value + forwardAcceptData, // message + 0, // gasLimit + ), + ) + .to.emit(forwarder, 'L1OwnershipTransferred') + .withArgs(currentL1Owner, newL1OwnerAddress) + + const updatedL1Owner = await forwarder.l1Owner() + assert.equal(updatedL1Owner, newL1OwnerAddress) + }) + }) +}) diff --git a/contracts/test/v0.8/dev/ScrollCrossDomainGovernor.test.ts b/contracts/test/v0.8/dev/ScrollCrossDomainGovernor.test.ts new file mode 100644 index 00000000000..adb78c26248 --- /dev/null +++ b/contracts/test/v0.8/dev/ScrollCrossDomainGovernor.test.ts @@ -0,0 +1,459 @@ +import { ethers } from 'hardhat' +import { assert, expect } from 'chai' +import etherslib, { Contract, ContractFactory } from 'ethers' +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' +import { publicAbi, stripHexPrefix } from '../../test-helpers/helpers' + +let owner: SignerWithAddress +let stranger: SignerWithAddress +let l1OwnerAddress: string +let newL1OwnerAddress: string +let governorFactory: ContractFactory +let greeterFactory: ContractFactory +let multisendFactory: ContractFactory +let crossDomainMessengerFactory: ContractFactory +let crossDomainMessenger: Contract +let governor: Contract +let greeter: Contract +let multisend: Contract + +before(async () => { + const accounts = await ethers.getSigners() + owner = accounts[0] + stranger = accounts[1] + + // governor config + l1OwnerAddress = owner.address + newL1OwnerAddress = stranger.address + + // Contract factories + governorFactory = await ethers.getContractFactory( + 'src/v0.8/l2ep/dev/scroll/ScrollCrossDomainGovernor.sol:ScrollCrossDomainGovernor', + owner, + ) + greeterFactory = await ethers.getContractFactory( + 'src/v0.8/tests/Greeter.sol:Greeter', + owner, + ) + multisendFactory = await ethers.getContractFactory( + 'src/v0.8/vendor/MultiSend.sol:MultiSend', + owner, + ) + crossDomainMessengerFactory = await ethers.getContractFactory( + 'src/v0.8/vendor/MockScrollCrossDomainMessenger.sol:MockScrollCrossDomainMessenger', + ) +}) + +describe('ScrollCrossDomainGovernor', () => { + beforeEach(async () => { + crossDomainMessenger = + await crossDomainMessengerFactory.deploy(l1OwnerAddress) + governor = await governorFactory.deploy( + crossDomainMessenger.address, + l1OwnerAddress, + ) + greeter = await greeterFactory.deploy(governor.address) + multisend = await multisendFactory.deploy() + }) + + it('has a limited public interface [ @skip-coverage ]', async () => { + publicAbi(governor, [ + 'typeAndVersion', + 'crossDomainMessenger', + 'forward', + 'forwardDelegate', + 'l1Owner', + 'transferL1Ownership', + 'acceptL1Ownership', + // ConfirmedOwner methods: + 'owner', + 'transferOwnership', + 'acceptOwnership', + ]) + }) + + describe('#constructor', () => { + it('should set the owner correctly', async () => { + const response = await governor.owner() + assert.equal(response, owner.address) + }) + + it('should set the l1Owner correctly', async () => { + const response = await governor.l1Owner() + assert.equal(response, l1OwnerAddress) + }) + + it('should set the crossdomain messenger correctly', async () => { + const response = await governor.crossDomainMessenger() + assert.equal(response, crossDomainMessenger.address) + }) + + it('should set the typeAndVersion correctly', async () => { + const response = await governor.typeAndVersion() + assert.equal(response, 'ScrollCrossDomainGovernor 1.0.0') + }) + }) + + describe('#forward', () => { + it('should not be callable by unknown address', async () => { + await expect( + governor.connect(stranger).forward(greeter.address, '0x'), + ).to.be.revertedWith('Sender is not the L2 messenger') + }) + + it('should be callable by crossdomain messenger address / L1 owner', async () => { + const newGreeting = 'hello' + const setGreetingData = greeterFactory.interface.encodeFunctionData( + 'setGreeting', + [newGreeting], + ) + const forwardData = governorFactory.interface.encodeFunctionData( + 'forward', + [greeter.address, setGreetingData], + ) + await crossDomainMessenger // Simulate cross-chain message + .connect(stranger) + ['sendMessage(address,uint256,bytes,uint256)']( + governor.address, // target + 0, // value + forwardData, // message + 0, // gasLimit + ) + + const updatedGreeting = await greeter.greeting() + assert.equal(updatedGreeting, newGreeting) + }) + + it('should be callable by L2 owner', async () => { + const newGreeting = 'hello' + const setGreetingData = greeterFactory.interface.encodeFunctionData( + 'setGreeting', + [newGreeting], + ) + await governor.connect(owner).forward(greeter.address, setGreetingData) + + const updatedGreeting = await greeter.greeting() + assert.equal(updatedGreeting, newGreeting) + }) + + it('should revert when contract call reverts', async () => { + const setGreetingData = greeterFactory.interface.encodeFunctionData( + 'setGreeting', + [''], + ) + const forwardData = governorFactory.interface.encodeFunctionData( + 'forward', + [greeter.address, setGreetingData], + ) + await expect( + crossDomainMessenger // Simulate cross-chain message + .connect(stranger) + ['sendMessage(address,uint256,bytes,uint256)']( + governor.address, // target + 0, // value + forwardData, // message + 0, // gasLimit + ), + ).to.be.revertedWith('Invalid greeting length') + }) + }) + + describe('#forwardDelegate', () => { + it('should not be callable by unknown address', async () => { + await expect( + governor.connect(stranger).forwardDelegate(multisend.address, '0x'), + ).to.be.revertedWith('Sender is not the L2 messenger') + }) + + it('should be callable by crossdomain messenger address / L1 owner', async () => { + const calls = [ + { + to: greeter.address, + data: greeterFactory.interface.encodeFunctionData('setGreeting', [ + 'foo', + ]), + value: 0, + }, + { + to: greeter.address, + data: greeterFactory.interface.encodeFunctionData('setGreeting', [ + 'bar', + ]), + value: 0, + }, + ] + const multisendData = encodeMultisendData(multisend.interface, calls) + const forwardData = governorFactory.interface.encodeFunctionData( + 'forwardDelegate', + [multisend.address, multisendData], + ) + + await crossDomainMessenger // Simulate cross-chain message + .connect(stranger) + ['sendMessage(address,uint256,bytes,uint256)']( + governor.address, // target + 0, // value + forwardData, // message + 0, // gasLimit + ) + + const updatedGreeting = await greeter.greeting() + assert.equal(updatedGreeting, 'bar') + }) + + it('should be callable by L2 owner', async () => { + const calls = [ + { + to: greeter.address, + data: greeterFactory.interface.encodeFunctionData('setGreeting', [ + 'foo', + ]), + value: 0, + }, + { + to: greeter.address, + data: greeterFactory.interface.encodeFunctionData('setGreeting', [ + 'bar', + ]), + value: 0, + }, + ] + const multisendData = encodeMultisendData(multisend.interface, calls) + await governor + .connect(owner) + .forwardDelegate(multisend.address, multisendData) + + const updatedGreeting = await greeter.greeting() + assert.equal(updatedGreeting, 'bar') + }) + + it('should revert batch when one call fails', async () => { + const calls = [ + { + to: greeter.address, + data: greeterFactory.interface.encodeFunctionData('setGreeting', [ + 'foo', + ]), + value: 0, + }, + { + to: greeter.address, + data: greeterFactory.interface.encodeFunctionData('setGreeting', [ + '', // should revert + ]), + value: 0, + }, + ] + const multisendData = encodeMultisendData(multisend.interface, calls) + const forwardData = governorFactory.interface.encodeFunctionData( + 'forwardDelegate', + [multisend.address, multisendData], + ) + + await expect( + crossDomainMessenger // Simulate cross-chain message + .connect(stranger) + ['sendMessage(address,uint256,bytes,uint256)']( + governor.address, // target + 0, // value + forwardData, // message + 0, // gasLimit + ), + ).to.be.revertedWith('Governor delegatecall reverted') + + const greeting = await greeter.greeting() + assert.equal(greeting, '') // Unchanged + }) + + it('should bubble up revert when contract call reverts', async () => { + const triggerRevertData = + greeterFactory.interface.encodeFunctionData('triggerRevert') + const forwardData = governorFactory.interface.encodeFunctionData( + 'forwardDelegate', + [greeter.address, triggerRevertData], + ) + + await expect( + crossDomainMessenger // Simulate cross-chain message + .connect(stranger) + ['sendMessage(address,uint256,bytes,uint256)']( + governor.address, // target + 0, // value + forwardData, // message + 0, // gasLimit + ), + ).to.be.revertedWith('Greeter: revert triggered') + }) + }) + + describe('#transferL1Ownership', () => { + it('should not be callable by non-owners', async () => { + await expect( + governor.connect(stranger).transferL1Ownership(stranger.address), + ).to.be.revertedWith('Sender is not the L2 messenger') + }) + + it('should not be callable by L2 owner', async () => { + const governorOwner = await governor.owner() + assert.equal(governorOwner, owner.address) + + await expect( + governor.connect(owner).transferL1Ownership(stranger.address), + ).to.be.revertedWith('Sender is not the L2 messenger') + }) + + it('should be callable by current L1 owner', async () => { + const currentL1Owner = await governor.l1Owner() + const forwardData = governorFactory.interface.encodeFunctionData( + 'transferL1Ownership', + [newL1OwnerAddress], + ) + + await expect( + crossDomainMessenger // Simulate cross-chain message + .connect(stranger) + ['sendMessage(address,uint256,bytes,uint256)']( + governor.address, // target + 0, // value + forwardData, // message + 0, // gasLimit + ), + ) + .to.emit(governor, 'L1OwnershipTransferRequested') + .withArgs(currentL1Owner, newL1OwnerAddress) + }) + + it('should be callable by current L1 owner to zero address', async () => { + const currentL1Owner = await governor.l1Owner() + const forwardData = governorFactory.interface.encodeFunctionData( + 'transferL1Ownership', + [ethers.constants.AddressZero], + ) + + await expect( + crossDomainMessenger // Simulate cross-chain message + .connect(stranger) + ['sendMessage(address,uint256,bytes,uint256)']( + governor.address, // target + 0, // value + forwardData, // message + 0, // gasLimit + ), + ) + .to.emit(governor, 'L1OwnershipTransferRequested') + .withArgs(currentL1Owner, ethers.constants.AddressZero) + }) + }) + + describe('#acceptL1Ownership', () => { + it('should not be callable by non pending-owners', async () => { + const forwardData = governorFactory.interface.encodeFunctionData( + 'acceptL1Ownership', + [], + ) + await expect( + crossDomainMessenger // Simulate cross-chain message + .connect(stranger) + ['sendMessage(address,uint256,bytes,uint256)']( + governor.address, // target + 0, // value + forwardData, // message + 0, // gasLimit + ), + ).to.be.revertedWith('Must be proposed L1 owner') + }) + + it('should be callable by pending L1 owner', async () => { + const currentL1Owner = await governor.l1Owner() + + // Transfer ownership + const forwardTransferData = governorFactory.interface.encodeFunctionData( + 'transferL1Ownership', + [newL1OwnerAddress], + ) + await crossDomainMessenger // Simulate cross-chain message + .connect(stranger) + ['sendMessage(address,uint256,bytes,uint256)']( + governor.address, // target + 0, // value + forwardTransferData, // message + 0, // gasLimit + ) + + const forwardAcceptData = governorFactory.interface.encodeFunctionData( + 'acceptL1Ownership', + [], + ) + // Simulate cross-chain message from another sender + await crossDomainMessenger._setMockMessageSender(newL1OwnerAddress) + + await expect( + crossDomainMessenger // Simulate cross-chain message + .connect(stranger) + ['sendMessage(address,uint256,bytes,uint256)']( + governor.address, // target + 0, // value + forwardAcceptData, // message + 0, // gasLimit + ), + ) + .to.emit(governor, 'L1OwnershipTransferred') + .withArgs(currentL1Owner, newL1OwnerAddress) + + const updatedL1Owner = await governor.l1Owner() + assert.equal(updatedL1Owner, newL1OwnerAddress) + }) + }) +}) + +// Multisend contract helpers + +/** + * Encodes an underlying transaction for the Multisend contract + * + * @param operation 0 for CALL, 1 for DELEGATECALL + * @param to tx target address + * @param value tx value + * @param data tx data + */ +export function encodeTxData( + operation: number, + to: string, + value: number, + data: string, +): string { + const dataBuffer = Buffer.from(stripHexPrefix(data), 'hex') + const types = ['uint8', 'address', 'uint256', 'uint256', 'bytes'] + const values = [operation, to, value, dataBuffer.length, dataBuffer] + const encoded = ethers.utils.solidityPack(types, values) + return stripHexPrefix(encoded) +} + +/** + * Encodes a Multisend call + * + * @param MultisendInterface Ethers Interface object of the Multisend contract + * @param transactions one or more transactions to include in the Multisend call + * @param to tx target address + * @param value tx value + * @param data tx data + */ +export function encodeMultisendData( + MultisendInterface: etherslib.utils.Interface, + transactions: { to: string; value: number; data: string }[], +): string { + let nestedTransactionData = '0x' + for (const transaction of transactions) { + nestedTransactionData += encodeTxData( + 0, + transaction.to, + transaction.value, + transaction.data, + ) + } + const encodedMultisendFnData = MultisendInterface.encodeFunctionData( + 'multiSend', + [nestedTransactionData], + ) + return encodedMultisendFnData +} diff --git a/contracts/test/v0.8/dev/ScrollSequencerUptimeFeed.test.ts b/contracts/test/v0.8/dev/ScrollSequencerUptimeFeed.test.ts new file mode 100644 index 00000000000..b294032e73d --- /dev/null +++ b/contracts/test/v0.8/dev/ScrollSequencerUptimeFeed.test.ts @@ -0,0 +1,426 @@ +import { ethers, network } from 'hardhat' +import { BigNumber, Contract } from 'ethers' +import { expect } from 'chai' +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' + +describe('ScrollSequencerUptimeFeed', () => { + let l2CrossDomainMessenger: Contract + let scrollUptimeFeed: Contract + let uptimeFeedConsumer: Contract + let deployer: SignerWithAddress + let l1Owner: SignerWithAddress + let l2Messenger: SignerWithAddress + let dummy: SignerWithAddress + const gasUsedDeviation = 100 + const initialStatus = 0 + + before(async () => { + const accounts = await ethers.getSigners() + deployer = accounts[0] + l1Owner = accounts[1] + dummy = accounts[3] + + const l2CrossDomainMessengerFactory = await ethers.getContractFactory( + 'src/v0.8/l2ep/test/mocks/MockScrollL2CrossDomainMessenger.sol:MockScrollL2CrossDomainMessenger', + deployer, + ) + + l2CrossDomainMessenger = await l2CrossDomainMessengerFactory.deploy() + + // Pretend we're on L2 + await network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [l2CrossDomainMessenger.address], + }) + l2Messenger = await ethers.getSigner(l2CrossDomainMessenger.address) + // Credit the L2 messenger with some ETH + await dummy.sendTransaction({ + to: l2Messenger.address, + value: ethers.utils.parseEther('10'), + }) + }) + + beforeEach(async () => { + const scrollSequencerStatusRecorderFactory = + await ethers.getContractFactory( + 'src/v0.8/l2ep/dev/scroll/ScrollSequencerUptimeFeed.sol:ScrollSequencerUptimeFeed', + deployer, + ) + scrollUptimeFeed = await scrollSequencerStatusRecorderFactory.deploy( + l1Owner.address, + l2CrossDomainMessenger.address, + initialStatus, + ) + + // Set mock sender in mock L2 messenger contract + await l2CrossDomainMessenger.setSender(l1Owner.address) + + // Mock consumer + const statusFeedConsumerFactory = await ethers.getContractFactory( + 'src/v0.8/tests/FeedConsumer.sol:FeedConsumer', + deployer, + ) + uptimeFeedConsumer = await statusFeedConsumerFactory.deploy( + scrollUptimeFeed.address, + ) + }) + + describe('constructor', () => { + it('should have been deployed with the correct initial state', async () => { + const l1Sender = await scrollUptimeFeed.l1Sender() + expect(l1Sender).to.equal(l1Owner.address) + const { roundId, answer } = await scrollUptimeFeed.latestRoundData() + expect(roundId).to.equal(1) + expect(answer).to.equal(initialStatus) + }) + }) + + describe('#updateStatus', () => { + it('should revert if called by an address that is not the L2 Cross Domain Messenger', async () => { + const timestamp = await scrollUptimeFeed.latestTimestamp() + expect( + scrollUptimeFeed.connect(dummy).updateStatus(true, timestamp), + ).to.be.revertedWith('InvalidSender') + }) + + it('should revert if called by an address that is not the L2 Cross Domain Messenger and is not the L1 sender', async () => { + const timestamp = await scrollUptimeFeed.latestTimestamp() + await l2CrossDomainMessenger.setSender(dummy.address) + expect( + scrollUptimeFeed.connect(dummy).updateStatus(true, timestamp), + ).to.be.revertedWith('InvalidSender') + }) + + it(`should update status when status has not changed and incoming timestamp is the same as latest`, async () => { + const timestamp = await scrollUptimeFeed.latestTimestamp() + let tx = await scrollUptimeFeed + .connect(l2Messenger) + .updateStatus(true, timestamp) + await expect(tx) + .to.emit(scrollUptimeFeed, 'AnswerUpdated') + .withArgs(1, 2 /** roundId */, timestamp) + expect(await scrollUptimeFeed.latestAnswer()).to.equal(1) + + const latestRoundBeforeUpdate = await scrollUptimeFeed.latestRoundData() + + tx = await scrollUptimeFeed + .connect(l2Messenger) + .updateStatus(true, timestamp.add(200)) + + // Submit another status update with the same status + const latestBlock = await ethers.provider.getBlock('latest') + + await expect(tx) + .to.emit(scrollUptimeFeed, 'RoundUpdated') + .withArgs(1, latestBlock.timestamp) + expect(await scrollUptimeFeed.latestAnswer()).to.equal(1) + expect(await scrollUptimeFeed.latestTimestamp()).to.equal(timestamp) + + // Verify that latest round has been properly updated + const latestRoundDataAfterUpdate = + await scrollUptimeFeed.latestRoundData() + expect(latestRoundDataAfterUpdate.roundId).to.equal( + latestRoundBeforeUpdate.roundId, + ) + expect(latestRoundDataAfterUpdate.answer).to.equal( + latestRoundBeforeUpdate.answer, + ) + expect(latestRoundDataAfterUpdate.startedAt).to.equal( + latestRoundBeforeUpdate.startedAt, + ) + expect(latestRoundDataAfterUpdate.answeredInRound).to.equal( + latestRoundBeforeUpdate.answeredInRound, + ) + expect(latestRoundDataAfterUpdate.updatedAt).to.equal( + latestBlock.timestamp, + ) + }) + + it(`should update status when status has changed and incoming timestamp is newer than the latest`, async () => { + let timestamp = await scrollUptimeFeed.latestTimestamp() + let tx = await scrollUptimeFeed + .connect(l2Messenger) + .updateStatus(true, timestamp) + await expect(tx) + .to.emit(scrollUptimeFeed, 'AnswerUpdated') + .withArgs(1, 2 /** roundId */, timestamp) + expect(await scrollUptimeFeed.latestAnswer()).to.equal(1) + + // Submit another status update, different status, newer timestamp should update + timestamp = timestamp.add(2000) + tx = await scrollUptimeFeed + .connect(l2Messenger) + .updateStatus(false, timestamp) + await expect(tx) + .to.emit(scrollUptimeFeed, 'AnswerUpdated') + .withArgs(0, 3 /** roundId */, timestamp) + expect(await scrollUptimeFeed.latestAnswer()).to.equal(0) + expect(await scrollUptimeFeed.latestTimestamp()).to.equal(timestamp) + }) + + it(`should update status when status has changed and incoming timestamp is the same as latest`, async () => { + const timestamp = await scrollUptimeFeed.latestTimestamp() + let tx = await scrollUptimeFeed + .connect(l2Messenger) + .updateStatus(true, timestamp) + await expect(tx) + .to.emit(scrollUptimeFeed, 'AnswerUpdated') + .withArgs(1, 2 /** roundId */, timestamp) + expect(await scrollUptimeFeed.latestAnswer()).to.equal(1) + + // Submit another status update, different status, same timestamp should update + tx = await scrollUptimeFeed + .connect(l2Messenger) + .updateStatus(false, timestamp) + await expect(tx) + .to.emit(scrollUptimeFeed, 'AnswerUpdated') + .withArgs(0, 3 /** roundId */, timestamp) + expect(await scrollUptimeFeed.latestAnswer()).to.equal(0) + expect(await scrollUptimeFeed.latestTimestamp()).to.equal(timestamp) + }) + + it('should ignore out-of-order updates', async () => { + const timestamp = (await scrollUptimeFeed.latestTimestamp()).add(10_000) + // Update status + let tx = await scrollUptimeFeed + .connect(l2Messenger) + .updateStatus(true, timestamp) + await expect(tx) + .to.emit(scrollUptimeFeed, 'AnswerUpdated') + .withArgs(1, 2 /** roundId */, timestamp) + expect(await scrollUptimeFeed.latestAnswer()).to.equal(1) + + // Update with different status, but stale timestamp, should be ignored + const staleTimestamp = timestamp.sub(1000) + tx = await scrollUptimeFeed + .connect(l2Messenger) + .updateStatus(false, staleTimestamp) + await expect(tx) + .to.not.emit(scrollUptimeFeed, 'AnswerUpdated') + .withArgs(1, 2 /** roundId */, timestamp) + await expect(tx).to.emit(scrollUptimeFeed, 'UpdateIgnored') + }) + }) + + describe('AggregatorV3Interface', () => { + it('should return valid answer from getRoundData and latestRoundData', async () => { + let [roundId, answer, startedAt, updatedAt, answeredInRound] = + await scrollUptimeFeed.latestRoundData() + expect(roundId).to.equal(1) + expect(answer).to.equal(0) + expect(answeredInRound).to.equal(roundId) + expect(startedAt).to.equal(updatedAt) + + // Submit status update with different status and newer timestamp, should update + const timestamp = (startedAt as BigNumber).add(1000) + await scrollUptimeFeed.connect(l2Messenger).updateStatus(true, timestamp) + ;[roundId, answer, startedAt, updatedAt, answeredInRound] = + await scrollUptimeFeed.getRoundData(2) + expect(roundId).to.equal(2) + expect(answer).to.equal(1) + expect(answeredInRound).to.equal(roundId) + expect(startedAt).to.equal(timestamp) + expect(updatedAt.lte(startedAt)).to.be.true + + // Check that last round is still returning the correct data + ;[roundId, answer, startedAt, updatedAt, answeredInRound] = + await scrollUptimeFeed.getRoundData(1) + expect(roundId).to.equal(1) + expect(answer).to.equal(0) + expect(answeredInRound).to.equal(roundId) + expect(startedAt).to.equal(updatedAt) + + // Assert latestRoundData corresponds to latest round id + expect(await scrollUptimeFeed.getRoundData(2)).to.deep.equal( + await scrollUptimeFeed.latestRoundData(), + ) + }) + + it('should revert from #getRoundData when round does not yet exist (future roundId)', async () => { + expect(scrollUptimeFeed.getRoundData(2)).to.be.revertedWith( + 'NoDataPresent()', + ) + }) + + it('should revert from #getAnswer when round does not yet exist (future roundId)', async () => { + expect(scrollUptimeFeed.getAnswer(2)).to.be.revertedWith( + 'NoDataPresent()', + ) + }) + + it('should revert from #getTimestamp when round does not yet exist (future roundId)', async () => { + expect(scrollUptimeFeed.getTimestamp(2)).to.be.revertedWith( + 'NoDataPresent()', + ) + }) + }) + + describe('Protect reads on AggregatorV2V3Interface functions', () => { + it('should disallow reads on AggregatorV2V3Interface functions when consuming contract is not whitelisted', async () => { + // Sanity - consumer is not whitelisted + expect(await scrollUptimeFeed.checkEnabled()).to.be.true + expect( + await scrollUptimeFeed.hasAccess(uptimeFeedConsumer.address, '0x00'), + ).to.be.false + + // Assert reads are not possible from consuming contract + await expect(uptimeFeedConsumer.latestAnswer()).to.be.revertedWith( + 'No access', + ) + await expect(uptimeFeedConsumer.latestRoundData()).to.be.revertedWith( + 'No access', + ) + }) + + it('should allow reads on AggregatorV2V3Interface functions when consuming contract is whitelisted', async () => { + // Whitelist consumer + await scrollUptimeFeed.addAccess(uptimeFeedConsumer.address) + // Sanity - consumer is whitelisted + expect(await scrollUptimeFeed.checkEnabled()).to.be.true + expect( + await scrollUptimeFeed.hasAccess(uptimeFeedConsumer.address, '0x00'), + ).to.be.true + + // Assert reads are possible from consuming contract + expect(await uptimeFeedConsumer.latestAnswer()).to.be.equal('0') + const [roundId, answer] = await uptimeFeedConsumer.latestRoundData() + expect(roundId).to.equal(1) + expect(answer).to.equal(0) + }) + }) + + describe('Gas costs', () => { + it('should consume a known amount of gas for updates @skip-coverage', async () => { + // Sanity - start at flag = 0 (`false`) + expect(await scrollUptimeFeed.latestAnswer()).to.equal(0) + let timestamp = await scrollUptimeFeed.latestTimestamp() + + // Gas for no update + timestamp = timestamp.add(1000) + const _noUpdateTx = await scrollUptimeFeed + .connect(l2Messenger) + .updateStatus(false, timestamp) + const noUpdateTx = await _noUpdateTx.wait(1) + // Assert no update + expect(await scrollUptimeFeed.latestAnswer()).to.equal(0) + expect(noUpdateTx.cumulativeGasUsed.toNumber()).to.be.closeTo( + 38594, + gasUsedDeviation, + ) + + // Gas for update + timestamp = timestamp.add(1000) + const _updateTx = await scrollUptimeFeed + .connect(l2Messenger) + .updateStatus(true, timestamp) + const updateTx = await _updateTx.wait(1) + // Assert update + expect(await scrollUptimeFeed.latestAnswer()).to.equal(1) + expect(updateTx.cumulativeGasUsed.toNumber()).to.be.closeTo( + 58458, + gasUsedDeviation, + ) + }) + + describe('Aggregator interface', () => { + beforeEach(async () => { + const timestamp = (await scrollUptimeFeed.latestTimestamp()).add(1000) + // Initialise a round + await scrollUptimeFeed + .connect(l2Messenger) + .updateStatus(true, timestamp) + }) + + it('should consume a known amount of gas for getRoundData(uint80) @skip-coverage', async () => { + const _tx = await l2Messenger.sendTransaction( + await scrollUptimeFeed + .connect(l2Messenger) + .populateTransaction.getRoundData(1), + ) + const tx = await _tx.wait(1) + expect(tx.cumulativeGasUsed.toNumber()).to.be.closeTo( + 30952, + gasUsedDeviation, + ) + }) + + it('should consume a known amount of gas for latestRoundData() @skip-coverage', async () => { + const _tx = await l2Messenger.sendTransaction( + await scrollUptimeFeed + .connect(l2Messenger) + .populateTransaction.latestRoundData(), + ) + const tx = await _tx.wait(1) + expect(tx.cumulativeGasUsed.toNumber()).to.be.closeTo( + 28523, + gasUsedDeviation, + ) + }) + + it('should consume a known amount of gas for latestAnswer() @skip-coverage', async () => { + const _tx = await l2Messenger.sendTransaction( + await scrollUptimeFeed + .connect(l2Messenger) + .populateTransaction.latestAnswer(), + ) + const tx = await _tx.wait(1) + expect(tx.cumulativeGasUsed.toNumber()).to.be.closeTo( + 28229, + gasUsedDeviation, + ) + }) + + it('should consume a known amount of gas for latestTimestamp() @skip-coverage', async () => { + const _tx = await l2Messenger.sendTransaction( + await scrollUptimeFeed + .connect(l2Messenger) + .populateTransaction.latestTimestamp(), + ) + const tx = await _tx.wait(1) + expect(tx.cumulativeGasUsed.toNumber()).to.be.closeTo( + 28129, + gasUsedDeviation, + ) + }) + + it('should consume a known amount of gas for latestRound() @skip-coverage', async () => { + const _tx = await l2Messenger.sendTransaction( + await scrollUptimeFeed + .connect(l2Messenger) + .populateTransaction.latestRound(), + ) + const tx = await _tx.wait(1) + expect(tx.cumulativeGasUsed.toNumber()).to.be.closeTo( + 28145, + gasUsedDeviation, + ) + }) + + it('should consume a known amount of gas for getAnswer(roundId) @skip-coverage', async () => { + const _tx = await l2Messenger.sendTransaction( + await scrollUptimeFeed + .connect(l2Messenger) + .populateTransaction.getAnswer(1), + ) + const tx = await _tx.wait(1) + expect(tx.cumulativeGasUsed.toNumber()).to.be.closeTo( + 30682, + gasUsedDeviation, + ) + }) + + it('should consume a known amount of gas for getTimestamp(roundId) @skip-coverage', async () => { + const _tx = await l2Messenger.sendTransaction( + await scrollUptimeFeed + .connect(l2Messenger) + .populateTransaction.getTimestamp(1), + ) + const tx = await _tx.wait(1) + expect(tx.cumulativeGasUsed.toNumber()).to.be.closeTo( + 30570, + gasUsedDeviation, + ) + }) + }) + }) +}) diff --git a/contracts/test/v0.8/dev/ScrollValidator.test.ts b/contracts/test/v0.8/dev/ScrollValidator.test.ts new file mode 100644 index 00000000000..866d52b202f --- /dev/null +++ b/contracts/test/v0.8/dev/ScrollValidator.test.ts @@ -0,0 +1,118 @@ +import { ethers } from 'hardhat' +import { BigNumber, Contract, ContractFactory } from 'ethers' +import { expect } from 'chai' +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' + +describe('ScrollValidator', () => { + const GAS_LIMIT = BigNumber.from(1_900_000) + /** Fake L2 target */ + const L2_SEQ_STATUS_RECORDER_ADDRESS = + '0x491B1dDA0A8fa069bbC1125133A975BF4e85a91b' + let scrollValidator: Contract + let scrollUptimeFeedFactory: ContractFactory + let mockScrollL1CrossDomainMessenger: Contract + let deployer: SignerWithAddress + let eoaValidator: SignerWithAddress + + before(async () => { + const accounts = await ethers.getSigners() + deployer = accounts[0] + eoaValidator = accounts[1] + }) + + beforeEach(async () => { + // Required for building the calldata + scrollUptimeFeedFactory = await ethers.getContractFactory( + 'src/v0.8/l2ep/dev/scroll/ScrollSequencerUptimeFeed.sol:ScrollSequencerUptimeFeed', + deployer, + ) + + // Scroll Messenger contract on L1 + const mockScrollL1CrossDomainMessengerFactory = + await ethers.getContractFactory( + 'src/v0.8/l2ep/test/mocks/MockScrollL1CrossDomainMessenger.sol:MockScrollL1CrossDomainMessenger', + ) + mockScrollL1CrossDomainMessenger = + await mockScrollL1CrossDomainMessengerFactory.deploy() + + // Contract under test + const scrollValidatorFactory = await ethers.getContractFactory( + 'src/v0.8/l2ep/dev/scroll/ScrollValidator.sol:ScrollValidator', + deployer, + ) + + scrollValidator = await scrollValidatorFactory.deploy( + mockScrollL1CrossDomainMessenger.address, + L2_SEQ_STATUS_RECORDER_ADDRESS, + GAS_LIMIT, + ) + }) + + describe('#setGasLimit', () => { + it('correctly updates the gas limit', async () => { + const newGasLimit = BigNumber.from(2_000_000) + const tx = await scrollValidator.setGasLimit(newGasLimit) + await tx.wait() + const currentGasLimit = await scrollValidator.getGasLimit() + expect(currentGasLimit).to.equal(newGasLimit) + }) + }) + + describe('#validate', () => { + it('reverts if called by account with no access', async () => { + await expect( + scrollValidator.connect(eoaValidator).validate(0, 0, 1, 1), + ).to.be.revertedWith('No access') + }) + + it('posts sequencer status when there is not status change', async () => { + await scrollValidator.addAccess(eoaValidator.address) + + const currentBlock = await ethers.provider.getBlock('latest') + const futureTimestamp = currentBlock.timestamp + 5000 + + await ethers.provider.send('evm_setNextBlockTimestamp', [futureTimestamp]) + const sequencerStatusRecorderCallData = + scrollUptimeFeedFactory.interface.encodeFunctionData('updateStatus', [ + false, + futureTimestamp, + ]) + + await expect(scrollValidator.connect(eoaValidator).validate(0, 0, 0, 0)) + .to.emit(mockScrollL1CrossDomainMessenger, 'SentMessage') + .withArgs( + scrollValidator.address, // sender + L2_SEQ_STATUS_RECORDER_ADDRESS, // target + 0, // value + 0, // nonce + GAS_LIMIT, // gas limit + sequencerStatusRecorderCallData, // message + ) + }) + + it('post sequencer offline', async () => { + await scrollValidator.addAccess(eoaValidator.address) + + const currentBlock = await ethers.provider.getBlock('latest') + const futureTimestamp = currentBlock.timestamp + 10000 + + await ethers.provider.send('evm_setNextBlockTimestamp', [futureTimestamp]) + const sequencerStatusRecorderCallData = + scrollUptimeFeedFactory.interface.encodeFunctionData('updateStatus', [ + true, + futureTimestamp, + ]) + + await expect(scrollValidator.connect(eoaValidator).validate(0, 0, 1, 1)) + .to.emit(mockScrollL1CrossDomainMessenger, 'SentMessage') + .withArgs( + scrollValidator.address, // sender + L2_SEQ_STATUS_RECORDER_ADDRESS, // target + 0, // value + 0, // nonce + GAS_LIMIT, // gas limit + sequencerStatusRecorderCallData, // message + ) + }) + }) +}) From 35ad7d164a29409e60a9896434df5685bc8f2a59 Mon Sep 17 00:00:00 2001 From: Domino Valdano <2644901+reductionista@users.noreply.github.com> Date: Tue, 12 Dec 2023 13:11:14 -0800 Subject: [PATCH 06/29] Handle edge case involving blocks not being found in the db (#11298) If there is a backfill followed by an error, logs get written to the db but no blocks. This will make the logpoller (or backup log poller) rely on the chain next time instead of the db to determine lastFinalizedBlock, which could result in a gap in logs processed. Fixing this by writing the last block in the backfil to the db along with the logs. Its lastFinalizedBlock field will be set to its own block number + 1, so if the db crashes it should start by pulling the logs from that one. --- core/chains/evm/logpoller/log_poller.go | 2 +- core/chains/evm/logpoller/log_poller_test.go | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/core/chains/evm/logpoller/log_poller.go b/core/chains/evm/logpoller/log_poller.go index fb380f84b2c..1cf1cf42beb 100644 --- a/core/chains/evm/logpoller/log_poller.go +++ b/core/chains/evm/logpoller/log_poller.go @@ -679,7 +679,7 @@ func (lp *logPoller) backfill(ctx context.Context, start, end int64) error { } lp.lggr.Debugw("Backfill found logs", "from", from, "to", to, "logs", len(gethLogs), "blocks", blocks) - err = lp.orm.InsertLogs(convertLogs(gethLogs, blocks, lp.lggr, lp.ec.ConfiguredChainID()), pg.WithParentCtx(ctx)) + err = lp.orm.InsertLogsWithBlock(convertLogs(gethLogs, blocks, lp.lggr, lp.ec.ConfiguredChainID()), blocks[len(blocks)-1], pg.WithParentCtx(ctx)) if err != nil { lp.lggr.Warnw("Unable to insert logs, retrying", "err", err, "from", from, "to", to) return err diff --git a/core/chains/evm/logpoller/log_poller_test.go b/core/chains/evm/logpoller/log_poller_test.go index 82447bdb5f4..6c4dd381b54 100644 --- a/core/chains/evm/logpoller/log_poller_test.go +++ b/core/chains/evm/logpoller/log_poller_test.go @@ -965,8 +965,8 @@ func TestLogPoller_PollAndSaveLogs(t *testing.T) { lgs, err = th.ORM.SelectLogsByBlockRange(11, 17) require.NoError(t, err) assert.Equal(t, 7, len(lgs)) - th.assertHaveCanonical(t, 15, 16) - th.assertDontHave(t, 11, 14) // Do not expect to save backfilled blocks. + th.assertHaveCanonical(t, 14, 16) // Should have last finalized block plus unfinalized blocks + th.assertDontHave(t, 11, 13) // Should not have older finalized blocks // Verify that a custom block timestamp will get written to db correctly also b, err = th.Client.BlockByNumber(testutils.Context(t), nil) @@ -1057,8 +1057,8 @@ func TestLogPoller_PollAndSaveLogsDeepReorg(t *testing.T) { require.NoError(t, err) assert.Equal(t, hexutil.MustDecode(`0x0000000000000000000000000000000000000000000000000000000000000002`), lgs[0].Data) th.assertHaveCanonical(t, 1, 1) - th.assertDontHave(t, 2, 5) // These blocks are backfilled - th.assertHaveCanonical(t, 6, 10) + th.assertDontHave(t, 2, 3) // These blocks are backfilled + th.assertHaveCanonical(t, 5, 10) }) } } From a8d096cc69b49cd2f8fc0672b819ccd8b5b38048 Mon Sep 17 00:00:00 2001 From: Dimitris Grigoriou Date: Tue, 12 Dec 2023 23:18:34 +0200 Subject: [PATCH 07/29] Remove big from core utils (#11511) * Change difficulty from Big to BigInt * Fix headtracker mock head * Remove EsnureClosed * Fix mock heads * Migrate to common Mailbox * Fix Tracker close on txm * Change to EnsureHexPrefix * Change names to mailbox * Remove core/null dependency from common * Remove core mailbox * Fix dependencies * Tidy * Fix dependencies * Change path to internal utils * Minor fixes * Implement skeleton interfaces, structs, & methods for ChainReader EVM POC - Read ChainReader config in from RelayConfig - Add some initialization and validation relay skeletons - Use medianProviderWrapper instead of passing medianContract separately This avoids us having to modify the signature of NewMedianFactory, which would require further modifications to all non-evm repos and chainlink-relay - Add chain_reader_test.go with some basic relay tests Co-authored-by: Jordan Krage - Add chain reader config validation - Add chain reader config validation tests - Add config for chain reader median contract to cr validation testcases - Add unimplemented Encode(), Decode(), GetMaxEncodingSize(), GetMaxDecodingSize() - Add ChainReader() method to mock provider for plugin test - Rename relaymercury.ChainReader to MercuryChainReader, resolve name collisions - Add tests for errors during ChainReader construction - Propagate InvalidConfig & any other errors back to client We should ignore Unimplemented until node ops have been given ample time to migrate to the new job spec (including a section for ChainReader config) so that we can remove the old product-specific MedianContract component from MedianProvider. All other errors we can immediately start passing back to the client, letting the core node decide how to handle them (eg. displaying an "invalid job spec" message to the UI if the RelayConfig was invalid or the ContractID missing) * Update relay versions * Big migration * Simplify chain reader config validation * Rename MinKey function * Remove big from utils * Fix dependencies * Minor fixes * Fix merge conflicts * Minor fixes --------- Co-authored-by: Domino Valdano <2644901+reductionista@users.noreply.github.com> Co-authored-by: ilija --- core/chains/evm/assets/assets.go | 6 +- core/chains/evm/assets/wei.go | 10 +-- core/chains/evm/client/chain_id_sub.go | 4 +- core/chains/evm/client/chain_id_sub_test.go | 4 +- core/chains/evm/client/client.go | 5 +- core/chains/evm/client/node_lifecycle.go | 5 +- core/chains/evm/client/pool.go | 2 +- core/chains/evm/client/rpc_client.go | 5 +- .../evm/client/send_only_node_lifecycle.go | 2 +- .../evm/client/simulated_backend_client.go | 8 +-- core/chains/evm/config/config_test.go | 16 ++--- core/chains/evm/config/toml/config.go | 8 +-- core/chains/evm/config/toml/defaults.go | 14 ++-- core/chains/evm/forwarders/forwarder.go | 4 +- .../evm/forwarders/forwarder_manager.go | 7 +- .../evm/forwarders/forwarder_manager_test.go | 12 ++-- core/chains/evm/forwarders/mocks/orm.go | 29 ++++---- core/chains/evm/forwarders/orm.go | 14 ++-- core/chains/evm/forwarders/orm_test.go | 4 +- .../evm/gas/block_history_estimator_test.go | 15 ++-- .../evm/headtracker/head_broadcaster_test.go | 5 +- .../evm/headtracker/head_tracker_test.go | 9 +-- core/chains/evm/headtracker/heads_test.go | 5 +- core/chains/evm/headtracker/orm.go | 6 +- core/chains/evm/log/orm.go | 7 +- core/chains/evm/logpoller/log_poller.go | 3 +- core/chains/evm/logpoller/log_poller_test.go | 5 +- core/chains/evm/logpoller/models.go | 6 +- .../evm/logpoller/observability_test.go | 3 +- core/chains/evm/logpoller/orm.go | 16 ++--- core/chains/evm/logpoller/orm_test.go | 69 ++++++++++--------- core/chains/evm/logpoller/query.go | 4 +- core/chains/evm/logpoller/query_test.go | 3 +- core/chains/evm/txmgr/broadcaster_test.go | 3 +- core/chains/evm/txmgr/evm_tx_store.go | 6 +- core/chains/evm/txmgr/resender_test.go | 4 +- core/chains/evm/txmgr/tracker_test.go | 6 +- core/chains/evm/txmgr/txmgr_test.go | 5 +- core/chains/evm/types/models.go | 5 +- core/chains/evm/types/types.go | 3 +- core/{utils => chains/evm/utils/big}/big.go | 21 +++--- .../evm/utils/big}/big_test.go | 14 ++-- core/chains/evm/utils/utils.go | 37 ++++++++++ core/chains/legacyevm/chain.go | 4 +- core/cmd/blocks_commands_test.go | 4 +- core/cmd/eth_keys_commands_test.go | 3 +- core/cmd/evm_chains_commands_test.go | 6 +- core/cmd/evm_transaction_commands.go | 3 +- core/cmd/forwarders_commands.go | 4 +- core/cmd/forwarders_commands_test.go | 3 +- core/cmd/ocr2vrf_configure_commands.go | 3 +- core/cmd/shell_local.go | 3 +- core/internal/cltest/cltest.go | 21 +++--- core/internal/cltest/factories.go | 17 ++--- core/internal/cltest/simulated_backend.go | 6 +- core/internal/features/features_test.go | 5 +- .../features/ocr2/features_ocr2_test.go | 4 +- .../testutils/configtest/general_config.go | 8 +-- core/internal/testutils/evmtest/evmtest.go | 6 +- core/internal/testutils/evmtest/v2/evmtest.go | 4 +- core/scripts/functions/src/fetching.go | 3 +- core/services/blockhashstore/delegate_test.go | 10 +-- core/services/blockhashstore/validate_test.go | 4 +- .../blockheaderfeeder/validate_test.go | 6 +- core/services/chainlink/config.go | 4 +- core/services/chainlink/config_test.go | 11 +-- .../relayer_chain_interoperators_test.go | 6 +- core/services/directrequest/delegate_test.go | 4 +- core/services/directrequest/validate.go | 4 +- core/services/feeds/service.go | 4 +- core/services/feeds/service_test.go | 4 +- core/services/fluxmonitorv2/orm_test.go | 4 +- core/services/job/job_orm_test.go | 14 ++-- core/services/job/mocks/orm.go | 15 ++-- core/services/job/models.go | 29 ++++---- core/services/job/orm.go | 6 +- core/services/keeper/integration_test.go | 8 +-- core/services/keeper/models.go | 9 +-- core/services/keeper/models_test.go | 4 +- core/services/keeper/orm.go | 10 +-- core/services/keeper/orm_test.go | 13 ++-- .../keeper/registry1_1_synchronizer_test.go | 4 +- .../keeper/registry1_3_synchronizer_test.go | 6 +- .../registry_synchronizer_process_logs.go | 20 +++--- .../keeper/registry_synchronizer_sync.go | 17 ++--- .../keeper/registry_synchronizer_sync_test.go | 4 +- core/services/keeper/upkeep_executer_test.go | 15 ++-- .../keeper/upkeep_executer_unit_test.go | 4 +- core/services/keystore/eth_test.go | 3 +- core/services/keystore/keys/ethkey/models.go | 4 +- core/services/ocr/database.go | 6 +- core/services/ocr2/delegate_test.go | 4 +- .../evmregistry/v20/registry_test.go | 6 +- .../v21/logprovider/recoverer_test.go | 4 +- .../evmregistry/v21/registry_test.go | 6 +- .../evmregistry/v21/upkeepstate/orm.go | 12 ++-- .../evmregistry/v21/upkeepstate/orm_test.go | 4 +- .../evmregistry/v21/upkeepstate/store.go | 3 +- .../plugins/ocr2keeper/integration_test.go | 4 +- .../internal/ocr2vrf_integration_test.go | 3 +- .../ocr2/plugins/s4/integration_test.go | 6 +- core/services/ocr2/plugins/s4/messages.go | 6 +- core/services/ocr2/plugins/s4/plugin.go | 4 +- core/services/ocr2/plugins/s4/plugin_test.go | 8 +-- core/services/ocrcommon/telemetry_test.go | 5 +- core/services/pipeline/orm_test.go | 5 +- .../promreporter/prom_reporter_test.go | 3 +- core/services/relay/evm/median_test.go | 4 +- .../relay/evm/relayer_extender_test.go | 4 +- core/services/relay/evm/types/types.go | 4 +- core/services/relay/evm/types/types_test.go | 2 +- core/services/s4/address_range.go | 28 ++++---- core/services/s4/address_range_test.go | 8 +-- core/services/s4/in_memory_orm.go | 6 +- core/services/s4/in_memory_orm_test.go | 16 ++--- core/services/s4/mocks/orm.go | 15 ++-- core/services/s4/orm.go | 10 +-- core/services/s4/postgres_orm.go | 4 +- core/services/s4/postgres_orm_test.go | 4 +- core/services/s4/storage.go | 7 +- core/services/s4/storage_test.go | 9 +-- core/services/vrf/delegate_test.go | 2 +- core/services/vrf/v1/integration_test.go | 6 +- .../vrf/v2/integration_helpers_test.go | 5 +- core/services/vrf/v2/integration_v2_test.go | 3 +- .../vrf/v2/listener_v2_log_listener_test.go | 5 +- core/store/migrate/migrate_test.go | 8 +-- core/store/models/common.go | 4 +- core/web/eth_keys_controller.go | 4 +- core/web/evm_chains_controller_test.go | 10 +-- core/web/evm_forwarders_controller.go | 4 +- core/web/evm_forwarders_controller_test.go | 5 +- core/web/evm_transfer_controller_test.go | 18 ++--- core/web/loader/loader_test.go | 5 +- core/web/presenters/eth_key.go | 8 +-- core/web/presenters/eth_key_test.go | 8 +-- core/web/presenters/eth_tx.go | 8 +-- core/web/presenters/evm_forwarder.go | 4 +- core/web/presenters/job.go | 16 ++--- core/web/presenters/job_test.go | 8 +-- core/web/replay_controller.go | 8 +-- core/web/resolver/chain_test.go | 6 +- core/web/resolver/eth_key_test.go | 22 +++--- core/web/resolver/eth_transaction_test.go | 4 +- core/web/resolver/node_test.go | 4 +- core/web/resolver/spec_test.go | 18 ++--- integration-tests/client/chainlink_models.go | 6 +- integration-tests/types/config/node/core.go | 5 +- 148 files changed, 636 insertions(+), 550 deletions(-) rename core/{utils => chains/evm/utils/big}/big.go (91%) rename core/{utils => chains/evm/utils/big}/big_test.go (95%) create mode 100644 core/chains/evm/utils/utils.go diff --git a/core/chains/evm/assets/assets.go b/core/chains/evm/assets/assets.go index 377e92a855a..738ba5c817b 100644 --- a/core/chains/evm/assets/assets.go +++ b/core/chains/evm/assets/assets.go @@ -7,7 +7,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/assets" "github.com/smartcontractkit/chainlink-common/pkg/utils/bytes" - "github.com/smartcontractkit/chainlink/v2/core/utils" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/shopspring/decimal" ) @@ -108,10 +108,10 @@ func (e *Eth) ToInt() *big.Int { // Scan reads the database value and returns an instance. func (e *Eth) Scan(value interface{}) error { - return (*utils.Big)(e).Scan(value) + return (*ubig.Big)(e).Scan(value) } // Value returns the Eth value for serialization to database. func (e Eth) Value() (driver.Value, error) { - return (utils.Big)(e).Value() + return (ubig.Big)(e).Value() } diff --git a/core/chains/evm/assets/wei.go b/core/chains/evm/assets/wei.go index be0143b3a86..8bacabfdb4a 100644 --- a/core/chains/evm/assets/wei.go +++ b/core/chains/evm/assets/wei.go @@ -11,7 +11,7 @@ import ( "golang.org/x/exp/constraints" bigmath "github.com/smartcontractkit/chainlink-common/pkg/utils/big_math" - "github.com/smartcontractkit/chainlink/v2/core/utils" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" ) const ( @@ -58,10 +58,10 @@ func suffixExp(suf string) int32 { } } -// Wei extends utils.Big to implement encoding.TextMarshaler and +// Wei extends ubig.Big to implement encoding.TextMarshaler and // encoding.TextUnmarshaler with support for unit suffixes, as well as // additional functions -type Wei utils.Big +type Wei ubig.Big func MaxWei(w, x *Wei) *Wei { return NewWei(bigmath.Max(w.ToInt(), x.ToInt())) @@ -271,10 +271,10 @@ func (w *Wei) AddPercentage(percentage uint16) *Wei { // Scan reads the database value and returns an instance. func (w *Wei) Scan(value interface{}) error { - return (*utils.Big)(w).Scan(value) + return (*ubig.Big)(w).Scan(value) } // Value returns this instance serialized for database storage. func (w Wei) Value() (driver.Value, error) { - return (utils.Big)(w).Value() + return (ubig.Big)(w).Value() } diff --git a/core/chains/evm/client/chain_id_sub.go b/core/chains/evm/client/chain_id_sub.go index 8ea4e207970..c3162b300c7 100644 --- a/core/chains/evm/client/chain_id_sub.go +++ b/core/chains/evm/client/chain_id_sub.go @@ -6,7 +6,7 @@ import ( "github.com/ethereum/go-ethereum" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/utils" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" ) var _ ethereum.Subscription = &chainIDSubForwarder{} @@ -64,7 +64,7 @@ func (c *chainIDSubForwarder) forwardLoop() { return case h := <-c.srcCh: - h.EVMChainID = utils.NewBig(c.chainID) + h.EVMChainID = ubig.New(c.chainID) select { case c.destCh <- h: case <-c.unSub: diff --git a/core/chains/evm/client/chain_id_sub_test.go b/core/chains/evm/client/chain_id_sub_test.go index 211ba812fbe..c71b45c489e 100644 --- a/core/chains/evm/client/chain_id_sub_test.go +++ b/core/chains/evm/client/chain_id_sub_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/assert" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/utils" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" ) type mockSubscription struct { @@ -111,7 +111,7 @@ func TestChainIDSubForwarder(t *testing.T) { forwarder.srcCh <- head receivedHead := <-ch assert.Equal(t, head, receivedHead) - assert.Equal(t, utils.NewBig(chainID), receivedHead.EVMChainID) + assert.Equal(t, ubig.New(chainID), receivedHead.EVMChainID) expectedErr := errors.New("error") sub.Errors <- expectedErr diff --git a/core/chains/evm/client/client.go b/core/chains/evm/client/client.go index 688cc3c9bea..b85331a62a1 100644 --- a/core/chains/evm/client/client.go +++ b/core/chains/evm/client/client.go @@ -14,6 +14,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/common/config" htrktypes "github.com/smartcontractkit/chainlink/v2/common/headtracker/types" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/ethereum/go-ethereum" @@ -286,7 +287,7 @@ func (client *client) HeadByNumber(ctx context.Context, number *big.Int) (head * err = ethereum.NotFound return } - head.EVMChainID = utils.NewBig(client.ConfiguredChainID()) + head.EVMChainID = ubig.New(client.ConfiguredChainID()) return } @@ -299,7 +300,7 @@ func (client *client) HeadByHash(ctx context.Context, hash common.Hash) (head *e err = ethereum.NotFound return } - head.EVMChainID = utils.NewBig(client.ConfiguredChainID()) + head.EVMChainID = ubig.New(client.ConfiguredChainID()) return } diff --git a/core/chains/evm/client/node_lifecycle.go b/core/chains/evm/client/node_lifecycle.go index f838325a646..4e984de00f0 100644 --- a/core/chains/evm/client/node_lifecycle.go +++ b/core/chains/evm/client/node_lifecycle.go @@ -12,10 +12,11 @@ import ( "github.com/prometheus/client_golang/prometheus/promauto" "github.com/smartcontractkit/chainlink-common/pkg/logger" + cutils "github.com/smartcontractkit/chainlink-common/pkg/utils" bigmath "github.com/smartcontractkit/chainlink-common/pkg/utils/big_math" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/utils" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ) var ( @@ -50,7 +51,7 @@ func zombieNodeCheckInterval(noNewHeadsThreshold time.Duration) time.Duration { if interval <= 0 || interval > queryTimeout { interval = queryTimeout } - return utils.WithJitter(interval) + return cutils.WithJitter(interval) } func (n *node) setLatestReceived(blockNumber int64, totalDifficulty *big.Int) { diff --git a/core/chains/evm/client/pool.go b/core/chains/evm/client/pool.go index 6c36cc3e987..afe592533c3 100644 --- a/core/chains/evm/client/pool.go +++ b/core/chains/evm/client/pool.go @@ -17,10 +17,10 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/common/config" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) var ( diff --git a/core/chains/evm/client/rpc_client.go b/core/chains/evm/client/rpc_client.go index 01851c4ae90..3cc90c4d8d9 100644 --- a/core/chains/evm/client/rpc_client.go +++ b/core/chains/evm/client/rpc_client.go @@ -24,6 +24,7 @@ import ( commontypes "github.com/smartcontractkit/chainlink/v2/common/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/utils" ) @@ -491,7 +492,7 @@ func (r *rpcClient) BlockByNumber(ctx context.Context, number *big.Int) (head *e err = ethereum.NotFound return } - head.EVMChainID = utils.NewBig(r.chainID) + head.EVMChainID = ubig.New(r.chainID) return } @@ -504,7 +505,7 @@ func (r *rpcClient) BlockByHash(ctx context.Context, hash common.Hash) (head *ev err = ethereum.NotFound return } - head.EVMChainID = utils.NewBig(r.chainID) + head.EVMChainID = ubig.New(r.chainID) return } diff --git a/core/chains/evm/client/send_only_node_lifecycle.go b/core/chains/evm/client/send_only_node_lifecycle.go index 9d704e49389..127a5c6678c 100644 --- a/core/chains/evm/client/send_only_node_lifecycle.go +++ b/core/chains/evm/client/send_only_node_lifecycle.go @@ -4,7 +4,7 @@ import ( "fmt" "time" - "github.com/smartcontractkit/chainlink/v2/core/utils" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ) // verifyLoop may only be triggered once, on Start, if initial chain ID check diff --git a/core/chains/evm/client/simulated_backend_client.go b/core/chains/evm/client/simulated_backend_client.go index 293bf64badc..bd2e959d9bc 100644 --- a/core/chains/evm/client/simulated_backend_client.go +++ b/core/chains/evm/client/simulated_backend_client.go @@ -23,7 +23,7 @@ import ( commonclient "github.com/smartcontractkit/chainlink/v2/common/client" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/utils" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" ) func init() { @@ -197,7 +197,7 @@ func (c *SimulatedBackendClient) HeadByNumber(ctx context.Context, n *big.Int) ( return nil, ethereum.NotFound } return &evmtypes.Head{ - EVMChainID: utils.NewBigI(c.chainId.Int64()), + EVMChainID: ubig.NewI(c.chainId.Int64()), Hash: header.Hash(), Number: header.Number.Int64(), ParentHash: header.ParentHash, @@ -214,7 +214,7 @@ func (c *SimulatedBackendClient) HeadByHash(ctx context.Context, h common.Hash) return nil, ethereum.NotFound } return &evmtypes.Head{ - EVMChainID: utils.NewBigI(c.chainId.Int64()), + EVMChainID: ubig.NewI(c.chainId.Int64()), Hash: header.Hash(), Number: header.Number.Int64(), ParentHash: header.ParentHash, @@ -302,7 +302,7 @@ func (c *SimulatedBackendClient) SubscribeNewHead( case h := <-ch: var head *evmtypes.Head if h != nil { - head = &evmtypes.Head{Difficulty: h.Difficulty, Timestamp: time.Unix(int64(h.Time), 0), Number: h.Number.Int64(), Hash: h.Hash(), ParentHash: h.ParentHash, Parent: lastHead, EVMChainID: utils.NewBig(c.chainId)} + head = &evmtypes.Head{Difficulty: h.Difficulty, Timestamp: time.Unix(int64(h.Time), 0), Number: h.Number.Int64(), Hash: h.Hash(), ParentHash: h.ParentHash, Parent: lastHead, EVMChainID: ubig.New(c.chainId)} lastHead = head } select { diff --git a/core/chains/evm/config/config_test.go b/core/chains/evm/config/config_test.go index d34d1eae63e..0127328239a 100644 --- a/core/chains/evm/config/config_test.go +++ b/core/chains/evm/config/config_test.go @@ -14,6 +14,7 @@ import ( commonconfig "github.com/smartcontractkit/chainlink/v2/common/config" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/config" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" @@ -21,13 +22,12 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" "github.com/smartcontractkit/chainlink/v2/core/store/models" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func TestChainScopedConfig(t *testing.T) { t.Parallel() gcfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { - id := utils.NewBig(big.NewInt(rand.Int63())) + id := ubig.New(big.NewInt(rand.Int63())) c.EVM[0] = &toml.EVMConfig{ ChainID: id, Chain: toml.Defaults(id, &toml.Chain{ @@ -38,7 +38,7 @@ func TestChainScopedConfig(t *testing.T) { cfg := evmtest.NewChainScopedConfig(t, gcfg) overrides := func(c *chainlink.Config, s *chainlink.Secrets) { - id := utils.NewBig(big.NewInt(rand.Int63())) + id := ubig.New(big.NewInt(rand.Int63())) c.EVM[0] = &toml.EVMConfig{ ChainID: id, Chain: toml.Defaults(id, &toml.Chain{ @@ -65,7 +65,7 @@ func TestChainScopedConfig(t *testing.T) { t.Run("uses customer configured value when set", func(t *testing.T) { var override uint32 = 10 gasBumpOverrides := func(c *chainlink.Config, s *chainlink.Secrets) { - id := utils.NewBig(big.NewInt(rand.Int63())) + id := ubig.New(big.NewInt(rand.Int63())) c.EVM[0] = &toml.EVMConfig{ ChainID: id, Chain: toml.Defaults(id, &toml.Chain{ @@ -292,7 +292,7 @@ func TestChainScopedConfig_GasEstimator(t *testing.T) { func TestChainScopedConfig_BSCDefaults(t *testing.T) { chainID := big.NewInt(56) gcfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, secrets *chainlink.Secrets) { - id := utils.NewBig(chainID) + id := ubig.New(chainID) cfg := toml.Defaults(id) c.EVM[0] = &toml.EVMConfig{ ChainID: id, @@ -344,7 +344,7 @@ func TestChainScopedConfig_Profiles(t *testing.T) { t.Parallel() gcfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, secrets *chainlink.Secrets) { - id := utils.NewBigI(tt.chainID) + id := ubig.NewI(tt.chainID) cfg := toml.Defaults(id) c.EVM[0] = &toml.EVMConfig{ ChainID: id, @@ -379,7 +379,7 @@ func TestChainScopedConfig_HeadTracker(t *testing.T) { func Test_chainScopedConfig_Validate(t *testing.T) { configWithChains := func(t *testing.T, id int64, chains ...*toml.Chain) config.AppConfig { return configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { - chainID := utils.NewBigI(id) + chainID := ubig.NewI(id) c.EVM[0] = &toml.EVMConfig{ChainID: chainID, Enabled: ptr(true), Chain: toml.Defaults(chainID, chains...), Nodes: toml.EVMNodes{{ Name: ptr("fake"), @@ -462,7 +462,7 @@ func Test_chainScopedConfig_Validate(t *testing.T) { func TestNodePoolConfig(t *testing.T) { gcfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { - id := utils.NewBig(big.NewInt(rand.Int63())) + id := ubig.New(big.NewInt(rand.Int63())) c.EVM[0] = &toml.EVMConfig{ ChainID: id, Chain: toml.Defaults(id, &toml.Chain{}), diff --git a/core/chains/evm/config/toml/config.go b/core/chains/evm/config/toml/config.go index 9e51d5be790..16ad74dbca2 100644 --- a/core/chains/evm/config/toml/config.go +++ b/core/chains/evm/config/toml/config.go @@ -19,10 +19,10 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/core/store/models" - "github.com/smartcontractkit/chainlink/v2/core/utils" configutils "github.com/smartcontractkit/chainlink/v2/core/utils/config" ) @@ -161,7 +161,7 @@ func (cs EVMConfigs) NodeStatus(name string) (commontypes.NodeStatus, error) { return commontypes.NodeStatus{}, fmt.Errorf("node %s: %w", name, chains.ErrNotFound) } -func legacyNode(n *Node, chainID *utils.Big) (v2 types.Node) { +func legacyNode(n *Node, chainID *big.Big) (v2 types.Node) { v2.Name = *n.Name v2.EVMChainID = *chainID if n.HTTPURL != nil { @@ -215,7 +215,7 @@ func (cs EVMConfigs) Nodes(chainID relay.ChainID) (ns []types.Node, err error) { continue } - ns = append(ns, legacyNode(n, utils.NewBigI(evmID))) + ns = append(ns, legacyNode(n, big.NewI(evmID))) } return } @@ -268,7 +268,7 @@ func (ns *EVMNodes) SetFrom(fs *EVMNodes) { } type EVMConfig struct { - ChainID *utils.Big + ChainID *big.Big Enabled *bool Chain Nodes EVMNodes diff --git a/core/chains/evm/config/toml/defaults.go b/core/chains/evm/config/toml/defaults.go index d362e9ac3dc..27127993d8a 100644 --- a/core/chains/evm/config/toml/defaults.go +++ b/core/chains/evm/config/toml/defaults.go @@ -9,7 +9,7 @@ import ( "strings" "github.com/smartcontractkit/chainlink/v2/common/config" - "github.com/smartcontractkit/chainlink/v2/core/utils" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" configutils "github.com/smartcontractkit/chainlink/v2/core/utils/config" ) @@ -21,7 +21,7 @@ var ( defaultNames = map[string]string{} // DefaultIDs is the set of chain ids which have defaults. - DefaultIDs []*utils.Big + DefaultIDs []*big.Big ) func init() { @@ -36,7 +36,7 @@ func init() { log.Fatalf("failed to read %q: %v", path, err) } var config = struct { - ChainID *utils.Big + ChainID *big.Big Chain }{} @@ -61,13 +61,13 @@ func init() { defaults[id] = config.Chain defaultNames[id] = strings.ReplaceAll(strings.TrimSuffix(fe.Name(), ".toml"), "_", " ") } - slices.SortFunc(DefaultIDs, func(a, b *utils.Big) int { + slices.SortFunc(DefaultIDs, func(a, b *big.Big) int { return a.Cmp(b) }) } // DefaultsNamed returns the default Chain values, optionally for the given chainID, as well as a name if the chainID is known. -func DefaultsNamed(chainID *utils.Big) (c Chain, name string) { +func DefaultsNamed(chainID *big.Big) (c Chain, name string) { c.SetFrom(&fallback) if chainID == nil { return @@ -82,7 +82,7 @@ func DefaultsNamed(chainID *utils.Big) (c Chain, name string) { // Defaults returns a Chain based on the defaults for chainID and fields from with, applied in order so later Chains // override earlier ones. -func Defaults(chainID *utils.Big, with ...*Chain) Chain { +func Defaults(chainID *big.Big, with ...*Chain) Chain { c, _ := DefaultsNamed(chainID) for _, w := range with { c.SetFrom(w) @@ -90,7 +90,7 @@ func Defaults(chainID *utils.Big, with ...*Chain) Chain { return c } -func ChainTypeForID(chainID *utils.Big) (config.ChainType, bool) { +func ChainTypeForID(chainID *big.Big) (config.ChainType, bool) { s := chainID.String() if d, ok := defaults[s]; ok { if d.ChainType == nil { diff --git a/core/chains/evm/forwarders/forwarder.go b/core/chains/evm/forwarders/forwarder.go index 0221c39e0a6..a0f6334a2c7 100644 --- a/core/chains/evm/forwarders/forwarder.go +++ b/core/chains/evm/forwarders/forwarder.go @@ -5,14 +5,14 @@ import ( "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/chainlink/v2/core/utils" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" ) // Forwarder is the struct for Forwarder Addresses type Forwarder struct { ID int64 Address common.Address - EVMChainID utils.Big + EVMChainID big.Big CreatedAt time.Time UpdatedAt time.Time } diff --git a/core/chains/evm/forwarders/forwarder_manager.go b/core/chains/evm/forwarders/forwarder_manager.go index eaf0c32afe3..03792966fef 100644 --- a/core/chains/evm/forwarders/forwarder_manager.go +++ b/core/chains/evm/forwarders/forwarder_manager.go @@ -14,15 +14,16 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmlogpoller "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_receiver" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/offchain_aggregator_wrapper" "github.com/smartcontractkit/chainlink/v2/core/services/pg" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) var forwardABI = evmtypes.MustGetABI(authorized_forwarder.AuthorizedForwarderABI).Methods["forward"] @@ -79,7 +80,7 @@ func (f *FwdMgr) Start(ctx context.Context) error { f.logger.Debug("Initializing EVM forwarder manager") chainId := f.evmClient.ConfiguredChainID() - fwdrs, err := f.ORM.FindForwardersByChain(utils.Big(*chainId)) + fwdrs, err := f.ORM.FindForwardersByChain(big.Big(*chainId)) if err != nil { return errors.Wrapf(err, "Failed to retrieve forwarders for chain %d", chainId) } @@ -112,7 +113,7 @@ func FilterName(addr common.Address) string { func (f *FwdMgr) ForwarderFor(addr common.Address) (forwarder common.Address, err error) { // Gets forwarders for current chain. - fwdrs, err := f.ORM.FindForwardersByChain(utils.Big(*f.evmClient.ConfiguredChainID())) + fwdrs, err := f.ORM.FindForwardersByChain(big.Big(*f.evmClient.ConfiguredChainID())) if err != nil { return common.Address{}, err } diff --git a/core/chains/evm/forwarders/forwarder_manager_test.go b/core/chains/evm/forwarders/forwarder_manager_test.go index 1da638e743d..5ef150aa5c3 100644 --- a/core/chains/evm/forwarders/forwarder_manager_test.go +++ b/core/chains/evm/forwarders/forwarder_manager_test.go @@ -12,10 +12,13 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/utils" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_receiver" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/operator_wrapper" @@ -24,7 +27,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/pg" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) var GetAuthorisedSendersABI = evmtypes.MustGetABI(authorized_receiver.AuthorizedReceiverABI).Methods["getAuthorizedSenders"] @@ -62,9 +64,9 @@ func TestFwdMgr_MaybeForwardTransaction(t *testing.T) { fwdMgr := forwarders.NewFwdMgr(db, evmClient, lp, lggr, evmcfg.EVM(), evmcfg.Database()) fwdMgr.ORM = forwarders.NewORM(db, logger.Test(t), cfg.Database()) - fwd, err := fwdMgr.ORM.CreateForwarder(forwarderAddr, utils.Big(*testutils.FixtureChainID)) + fwd, err := fwdMgr.ORM.CreateForwarder(forwarderAddr, ubig.Big(*testutils.FixtureChainID)) require.NoError(t, err) - lst, err := fwdMgr.ORM.FindForwardersByChain(utils.Big(*testutils.FixtureChainID)) + lst, err := fwdMgr.ORM.FindForwardersByChain(ubig.Big(*testutils.FixtureChainID)) require.NoError(t, err) require.Equal(t, len(lst), 1) require.Equal(t, lst[0].Address, forwarderAddr) @@ -115,9 +117,9 @@ func TestFwdMgr_AccountUnauthorizedToForward_SkipsForwarding(t *testing.T) { fwdMgr := forwarders.NewFwdMgr(db, evmClient, lp, lggr, evmcfg.EVM(), evmcfg.Database()) fwdMgr.ORM = forwarders.NewORM(db, logger.Test(t), cfg.Database()) - _, err = fwdMgr.ORM.CreateForwarder(forwarderAddr, utils.Big(*testutils.FixtureChainID)) + _, err = fwdMgr.ORM.CreateForwarder(forwarderAddr, ubig.Big(*testutils.FixtureChainID)) require.NoError(t, err) - lst, err := fwdMgr.ORM.FindForwardersByChain(utils.Big(*testutils.FixtureChainID)) + lst, err := fwdMgr.ORM.FindForwardersByChain(ubig.Big(*testutils.FixtureChainID)) require.NoError(t, err) require.Equal(t, len(lst), 1) require.Equal(t, lst[0].Address, forwarderAddr) diff --git a/core/chains/evm/forwarders/mocks/orm.go b/core/chains/evm/forwarders/mocks/orm.go index c06a04b8eb1..691fbce8e9c 100644 --- a/core/chains/evm/forwarders/mocks/orm.go +++ b/core/chains/evm/forwarders/mocks/orm.go @@ -4,12 +4,13 @@ package mocks import ( common "github.com/ethereum/go-ethereum/common" + big "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" + forwarders "github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders" + mock "github.com/stretchr/testify/mock" pg "github.com/smartcontractkit/chainlink/v2/core/services/pg" - - utils "github.com/smartcontractkit/chainlink/v2/core/utils" ) // ORM is an autogenerated mock type for the ORM type @@ -18,7 +19,7 @@ type ORM struct { } // CreateForwarder provides a mock function with given fields: addr, evmChainId -func (_m *ORM) CreateForwarder(addr common.Address, evmChainId utils.Big) (forwarders.Forwarder, error) { +func (_m *ORM) CreateForwarder(addr common.Address, evmChainId big.Big) (forwarders.Forwarder, error) { ret := _m.Called(addr, evmChainId) if len(ret) == 0 { @@ -27,16 +28,16 @@ func (_m *ORM) CreateForwarder(addr common.Address, evmChainId utils.Big) (forwa var r0 forwarders.Forwarder var r1 error - if rf, ok := ret.Get(0).(func(common.Address, utils.Big) (forwarders.Forwarder, error)); ok { + if rf, ok := ret.Get(0).(func(common.Address, big.Big) (forwarders.Forwarder, error)); ok { return rf(addr, evmChainId) } - if rf, ok := ret.Get(0).(func(common.Address, utils.Big) forwarders.Forwarder); ok { + if rf, ok := ret.Get(0).(func(common.Address, big.Big) forwarders.Forwarder); ok { r0 = rf(addr, evmChainId) } else { r0 = ret.Get(0).(forwarders.Forwarder) } - if rf, ok := ret.Get(1).(func(common.Address, utils.Big) error); ok { + if rf, ok := ret.Get(1).(func(common.Address, big.Big) error); ok { r1 = rf(addr, evmChainId) } else { r1 = ret.Error(1) @@ -101,7 +102,7 @@ func (_m *ORM) FindForwarders(offset int, limit int) ([]forwarders.Forwarder, in } // FindForwardersByChain provides a mock function with given fields: evmChainId -func (_m *ORM) FindForwardersByChain(evmChainId utils.Big) ([]forwarders.Forwarder, error) { +func (_m *ORM) FindForwardersByChain(evmChainId big.Big) ([]forwarders.Forwarder, error) { ret := _m.Called(evmChainId) if len(ret) == 0 { @@ -110,10 +111,10 @@ func (_m *ORM) FindForwardersByChain(evmChainId utils.Big) ([]forwarders.Forward var r0 []forwarders.Forwarder var r1 error - if rf, ok := ret.Get(0).(func(utils.Big) ([]forwarders.Forwarder, error)); ok { + if rf, ok := ret.Get(0).(func(big.Big) ([]forwarders.Forwarder, error)); ok { return rf(evmChainId) } - if rf, ok := ret.Get(0).(func(utils.Big) []forwarders.Forwarder); ok { + if rf, ok := ret.Get(0).(func(big.Big) []forwarders.Forwarder); ok { r0 = rf(evmChainId) } else { if ret.Get(0) != nil { @@ -121,7 +122,7 @@ func (_m *ORM) FindForwardersByChain(evmChainId utils.Big) ([]forwarders.Forward } } - if rf, ok := ret.Get(1).(func(utils.Big) error); ok { + if rf, ok := ret.Get(1).(func(big.Big) error); ok { r1 = rf(evmChainId) } else { r1 = ret.Error(1) @@ -131,7 +132,7 @@ func (_m *ORM) FindForwardersByChain(evmChainId utils.Big) ([]forwarders.Forward } // FindForwardersInListByChain provides a mock function with given fields: evmChainId, addrs -func (_m *ORM) FindForwardersInListByChain(evmChainId utils.Big, addrs []common.Address) ([]forwarders.Forwarder, error) { +func (_m *ORM) FindForwardersInListByChain(evmChainId big.Big, addrs []common.Address) ([]forwarders.Forwarder, error) { ret := _m.Called(evmChainId, addrs) if len(ret) == 0 { @@ -140,10 +141,10 @@ func (_m *ORM) FindForwardersInListByChain(evmChainId utils.Big, addrs []common. var r0 []forwarders.Forwarder var r1 error - if rf, ok := ret.Get(0).(func(utils.Big, []common.Address) ([]forwarders.Forwarder, error)); ok { + if rf, ok := ret.Get(0).(func(big.Big, []common.Address) ([]forwarders.Forwarder, error)); ok { return rf(evmChainId, addrs) } - if rf, ok := ret.Get(0).(func(utils.Big, []common.Address) []forwarders.Forwarder); ok { + if rf, ok := ret.Get(0).(func(big.Big, []common.Address) []forwarders.Forwarder); ok { r0 = rf(evmChainId, addrs) } else { if ret.Get(0) != nil { @@ -151,7 +152,7 @@ func (_m *ORM) FindForwardersInListByChain(evmChainId utils.Big, addrs []common. } } - if rf, ok := ret.Get(1).(func(utils.Big, []common.Address) error); ok { + if rf, ok := ret.Get(1).(func(big.Big, []common.Address) error); ok { r1 = rf(evmChainId, addrs) } else { r1 = ret.Error(1) diff --git a/core/chains/evm/forwarders/orm.go b/core/chains/evm/forwarders/orm.go index 104e2574252..2a455360190 100644 --- a/core/chains/evm/forwarders/orm.go +++ b/core/chains/evm/forwarders/orm.go @@ -8,18 +8,18 @@ import ( "github.com/pkg/errors" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/services/pg" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) //go:generate mockery --quiet --name ORM --output ./mocks/ --case=underscore type ORM interface { - CreateForwarder(addr common.Address, evmChainId utils.Big) (fwd Forwarder, err error) + CreateForwarder(addr common.Address, evmChainId big.Big) (fwd Forwarder, err error) FindForwarders(offset, limit int) ([]Forwarder, int, error) - FindForwardersByChain(evmChainId utils.Big) ([]Forwarder, error) + FindForwardersByChain(evmChainId big.Big) ([]Forwarder, error) DeleteForwarder(id int64, cleanup func(tx pg.Queryer, evmChainId int64, addr common.Address) error) error - FindForwardersInListByChain(evmChainId utils.Big, addrs []common.Address) ([]Forwarder, error) + FindForwardersInListByChain(evmChainId big.Big, addrs []common.Address) ([]Forwarder, error) } type orm struct { @@ -33,7 +33,7 @@ func NewORM(db *sqlx.DB, lggr logger.Logger, cfg pg.QConfig) *orm { } // CreateForwarder creates the Forwarder address associated with the current EVM chain id. -func (o *orm) CreateForwarder(addr common.Address, evmChainId utils.Big) (fwd Forwarder, err error) { +func (o *orm) CreateForwarder(addr common.Address, evmChainId big.Big) (fwd Forwarder, err error) { sql := `INSERT INTO evm.forwarders (address, evm_chain_id, created_at, updated_at) VALUES ($1, $2, now(), now()) RETURNING *` err = o.q.Get(&fwd, sql, addr, evmChainId) return fwd, err @@ -93,13 +93,13 @@ func (o *orm) FindForwarders(offset, limit int) (fwds []Forwarder, count int, er } // FindForwardersByChain returns all forwarder addresses for a chain. -func (o *orm) FindForwardersByChain(evmChainId utils.Big) (fwds []Forwarder, err error) { +func (o *orm) FindForwardersByChain(evmChainId big.Big) (fwds []Forwarder, err error) { sql := `SELECT * FROM evm.forwarders where evm_chain_id = $1 ORDER BY created_at DESC, id DESC` err = o.q.Select(&fwds, sql, evmChainId) return } -func (o *orm) FindForwardersInListByChain(evmChainId utils.Big, addrs []common.Address) ([]Forwarder, error) { +func (o *orm) FindForwardersInListByChain(evmChainId big.Big, addrs []common.Address) ([]Forwarder, error) { var fwdrs []Forwarder arg := map[string]interface{}{ diff --git a/core/chains/evm/forwarders/orm_test.go b/core/chains/evm/forwarders/orm_test.go index ba9664c196a..e95ac3778c6 100644 --- a/core/chains/evm/forwarders/orm_test.go +++ b/core/chains/evm/forwarders/orm_test.go @@ -10,10 +10,10 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/pg" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/jmoiron/sqlx" ) @@ -42,7 +42,7 @@ func Test_DeleteForwarder(t *testing.T) { addr := testutils.NewAddress() chainID := testutils.FixtureChainID - fwd, err := orm.CreateForwarder(addr, *utils.NewBig(chainID)) + fwd, err := orm.CreateForwarder(addr, *big.New(chainID)) require.NoError(t, err) assert.Equal(t, addr, fwd.Address) diff --git a/core/chains/evm/gas/block_history_estimator_test.go b/core/chains/evm/gas/block_history_estimator_test.go index d3edf212b6a..43ea3e0bb79 100644 --- a/core/chains/evm/gas/block_history_estimator_test.go +++ b/core/chains/evm/gas/block_history_estimator_test.go @@ -25,6 +25,7 @@ import ( evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" @@ -429,7 +430,7 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { elems[1].Result = &b42 }) - head := evmtypes.NewHead(big.NewInt(44), b44.Hash, b43.Hash, uint64(time.Now().Unix()), utils.NewBig(&cltest.FixtureChainID)) + head := evmtypes.NewHead(big.NewInt(44), b44.Hash, b43.Hash, uint64(time.Now().Unix()), ubig.New(&cltest.FixtureChainID)) err = bhe.FetchBlocks(testutils.Context(t), &head) require.NoError(t, err) @@ -493,8 +494,8 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { elems[1].Result = &b2 }) - head2 := evmtypes.NewHead(big.NewInt(2), b2.Hash, b1.Hash, uint64(time.Now().Unix()), utils.NewBig(&cltest.FixtureChainID)) - head3 := evmtypes.NewHead(big.NewInt(3), b3.Hash, b2.Hash, uint64(time.Now().Unix()), utils.NewBig(&cltest.FixtureChainID)) + head2 := evmtypes.NewHead(big.NewInt(2), b2.Hash, b1.Hash, uint64(time.Now().Unix()), ubig.New(&cltest.FixtureChainID)) + head3 := evmtypes.NewHead(big.NewInt(3), b3.Hash, b2.Hash, uint64(time.Now().Unix()), ubig.New(&cltest.FixtureChainID)) head3.Parent = &head2 err := bhe.FetchBlocks(testutils.Context(t), &head3) require.NoError(t, err) @@ -546,8 +547,8 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { gas.SetRollingBlockHistory(bhe, blocks) // RE-ORG, head2 and head3 have different hash than saved b2 and b3 - head2 := evmtypes.NewHead(big.NewInt(2), utils.NewHash(), b1.Hash, uint64(time.Now().Unix()), utils.NewBig(&cltest.FixtureChainID)) - head3 := evmtypes.NewHead(big.NewInt(3), utils.NewHash(), head2.Hash, uint64(time.Now().Unix()), utils.NewBig(&cltest.FixtureChainID)) + head2 := evmtypes.NewHead(big.NewInt(2), utils.NewHash(), b1.Hash, uint64(time.Now().Unix()), ubig.New(&cltest.FixtureChainID)) + head3 := evmtypes.NewHead(big.NewInt(3), utils.NewHash(), head2.Hash, uint64(time.Now().Unix()), ubig.New(&cltest.FixtureChainID)) head3.Parent = &head2 ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { @@ -617,8 +618,8 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { gas.SetRollingBlockHistory(bhe, blocks) // head2 and head3 have identical hash to saved blocks - head2 := evmtypes.NewHead(big.NewInt(2), b2.Hash, b1.Hash, uint64(time.Now().Unix()), utils.NewBig(&cltest.FixtureChainID)) - head3 := evmtypes.NewHead(big.NewInt(3), b3.Hash, head2.Hash, uint64(time.Now().Unix()), utils.NewBig(&cltest.FixtureChainID)) + head2 := evmtypes.NewHead(big.NewInt(2), b2.Hash, b1.Hash, uint64(time.Now().Unix()), ubig.New(&cltest.FixtureChainID)) + head3 := evmtypes.NewHead(big.NewInt(3), b3.Hash, head2.Hash, uint64(time.Now().Unix()), ubig.New(&cltest.FixtureChainID)) head3.Parent = &head2 err := bhe.FetchBlocks(testutils.Context(t), &head3) diff --git a/core/chains/evm/headtracker/head_broadcaster_test.go b/core/chains/evm/headtracker/head_broadcaster_test.go index b9fab9cdd48..21c864eda69 100644 --- a/core/chains/evm/headtracker/head_broadcaster_test.go +++ b/core/chains/evm/headtracker/head_broadcaster_test.go @@ -19,6 +19,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" @@ -84,7 +85,7 @@ func TestHeadBroadcaster_Subscribe(t *testing.T) { assert.Equal(t, (*evmtypes.Head)(nil), latest1) headers := <-chchHeaders - h := evmtypes.Head{Number: 1, Hash: utils.NewHash(), ParentHash: utils.NewHash(), EVMChainID: utils.NewBig(&cltest.FixtureChainID)} + h := evmtypes.Head{Number: 1, Hash: utils.NewHash(), ParentHash: utils.NewHash(), EVMChainID: big.New(&cltest.FixtureChainID)} headers <- &h g.Eventually(checker1.OnNewLongestChainCount).Should(gomega.Equal(int32(1))) @@ -95,7 +96,7 @@ func TestHeadBroadcaster_Subscribe(t *testing.T) { unsubscribe1() - headers <- &evmtypes.Head{Number: 2, Hash: utils.NewHash(), ParentHash: h.Hash, EVMChainID: utils.NewBig(&cltest.FixtureChainID)} + headers <- &evmtypes.Head{Number: 2, Hash: utils.NewHash(), ParentHash: h.Hash, EVMChainID: big.New(&cltest.FixtureChainID)} g.Eventually(checker2.OnNewLongestChainCount).Should(gomega.Equal(int32(1))) } diff --git a/core/chains/evm/headtracker/head_tracker_test.go b/core/chains/evm/headtracker/head_tracker_test.go index d8abb1328ac..67e76aee52b 100644 --- a/core/chains/evm/headtracker/head_tracker_test.go +++ b/core/chains/evm/headtracker/head_tracker_test.go @@ -29,6 +29,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" @@ -258,7 +259,7 @@ func TestHeadTracker_CallsHeadTrackableCallbacks(t *testing.T) { assert.Equal(t, int32(0), checker.OnNewLongestChainCount()) headers := <-chchHeaders - headers.TrySend(&evmtypes.Head{Number: 1, Hash: utils.NewHash(), EVMChainID: utils.NewBig(&cltest.FixtureChainID)}) + headers.TrySend(&evmtypes.Head{Number: 1, Hash: utils.NewHash(), EVMChainID: ubig.New(&cltest.FixtureChainID)}) g.Eventually(checker.OnNewLongestChainCount).Should(gomega.Equal(int32(1))) ht.Stop(t) @@ -719,7 +720,7 @@ func TestHeadTracker_Backfill(t *testing.T) { ParentHash: gethCommon.BigToHash(big.NewInt(0)), Time: now, } - head0 := evmtypes.NewHead(gethHead0.Number, utils.NewHash(), gethHead0.ParentHash, gethHead0.Time, utils.NewBig(&cltest.FixtureChainID)) + head0 := evmtypes.NewHead(gethHead0.Number, utils.NewHash(), gethHead0.ParentHash, gethHead0.Time, ubig.New(&cltest.FixtureChainID)) h1 := *cltest.Head(1) h1.ParentHash = head0.Hash @@ -729,7 +730,7 @@ func TestHeadTracker_Backfill(t *testing.T) { ParentHash: utils.NewHash(), Time: now, } - head8 := evmtypes.NewHead(gethHead8.Number, utils.NewHash(), gethHead8.ParentHash, gethHead8.Time, utils.NewBig(&cltest.FixtureChainID)) + head8 := evmtypes.NewHead(gethHead8.Number, utils.NewHash(), gethHead8.ParentHash, gethHead8.Time, ubig.New(&cltest.FixtureChainID)) h9 := *cltest.Head(9) h9.ParentHash = head8.Hash @@ -739,7 +740,7 @@ func TestHeadTracker_Backfill(t *testing.T) { ParentHash: h9.Hash, Time: now, } - head10 := evmtypes.NewHead(gethHead10.Number, utils.NewHash(), gethHead10.ParentHash, gethHead10.Time, utils.NewBig(&cltest.FixtureChainID)) + head10 := evmtypes.NewHead(gethHead10.Number, utils.NewHash(), gethHead10.ParentHash, gethHead10.Time, ubig.New(&cltest.FixtureChainID)) h11 := *cltest.Head(11) h11.ParentHash = head10.Hash diff --git a/core/chains/evm/headtracker/heads_test.go b/core/chains/evm/headtracker/heads_test.go index 7da6b1cc9ba..11c1bfd4f7a 100644 --- a/core/chains/evm/headtracker/heads_test.go +++ b/core/chains/evm/headtracker/heads_test.go @@ -10,6 +10,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/utils" ) @@ -77,11 +78,11 @@ func TestHeads_AddHeads(t *testing.T) { var parentHash common.Hash for i := 0; i < 5; i++ { hash := utils.NewHash() - h := evmtypes.NewHead(big.NewInt(int64(i)), hash, parentHash, uint64(time.Now().Unix()), utils.NewBigI(0)) + h := evmtypes.NewHead(big.NewInt(int64(i)), hash, parentHash, uint64(time.Now().Unix()), ubig.NewI(0)) testHeads = append(testHeads, &h) if i == 2 { // uncled block - h := evmtypes.NewHead(big.NewInt(int64(i)), uncleHash, parentHash, uint64(time.Now().Unix()), utils.NewBigI(0)) + h := evmtypes.NewHead(big.NewInt(int64(i)), uncleHash, parentHash, uint64(time.Now().Unix()), ubig.NewI(0)) testHeads = append(testHeads, &h) } parentHash = hash diff --git a/core/chains/evm/headtracker/orm.go b/core/chains/evm/headtracker/orm.go index 88d569b9a21..859f6764b63 100644 --- a/core/chains/evm/headtracker/orm.go +++ b/core/chains/evm/headtracker/orm.go @@ -12,8 +12,8 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/services/pg" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) type ORM interface { @@ -32,11 +32,11 @@ type ORM interface { type orm struct { q pg.Q - chainID utils.Big + chainID ubig.Big } func NewORM(db *sqlx.DB, lggr logger.Logger, cfg pg.QConfig, chainID big.Int) ORM { - return &orm{pg.NewQ(db, logger.Named(lggr, "HeadTrackerORM"), cfg), utils.Big(chainID)} + return &orm{pg.NewQ(db, logger.Named(lggr, "HeadTrackerORM"), cfg), ubig.Big(chainID)} } func (orm *orm) IdempotentInsertHead(ctx context.Context, head *evmtypes.Head) error { diff --git a/core/chains/evm/log/orm.go b/core/chains/evm/log/orm.go index a2bcab6e785..3feb4bb836b 100644 --- a/core/chains/evm/log/orm.go +++ b/core/chains/evm/log/orm.go @@ -12,6 +12,7 @@ import ( "github.com/jmoiron/sqlx" "github.com/smartcontractkit/chainlink-common/pkg/logger" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/utils" ) @@ -48,13 +49,13 @@ type ORM interface { type orm struct { q pg.Q - evmChainID utils.Big + evmChainID ubig.Big } var _ ORM = (*orm)(nil) func NewORM(db *sqlx.DB, lggr logger.Logger, cfg pg.QConfig, evmChainID big.Int) *orm { - return &orm{pg.NewQ(db, lggr, cfg), *utils.NewBig(&evmChainID)} + return &orm{pg.NewQ(db, lggr, cfg), *ubig.New(&evmChainID)} } func (o *orm) WasBroadcastConsumed(blockHash common.Hash, logIndex uint, jobID int32, qopts ...pg.QOpt) (consumed bool, err error) { @@ -128,7 +129,7 @@ func (o *orm) MarkBroadcastsConsumed(blockHashes []common.Hash, blockNumbers []u BlockNumber uint64 `db:"blockNumber"` LogIndex uint `db:"logIndex"` JobID int32 `db:"jobID"` - ChainID utils.Big `db:"chainID"` + ChainID ubig.Big `db:"chainID"` } inputs := make([]input, len(blockHashes)) query := ` diff --git a/core/chains/evm/logpoller/log_poller.go b/core/chains/evm/logpoller/log_poller.go index 1cf1cf42beb..77b80253591 100644 --- a/core/chains/evm/logpoller/log_poller.go +++ b/core/chains/evm/logpoller/log_poller.go @@ -26,6 +26,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/utils" ) @@ -608,7 +609,7 @@ func convertLogs(logs []types.Log, blocks []LogPollerBlock, lggr logger.Logger, blockTimestamp = blocks[i].BlockTimestamp } lgs = append(lgs, Log{ - EvmChainId: utils.NewBig(chainID), + EvmChainId: ubig.New(chainID), LogIndex: int64(l.Index), BlockHash: l.BlockHash, // We assume block numbers fit in int64 diff --git a/core/chains/evm/logpoller/log_poller_test.go b/core/chains/evm/logpoller/log_poller_test.go index 6c4dd381b54..ed2d617065b 100644 --- a/core/chains/evm/logpoller/log_poller_test.go +++ b/core/chains/evm/logpoller/log_poller_test.go @@ -30,6 +30,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -62,7 +63,7 @@ func populateDatabase(t testing.TB, o *logpoller.DbORM, chainID *big.Int) (commo blockTimestamp := startDate.Add(time.Duration(j*1000) * time.Hour) logs = append(logs, logpoller.Log{ - EvmChainId: utils.NewBig(chainID), + EvmChainId: ubig.New(chainID), LogIndex: 1, BlockHash: common.HexToHash(fmt.Sprintf("0x%d", i+(1000*j))), BlockNumber: blockNumber, @@ -1341,7 +1342,7 @@ func TestNotifyAfterInsert(t *testing.T) { require.NoError(t, err) log := logpoller.Log{ - EvmChainId: utils.NewBig(chainID), + EvmChainId: ubig.New(chainID), LogIndex: 10, BlockHash: testutils.Random32Byte(), BlockNumber: 100, diff --git a/core/chains/evm/logpoller/models.go b/core/chains/evm/logpoller/models.go index 87ddd079a5b..c5d6f5eab1c 100644 --- a/core/chains/evm/logpoller/models.go +++ b/core/chains/evm/logpoller/models.go @@ -7,13 +7,13 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/lib/pq" - "github.com/smartcontractkit/chainlink/v2/core/utils" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" ) // LogPollerBlock represents an unfinalized block // used for reorg detection when polling. type LogPollerBlock struct { - EvmChainId *utils.Big + EvmChainId *big.Big BlockHash common.Hash // Note geth uses int64 internally https://github.com/ethereum/go-ethereum/blob/f66f1a16b3c480d3a43ac7e8a09ab3e362e96ae4/eth/filters/api.go#L340 BlockNumber int64 @@ -24,7 +24,7 @@ type LogPollerBlock struct { // Log represents an EVM log. type Log struct { - EvmChainId *utils.Big + EvmChainId *big.Big LogIndex int64 BlockHash common.Hash BlockNumber int64 diff --git a/core/chains/evm/logpoller/observability_test.go b/core/chains/evm/logpoller/observability_test.go index 76575f46ca4..749934dc4b5 100644 --- a/core/chains/evm/logpoller/observability_test.go +++ b/core/chains/evm/logpoller/observability_test.go @@ -16,6 +16,7 @@ import ( "github.com/prometheus/client_golang/prometheus/testutil" "github.com/smartcontractkit/chainlink-common/pkg/logger" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/pg" @@ -126,7 +127,7 @@ func generateRandomLogs(chainId, count int) []Log { logs := make([]Log, count) for i := range logs { logs[i] = Log{ - EvmChainId: utils.NewBigI(int64(chainId)), + EvmChainId: ubig.NewI(int64(chainId)), LogIndex: int64(i + 1), BlockHash: utils.RandomBytes32(), BlockNumber: int64(i + 1), diff --git a/core/chains/evm/logpoller/orm.go b/core/chains/evm/logpoller/orm.go index c24d423b253..663c56d10ed 100644 --- a/core/chains/evm/logpoller/orm.go +++ b/core/chains/evm/logpoller/orm.go @@ -12,8 +12,8 @@ import ( "github.com/pkg/errors" "github.com/smartcontractkit/chainlink-common/pkg/logger" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/services/pg" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) // ORM represents the persistent data access layer used by the log poller. At this moment, it's a bit leaky abstraction, because @@ -119,7 +119,7 @@ func (o *DbORM) InsertFilter(filter Filter, qopts ...pg.QOpt) (err error) { // DeleteFilter removes all events,address pairs associated with the Filter func (o *DbORM) DeleteFilter(name string, qopts ...pg.QOpt) error { q := o.q.WithOpts(qopts...) - return q.ExecQ(`DELETE FROM evm.log_poller_filters WHERE name = $1 AND evm_chain_id = $2`, name, utils.NewBig(o.chainID)) + return q.ExecQ(`DELETE FROM evm.log_poller_filters WHERE name = $1 AND evm_chain_id = $2`, name, ubig.New(o.chainID)) } // LoadFiltersForChain returns all filters for this chain @@ -131,7 +131,7 @@ func (o *DbORM) LoadFilters(qopts ...pg.QOpt) (map[string]Filter, error) { ARRAY_AGG(DISTINCT event)::BYTEA[] AS event_sigs, MAX(retention) AS retention FROM evm.log_poller_filters WHERE evm_chain_id = $1 - GROUP BY name`, utils.NewBig(o.chainID)) + GROUP BY name`, ubig.New(o.chainID)) filters := make(map[string]Filter) for _, filter := range rows { filters[filter.Name] = filter @@ -143,7 +143,7 @@ func (o *DbORM) LoadFilters(qopts ...pg.QOpt) (map[string]Filter, error) { func (o *DbORM) SelectBlockByHash(hash common.Hash, qopts ...pg.QOpt) (*LogPollerBlock, error) { q := o.q.WithOpts(qopts...) var b LogPollerBlock - if err := q.Get(&b, `SELECT * FROM evm.log_poller_blocks WHERE block_hash = $1 AND evm_chain_id = $2`, hash, utils.NewBig(o.chainID)); err != nil { + if err := q.Get(&b, `SELECT * FROM evm.log_poller_blocks WHERE block_hash = $1 AND evm_chain_id = $2`, hash, ubig.New(o.chainID)); err != nil { return nil, err } return &b, nil @@ -152,7 +152,7 @@ func (o *DbORM) SelectBlockByHash(hash common.Hash, qopts ...pg.QOpt) (*LogPolle func (o *DbORM) SelectBlockByNumber(n int64, qopts ...pg.QOpt) (*LogPollerBlock, error) { q := o.q.WithOpts(qopts...) var b LogPollerBlock - if err := q.Get(&b, `SELECT * FROM evm.log_poller_blocks WHERE block_number = $1 AND evm_chain_id = $2`, n, utils.NewBig(o.chainID)); err != nil { + if err := q.Get(&b, `SELECT * FROM evm.log_poller_blocks WHERE block_number = $1 AND evm_chain_id = $2`, n, ubig.New(o.chainID)); err != nil { return nil, err } return &b, nil @@ -161,7 +161,7 @@ func (o *DbORM) SelectBlockByNumber(n int64, qopts ...pg.QOpt) (*LogPollerBlock, func (o *DbORM) SelectLatestBlock(qopts ...pg.QOpt) (*LogPollerBlock, error) { q := o.q.WithOpts(qopts...) var b LogPollerBlock - if err := q.Get(&b, `SELECT * FROM evm.log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1`, utils.NewBig(o.chainID)); err != nil { + if err := q.Get(&b, `SELECT * FROM evm.log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1`, ubig.New(o.chainID)); err != nil { return nil, err } return &b, nil @@ -191,7 +191,7 @@ func (o *DbORM) SelectLatestLogByEventSigWithConfs(eventSig common.Hash, address // DeleteBlocksBefore delete all blocks before and including end. func (o *DbORM) DeleteBlocksBefore(end int64, qopts ...pg.QOpt) error { q := o.q.WithOpts(qopts...) - _, err := q.Exec(`DELETE FROM evm.log_poller_blocks WHERE block_number <= $1 AND evm_chain_id = $2`, end, utils.NewBig(o.chainID)) + _, err := q.Exec(`DELETE FROM evm.log_poller_blocks WHERE block_number <= $1 AND evm_chain_id = $2`, end, ubig.New(o.chainID)) return err } @@ -241,7 +241,7 @@ func (o *DbORM) DeleteExpiredLogs(qopts ...pg.QOpt) error { ) DELETE FROM evm.logs l USING r WHERE l.evm_chain_id = $1 AND l.address=r.address AND l.event_sig=r.event AND l.created_at <= STATEMENT_TIMESTAMP() - (r.retention / 10^9 * interval '1 second')`, // retention is in nanoseconds (time.Duration aka BIGINT) - utils.NewBig(o.chainID)) + ubig.New(o.chainID)) } // InsertLogs is idempotent to support replays. diff --git a/core/chains/evm/logpoller/orm_test.go b/core/chains/evm/logpoller/orm_test.go index 2a6ebb2c04e..3c54b3cf654 100644 --- a/core/chains/evm/logpoller/orm_test.go +++ b/core/chains/evm/logpoller/orm_test.go @@ -18,6 +18,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" @@ -37,7 +38,7 @@ func GenLog(chainID *big.Int, logIndex int64, blockNum int64, blockHash string, func GenLogWithTimestamp(chainID *big.Int, logIndex int64, blockNum int64, blockHash string, topic1 []byte, address common.Address, blockTimestamp time.Time) logpoller.Log { return logpoller.Log{ - EvmChainId: utils.NewBig(chainID), + EvmChainId: ubig.New(chainID), LogIndex: logIndex, BlockHash: common.HexToHash(blockHash), BlockNumber: blockNum, @@ -52,7 +53,7 @@ func GenLogWithTimestamp(chainID *big.Int, logIndex int64, blockNum int64, block func GenLogWithData(chainID *big.Int, address common.Address, eventSig common.Hash, logIndex int64, blockNum int64, data []byte) logpoller.Log { return logpoller.Log{ - EvmChainId: utils.NewBig(chainID), + EvmChainId: ubig.New(chainID), LogIndex: logIndex, BlockHash: utils.RandomBytes32(), BlockNumber: blockNum, @@ -219,7 +220,7 @@ func TestORM(t *testing.T) { topic2 := common.HexToHash("0x1600") require.NoError(t, o1.InsertLogs([]logpoller.Log{ { - EvmChainId: utils.NewBig(th.ChainID), + EvmChainId: ubig.New(th.ChainID), LogIndex: 1, BlockHash: common.HexToHash("0x1234"), BlockNumber: int64(10), @@ -230,7 +231,7 @@ func TestORM(t *testing.T) { Data: []byte("hello"), }, { - EvmChainId: utils.NewBig(th.ChainID), + EvmChainId: ubig.New(th.ChainID), LogIndex: 2, BlockHash: common.HexToHash("0x1234"), BlockNumber: int64(11), @@ -241,7 +242,7 @@ func TestORM(t *testing.T) { Data: []byte("hello"), }, { - EvmChainId: utils.NewBig(th.ChainID), + EvmChainId: ubig.New(th.ChainID), LogIndex: 3, BlockHash: common.HexToHash("0x1234"), BlockNumber: int64(12), @@ -252,7 +253,7 @@ func TestORM(t *testing.T) { Data: []byte("hello"), }, { - EvmChainId: utils.NewBig(th.ChainID), + EvmChainId: ubig.New(th.ChainID), LogIndex: 4, BlockHash: common.HexToHash("0x1234"), BlockNumber: int64(13), @@ -263,7 +264,7 @@ func TestORM(t *testing.T) { Data: []byte("hello"), }, { - EvmChainId: utils.NewBig(th.ChainID), + EvmChainId: ubig.New(th.ChainID), LogIndex: 5, BlockHash: common.HexToHash("0x1234"), BlockNumber: int64(14), @@ -274,7 +275,7 @@ func TestORM(t *testing.T) { Data: []byte("hello2"), }, { - EvmChainId: utils.NewBig(th.ChainID), + EvmChainId: ubig.New(th.ChainID), LogIndex: 6, BlockHash: common.HexToHash("0x1234"), BlockNumber: int64(15), @@ -285,7 +286,7 @@ func TestORM(t *testing.T) { Data: []byte("hello2"), }, { - EvmChainId: utils.NewBig(th.ChainID), + EvmChainId: ubig.New(th.ChainID), LogIndex: 7, BlockHash: common.HexToHash("0x1237"), BlockNumber: int64(16), @@ -296,7 +297,7 @@ func TestORM(t *testing.T) { Data: []byte("hello short retention"), }, { - EvmChainId: utils.NewBig(th.ChainID), + EvmChainId: ubig.New(th.ChainID), LogIndex: 8, BlockHash: common.HexToHash("0x1238"), BlockNumber: int64(17), @@ -451,7 +452,7 @@ func insertLogsTopicValueRange(t *testing.T, chainID *big.Int, o *logpoller.DbOR var lgs []logpoller.Log for i := start; i <= stop; i++ { lgs = append(lgs, logpoller.Log{ - EvmChainId: utils.NewBig(chainID), + EvmChainId: ubig.New(chainID), LogIndex: int64(i), BlockHash: common.HexToHash("0x1234"), BlockNumber: int64(blockNumber), @@ -536,7 +537,7 @@ func TestORM_SelectIndexedLogsByTxHash(t *testing.T) { require.NoError(t, o1.InsertBlock(common.HexToHash("0x1"), 1, time.Now(), 0)) logs := []logpoller.Log{ { - EvmChainId: utils.NewBig(th.ChainID), + EvmChainId: ubig.New(th.ChainID), LogIndex: int64(0), BlockHash: common.HexToHash("0x1"), BlockNumber: int64(1), @@ -547,7 +548,7 @@ func TestORM_SelectIndexedLogsByTxHash(t *testing.T) { Data: logpoller.EvmWord(1).Bytes(), }, { - EvmChainId: utils.NewBig(th.ChainID), + EvmChainId: ubig.New(th.ChainID), LogIndex: int64(1), BlockHash: common.HexToHash("0x1"), BlockNumber: int64(1), @@ -559,7 +560,7 @@ func TestORM_SelectIndexedLogsByTxHash(t *testing.T) { }, // Different txHash { - EvmChainId: utils.NewBig(th.ChainID), + EvmChainId: ubig.New(th.ChainID), LogIndex: int64(2), BlockHash: common.HexToHash("0x1"), BlockNumber: int64(1), @@ -571,7 +572,7 @@ func TestORM_SelectIndexedLogsByTxHash(t *testing.T) { }, // Different eventSig { - EvmChainId: utils.NewBig(th.ChainID), + EvmChainId: ubig.New(th.ChainID), LogIndex: int64(3), BlockHash: common.HexToHash("0x1"), BlockNumber: int64(1), @@ -600,7 +601,7 @@ func TestORM_DataWords(t *testing.T) { require.NoError(t, o1.InsertBlock(common.HexToHash("0x1"), 1, time.Now(), 0)) require.NoError(t, o1.InsertLogs([]logpoller.Log{ { - EvmChainId: utils.NewBig(th.ChainID), + EvmChainId: ubig.New(th.ChainID), LogIndex: int64(0), BlockHash: common.HexToHash("0x1"), BlockNumber: int64(1), @@ -612,7 +613,7 @@ func TestORM_DataWords(t *testing.T) { }, { // In block 2, unconfirmed to start - EvmChainId: utils.NewBig(th.ChainID), + EvmChainId: ubig.New(th.ChainID), LogIndex: int64(1), BlockHash: common.HexToHash("0x2"), BlockNumber: int64(2), @@ -667,7 +668,7 @@ func TestORM_SelectLogsWithSigsByBlockRangeFilter(t *testing.T) { sourceAddr := common.HexToAddress("0x12345") inputLogs := []logpoller.Log{ { - EvmChainId: utils.NewBig(th.ChainID), + EvmChainId: ubig.New(th.ChainID), LogIndex: 1, BlockHash: common.HexToHash("0x1234"), BlockNumber: int64(10), @@ -678,7 +679,7 @@ func TestORM_SelectLogsWithSigsByBlockRangeFilter(t *testing.T) { Data: []byte("hello1"), }, { - EvmChainId: utils.NewBig(th.ChainID), + EvmChainId: ubig.New(th.ChainID), LogIndex: 2, BlockHash: common.HexToHash("0x1235"), BlockNumber: int64(11), @@ -689,7 +690,7 @@ func TestORM_SelectLogsWithSigsByBlockRangeFilter(t *testing.T) { Data: []byte("hello2"), }, { - EvmChainId: utils.NewBig(th.ChainID), + EvmChainId: ubig.New(th.ChainID), LogIndex: 3, BlockHash: common.HexToHash("0x1236"), BlockNumber: int64(12), @@ -700,7 +701,7 @@ func TestORM_SelectLogsWithSigsByBlockRangeFilter(t *testing.T) { Data: []byte("hello3"), }, { - EvmChainId: utils.NewBig(th.ChainID), + EvmChainId: ubig.New(th.ChainID), LogIndex: 4, BlockHash: common.HexToHash("0x1237"), BlockNumber: int64(13), @@ -711,7 +712,7 @@ func TestORM_SelectLogsWithSigsByBlockRangeFilter(t *testing.T) { Data: []byte("hello4"), }, { - EvmChainId: utils.NewBig(th.ChainID), + EvmChainId: ubig.New(th.ChainID), LogIndex: 5, BlockHash: common.HexToHash("0x1238"), BlockNumber: int64(14), @@ -722,7 +723,7 @@ func TestORM_SelectLogsWithSigsByBlockRangeFilter(t *testing.T) { Data: []byte("hello5"), }, { - EvmChainId: utils.NewBig(th.ChainID), + EvmChainId: ubig.New(th.ChainID), LogIndex: 6, BlockHash: common.HexToHash("0x1239"), BlockNumber: int64(15), @@ -827,7 +828,7 @@ func BenchmarkLogs(b *testing.B) { addr := common.HexToAddress("0x1234") for i := 0; i < 10_000; i++ { lgs = append(lgs, logpoller.Log{ - EvmChainId: utils.NewBig(th.ChainID), + EvmChainId: ubig.New(th.ChainID), LogIndex: int64(i), BlockHash: common.HexToHash("0x1"), BlockNumber: 1, @@ -866,7 +867,7 @@ func TestSelectLogsWithSigsExcluding(t *testing.T) { //Insert two logs that mimics an oracle request from 2 different addresses (matching will be on topic index 1) require.NoError(t, orm.InsertLogs([]logpoller.Log{ { - EvmChainId: (*utils.Big)(th.ChainID), + EvmChainId: (*ubig.Big)(th.ChainID), LogIndex: 1, BlockHash: common.HexToHash("0x1"), BlockNumber: 1, @@ -878,7 +879,7 @@ func TestSelectLogsWithSigsExcluding(t *testing.T) { Data: []byte("requestID-A1"), }, { - EvmChainId: (*utils.Big)(th.ChainID), + EvmChainId: (*ubig.Big)(th.ChainID), LogIndex: 2, BlockHash: common.HexToHash("0x1"), BlockNumber: 1, @@ -907,7 +908,7 @@ func TestSelectLogsWithSigsExcluding(t *testing.T) { //Insert a log that mimics response for requestID-A1 require.NoError(t, orm.InsertLogs([]logpoller.Log{ { - EvmChainId: (*utils.Big)(th.ChainID), + EvmChainId: (*ubig.Big)(th.ChainID), LogIndex: 3, BlockHash: common.HexToHash("0x2"), BlockNumber: 2, @@ -935,7 +936,7 @@ func TestSelectLogsWithSigsExcluding(t *testing.T) { //Insert 3 request from addressC (matching will be on topic index 3) require.NoError(t, orm.InsertLogs([]logpoller.Log{ { - EvmChainId: (*utils.Big)(th.ChainID), + EvmChainId: (*ubig.Big)(th.ChainID), LogIndex: 5, BlockHash: common.HexToHash("0x2"), BlockNumber: 3, @@ -947,7 +948,7 @@ func TestSelectLogsWithSigsExcluding(t *testing.T) { Data: []byte("requestID-C1"), }, { - EvmChainId: (*utils.Big)(th.ChainID), + EvmChainId: (*ubig.Big)(th.ChainID), LogIndex: 6, BlockHash: common.HexToHash("0x2"), BlockNumber: 3, @@ -958,7 +959,7 @@ func TestSelectLogsWithSigsExcluding(t *testing.T) { TxHash: common.HexToHash("0x0002"), Data: []byte("requestID-C2"), }, { - EvmChainId: (*utils.Big)(th.ChainID), + EvmChainId: (*ubig.Big)(th.ChainID), LogIndex: 7, BlockHash: common.HexToHash("0x2"), BlockNumber: 3, @@ -983,7 +984,7 @@ func TestSelectLogsWithSigsExcluding(t *testing.T) { //Fulfill requestID-C2 require.NoError(t, orm.InsertLogs([]logpoller.Log{ { - EvmChainId: (*utils.Big)(th.ChainID), + EvmChainId: (*ubig.Big)(th.ChainID), LogIndex: 8, BlockHash: common.HexToHash("0x3"), BlockNumber: 3, @@ -1006,7 +1007,7 @@ func TestSelectLogsWithSigsExcluding(t *testing.T) { //Fulfill requestID-C3 require.NoError(t, orm.InsertLogs([]logpoller.Log{ { - EvmChainId: (*utils.Big)(th.ChainID), + EvmChainId: (*ubig.Big)(th.ChainID), LogIndex: 9, BlockHash: common.HexToHash("0x3"), BlockNumber: 3, @@ -1041,7 +1042,7 @@ func TestSelectLogsWithSigsExcluding(t *testing.T) { //Fulfill requestID-C3 require.NoError(t, orm.InsertLogs([]logpoller.Log{ { - EvmChainId: (*utils.Big)(th.ChainID), + EvmChainId: (*ubig.Big)(th.ChainID), LogIndex: 10, BlockHash: common.HexToHash("0x2"), BlockNumber: 10, @@ -1533,7 +1534,7 @@ func Benchmark_LogsDataWordBetween(b *testing.B) { data = append(data, logpoller.EvmWord(uint64(numberOfMessagesPerReport*(i+1))).Bytes()...) dbLogs = append(dbLogs, logpoller.Log{ - EvmChainId: utils.NewBig(chainId), + EvmChainId: ubig.New(chainId), LogIndex: int64(i + 1), BlockHash: utils.RandomBytes32(), BlockNumber: int64(i + 1), diff --git a/core/chains/evm/logpoller/query.go b/core/chains/evm/logpoller/query.go index b7fbfade680..a37b15b2b2d 100644 --- a/core/chains/evm/logpoller/query.go +++ b/core/chains/evm/logpoller/query.go @@ -9,7 +9,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/lib/pq" - "github.com/smartcontractkit/chainlink/v2/core/utils" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" ) type bytesProducer interface { @@ -34,7 +34,7 @@ type queryArgs struct { func newQueryArgs(chainId *big.Int) *queryArgs { return &queryArgs{ args: map[string]interface{}{ - "evm_chain_id": utils.NewBig(chainId), + "evm_chain_id": ubig.New(chainId), }, err: []error{}, } diff --git a/core/chains/evm/logpoller/query_test.go b/core/chains/evm/logpoller/query_test.go index e38aeb05819..bc2b20c85c2 100644 --- a/core/chains/evm/logpoller/query_test.go +++ b/core/chains/evm/logpoller/query_test.go @@ -8,6 +8,7 @@ import ( "github.com/lib/pq" "github.com/stretchr/testify/require" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/utils" ) @@ -22,7 +23,7 @@ func Test_QueryArgs(t *testing.T) { name: "valid arguments", queryArgs: newQueryArgs(big.NewInt(20)).withAddress(utils.ZeroAddress), want: map[string]interface{}{ - "evm_chain_id": utils.NewBigI(20), + "evm_chain_id": ubig.NewI(20), "address": utils.ZeroAddress, }, }, diff --git a/core/chains/evm/txmgr/broadcaster_test.go b/core/chains/evm/txmgr/broadcaster_test.go index 21a4bd2865c..b9e8fe99e31 100644 --- a/core/chains/evm/txmgr/broadcaster_test.go +++ b/core/chains/evm/txmgr/broadcaster_test.go @@ -37,6 +37,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -1897,7 +1898,7 @@ func Test_NextNonce(t *testing.T) { ethClient.On("PendingNonceAt", mock.Anything, addr1).Return(uint64(randNonce), nil).Once() eb := NewTestEthBroadcaster(t, txStore, ethClient, ks, evmcfg, checkerFactory, false) ctx := testutils.Context(t) - cltest.MustInsertRandomKey(t, ks, *utils.NewBig(testutils.FixtureChainID)) + cltest.MustInsertRandomKey(t, ks, *ubig.New(testutils.FixtureChainID)) nonce, err := eb.GetNextSequence(ctx, addr1) require.NoError(t, err) diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go index 1c9868741fa..bb2a30e51dd 100644 --- a/core/chains/evm/txmgr/evm_tx_store.go +++ b/core/chains/evm/txmgr/evm_tx_store.go @@ -28,8 +28,8 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/label" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/services/pg" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) var ( @@ -177,7 +177,7 @@ type DbEthTx struct { Subject uuid.NullUUID PipelineTaskRunID uuid.NullUUID MinConfirmations null.Uint32 - EVMChainID utils.Big + EVMChainID ubig.Big // TransmitChecker defines the check that should be performed before a transaction is submitted on // chain. TransmitChecker *sqlutil.JSON @@ -210,7 +210,7 @@ func (db *DbEthTx) FromTx(tx *Tx) { db.CallbackCompleted = tx.CallbackCompleted if tx.ChainID != nil { - db.EVMChainID = *utils.NewBig(tx.ChainID) + db.EVMChainID = *ubig.New(tx.ChainID) } if tx.Sequence != nil { n := tx.Sequence.Int64() diff --git a/core/chains/evm/txmgr/resender_test.go b/core/chains/evm/txmgr/resender_test.go index 0e86c0d4f8c..f6b0e3e29c7 100644 --- a/core/chains/evm/txmgr/resender_test.go +++ b/core/chains/evm/txmgr/resender_test.go @@ -16,6 +16,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" @@ -23,7 +24,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/store/models" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func Test_EthResender_resendUnconfirmed(t *testing.T) { @@ -109,7 +109,7 @@ func Test_EthResender_alertUnconfirmed(t *testing.T) { delay := models.MustNewDuration(1 * time.Nanosecond) cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0] = &toml.EVMConfig{ - Chain: toml.Defaults(utils.NewBig(big.NewInt(0)), &toml.Chain{ + Chain: toml.Defaults(ubig.New(big.NewInt(0)), &toml.Chain{ Transactions: toml.Transactions{ResendAfterThreshold: delay}, }), } diff --git a/core/chains/evm/txmgr/tracker_test.go b/core/chains/evm/txmgr/tracker_test.go index a31187f04e8..3e0bef51568 100644 --- a/core/chains/evm/txmgr/tracker_test.go +++ b/core/chains/evm/txmgr/tracker_test.go @@ -7,12 +7,12 @@ import ( "time" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" @@ -33,8 +33,8 @@ func newTestEvmTrackerSetup(t *testing.T) (*txmgr.Tracker, txmgr.TestEvmTxStore, func generateEnabledAddresses(t *testing.T, keyStore keystore.Eth, chainID *big.Int) []common.Address { var enabledAddresses []common.Address - _, addr1 := cltest.MustInsertRandomKey(t, keyStore, *utils.NewBigI(chainID.Int64())) - _, addr2 := cltest.MustInsertRandomKey(t, keyStore, *utils.NewBigI(chainID.Int64())) + _, addr1 := cltest.MustInsertRandomKey(t, keyStore, *ubig.NewI(chainID.Int64())) + _, addr2 := cltest.MustInsertRandomKey(t, keyStore, *ubig.NewI(chainID.Int64())) enabledAddresses = append(enabledAddresses, addr1, addr2) return enabledAddresses } diff --git a/core/chains/evm/txmgr/txmgr_test.go b/core/chains/evm/txmgr/txmgr_test.go index 9833acfd459..df913a41905 100644 --- a/core/chains/evm/txmgr/txmgr_test.go +++ b/core/chains/evm/txmgr/txmgr_test.go @@ -33,6 +33,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" @@ -206,7 +207,7 @@ func TestTxm_CreateTransaction(t *testing.T) { require.Error(t, err) assert.Contains(t, err.Error(), fmt.Sprintf("no eth key exists with address %s", rndAddr.String())) - _, otherAddress := cltest.MustInsertRandomKey(t, kst.Eth(), *utils.NewBigI(1337)) + _, otherAddress := cltest.MustInsertRandomKey(t, kst.Eth(), *ubig.NewI(1337)) _, err = txm.CreateTransaction(testutils.Context(t), txmgr.TxRequest{ FromAddress: otherAddress, @@ -301,7 +302,7 @@ func TestTxm_CreateTransaction(t *testing.T) { // Create mock forwarder, mock authorizedsenders call. form := forwarders.NewORM(db, logger.Test(t), cfg.Database()) fwdrAddr := testutils.NewAddress() - fwdr, err := form.CreateForwarder(fwdrAddr, utils.Big(cltest.FixtureChainID)) + fwdr, err := form.CreateForwarder(fwdrAddr, ubig.Big(cltest.FixtureChainID)) require.NoError(t, err) require.Equal(t, fwdr.Address, fwdrAddr) diff --git a/core/chains/evm/types/models.go b/core/chains/evm/types/models.go index 314180a7e98..b7c1e5b56d5 100644 --- a/core/chains/evm/types/models.go +++ b/core/chains/evm/types/models.go @@ -20,6 +20,7 @@ import ( commontypes "github.com/smartcontractkit/chainlink/v2/common/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types/internal/blocks" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/null" "github.com/smartcontractkit/chainlink/v2/core/utils" ) @@ -32,7 +33,7 @@ type Head struct { L1BlockNumber null.Int64 ParentHash common.Hash Parent *Head - EVMChainID *utils.Big + EVMChainID *ubig.Big Timestamp time.Time CreatedAt time.Time BaseFeePerGas *assets.Wei @@ -47,7 +48,7 @@ var _ commontypes.Head[common.Hash] = &Head{} var _ htrktypes.Head[common.Hash, *big.Int] = &Head{} // NewHead returns a Head instance. -func NewHead(number *big.Int, blockHash common.Hash, parentHash common.Hash, timestamp uint64, chainID *utils.Big) Head { +func NewHead(number *big.Int, blockHash common.Hash, parentHash common.Hash, timestamp uint64, chainID *ubig.Big) Head { return Head{ Number: number.Int64(), Hash: blockHash, diff --git a/core/chains/evm/types/types.go b/core/chains/evm/types/types.go index d0e7292b204..aa43806da1f 100644 --- a/core/chains/evm/types/types.go +++ b/core/chains/evm/types/types.go @@ -13,6 +13,7 @@ import ( "gopkg.in/guregu/null.v4" "github.com/smartcontractkit/chainlink-common/pkg/types" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/core/utils" ) @@ -26,7 +27,7 @@ type Configs interface { type Node struct { Name string - EVMChainID utils.Big + EVMChainID ubig.Big WSURL null.String HTTPURL null.String SendOnly bool diff --git a/core/utils/big.go b/core/chains/evm/utils/big/big.go similarity index 91% rename from core/utils/big.go rename to core/chains/evm/utils/big/big.go index 69fab223de7..f0ff475a7e7 100644 --- a/core/utils/big.go +++ b/core/chains/evm/utils/big/big.go @@ -1,4 +1,4 @@ -package utils +package big import ( "database/sql/driver" @@ -10,6 +10,7 @@ import ( bigmath "github.com/smartcontractkit/chainlink-common/pkg/utils/big_math" "github.com/smartcontractkit/chainlink-common/pkg/utils/bytes" + "github.com/smartcontractkit/chainlink/v2/core/utils" ) const base10 = 10 @@ -50,8 +51,8 @@ func (b *BigFloat) Value() *big.Float { // Big stores large integers and can deserialize a variety of inputs. type Big big.Int -// NewBig constructs a Big from *big.Int. -func NewBig(i *big.Int) *Big { +// New constructs a Big from *big.Int. +func New(i *big.Int) *Big { if i != nil { var b big.Int b.Set(i) @@ -60,9 +61,9 @@ func NewBig(i *big.Int) *Big { return nil } -// NewBigI constructs a Big from int64. -func NewBigI(i int64) *Big { - return NewBig(big.NewInt(i)) +// NewI constructs a Big from int64. +func NewI(i int64) *Big { + return New(big.NewInt(i)) } // MarshalText marshals this instance to base 10 number as string. @@ -83,7 +84,7 @@ func (b Big) MarshalJSON() ([]byte, error) { func (b *Big) UnmarshalText(input []byte) error { input = bytes.TrimQuotes(input) str := string(input) - if HasHexPrefix(str) { + if utils.HasHexPrefix(str) { decoded, err := hexutil.DecodeBig(str) if err != nil { return err @@ -174,15 +175,15 @@ func (b *Big) Int64() int64 { // Add returns the sum of b and c func (b *Big) Add(c *Big) *Big { - return NewBig(bigmath.Add(b.ToInt(), c.ToInt())) + return New(bigmath.Add(b.ToInt(), c.ToInt())) } // Sub returns the differencs between b and c func (b *Big) Sub(c *Big) *Big { - return NewBig(bigmath.Sub(b.ToInt(), c.ToInt())) + return New(bigmath.Sub(b.ToInt(), c.ToInt())) } // Sub returns b % c func (b *Big) Mod(c *Big) *Big { - return NewBig(bigmath.Mod(b.ToInt(), c.ToInt())) + return New(bigmath.Mod(b.ToInt(), c.ToInt())) } diff --git a/core/utils/big_test.go b/core/chains/evm/utils/big/big_test.go similarity index 95% rename from core/utils/big_test.go rename to core/chains/evm/utils/big/big_test.go index e46d46a0651..c4774cf1988 100644 --- a/core/utils/big_test.go +++ b/core/chains/evm/utils/big/big_test.go @@ -1,4 +1,4 @@ -package utils +package big import ( "encoding/json" @@ -198,15 +198,15 @@ func TestBig_Scan(t *testing.T) { input interface{} want *Big }{ - {"zero string", "0", NewBig(big.NewInt(0))}, - {"one string", "1", NewBig(big.NewInt(1))}, + {"zero string", "0", New(big.NewInt(0))}, + {"one string", "1", New(big.NewInt(1))}, { "large string", "115792089237316195423570985008687907853269984665640564039457584007913129639935", - NewBig(uint256Max), + New(uint256Max), }, - {"zero as bytes", []uint8{48}, NewBig(big.NewInt(0))}, - {"small number as bytes", []uint8{49, 52}, NewBig(big.NewInt(14))}, + {"zero as bytes", []uint8{48}, New(big.NewInt(0))}, + {"small number as bytes", []uint8{49, 52}, New(big.NewInt(14))}, { "max number as bytes", []uint8{ @@ -216,7 +216,7 @@ func TestBig_Scan(t *testing.T) { 48, 51, 57, 52, 53, 55, 53, 56, 52, 48, 48, 55, 57, 49, 51, 49, 50, 57, 54, 51, 57, 57, 51, 53, }, - NewBig(uint256Max), + New(uint256Max), }, } for _, test := range tests { diff --git a/core/chains/evm/utils/utils.go b/core/chains/evm/utils/utils.go new file mode 100644 index 00000000000..abcea77124a --- /dev/null +++ b/core/chains/evm/utils/utils.go @@ -0,0 +1,37 @@ +package utils + +import ( + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/jpillora/backoff" + "golang.org/x/crypto/sha3" +) + +// MustHash returns the keccak256 hash, or panics on failure. +func MustHash(in string) common.Hash { + out, err := Keccak256([]byte(in)) + if err != nil { + panic(err) + } + return common.BytesToHash(out) +} + +// Keccak256 is a simplified interface for the legacy SHA3 implementation that +// Ethereum uses. +func Keccak256(in []byte) ([]byte, error) { + hash := sha3.NewLegacyKeccak256() + _, err := hash.Write(in) + return hash.Sum(nil), err +} + +// NewRedialBackoff is a standard backoff to use for redialling or reconnecting to +// unreachable network endpoints +func NewRedialBackoff() backoff.Backoff { + return backoff.Backoff{ + Min: 1 * time.Second, + Max: 15 * time.Second, + Jitter: true, + } + +} diff --git a/core/chains/legacyevm/chain.go b/core/chains/legacyevm/chain.go index 18277a55d03..ef84573cd09 100644 --- a/core/chains/legacyevm/chain.go +++ b/core/chains/legacyevm/chain.go @@ -33,11 +33,11 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/monitor" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/config" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/pg" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) //go:generate mockery --quiet --name Chain --output ./mocks/ --case=underscore @@ -127,7 +127,7 @@ type chain struct { } type errChainDisabled struct { - ChainID *utils.Big + ChainID *ubig.Big } func (e errChainDisabled) Error() string { diff --git a/core/cmd/blocks_commands_test.go b/core/cmd/blocks_commands_test.go index d0c0e118f9d..30540748cb1 100644 --- a/core/cmd/blocks_commands_test.go +++ b/core/cmd/blocks_commands_test.go @@ -8,15 +8,15 @@ import ( "github.com/stretchr/testify/require" "github.com/urfave/cli" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func Test_ReplayFromBlock(t *testing.T) { t.Parallel() app := startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.EVM[0].ChainID = (*utils.Big)(big.NewInt(5)) + c.EVM[0].ChainID = (*ubig.Big)(big.NewInt(5)) c.EVM[0].Enabled = ptr(true) }) diff --git a/core/cmd/eth_keys_commands_test.go b/core/cmd/eth_keys_commands_test.go index 3eb45e27bd0..7c85b779ecc 100644 --- a/core/cmd/eth_keys_commands_test.go +++ b/core/cmd/eth_keys_commands_test.go @@ -14,6 +14,7 @@ import ( commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -39,7 +40,7 @@ func TestEthKeysPresenter_RenderTable(t *testing.T) { isDisabled = true createdAt = time.Now() updatedAt = time.Now().Add(time.Second) - maxGasPriceWei = utils.NewBigI(12345) + maxGasPriceWei = ubig.NewI(12345) bundleID = cltest.DefaultOCRKeyBundleID buffer = bytes.NewBufferString("") r = cmd.RendererTable{Writer: buffer} diff --git a/core/cmd/evm_chains_commands_test.go b/core/cmd/evm_chains_commands_test.go index b4891271210..fa6d7bb519c 100644 --- a/core/cmd/evm_chains_commands_test.go +++ b/core/cmd/evm_chains_commands_test.go @@ -8,15 +8,15 @@ import ( "github.com/stretchr/testify/require" client2 "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) -func newRandChainID() *utils.Big { - return utils.NewBig(testutils.NewRandomEVMChainID()) +func newRandChainID() *big.Big { + return big.New(testutils.NewRandomEVMChainID()) } func TestShell_IndexEVMChains(t *testing.T) { diff --git a/core/cmd/evm_transaction_commands.go b/core/cmd/evm_transaction_commands.go index d702bc3b799..a1a11ab9b37 100644 --- a/core/cmd/evm_transaction_commands.go +++ b/core/cmd/evm_transaction_commands.go @@ -11,6 +11,7 @@ import ( "go.uber.org/multierr" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/store/models" "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/utils/stringutils" @@ -186,7 +187,7 @@ func (s *Shell) SendEther(c *cli.Context) (err error) { DestinationAddress: destinationAddress, FromAddress: fromAddress, Amount: amount, - EVMChainID: (*utils.Big)(evmChainID), + EVMChainID: (*ubig.Big)(evmChainID), AllowHigherAmounts: c.IsSet("force"), } diff --git a/core/cmd/forwarders_commands.go b/core/cmd/forwarders_commands.go index 51e90a4390c..a870d4714c7 100644 --- a/core/cmd/forwarders_commands.go +++ b/core/cmd/forwarders_commands.go @@ -14,7 +14,7 @@ import ( "github.com/urfave/cli" "go.uber.org/multierr" - "github.com/smartcontractkit/chainlink/v2/core/utils" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/web" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) @@ -136,7 +136,7 @@ func (s *Shell) TrackForwarder(c *cli.Context) (err error) { } request, err := json.Marshal(web.TrackEVMForwarderRequest{ - EVMChainID: (*utils.Big)(chainID), + EVMChainID: (*ubig.Big)(chainID), Address: address, }) if err != nil { diff --git a/core/cmd/forwarders_commands_test.go b/core/cmd/forwarders_commands_test.go index 179216b8e41..5946d31dc3d 100644 --- a/core/cmd/forwarders_commands_test.go +++ b/core/cmd/forwarders_commands_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "github.com/urfave/cli" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" @@ -23,7 +24,7 @@ func TestEVMForwarderPresenter_RenderTable(t *testing.T) { var ( id = "1" address = utils.RandomAddress() - evmChainID = utils.NewBigI(4) + evmChainID = big.NewI(4) createdAt = time.Now() updatedAt = time.Now().Add(time.Second) buffer = bytes.NewBufferString("") diff --git a/core/cmd/ocr2vrf_configure_commands.go b/core/cmd/ocr2vrf_configure_commands.go index cf014d5e5dc..06f26ddb6a4 100644 --- a/core/cmd/ocr2vrf_configure_commands.go +++ b/core/cmd/ocr2vrf_configure_commands.go @@ -17,6 +17,7 @@ import ( "github.com/jmoiron/sqlx" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" @@ -342,7 +343,7 @@ func (s *Shell) authorizeForwarder(c *cli.Context, db *sqlx.DB, lggr logger.Logg // Create forwarder for management in forwarder_manager.go. orm := forwarders.NewORM(db, lggr, s.Config.Database()) - _, err = orm.CreateForwarder(common.HexToAddress(forwarderAddress), *utils.NewBigI(chainID)) + _, err = orm.CreateForwarder(common.HexToAddress(forwarderAddress), *ubig.NewI(chainID)) if err != nil { return err } diff --git a/core/cmd/shell_local.go b/core/cmd/shell_local.go index a1f7fdb857c..e4c29a0e5c2 100644 --- a/core/cmd/shell_local.go +++ b/core/cmd/shell_local.go @@ -38,6 +38,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" "github.com/smartcontractkit/chainlink/v2/core/services/pg" @@ -855,7 +856,7 @@ func randomizeTestDBSequences(db *sqlx.DB) error { } var randNum *big.Int - randNum, err = crand.Int(crand.Reader, utils.NewBigI(10000).ToInt()) + randNum, err = crand.Int(crand.Reader, ubig.NewI(10000).ToInt()) if err != nil { return fmt.Errorf("%s: failed to generate random number", failedToRandomizeTestDBSequencesError{}) } diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go index dc90201890d..c5e1fc5e4d0 100644 --- a/core/internal/cltest/cltest.go +++ b/core/internal/cltest/cltest.go @@ -51,6 +51,7 @@ import ( httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -232,10 +233,10 @@ func NewApplicationWithKey(t *testing.T, flagsAndDeps ...interface{}) *TestAppli func NewApplicationWithConfigAndKey(t testing.TB, c chainlink.GeneralConfig, flagsAndDeps ...interface{}) *TestApplication { app := NewApplicationWithConfig(t, c, flagsAndDeps...) - chainID := *utils.NewBig(&FixtureChainID) + chainID := *ubig.New(&FixtureChainID) for _, dep := range flagsAndDeps { switch v := dep.(type) { - case *utils.Big: + case *ubig.Big: chainID = *v } } @@ -255,7 +256,7 @@ func NewApplicationWithConfigAndKey(t testing.TB, c chainlink.GeneralConfig, fla return app } -func setKeys(t testing.TB, app *TestApplication, flagsAndDeps ...interface{}) (chainID utils.Big) { +func setKeys(t testing.TB, app *TestApplication, flagsAndDeps ...interface{}) (chainID ubig.Big) { require.NoError(t, app.KeyStore.Unlock(Password)) for _, dep := range flagsAndDeps { @@ -993,13 +994,13 @@ func Head(val interface{}) *evmtypes.Head { time := uint64(0) switch t := val.(type) { case int: - h = evmtypes.NewHead(big.NewInt(int64(t)), utils.NewHash(), utils.NewHash(), time, utils.NewBig(&FixtureChainID)) + h = evmtypes.NewHead(big.NewInt(int64(t)), utils.NewHash(), utils.NewHash(), time, ubig.New(&FixtureChainID)) case uint64: - h = evmtypes.NewHead(big.NewInt(int64(t)), utils.NewHash(), utils.NewHash(), time, utils.NewBig(&FixtureChainID)) + h = evmtypes.NewHead(big.NewInt(int64(t)), utils.NewHash(), utils.NewHash(), time, ubig.New(&FixtureChainID)) case int64: - h = evmtypes.NewHead(big.NewInt(t), utils.NewHash(), utils.NewHash(), time, utils.NewBig(&FixtureChainID)) + h = evmtypes.NewHead(big.NewInt(t), utils.NewHash(), utils.NewHash(), time, ubig.New(&FixtureChainID)) case *big.Int: - h = evmtypes.NewHead(t, utils.NewHash(), utils.NewHash(), time, utils.NewBig(&FixtureChainID)) + h = evmtypes.NewHead(t, utils.NewHash(), utils.NewHash(), time, ubig.New(&FixtureChainID)) default: panic(fmt.Sprintf("Could not convert %v of type %T to Head", val, val)) } @@ -1009,7 +1010,7 @@ func Head(val interface{}) *evmtypes.Head { func HeadWithHash(n int64, hash common.Hash) *evmtypes.Head { var h evmtypes.Head time := uint64(0) - h = evmtypes.NewHead(big.NewInt(n), hash, utils.NewHash(), time, utils.NewBig(&FixtureChainID)) + h = evmtypes.NewHead(big.NewInt(n), hash, utils.NewHash(), time, ubig.New(&FixtureChainID)) return &h } @@ -1390,7 +1391,7 @@ func (b *Blocks) NewHead(number uint64) *evmtypes.Head { ParentHash: parent.Hash, Parent: parent, Timestamp: time.Unix(parent.Number+1, 0), - EVMChainID: utils.NewBig(&FixtureChainID), + EVMChainID: ubig.New(&FixtureChainID), } return head } @@ -1429,7 +1430,7 @@ func NewBlocks(t *testing.T, numHashes int) *Blocks { hash := utils.NewHash() hashes = append(hashes, hash) - heads[i] = &evmtypes.Head{Hash: hash, Number: i, Timestamp: time.Unix(i, 0), EVMChainID: utils.NewBig(&FixtureChainID)} + heads[i] = &evmtypes.Head{Hash: hash, Number: i, Timestamp: time.Unix(i, 0), EVMChainID: ubig.New(&FixtureChainID)} if i > 0 { parent := heads[i-1] heads[i].Parent = parent diff --git a/core/internal/cltest/factories.go b/core/internal/cltest/factories.go index a76d23d3762..bece916ecc5 100644 --- a/core/internal/cltest/factories.go +++ b/core/internal/cltest/factories.go @@ -32,6 +32,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flux_aggregator_wrapper" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" @@ -240,12 +241,12 @@ type RandomKey struct { Nonce int64 Disabled bool - chainIDs []utils.Big // nil: Fixture, set empty for none + chainIDs []ubig.Big // nil: Fixture, set empty for none } func (r RandomKey) MustInsert(t testing.TB, keystore keystore.Eth) (ethkey.KeyV2, common.Address) { if r.chainIDs == nil { - r.chainIDs = []utils.Big{*utils.NewBig(&FixtureChainID)} + r.chainIDs = []ubig.Big{*ubig.New(&FixtureChainID)} } key := MustGenerateRandomKey(t) @@ -272,7 +273,7 @@ func (r RandomKey) MustInsertWithState(t testing.TB, keystore keystore.Eth) (eth // MustInsertRandomKey inserts a randomly generated (not cryptographically secure) key for testing. // By default, it is enabled for the fixture chain. Pass chainIDs to override. // Use MustInsertRandomKeyNoChains for a key associate with no chains. -func MustInsertRandomKey(t testing.TB, keystore keystore.Eth, chainIDs ...utils.Big) (ethkey.KeyV2, common.Address) { +func MustInsertRandomKey(t testing.TB, keystore keystore.Eth, chainIDs ...ubig.Big) (ethkey.KeyV2, common.Address) { r := RandomKey{} if len(chainIDs) > 0 { r.chainIDs = chainIDs @@ -281,7 +282,7 @@ func MustInsertRandomKey(t testing.TB, keystore keystore.Eth, chainIDs ...utils. } func MustInsertRandomKeyNoChains(t testing.TB, keystore keystore.Eth) (ethkey.KeyV2, common.Address) { - return RandomKey{chainIDs: []utils.Big{}}.MustInsert(t, keystore) + return RandomKey{chainIDs: []ubig.Big{}}.MustInsert(t, keystore) } func MustInsertRandomKeyReturningState(t testing.TB, keystore keystore.Eth) (ethkey.State, common.Address) { @@ -299,7 +300,7 @@ func MustGenerateRandomKeyState(_ testing.TB) ethkey.State { } func MustInsertHead(t *testing.T, db *sqlx.DB, cfg pg.QConfig, number int64) evmtypes.Head { - h := evmtypes.NewHead(big.NewInt(number), utils.NewHash(), utils.NewHash(), 0, utils.NewBig(&FixtureChainID)) + h := evmtypes.NewHead(big.NewInt(number), utils.NewHash(), utils.NewHash(), 0, ubig.New(&FixtureChainID)) horm := headtracker.NewORM(db, logger.TestLogger(t), cfg, FixtureChainID) err := horm.IdempotentInsertHead(testutils.Context(t), &h) @@ -347,7 +348,7 @@ NOW(),NOW(),$1,'{}',false,$2,$3,0,0,0,0,0,0,0,0,0 func MakeDirectRequestJobSpec(t *testing.T) *job.Job { t.Helper() - drs := &job.DirectRequestSpec{EVMChainID: (*utils.Big)(testutils.FixtureChainID)} + drs := &job.DirectRequestSpec{EVMChainID: (*ubig.Big)(testutils.FixtureChainID)} spec := &job.Job{ Type: job.DirectRequest, SchemaVersion: 1, @@ -391,7 +392,7 @@ func MustInsertKeeperJob(t *testing.T, db *sqlx.DB, korm keeper.ORM, from ethkey } func MustInsertKeeperRegistry(t *testing.T, db *sqlx.DB, korm keeper.ORM, ethKeyStore keystore.Eth, keeperIndex, numKeepers, blockCountPerTurn int32) (keeper.Registry, job.Job) { - key, _ := MustInsertRandomKey(t, ethKeyStore, *utils.NewBig(testutils.SimulatedChainID)) + key, _ := MustInsertRandomKey(t, ethKeyStore, *ubig.New(testutils.SimulatedChainID)) from := key.EIP55Address t.Helper() contractAddress := NewEIP55Address() @@ -415,7 +416,7 @@ func MustInsertKeeperRegistry(t *testing.T, db *sqlx.DB, korm keeper.ORM, ethKey func MustInsertUpkeepForRegistry(t *testing.T, db *sqlx.DB, cfg pg.QConfig, registry keeper.Registry) keeper.UpkeepRegistration { korm := keeper.NewORM(db, logger.TestLogger(t), cfg) - upkeepID := utils.NewBigI(int64(mathrand.Uint32())) + upkeepID := ubig.NewI(int64(mathrand.Uint32())) upkeep := keeper.UpkeepRegistration{ UpkeepID: upkeepID, ExecuteGas: uint32(150_000), diff --git a/core/internal/cltest/simulated_backend.go b/core/internal/cltest/simulated_backend.go index 010478837da..0aecc7f8324 100644 --- a/core/internal/cltest/simulated_backend.go +++ b/core/internal/cltest/simulated_backend.go @@ -11,12 +11,12 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/pg" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func NewSimulatedBackend(t *testing.T, alloc core.GenesisAlloc, gasLimit uint32) *backends.SimulatedBackend { @@ -39,7 +39,7 @@ func NewApplicationWithConfigV2OnSimulatedBlockchain( } require.Zero(t, evmtest.MustGetDefaultChainID(t, cfg.EVMConfigs()).Cmp(testutils.SimulatedChainID)) - chainID := utils.NewBig(testutils.SimulatedChainID) + chainID := big.New(testutils.SimulatedChainID) client := client.NewSimulatedBackendClient(t, backend, testutils.SimulatedChainID) eventBroadcaster := pg.NewEventBroadcaster(cfg.Database().URL(), 0, 0, logger.TestLogger(t), uuid.New()) @@ -64,7 +64,7 @@ func NewApplicationWithConfigV2AndKeyOnSimulatedBlockchain( } require.Zero(t, evmtest.MustGetDefaultChainID(t, cfg.EVMConfigs()).Cmp(testutils.SimulatedChainID)) - chainID := utils.NewBig(testutils.SimulatedChainID) + chainID := big.New(testutils.SimulatedChainID) client := client.NewSimulatedBackendClient(t, backend, testutils.SimulatedChainID) eventBroadcaster := pg.NewEventBroadcaster(cfg.Database().URL(), 0, 0, logger.TestLogger(t), uuid.New()) diff --git a/core/internal/features/features_test.go b/core/internal/features/features_test.go index 7b29fdae4fa..f115a3f8858 100644 --- a/core/internal/features/features_test.go +++ b/core/internal/features/features_test.go @@ -46,6 +46,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/consumer_wrapper" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flags_wrapper" @@ -771,7 +772,7 @@ func setupForwarderEnabledNode(t *testing.T, owner *bind.TransactOpts, portV2 in // add forwarder address to be tracked in db forwarderORM := forwarders.NewORM(app.GetSqlxDB(), logger.TestLogger(t), config.Database()) - chainID := utils.Big(*b.Blockchain().Config().ChainID) + chainID := ubig.Big(*b.Blockchain().Config().ChainID) _, err = forwarderORM.CreateForwarder(forwarder, chainID) require.NoError(t, err) @@ -1277,7 +1278,7 @@ func TestIntegration_BlockHistoryEstimator(t *testing.T) { Transactions: cltest.LegacyTransactionsFromGasPrices(48_000_000_000, 49_000_000_000, 31_000_000_000), } - evmChainID := utils.NewBig(evmtest.MustGetDefaultChainID(t, cfg.EVMConfigs())) + evmChainID := ubig.New(evmtest.MustGetDefaultChainID(t, cfg.EVMConfigs())) h40 := evmtypes.Head{Hash: utils.NewHash(), Number: 40, EVMChainID: evmChainID} h41 := evmtypes.Head{Hash: b41.Hash, ParentHash: h40.Hash, Number: 41, EVMChainID: evmChainID} h42 := evmtypes.Head{Hash: b42.Hash, ParentHash: h41.Hash, Number: 42, EVMChainID: evmChainID} diff --git a/core/internal/features/ocr2/features_ocr2_test.go b/core/internal/features/ocr2/features_ocr2_test.go index 295bb7fb14a..70d4b0d79fd 100644 --- a/core/internal/features/ocr2/features_ocr2_test.go +++ b/core/internal/features/ocr2/features_ocr2_test.go @@ -37,6 +37,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" @@ -51,7 +52,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/store/models" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) type ocr2Node struct { @@ -170,7 +170,7 @@ func setupNodeOCR2( // add forwarder address to be tracked in db forwarderORM := forwarders.NewORM(app.GetSqlxDB(), logger.TestLogger(t), config.Database()) - chainID := utils.Big(*b.Blockchain().Config().ChainID) + chainID := ubig.Big(*b.Blockchain().Config().ChainID) _, err2 = forwarderORM.CreateForwarder(faddr, chainID) require.NoError(t, err2) diff --git a/core/internal/testutils/configtest/general_config.go b/core/internal/testutils/configtest/general_config.go index f076521b71c..c414c973160 100644 --- a/core/internal/testutils/configtest/general_config.go +++ b/core/internal/testutils/configtest/general_config.go @@ -10,11 +10,11 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/store/dialects" "github.com/smartcontractkit/chainlink/v2/core/store/models" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) const DefaultPeerID = "12D3KooWPjceQrSwdWXPyLLeABRXmuqt69Rg3sBYbU1Nft9HyQ6X" @@ -64,7 +64,7 @@ func overrides(c *chainlink.Config, s *chainlink.Secrets) { c.WebServer.ListenIP = &testIP c.WebServer.TLS.ListenIP = &testIP - chainID := utils.NewBigI(evmclient.NullClientChainID) + chainID := big.NewI(evmclient.NullClientChainID) c.EVM = append(c.EVM, &evmcfg.EVMConfig{ ChainID: chainID, Chain: evmcfg.Defaults(chainID), @@ -95,7 +95,7 @@ func NewGeneralConfigSimulated(t testing.TB, overrideFn func(*chainlink.Config, // simulated is a config override func that appends the simulated EVM chain (testutils.SimulatedChainID), // or replaces the null chain (client.NullClientChainID) if that is the only entry. func simulated(c *chainlink.Config, s *chainlink.Secrets) { - chainID := utils.NewBig(testutils.SimulatedChainID) + chainID := big.New(testutils.SimulatedChainID) enabled := true cfg := evmcfg.EVMConfig{ ChainID: chainID, @@ -103,7 +103,7 @@ func simulated(c *chainlink.Config, s *chainlink.Secrets) { Enabled: &enabled, Nodes: evmcfg.EVMNodes{&validTestNode}, } - if len(c.EVM) == 1 && c.EVM[0].ChainID.Cmp(utils.NewBigI(client.NullClientChainID)) == 0 { + if len(c.EVM) == 1 && c.EVM[0].ChainID.Cmp(big.NewI(client.NullClientChainID)) == 0 { c.EVM[0] = &cfg // replace null, if only entry } else { c.EVM = append(c.EVM, &cfg) diff --git a/core/internal/testutils/evmtest/evmtest.go b/core/internal/testutils/evmtest/evmtest.go index 095ea1a35c9..eb1a03530ae 100644 --- a/core/internal/testutils/evmtest/evmtest.go +++ b/core/internal/testutils/evmtest/evmtest.go @@ -31,6 +31,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -38,7 +39,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/relay" evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func NewChainScopedConfig(t testing.TB, cfg legacyevm.AppConfig) evmconfig.ChainScopedConfig { @@ -46,7 +46,7 @@ func NewChainScopedConfig(t testing.TB, cfg legacyevm.AppConfig) evmconfig.Chain if len(cfg.EVMConfigs()) > 0 { evmCfg = cfg.EVMConfigs()[0] } else { - var chainID = (*utils.Big)(testutils.FixtureChainID) + var chainID = (*ubig.Big)(testutils.FixtureChainID) evmCfg = &evmtoml.EVMConfig{ ChainID: chainID, Chain: evmtoml.Defaults(chainID), @@ -267,7 +267,7 @@ func (mo *TestConfigs) NodeStatusesPaged(offset int, limit int, chainIDs ...stri return } -func legacyNode(n *evmtoml.Node, chainID *utils.Big) (v2 evmtypes.Node) { +func legacyNode(n *evmtoml.Node, chainID *ubig.Big) (v2 evmtypes.Node) { v2.Name = *n.Name v2.EVMChainID = *chainID if n.HTTPURL != nil { diff --git a/core/internal/testutils/evmtest/v2/evmtest.go b/core/internal/testutils/evmtest/v2/evmtest.go index fa22588c8fb..22b2bc5e0ca 100644 --- a/core/internal/testutils/evmtest/v2/evmtest.go +++ b/core/internal/testutils/evmtest/v2/evmtest.go @@ -5,9 +5,9 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func ChainEthMainnet(t *testing.T) config.ChainScopedConfig { return scopedConfig(t, 1) } @@ -16,7 +16,7 @@ func ChainArbitrumMainnet(t *testing.T) config.ChainScopedConfig { return scoped func ChainArbitrumRinkeby(t *testing.T) config.ChainScopedConfig { return scopedConfig(t, 421611) } func scopedConfig(t *testing.T, chainID int64) config.ChainScopedConfig { - id := utils.NewBigI(chainID) + id := big.NewI(chainID) evmCfg := toml.EVMConfig{ChainID: id, Chain: toml.Defaults(id)} return config.NewTOMLChainScopedConfig(configtest.NewTestGeneralConfig(t), &evmCfg, logger.TestLogger(t)) } diff --git a/core/scripts/functions/src/fetching.go b/core/scripts/functions/src/fetching.go index 0b22a93252d..9be624a40b6 100644 --- a/core/scripts/functions/src/fetching.go +++ b/core/scripts/functions/src/fetching.go @@ -11,7 +11,6 @@ import ( "github.com/urfave/cli" helpers "github.com/smartcontractkit/chainlink/core/scripts/common" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) @@ -114,7 +113,7 @@ func findEvmOCR2Bundle(ocr2Bundles []ocr2Bundle) int { func findFirstGoodEthKeyAddress(chainID int64, ethKeys []presenters.ETHKeyResource) (string, error) { for _, ethKey := range ethKeys { - if ethKey.EVMChainID.Equal(utils.NewBigI(chainID)) && !ethKey.Disabled { + if ethKey.EVMChainID.Equal(ubig.NewI(chainID)) && !ethKey.Disabled { if ethKey.EthBalance.IsZero() { fmt.Println("WARN: selected ETH address has zero balance", ethKey.Address) } diff --git a/core/services/blockhashstore/delegate_test.go b/core/services/blockhashstore/delegate_test.go index 0096ac5ca9e..6fffcfdd493 100644 --- a/core/services/blockhashstore/delegate_test.go +++ b/core/services/blockhashstore/delegate_test.go @@ -13,6 +13,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" mocklp "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -26,7 +27,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func TestDelegate_JobType(t *testing.T) { @@ -90,7 +90,7 @@ func TestDelegate_ServicesForSpec(t *testing.T) { defaultWaitBlocks := (int32)(testData.legacyChains.Slice()[0].Config().EVM().FinalityDepth()) t.Run("happy", func(t *testing.T) { - spec := job.Job{BlockhashStoreSpec: &job.BlockhashStoreSpec{WaitBlocks: defaultWaitBlocks, EVMChainID: (*utils.Big)(testutils.FixtureChainID)}} + spec := job.Job{BlockhashStoreSpec: &job.BlockhashStoreSpec{WaitBlocks: defaultWaitBlocks, EVMChainID: (*big.Big)(testutils.FixtureChainID)}} services, err := delegate.ServicesForSpec(spec) require.NoError(t, err) @@ -107,7 +107,7 @@ func TestDelegate_ServicesForSpec(t *testing.T) { CoordinatorV1Address: &coordinatorV1, CoordinatorV2Address: &coordinatorV2, CoordinatorV2PlusAddress: &coordinatorV2Plus, - EVMChainID: (*utils.Big)(testutils.FixtureChainID), + EVMChainID: (*big.Big)(testutils.FixtureChainID), }} services, err := delegate.ServicesForSpec(spec) @@ -123,7 +123,7 @@ func TestDelegate_ServicesForSpec(t *testing.T) { t.Run("wrong EVMChainID", func(t *testing.T) { spec := job.Job{BlockhashStoreSpec: &job.BlockhashStoreSpec{ - EVMChainID: utils.NewBigI(123), + EVMChainID: big.NewI(123), }} _, err := delegate.ServicesForSpec(spec) assert.Error(t, err) @@ -152,7 +152,7 @@ func TestDelegate_StartStop(t *testing.T) { WaitBlocks: defaultWaitBlocks, PollPeriod: time.Second, RunTimeout: testutils.WaitTimeout(t), - EVMChainID: (*utils.Big)(testutils.FixtureChainID), + EVMChainID: (*big.Big)(testutils.FixtureChainID), }} services, err := delegate.ServicesForSpec(spec) diff --git a/core/services/blockhashstore/validate_test.go b/core/services/blockhashstore/validate_test.go index 0b7110a7528..48487bb5489 100644 --- a/core/services/blockhashstore/validate_test.go +++ b/core/services/blockhashstore/validate_test.go @@ -6,9 +6,9 @@ import ( "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func TestValidate(t *testing.T) { @@ -49,7 +49,7 @@ fromAddresses = ["0x469aA2CD13e037DC5236320783dCfd0e641c0559"]`, os.BlockhashStoreSpec.BlockhashStoreAddress) require.Equal(t, 23*time.Second, os.BlockhashStoreSpec.PollPeriod) require.Equal(t, 7*time.Second, os.BlockhashStoreSpec.RunTimeout) - require.Equal(t, utils.NewBigI(4), os.BlockhashStoreSpec.EVMChainID) + require.Equal(t, big.NewI(4), os.BlockhashStoreSpec.EVMChainID) require.Equal(t, fromAddresses, os.BlockhashStoreSpec.FromAddresses) }, diff --git a/core/services/blockheaderfeeder/validate_test.go b/core/services/blockheaderfeeder/validate_test.go index c58058d1620..cdab0322a40 100644 --- a/core/services/blockheaderfeeder/validate_test.go +++ b/core/services/blockheaderfeeder/validate_test.go @@ -6,9 +6,9 @@ import ( "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func TestValidate(t *testing.T) { @@ -59,7 +59,7 @@ storeBlockhashesBatchSize = 10 os.BlockHeaderFeederSpec.BatchBlockhashStoreAddress) require.Equal(t, 23*time.Second, os.BlockHeaderFeederSpec.PollPeriod) require.Equal(t, 7*time.Second, os.BlockHeaderFeederSpec.RunTimeout) - require.Equal(t, utils.NewBigI(4), os.BlockHeaderFeederSpec.EVMChainID) + require.Equal(t, big.NewI(4), os.BlockHeaderFeederSpec.EVMChainID) require.Equal(t, fromAddresses, os.BlockHeaderFeederSpec.FromAddresses) require.Equal(t, uint16(20), @@ -86,7 +86,7 @@ fromAddresses = ["0x469aA2CD13e037DC5236320783dCfd0e641c0559"] require.Equal(t, int32(256), os.BlockHeaderFeederSpec.WaitBlocks) require.Equal(t, 15*time.Second, os.BlockHeaderFeederSpec.PollPeriod) require.Equal(t, 30*time.Second, os.BlockHeaderFeederSpec.RunTimeout) - require.Equal(t, utils.NewBigI(4), os.BlockHeaderFeederSpec.EVMChainID) + require.Equal(t, big.NewI(4), os.BlockHeaderFeederSpec.EVMChainID) require.Equal(t, fromAddresses, os.BlockHeaderFeederSpec.FromAddresses) require.Equal(t, uint16(100), diff --git a/core/services/chainlink/config.go b/core/services/chainlink/config.go index b2f60384ec8..192fbb311d3 100644 --- a/core/services/chainlink/config.go +++ b/core/services/chainlink/config.go @@ -28,9 +28,9 @@ import ( // When adding a new field: // - consider including a unit suffix with the field name // - TOML is limited to int64/float64, so fields requiring greater range/precision must use non-standard types -// implementing encoding.TextMarshaler/TextUnmarshaler, like utils.Big and decimal.Decimal +// implementing encoding.TextMarshaler/TextUnmarshaler, like big.Big and decimal.Decimal // - std lib types that don't implement encoding.TextMarshaler/TextUnmarshaler (time.Duration, url.URL, big.Int) won't -// work as expected, and require wrapper types. See models.Duration, models.URL, utils.Big. +// work as expected, and require wrapper types. See models.Duration, models.URL, big.Big. type Config struct { toml.Core diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go index 6453fe05e00..85a4c99b862 100644 --- a/core/services/chainlink/config_test.go +++ b/core/services/chainlink/config_test.go @@ -26,6 +26,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" legacy "github.com/smartcontractkit/chainlink/v2/core/config" "github.com/smartcontractkit/chainlink/v2/core/config/toml" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -95,7 +96,7 @@ var ( }, EVM: []*evmcfg.EVMConfig{ { - ChainID: utils.NewBigI(1), + ChainID: big.NewI(1), Chain: evmcfg.Chain{ FinalityDepth: ptr[uint32](26), FinalityTagEnabled: ptr[bool](false), @@ -112,7 +113,7 @@ var ( }, }}, { - ChainID: utils.NewBigI(42), + ChainID: big.NewI(42), Chain: evmcfg.Chain{ GasEstimator: evmcfg.GasEstimator{ PriceDefault: assets.NewWeiI(math.MaxInt64), @@ -125,7 +126,7 @@ var ( }, }}, { - ChainID: utils.NewBigI(137), + ChainID: big.NewI(137), Chain: evmcfg.Chain{ GasEstimator: evmcfg.GasEstimator{ Mode: ptr("FixedPrice"), @@ -463,7 +464,7 @@ func TestConfig_Marshal(t *testing.T) { } full.EVM = []*evmcfg.EVMConfig{ { - ChainID: utils.NewBigI(1), + ChainID: big.NewI(1), Enabled: ptr(false), Chain: evmcfg.Chain{ AutoCreateKey: ptr(false), @@ -1466,7 +1467,7 @@ func assertValidationError(t *testing.T, invalid interface{ Validate() error }, func TestConfig_setDefaults(t *testing.T) { var c Config - c.EVM = evmcfg.EVMConfigs{{ChainID: utils.NewBigI(99999133712345)}} + c.EVM = evmcfg.EVMConfigs{{ChainID: big.NewI(99999133712345)}} c.Cosmos = coscfg.TOMLConfigs{{ChainID: ptr("unknown cosmos chain")}} c.Solana = solana.TOMLConfigs{{ChainID: ptr("unknown solana chain")}} c.Starknet = stkcfg.TOMLConfigs{{ChainID: ptr("unknown starknet chain")}} diff --git a/core/services/chainlink/relayer_chain_interoperators_test.go b/core/services/chainlink/relayer_chain_interoperators_test.go index a0754fa0139..d89fbce12db 100644 --- a/core/services/chainlink/relayer_chain_interoperators_test.go +++ b/core/services/chainlink/relayer_chain_interoperators_test.go @@ -18,6 +18,7 @@ import ( stkcfg "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config" "github.com/smartcontractkit/chainlink-solana/pkg/solana" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -31,12 +32,11 @@ import ( evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func TestCoreRelayerChainInteroperators(t *testing.T) { - evmChainID1, evmChainID2 := utils.NewBig(big.NewInt(1)), utils.NewBig(big.NewInt(2)) + evmChainID1, evmChainID2 := ubig.New(big.NewInt(1)), ubig.New(big.NewInt(2)) solanaChainID1, solanaChainID2 := "solana-id-1", "solana-id-2" starknetChainID1, starknetChainID2 := "starknet-id-1", "starknet-id-2" cosmosChainID1, cosmosChainID2 := "cosmos-id-1", "cosmos-id-2" @@ -71,7 +71,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { Chain: cfg, Nodes: evmcfg.EVMNodes{&node1_1, &node1_2}, } - id2 := utils.NewBig(big.NewInt(2)) + id2 := ubig.New(big.NewInt(2)) c.EVM = append(c.EVM, &evmcfg.EVMConfig{ ChainID: evmChainID2, Chain: evmcfg.Defaults(id2), diff --git a/core/services/directrequest/delegate_test.go b/core/services/directrequest/delegate_test.go index 865edb1b481..be61cde4d60 100644 --- a/core/services/directrequest/delegate_test.go +++ b/core/services/directrequest/delegate_test.go @@ -20,6 +20,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log" log_mocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log/mocks" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/operator_wrapper" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -34,7 +35,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" pipeline_mocks "github.com/smartcontractkit/chainlink/v2/core/services/pipeline/mocks" evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func TestDelegate_ServicesForSpec(t *testing.T) { @@ -59,7 +59,7 @@ func TestDelegate_ServicesForSpec(t *testing.T) { }) t.Run("Spec with DirectRequestSpec", func(t *testing.T) { - spec := job.Job{DirectRequestSpec: &job.DirectRequestSpec{EVMChainID: (*utils.Big)(testutils.FixtureChainID)}, PipelineSpec: &pipeline.Spec{}} + spec := job.Job{DirectRequestSpec: &job.DirectRequestSpec{EVMChainID: (*ubig.Big)(testutils.FixtureChainID)}, PipelineSpec: &pipeline.Spec{}} services, err := delegate.ServicesForSpec(spec) require.NoError(t, err) assert.Len(t, services, 1) diff --git a/core/services/directrequest/validate.go b/core/services/directrequest/validate.go index bc31f09b685..271e720660f 100644 --- a/core/services/directrequest/validate.go +++ b/core/services/directrequest/validate.go @@ -5,18 +5,18 @@ import ( "github.com/pkg/errors" "github.com/smartcontractkit/chainlink-common/pkg/assets" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/null" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" "github.com/smartcontractkit/chainlink/v2/core/store/models" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) type DirectRequestToml struct { ContractAddress ethkey.EIP55Address `toml:"contractAddress"` Requesters models.AddressCollection `toml:"requesters"` MinContractPayment *assets.Link `toml:"minContractPaymentLinkJuels"` - EVMChainID *utils.Big `toml:"evmChainID"` + EVMChainID *big.Big `toml:"evmChainID"` MinIncomingConfirmations null.Uint32 `toml:"minIncomingConfirmations"` } diff --git a/core/services/feeds/service.go b/core/services/feeds/service.go index ea6e6cae5ab..a1b4e9b2837 100644 --- a/core/services/feeds/service.go +++ b/core/services/feeds/service.go @@ -19,6 +19,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/logger" pb "github.com/smartcontractkit/chainlink/v2/core/services/feeds/proto" @@ -32,7 +33,6 @@ import ( ocr2 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" "github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap" "github.com/smartcontractkit/chainlink/v2/core/services/pg" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/utils/crypto" ) @@ -1073,7 +1073,7 @@ func (s *service) findExistingJobForOCR2(j *job.Job, qopts pg.QOpt) (int32, erro // findExistingJobForOCRFlux looks for existing job for OCR or flux func (s *service) findExistingJobForOCRFlux(j *job.Job, qopts pg.QOpt) (int32, error) { var address ethkey.EIP55Address - var evmChainID *utils.Big + var evmChainID *big.Big switch j.Type { case job.OffchainReporting: diff --git a/core/services/feeds/service_test.go b/core/services/feeds/service_test.go index bd0993825e2..d37393eba9e 100644 --- a/core/services/feeds/service_test.go +++ b/core/services/feeds/service_test.go @@ -19,6 +19,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -41,7 +42,6 @@ import ( evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/services/versioning" "github.com/smartcontractkit/chainlink/v2/core/store/models" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/utils/crypto" ) @@ -1543,7 +1543,7 @@ func Test_Service_ListSpecsByJobProposalIDs(t *testing.T) { } func Test_Service_ApproveSpec(t *testing.T) { - var evmChainID *utils.Big + var evmChainID *big.Big address := ethkey.EIP55AddressFromAddress(common.Address{}) externalJobID := uuid.New() diff --git a/core/services/fluxmonitorv2/orm_test.go b/core/services/fluxmonitorv2/orm_test.go index 6e06a1e65b8..bcbec4363e2 100644 --- a/core/services/fluxmonitorv2/orm_test.go +++ b/core/services/fluxmonitorv2/orm_test.go @@ -14,6 +14,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" txmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" @@ -22,7 +23,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/fluxmonitorv2" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func TestORM_MostRecentFluxMonitorRoundID(t *testing.T) { @@ -159,7 +159,7 @@ func makeJob(t *testing.T) *job.Job { IdleTimerDisabled: false, CreatedAt: time.Now(), UpdatedAt: time.Now(), - EVMChainID: (*utils.Big)(testutils.FixtureChainID), + EVMChainID: (*big.Big)(testutils.FixtureChainID), }, } } diff --git a/core/services/job/job_orm_test.go b/core/services/job/job_orm_test.go index 21035140f54..c0622ba8066 100644 --- a/core/services/job/job_orm_test.go +++ b/core/services/job/job_orm_test.go @@ -19,6 +19,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" @@ -41,7 +42,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrfcommon" "github.com/smartcontractkit/chainlink/v2/core/services/webhook" "github.com/smartcontractkit/chainlink/v2/core/testdata/testspecs" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) const mercuryOracleTOML = `name = 'LINK / ETH | 0x0000000000000000000000000000000000000000000000000000000000000001 | verifier_proxy 0x0000000000000000000000000000000000000001' @@ -695,7 +695,7 @@ func TestORM_CreateJob_EVMChainID_Validation(t *testing.T) { } func TestORM_CreateJob_OCR_DuplicatedContractAddress(t *testing.T) { - customChainID := utils.NewBig(testutils.NewRandomEVMChainID()) + customChainID := big.New(testutils.NewRandomEVMChainID()) config := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { enabled := true @@ -764,7 +764,7 @@ func TestORM_CreateJob_OCR_DuplicatedContractAddress(t *testing.T) { } func TestORM_CreateJob_OCR2_DuplicatedContractAddress(t *testing.T) { - customChainID := utils.NewBig(testutils.NewRandomEVMChainID()) + customChainID := big.New(testutils.NewRandomEVMChainID()) config := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { enabled := true @@ -825,7 +825,7 @@ func TestORM_CreateJob_OCR2_DuplicatedContractAddress(t *testing.T) { } func TestORM_CreateJob_OCR2_Sending_Keys_Transmitter_Keys_Validations(t *testing.T) { - customChainID := utils.NewBig(testutils.NewRandomEVMChainID()) + customChainID := big.New(testutils.NewRandomEVMChainID()) config := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { enabled := true @@ -1021,7 +1021,7 @@ func Test_FindJob(t *testing.T) { // Create a config with multiple EVM chains. The test fixtures already load 1337 // Additional chains will need additional fixture statements to add a chain to evm_chains. config := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { - chainID := utils.NewBigI(1337) + chainID := big.NewI(1337) enabled := true c.EVM = append(c.EVM, &evmcfg.EVMConfig{ ChainID: chainID, @@ -1154,7 +1154,7 @@ func Test_FindJob(t *testing.T) { assert.Equal(t, job.ID, jbID) - _, err2 = orm.FindJobIDByAddress("not-existing", utils.NewBigI(0)) + _, err2 = orm.FindJobIDByAddress("not-existing", big.NewI(0)) require.Error(t, err2) require.ErrorIs(t, err2, sql.ErrNoRows) }) @@ -1222,7 +1222,7 @@ func Test_FindJobsByPipelineSpecIDs(t *testing.T) { jb, err := directrequest.ValidatedDirectRequestSpec(testspecs.GetDirectRequestSpec()) require.NoError(t, err) - jb.DirectRequestSpec.EVMChainID = utils.NewBigI(0) + jb.DirectRequestSpec.EVMChainID = big.NewI(0) err = orm.CreateJob(&jb) require.NoError(t, err) diff --git a/core/services/job/mocks/orm.go b/core/services/job/mocks/orm.go index 66602c60053..062c6e936bc 100644 --- a/core/services/job/mocks/orm.go +++ b/core/services/job/mocks/orm.go @@ -3,9 +3,10 @@ package mocks import ( - context "context" - common "github.com/ethereum/go-ethereum/common" + big "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" + + context "context" ethkey "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" @@ -17,8 +18,6 @@ import ( pipeline "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" - utils "github.com/smartcontractkit/chainlink/v2/core/utils" - uuid "github.com/google/uuid" ) @@ -223,7 +222,7 @@ func (_m *ORM) FindJobByExternalJobID(_a0 uuid.UUID, qopts ...pg.QOpt) (job.Job, } // FindJobIDByAddress provides a mock function with given fields: address, evmChainID, qopts -func (_m *ORM) FindJobIDByAddress(address ethkey.EIP55Address, evmChainID *utils.Big, qopts ...pg.QOpt) (int32, error) { +func (_m *ORM) FindJobIDByAddress(address ethkey.EIP55Address, evmChainID *big.Big, qopts ...pg.QOpt) (int32, error) { _va := make([]interface{}, len(qopts)) for _i := range qopts { _va[_i] = qopts[_i] @@ -239,16 +238,16 @@ func (_m *ORM) FindJobIDByAddress(address ethkey.EIP55Address, evmChainID *utils var r0 int32 var r1 error - if rf, ok := ret.Get(0).(func(ethkey.EIP55Address, *utils.Big, ...pg.QOpt) (int32, error)); ok { + if rf, ok := ret.Get(0).(func(ethkey.EIP55Address, *big.Big, ...pg.QOpt) (int32, error)); ok { return rf(address, evmChainID, qopts...) } - if rf, ok := ret.Get(0).(func(ethkey.EIP55Address, *utils.Big, ...pg.QOpt) int32); ok { + if rf, ok := ret.Get(0).(func(ethkey.EIP55Address, *big.Big, ...pg.QOpt) int32); ok { r0 = rf(address, evmChainID, qopts...) } else { r0 = ret.Get(0).(int32) } - if rf, ok := ret.Get(1).(func(ethkey.EIP55Address, *utils.Big, ...pg.QOpt) error); ok { + if rf, ok := ret.Get(1).(func(ethkey.EIP55Address, *big.Big, ...pg.QOpt) error); ok { r1 = rf(address, evmChainID, qopts...) } else { r1 = ret.Error(1) diff --git a/core/services/job/models.go b/core/services/job/models.go index 18a0cb79e2a..b21ecc12e72 100644 --- a/core/services/job/models.go +++ b/core/services/job/models.go @@ -20,6 +20,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" clnull "github.com/smartcontractkit/chainlink/v2/core/null" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" @@ -246,7 +247,7 @@ type OCROracleSpec struct { ContractConfigTrackerSubscribeInterval models.Interval `toml:"contractConfigTrackerSubscribeInterval"` ContractConfigTrackerPollInterval models.Interval `toml:"contractConfigTrackerPollInterval"` ContractConfigConfirmations uint16 `toml:"contractConfigConfirmations"` - EVMChainID *utils.Big `toml:"evmChainID" db:"evm_chain_id"` + EVMChainID *big.Big `toml:"evmChainID" db:"evm_chain_id"` DatabaseTimeout *models.Interval `toml:"databaseTimeout"` ObservationGracePeriod *models.Interval `toml:"observationGracePeriod"` ContractTransmitterTransmitTimeout *models.Interval `toml:"contractTransmitterTransmitTimeout"` @@ -434,7 +435,7 @@ type DirectRequestSpec struct { MinIncomingConfirmations clnull.Uint32 `toml:"minIncomingConfirmations"` Requesters models.AddressCollection `toml:"requesters"` MinContractPayment *commonassets.Link `toml:"minContractPaymentLinkJuels"` - EVMChainID *utils.Big `toml:"evmChainID"` + EVMChainID *big.Big `toml:"evmChainID"` CreatedAt time.Time `toml:"-"` UpdatedAt time.Time `toml:"-"` } @@ -475,9 +476,9 @@ type FluxMonitorSpec struct { DrumbeatRandomDelay time.Duration DrumbeatEnabled bool MinPayment *commonassets.Link - EVMChainID *utils.Big `toml:"evmChainID"` - CreatedAt time.Time `toml:"-"` - UpdatedAt time.Time `toml:"-"` + EVMChainID *big.Big `toml:"evmChainID"` + CreatedAt time.Time `toml:"-"` + UpdatedAt time.Time `toml:"-"` } type KeeperSpec struct { @@ -485,7 +486,7 @@ type KeeperSpec struct { ContractAddress ethkey.EIP55Address `toml:"contractAddress"` MinIncomingConfirmations *uint32 `toml:"minIncomingConfirmations"` FromAddress ethkey.EIP55Address `toml:"fromAddress"` - EVMChainID *utils.Big `toml:"evmChainID"` + EVMChainID *big.Big `toml:"evmChainID"` CreatedAt time.Time `toml:"-"` UpdatedAt time.Time `toml:"-"` } @@ -512,7 +513,7 @@ type VRFSpec struct { CoordinatorAddress ethkey.EIP55Address `toml:"coordinatorAddress"` PublicKey secp256k1.PublicKey `toml:"publicKey"` MinIncomingConfirmations uint32 `toml:"minIncomingConfirmations"` - EVMChainID *utils.Big `toml:"evmChainID"` + EVMChainID *big.Big `toml:"evmChainID"` FromAddresses []ethkey.EIP55Address `toml:"fromAddresses"` PollPeriod time.Duration `toml:"pollPeriod"` // For v2 jobs RequestedConfsDelay int64 `toml:"requestedConfsDelay"` // For v2 jobs. Optional, defaults to 0 if not provided. @@ -586,7 +587,7 @@ type BlockhashStoreSpec struct { RunTimeout time.Duration `toml:"runTimeout"` // EVMChainID defines the chain ID for monitoring and storing of blockhashes. - EVMChainID *utils.Big `toml:"evmChainID"` + EVMChainID *big.Big `toml:"evmChainID"` // FromAddress is the sender address that should be used to store blockhashes. FromAddresses []ethkey.EIP55Address `toml:"fromAddresses"` @@ -635,7 +636,7 @@ type BlockHeaderFeederSpec struct { RunTimeout time.Duration `toml:"runTimeout"` // EVMChainID defines the chain ID for monitoring and storing of blockhashes. - EVMChainID *utils.Big `toml:"evmChainID"` + EVMChainID *big.Big `toml:"evmChainID"` // FromAddress is the sender address that should be used to store blockhashes. FromAddresses []ethkey.EIP55Address `toml:"fromAddresses"` @@ -662,11 +663,11 @@ type LegacyGasStationServerSpec struct { ForwarderAddress ethkey.EIP55Address `toml:"forwarderAddress"` // EVMChainID defines the chain ID from which the meta-transaction request originates. - EVMChainID *utils.Big `toml:"evmChainID"` + EVMChainID *big.Big `toml:"evmChainID"` // CCIPChainSelector is the CCIP chain selector that corresponds to EVMChainID param. // This selector is equivalent to (source) chainID specified in SendTransaction request - CCIPChainSelector *utils.Big `toml:"ccipChainSelector"` + CCIPChainSelector *big.Big `toml:"ccipChainSelector"` // FromAddress is the sender address that should be used to send meta-transactions FromAddresses []ethkey.EIP55Address `toml:"fromAddresses"` @@ -699,10 +700,10 @@ type LegacyGasStationSidecarSpec struct { RunTimeout time.Duration `toml:"runTimeout"` // EVMChainID defines the chain ID for the on-chain events tracked by sidecar - EVMChainID *utils.Big `toml:"evmChainID"` + EVMChainID *big.Big `toml:"evmChainID"` // CCIPChainSelector is the CCIP chain selector that corresponds to EVMChainID param - CCIPChainSelector *utils.Big `toml:"ccipChainSelector"` + CCIPChainSelector *big.Big `toml:"ccipChainSelector"` // CreatedAt is the time this job was created. CreatedAt time.Time `toml:"-"` @@ -772,7 +773,7 @@ type EALSpec struct { ForwarderAddress ethkey.EIP55Address `toml:"forwarderAddress"` // EVMChainID defines the chain ID from which the meta-transaction request originates. - EVMChainID *utils.Big `toml:"evmChainID"` + EVMChainID *big.Big `toml:"evmChainID"` // FromAddress is the sender address that should be used to send meta-transactions FromAddresses []ethkey.EIP55Address `toml:"fromAddresses"` diff --git a/core/services/job/orm.go b/core/services/job/orm.go index 482d3d851e4..b2cf2b2af4b 100644 --- a/core/services/job/orm.go +++ b/core/services/job/orm.go @@ -22,6 +22,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/bridges" evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/config" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/null" @@ -32,7 +33,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/core/store/models" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) var ( @@ -52,7 +52,7 @@ type ORM interface { FindJobTx(ctx context.Context, id int32) (Job, error) FindJob(ctx context.Context, id int32) (Job, error) FindJobByExternalJobID(uuid uuid.UUID, qopts ...pg.QOpt) (Job, error) - FindJobIDByAddress(address ethkey.EIP55Address, evmChainID *utils.Big, qopts ...pg.QOpt) (int32, error) + FindJobIDByAddress(address ethkey.EIP55Address, evmChainID *big.Big, qopts ...pg.QOpt) (int32, error) FindOCR2JobIDByAddress(contractID string, feedID *common.Hash, qopts ...pg.QOpt) (int32, error) FindJobIDsWithBridge(name string) ([]int32, error) DeleteJob(id int32, qopts ...pg.QOpt) error @@ -832,7 +832,7 @@ func (o *orm) FindJobByExternalJobID(externalJobID uuid.UUID, qopts ...pg.QOpt) } // FindJobIDByAddress - finds a job id by contract address. Currently only OCR and FM jobs are supported -func (o *orm) FindJobIDByAddress(address ethkey.EIP55Address, evmChainID *utils.Big, qopts ...pg.QOpt) (jobID int32, err error) { +func (o *orm) FindJobIDByAddress(address ethkey.EIP55Address, evmChainID *big.Big, qopts ...pg.QOpt) (jobID int32, err error) { q := o.q.WithOpts(qopts...) err = q.Transaction(func(tx pg.Queryer) error { stmt := ` diff --git a/core/services/keeper/integration_test.go b/core/services/keeper/integration_test.go index 29a0b68702d..c35ebc81b7f 100644 --- a/core/services/keeper/integration_test.go +++ b/core/services/keeper/integration_test.go @@ -19,6 +19,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/basic_upkeep_contract" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_logic1_3" @@ -36,7 +37,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keeper" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" "github.com/smartcontractkit/chainlink/v2/core/store/models" - "github.com/smartcontractkit/chainlink/v2/core/utils" webpresenters "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) @@ -405,7 +405,7 @@ func TestKeeperForwarderEthIntegration(t *testing.T) { c.EVM[0].MinIncomingConfirmations = ptr[uint32](1) // disable reorg protection for this test c.EVM[0].HeadTracker.MaxBufferSize = ptr[uint32](100) // helps prevent missed heads c.EVM[0].Transactions.ForwardersEnabled = ptr(true) // Enable Operator Forwarder flow - c.EVM[0].ChainID = (*utils.Big)(testutils.SimulatedChainID) + c.EVM[0].ChainID = (*ubig.Big)(testutils.SimulatedChainID) }) scopedConfig := evmtest.NewChainScopedConfig(t, config) korm := keeper.NewORM(db, logger.TestLogger(t), scopedConfig.Database()) @@ -414,7 +414,7 @@ func TestKeeperForwarderEthIntegration(t *testing.T) { require.NoError(t, app.Start(testutils.Context(t))) forwarderORM := forwarders.NewORM(db, logger.TestLogger(t), config.Database()) - chainID := utils.Big(*backend.ConfiguredChainID()) + chainID := ubig.Big(*backend.ConfiguredChainID()) _, err = forwarderORM.CreateForwarder(fwdrAddress, chainID) require.NoError(t, err) @@ -431,7 +431,7 @@ func TestKeeperForwarderEthIntegration(t *testing.T) { KeeperSpec: &job.KeeperSpec{ FromAddress: nodeAddressEIP55, ContractAddress: regAddrEIP55, - EVMChainID: (*utils.Big)(testutils.SimulatedChainID), + EVMChainID: (*ubig.Big)(testutils.SimulatedChainID), }, SchemaVersion: 1, ForwardingAllowed: true, diff --git a/core/services/keeper/models.go b/core/services/keeper/models.go index fd5538b6047..8f72f0b22c9 100644 --- a/core/services/keeper/models.go +++ b/core/services/keeper/models.go @@ -8,6 +8,7 @@ import ( "github.com/pkg/errors" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/null" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" "github.com/smartcontractkit/chainlink/v2/core/utils" @@ -34,7 +35,7 @@ type UpkeepRegistration struct { LastRunBlockHeight int64 RegistryID int64 Registry Registry - UpkeepID *utils.Big + UpkeepID *big.Big LastKeeperIndex null.Int64 PositioningConstant int32 } @@ -60,16 +61,16 @@ func (upkeep UpkeepRegistration) PrettyID() string { return NewUpkeepIdentifier(upkeep.UpkeepID).String() } -func NewUpkeepIdentifier(i *utils.Big) *UpkeepIdentifier { +func NewUpkeepIdentifier(i *big.Big) *UpkeepIdentifier { val := UpkeepIdentifier(*i) return &val } -type UpkeepIdentifier utils.Big +type UpkeepIdentifier big.Big // String produces a hex encoded value, zero padded, prefixed with UpkeepPrefix func (ui UpkeepIdentifier) String() string { - val := utils.Big(ui) + val := big.Big(ui) result, err := utils.Uint256ToBytes(val.ToInt()) if err != nil { panic(errors.Wrap(err, "invariant, invalid upkeepID")) diff --git a/core/services/keeper/models_test.go b/core/services/keeper/models_test.go index ad81f47d8ee..729d1bbf231 100644 --- a/core/services/keeper/models_test.go +++ b/core/services/keeper/models_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink/v2/core/utils" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" ) func TestUpkeepIdentifer_String(t *testing.T) { @@ -26,7 +26,7 @@ func TestUpkeepIdentifer_String(t *testing.T) { return } - result := NewUpkeepIdentifier(utils.NewBig(o)).String() + result := NewUpkeepIdentifier(ubig.New(o)).String() require.Equal(t, test.hex, result) }) } diff --git a/core/services/keeper/orm.go b/core/services/keeper/orm.go index 91883f8056c..fc8770cd864 100644 --- a/core/services/keeper/orm.go +++ b/core/services/keeper/orm.go @@ -7,10 +7,10 @@ import ( "github.com/lib/pq" "github.com/pkg/errors" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" "github.com/smartcontractkit/chainlink/v2/core/services/pg" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) // ORM implements ORM layer using PostgreSQL @@ -86,7 +86,7 @@ RETURNING * } // UpdateUpkeepLastKeeperIndex updates the last keeper index for an upkeep -func (korm ORM) UpdateUpkeepLastKeeperIndex(jobID int32, upkeepID *utils.Big, fromAddress ethkey.EIP55Address) error { +func (korm ORM) UpdateUpkeepLastKeeperIndex(jobID int32, upkeepID *big.Big, fromAddress ethkey.EIP55Address) error { _, err := korm.q.Exec(` UPDATE upkeep_registrations SET @@ -98,7 +98,7 @@ func (korm ORM) UpdateUpkeepLastKeeperIndex(jobID int32, upkeepID *utils.Big, fr } // BatchDeleteUpkeepsForJob deletes all upkeeps by the given IDs for the job with the given ID -func (korm ORM) BatchDeleteUpkeepsForJob(jobID int32, upkeepIDs []utils.Big) (int64, error) { +func (korm ORM) BatchDeleteUpkeepsForJob(jobID int32, upkeepIDs []big.Big) (int64, error) { strIds := []string{} for _, upkeepID := range upkeepIDs { strIds = append(strIds, upkeepID.String()) @@ -202,7 +202,7 @@ func loadUpkeepsRegistry(q pg.Queryer, upkeeps []UpkeepRegistration) error { return nil } -func (korm ORM) AllUpkeepIDsForRegistry(regID int64) (upkeeps []utils.Big, err error) { +func (korm ORM) AllUpkeepIDsForRegistry(regID int64) (upkeeps []big.Big, err error) { err = korm.q.Select(&upkeeps, ` SELECT upkeep_id FROM upkeep_registrations @@ -212,7 +212,7 @@ WHERE registry_id = $1 } // SetLastRunInfoForUpkeepOnJob sets the last run block height and the associated keeper index only if the new block height is greater than the previous. -func (korm ORM) SetLastRunInfoForUpkeepOnJob(jobID int32, upkeepID *utils.Big, height int64, fromAddress ethkey.EIP55Address, qopts ...pg.QOpt) (int64, error) { +func (korm ORM) SetLastRunInfoForUpkeepOnJob(jobID int32, upkeepID *big.Big, height int64, fromAddress ethkey.EIP55Address, qopts ...pg.QOpt) (int64, error) { res, err := korm.q.WithOpts(qopts...).Exec(` UPDATE upkeep_registrations SET last_run_block_height = $1, diff --git a/core/services/keeper/orm_test.go b/core/services/keeper/orm_test.go index d67baa09a06..e5b56e9511e 100644 --- a/core/services/keeper/orm_test.go +++ b/core/services/keeper/orm_test.go @@ -15,6 +15,7 @@ import ( "github.com/jmoiron/sqlx" evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" @@ -45,7 +46,7 @@ func setupKeeperDB(t *testing.T) ( func newUpkeep(registry keeper.Registry, upkeepID int64) keeper.UpkeepRegistration { return keeper.UpkeepRegistration{ - UpkeepID: utils.NewBigI(upkeepID), + UpkeepID: ubig.NewI(upkeepID), ExecuteGas: executeGas, Registry: registry, RegistryID: registry.ID, @@ -103,7 +104,7 @@ func TestKeeperDB_UpsertUpkeep(t *testing.T) { registry, _ := cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 0, 1, 20) upkeep := keeper.UpkeepRegistration{ - UpkeepID: utils.NewBigI(0), + UpkeepID: ubig.NewI(0), ExecuteGas: executeGas, Registry: registry, RegistryID: registry.ID, @@ -139,7 +140,7 @@ func TestKeeperDB_BatchDeleteUpkeepsForJob(t *testing.T) { registry, job := cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 0, 1, 20) expectedUpkeepID := cltest.MustInsertUpkeepForRegistry(t, db, config.Database(), registry).UpkeepID - var upkeepIDs []utils.Big + var upkeepIDs []ubig.Big for i := 0; i < 2; i++ { upkeep := cltest.MustInsertUpkeepForRegistry(t, db, config.Database(), registry) upkeepIDs = append(upkeepIDs, *upkeep.UpkeepID) @@ -180,7 +181,7 @@ func TestKeeperDB_EligibleUpkeeps_Shuffle(t *testing.T) { assert.NoError(t, err) require.Len(t, eligibleUpkeeps, 100) - shuffled := [100]*utils.Big{} + shuffled := [100]*ubig.Big{} for i := 0; i < 100; i++ { shuffled[i] = eligibleUpkeeps[i].UpkeepID } @@ -372,8 +373,8 @@ func TestKeeperDB_AllUpkeepIDsForRegistry(t *testing.T) { require.NoError(t, err) // No upkeeps returned require.Len(t, upkeepIDs, 2) - require.Contains(t, upkeepIDs, *utils.NewBig(big.NewInt(3))) - require.Contains(t, upkeepIDs, *utils.NewBig(big.NewInt(8))) + require.Contains(t, upkeepIDs, *ubig.New(big.NewInt(3))) + require.Contains(t, upkeepIDs, *ubig.New(big.NewInt(8))) } func TestKeeperDB_UpdateUpkeepLastKeeperIndex(t *testing.T) { diff --git a/core/services/keeper/registry1_1_synchronizer_test.go b/core/services/keeper/registry1_1_synchronizer_test.go index fb0b1866c41..a4f03d4d34a 100644 --- a/core/services/keeper/registry1_1_synchronizer_test.go +++ b/core/services/keeper/registry1_1_synchronizer_test.go @@ -16,6 +16,7 @@ import ( evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" logmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log/mocks" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" registry1_1 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_1" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -24,7 +25,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/keeper" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) var registryConfig1_1 = registry1_1.GetConfig{ @@ -123,7 +123,7 @@ func Test_RegistrySynchronizer1_1_Start(t *testing.T) { func Test_RegistrySynchronizer_CalcPositioningConstant(t *testing.T) { t.Parallel() for _, upkeepID := range []int64{0, 1, 100, 10_000} { - _, err := keeper.CalcPositioningConstant(utils.NewBigI(upkeepID), cltest.NewEIP55Address()) + _, err := keeper.CalcPositioningConstant(ubig.NewI(upkeepID), cltest.NewEIP55Address()) require.NoError(t, err) } } diff --git a/core/services/keeper/registry1_3_synchronizer_test.go b/core/services/keeper/registry1_3_synchronizer_test.go index 6e3be4ea785..77bb873e1d0 100644 --- a/core/services/keeper/registry1_3_synchronizer_test.go +++ b/core/services/keeper/registry1_3_synchronizer_test.go @@ -17,6 +17,7 @@ import ( evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" logmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log/mocks" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" registry1_3 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_3" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -25,7 +26,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/keeper" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) var registryConfig1_3 = registry1_3.Config{ @@ -654,7 +654,7 @@ func Test_RegistrySynchronizer1_3_UpkeepPausedLog_UpkeepUnpausedLog(t *testing.T cltest.WaitForCount(t, db, "upkeep_registrations", 3) var upkeep keeper.UpkeepRegistration - err := db.Get(&upkeep, `SELECT * FROM upkeep_registrations WHERE upkeep_id = $1`, utils.NewBig(upkeepId)) + err := db.Get(&upkeep, `SELECT * FROM upkeep_registrations WHERE upkeep_id = $1`, ubig.New(upkeepId)) require.NoError(t, err) require.Equal(t, upkeepId.String(), upkeep.UpkeepID.String()) @@ -714,7 +714,7 @@ func Test_RegistrySynchronizer1_3_UpkeepCheckDataUpdatedLog(t *testing.T) { g.Eventually(func() []byte { var upkeep keeper.UpkeepRegistration - err := db.Get(&upkeep, `SELECT * FROM upkeep_registrations WHERE upkeep_id = $1`, utils.NewBig(upkeepId)) + err := db.Get(&upkeep, `SELECT * FROM upkeep_registrations WHERE upkeep_id = $1`, ubig.New(upkeepId)) require.NoError(t, err) return upkeep.CheckData }, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.Equal(newCheckData)) diff --git a/core/services/keeper/registry_synchronizer_process_logs.go b/core/services/keeper/registry_synchronizer_process_logs.go index 9e1aa3b410b..7b82f49ae4c 100644 --- a/core/services/keeper/registry_synchronizer_process_logs.go +++ b/core/services/keeper/registry_synchronizer_process_logs.go @@ -7,11 +7,11 @@ import ( "github.com/pkg/errors" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" registry1_1 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_1" registry1_2 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_2" registry1_3 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_3" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func (rs *RegistrySynchronizer) processLogs() { @@ -109,7 +109,7 @@ func (rs *RegistrySynchronizer) handleUpkeepCancelled(broadcast log.Broadcast) e return errors.Wrap(err, "Unable to fetch cancelled upkeep ID from log") } - affected, err := rs.orm.BatchDeleteUpkeepsForJob(rs.job.ID, []utils.Big{*utils.NewBig(cancelledID)}) + affected, err := rs.orm.BatchDeleteUpkeepsForJob(rs.job.ID, []big.Big{*big.New(cancelledID)}) if err != nil { return errors.Wrap(err, "unable to batch delete upkeeps") } @@ -130,7 +130,7 @@ func (rs *RegistrySynchronizer) handleUpkeepRegistered(broadcast log.Broadcast) return errors.Wrap(err, "Unable to fetch upkeep ID from registration log") } - err = rs.syncUpkeep(&rs.registryWrapper, registry, utils.NewBig(upkeepID)) + err = rs.syncUpkeep(&rs.registryWrapper, registry, big.New(upkeepID)) if err != nil { return errors.Wrapf(err, "failed to sync upkeep, log: %v", broadcast.String()) } @@ -144,7 +144,7 @@ func (rs *RegistrySynchronizer) handleUpkeepPerformed(broadcast log.Broadcast) e if err != nil { return errors.Wrap(err, "Unable to fetch upkeep ID from performed log") } - rowsAffected, err := rs.orm.SetLastRunInfoForUpkeepOnJob(rs.job.ID, utils.NewBig(log.UpkeepID), int64(broadcast.RawLog().BlockNumber), ethkey.EIP55AddressFromAddress(log.FromKeeper)) + rowsAffected, err := rs.orm.SetLastRunInfoForUpkeepOnJob(rs.job.ID, big.New(log.UpkeepID), int64(broadcast.RawLog().BlockNumber), ethkey.EIP55AddressFromAddress(log.FromKeeper)) if err != nil { return errors.Wrap(err, "failed to set last run to 0") } @@ -171,7 +171,7 @@ func (rs *RegistrySynchronizer) handleUpkeepGasLimitSet(broadcast log.Broadcast) return errors.Wrap(err, "Unable to fetch upkeep ID from gas limit set log") } - err = rs.syncUpkeep(&rs.registryWrapper, registry, utils.NewBig(upkeepID)) + err = rs.syncUpkeep(&rs.registryWrapper, registry, big.New(upkeepID)) if err != nil { return errors.Wrapf(err, "failed to sync upkeep, log: %v", broadcast.String()) } @@ -191,7 +191,7 @@ func (rs *RegistrySynchronizer) handleUpkeepReceived(broadcast log.Broadcast) er return errors.Wrap(err, "Unable to fetch upkeep ID from received log") } - err = rs.syncUpkeep(&rs.registryWrapper, registry, utils.NewBig(upkeepID)) + err = rs.syncUpkeep(&rs.registryWrapper, registry, big.New(upkeepID)) if err != nil { return errors.Wrapf(err, "failed to sync upkeep, log: %v", broadcast.String()) } @@ -206,7 +206,7 @@ func (rs *RegistrySynchronizer) handleUpkeepMigrated(broadcast log.Broadcast) er return errors.Wrap(err, "Unable to fetch migrated upkeep ID from log") } - affected, err := rs.orm.BatchDeleteUpkeepsForJob(rs.job.ID, []utils.Big{*utils.NewBig(migratedID)}) + affected, err := rs.orm.BatchDeleteUpkeepsForJob(rs.job.ID, []big.Big{*big.New(migratedID)}) if err != nil { return errors.Wrap(err, "unable to batch delete upkeeps") } @@ -222,7 +222,7 @@ func (rs *RegistrySynchronizer) handleUpkeepPaused(broadcast log.Broadcast) erro return errors.Wrap(err, "Unable to fetch upkeep ID from upkeep paused log") } - _, err = rs.orm.BatchDeleteUpkeepsForJob(rs.job.ID, []utils.Big{*utils.NewBig(pausedUpkeepId)}) + _, err = rs.orm.BatchDeleteUpkeepsForJob(rs.job.ID, []big.Big{*big.New(pausedUpkeepId)}) if err != nil { return errors.Wrap(err, "unable to batch delete upkeeps") } @@ -243,7 +243,7 @@ func (rs *RegistrySynchronizer) handleUpkeepUnpaused(broadcast log.Broadcast) er return errors.Wrap(err, "Unable to fetch upkeep ID from upkeep unpaused log") } - err = rs.syncUpkeep(&rs.registryWrapper, registry, utils.NewBig(unpausedUpkeepId)) + err = rs.syncUpkeep(&rs.registryWrapper, registry, big.New(unpausedUpkeepId)) if err != nil { return errors.Wrapf(err, "failed to sync upkeep, log: %s", broadcast.String()) } @@ -264,7 +264,7 @@ func (rs *RegistrySynchronizer) handleUpkeepCheckDataUpdated(broadcast log.Broad return errors.Wrap(err, "Unable to parse update log from upkeep check data updated log") } - err = rs.syncUpkeep(&rs.registryWrapper, registry, utils.NewBig(updateLog.UpkeepID)) + err = rs.syncUpkeep(&rs.registryWrapper, registry, big.New(updateLog.UpkeepID)) if err != nil { return errors.Wrapf(err, "unable to update check data for upkeep %s", updateLog.UpkeepID.String()) } diff --git a/core/services/keeper/registry_synchronizer_sync.go b/core/services/keeper/registry_synchronizer_sync.go index 649ccd94066..f90e0bc85d7 100644 --- a/core/services/keeper/registry_synchronizer_sync.go +++ b/core/services/keeper/registry_synchronizer_sync.go @@ -7,6 +7,7 @@ import ( "github.com/pkg/errors" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" "github.com/smartcontractkit/chainlink/v2/core/utils" ) @@ -53,15 +54,15 @@ func (rs *RegistrySynchronizer) fullSyncUpkeeps(reg Registry) error { } activeSet := make(map[string]bool) - allActiveUpkeeps := make([]utils.Big, 0) + allActiveUpkeeps := make([]big.Big, 0) for _, upkeepID := range activeUpkeepIDs { activeSet[upkeepID.String()] = true - allActiveUpkeeps = append(allActiveUpkeeps, *utils.NewBig(upkeepID)) + allActiveUpkeeps = append(allActiveUpkeeps, *big.New(upkeepID)) } rs.batchSyncUpkeepsOnRegistry(reg, allActiveUpkeeps) // All upkeeps in existingUpkeepIDs, not in activeUpkeepIDs should be deleted - canceled := make([]utils.Big, 0) + canceled := make([]big.Big, 0) for _, upkeepID := range existingUpkeepIDs { if _, found := activeSet[upkeepID.ToInt().String()]; !found { canceled = append(canceled, upkeepID) @@ -75,7 +76,7 @@ func (rs *RegistrySynchronizer) fullSyncUpkeeps(reg Registry) error { // batchSyncUpkeepsOnRegistry syncs upkeeps at a time in parallel // for all the IDs within newUpkeeps slice -func (rs *RegistrySynchronizer) batchSyncUpkeepsOnRegistry(reg Registry, newUpkeeps []utils.Big) { +func (rs *RegistrySynchronizer) batchSyncUpkeepsOnRegistry(reg Registry, newUpkeeps []big.Big) { wg := sync.WaitGroup{} wg.Add(len(newUpkeeps)) chSyncUpkeepQueue := make(chan struct{}, rs.syncUpkeepQueueSize) @@ -93,7 +94,7 @@ func (rs *RegistrySynchronizer) batchSyncUpkeepsOnRegistry(reg Registry, newUpke wg.Wait() } -func (rs *RegistrySynchronizer) syncUpkeepWithCallback(getter upkeepGetter, registry Registry, upkeepID *utils.Big, doneCallback func()) { +func (rs *RegistrySynchronizer) syncUpkeepWithCallback(getter upkeepGetter, registry Registry, upkeepID *big.Big, doneCallback func()) { defer doneCallback() if err := rs.syncUpkeep(getter, registry, upkeepID); err != nil { @@ -104,7 +105,7 @@ func (rs *RegistrySynchronizer) syncUpkeepWithCallback(getter upkeepGetter, regi } } -func (rs *RegistrySynchronizer) syncUpkeep(getter upkeepGetter, registry Registry, upkeepID *utils.Big) error { +func (rs *RegistrySynchronizer) syncUpkeep(getter upkeepGetter, registry Registry, upkeepID *big.Big) error { upkeep, err := getter.GetUpkeep(nil, upkeepID.ToInt()) if err != nil { return errors.Wrap(err, "failed to get upkeep config") @@ -173,9 +174,9 @@ func (rs *RegistrySynchronizer) newRegistryFromChain() (Registry, error) { // CalcPositioningConstant calculates a positioning constant. // The positioning constant is fixed because upkeepID and registryAddress are immutable -func CalcPositioningConstant(upkeepID *utils.Big, registryAddress ethkey.EIP55Address) (int32, error) { +func CalcPositioningConstant(upkeepID *big.Big, registryAddress ethkey.EIP55Address) (int32, error) { upkeepBytes := make([]byte, binary.MaxVarintLen64) - binary.PutVarint(upkeepBytes, upkeepID.Mod(utils.NewBigI(math.MaxInt64)).Int64()) + binary.PutVarint(upkeepBytes, upkeepID.Mod(big.NewI(math.MaxInt64)).Int64()) bytesToHash := utils.ConcatBytes(upkeepBytes, registryAddress.Bytes()) checksum, err := utils.Keccak256(bytesToHash) if err != nil { diff --git a/core/services/keeper/registry_synchronizer_sync_test.go b/core/services/keeper/registry_synchronizer_sync_test.go index 10a51679c5e..e6f42a83201 100644 --- a/core/services/keeper/registry_synchronizer_sync_test.go +++ b/core/services/keeper/registry_synchronizer_sync_test.go @@ -10,10 +10,10 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) // GetUpkeepFailure implements the upkeepGetter interface with an induced error and nil @@ -42,7 +42,7 @@ func TestSyncUpkeepWithCallback_UpkeepNotFound(t *testing.T) { t.FailNow() } - id := utils.NewBig(o) + id := ubig.New(o) count := 0 doneFunc := func() { count++ diff --git a/core/services/keeper/upkeep_executer_test.go b/core/services/keeper/upkeep_executer_test.go index 123b1dc0de1..61ccca956f4 100644 --- a/core/services/keeper/upkeep_executer_test.go +++ b/core/services/keeper/upkeep_executer_test.go @@ -23,6 +23,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" txmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -39,7 +40,7 @@ import ( ) func newHead() evmtypes.Head { - return evmtypes.NewHead(big.NewInt(20), utils.NewHash(), utils.NewHash(), 1000, utils.NewBigI(0)) + return evmtypes.NewHead(big.NewInt(20), utils.NewHash(), utils.NewHash(), 1000, ubig.NewI(0)) } func mockEstimator(t *testing.T) gas.EvmFeeEstimator { @@ -128,7 +129,7 @@ func Test_UpkeepExecuter_PerformsUpkeep_Happy(t *testing.T) { t.Run("runs upkeep on triggering block number", func(t *testing.T) { db, config, ethMock, executer, registry, upkeep, job, jpv2, txm, _, _, _ := setup(t, mockEstimator(t), func(c *chainlink.Config, s *chainlink.Secrets) { - c.EVM[0].ChainID = (*utils.Big)(testutils.SimulatedChainID) + c.EVM[0].ChainID = (*ubig.Big)(testutils.SimulatedChainID) }) gasLimit := 5_000_000 + config.Keeper().Registry().PerformGasOverhead() @@ -173,7 +174,7 @@ func Test_UpkeepExecuter_PerformsUpkeep_Happy(t *testing.T) { runTest := func(t *testing.T, eip1559 bool) { db, config, ethMock, executer, registry, upkeep, job, jpv2, txm, _, _, _ := setup(t, mockEstimator(t), func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].GasEstimator.EIP1559DynamicFees = &eip1559 - c.EVM[0].ChainID = (*utils.Big)(testutils.SimulatedChainID) + c.EVM[0].ChainID = (*ubig.Big)(testutils.SimulatedChainID) }) gasLimit := 5_000_000 + config.Keeper().Registry().PerformGasOverhead() @@ -226,7 +227,7 @@ func Test_UpkeepExecuter_PerformsUpkeep_Happy(t *testing.T) { t.Run("errors if submission key not found", func(t *testing.T) { _, _, ethMock, executer, registry, _, job, jpv2, _, keyStore, _, _ := setup(t, mockEstimator(t), func(c *chainlink.Config, s *chainlink.Secrets) { - c.EVM[0].ChainID = (*utils.Big)(testutils.SimulatedChainID) + c.EVM[0].ChainID = (*ubig.Big)(testutils.SimulatedChainID) }) // replace expected key with random one @@ -263,7 +264,7 @@ func Test_UpkeepExecuter_PerformsUpkeep_Happy(t *testing.T) { registry, jb := cltest.MustInsertKeeperRegistry(t, db, orm, keyStore.Eth(), 0, 1, 20) // change chain ID to non-configured chain - jb.KeeperSpec.EVMChainID = (*utils.Big)(big.NewInt(999)) + jb.KeeperSpec.EVMChainID = (*ubig.Big)(big.NewInt(999)) cltest.MustInsertUpkeepForRegistry(t, db, ch.Config().Database(), registry) lggr := logger.TestLogger(t) executer := keeper.NewUpkeepExecuter(jb, orm, jpv2.Pr, ethMock, ch.HeadBroadcaster(), ch.GasEstimator(), lggr, ch.Config().Keeper(), jb.KeeperSpec.FromAddress.Address()) @@ -278,7 +279,7 @@ func Test_UpkeepExecuter_PerformsUpkeep_Happy(t *testing.T) { t.Run("triggers if heads are skipped but later heads arrive within range", func(t *testing.T) { db, config, ethMock, executer, registry, upkeep, job, jpv2, txm, _, _, _ := setup(t, mockEstimator(t), func(c *chainlink.Config, s *chainlink.Secrets) { - c.EVM[0].ChainID = (*utils.Big)(testutils.SimulatedChainID) + c.EVM[0].ChainID = (*ubig.Big)(testutils.SimulatedChainID) }) etxs := []cltest.Awaiter{ @@ -321,7 +322,7 @@ func Test_UpkeepExecuter_PerformsUpkeep_Error(t *testing.T) { db, _, ethMock, executer, registry, _, _, _, _, _, _, _ := setup(t, mockEstimator(t), func(c *chainlink.Config, s *chainlink.Secrets) { - c.EVM[0].ChainID = (*utils.Big)(testutils.SimulatedChainID) + c.EVM[0].ChainID = (*ubig.Big)(testutils.SimulatedChainID) }) var wasCalled atomic.Bool diff --git a/core/services/keeper/upkeep_executer_unit_test.go b/core/services/keeper/upkeep_executer_unit_test.go index a8fc46319cd..8589720ca5f 100644 --- a/core/services/keeper/upkeep_executer_unit_test.go +++ b/core/services/keeper/upkeep_executer_unit_test.go @@ -7,11 +7,11 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) type registry struct { @@ -34,7 +34,7 @@ func TestBuildJobSpec(t *testing.T) { ContractAddress: contract, }} - upkeepID := utils.NewBigI(4) + upkeepID := big.NewI(4) upkeep := UpkeepRegistration{ Registry: Registry{ FromAddress: from, diff --git a/core/services/keystore/eth_test.go b/core/services/keystore/eth_test.go index 42d6c575376..3935a44558b 100644 --- a/core/services/keystore/eth_test.go +++ b/core/services/keystore/eth_test.go @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/require" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" @@ -673,7 +674,7 @@ func Test_EthKeyStore_Delete(t *testing.T) { _, addr1 := cltest.MustInsertRandomKey(t, ks) _, addr2 := cltest.MustInsertRandomKey(t, ks) - cltest.MustInsertRandomKey(t, ks, *utils.NewBig(testutils.SimulatedChainID)) + cltest.MustInsertRandomKey(t, ks, *ubig.New(testutils.SimulatedChainID)) require.NoError(t, ks.Add(addr1, testutils.SimulatedChainID)) require.NoError(t, ks.Enable(addr1, testutils.SimulatedChainID)) diff --git a/core/services/keystore/keys/ethkey/models.go b/core/services/keystore/keys/ethkey/models.go index b90503c3ed6..df4c474b7b9 100644 --- a/core/services/keystore/keys/ethkey/models.go +++ b/core/services/keystore/keys/ethkey/models.go @@ -3,13 +3,13 @@ package ethkey import ( "time" - "github.com/smartcontractkit/chainlink/v2/core/utils" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" ) type State struct { ID int32 Address EIP55Address - EVMChainID utils.Big + EVMChainID big.Big Disabled bool CreatedAt time.Time UpdatedAt time.Time diff --git a/core/services/ocr/database.go b/core/services/ocr/database.go index 524dfa0e7bb..cec9596bb91 100644 --- a/core/services/ocr/database.go +++ b/core/services/ocr/database.go @@ -15,9 +15,9 @@ import ( "github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/pg" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) type db struct { @@ -161,7 +161,7 @@ func (d *db) WriteConfig(ctx context.Context, c ocrtypes.ContractConfig) error { } func (d *db) StorePendingTransmission(ctx context.Context, k ocrtypes.ReportTimestamp, p ocrtypes.PendingTransmission) error { - median := utils.NewBig(p.Median) + median := big.New(p.Median) var rs [][]byte var ss [][]byte // Note: p.Rs and p.Ss are of type [][32]byte. @@ -232,7 +232,7 @@ WHERE ocr_oracle_spec_id = $1 AND config_digest = $2 k := ocrtypes.ReportTimestamp{} p := ocrtypes.PendingTransmission{} - var median utils.Big + var median big.Big var rs [][]byte var ss [][]byte var vs []byte diff --git a/core/services/ocr2/delegate_test.go b/core/services/ocr2/delegate_test.go index b55e128119d..3da0c9cbfd6 100644 --- a/core/services/ocr2/delegate_test.go +++ b/core/services/ocr2/delegate_test.go @@ -11,6 +11,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types" evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" txmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" @@ -23,11 +24,10 @@ import ( ocr2validate "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/testdata/testspecs" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func TestGetEVMEffectiveTransmitterID(t *testing.T) { - customChainID := utils.NewBig(testutils.NewRandomEVMChainID()) + customChainID := big.New(testutils.NewRandomEVMChainID()) config := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { enabled := true diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/registry_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/registry_test.go index 0e0ceba7160..51448db35cf 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/registry_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/registry_test.go @@ -16,8 +16,8 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func TestGetActiveUpkeepKeys(t *testing.T) { @@ -176,8 +176,8 @@ func TestPollLogs(t *testing.T) { InputStart: 250, InputEnd: 500, OutputLogs: []logpoller.Log{ - {EvmChainId: utils.NewBig(big.NewInt(5)), LogIndex: 1}, - {EvmChainId: utils.NewBig(big.NewInt(6)), LogIndex: 2}, + {EvmChainId: ubig.New(big.NewInt(5)), LogIndex: 1}, + {EvmChainId: ubig.New(big.NewInt(6)), LogIndex: 2}, }, OutputErr: nil, }, diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/recoverer_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/recoverer_test.go index 89b19b4a819..65fe3c85fb8 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/recoverer_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/recoverer_test.go @@ -21,12 +21,12 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" lpmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/core" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/core/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/pg" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func TestLogRecoverer_GetRecoverables(t *testing.T) { @@ -1023,7 +1023,7 @@ func TestLogRecoverer_GetProposalData(t *testing.T) { LogsWithSigsFn: func(start, end int64, eventSigs []common.Hash, address common.Address, qopts ...pg.QOpt) ([]logpoller.Log, error) { return []logpoller.Log{ { - EvmChainId: utils.NewBig(big.NewInt(1)), + EvmChainId: ubig.New(big.NewInt(1)), LogIndex: 3, BlockHash: [32]byte{1}, BlockNumber: 80, diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_test.go index f3e4402092c..0d097ceadb4 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_test.go @@ -19,6 +19,7 @@ import ( types3 "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_utils_2_1" iregistry21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1" @@ -27,7 +28,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider" "github.com/smartcontractkit/chainlink/v2/core/services/pg" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func TestPollLogs(t *testing.T) { @@ -132,8 +132,8 @@ func TestPollLogs(t *testing.T) { InputStart: 250, InputEnd: 500, OutputLogs: []logpoller.Log{ - {EvmChainId: utils.NewBig(big.NewInt(5)), LogIndex: 1}, - {EvmChainId: utils.NewBig(big.NewInt(6)), LogIndex: 2}, + {EvmChainId: ubig.New(big.NewInt(5)), LogIndex: 1}, + {EvmChainId: ubig.New(big.NewInt(6)), LogIndex: 2}, }, OutputErr: nil, }, diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/upkeepstate/orm.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/upkeepstate/orm.go index c918ad595fa..a5bd738de4c 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/upkeepstate/orm.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/upkeepstate/orm.go @@ -7,18 +7,18 @@ import ( "github.com/jmoiron/sqlx" "github.com/lib/pq" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/pg" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) type orm struct { - chainID *utils.Big + chainID *ubig.Big q pg.Q } type persistedStateRecord struct { - UpkeepID *utils.Big + UpkeepID *ubig.Big WorkID string CompletionState uint8 BlockNumber int64 @@ -29,7 +29,7 @@ type persistedStateRecord struct { // NewORM creates an ORM scoped to chainID. func NewORM(chainID *big.Int, db *sqlx.DB, lggr logger.Logger, cfg pg.QConfig) *orm { return &orm{ - chainID: utils.NewBig(chainID), + chainID: ubig.New(chainID), q: pg.NewQ(db, lggr.Named("ORM"), cfg), } } @@ -43,12 +43,12 @@ func (o *orm) BatchInsertRecords(state []persistedStateRecord, qopts ...pg.QOpt) } type row struct { - EvmChainId *utils.Big + EvmChainId *ubig.Big WorkId string CompletionState uint8 BlockNumber int64 InsertedAt time.Time - UpkeepId *utils.Big + UpkeepId *ubig.Big IneligibilityReason uint8 } diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/upkeepstate/orm_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/upkeepstate/orm_test.go index 54ca7285dd0..bfd131b5055 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/upkeepstate/orm_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/upkeepstate/orm_test.go @@ -9,10 +9,10 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func TestInsertSelectDelete(t *testing.T) { @@ -23,7 +23,7 @@ func TestInsertSelectDelete(t *testing.T) { inserted := []persistedStateRecord{ { - UpkeepID: utils.NewBig(big.NewInt(2)), + UpkeepID: ubig.New(big.NewInt(2)), WorkID: "0x1", CompletionState: 100, BlockNumber: 2, diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/upkeepstate/store.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/upkeepstate/store.go index 4a4de5ea1ad..19b3c46f502 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/upkeepstate/store.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/upkeepstate/store.go @@ -12,6 +12,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/services" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/core" "github.com/smartcontractkit/chainlink/v2/core/services/pg" @@ -225,7 +226,7 @@ func (u *upkeepStateStore) upsertStateRecord(ctx context.Context, workID string, u.cache[workID] = record u.pendingRecords = append(u.pendingRecords, persistedStateRecord{ - UpkeepID: utils.NewBig(upkeepID), + UpkeepID: ubig.New(upkeepID), WorkID: record.workID, CompletionState: uint8(record.state), IneligibilityReason: reason, diff --git a/core/services/ocr2/plugins/ocr2keeper/integration_test.go b/core/services/ocr2/plugins/ocr2keeper/integration_test.go index 58c1e38e017..6674b0828b1 100644 --- a/core/services/ocr2/plugins/ocr2keeper/integration_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/integration_test.go @@ -37,6 +37,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/config/toml" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/basic_upkeep_contract" @@ -60,7 +61,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/store/models" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) const ( @@ -448,7 +448,7 @@ func setupForwarderForNode( // add forwarder address to be tracked in db forwarderORM := forwarders.NewORM(app.GetSqlxDB(), logger.TestLogger(t), app.GetConfig().Database()) - chainID := utils.Big(*backend.Blockchain().Config().ChainID) + chainID := ubig.Big(*backend.Blockchain().Config().ChainID) _, err = forwarderORM.CreateForwarder(faddr, chainID) require.NoError(t, err) diff --git a/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go b/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go index 4a583e5db3f..c559fb27fb7 100644 --- a/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go +++ b/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go @@ -33,6 +33,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_v3_aggregator_contract" @@ -285,7 +286,7 @@ func setupNodeOCR2( // Add the forwarder to the node's forwarder manager. forwarderORM := forwarders.NewORM(app.GetSqlxDB(), logger.TestLogger(t), config.Database()) - chainID := utils.Big(*b.Blockchain().Config().ChainID) + chainID := ubig.Big(*b.Blockchain().Config().ChainID) _, err = forwarderORM.CreateForwarder(faddr, chainID) require.NoError(t, err) effectiveTransmitter = faddr diff --git a/core/services/ocr2/plugins/s4/integration_test.go b/core/services/ocr2/plugins/s4/integration_test.go index 54f0f02ad98..8efe38f8e2d 100644 --- a/core/services/ocr2/plugins/s4/integration_test.go +++ b/core/services/ocr2/plugins/s4/integration_test.go @@ -9,6 +9,7 @@ import ( "testing" "time" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" @@ -16,7 +17,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/s4" "github.com/smartcontractkit/chainlink/v2/core/services/pg" s4_svc "github.com/smartcontractkit/chainlink/v2/core/services/s4" - "github.com/smartcontractkit/chainlink/v2/core/utils" commonlogger "github.com/smartcontractkit/chainlink-common/pkg/logger" @@ -357,14 +357,14 @@ func TestS4Integration_RandomState(t *testing.T) { type user struct { privateKey *ecdsa.PrivateKey - address *utils.Big + address *big.Big } nUsers := 100 users := make([]user, nUsers) for i := 0; i < nUsers; i++ { pk, addr := testutils.NewPrivateKeyAndAddress(t) - users[i] = user{pk, utils.NewBig(addr.Big())} + users[i] = user{pk, big.New(addr.Big())} } // generating test records diff --git a/core/services/ocr2/plugins/s4/messages.go b/core/services/ocr2/plugins/s4/messages.go index 8f3a64f4e23..c9695d2db76 100644 --- a/core/services/ocr2/plugins/s4/messages.go +++ b/core/services/ocr2/plugins/s4/messages.go @@ -4,8 +4,8 @@ import ( "bytes" "math/big" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/services/s4" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/ethereum/go-ethereum/common" "google.golang.org/protobuf/proto" @@ -58,8 +58,8 @@ func UnmarshalRows(data []byte) ([]*Row, error) { return rows.Rows, nil } -func UnmarshalAddress(address []byte) *utils.Big { - return utils.NewBig(new(big.Int).SetBytes(address)) +func UnmarshalAddress(address []byte) *ubig.Big { + return ubig.New(new(big.Int).SetBytes(address)) } func (row *Row) VerifySignature() error { diff --git a/core/services/ocr2/plugins/s4/plugin.go b/core/services/ocr2/plugins/s4/plugin.go index 68bd9fd2142..fcb025b21cd 100644 --- a/core/services/ocr2/plugins/s4/plugin.go +++ b/core/services/ocr2/plugins/s4/plugin.go @@ -4,9 +4,9 @@ import ( "context" "time" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/s4" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/pkg/errors" "github.com/smartcontractkit/libocr/commontypes" @@ -123,7 +123,7 @@ func (c *plugin) Observation(ctx context.Context, ts types.ReportTimestamp, quer c.logger.Error("ORM GetSnapshot error", commontypes.LogFields{"err": err}) } else { type rkey struct { - address *utils.Big + address *big.Big slotID uint } diff --git a/core/services/ocr2/plugins/s4/plugin_test.go b/core/services/ocr2/plugins/s4/plugin_test.go index e2b5d21b847..e0aa84183e1 100644 --- a/core/services/ocr2/plugins/s4/plugin_test.go +++ b/core/services/ocr2/plugins/s4/plugin_test.go @@ -5,13 +5,13 @@ import ( "testing" "time" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/s4" s4_svc "github.com/smartcontractkit/chainlink/v2/core/services/s4" s4_mocks "github.com/smartcontractkit/chainlink/v2/core/services/s4/mocks" - "github.com/smartcontractkit/chainlink/v2/core/utils" commonlogger "github.com/smartcontractkit/chainlink-common/pkg/logger" @@ -51,7 +51,7 @@ func generateTestRows(t *testing.T, n int, ttl time.Duration) []*s4.Row { func generateTestOrmRow(t *testing.T, ttl time.Duration, version uint64, confimed bool) *s4_svc.Row { priv, addr := testutils.NewPrivateKeyAndAddress(t) row := &s4_svc.Row{ - Address: utils.NewBig(addr.Big()), + Address: big.New(addr.Big()), SlotId: 0, Version: version, Confirmed: confimed, @@ -296,7 +296,7 @@ func TestPlugin_Query(t *testing.T) { for i := 0; i < 256; i++ { var thisAddress common.Address thisAddress[0] = byte(i) - ormRows[i].Address = utils.NewBig(thisAddress.Big()) + ormRows[i].Address = big.New(thisAddress.Big()) } versions := rowsToShapshotRows(ormRows) @@ -322,7 +322,7 @@ func TestPlugin_Query(t *testing.T) { assert.Len(t, qq.Rows, 16) for _, r := range qq.Rows { thisAddress := s4.UnmarshalAddress(r.Address) - assert.True(t, ar.Contains((*utils.Big)(thisAddress))) + assert.True(t, ar.Contains((*big.Big)(thisAddress))) } ar.Advance() diff --git a/core/services/ocrcommon/telemetry_test.go b/core/services/ocrcommon/telemetry_test.go index 9c90eea180a..7627a627dea 100644 --- a/core/services/ocrcommon/telemetry_test.go +++ b/core/services/ocrcommon/telemetry_test.go @@ -19,6 +19,7 @@ import ( mercuryv1 "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v1" mercuryv2 "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v2" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" @@ -147,7 +148,7 @@ func TestGetChainID(t *testing.T) { } j.Type = job.Type(pipeline.OffchainReportingJobType) - j.OCROracleSpec.EVMChainID = (*utils.Big)(big.NewInt(1234567890)) + j.OCROracleSpec.EVMChainID = (*ubig.Big)(big.NewInt(1234567890)) assert.Equal(t, "1234567890", e.getChainID()) j.Type = job.Type(pipeline.OffchainReporting2JobType) @@ -206,7 +207,7 @@ func TestSendEATelemetry(t *testing.T) { OCROracleSpec: &job.OCROracleSpec{ ContractAddress: ethkey.EIP55AddressFromAddress(feedAddress), CaptureEATelemetry: true, - EVMChainID: (*utils.Big)(big.NewInt(9)), + EVMChainID: (*ubig.Big)(big.NewInt(9)), }, } diff --git a/core/services/pipeline/orm_test.go b/core/services/pipeline/orm_test.go index dcbbfd9c97e..92a6c25da39 100644 --- a/core/services/pipeline/orm_test.go +++ b/core/services/pipeline/orm_test.go @@ -13,6 +13,7 @@ import ( "github.com/jmoiron/sqlx" "github.com/smartcontractkit/chainlink/v2/core/bridges" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -531,7 +532,7 @@ func Test_GetUnfinishedRuns_Keepers(t *testing.T) { FromAddress: cltest.NewEIP55Address(), CreatedAt: timestamp, UpdatedAt: timestamp, - EVMChainID: (*utils.Big)(&cltest.FixtureChainID), + EVMChainID: (*big.Big)(&cltest.FixtureChainID), }, ExternalJobID: uuid.MustParse("0EEC7E1D-D0D2-476C-A1A8-72DFB6633F46"), PipelineSpec: &pipeline.Spec{ @@ -630,7 +631,7 @@ func Test_GetUnfinishedRuns_DirectRequest(t *testing.T) { ContractAddress: cltest.NewEIP55Address(), CreatedAt: timestamp, UpdatedAt: timestamp, - EVMChainID: (*utils.Big)(&cltest.FixtureChainID), + EVMChainID: (*big.Big)(&cltest.FixtureChainID), }, ExternalJobID: uuid.MustParse("0EEC7E1D-D0D2-476C-A1A8-72DFB6633F46"), PipelineSpec: &pipeline.Spec{ diff --git a/core/services/promreporter/prom_reporter_test.go b/core/services/promreporter/prom_reporter_test.go index 1cebba2faf9..7b9930e4daa 100644 --- a/core/services/promreporter/prom_reporter_test.go +++ b/core/services/promreporter/prom_reporter_test.go @@ -16,6 +16,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/mocks" @@ -29,7 +30,7 @@ import ( ) func newHead() evmtypes.Head { - return evmtypes.Head{Number: 42, EVMChainID: utils.NewBigI(0)} + return evmtypes.Head{Number: 42, EVMChainID: ubig.NewI(0)} } func newLegacyChainContainer(t *testing.T, db *sqlx.DB) legacyevm.LegacyChainContainer { diff --git a/core/services/relay/evm/median_test.go b/core/services/relay/evm/median_test.go index 4286290d289..9c474006aa7 100644 --- a/core/services/relay/evm/median_test.go +++ b/core/services/relay/evm/median_test.go @@ -9,11 +9,11 @@ import ( commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" evmtypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func TestNewMedianProvider(t *testing.T) { @@ -37,7 +37,7 @@ func TestNewMedianProvider(t *testing.T) { }) t.Run("invalid contractID", func(t *testing.T) { - relayConfig := evmtypes.RelayConfig{ChainID: utils.NewBig(chainID)} + relayConfig := evmtypes.RelayConfig{ChainID: big.New(chainID)} rc, err2 := json.Marshal(&relayConfig) require.NoError(t, err2) rargsBadContractID := commontypes.RelayArgs{ContractID: "NotAContractID", RelayConfig: rc} diff --git a/core/services/relay/evm/relayer_extender_test.go b/core/services/relay/evm/relayer_extender_test.go index 3f4a3749ac8..af15461aee9 100644 --- a/core/services/relay/evm/relayer_extender_test.go +++ b/core/services/relay/evm/relayer_extender_test.go @@ -10,6 +10,7 @@ import ( evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" @@ -17,7 +18,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func TestChainRelayExtenders(t *testing.T) { @@ -28,7 +28,7 @@ func TestChainRelayExtenders(t *testing.T) { one := uint32(1) c.EVM[0].MinIncomingConfirmations = &one t := true - c.EVM = append(c.EVM, &toml.EVMConfig{ChainID: utils.NewBig(newId), Enabled: &t, Chain: toml.Defaults(nil)}) + c.EVM = append(c.EVM, &toml.EVMConfig{ChainID: ubig.New(newId), Enabled: &t, Chain: toml.Defaults(nil)}) }) db := pgtest.NewSqlxDB(t) kst := cltest.NewKeyStore(t, db, cfg.Database()) diff --git a/core/services/relay/evm/types/types.go b/core/services/relay/evm/types/types.go index 24afb65c55a..129ccb4a5e6 100644 --- a/core/services/relay/evm/types/types.go +++ b/core/services/relay/evm/types/types.go @@ -17,7 +17,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink/v2/core/utils" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" ) type ChainReaderConfig struct { @@ -47,7 +47,7 @@ const ( ) type RelayConfig struct { - ChainID *utils.Big `json:"chainID"` + ChainID *big.Big `json:"chainID"` FromBlock uint64 `json:"fromBlock"` EffectiveTransmitterID null.String `json:"effectiveTransmitterID"` ConfigContractAddress *common.Address `json:"configContractAddress"` diff --git a/core/services/relay/evm/types/types_test.go b/core/services/relay/evm/types/types_test.go index dec368614ec..6952c35a706 100644 --- a/core/services/relay/evm/types/types_test.go +++ b/core/services/relay/evm/types/types_test.go @@ -12,7 +12,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/utils" ) -// ChainID *utils.Big `json:"chainID"` +// ChainID *big.Big `json:"chainID"` // FromBlock uint64 `json:"fromBlock"` // // Contract-specific diff --git a/core/services/s4/address_range.go b/core/services/s4/address_range.go index 679bb3b846a..e7b60ecb479 100644 --- a/core/services/s4/address_range.go +++ b/core/services/s4/address_range.go @@ -5,23 +5,23 @@ import ( "errors" "math/big" - "github.com/smartcontractkit/chainlink/v2/core/utils" - "github.com/ethereum/go-ethereum/common" + + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" ) // AddressRange represents a range of Ethereum addresses. type AddressRange struct { // MinAddress (inclusive). - MinAddress *utils.Big + MinAddress *ubig.Big // MaxAddress (inclusive). - MaxAddress *utils.Big + MaxAddress *ubig.Big } var ( ErrInvalidIntervals = errors.New("invalid intervals value") - MinAddress = utils.NewBig(common.BytesToAddress(bytes.Repeat([]byte{0x00}, common.AddressLength)).Big()) - MaxAddress = utils.NewBig(common.BytesToAddress(bytes.Repeat([]byte{0xff}, common.AddressLength)).Big()) + MinAddress = ubig.New(common.BytesToAddress(bytes.Repeat([]byte{0x00}, common.AddressLength)).Big()) + MaxAddress = ubig.New(common.BytesToAddress(bytes.Repeat([]byte{0xff}, common.AddressLength)).Big()) ) // NewFullAddressRange creates AddressRange for all address space: 0x00..-0xFF.. @@ -33,7 +33,7 @@ func NewFullAddressRange() *AddressRange { } // NewSingleAddressRange creates AddressRange for a single address. -func NewSingleAddressRange(address *utils.Big) (*AddressRange, error) { +func NewSingleAddressRange(address *ubig.Big) (*AddressRange, error) { if address == nil || address.Cmp(MinAddress) < 0 || address.Cmp(MaxAddress) > 0 { return nil, errors.New("invalid address") } @@ -56,12 +56,12 @@ func NewInitialAddressRangeForIntervals(intervals uint) (*AddressRange, error) { } divisor := big.NewInt(int64(intervals)) - maxPlusOne := MaxAddress.Add(utils.NewBigI(1)) - interval := utils.NewBig(new(big.Int).Div(maxPlusOne.ToInt(), divisor)) + maxPlusOne := MaxAddress.Add(ubig.NewI(1)) + interval := ubig.New(new(big.Int).Div(maxPlusOne.ToInt(), divisor)) return &AddressRange{ MinAddress: MinAddress, - MaxAddress: MinAddress.Add(interval).Sub(utils.NewBigI(1)), + MaxAddress: MinAddress.Add(interval).Sub(ubig.NewI(1)), }, nil } @@ -80,7 +80,7 @@ func (r *AddressRange) Advance() { if r.MinAddress.Cmp(MaxAddress) >= 0 { r.MinAddress = MinAddress - r.MaxAddress = MinAddress.Add(interval).Sub(utils.NewBigI(1)) + r.MaxAddress = MinAddress.Add(interval).Sub(ubig.NewI(1)) } if r.MaxAddress.Cmp(MaxAddress) > 0 { @@ -89,7 +89,7 @@ func (r *AddressRange) Advance() { } // Contains returns true if the given address belongs to the range. -func (r *AddressRange) Contains(address *utils.Big) bool { +func (r *AddressRange) Contains(address *ubig.Big) bool { if r == nil { return false } @@ -97,9 +97,9 @@ func (r *AddressRange) Contains(address *utils.Big) bool { } // Interval returns the interval between max and min address plus one. -func (r *AddressRange) Interval() *utils.Big { +func (r *AddressRange) Interval() *ubig.Big { if r == nil { return nil } - return r.MaxAddress.Sub(r.MinAddress).Add(utils.NewBigI(1)) + return r.MaxAddress.Sub(r.MinAddress).Add(ubig.NewI(1)) } diff --git a/core/services/s4/address_range_test.go b/core/services/s4/address_range_test.go index bbd4d3baa54..2b12acd08eb 100644 --- a/core/services/s4/address_range_test.go +++ b/core/services/s4/address_range_test.go @@ -3,8 +3,8 @@ package s4_test import ( "testing" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/services/s4" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/stretchr/testify/assert" ) @@ -26,7 +26,7 @@ func TestAddressRange_NewFullAddressRange(t *testing.T) { func TestAddressRange_NewSingleAddressRange(t *testing.T) { t.Parallel() - addr := utils.NewBigI(0x123) + addr := big.NewI(0x123) sar, err := s4.NewSingleAddressRange(addr) assert.NoError(t, err) assert.Equal(t, addr, sar.MinAddress) @@ -94,10 +94,10 @@ func TestAddressRange_Contains(t *testing.T) { assert.NoError(t, err) assert.True(t, r.Contains(r.MinAddress)) assert.True(t, r.Contains(r.MaxAddress)) - assert.False(t, r.Contains(r.MaxAddress.Add(utils.NewBigI(1)))) + assert.False(t, r.Contains(r.MaxAddress.Add(big.NewI(1)))) r.Advance() assert.True(t, r.Contains(r.MinAddress)) assert.True(t, r.Contains(r.MaxAddress)) - assert.False(t, r.Contains(r.MinAddress.Sub(utils.NewBigI(1)))) + assert.False(t, r.Contains(r.MinAddress.Sub(big.NewI(1)))) } diff --git a/core/services/s4/in_memory_orm.go b/core/services/s4/in_memory_orm.go index bb67d2d63a4..28b50ce430c 100644 --- a/core/services/s4/in_memory_orm.go +++ b/core/services/s4/in_memory_orm.go @@ -5,8 +5,8 @@ import ( "sync" "time" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/services/pg" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) type key struct { @@ -32,7 +32,7 @@ func NewInMemoryORM() ORM { } } -func (o *inMemoryOrm) Get(address *utils.Big, slotId uint, qopts ...pg.QOpt) (*Row, error) { +func (o *inMemoryOrm) Get(address *big.Big, slotId uint, qopts ...pg.QOpt) (*Row, error) { o.mu.RLock() defer o.mu.RUnlock() @@ -103,7 +103,7 @@ func (o *inMemoryOrm) GetSnapshot(addressRange *AddressRange, qopts ...pg.QOpt) for _, mrow := range o.rows { if mrow.Row.Expiration > now { rows = append(rows, &SnapshotRow{ - Address: utils.NewBig(mrow.Row.Address.ToInt()), + Address: big.New(mrow.Row.Address.ToInt()), SlotId: mrow.Row.SlotId, Version: mrow.Row.Version, Expiration: mrow.Row.Expiration, diff --git a/core/services/s4/in_memory_orm_test.go b/core/services/s4/in_memory_orm_test.go index 68bff00634f..318db5f1a44 100644 --- a/core/services/s4/in_memory_orm_test.go +++ b/core/services/s4/in_memory_orm_test.go @@ -4,9 +4,9 @@ import ( "testing" "time" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/s4" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" @@ -21,7 +21,7 @@ func TestInMemoryORM(t *testing.T) { signature := testutils.Random32Byte() expiration := time.Now().Add(time.Minute).UnixMilli() row := &s4.Row{ - Address: utils.NewBig(address.Big()), + Address: big.New(address.Big()), SlotId: slotId, Payload: payload[:], Version: 3, @@ -33,7 +33,7 @@ func TestInMemoryORM(t *testing.T) { orm := s4.NewInMemoryORM() t.Run("row not found", func(t *testing.T) { - _, err := orm.Get(utils.NewBig(address.Big()), slotId) + _, err := orm.Get(big.New(address.Big()), slotId) assert.ErrorIs(t, err, s4.ErrNotFound) }) @@ -41,7 +41,7 @@ func TestInMemoryORM(t *testing.T) { err := orm.Update(row) assert.NoError(t, err) - e, err := orm.Get(utils.NewBig(address.Big()), slotId) + e, err := orm.Get(big.New(address.Big()), slotId) assert.NoError(t, err) assert.Equal(t, row, e) }) @@ -59,7 +59,7 @@ func TestInMemoryORM(t *testing.T) { err = orm.Update(row) assert.NoError(t, err) - e, err := orm.Get(utils.NewBig(address.Big()), slotId) + e, err := orm.Get(big.New(address.Big()), slotId) assert.NoError(t, err) assert.Equal(t, row, e) }) @@ -76,7 +76,7 @@ func TestInMemoryORM_DeleteExpired(t *testing.T) { thisAddress[0] = byte(i) row := &s4.Row{ - Address: utils.NewBig(thisAddress.Big()), + Address: big.New(thisAddress.Big()), SlotId: 1, Payload: []byte{}, Version: 1, @@ -109,7 +109,7 @@ func TestInMemoryORM_GetUnconfirmedRows(t *testing.T) { thisAddress[0] = byte(i) row := &s4.Row{ - Address: utils.NewBig(thisAddress.Big()), + Address: big.New(thisAddress.Big()), SlotId: 1, Payload: []byte{}, Version: 1, @@ -139,7 +139,7 @@ func TestInMemoryORM_GetSnapshot(t *testing.T) { thisAddress[0] = byte(i) row := &s4.Row{ - Address: utils.NewBig(thisAddress.Big()), + Address: big.New(thisAddress.Big()), SlotId: 1, Payload: []byte{}, Version: uint64(i), diff --git a/core/services/s4/mocks/orm.go b/core/services/s4/mocks/orm.go index 706c1194293..3b8cac8e76d 100644 --- a/core/services/s4/mocks/orm.go +++ b/core/services/s4/mocks/orm.go @@ -3,13 +3,14 @@ package mocks import ( + big "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" + mock "github.com/stretchr/testify/mock" + pg "github.com/smartcontractkit/chainlink/v2/core/services/pg" + s4 "github.com/smartcontractkit/chainlink/v2/core/services/s4" - mock "github.com/stretchr/testify/mock" time "time" - - utils "github.com/smartcontractkit/chainlink/v2/core/utils" ) // ORM is an autogenerated mock type for the ORM type @@ -53,7 +54,7 @@ func (_m *ORM) DeleteExpired(limit uint, utcNow time.Time, qopts ...pg.QOpt) (in } // Get provides a mock function with given fields: address, slotId, qopts -func (_m *ORM) Get(address *utils.Big, slotId uint, qopts ...pg.QOpt) (*s4.Row, error) { +func (_m *ORM) Get(address *big.Big, slotId uint, qopts ...pg.QOpt) (*s4.Row, error) { _va := make([]interface{}, len(qopts)) for _i := range qopts { _va[_i] = qopts[_i] @@ -69,10 +70,10 @@ func (_m *ORM) Get(address *utils.Big, slotId uint, qopts ...pg.QOpt) (*s4.Row, var r0 *s4.Row var r1 error - if rf, ok := ret.Get(0).(func(*utils.Big, uint, ...pg.QOpt) (*s4.Row, error)); ok { + if rf, ok := ret.Get(0).(func(*big.Big, uint, ...pg.QOpt) (*s4.Row, error)); ok { return rf(address, slotId, qopts...) } - if rf, ok := ret.Get(0).(func(*utils.Big, uint, ...pg.QOpt) *s4.Row); ok { + if rf, ok := ret.Get(0).(func(*big.Big, uint, ...pg.QOpt) *s4.Row); ok { r0 = rf(address, slotId, qopts...) } else { if ret.Get(0) != nil { @@ -80,7 +81,7 @@ func (_m *ORM) Get(address *utils.Big, slotId uint, qopts ...pg.QOpt) (*s4.Row, } } - if rf, ok := ret.Get(1).(func(*utils.Big, uint, ...pg.QOpt) error); ok { + if rf, ok := ret.Get(1).(func(*big.Big, uint, ...pg.QOpt) error); ok { r1 = rf(address, slotId, qopts...) } else { r1 = ret.Error(1) diff --git a/core/services/s4/orm.go b/core/services/s4/orm.go index 1e0227b1191..59f3410e143 100644 --- a/core/services/s4/orm.go +++ b/core/services/s4/orm.go @@ -3,13 +3,13 @@ package s4 import ( "time" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/services/pg" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) // Row represents a data row persisted by ORM. type Row struct { - Address *utils.Big + Address *big.Big SlotId uint Payload []byte Version uint64 @@ -20,7 +20,7 @@ type Row struct { // SnapshotRow(s) are returned by GetSnapshot function. type SnapshotRow struct { - Address *utils.Big + Address *big.Big SlotId uint Version uint64 Expiration int64 @@ -35,7 +35,7 @@ type ORM interface { // Get reads a row for the given address and slotId combination. // If such row does not exist, ErrNotFound is returned. // There is no filter on Expiration. - Get(address *utils.Big, slotId uint, qopts ...pg.QOpt) (*Row, error) + Get(address *big.Big, slotId uint, qopts ...pg.QOpt) (*Row, error) // Update inserts or updates the row identified by (Address, SlotId) pair. // When updating, the new row must have greater or equal version, @@ -59,7 +59,7 @@ type ORM interface { func (r Row) Clone() *Row { clone := Row{ - Address: utils.NewBig(r.Address.ToInt()), + Address: big.New(r.Address.ToInt()), SlotId: r.SlotId, Payload: make([]byte, len(r.Payload)), Version: r.Version, diff --git a/core/services/s4/postgres_orm.go b/core/services/s4/postgres_orm.go index 1f91270fd08..dba98b64aa6 100644 --- a/core/services/s4/postgres_orm.go +++ b/core/services/s4/postgres_orm.go @@ -5,9 +5,9 @@ import ( "fmt" "time" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/pg" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/jmoiron/sqlx" "github.com/pkg/errors" @@ -34,7 +34,7 @@ func NewPostgresORM(db *sqlx.DB, lggr logger.Logger, cfg pg.QConfig, tableName, } } -func (o orm) Get(address *utils.Big, slotId uint, qopts ...pg.QOpt) (*Row, error) { +func (o orm) Get(address *big.Big, slotId uint, qopts ...pg.QOpt) (*Row, error) { row := &Row{} q := o.q.WithOpts(qopts...) diff --git a/core/services/s4/postgres_orm_test.go b/core/services/s4/postgres_orm_test.go index c233fe2361a..4d07524b4ea 100644 --- a/core/services/s4/postgres_orm_test.go +++ b/core/services/s4/postgres_orm_test.go @@ -6,12 +6,12 @@ import ( "testing" "time" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/s4" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/stretchr/testify/assert" ) @@ -36,7 +36,7 @@ func generateTestRows(t *testing.T, n int) []*s4.Row { rows := make([]*s4.Row, n) for i := 0; i < n; i++ { row := &s4.Row{ - Address: utils.NewBig(testutils.NewAddress().Big()), + Address: big.New(testutils.NewAddress().Big()), SlotId: 1, Payload: cltest.MustRandomBytes(t, 32), Version: 1 + uint64(i), diff --git a/core/services/s4/storage.go b/core/services/s4/storage.go index 65aa2f4bab5..7c9a92d1f68 100644 --- a/core/services/s4/storage.go +++ b/core/services/s4/storage.go @@ -3,6 +3,7 @@ package s4 import ( "context" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/utils" @@ -92,7 +93,7 @@ func (s *storage) Get(ctx context.Context, key *Key) (*Record, *Metadata, error) return nil, nil, ErrSlotIdTooBig } - bigAddress := utils.NewBig(key.Address.Big()) + bigAddress := big.New(key.Address.Big()) row, err := s.orm.Get(bigAddress, key.SlotId, pg.WithParentCtx(ctx)) if err != nil { return nil, nil, err @@ -118,7 +119,7 @@ func (s *storage) Get(ctx context.Context, key *Key) (*Record, *Metadata, error) } func (s *storage) List(ctx context.Context, address common.Address) ([]*SnapshotRow, error) { - bigAddress := utils.NewBig(address.Big()) + bigAddress := big.New(address.Big()) sar, err := NewSingleAddressRange(bigAddress) if err != nil { return nil, err @@ -148,7 +149,7 @@ func (s *storage) Put(ctx context.Context, key *Key, record *Record, signature [ } row := &Row{ - Address: utils.NewBig(key.Address.Big()), + Address: big.New(key.Address.Big()), SlotId: key.SlotId, Payload: make([]byte, len(record.Payload)), Version: key.Version, diff --git a/core/services/s4/storage_test.go b/core/services/s4/storage_test.go index 11a8f6544ce..86161f298e4 100644 --- a/core/services/s4/storage_test.go +++ b/core/services/s4/storage_test.go @@ -4,6 +4,7 @@ import ( "testing" "time" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/s4" @@ -51,7 +52,7 @@ func TestStorage_Errors(t *testing.T) { SlotId: 1, Version: 0, } - ormMock.On("Get", utils.NewBig(key.Address.Big()), uint(key.SlotId), mock.Anything).Return(nil, s4.ErrNotFound) + ormMock.On("Get", big.New(key.Address.Big()), uint(key.SlotId), mock.Anything).Return(nil, s4.ErrNotFound) _, _, err := storage.Get(testutils.Context(t), key) assert.ErrorIs(t, err, s4.ErrNotFound) }) @@ -179,8 +180,8 @@ func TestStorage_PutAndGet(t *testing.T) { assert.NoError(t, err) ormMock.On("Update", mock.Anything, mock.Anything).Return(nil) - ormMock.On("Get", utils.NewBig(key.Address.Big()), uint(2), mock.Anything).Return(&s4.Row{ - Address: utils.NewBig(key.Address.Big()), + ormMock.On("Get", big.New(key.Address.Big()), uint(2), mock.Anything).Return(&s4.Row{ + Address: big.New(key.Address.Big()), SlotId: key.SlotId, Version: key.Version, Payload: record.Payload, @@ -217,7 +218,7 @@ func TestStorage_List(t *testing.T) { }, } - addressRange, err := s4.NewSingleAddressRange(utils.NewBig(address.Big())) + addressRange, err := s4.NewSingleAddressRange(big.New(address.Big())) assert.NoError(t, err) ormMock.On("GetSnapshot", addressRange, mock.Anything).Return(ormRows, nil) diff --git a/core/services/vrf/delegate_test.go b/core/services/vrf/delegate_test.go index 3b643d19b0b..663080c86a0 100644 --- a/core/services/vrf/delegate_test.go +++ b/core/services/vrf/delegate_test.go @@ -15,8 +15,8 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" - "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" diff --git a/core/services/vrf/v1/integration_test.go b/core/services/vrf/v1/integration_test.go index a7dca56776f..3e9cfbe0870 100644 --- a/core/services/vrf/v1/integration_test.go +++ b/core/services/vrf/v1/integration_test.go @@ -16,6 +16,7 @@ import ( "gopkg.in/guregu/null.v4" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/solidity_vrf_coordinator_interface" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" @@ -29,7 +30,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrftesthelpers" "github.com/smartcontractkit/chainlink/v2/core/store/models" "github.com/smartcontractkit/chainlink/v2/core/testdata/testspecs" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func TestIntegration_VRF_JPV2(t *testing.T) { @@ -47,7 +47,7 @@ func TestIntegration_VRF_JPV2(t *testing.T) { t.Run(test.name, func(t *testing.T) { config, _ := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].GasEstimator.EIP1559DynamicFees = &test.eip1559 - c.EVM[0].ChainID = (*utils.Big)(testutils.SimulatedChainID) + c.EVM[0].ChainID = (*ubig.Big)(testutils.SimulatedChainID) }) key1 := cltest.MustGenerateRandomKey(t) key2 := cltest.MustGenerateRandomKey(t) @@ -134,7 +134,7 @@ func TestIntegration_VRF_WithBHS(t *testing.T) { c.Feature.LogPoller = ptr(true) c.EVM[0].FinalityDepth = ptr[uint32](2) c.EVM[0].LogPollInterval = models.MustNewDuration(time.Second) - c.EVM[0].ChainID = (*utils.Big)(testutils.SimulatedChainID) + c.EVM[0].ChainID = (*ubig.Big)(testutils.SimulatedChainID) }) key := cltest.MustGenerateRandomKey(t) cu := vrftesthelpers.NewVRFCoordinatorUniverse(t, key) diff --git a/core/services/vrf/v2/integration_helpers_test.go b/core/services/vrf/v2/integration_helpers_test.go index 03d96cadf20..d8a7da70a86 100644 --- a/core/services/vrf/v2/integration_helpers_test.go +++ b/core/services/vrf/v2/integration_helpers_test.go @@ -21,6 +21,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" v2 "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_consumer_v2_upgradeable_example" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_external_sub_owner_example" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrfv2_transparent_upgradeable_proxy" @@ -540,7 +541,7 @@ func testSingleConsumerHappyPathBatchFulfillment( })(c, s) c.EVM[0].GasEstimator.LimitDefault = ptr[uint32](5_000_000) c.EVM[0].MinIncomingConfirmations = ptr[uint32](2) - c.EVM[0].ChainID = (*utils.Big)(testutils.SimulatedChainID) + c.EVM[0].ChainID = (*ubig.Big)(testutils.SimulatedChainID) c.Feature.LogPoller = ptr(true) c.EVM[0].LogPollInterval = models.MustNewDuration(1 * time.Second) }) @@ -1645,7 +1646,7 @@ func testMaliciousConsumer( c.EVM[0].GasEstimator.PriceMax = assets.GWei(1) c.EVM[0].GasEstimator.PriceDefault = assets.GWei(1) c.EVM[0].GasEstimator.FeeCapDefault = assets.GWei(1) - c.EVM[0].ChainID = (*utils.Big)(testutils.SimulatedChainID) + c.EVM[0].ChainID = (*ubig.Big)(testutils.SimulatedChainID) c.Feature.LogPoller = ptr(true) c.EVM[0].LogPollInterval = models.MustNewDuration(1 * time.Second) }) diff --git a/core/services/vrf/v2/integration_v2_test.go b/core/services/vrf/v2/integration_v2_test.go index fa95b694f98..8d6354c4fd8 100644 --- a/core/services/vrf/v2/integration_v2_test.go +++ b/core/services/vrf/v2/integration_v2_test.go @@ -40,6 +40,7 @@ import ( evmlogger "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_blockhash_store" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_vrf_coordinator_v2" @@ -2057,7 +2058,7 @@ func TestStartingCountsV1(t *testing.T) { md2, err := json.Marshal(&m2) md2SQL := sqlutil.JSON(md2) require.NoError(t, err) - chainID := utils.NewBig(testutils.SimulatedChainID) + chainID := ubig.New(testutils.SimulatedChainID) confirmedTxes := []txmgr.Tx{ { Sequence: &n1, diff --git a/core/services/vrf/v2/listener_v2_log_listener_test.go b/core/services/vrf/v2/listener_v2_log_listener_test.go index 11b299abc40..6f5177c230a 100644 --- a/core/services/vrf/v2/listener_v2_log_listener_test.go +++ b/core/services/vrf/v2/listener_v2_log_listener_test.go @@ -21,6 +21,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" evmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm/mocks" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2" @@ -761,8 +762,8 @@ func TestUpdateLastProcessedBlock_UnfulfilledNFulfilledVRFReqs(t *testing.T) { * TestGetUnfulfilled_UnfulfilledNFulfilledVRFReqs */ -func SetupGetUnfulfilledTH(t *testing.T) (*listenerV2, *utils.Big) { - chainID := utils.NewBig(big.NewInt(12345)) +func SetupGetUnfulfilledTH(t *testing.T) (*listenerV2, *ubig.Big) { + chainID := ubig.New(big.NewInt(12345)) lggr := logger.TestLogger(t) j, err := vrfcommon.ValidatedVRFSpec(testspecs.GenerateVRFSpec(testspecs.VRFSpecParams{ RequestedConfsDelay: 10, diff --git a/core/store/migrate/migrate_test.go b/core/store/migrate/migrate_test.go index 43ddd41d56f..10c698e96fd 100644 --- a/core/store/migrate/migrate_test.go +++ b/core/store/migrate/migrate_test.go @@ -16,6 +16,7 @@ import ( evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/config/env" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -29,7 +30,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/core/store/migrate" "github.com/smartcontractkit/chainlink/v2/core/store/models" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) var migrationDir = "migrations" @@ -417,7 +417,7 @@ func TestMigrate(t *testing.T) { func TestSetMigrationENVVars(t *testing.T) { t.Run("ValidEVMConfig", func(t *testing.T) { - chainID := utils.NewBig(big.NewInt(1337)) + chainID := ubig.New(big.NewInt(1337)) testConfig := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { evmEnabled := true c.EVM = evmcfg.EVMConfigs{&evmcfg.EVMConfig{ @@ -433,7 +433,7 @@ func TestSetMigrationENVVars(t *testing.T) { }) t.Run("EVMConfigMissing", func(t *testing.T) { - chainID := utils.NewBig(big.NewInt(1337)) + chainID := ubig.New(big.NewInt(1337)) testConfig := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM = nil }) require.NoError(t, migrate.SetMigrationENVVars(testConfig)) @@ -535,7 +535,7 @@ func BenchmarkBackfillingRecordsWithMigration202(b *testing.B) { var blocks []logpoller.LogPollerBlock for i := 0; i < maxLogsSize; i++ { blocks = append(blocks, logpoller.LogPollerBlock{ - EvmChainId: utils.NewBigI(int64(j + 1)), + EvmChainId: ubig.NewI(int64(j + 1)), BlockHash: testutils.Random32Byte(), BlockNumber: int64(i + 1000), FinalizedBlockNumber: 0, diff --git a/core/store/models/common.go b/core/store/models/common.go index 10f391861e1..93cc708fe0b 100644 --- a/core/store/models/common.go +++ b/core/store/models/common.go @@ -18,7 +18,7 @@ import ( "go.uber.org/multierr" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" - "github.com/smartcontractkit/chainlink/v2/core/utils" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" ) // CronParser is the global parser for crontabs. @@ -365,7 +365,7 @@ type SendEtherRequest struct { DestinationAddress common.Address `json:"address"` FromAddress common.Address `json:"from"` Amount assets.Eth `json:"amount"` - EVMChainID *utils.Big `json:"evmChainID"` + EVMChainID *big.Big `json:"evmChainID"` AllowHigherAmounts bool `json:"allowHigherAmounts"` SkipWaitTxAttempt bool `json:"skipWaitTxAttempt"` WaitAttemptTimeout *time.Duration `json:"waitAttemptTimeout"` diff --git a/core/web/eth_keys_controller.go b/core/web/eth_keys_controller.go index d99992c0f56..fe76e8863ef 100644 --- a/core/web/eth_keys_controller.go +++ b/core/web/eth_keys_controller.go @@ -11,6 +11,7 @@ import ( commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/config/toml" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -19,7 +20,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" "github.com/ethereum/go-ethereum/common" @@ -393,7 +393,7 @@ func (ekc *ETHKeysController) getLinkBalance(ctx context.Context, state ethkey.S // gets the key specific max gas price from the chain config and sets it on the // resource. func (ekc *ETHKeysController) setKeyMaxGasPriceWei(price *assets.Wei) presenters.NewETHKeyOption { - return presenters.SetETHKeyMaxGasPriceWei(utils.NewBig(price.ToInt())) + return presenters.SetETHKeyMaxGasPriceWei(ubig.New(price.ToInt())) } func (ekc *ETHKeysController) getKeyMaxGasPriceWei(state ethkey.State, keyAddress common.Address) *assets.Wei { diff --git a/core/web/evm_chains_controller_test.go b/core/web/evm_chains_controller_test.go index 3d5a4e3eedd..ea3d5476cec 100644 --- a/core/web/evm_chains_controller_test.go +++ b/core/web/evm_chains_controller_test.go @@ -12,12 +12,12 @@ import ( "github.com/stretchr/testify/require" evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) @@ -25,7 +25,7 @@ import ( func Test_EVMChainsController_Show(t *testing.T) { t.Parallel() - validId := utils.NewBig(testutils.NewRandomEVMChainID()) + validId := ubig.New(testutils.NewRandomEVMChainID()) testCases := []struct { name string @@ -111,9 +111,9 @@ func Test_EVMChainsController_Index(t *testing.T) { }) configuredChains := evmcfg.EVMConfigs{ - {ChainID: utils.NewBig(chainIDs[0]), Chain: evmcfg.Defaults(nil)}, + {ChainID: ubig.New(chainIDs[0]), Chain: evmcfg.Defaults(nil)}, { - ChainID: utils.NewBig(chainIDs[1]), + ChainID: ubig.New(chainIDs[1]), Chain: evmcfg.Defaults(nil, &evmcfg.Chain{ RPCBlockQueryDelay: ptr[uint16](13), GasEstimator: evmcfg.GasEstimator{ @@ -126,7 +126,7 @@ func Test_EVMChainsController_Index(t *testing.T) { }), }, { - ChainID: utils.NewBig(chainIDs[2]), + ChainID: ubig.New(chainIDs[2]), Chain: evmcfg.Defaults(nil, &evmcfg.Chain{ RPCBlockQueryDelay: ptr[uint16](5), GasEstimator: evmcfg.GasEstimator{ diff --git a/core/web/evm_forwarders_controller.go b/core/web/evm_forwarders_controller.go index 6228723506d..56d1285c88e 100644 --- a/core/web/evm_forwarders_controller.go +++ b/core/web/evm_forwarders_controller.go @@ -8,10 +8,10 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/logger/audit" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/pg" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/utils/stringutils" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" @@ -43,7 +43,7 @@ func (cc *EVMForwardersController) Index(c *gin.Context, size, page, offset int) // TrackEVMForwarderRequest is a JSONAPI request for creating an EVM forwarder. type TrackEVMForwarderRequest struct { - EVMChainID *utils.Big `json:"evmChainId"` + EVMChainID *ubig.Big `json:"evmChainId"` Address common.Address `json:"address"` } diff --git a/core/web/evm_forwarders_controller_test.go b/core/web/evm_forwarders_controller_test.go index 31e49f20ecc..49671157cbd 100644 --- a/core/web/evm_forwarders_controller_test.go +++ b/core/web/evm_forwarders_controller_test.go @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/require" evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" @@ -42,7 +43,7 @@ func setupEVMForwardersControllerTest(t *testing.T, overrideFn func(c *chainlink func Test_EVMForwardersController_Track(t *testing.T) { t.Parallel() - chainId := utils.NewBig(testutils.NewRandomEVMChainID()) + chainId := big.New(testutils.NewRandomEVMChainID()) controller := setupEVMForwardersControllerTest(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM = evmcfg.EVMConfigs{ {ChainID: chainId, Enabled: ptr(true), Chain: evmcfg.Defaults(chainId)}, @@ -79,7 +80,7 @@ func Test_EVMForwardersController_Track(t *testing.T) { func Test_EVMForwardersController_Index(t *testing.T) { t.Parallel() - chainId := utils.NewBig(testutils.NewRandomEVMChainID()) + chainId := big.New(testutils.NewRandomEVMChainID()) controller := setupEVMForwardersControllerTest(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM = evmcfg.EVMConfigs{ {ChainID: chainId, Enabled: ptr(true), Chain: evmcfg.Defaults(chainId)}, diff --git a/core/web/evm_transfer_controller_test.go b/core/web/evm_transfer_controller_test.go index c41219e1894..dd083a8cd63 100644 --- a/core/web/evm_transfer_controller_test.go +++ b/core/web/evm_transfer_controller_test.go @@ -13,13 +13,13 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/store/models" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" @@ -55,7 +55,7 @@ func TestTransfersController_CreateSuccess_From(t *testing.T) { FromAddress: key.Address, Amount: amount, SkipWaitTxAttempt: true, - EVMChainID: utils.NewBig(evmtest.MustGetDefaultChainID(t, app.Config.EVMConfigs())), + EVMChainID: ubig.New(evmtest.MustGetDefaultChainID(t, app.Config.EVMConfigs())), } body, err := json.Marshal(&request) @@ -96,7 +96,7 @@ func TestTransfersController_CreateSuccess_From_WEI(t *testing.T) { FromAddress: key.Address, Amount: amount, SkipWaitTxAttempt: true, - EVMChainID: utils.NewBig(evmtest.MustGetDefaultChainID(t, app.Config.EVMConfigs())), + EVMChainID: ubig.New(evmtest.MustGetDefaultChainID(t, app.Config.EVMConfigs())), } body, err := json.Marshal(&request) @@ -142,7 +142,7 @@ func TestTransfersController_CreateSuccess_From_BalanceMonitorDisabled(t *testin FromAddress: key.Address, Amount: amount, SkipWaitTxAttempt: true, - EVMChainID: utils.NewBig(evmtest.MustGetDefaultChainID(t, app.Config.EVMConfigs())), + EVMChainID: ubig.New(evmtest.MustGetDefaultChainID(t, app.Config.EVMConfigs())), } body, err := json.Marshal(&request) @@ -172,7 +172,7 @@ func TestTransfersController_TransferZeroAddressError(t *testing.T) { DestinationAddress: common.HexToAddress("0xFA01FA015C8A5332987319823728982379128371"), FromAddress: common.HexToAddress("0x0000000000000000000000000000000000000000"), Amount: amount, - EVMChainID: utils.NewBig(evmtest.MustGetDefaultChainID(t, app.Config.EVMConfigs())), + EVMChainID: ubig.New(evmtest.MustGetDefaultChainID(t, app.Config.EVMConfigs())), } body, err := json.Marshal(&request) @@ -207,7 +207,7 @@ func TestTransfersController_TransferBalanceToLowError(t *testing.T) { DestinationAddress: common.HexToAddress("0xFA01FA015C8A5332987319823728982379128371"), Amount: amount, AllowHigherAmounts: false, - EVMChainID: utils.NewBig(evmtest.MustGetDefaultChainID(t, app.Config.EVMConfigs())), + EVMChainID: ubig.New(evmtest.MustGetDefaultChainID(t, app.Config.EVMConfigs())), } body, err := json.Marshal(&request) @@ -245,7 +245,7 @@ func TestTransfersController_TransferBalanceToLowError_ZeroBalance(t *testing.T) DestinationAddress: common.HexToAddress("0xFA01FA015C8A5332987319823728982379128371"), Amount: amount, AllowHigherAmounts: false, - EVMChainID: utils.NewBig(evmtest.MustGetDefaultChainID(t, app.Config.EVMConfigs())), + EVMChainID: ubig.New(evmtest.MustGetDefaultChainID(t, app.Config.EVMConfigs())), } body, err := json.Marshal(&request) @@ -288,7 +288,7 @@ func TestTransfersController_CreateSuccess_eip1559(t *testing.T) { config := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].GasEstimator.EIP1559DynamicFees = ptr(true) c.EVM[0].GasEstimator.Mode = ptr("FixedPrice") - c.EVM[0].ChainID = (*utils.Big)(testutils.FixtureChainID) + c.EVM[0].ChainID = (*ubig.Big)(testutils.FixtureChainID) // NOTE: FallbackPollInterval is used in this test to quickly create TxAttempts // Testing triggers requires committing transactions and does not work with transactional tests c.Database.Listener.FallbackPollInterval = models.MustNewDuration(time.Second) @@ -308,7 +308,7 @@ func TestTransfersController_CreateSuccess_eip1559(t *testing.T) { FromAddress: key.Address, Amount: amount, WaitAttemptTimeout: &timeout, - EVMChainID: utils.NewBig(evmtest.MustGetDefaultChainID(t, config.EVMConfigs())), + EVMChainID: ubig.New(evmtest.MustGetDefaultChainID(t, config.EVMConfigs())), } body, err := json.Marshal(&request) diff --git a/core/web/loader/loader_test.go b/core/web/loader/loader_test.go index 9bd1feb05bf..cbd73a575a9 100644 --- a/core/web/loader/loader_test.go +++ b/core/web/loader/loader_test.go @@ -17,6 +17,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtxmgrmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" coremocks "github.com/smartcontractkit/chainlink/v2/core/internal/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" @@ -35,9 +36,9 @@ func TestLoader_Chains(t *testing.T) { app := coremocks.NewApplication(t) ctx := InjectDataloader(testutils.Context(t), app) - one := utils.NewBigI(1) + one := ubig.NewI(1) chain := toml.EVMConfig{ChainID: one, Chain: toml.Defaults(one)} - two := utils.NewBigI(2) + two := ubig.NewI(2) chain2 := toml.EVMConfig{ChainID: two, Chain: toml.Defaults(two)} evmORM := evmtest.NewTestConfigs(&chain, &chain2) app.On("EVMORM").Return(evmORM) diff --git a/core/web/presenters/eth_key.go b/core/web/presenters/eth_key.go index 3d952dabeda..d661d4334cd 100644 --- a/core/web/presenters/eth_key.go +++ b/core/web/presenters/eth_key.go @@ -5,22 +5,22 @@ import ( commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) // ETHKeyResource represents a ETH key JSONAPI resource. It holds the hex // representation of the address plus its ETH & LINK balances type ETHKeyResource struct { JAID - EVMChainID utils.Big `json:"evmChainID"` + EVMChainID big.Big `json:"evmChainID"` Address string `json:"address"` EthBalance *assets.Eth `json:"ethBalance"` LinkBalance *commonassets.Link `json:"linkBalance"` Disabled bool `json:"disabled"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` - MaxGasPriceWei *utils.Big `json:"maxGasPriceWei"` + MaxGasPriceWei *big.Big `json:"maxGasPriceWei"` } // GetName implements the api2go EntityNamer interface @@ -69,7 +69,7 @@ func SetETHKeyLinkBalance(linkBalance *commonassets.Link) NewETHKeyOption { } } -func SetETHKeyMaxGasPriceWei(maxGasPriceWei *utils.Big) NewETHKeyOption { +func SetETHKeyMaxGasPriceWei(maxGasPriceWei *big.Big) NewETHKeyOption { return func(r *ETHKeyResource) { r.MaxGasPriceWei = maxGasPriceWei } diff --git a/core/web/presenters/eth_key_test.go b/core/web/presenters/eth_key_test.go index 85d005cf610..8be13de74a1 100644 --- a/core/web/presenters/eth_key_test.go +++ b/core/web/presenters/eth_key_test.go @@ -7,8 +7,8 @@ import ( commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/ethereum/go-ethereum/common" "github.com/manyminds/api2go/jsonapi" @@ -31,7 +31,7 @@ func TestETHKeyResource(t *testing.T) { state := ethkey.State{ ID: 1, - EVMChainID: *utils.NewBigI(42), + EVMChainID: *big.NewI(42), Address: eip55address, CreatedAt: now, UpdatedAt: now, @@ -41,12 +41,12 @@ func TestETHKeyResource(t *testing.T) { r := NewETHKeyResource(key, state, SetETHKeyEthBalance(assets.NewEth(1)), SetETHKeyLinkBalance(commonassets.NewLinkFromJuels(1)), - SetETHKeyMaxGasPriceWei(utils.NewBigI(12345)), + SetETHKeyMaxGasPriceWei(big.NewI(12345)), ) assert.Equal(t, assets.NewEth(1), r.EthBalance) assert.Equal(t, commonassets.NewLinkFromJuels(1), r.LinkBalance) - assert.Equal(t, utils.NewBigI(12345), r.MaxGasPriceWei) + assert.Equal(t, big.NewI(12345), r.MaxGasPriceWei) b, err := jsonapi.Marshal(r) require.NoError(t, err) diff --git a/core/web/presenters/eth_tx.go b/core/web/presenters/eth_tx.go index 2c2b5b90ff2..f944a99213f 100644 --- a/core/web/presenters/eth_tx.go +++ b/core/web/presenters/eth_tx.go @@ -8,7 +8,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" - "github.com/smartcontractkit/chainlink/v2/core/utils" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" ) // EthTxResource represents a Ethereum Transaction JSONAPI resource. @@ -25,7 +25,7 @@ type EthTxResource struct { SentAt string `json:"sentAt"` To *common.Address `json:"to"` Value string `json:"value"` - EVMChainID utils.Big `json:"evmChainID"` + EVMChainID big.Big `json:"evmChainID"` } // GetName implements the api2go EntityNamer interface @@ -50,7 +50,7 @@ func NewEthTxResource(tx txmgr.Tx) EthTxResource { } if tx.ChainID != nil { - r.EVMChainID = *utils.NewBig(tx.ChainID) + r.EVMChainID = *big.New(tx.ChainID) } return r } @@ -65,7 +65,7 @@ func NewEthTxResourceFromAttempt(txa txmgr.TxAttempt) EthTxResource { r.Hex = hexutil.Encode(txa.SignedRawTx) if txa.Tx.ChainID != nil { - r.EVMChainID = *utils.NewBig(txa.Tx.ChainID) + r.EVMChainID = *big.New(txa.Tx.ChainID) } if tx.Sequence != nil { diff --git a/core/web/presenters/evm_forwarder.go b/core/web/presenters/evm_forwarder.go index c91bfc088f1..43c27644850 100644 --- a/core/web/presenters/evm_forwarder.go +++ b/core/web/presenters/evm_forwarder.go @@ -6,14 +6,14 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders" - "github.com/smartcontractkit/chainlink/v2/core/utils" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" ) // EVMForwarderResource is an EVM forwarder JSONAPI resource. type EVMForwarderResource struct { JAID Address common.Address `json:"address"` - EVMChainID utils.Big `json:"evmChainId"` + EVMChainID big.Big `json:"evmChainId"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` } diff --git a/core/web/presenters/job.go b/core/web/presenters/job.go index 9b0a3cb3425..a2a9e70c793 100644 --- a/core/web/presenters/job.go +++ b/core/web/presenters/job.go @@ -9,6 +9,7 @@ import ( commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" clnull "github.com/smartcontractkit/chainlink/v2/core/null" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" @@ -16,7 +17,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/core/services/signatures/secp256k1" "github.com/smartcontractkit/chainlink/v2/core/store/models" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) // JobSpecType defines the the the spec type of the job @@ -49,7 +49,7 @@ type DirectRequestSpec struct { Initiator string `json:"initiator"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` - EVMChainID *utils.Big `json:"evmChainID"` + EVMChainID *big.Big `json:"evmChainID"` } // NewDirectRequestSpec initializes a new DirectRequestSpec from a @@ -84,7 +84,7 @@ type FluxMonitorSpec struct { MinPayment *commonassets.Link `json:"minPayment"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` - EVMChainID *utils.Big `json:"evmChainID"` + EVMChainID *big.Big `json:"evmChainID"` } // NewFluxMonitorSpec initializes a new DirectFluxMonitorSpec from a @@ -131,7 +131,7 @@ type OffChainReportingSpec struct { ContractConfigConfirmations uint16 `json:"contractConfigConfirmations"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` - EVMChainID *utils.Big `json:"evmChainID"` + EVMChainID *big.Big `json:"evmChainID"` DatabaseTimeout *models.Interval `json:"databaseTimeout"` ObservationGracePeriod *models.Interval `json:"observationGracePeriod"` ContractTransmitterTransmitTimeout *models.Interval `json:"contractTransmitterTransmitTimeout"` @@ -220,7 +220,7 @@ type KeeperSpec struct { FromAddress ethkey.EIP55Address `json:"fromAddress"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` - EVMChainID *utils.Big `json:"evmChainID"` + EVMChainID *big.Big `json:"evmChainID"` } // NewKeeperSpec generates a new KeeperSpec from a job.KeeperSpec @@ -275,7 +275,7 @@ type VRFSpec struct { MinIncomingConfirmations uint32 `json:"confirmations"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` - EVMChainID *utils.Big `json:"evmChainID"` + EVMChainID *big.Big `json:"evmChainID"` ChunkSize uint32 `json:"chunkSize"` RequestTimeout models.Duration `json:"requestTimeout"` BackoffInitialDelay models.Duration `json:"backoffInitialDelay"` @@ -317,7 +317,7 @@ type BlockhashStoreSpec struct { TrustedBlockhashStoreBatchSize int32 `json:"trustedBlockhashStoreBatchSize"` PollPeriod time.Duration `json:"pollPeriod"` RunTimeout time.Duration `json:"runTimeout"` - EVMChainID *utils.Big `json:"evmChainID"` + EVMChainID *big.Big `json:"evmChainID"` FromAddresses []ethkey.EIP55Address `json:"fromAddresses"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` @@ -353,7 +353,7 @@ type BlockHeaderFeederSpec struct { BatchBlockhashStoreAddress ethkey.EIP55Address `json:"batchBlockhashStoreAddress"` PollPeriod time.Duration `json:"pollPeriod"` RunTimeout time.Duration `json:"runTimeout"` - EVMChainID *utils.Big `json:"evmChainID"` + EVMChainID *big.Big `json:"evmChainID"` FromAddresses []ethkey.EIP55Address `json:"fromAddresses"` GetBlockhashesBatchSize uint16 `json:"getBlockhashesBatchSize"` StoreBlockhashesBatchSize uint16 `json:"storeBlockhashesBatchSize"` diff --git a/core/web/presenters/job_test.go b/core/web/presenters/job_test.go index 260cce0caf6..a5d6db0df18 100644 --- a/core/web/presenters/job_test.go +++ b/core/web/presenters/job_test.go @@ -14,12 +14,12 @@ import ( "gopkg.in/guregu/null.v4" "github.com/smartcontractkit/chainlink-common/pkg/assets" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" clnull "github.com/smartcontractkit/chainlink/v2/core/null" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/store/models" - "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) @@ -29,7 +29,7 @@ func TestJob(t *testing.T) { contractAddress, err := ethkey.NewEIP55Address("0x9E40733cC9df84636505f4e6Db28DCa0dC5D1bba") require.NoError(t, err) cronSchedule := "0 0 0 1 1 *" - evmChainID := utils.NewBigI(42) + evmChainID := big.NewI(42) fromAddress, err := ethkey.NewEIP55Address("0xa8037A20989AFcBC51798de9762b351D63ff462e") require.NoError(t, err) @@ -484,7 +484,7 @@ func TestJob(t *testing.T) { BlockhashStoreAddress: contractAddress, PollPeriod: 25 * time.Second, RunTimeout: 10 * time.Second, - EVMChainID: utils.NewBigI(4), + EVMChainID: big.NewI(4), FromAddresses: []ethkey.EIP55Address{fromAddress}, TrustedBlockhashStoreAddress: &trustedBlockhashStoreAddress, TrustedBlockhashStoreBatchSize: trustedBlockhashStoreBatchSize, @@ -564,7 +564,7 @@ func TestJob(t *testing.T) { BatchBlockhashStoreAddress: batchBHSAddress, PollPeriod: 25 * time.Second, RunTimeout: 10 * time.Second, - EVMChainID: utils.NewBigI(4), + EVMChainID: big.NewI(4), FromAddresses: []ethkey.EIP55Address{fromAddress}, GetBlockhashesBatchSize: 5, StoreBlockhashesBatchSize: 10, diff --git a/core/web/replay_controller.go b/core/web/replay_controller.go index 5006b68c845..84c54e3836e 100644 --- a/core/web/replay_controller.go +++ b/core/web/replay_controller.go @@ -7,8 +7,8 @@ import ( "github.com/gin-gonic/gin" "github.com/pkg/errors" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) type ReplayController struct { @@ -64,14 +64,14 @@ func (bdc *ReplayController) ReplayFromBlock(c *gin.Context) { response := ReplayResponse{ Message: "Replay started", - EVMChainID: utils.NewBig(chainID), + EVMChainID: big.New(chainID), } jsonAPIResponse(c, &response, "response") } type ReplayResponse struct { - Message string `json:"message"` - EVMChainID *utils.Big `json:"evmChainID"` + Message string `json:"message"` + EVMChainID *big.Big `json:"evmChainID"` } // GetID returns the jsonapi ID. diff --git a/core/web/resolver/chain_test.go b/core/web/resolver/chain_test.go index c3cafd329b4..700963cd4da 100644 --- a/core/web/resolver/chain_test.go +++ b/core/web/resolver/chain_test.go @@ -9,12 +9,12 @@ import ( "github.com/stretchr/testify/require" evmtoml "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" - "github.com/smartcontractkit/chainlink/v2/core/utils" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" ) func TestResolver_Chains(t *testing.T) { var ( - chainID = *utils.NewBigI(1) + chainID = *big.NewI(1) query = ` query GetChains { chains { @@ -100,7 +100,7 @@ ResendAfterThreshold = '1h0m0s' func TestResolver_Chain(t *testing.T) { var ( - chainID = *utils.NewBigI(1) + chainID = *big.NewI(1) query = ` query GetChain { chain(id: "1") { diff --git a/core/web/resolver/eth_key_test.go b/core/web/resolver/eth_key_test.go index ea106a4b30c..1874e4c68e0 100644 --- a/core/web/resolver/eth_key_test.go +++ b/core/web/resolver/eth_key_test.go @@ -14,12 +14,12 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" mocks2 "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) type mockEvmConfig struct { @@ -80,13 +80,13 @@ func TestResolver_ETHKeys(t *testing.T) { states := []ethkey.State{ { Address: ethkey.MustEIP55Address(address.Hex()), - EVMChainID: *utils.NewBigI(12), + EVMChainID: *big.NewI(12), Disabled: false, CreatedAt: f.Timestamp(), UpdatedAt: f.Timestamp(), }, } - chainID := *utils.NewBigI(12) + chainID := *big.NewI(12) linkAddr := common.HexToAddress("0x5431F5F973781809D18643b87B44921b11355d81") cfg := configtest.NewGeneralConfig(t, nil) @@ -139,13 +139,13 @@ func TestResolver_ETHKeys(t *testing.T) { states := []ethkey.State{ { Address: ethkey.MustEIP55Address(address.Hex()), - EVMChainID: *utils.NewBigI(12), + EVMChainID: *big.NewI(12), Disabled: false, CreatedAt: f.Timestamp(), UpdatedAt: f.Timestamp(), }, } - chainID := *utils.NewBigI(12) + chainID := *big.NewI(12) f.Mocks.legacyEVMChains.On("Get", states[0].EVMChainID.String()).Return(nil, evmrelay.ErrNoChains) f.Mocks.ethKs.On("GetStatesForKeys", keys).Return(states, nil) f.Mocks.ethKs.On("Get", keys[0].Address.Hex()).Return(keys[0], nil) @@ -225,7 +225,7 @@ func TestResolver_ETHKeys(t *testing.T) { states := []ethkey.State{ { Address: ethkey.MustEIP55Address(address.Hex()), - EVMChainID: *utils.NewBigI(12), + EVMChainID: *big.NewI(12), Disabled: false, CreatedAt: f.Timestamp(), UpdatedAt: f.Timestamp(), @@ -257,7 +257,7 @@ func TestResolver_ETHKeys(t *testing.T) { states := []ethkey.State{ { Address: ethkey.MustEIP55Address(address.Hex()), - EVMChainID: *utils.NewBigI(12), + EVMChainID: *big.NewI(12), Disabled: false, CreatedAt: f.Timestamp(), UpdatedAt: f.Timestamp(), @@ -288,13 +288,13 @@ func TestResolver_ETHKeys(t *testing.T) { states := []ethkey.State{ { Address: ethkey.MustEIP55Address(address.Hex()), - EVMChainID: *utils.NewBigI(12), + EVMChainID: *big.NewI(12), Disabled: false, CreatedAt: f.Timestamp(), UpdatedAt: f.Timestamp(), }, } - chainID := *utils.NewBigI(12) + chainID := *big.NewI(12) linkAddr := common.HexToAddress("0x5431F5F973781809D18643b87B44921b11355d81") f.Mocks.ethKs.On("GetStatesForKeys", keys).Return(states, nil) @@ -342,13 +342,13 @@ func TestResolver_ETHKeys(t *testing.T) { states := []ethkey.State{ { Address: ethkey.EIP55AddressFromAddress(address), - EVMChainID: *utils.NewBigI(12), + EVMChainID: *big.NewI(12), Disabled: false, CreatedAt: f.Timestamp(), UpdatedAt: f.Timestamp(), }, } - chainID := *utils.NewBigI(12) + chainID := *big.NewI(12) linkAddr := common.HexToAddress("0x5431F5F973781809D18643b87B44921b11355d81") f.Mocks.ethKs.On("GetStatesForKeys", keys).Return(states, nil) diff --git a/core/web/resolver/eth_transaction_test.go b/core/web/resolver/eth_transaction_test.go index a719c838e81..238aa9d1679 100644 --- a/core/web/resolver/eth_transaction_test.go +++ b/core/web/resolver/eth_transaction_test.go @@ -15,7 +15,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/utils" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" ) func TestResolver_EthTransaction(t *testing.T) { @@ -54,7 +54,7 @@ func TestResolver_EthTransaction(t *testing.T) { "hash": "0x5431F5F973781809D18643b87B44921b11355d81", } hash := common.HexToHash("0x5431F5F973781809D18643b87B44921b11355d81") - chainID := *utils.NewBigI(22) + chainID := *ubig.NewI(22) gError := errors.New("error") testCases := []GQLTestCase{ diff --git a/core/web/resolver/node_test.go b/core/web/resolver/node_test.go index 24a31b986f1..a209a60fc3c 100644 --- a/core/web/resolver/node_test.go +++ b/core/web/resolver/node_test.go @@ -8,16 +8,16 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/store/models" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) func TestResolver_Nodes(t *testing.T) { t.Parallel() var ( - chainID = *utils.NewBigI(1) + chainID = *big.NewI(1) query = ` query GetNodes { diff --git a/core/web/resolver/spec_test.go b/core/web/resolver/spec_test.go index ef89dafa048..277aac851a6 100644 --- a/core/web/resolver/spec_test.go +++ b/core/web/resolver/spec_test.go @@ -13,13 +13,13 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" clnull "github.com/smartcontractkit/chainlink/v2/core/null" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/core/services/signatures/secp256k1" "github.com/smartcontractkit/chainlink/v2/core/store/models" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) // Specs are only embedded on the job and are not fetchable by it's own id, so @@ -95,7 +95,7 @@ func TestResolver_DirectRequestSpec(t *testing.T) { DirectRequestSpec: &job.DirectRequestSpec{ ContractAddress: contractAddress, CreatedAt: f.Timestamp(), - EVMChainID: utils.NewBigI(42), + EVMChainID: ubig.NewI(42), MinIncomingConfirmations: clnull.NewUint32(1, true), MinContractPayment: commonassets.NewLinkFromJuels(1000), Requesters: models.AddressCollection{requesterAddress}, @@ -160,7 +160,7 @@ func TestResolver_FluxMonitorSpec(t *testing.T) { FluxMonitorSpec: &job.FluxMonitorSpec{ ContractAddress: contractAddress, CreatedAt: f.Timestamp(), - EVMChainID: utils.NewBigI(42), + EVMChainID: ubig.NewI(42), DrumbeatEnabled: false, IdleTimerDisabled: false, IdleTimerPeriod: time.Duration(1 * time.Hour), @@ -227,7 +227,7 @@ func TestResolver_FluxMonitorSpec(t *testing.T) { FluxMonitorSpec: &job.FluxMonitorSpec{ ContractAddress: contractAddress, CreatedAt: f.Timestamp(), - EVMChainID: utils.NewBigI(42), + EVMChainID: ubig.NewI(42), DrumbeatEnabled: true, DrumbeatRandomDelay: time.Duration(1 * time.Second), DrumbeatSchedule: "CRON_TZ=UTC 0 0 1 1 *", @@ -310,7 +310,7 @@ func TestResolver_KeeperSpec(t *testing.T) { KeeperSpec: &job.KeeperSpec{ ContractAddress: contractAddress, CreatedAt: f.Timestamp(), - EVMChainID: utils.NewBigI(42), + EVMChainID: ubig.NewI(42), FromAddress: ethkey.EIP55AddressFromAddress(fromAddress), }, }, nil) @@ -381,7 +381,7 @@ func TestResolver_OCRSpec(t *testing.T) { ObservationGracePeriod: models.NewInterval(4 * time.Second), ContractTransmitterTransmitTimeout: models.NewInterval(555 * time.Millisecond), CreatedAt: f.Timestamp(), - EVMChainID: utils.NewBigI(42), + EVMChainID: ubig.NewI(42), IsBootstrapPeer: false, EncryptedOCRKeyBundleID: &keyBundleID, ObservationTimeout: models.Interval(2 * time.Minute), @@ -584,7 +584,7 @@ func TestResolver_VRFSpec(t *testing.T) { MinIncomingConfirmations: 1, CoordinatorAddress: coordinatorAddress, CreatedAt: f.Timestamp(), - EVMChainID: utils.NewBigI(42), + EVMChainID: ubig.NewI(42), FromAddresses: []ethkey.EIP55Address{fromAddress1, fromAddress2}, PollPeriod: 1 * time.Minute, PublicKey: pubKey, @@ -745,7 +745,7 @@ func TestResolver_BlockhashStoreSpec(t *testing.T) { CoordinatorV2Address: &coordinatorV2Address, CoordinatorV2PlusAddress: &coordinatorV2PlusAddress, CreatedAt: f.Timestamp(), - EVMChainID: utils.NewBigI(42), + EVMChainID: ubig.NewI(42), FromAddresses: []ethkey.EIP55Address{fromAddress1, fromAddress2}, PollPeriod: 1 * time.Minute, RunTimeout: 37 * time.Second, @@ -849,7 +849,7 @@ func TestResolver_BlockHeaderFeederSpec(t *testing.T) { CoordinatorV2Address: &coordinatorV2Address, CoordinatorV2PlusAddress: &coordinatorV2PlusAddress, CreatedAt: f.Timestamp(), - EVMChainID: utils.NewBigI(42), + EVMChainID: ubig.NewI(42), FromAddresses: []ethkey.EIP55Address{fromAddress}, PollPeriod: 1 * time.Minute, RunTimeout: 37 * time.Second, diff --git a/integration-tests/client/chainlink_models.go b/integration-tests/client/chainlink_models.go index abc6ef30e41..e6e1de25e41 100644 --- a/integration-tests/client/chainlink_models.go +++ b/integration-tests/client/chainlink_models.go @@ -8,8 +8,8 @@ import ( "gopkg.in/guregu/null.v4" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) // EIServiceConfig represents External Initiator service config @@ -1420,6 +1420,6 @@ type ReplayResponseData struct { } type ReplayResponseAttributes struct { - Message string `json:"message"` - EVMChainID *utils.Big `json:"evmChainID"` + Message string `json:"message"` + EVMChainID *big.Big `json:"evmChainID"` } diff --git a/integration-tests/types/config/node/core.go b/integration-tests/types/config/node/core.go index 0337274bb1c..7436c05a107 100644 --- a/integration-tests/types/config/node/core.go +++ b/integration-tests/types/config/node/core.go @@ -16,6 +16,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/config/toml" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" @@ -162,7 +163,7 @@ func SetChainConfig( } cfg.EVM = evmcfg.EVMConfigs{ { - ChainID: utils.NewBig(big.NewInt(chain.ChainID)), + ChainID: ubig.New(big.NewInt(chain.ChainID)), Chain: chainConfig, Nodes: nodes, }, @@ -179,7 +180,7 @@ func WithPrivateEVMs(networks []blockchain.EVMNetwork) NodeConfigOpt { var evmConfigs []*evmcfg.EVMConfig for _, network := range networks { evmConfigs = append(evmConfigs, &evmcfg.EVMConfig{ - ChainID: utils.NewBig(big.NewInt(network.ChainID)), + ChainID: ubig.New(big.NewInt(network.ChainID)), Chain: evmcfg.Chain{ AutoCreateKey: ptr.Ptr(true), FinalityDepth: ptr.Ptr[uint32](50), From 96b7ab6ee1daa751a58fe34d1f67b90066f26afd Mon Sep 17 00:00:00 2001 From: Jordan Krage Date: Tue, 12 Dec 2023 15:24:26 -0600 Subject: [PATCH 08/29] bump toml/v2 and prometheus to latest patch (#11541) Co-authored-by: Vyzaldy Sanchez --- core/scripts/go.mod | 4 ++-- core/scripts/go.sum | 8 ++++---- go.mod | 4 ++-- go.sum | 8 ++++---- integration-tests/go.mod | 4 ++-- integration-tests/go.sum | 8 ++++---- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 2f4d45e746f..c5327596272 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -17,7 +17,7 @@ require ( github.com/manyminds/api2go v0.0.0-20171030193247-e7b693844a6f github.com/montanaflynn/stats v0.7.1 github.com/olekukonko/tablewriter v0.0.5 - github.com/pelletier/go-toml/v2 v2.1.0 + github.com/pelletier/go-toml/v2 v2.1.1 github.com/pkg/errors v0.9.1 github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/chainlink-automation v1.0.1 @@ -224,7 +224,7 @@ require ( github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.45.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect - github.com/prometheus/prometheus v0.48.0 // indirect + github.com/prometheus/prometheus v0.48.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index a59590fa124..28750a076d5 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1029,8 +1029,8 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9 github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= -github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= -github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI= +github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 h1:hDSdbBuw3Lefr6R18ax0tZ2BJeNB3NehB3trOwYBsdU= github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= @@ -1076,8 +1076,8 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/prometheus/prometheus v0.48.0 h1:yrBloImGQ7je4h8M10ujGh4R6oxYQJQKlMuETwNskGk= -github.com/prometheus/prometheus v0.48.0/go.mod h1:SRw624aMAxTfryAcP8rOjg4S/sHHaetx2lyJJ2nM83g= +github.com/prometheus/prometheus v0.48.1 h1:CTszphSNTXkuCG6O0IfpKdHcJkvvnAAE1GbELKS+NFk= +github.com/prometheus/prometheus v0.48.1/go.mod h1:SRw624aMAxTfryAcP8rOjg4S/sHHaetx2lyJJ2nM83g= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= diff --git a/go.mod b/go.mod index d8394633c3f..e7b93c40bdb 100644 --- a/go.mod +++ b/go.mod @@ -51,13 +51,13 @@ require ( github.com/onsi/gomega v1.30.0 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pelletier/go-toml v1.9.5 - github.com/pelletier/go-toml/v2 v2.1.0 + github.com/pelletier/go-toml/v2 v2.1.1 github.com/pkg/errors v0.9.1 github.com/pressly/goose/v3 v3.16.0 github.com/prometheus/client_golang v1.17.0 github.com/prometheus/client_model v0.5.0 github.com/prometheus/common v0.45.0 - github.com/prometheus/prometheus v0.48.0 + github.com/prometheus/prometheus v0.48.1 github.com/robfig/cron/v3 v3.0.1 github.com/rogpeppe/go-internal v1.11.0 github.com/scylladb/go-reflectx v1.0.1 diff --git a/go.sum b/go.sum index d702fd37e90..e9a7f0267ad 100644 --- a/go.sum +++ b/go.sum @@ -1015,8 +1015,8 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9 github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= -github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= -github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI= +github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 h1:hDSdbBuw3Lefr6R18ax0tZ2BJeNB3NehB3trOwYBsdU= github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= @@ -1062,8 +1062,8 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/prometheus/prometheus v0.48.0 h1:yrBloImGQ7je4h8M10ujGh4R6oxYQJQKlMuETwNskGk= -github.com/prometheus/prometheus v0.48.0/go.mod h1:SRw624aMAxTfryAcP8rOjg4S/sHHaetx2lyJJ2nM83g= +github.com/prometheus/prometheus v0.48.1 h1:CTszphSNTXkuCG6O0IfpKdHcJkvvnAAE1GbELKS+NFk= +github.com/prometheus/prometheus v0.48.1/go.mod h1:SRw624aMAxTfryAcP8rOjg4S/sHHaetx2lyJJ2nM83g= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index c080f617552..84da65e9a5d 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -18,7 +18,7 @@ require ( github.com/lib/pq v1.10.9 github.com/manifoldco/promptui v0.9.0 github.com/onsi/gomega v1.30.0 - github.com/pelletier/go-toml/v2 v2.1.0 + github.com/pelletier/go-toml/v2 v2.1.1 github.com/rs/zerolog v1.30.0 github.com/scylladb/go-reflectx v1.0.1 github.com/segmentio/ksuid v1.0.4 @@ -330,7 +330,7 @@ require ( github.com/prometheus/common/sigv4 v0.1.0 // indirect github.com/prometheus/exporter-toolkit v0.10.1-0.20230714054209-2f4150c63f97 // indirect github.com/prometheus/procfs v0.12.0 // indirect - github.com/prometheus/prometheus v0.48.0 // indirect + github.com/prometheus/prometheus v0.48.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index e8cefd67d6d..854978e3353 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1278,8 +1278,8 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9 github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= -github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI= +github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= @@ -1341,8 +1341,8 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/prometheus/prometheus v0.48.0 h1:yrBloImGQ7je4h8M10ujGh4R6oxYQJQKlMuETwNskGk= -github.com/prometheus/prometheus v0.48.0/go.mod h1:SRw624aMAxTfryAcP8rOjg4S/sHHaetx2lyJJ2nM83g= +github.com/prometheus/prometheus v0.48.1 h1:CTszphSNTXkuCG6O0IfpKdHcJkvvnAAE1GbELKS+NFk= +github.com/prometheus/prometheus v0.48.1/go.mod h1:SRw624aMAxTfryAcP8rOjg4S/sHHaetx2lyJJ2nM83g= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/pyroscope-io/client v0.7.1 h1:yFRhj3vbgjBxehvxQmedmUWJQ4CAfCHhn+itPsuWsHw= github.com/pyroscope-io/client v0.7.1/go.mod h1:4h21iOU4pUOq0prKyDlvYRL+SCKsBc5wKiEtV+rJGqU= From 00e1c55ddb5fa3736fccaa545c12cff91b702b68 Mon Sep 17 00:00:00 2001 From: ferglor <19188060+ferglor@users.noreply.github.com> Date: Tue, 12 Dec 2023 21:34:28 +0000 Subject: [PATCH 09/29] Change keepers to use the default contract transmitter (#11308) * Switch keepers to use the default contract transmitter Pass the gas limit into the transmitter constructor so we can specify the automation gas limit Update tests * Fix streams import * Clean up function calls * Remove pipeline runner dependency for automation * Use contractTransmitterOpts to specify a pluginGasLimit * Make the pluginGasLimit a pointer * Clean up the pipeline transmitter * Attempt to listen for transmits Clean up linter Extract function Intentionally fail test Rework transmit listen Try filtering for transmits Update test * Revert "Attempt to listen for transmits" This reverts commit 198e6669a6f64768c84acb82e01b2773c89426ce. * Listen for performed events * Goimports * Add wrapper function that lets us specify a count of performed * Update integration test * Pass the configWatcher as a parameter to indicate that its required --- core/services/ocr2/delegate.go | 4 +- .../plugins/ocr2keeper/integration_21_test.go | 93 +++++++----------- .../plugins/ocr2keeper/integration_test.go | 19 ---- core/services/ocr2/plugins/ocr2keeper/util.go | 14 +-- .../ocrcommon/transmitter_pipeline.go | 97 ------------------- .../ocrcommon/transmitter_pipeline_test.go | 77 --------------- core/services/relay/evm/evm.go | 63 ++---------- core/services/relay/evm/ocr2keeper.go | 25 +++-- core/services/relay/evm/ocr2vrf.go | 4 +- 9 files changed, 67 insertions(+), 329 deletions(-) delete mode 100644 core/services/ocrcommon/transmitter_pipeline.go delete mode 100644 core/services/ocrcommon/transmitter_pipeline_test.go diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go index 5200866e3af..1b7be2b7f0e 100644 --- a/core/services/ocr2/delegate.go +++ b/core/services/ocr2/delegate.go @@ -1084,7 +1084,7 @@ func (d *Delegate) newServicesOCR2Keepers21( return nil, fmt.Errorf("keeper2 services: failed to get chain %s: %w", rid.ChainID, err2) } - keeperProvider, services, err2 := ocr2keeper.EVMDependencies21(jb, d.db, lggr, chain, d.pipelineRunner, mc, kb, d.cfg.Database()) + keeperProvider, services, err2 := ocr2keeper.EVMDependencies21(jb, d.db, lggr, chain, mc, kb, d.cfg.Database(), d.ethKs) if err2 != nil { return nil, errors.Wrap(err2, "could not build dependencies for ocr2 keepers") } @@ -1201,7 +1201,7 @@ func (d *Delegate) newServicesOCR2Keepers20( return nil, fmt.Errorf("keepers2.0 services: failed to get chain (%s): %w", rid.ChainID, err2) } - keeperProvider, rgstry, encoder, logProvider, err2 := ocr2keeper.EVMDependencies20(jb, d.db, lggr, chain, d.pipelineRunner) + keeperProvider, rgstry, encoder, logProvider, err2 := ocr2keeper.EVMDependencies20(jb, d.db, lggr, chain, d.ethKs) if err2 != nil { return nil, errors.Wrap(err2, "could not build dependencies for ocr2 keepers") } diff --git a/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go b/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go index c2b6612f664..81a35a5ced2 100644 --- a/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go @@ -54,7 +54,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams" - "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" ) @@ -117,7 +116,7 @@ func TestIntegration_KeeperPluginConditionalUpkeep(t *testing.T) { require.NoError(t, err) registry := deployKeeper21Registry(t, steve, backend, linkAddr, linkFeedAddr, gasFeedAddr) - nodes, _ := setupNodes(t, nodeKeys, registry, backend, steve) + setupNodes(t, nodeKeys, registry, backend, steve) <-time.After(time.Second * 5) @@ -160,8 +159,6 @@ func TestIntegration_KeeperPluginConditionalUpkeep(t *testing.T) { } g.Eventually(receivedBytes, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.Equal(payload1)) - checkPipelineRuns(t, nodes, 1) - // change payload _, err = upkeepContract.SetBytesToSend(carrol, payload2) require.NoError(t, err) @@ -204,7 +201,7 @@ func TestIntegration_KeeperPluginLogUpkeep(t *testing.T) { require.NoError(t, err) registry := deployKeeper21Registry(t, steve, backend, linkAddr, linkFeedAddr, gasFeedAddr) - nodes, _ := setupNodes(t, nodeKeys, registry, backend, steve) + setupNodes(t, nodeKeys, registry, backend, steve) upkeeps := 1 _, err = linkToken.Transfer(sergey, carrol.From, big.NewInt(0).Mul(oneHunEth, big.NewInt(int64(upkeeps+1)))) @@ -228,35 +225,36 @@ func TestIntegration_KeeperPluginLogUpkeep(t *testing.T) { g.Eventually(listener, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.BeTrue()) done() - runs := checkPipelineRuns(t, nodes, 1) - t.Run("recover logs", func(t *testing.T) { - addr, contract := addrs[0], contracts[0] upkeepID := registerUpkeep(t, registry, addr, carrol, steve, backend) backend.Commit() t.Logf("Registered new upkeep %s for address %s", upkeepID.String(), addr.String()) // Emit 100 logs in a burst - emits := 100 + recoverEmits := 100 i := 0 emitEvents(testutils.Context(t), t, 100, []*log_upkeep_counter_wrapper.LogUpkeepCounter{contract}, carrol, func() { i++ - if i%(emits/4) == 0 { + if i%(recoverEmits/4) == 0 { backend.Commit() time.Sleep(time.Millisecond * 250) // otherwise we get "invalid transaction nonce" errors } }) - // Mine enough blocks to ensre these logs don't fall into log provider range + + beforeDummyBlocks := backend.Blockchain().CurrentBlock().Number.Uint64() + + // Mine enough blocks to ensure these logs don't fall into log provider range dummyBlocks := 500 for i := 0; i < dummyBlocks; i++ { backend.Commit() time.Sleep(time.Millisecond * 10) } - t.Logf("Mined %d blocks, waiting for logs to be recovered", dummyBlocks) - expectedPostRecover := runs + emits - waitPipelineRuns(t, nodes, expectedPostRecover, testutils.WaitTimeout(t), cltest.DBPollingInterval) + t.Logf("Mined %d blocks, waiting for logs to be recovered", dummyBlocks) + listener, done := listenPerformedN(t, backend, registry, ids, int64(beforeDummyBlocks), recoverEmits) + g.Eventually(listener, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.BeTrue()) + done() }) } @@ -296,7 +294,7 @@ func TestIntegration_KeeperPluginLogUpkeep_Retry(t *testing.T) { registry := deployKeeper21Registry(t, registryOwner, backend, linkAddr, linkFeedAddr, gasFeedAddr) - nodes, mercuryServer := setupNodes(t, nodeKeys, registry, backend, registryOwner) + _, mercuryServer := setupNodes(t, nodeKeys, registry, backend, registryOwner) const upkeepCount = 10 const mercuryFailCount = upkeepCount * 3 * 2 @@ -374,39 +372,6 @@ func TestIntegration_KeeperPluginLogUpkeep_Retry(t *testing.T) { g.Eventually(listener, testutils.WaitTimeout(t)-(5*time.Second), cltest.DBPollingInterval).Should(gomega.BeTrue()) done() - - _ = checkPipelineRuns(t, nodes, 1*len(nodes)) // TODO: TBD -} - -func waitPipelineRuns(t *testing.T, nodes []Node, n int, timeout, interval time.Duration) { - ctx, cancel := context.WithTimeout(testutils.Context(t), timeout) - defer cancel() - var allRuns []pipeline.Run - for len(allRuns) < n && ctx.Err() == nil { - allRuns = []pipeline.Run{} - for _, node := range nodes { - runs, err := node.App.PipelineORM().GetAllRuns() - require.NoError(t, err) - allRuns = append(allRuns, runs...) - } - time.Sleep(interval) - } - runs := len(allRuns) - t.Logf("found %d pipeline runs", runs) - require.GreaterOrEqual(t, runs, n) -} - -func checkPipelineRuns(t *testing.T, nodes []Node, n int) int { - var allRuns []pipeline.Run - for _, node := range nodes { - runs, err2 := node.App.PipelineORM().GetAllRuns() - require.NoError(t, err2) - allRuns = append(allRuns, runs...) - } - runs := len(allRuns) - t.Logf("found %d pipeline runs", runs) - require.GreaterOrEqual(t, runs, n) - return runs } func emitEvents(ctx context.Context, t *testing.T, n int, contracts []*log_upkeep_counter_wrapper.LogUpkeepCounter, carrol *bind.TransactOpts, afterEmit func()) { @@ -424,32 +389,32 @@ func mapListener(m *sync.Map, n int) func() bool { return func() bool { count := 0 m.Range(func(key, value interface{}) bool { - count++ + count += value.(int) return true }) return count > n } } -func listenPerformed(t *testing.T, backend *backends.SimulatedBackend, registry *iregistry21.IKeeperRegistryMaster, ids []*big.Int, startBlock int64) (func() bool, func()) { +func listenPerformedN(t *testing.T, backend *backends.SimulatedBackend, registry *iregistry21.IKeeperRegistryMaster, ids []*big.Int, startBlock int64, count int) (func() bool, func()) { cache := &sync.Map{} ctx, cancel := context.WithCancel(testutils.Context(t)) start := startBlock go func() { for ctx.Err() == nil { - bl := backend.Blockchain().CurrentBlock().Number.Uint64() + currentBlock := backend.Blockchain().CurrentBlock().Number.Uint64() - sc := make([]bool, len(ids)) - for i := range sc { - sc[i] = true + success := make([]bool, len(ids)) + for i := range success { + success[i] = true } iter, err := registry.FilterUpkeepPerformed(&bind.FilterOpts{ Start: uint64(start), - End: &bl, + End: ¤tBlock, Context: ctx, - }, ids, sc) + }, ids, success) if ctx.Err() != nil { return @@ -460,7 +425,15 @@ func listenPerformed(t *testing.T, backend *backends.SimulatedBackend, registry for iter.Next() { if iter.Event != nil { t.Logf("[automation-ocr3 | EvmRegistry] upkeep performed event emitted for id %s", iter.Event.Id.String()) - cache.Store(iter.Event.Id.String(), true) + + //cache.Store(iter.Event.Id.String(), true) + count, ok := cache.Load(iter.Event.Id.String()) + if !ok { + cache.Store(iter.Event.Id.String(), 1) + continue + } + countI := count.(int) + cache.Store(iter.Event.Id.String(), countI+1) } } @@ -470,7 +443,11 @@ func listenPerformed(t *testing.T, backend *backends.SimulatedBackend, registry } }() - return mapListener(cache, 0), cancel + return mapListener(cache, count), cancel +} + +func listenPerformed(t *testing.T, backend *backends.SimulatedBackend, registry *iregistry21.IKeeperRegistryMaster, ids []*big.Int, startBlock int64) (func() bool, func()) { + return listenPerformedN(t, backend, registry, ids, startBlock, 0) } func setupNodes(t *testing.T, nodeKeys [5]ethkey.KeyV2, registry *iregistry21.IKeeperRegistryMaster, backend *backends.SimulatedBackend, usr *bind.TransactOpts) ([]Node, *SimulatedMercuryServer) { diff --git a/core/services/ocr2/plugins/ocr2keeper/integration_test.go b/core/services/ocr2/plugins/ocr2keeper/integration_test.go index 6674b0828b1..d0a93f77631 100644 --- a/core/services/ocr2/plugins/ocr2keeper/integration_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/integration_test.go @@ -58,7 +58,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" "github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap" - "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/store/models" ) @@ -411,15 +410,6 @@ func TestIntegration_KeeperPluginBasic(t *testing.T) { } g.Eventually(receivedBytes, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.Equal(payload1)) - // check pipeline runs - var allRuns []pipeline.Run - for _, node := range nodes { - runs, err2 := node.App.PipelineORM().GetAllRuns() - require.NoError(t, err2) - allRuns = append(allRuns, runs...) - } - require.GreaterOrEqual(t, len(allRuns), 1) - // change payload _, err = upkeepContract.SetBytesToSend(carrol, payload2) require.NoError(t, err) @@ -683,15 +673,6 @@ func TestIntegration_KeeperPluginForwarderEnabled(t *testing.T) { } g.Eventually(receivedBytes, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.Equal(payload1)) - // check pipeline runs - var allRuns []pipeline.Run - for _, node := range nodes { - runs, err2 := node.App.PipelineORM().GetAllRuns() - require.NoError(t, err2) - allRuns = append(allRuns, runs...) - } - require.GreaterOrEqual(t, len(allRuns), 1) - // change payload _, err = upkeepContract.SetBytesToSend(carrol, payload2) require.NoError(t, err) diff --git a/core/services/ocr2/plugins/ocr2keeper/util.go b/core/services/ocr2/plugins/ocr2keeper/util.go index 76e5bb6e00e..c3c60ad58b1 100644 --- a/core/services/ocr2/plugins/ocr2keeper/util.go +++ b/core/services/ocr2/plugins/ocr2keeper/util.go @@ -17,13 +17,13 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/models" evmregistry20 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20" evmregistry21 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21" evmregistry21transmit "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/transmit" "github.com/smartcontractkit/chainlink/v2/core/services/pg" - "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" ) @@ -43,9 +43,9 @@ var ( ErrNoChainFromSpec = fmt.Errorf("could not create chain from spec") ) -func EVMProvider(db *sqlx.DB, chain legacyevm.Chain, lggr logger.Logger, spec job.Job, pr pipeline.Runner) (evmrelay.OCR2KeeperProvider, error) { +func EVMProvider(db *sqlx.DB, chain legacyevm.Chain, lggr logger.Logger, spec job.Job, ethKeystore keystore.Eth) (evmrelay.OCR2KeeperProvider, error) { oSpec := spec.OCR2OracleSpec - ocr2keeperRelayer := evmrelay.NewOCR2KeeperRelayer(db, chain, pr, spec, lggr.Named("OCR2KeeperRelayer")) + ocr2keeperRelayer := evmrelay.NewOCR2KeeperRelayer(db, chain, lggr.Named("OCR2KeeperRelayer"), ethKeystore) keeperProvider, err := ocr2keeperRelayer.NewOCR2KeeperProvider( types.RelayArgs{ @@ -71,7 +71,7 @@ func EVMDependencies20( db *sqlx.DB, lggr logger.Logger, chain legacyevm.Chain, - pr pipeline.Runner, + ethKeystore keystore.Eth, ) (evmrelay.OCR2KeeperProvider, *evmregistry20.EvmRegistry, Encoder20, *evmregistry20.LogProvider, error) { var err error @@ -79,7 +79,7 @@ func EVMDependencies20( var registry *evmregistry20.EvmRegistry // the provider will be returned as a dependency - if keeperProvider, err = EVMProvider(db, chain, lggr, spec, pr); err != nil { + if keeperProvider, err = EVMProvider(db, chain, lggr, spec, ethKeystore); err != nil { return nil, nil, nil, nil, err } @@ -112,17 +112,17 @@ func EVMDependencies21( db *sqlx.DB, lggr logger.Logger, chain legacyevm.Chain, - pr pipeline.Runner, mc *models.MercuryCredentials, keyring ocrtypes.OnchainKeyring, dbCfg pg.QConfig, + ethKeystore keystore.Eth, ) (evmrelay.OCR2KeeperProvider, evmregistry21.AutomationServices, error) { var err error var keeperProvider evmrelay.OCR2KeeperProvider oSpec := spec.OCR2OracleSpec // the provider will be returned as a dependency - if keeperProvider, err = EVMProvider(db, chain, lggr, spec, pr); err != nil { + if keeperProvider, err = EVMProvider(db, chain, lggr, spec, ethKeystore); err != nil { return nil, nil, err } diff --git a/core/services/ocrcommon/transmitter_pipeline.go b/core/services/ocrcommon/transmitter_pipeline.go deleted file mode 100644 index e62f745a941..00000000000 --- a/core/services/ocrcommon/transmitter_pipeline.go +++ /dev/null @@ -1,97 +0,0 @@ -package ocrcommon - -import ( - "context" - "fmt" - - "github.com/ethereum/go-ethereum/common" - "github.com/pkg/errors" - - "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" -) - -const txObservationSource = ` - transmit_tx [type=ethtx - minConfirmations=0 - to="$(jobSpec.contractAddress)" - from="[$(jobSpec.fromAddress)]" - evmChainID="$(jobSpec.evmChainID)" - data="$(jobSpec.data)" - gasLimit="$(jobSpec.gasLimit)" - forwardingAllowed="$(jobSpec.forwardingAllowed)" - transmitChecker="$(jobSpec.transmitChecker)"] - transmit_tx -` - -type pipelineTransmitter struct { - lgr logger.Logger - fromAddress common.Address - gasLimit uint32 - effectiveTransmitterAddress common.Address - strategy types.TxStrategy - checker txmgr.TransmitCheckerSpec - pr pipeline.Runner - spec job.Job - chainID string -} - -// NewPipelineTransmitter creates a new eth transmitter using the job pipeline mechanism -func NewPipelineTransmitter( - lgr logger.Logger, - fromAddress common.Address, - gasLimit uint32, - effectiveTransmitterAddress common.Address, - strategy types.TxStrategy, - checker txmgr.TransmitCheckerSpec, - pr pipeline.Runner, - spec job.Job, - chainID string, -) Transmitter { - return &pipelineTransmitter{ - lgr: lgr, - fromAddress: fromAddress, - gasLimit: gasLimit, - effectiveTransmitterAddress: effectiveTransmitterAddress, - strategy: strategy, - checker: checker, - pr: pr, - spec: spec, - chainID: chainID, - } -} - -func (t *pipelineTransmitter) CreateEthTransaction(ctx context.Context, toAddress common.Address, payload []byte, _ *txmgr.TxMeta) error { - // t.strategy is ignored currently as pipeline does not support passing this (sc-55115) - vars := pipeline.NewVarsFrom(map[string]interface{}{ - "jobSpec": map[string]interface{}{ - "contractAddress": toAddress.String(), - "fromAddress": t.fromAddress.String(), - "gasLimit": t.gasLimit, - "evmChainID": t.chainID, - "forwardingAllowed": t.spec.ForwardingAllowed, - "data": payload, - "transmitChecker": t.checker, - }, - }) - - t.spec.PipelineSpec.DotDagSource = txObservationSource - run := pipeline.NewRun(*t.spec.PipelineSpec, vars) - - if _, err := t.pr.Run(ctx, run, t.lgr, true, nil); err != nil { - return errors.Wrap(err, "Skipped OCR transmission") - } - - if run.State != pipeline.RunStatusCompleted { - return fmt.Errorf("unexpected pipeline run state: %s with fatal errors %w", run.State, run.FatalErrors.ToError()) - } - - return nil -} - -func (t *pipelineTransmitter) FromAddress() common.Address { - return t.effectiveTransmitterAddress -} diff --git a/core/services/ocrcommon/transmitter_pipeline_test.go b/core/services/ocrcommon/transmitter_pipeline_test.go deleted file mode 100644 index e0114d0aa0d..00000000000 --- a/core/services/ocrcommon/transmitter_pipeline_test.go +++ /dev/null @@ -1,77 +0,0 @@ -package ocrcommon_test - -import ( - "testing" - - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" - "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" - pipelinemocks "github.com/smartcontractkit/chainlink/v2/core/services/pipeline/mocks" -) - -func Test_PipelineTransmitter_CreateEthTransaction(t *testing.T) { - t.Parallel() - - lggr := logger.TestLogger(t) - db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() - - _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) - - chainID := "12345" - gasLimit := uint32(1000) - effectiveTransmitterAddress := fromAddress - toAddress := testutils.NewAddress() - payload := []byte{1, 2, 3} - strategy := newMockTxStrategy(t) - checker := txmgr.TransmitCheckerSpec{CheckerType: txmgr.TransmitCheckerTypeSimulate} - runner := pipelinemocks.NewRunner(t) - - transmitter := ocrcommon.NewPipelineTransmitter( - lggr, - fromAddress, - gasLimit, - effectiveTransmitterAddress, - strategy, - checker, - runner, - job.Job{ - PipelineSpec: &pipeline.Spec{}, - }, - chainID, - ) - - runner.On("Run", mock.Anything, mock.AnythingOfType("*pipeline.Run"), mock.Anything, mock.Anything, mock.Anything). - Return(false, nil). - Run(func(args mock.Arguments) { - run := args.Get(1).(*pipeline.Run) - require.Equal(t, map[string]interface{}{ - "jobSpec": map[string]interface{}{ - "contractAddress": toAddress.String(), - "fromAddress": fromAddress.String(), - "gasLimit": gasLimit, - "evmChainID": chainID, - "forwardingAllowed": false, - "data": payload, - "transmitChecker": checker, - }, - }, run.Inputs.Val) - - save := args.Get(3).(bool) - require.True(t, save) - - run.State = pipeline.RunStatusCompleted - }).Once() - - require.NoError(t, transmitter.CreateEthTransaction(testutils.Context(t), toAddress, payload, nil)) -} diff --git a/core/services/relay/evm/evm.go b/core/services/relay/evm/evm.go index aea704adacf..83540e22bb7 100644 --- a/core/services/relay/evm/evm.go +++ b/core/services/relay/evm/evm.go @@ -27,13 +27,11 @@ import ( txm "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" mercuryconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/mercury/config" "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" "github.com/smartcontractkit/chainlink/v2/core/services/pg" - "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/functions" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury" mercuryutils "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/utils" @@ -373,7 +371,12 @@ func newConfigProvider(lggr logger.Logger, chain legacyevm.Chain, opts *types.Re return newConfigWatcher(lggr, aggregatorAddress, contractABI, offchainConfigDigester, cp, chain, relayConfig.FromBlock, opts.New), nil } -func newContractTransmitter(lggr logger.Logger, rargs commontypes.RelayArgs, transmitterID string, configWatcher *configWatcher, ethKeystore keystore.Eth) (*contractTransmitter, error) { +type configTransmitterOpts struct { + // override the gas limit default provided in the config watcher + pluginGasLimit *uint32 +} + +func newContractTransmitter(lggr logger.Logger, rargs commontypes.RelayArgs, transmitterID string, ethKeystore keystore.Eth, configWatcher *configWatcher, opts configTransmitterOpts) (*contractTransmitter, error) { var relayConfig types.RelayConfig if err := json.Unmarshal(rargs.RelayConfig, &relayConfig); err != nil { return nil, err @@ -415,6 +418,9 @@ func newContractTransmitter(lggr logger.Logger, rargs commontypes.RelayArgs, tra if ocr2Limit != nil { gasLimit = *ocr2Limit } + if opts.pluginGasLimit != nil { + gasLimit = *opts.pluginGasLimit + } transmitter, err := ocrcommon.NewTransmitter( configWatcher.chain.TxManager(), @@ -442,55 +448,6 @@ func newContractTransmitter(lggr logger.Logger, rargs commontypes.RelayArgs, tra ) } -func newPipelineContractTransmitter(lggr logger.Logger, rargs commontypes.RelayArgs, transmitterID string, pluginGasLimit *uint32, configWatcher *configWatcher, spec job.Job, pr pipeline.Runner) (*contractTransmitter, error) { - var relayConfig types.RelayConfig - if err := json.Unmarshal(rargs.RelayConfig, &relayConfig); err != nil { - return nil, err - } - - if !relayConfig.EffectiveTransmitterID.Valid { - return nil, pkgerrors.New("EffectiveTransmitterID must be specified") - } - effectiveTransmitterAddress := common.HexToAddress(relayConfig.EffectiveTransmitterID.String) - transmitterAddress := common.HexToAddress(transmitterID) - scoped := configWatcher.chain.Config() - strategy := txmgrcommon.NewQueueingTxStrategy(rargs.ExternalJobID, scoped.OCR2().DefaultTransactionQueueDepth(), scoped.Database().DefaultQueryTimeout()) - - var checker txm.TransmitCheckerSpec - if configWatcher.chain.Config().OCR2().SimulateTransactions() { - checker.CheckerType = txm.TransmitCheckerTypeSimulate - } - - gasLimit := configWatcher.chain.Config().EVM().GasEstimator().LimitDefault() - ocr2Limit := configWatcher.chain.Config().EVM().GasEstimator().LimitJobType().OCR2() - if ocr2Limit != nil { - gasLimit = *ocr2Limit - } - if pluginGasLimit != nil { - gasLimit = *pluginGasLimit - } - - return NewOCRContractTransmitter( - configWatcher.contractAddress, - configWatcher.chain.Client(), - configWatcher.contractABI, - ocrcommon.NewPipelineTransmitter( - lggr, - transmitterAddress, - gasLimit, - effectiveTransmitterAddress, - strategy, - checker, - pr, - spec, - configWatcher.chain.ID().String(), - ), - configWatcher.chain.LogPoller(), - lggr, - nil, - ) -} - func (r *Relayer) NewMedianProvider(rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (commontypes.MedianProvider, error) { lggr := r.lggr.Named("MedianProvider").Named(rargs.ExternalJobID.String()) relayOpts := types.NewRelayOpts(rargs) @@ -513,7 +470,7 @@ func (r *Relayer) NewMedianProvider(rargs commontypes.RelayArgs, pargs commontyp } reportCodec := evmreportcodec.ReportCodec{} - contractTransmitter, err := newContractTransmitter(lggr, rargs, pargs.TransmitterID, configWatcher, r.ks.Eth()) + contractTransmitter, err := newContractTransmitter(lggr, rargs, pargs.TransmitterID, r.ks.Eth(), configWatcher, configTransmitterOpts{}) if err != nil { return nil, err } diff --git a/core/services/relay/evm/ocr2keeper.go b/core/services/relay/evm/ocr2keeper.go index abc03c7abb1..55c4d78e7b4 100644 --- a/core/services/relay/evm/ocr2keeper.go +++ b/core/services/relay/evm/ocr2keeper.go @@ -22,8 +22,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) @@ -51,21 +50,19 @@ type OCR2KeeperRelayer interface { // ocr2keeperRelayer is the relayer with added DKG and OCR2Keeper provider functions. type ocr2keeperRelayer struct { - db *sqlx.DB - chain legacyevm.Chain - pr pipeline.Runner - spec job.Job - lggr logger.Logger + db *sqlx.DB + chain legacyevm.Chain + lggr logger.Logger + ethKeystore keystore.Eth } // NewOCR2KeeperRelayer is the constructor of ocr2keeperRelayer -func NewOCR2KeeperRelayer(db *sqlx.DB, chain legacyevm.Chain, pr pipeline.Runner, spec job.Job, lggr logger.Logger) OCR2KeeperRelayer { +func NewOCR2KeeperRelayer(db *sqlx.DB, chain legacyevm.Chain, lggr logger.Logger, ethKeystore keystore.Eth) OCR2KeeperRelayer { return &ocr2keeperRelayer{ - db: db, - chain: chain, - pr: pr, - spec: spec, - lggr: lggr, + db: db, + chain: chain, + lggr: lggr, + ethKeystore: ethKeystore, } } @@ -76,7 +73,7 @@ func (r *ocr2keeperRelayer) NewOCR2KeeperProvider(rargs commontypes.RelayArgs, p } gasLimit := cfgWatcher.chain.Config().EVM().OCR2().Automation().GasLimit() - contractTransmitter, err := newPipelineContractTransmitter(r.lggr, rargs, pargs.TransmitterID, &gasLimit, cfgWatcher, r.spec, r.pr) + contractTransmitter, err := newContractTransmitter(r.lggr, rargs, pargs.TransmitterID, r.ethKeystore, cfgWatcher, configTransmitterOpts{pluginGasLimit: &gasLimit}) if err != nil { return nil, err } diff --git a/core/services/relay/evm/ocr2vrf.go b/core/services/relay/evm/ocr2vrf.go index 39d0503b8b1..1e05f89d9de 100644 --- a/core/services/relay/evm/ocr2vrf.go +++ b/core/services/relay/evm/ocr2vrf.go @@ -67,7 +67,7 @@ func (r *ocr2vrfRelayer) NewDKGProvider(rargs commontypes.RelayArgs, pargs commo if err != nil { return nil, err } - contractTransmitter, err := newContractTransmitter(r.lggr, rargs, pargs.TransmitterID, configWatcher, r.ethKeystore) + contractTransmitter, err := newContractTransmitter(r.lggr, rargs, pargs.TransmitterID, r.ethKeystore, configWatcher, configTransmitterOpts{}) if err != nil { return nil, err } @@ -90,7 +90,7 @@ func (r *ocr2vrfRelayer) NewOCR2VRFProvider(rargs commontypes.RelayArgs, pargs c if err != nil { return nil, err } - contractTransmitter, err := newContractTransmitter(r.lggr, rargs, pargs.TransmitterID, configWatcher, r.ethKeystore) + contractTransmitter, err := newContractTransmitter(r.lggr, rargs, pargs.TransmitterID, r.ethKeystore, configWatcher, configTransmitterOpts{}) if err != nil { return nil, err } From f3d5417948c9a837b50327d4bf6a218fac915a92 Mon Sep 17 00:00:00 2001 From: Connor Stein Date: Tue, 12 Dec 2023 17:11:55 -0500 Subject: [PATCH 10/29] Standardize LP filter logging (#11515) * Standardize logs * Comments * More PR review * More * Fix test --- core/chains/evm/logpoller/log_poller.go | 15 +++++++++------ .../evm/logpoller/log_poller_internal_test.go | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/core/chains/evm/logpoller/log_poller.go b/core/chains/evm/logpoller/log_poller.go index 77b80253591..991cc8d4309 100644 --- a/core/chains/evm/logpoller/log_poller.go +++ b/core/chains/evm/logpoller/log_poller.go @@ -217,6 +217,7 @@ func (filter *Filter) Contains(other *Filter) bool { // Generally speaking this is harmless. We enforce that EventSigs and Addresses are non-empty, // which means that anonymous events are not supported and log.Topics >= 1 always (log.Topics[0] is the event signature). // The filter may be unregistered later by Filter.Name +// Warnings/debug information is keyed by filter name. func (lp *logPoller) RegisterFilter(filter Filter, qopts ...pg.QOpt) error { if len(filter.Addresses) == 0 { return errors.Errorf("at least one address must be specified") @@ -242,33 +243,35 @@ func (lp *logPoller) RegisterFilter(filter Filter, qopts ...pg.QOpt) error { if existingFilter, ok := lp.filters[filter.Name]; ok { if existingFilter.Contains(&filter) { // Nothing new in this Filter + lp.lggr.Warnw("Filter already present, no-op", "name", filter.Name, "filter", filter) return nil } - lp.lggr.Warnw("Updating existing filter with more events or addresses", "filter", filter) - } else { - lp.lggr.Debugw("Creating new filter", "filter", filter) + lp.lggr.Warnw("Updating existing filter with more events or addresses", "name", filter.Name, "filter", filter) } if err := lp.orm.InsertFilter(filter, qopts...); err != nil { - return errors.Wrap(err, "RegisterFilter failed to save filter to db") + return errors.Wrap(err, "error inserting filter") } lp.filters[filter.Name] = filter lp.filterDirty = true return nil } +// UnregisterFilter will remove the filter with the given name. +// If the name does not exist, it will log an error but not return an error. +// Warnings/debug information is keyed by filter name. func (lp *logPoller) UnregisterFilter(name string, qopts ...pg.QOpt) error { lp.filterMu.Lock() defer lp.filterMu.Unlock() _, ok := lp.filters[name] if !ok { - lp.lggr.Errorf("Filter %s not found", name) + lp.lggr.Warnw("Filter not found", "name", name) return nil } if err := lp.orm.DeleteFilter(name, qopts...); err != nil { - return errors.Wrapf(err, "Failed to delete filter %s", name) + return errors.Wrap(err, "error deleting filter") } delete(lp.filters, name) lp.filterDirty = true diff --git a/core/chains/evm/logpoller/log_poller_internal_test.go b/core/chains/evm/logpoller/log_poller_internal_test.go index f840eefc7b8..09e1deb864f 100644 --- a/core/chains/evm/logpoller/log_poller_internal_test.go +++ b/core/chains/evm/logpoller/log_poller_internal_test.go @@ -57,7 +57,7 @@ func TestLogPoller_RegisterFilter(t *testing.T) { a1 := common.HexToAddress("0x2ab9a2dc53736b361b72d900cdf9f78f9406fbbb") a2 := common.HexToAddress("0x2ab9a2dc53736b361b72d900cdf9f78f9406fbbc") - lggr, observedLogs := logger.TestObserved(t, zapcore.ErrorLevel) + lggr, observedLogs := logger.TestObserved(t, zapcore.WarnLevel) chainID := testutils.NewRandomEVMChainID() db := pgtest.NewSqlxDB(t) From ac9338f723d43283554e76bd9a996ebcaa90024d Mon Sep 17 00:00:00 2001 From: Rens Rooimans Date: Wed, 13 Dec 2023 10:37:42 +0100 Subject: [PATCH 11/29] bump Foundry to the December release (#11540) --- .github/workflows/solidity-foundry.yml | 2 +- contracts/GNUmakefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/solidity-foundry.yml b/.github/workflows/solidity-foundry.yml index 7f6fa4f482e..b629106972e 100644 --- a/.github/workflows/solidity-foundry.yml +++ b/.github/workflows/solidity-foundry.yml @@ -58,7 +58,7 @@ jobs: uses: foundry-rs/foundry-toolchain@v1 with: # Has to match the `make foundry` version. - version: nightly-09fe3e041369a816365a020f715ad6f94dbce9f2 + version: nightly-5b7e4cb3c882b28f3c32ba580de27ce7381f415a - name: Run Forge build if: needs.changes.outputs.changes == 'true' diff --git a/contracts/GNUmakefile b/contracts/GNUmakefile index f5be193249c..8ec536d520f 100644 --- a/contracts/GNUmakefile +++ b/contracts/GNUmakefile @@ -43,7 +43,7 @@ mockery: $(mockery) ## Install mockery. .PHONY: foundry foundry: ## Install foundry. - foundryup --version nightly-09fe3e041369a816365a020f715ad6f94dbce9f2 + foundryup --version nightly-5b7e4cb3c882b28f3c32ba580de27ce7381f415a .PHONY: foundry-refresh foundry-refresh: foundry From 57236b327a4f3f86d378ad2622572f3833256d3f Mon Sep 17 00:00:00 2001 From: Adam Hamrick Date: Wed, 13 Dec 2023 09:20:12 -0500 Subject: [PATCH 12/29] Removes Optimism Goerli from Scheduled Tests (#11559) * Removes Optimism Goerli from Scheduled Tests * Missed a spot --- .github/workflows/live-testnet-tests.yml | 57 +----------------------- 1 file changed, 2 insertions(+), 55 deletions(-) diff --git a/.github/workflows/live-testnet-tests.yml b/.github/workflows/live-testnet-tests.yml index 2e9809505f2..d060b5c510d 100644 --- a/.github/workflows/live-testnet-tests.yml +++ b/.github/workflows/live-testnet-tests.yml @@ -33,9 +33,6 @@ env: BSC_TESTNET_URLS: ${{ secrets.QA_BSC_TESTNET_URLS }} BSC_TESTNET_HTTP_URLS: ${{ secrets.QA_BSC_TESTNET_HTTP_URLS }} - OPTIMISM_GOERLI_URLS: ${{ secrets.QA_OPTIMISM_GOERLI_URLS }} - OPTIMISM_GOERLI_HTTP_URLS: ${{ secrets.QA_OPTIMISM_GOERLI_HTTP_URLS }} - OPTIMISM_SEPOLIA_URLS: ${{ secrets.QA_OPTIMISM_SEPOLIA_URLS }} OPTIMISM_SEPOLIA_HTTP_URLS: ${{ secrets.QA_OPTIMISM_SEPOLIA_HTTP_URLS }} @@ -147,7 +144,7 @@ jobs: id-token: write contents: read runs-on: ubuntu-latest - needs: [sepolia-smoke-tests, bsc-testnet-tests, optimism-goerli-smoke-tests, optimism-sepolia-smoke-tests, arbitrum-sepolia-smoke-tests, base-goerli-smoke-tests, base-sepolia-smoke-tests, polygon-mumbai-smoke-tests, avalanche-fuji-smoke-tests, fantom-testnet-smoke-tests, celo-alfajores-smoke-tests, scroll-sepolia-smoke-tests, linea-goerli-smoke-tests] + needs: [sepolia-smoke-tests, bsc-testnet-tests, optimism-sepolia-smoke-tests, arbitrum-sepolia-smoke-tests, base-goerli-smoke-tests, base-sepolia-smoke-tests, polygon-mumbai-smoke-tests, avalanche-fuji-smoke-tests, fantom-testnet-smoke-tests, celo-alfajores-smoke-tests, scroll-sepolia-smoke-tests, linea-goerli-smoke-tests] steps: - name: Debug Result run: echo ${{ join(needs.*.result, ',') }} @@ -208,7 +205,7 @@ jobs: strategy: fail-fast: false matrix: - network: [Sepolia, Optimism Goerli, Optimism Sepolia, Arbitrum Sepolia, Base Goerli, Base Sepolia, Polygon Mumbai, Avalanche Fuji, Fantom Testnet, Celo Alfajores, Scroll Sepolia, Linea Goerli] + network: [Sepolia, Optimism Sepolia, Arbitrum Sepolia, Base Goerli, Base Sepolia, Polygon Mumbai, Avalanche Fuji, Fantom Testnet, Celo Alfajores, Scroll Sepolia, Linea Goerli] steps: - name: Get Results id: test-results @@ -391,56 +388,6 @@ jobs: QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} - optimism-goerli-smoke-tests: - environment: integration - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - needs: [build-chainlink, build-tests] - env: - SELECTED_NETWORKS: OPTIMISM_GOERLI - strategy: - fail-fast: false - max-parallel: 1 - matrix: - include: # https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs#example-adding-configurations - - product: OCR - test: TestOCRBasic - - product: Automation Conditional - test: TestAutomationBasic/registry_2_1_conditional - - product: Automation Log Trigger - test: TestAutomationBasic/registry_2_1_logtrigger - name: Optimism Goerli ${{ matrix.product }} Tests - runs-on: ubuntu-latest - steps: - - name: Download Tests Binary - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: tests - - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests-binary@912bed7e07a1df4d06ea53a031e9773bb65dc7bd # v2.3.0 - env: - PYROSCOPE_SERVER: ${{ secrets.QA_PYROSCOPE_INSTANCE }} - PYROSCOPE_ENVIRONMENT: ci-smoke-${{ matrix.product }}-optimism-goerli - PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - with: - test_command_to_run: ./tests -test.timeout 30m -test.count=1 -test.parallel=1 -test.run ${{ matrix.test }} - binary_name: tests - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ github.sha }} - aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }} - dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }} - artifacts_location: ./logs - token: ${{ secrets.GITHUB_TOKEN }} - cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} - cache_restore_only: "true" - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} - optimism-sepolia-smoke-tests: environment: integration permissions: From 1a26acd5515ddeaf14e17f98cfbf474249d05157 Mon Sep 17 00:00:00 2001 From: Jordan Krage Date: Wed, 13 Dec 2023 08:35:28 -0600 Subject: [PATCH 13/29] fix health monitoring (#11558) --- core/chains/evm/gas/models.go | 31 +++- core/chains/evm/gas/models_test.go | 71 +++++---- core/chains/evm/txmgr/broadcaster_test.go | 12 +- core/chains/evm/txmgr/confirmer_test.go | 13 +- core/services/chainlink/relayer_factory.go | 6 +- core/services/relay/evm/evm.go | 4 +- core/web/health_controller.go | 11 +- core/web/health_controller_test.go | 70 ++++++++- core/web/testdata/body/health.json | 166 +++++++++++++++++++++ 9 files changed, 333 insertions(+), 51 deletions(-) create mode 100644 core/web/testdata/body/health.json diff --git a/core/chains/evm/gas/models.go b/core/chains/evm/gas/models.go index c7476d58ba4..8d977df0991 100644 --- a/core/chains/evm/gas/models.go +++ b/core/chains/evm/gas/models.go @@ -71,19 +71,31 @@ func NewEstimator(lggr logger.Logger, ethClient evmclient.Client, cfg Config, ge if rollups.IsRollupWithL1Support(cfg.ChainType()) { l1Oracle = rollups.NewL1GasPriceOracle(lggr, ethClient, cfg.ChainType()) } + var newEstimator func(logger.Logger) EvmEstimator switch s { case "Arbitrum": - return NewWrappedEvmEstimator(NewArbitrumEstimator(lggr, geCfg, ethClient, ethClient), df, l1Oracle) + newEstimator = func(l logger.Logger) EvmEstimator { + return NewArbitrumEstimator(lggr, geCfg, ethClient, ethClient) + } case "BlockHistory": - return NewWrappedEvmEstimator(NewBlockHistoryEstimator(lggr, ethClient, cfg, geCfg, bh, *ethClient.ConfiguredChainID()), df, l1Oracle) + newEstimator = func(l logger.Logger) EvmEstimator { + return NewBlockHistoryEstimator(lggr, ethClient, cfg, geCfg, bh, *ethClient.ConfiguredChainID()) + } case "FixedPrice": - return NewWrappedEvmEstimator(NewFixedPriceEstimator(geCfg, bh, lggr), df, l1Oracle) + newEstimator = func(l logger.Logger) EvmEstimator { + return NewFixedPriceEstimator(geCfg, bh, lggr) + } case "L2Suggested", "SuggestedPrice": - return NewWrappedEvmEstimator(NewSuggestedPriceEstimator(lggr, ethClient), df, l1Oracle) + newEstimator = func(l logger.Logger) EvmEstimator { + return NewSuggestedPriceEstimator(lggr, ethClient) + } default: lggr.Warnf("GasEstimator: unrecognised mode '%s', falling back to FixedPriceEstimator", s) - return NewWrappedEvmEstimator(NewFixedPriceEstimator(geCfg, bh, lggr), df, l1Oracle) + newEstimator = func(l logger.Logger) EvmEstimator { + return NewFixedPriceEstimator(geCfg, bh, lggr) + } } + return NewWrappedEvmEstimator(lggr, newEstimator, df, l1Oracle) } // DynamicFee encompasses both FeeCap and TipCap for EIP1559 transactions @@ -150,6 +162,7 @@ func (fee EvmFee) ValidDynamic() bool { // WrappedEvmEstimator provides a struct that wraps the EVM specific dynamic and legacy estimators into one estimator that conforms to the generic FeeEstimator type WrappedEvmEstimator struct { services.StateMachine + lggr logger.Logger EvmEstimator EIP1559Enabled bool l1Oracle rollups.L1Oracle @@ -157,16 +170,18 @@ type WrappedEvmEstimator struct { var _ EvmFeeEstimator = (*WrappedEvmEstimator)(nil) -func NewWrappedEvmEstimator(e EvmEstimator, eip1559Enabled bool, l1Oracle rollups.L1Oracle) EvmFeeEstimator { +func NewWrappedEvmEstimator(lggr logger.Logger, newEstimator func(logger.Logger) EvmEstimator, eip1559Enabled bool, l1Oracle rollups.L1Oracle) EvmFeeEstimator { + lggr = logger.Named(lggr, "WrappedEvmEstimator") return &WrappedEvmEstimator{ - EvmEstimator: e, + lggr: lggr, + EvmEstimator: newEstimator(lggr), EIP1559Enabled: eip1559Enabled, l1Oracle: l1Oracle, } } func (e *WrappedEvmEstimator) Name() string { - return fmt.Sprintf("WrappedEvmEstimator(%s)", e.EvmEstimator.Name()) + return e.lggr.Name() } func (e *WrappedEvmEstimator) Start(ctx context.Context) error { diff --git a/core/chains/evm/gas/models_test.go b/core/chains/evm/gas/models_test.go index a2dce58ee3f..95a7a471eba 100644 --- a/core/chains/evm/gas/models_test.go +++ b/core/chains/evm/gas/models_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks" @@ -27,39 +28,41 @@ func TestWrappedEvmEstimator(t *testing.T) { FeeCap: assets.NewWeiI(20), TipCap: assets.NewWeiI(1), } - - e := mocks.NewEvmEstimator(t) - e.On("GetDynamicFee", mock.Anything, mock.Anything, mock.Anything). + est := mocks.NewEvmEstimator(t) + est.On("GetDynamicFee", mock.Anything, mock.Anything, mock.Anything). Return(dynamicFee, gasLimit, nil).Twice() - e.On("GetLegacyGas", mock.Anything, mock.Anything, mock.Anything, mock.Anything). + est.On("GetLegacyGas", mock.Anything, mock.Anything, mock.Anything, mock.Anything). Return(legacyFee, gasLimit, nil).Twice() - e.On("BumpDynamicFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything). + est.On("BumpDynamicFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything). Return(dynamicFee, gasLimit, nil).Once() - e.On("BumpLegacyGas", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything). + est.On("BumpLegacyGas", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything). Return(legacyFee, gasLimit, nil).Once() + getRootEst := func(logger.Logger) gas.EvmEstimator { return est } - mockEvmEstimatorName := "MockEstimator" - mockEstimatorName := "WrappedEvmEstimator(MockEstimator)" + mockEstimatorName := "WrappedEvmEstimator" + mockEvmEstimatorName := "WrappedEvmEstimator.MockEstimator" // L1Oracle returns the correct L1Oracle interface t.Run("L1Oracle", func(t *testing.T) { + lggr := logger.Test(t) // expect nil - estimator := gas.NewWrappedEvmEstimator(e, false, nil) + estimator := gas.NewWrappedEvmEstimator(lggr, getRootEst, false, nil) l1Oracle := estimator.L1Oracle() assert.Nil(t, l1Oracle) // expect l1Oracle oracle := rollupMocks.NewL1Oracle(t) - estimator = gas.NewWrappedEvmEstimator(e, false, oracle) + estimator = gas.NewWrappedEvmEstimator(lggr, getRootEst, false, oracle) l1Oracle = estimator.L1Oracle() assert.Equal(t, oracle, l1Oracle) }) // GetFee returns gas estimation based on configuration value t.Run("GetFee", func(t *testing.T) { + lggr := logger.Test(t) // expect legacy fee data dynamicFees := false - estimator := gas.NewWrappedEvmEstimator(e, dynamicFees, nil) + estimator := gas.NewWrappedEvmEstimator(lggr, getRootEst, dynamicFees, nil) fee, max, err := estimator.GetFee(ctx, nil, 0, nil) require.NoError(t, err) assert.Equal(t, gasLimit, max) @@ -69,7 +72,7 @@ func TestWrappedEvmEstimator(t *testing.T) { // expect dynamic fee data dynamicFees = true - estimator = gas.NewWrappedEvmEstimator(e, dynamicFees, nil) + estimator = gas.NewWrappedEvmEstimator(lggr, getRootEst, dynamicFees, nil) fee, max, err = estimator.GetFee(ctx, nil, 0, nil) require.NoError(t, err) assert.Equal(t, gasLimit, max) @@ -80,8 +83,9 @@ func TestWrappedEvmEstimator(t *testing.T) { // BumpFee returns bumped fee type based on original fee calculation t.Run("BumpFee", func(t *testing.T) { + lggr := logger.Test(t) dynamicFees := false - estimator := gas.NewWrappedEvmEstimator(e, dynamicFees, nil) + estimator := gas.NewWrappedEvmEstimator(lggr, getRootEst, dynamicFees, nil) // expect legacy fee data fee, max, err := estimator.BumpFee(ctx, gas.EvmFee{Legacy: assets.NewWeiI(0)}, 0, nil, nil) @@ -114,11 +118,12 @@ func TestWrappedEvmEstimator(t *testing.T) { }) t.Run("GetMaxCost", func(t *testing.T) { + lggr := logger.Test(t) val := assets.NewEthValue(1) // expect legacy fee data dynamicFees := false - estimator := gas.NewWrappedEvmEstimator(e, dynamicFees, nil) + estimator := gas.NewWrappedEvmEstimator(lggr, getRootEst, dynamicFees, nil) total, err := estimator.GetMaxCost(ctx, val, nil, gasLimit, nil) require.NoError(t, err) fee := new(big.Int).Mul(legacyFee.ToInt(), big.NewInt(int64(gasLimit))) @@ -126,7 +131,7 @@ func TestWrappedEvmEstimator(t *testing.T) { // expect dynamic fee data dynamicFees = true - estimator = gas.NewWrappedEvmEstimator(e, dynamicFees, nil) + estimator = gas.NewWrappedEvmEstimator(lggr, getRootEst, dynamicFees, nil) total, err = estimator.GetMaxCost(ctx, val, nil, gasLimit, nil) require.NoError(t, err) fee = new(big.Int).Mul(dynamicFee.FeeCap.ToInt(), big.NewInt(int64(gasLimit))) @@ -134,33 +139,38 @@ func TestWrappedEvmEstimator(t *testing.T) { }) t.Run("Name", func(t *testing.T) { - evmEstimator := mocks.NewEvmEstimator(t) - oracle := rollupMocks.NewL1Oracle(t) + lggr := logger.Test(t) + oracle := rollupMocks.NewL1Oracle(t) + evmEstimator := mocks.NewEvmEstimator(t) evmEstimator.On("Name").Return(mockEvmEstimatorName, nil).Once() - estimator := gas.NewWrappedEvmEstimator(evmEstimator, false, oracle) - name := estimator.Name() - require.Equal(t, mockEstimatorName, name) + estimator := gas.NewWrappedEvmEstimator(lggr, func(logger.Logger) gas.EvmEstimator { + return evmEstimator + }, false, oracle) + + require.Equal(t, mockEstimatorName, estimator.Name()) + require.Equal(t, mockEvmEstimatorName, evmEstimator.Name()) }) t.Run("Start and stop calls both EVM estimator and L1Oracle", func(t *testing.T) { - evmEstimator := mocks.NewEvmEstimator(t) + lggr := logger.Test(t) oracle := rollupMocks.NewL1Oracle(t) + evmEstimator := mocks.NewEvmEstimator(t) - evmEstimator.On("Name").Return(mockEvmEstimatorName, nil).Times(4) evmEstimator.On("Start", mock.Anything).Return(nil).Twice() evmEstimator.On("Close").Return(nil).Twice() oracle.On("Start", mock.Anything).Return(nil).Once() oracle.On("Close").Return(nil).Once() + getEst := func(logger.Logger) gas.EvmEstimator { return evmEstimator } - estimator := gas.NewWrappedEvmEstimator(evmEstimator, false, nil) + estimator := gas.NewWrappedEvmEstimator(lggr, getEst, false, nil) err := estimator.Start(ctx) require.NoError(t, err) err = estimator.Close() require.NoError(t, err) - estimator = gas.NewWrappedEvmEstimator(evmEstimator, false, oracle) + estimator = gas.NewWrappedEvmEstimator(lggr, getEst, false, oracle) err = estimator.Start(ctx) require.NoError(t, err) err = estimator.Close() @@ -168,22 +178,25 @@ func TestWrappedEvmEstimator(t *testing.T) { }) t.Run("Read calls both EVM estimator and L1Oracle", func(t *testing.T) { + lggr := logger.Test(t) evmEstimator := mocks.NewEvmEstimator(t) oracle := rollupMocks.NewL1Oracle(t) evmEstimator.On("Ready").Return(nil).Twice() oracle.On("Ready").Return(nil).Once() + getEst := func(logger.Logger) gas.EvmEstimator { return evmEstimator } - estimator := gas.NewWrappedEvmEstimator(evmEstimator, false, nil) + estimator := gas.NewWrappedEvmEstimator(lggr, getEst, false, nil) err := estimator.Ready() require.NoError(t, err) - estimator = gas.NewWrappedEvmEstimator(evmEstimator, false, oracle) + estimator = gas.NewWrappedEvmEstimator(lggr, getEst, false, oracle) err = estimator.Ready() require.NoError(t, err) }) t.Run("HealthReport merges report from EVM estimator and L1Oracle", func(t *testing.T) { + lggr := logger.Test(t) evmEstimator := mocks.NewEvmEstimator(t) oracle := rollupMocks.NewL1Oracle(t) @@ -192,17 +205,17 @@ func TestWrappedEvmEstimator(t *testing.T) { oracleKey := "oracle" oracleError := errors.New("oracle error") - evmEstimator.On("Name").Return(mockEvmEstimatorName, nil).Twice() evmEstimator.On("HealthReport").Return(map[string]error{evmEstimatorKey: evmEstimatorError}).Twice() oracle.On("HealthReport").Return(map[string]error{oracleKey: oracleError}).Once() + getEst := func(logger.Logger) gas.EvmEstimator { return evmEstimator } - estimator := gas.NewWrappedEvmEstimator(evmEstimator, false, nil) + estimator := gas.NewWrappedEvmEstimator(lggr, getEst, false, nil) report := estimator.HealthReport() require.True(t, errors.Is(report[evmEstimatorKey], evmEstimatorError)) require.Nil(t, report[oracleKey]) require.NotNil(t, report[mockEstimatorName]) - estimator = gas.NewWrappedEvmEstimator(evmEstimator, false, oracle) + estimator = gas.NewWrappedEvmEstimator(lggr, getEst, false, oracle) report = estimator.HealthReport() require.True(t, errors.Is(report[evmEstimatorKey], evmEstimatorError)) require.True(t, errors.Is(report[oracleKey], oracleError)) diff --git a/core/chains/evm/txmgr/broadcaster_test.go b/core/chains/evm/txmgr/broadcaster_test.go index b9e8fe99e31..f676d3d18e2 100644 --- a/core/chains/evm/txmgr/broadcaster_test.go +++ b/core/chains/evm/txmgr/broadcaster_test.go @@ -64,7 +64,9 @@ func NewTestEthBroadcaster( lggr := logger.Test(t) ge := config.EVM().GasEstimator() - estimator := gas.NewWrappedEvmEstimator(gas.NewFixedPriceEstimator(config.EVM().GasEstimator(), ge.BlockHistory(), lggr), ge.EIP1559DynamicFees(), nil) + estimator := gas.NewWrappedEvmEstimator(lggr, func(lggr logger.Logger) gas.EvmEstimator { + return gas.NewFixedPriceEstimator(config.EVM().GasEstimator(), ge.BlockHistory(), lggr) + }, ge.EIP1559DynamicFees(), nil) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, keyStore, estimator) txNonceSyncer := txmgr.NewNonceSyncer(txStore, lggr, ethClient) ethBroadcaster := txmgr.NewEvmBroadcaster(txStore, txmgr.NewEvmTxmClient(ethClient), txmgr.NewEvmTxmConfig(config.EVM()), txmgr.NewEvmTxmFeeConfig(config.EVM().GasEstimator()), config.EVM().Transactions(), config.Database().Listener(), keyStore, txBuilder, txNonceSyncer, lggr, checkerFactory, nonceAutoSync) @@ -1134,7 +1136,9 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { // same as the parent test, but callback is set by ctor t.Run("callback set by ctor", func(t *testing.T) { lggr := logger.Test(t) - estimator := gas.NewWrappedEvmEstimator(gas.NewFixedPriceEstimator(evmcfg.EVM().GasEstimator(), evmcfg.EVM().GasEstimator().BlockHistory(), lggr), evmcfg.EVM().GasEstimator().EIP1559DynamicFees(), nil) + estimator := gas.NewWrappedEvmEstimator(lggr, func(lggr logger.Logger) gas.EvmEstimator { + return gas.NewFixedPriceEstimator(evmcfg.EVM().GasEstimator(), evmcfg.EVM().GasEstimator().BlockHistory(), lggr) + }, evmcfg.EVM().GasEstimator().EIP1559DynamicFees(), nil) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), evmcfg.EVM().GasEstimator(), ethKeyStore, estimator) localNextNonce = getLocalNextNonce(t, eb, fromAddress) ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(localNextNonce), nil).Once() @@ -1759,7 +1763,9 @@ func TestEthBroadcaster_SyncNonce(t *testing.T) { ethNodeNonce := uint64(22) - estimator := gas.NewWrappedEvmEstimator(gas.NewFixedPriceEstimator(evmcfg.EVM().GasEstimator(), evmcfg.EVM().GasEstimator().BlockHistory(), lggr), evmcfg.EVM().GasEstimator().EIP1559DynamicFees(), nil) + estimator := gas.NewWrappedEvmEstimator(lggr, func(lggr logger.Logger) gas.EvmEstimator { + return gas.NewFixedPriceEstimator(evmcfg.EVM().GasEstimator(), evmcfg.EVM().GasEstimator().BlockHistory(), lggr) + }, evmcfg.EVM().GasEstimator().EIP1559DynamicFees(), nil) checkerFactory := &testCheckerFactory{} ge := evmcfg.EVM().GasEstimator() diff --git a/core/chains/evm/txmgr/confirmer_test.go b/core/chains/evm/txmgr/confirmer_test.go index 3acbfe9800c..30b2a391a7f 100644 --- a/core/chains/evm/txmgr/confirmer_test.go +++ b/core/chains/evm/txmgr/confirmer_test.go @@ -122,9 +122,10 @@ func TestEthConfirmer_Lifecycle(t *testing.T) { cltest.MustInsertRandomKey(t, ethKeyStore) cltest.MustInsertRandomKey(t, ethKeyStore) estimator := gasmocks.NewEvmEstimator(t) + newEst := func(logger.Logger) gas.EvmEstimator { return estimator } lggr := logger.Test(t) ge := config.EVM().GasEstimator() - feeEstimator := gas.NewWrappedEvmEstimator(estimator, ge.EIP1559DynamicFees(), nil) + feeEstimator := gas.NewWrappedEvmEstimator(lggr, newEst, ge.EIP1559DynamicFees(), nil) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, ethKeyStore, feeEstimator) ec := txmgr.NewEvmConfirmer(txStore, txmgr.NewEvmTxmClient(ethClient), txmgr.NewEvmTxmConfig(config.EVM()), txmgr.NewEvmTxmFeeConfig(ge), config.EVM().Transactions(), config.Database(), ethKeyStore, txBuilder, lggr) ctx := testutils.Context(t) @@ -1639,9 +1640,10 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing kst := ksmocks.NewEth(t) estimator := gasmocks.NewEvmEstimator(t) + newEst := func(logger.Logger) gas.EvmEstimator { return estimator } estimator.On("BumpLegacyGas", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, uint32(0), pkgerrors.Wrapf(commonfee.ErrConnectivity, "transaction...")) ge := ccfg.EVM().GasEstimator() - feeEstimator := gas.NewWrappedEvmEstimator(estimator, ge.EIP1559DynamicFees(), nil) + feeEstimator := gas.NewWrappedEvmEstimator(lggr, newEst, ge.EIP1559DynamicFees(), nil) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, kst, feeEstimator) addresses := []gethCommon.Address{fromAddress} kst.On("EnabledAddressesForChain", &cltest.FixtureChainID).Return(addresses, nil).Maybe() @@ -1685,9 +1687,10 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing estimator := gasmocks.NewEvmEstimator(t) estimator.On("BumpDynamicFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.DynamicFee{}, uint32(0), pkgerrors.Wrapf(commonfee.ErrConnectivity, "transaction...")) + newEst := func(logger.Logger) gas.EvmEstimator { return estimator } // Create confirmer with necessary state ge := ccfg.EVM().GasEstimator() - feeEstimator := gas.NewWrappedEvmEstimator(estimator, ge.EIP1559DynamicFees(), nil) + feeEstimator := gas.NewWrappedEvmEstimator(lggr, newEst, ge.EIP1559DynamicFees(), nil) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, kst, feeEstimator) addresses := []gethCommon.Address{fromAddress} kst.On("EnabledAddressesForChain", &cltest.FixtureChainID).Return(addresses, nil).Maybe() @@ -3079,7 +3082,9 @@ func ptr[T any](t T) *T { return &t } func newEthConfirmer(t testing.TB, txStore txmgr.EvmTxStore, ethClient client.Client, config evmconfig.ChainScopedConfig, ks keystore.Eth, fn txmgrcommon.ResumeCallback) *txmgr.Confirmer { lggr := logger.Test(t) ge := config.EVM().GasEstimator() - estimator := gas.NewWrappedEvmEstimator(gas.NewFixedPriceEstimator(ge, ge.BlockHistory(), lggr), ge.EIP1559DynamicFees(), nil) + estimator := gas.NewWrappedEvmEstimator(lggr, func(lggr logger.Logger) gas.EvmEstimator { + return gas.NewFixedPriceEstimator(ge, ge.BlockHistory(), lggr) + }, ge.EIP1559DynamicFees(), nil) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, ks, estimator) ec := txmgr.NewEvmConfirmer(txStore, txmgr.NewEvmTxmClient(ethClient), txmgr.NewEvmTxmConfig(config.EVM()), txmgr.NewEvmTxmFeeConfig(ge), config.EVM().Transactions(), config.Database(), ks, txBuilder, lggr) ec.SetResumeCallback(fn) diff --git a/core/services/chainlink/relayer_factory.go b/core/services/chainlink/relayer_factory.go index 4ed73d8e53b..b4bd530d080 100644 --- a/core/services/chainlink/relayer_factory.go +++ b/core/services/chainlink/relayer_factory.go @@ -45,9 +45,11 @@ func (r *RelayerFactory) NewEVM(ctx context.Context, config EVMFactoryConfig) (m relayers := make(map[relay.ID]evmrelay.LoopRelayAdapter) + lggr := r.Logger.Named("EVM") + // override some common opts with the factory values. this seems weird... maybe other signatures should change, or this should take a different type... ccOpts := legacyevm.ChainRelayExtenderConfig{ - Logger: r.Logger.Named("EVM"), + Logger: lggr, KeyStore: config.CSAETHKeystore.Eth(), ChainOpts: config.ChainOpts, } @@ -71,7 +73,7 @@ func (r *RelayerFactory) NewEVM(ctx context.Context, config EVMFactoryConfig) (m EventBroadcaster: ccOpts.EventBroadcaster, MercuryPool: r.MercuryPool, } - relayer, err2 := evmrelay.NewRelayer(r.Logger.Named("EVM").Named(relayID.ChainID), chain, relayerOpts) + relayer, err2 := evmrelay.NewRelayer(lggr.Named(relayID.ChainID), chain, relayerOpts) if err2 != nil { err = errors.Join(err, err2) continue diff --git a/core/services/relay/evm/evm.go b/core/services/relay/evm/evm.go index 83540e22bb7..303cdd3ba0e 100644 --- a/core/services/relay/evm/evm.go +++ b/core/services/relay/evm/evm.go @@ -13,6 +13,7 @@ import ( "github.com/jmoiron/sqlx" pkgerrors "github.com/pkg/errors" "go.uber.org/multierr" + "golang.org/x/exp/maps" "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator" "github.com/smartcontractkit/libocr/offchainreporting2/reportingplugin/median" @@ -121,11 +122,12 @@ func (r *Relayer) Close() error { // Ready does noop: always ready func (r *Relayer) Ready() error { - return nil + return r.chain.Ready() } func (r *Relayer) HealthReport() (report map[string]error) { report = make(map[string]error) + maps.Copy(report, r.chain.HealthReport()) return } diff --git a/core/web/health_controller.go b/core/web/health_controller.go index d6a7edb2340..d6490e5542a 100644 --- a/core/web/health_controller.go +++ b/core/web/health_controller.go @@ -1,7 +1,10 @@ package web import ( + "cmp" "net/http" + "slices" + "testing" "github.com/gin-gonic/gin" @@ -94,6 +97,12 @@ func (hc *HealthController) Health(c *gin.Context) { }) } + if testing.Testing() { + slices.SortFunc(checks, func(a, b presenters.Check) int { + return cmp.Compare(a.Name, b.Name) + }) + } + // return a json description of all the checks - jsonAPIResponse(c, checks, "checks") + jsonAPIResponseWithStatus(c, checks, "checks", status) } diff --git a/core/web/health_controller_test.go b/core/web/health_controller_test.go index d380b279d00..7e7c42141ca 100644 --- a/core/web/health_controller_test.go +++ b/core/web/health_controller_test.go @@ -1,15 +1,19 @@ package web_test import ( + "bytes" + _ "embed" + "encoding/json" + "io" "net/http" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/mocks" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestHealthController_Readyz(t *testing.T) { @@ -47,3 +51,63 @@ func TestHealthController_Readyz(t *testing.T) { }) } } + +func TestHealthController_Health_status(t *testing.T) { + var tt = []struct { + name string + ready bool + status int + }{ + { + name: "not ready", + ready: false, + status: http.StatusServiceUnavailable, + }, + { + name: "ready", + ready: true, + status: http.StatusOK, + }, + } + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + app := cltest.NewApplicationWithKey(t) + healthChecker := new(mocks.Checker) + healthChecker.On("Start").Return(nil).Once() + healthChecker.On("IsHealthy").Return(tc.ready, nil).Once() + healthChecker.On("Close").Return(nil).Once() + + app.HealthChecker = healthChecker + require.NoError(t, app.Start(testutils.Context(t))) + + client := app.NewHTTPClient(nil) + resp, cleanup := client.Get("/health") + t.Cleanup(cleanup) + assert.Equal(t, tc.status, resp.StatusCode) + }) + } +} + +var ( + //go:embed testdata/body/health.json + healthJSON string +) + +func TestHealthController_Health_body(t *testing.T) { + app := cltest.NewApplicationWithKey(t) + require.NoError(t, app.Start(testutils.Context(t))) + + client := app.NewHTTPClient(nil) + resp, cleanup := client.Get("/health") + t.Cleanup(cleanup) + assert.Equal(t, http.StatusServiceUnavailable, resp.StatusCode) + body, err := io.ReadAll(resp.Body) + require.NoError(t, err) + + // pretty print for comparison + var b bytes.Buffer + require.NoError(t, json.Indent(&b, body, "", " ")) + body = b.Bytes() + + assert.Equal(t, healthJSON, string(body)) +} diff --git a/core/web/testdata/body/health.json b/core/web/testdata/body/health.json new file mode 100644 index 00000000000..d8418560543 --- /dev/null +++ b/core/web/testdata/body/health.json @@ -0,0 +1,166 @@ +{ + "data": [ + { + "type": "checks", + "id": "EVM.0", + "attributes": { + "name": "EVM.0", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.0.BalanceMonitor", + "attributes": { + "name": "EVM.0.BalanceMonitor", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.0.HeadBroadcaster", + "attributes": { + "name": "EVM.0.HeadBroadcaster", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.0.HeadTracker", + "attributes": { + "name": "EVM.0.HeadTracker", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.0.HeadTracker.HeadListener", + "attributes": { + "name": "EVM.0.HeadTracker.HeadListener", + "status": "failing", + "output": "Listener is not connected" + } + }, + { + "type": "checks", + "id": "EVM.0.LogBroadcaster", + "attributes": { + "name": "EVM.0.LogBroadcaster", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.0.Txm", + "attributes": { + "name": "EVM.0.Txm", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.0.Txm.BlockHistoryEstimator", + "attributes": { + "name": "EVM.0.Txm.BlockHistoryEstimator", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.0.Txm.Broadcaster", + "attributes": { + "name": "EVM.0.Txm.Broadcaster", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.0.Txm.Confirmer", + "attributes": { + "name": "EVM.0.Txm.Confirmer", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.0.Txm.WrappedEvmEstimator", + "attributes": { + "name": "EVM.0.Txm.WrappedEvmEstimator", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "JobSpawner", + "attributes": { + "name": "JobSpawner", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Mercury.WSRPCPool", + "attributes": { + "name": "Mercury.WSRPCPool", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Monitor", + "attributes": { + "name": "Monitor", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "PipelineORM", + "attributes": { + "name": "PipelineORM", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "PipelineRunner", + "attributes": { + "name": "PipelineRunner", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "PromReporter", + "attributes": { + "name": "PromReporter", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "TelemetryManager", + "attributes": { + "name": "TelemetryManager", + "status": "passing", + "output": "" + } + } + ] +} \ No newline at end of file From 6f13447cca0105bccd0aeea6c6cf69526f3e1585 Mon Sep 17 00:00:00 2001 From: Gabriel Paradiso Date: Wed, 13 Dec 2023 15:49:01 +0100 Subject: [PATCH 14/29] [FUN-990] s4 observability improvements (#11512) * chore: count s4 number of updates performed by nodes * chore: add storage total use and slots occupied * chore: add plugin side of counting updates * fix: modify total size counter to use snapshot len * chore: take into account the payload size for total size * chore: fix lint errors * fix: fetch only payload_size, reword metrics help * chore: remove don_id label * chore: remove don_id for consistency --- core/services/functions/connector_handler.go | 10 ++++++++ core/services/ocr2/plugins/s4/plugin.go | 27 +++++++++++++++++--- core/services/s4/orm.go | 11 ++++---- core/services/s4/postgres_orm.go | 2 +- core/services/s4/postgres_orm_test.go | 1 + 5 files changed, 42 insertions(+), 9 deletions(-) diff --git a/core/services/functions/connector_handler.go b/core/services/functions/connector_handler.go index 5496bbdefc1..1594dc6eb56 100644 --- a/core/services/functions/connector_handler.go +++ b/core/services/functions/connector_handler.go @@ -13,6 +13,8 @@ import ( ethCommon "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" "github.com/smartcontractkit/chainlink-common/pkg/assets" "github.com/smartcontractkit/chainlink-common/pkg/services" @@ -57,6 +59,13 @@ var ( _ connector.GatewayConnectorHandler = &functionsConnectorHandler{} ) +var ( + promStorageUserUpdatesCount = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "storage_user_updates", + Help: "Number of storage updates performed by users", + }, []string{}) +) + // internal request ID is a hash of (sender, requestID) func InternalId(sender []byte, requestId []byte) RequestID { return RequestID(crypto.Keccak256Hash(append(sender, requestId...)).Bytes()) @@ -185,6 +194,7 @@ func (h *functionsConnectorHandler) handleSecretsSet(ctx context.Context, gatewa err = h.storage.Put(ctx, &key, &record, request.Signature) if err == nil { response.Success = true + promStorageUserUpdatesCount.WithLabelValues().Inc() } else { response.ErrorMessage = fmt.Sprintf("Failed to set secret: %v", err) } diff --git a/core/services/ocr2/plugins/s4/plugin.go b/core/services/ocr2/plugins/s4/plugin.go index fcb025b21cd..677743c091d 100644 --- a/core/services/ocr2/plugins/s4/plugin.go +++ b/core/services/ocr2/plugins/s4/plugin.go @@ -4,13 +4,28 @@ import ( "context" "time" + "github.com/pkg/errors" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" + + "github.com/smartcontractkit/libocr/commontypes" + "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/s4" +) - "github.com/pkg/errors" - "github.com/smartcontractkit/libocr/commontypes" - "github.com/smartcontractkit/libocr/offchainreporting2plus/types" +var ( + promStoragePluginUpdatesCount = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "storage_plugin_updates", + Help: "Number of storage updates fetched from other nodes", + }, []string{}) + + promStorageTotalByteSize = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "storage_total_byte_size", + Help: "Current byte size of data stored in S4", + }, []string{}) ) type plugin struct { @@ -59,6 +74,7 @@ func (c *plugin) Query(ctx context.Context, ts types.ReportTimestamp) (types.Que return nil, errors.Wrap(err, "failed to GetVersions in Query()") } + var storageTotalByteSize uint64 rows := make([]*SnapshotRow, len(snapshot)) for i, v := range snapshot { rows[i] = &SnapshotRow{ @@ -66,6 +82,8 @@ func (c *plugin) Query(ctx context.Context, ts types.ReportTimestamp) (types.Que Slotid: uint32(v.SlotId), Version: v.Version, } + + storageTotalByteSize += v.PayloadSize } queryBytes, err := MarshalQuery(rows, c.addressRange) @@ -76,6 +94,8 @@ func (c *plugin) Query(ctx context.Context, ts types.ReportTimestamp) (types.Que promReportingPluginsQueryRowsCount.WithLabelValues(c.config.ProductName).Set(float64(len(rows))) promReportingPluginsQueryByteSize.WithLabelValues(c.config.ProductName).Set(float64(len(queryBytes))) + promStorageTotalByteSize.WithLabelValues().Set(float64(storageTotalByteSize)) + c.addressRange.Advance() c.logger.Debug("S4StorageReporting Query", commontypes.LogFields{ @@ -268,6 +288,7 @@ func (c *plugin) ShouldAcceptFinalizedReport(ctx context.Context, ts types.Repor c.logger.Error("Failed to Update a row in ShouldAcceptFinalizedReport()", commontypes.LogFields{"err": err}) continue } + promStoragePluginUpdatesCount.WithLabelValues().Inc() } c.logger.Debug("S4StorageReporting ShouldAcceptFinalizedReport", commontypes.LogFields{ diff --git a/core/services/s4/orm.go b/core/services/s4/orm.go index 59f3410e143..4d3cee9312a 100644 --- a/core/services/s4/orm.go +++ b/core/services/s4/orm.go @@ -20,11 +20,12 @@ type Row struct { // SnapshotRow(s) are returned by GetSnapshot function. type SnapshotRow struct { - Address *big.Big - SlotId uint - Version uint64 - Expiration int64 - Confirmed bool + Address *big.Big + SlotId uint + Version uint64 + Expiration int64 + Confirmed bool + PayloadSize uint64 } //go:generate mockery --quiet --name ORM --output ./mocks/ --case=underscore diff --git a/core/services/s4/postgres_orm.go b/core/services/s4/postgres_orm.go index dba98b64aa6..1f92f2e1281 100644 --- a/core/services/s4/postgres_orm.go +++ b/core/services/s4/postgres_orm.go @@ -90,7 +90,7 @@ func (o orm) GetSnapshot(addressRange *AddressRange, qopts ...pg.QOpt) ([]*Snaps q := o.q.WithOpts(qopts...) rows := make([]*SnapshotRow, 0) - stmt := fmt.Sprintf(`SELECT address, slot_id, version, expiration, confirmed FROM %s WHERE namespace = $1 AND address >= $2 AND address <= $3;`, o.tableName) + stmt := fmt.Sprintf(`SELECT address, slot_id, version, expiration, confirmed, octet_length(payload) AS payload_size FROM %s WHERE namespace = $1 AND address >= $2 AND address <= $3;`, o.tableName) if err := q.Select(&rows, stmt, o.namespace, addressRange.MinAddress, addressRange.MaxAddress); err != nil { if !errors.Is(err, sql.ErrNoRows) { return nil, err diff --git a/core/services/s4/postgres_orm_test.go b/core/services/s4/postgres_orm_test.go index 4d07524b4ea..d26f082ce5b 100644 --- a/core/services/s4/postgres_orm_test.go +++ b/core/services/s4/postgres_orm_test.go @@ -181,6 +181,7 @@ func TestPostgresORM_GetSnapshot(t *testing.T) { assert.Equal(t, snapshotRow.Version, sr.Version) assert.Equal(t, snapshotRow.Expiration, sr.Expiration) assert.Equal(t, snapshotRow.Confirmed, sr.Confirmed) + assert.Equal(t, snapshotRow.PayloadSize, uint64(len(sr.Payload))) } }) From 9b500414c022acc7fa704b516dfe65194d49fea4 Mon Sep 17 00:00:00 2001 From: Adam Hamrick Date: Wed, 13 Dec 2023 10:04:45 -0500 Subject: [PATCH 15/29] [TT-367] [TT-745] Quick and Dirty OCRv2 Soak Test (#11487) * Quick and Dirty OCRv2 Soak Test * Enable version in on-demand action * Remove inputs * Default input * Fix echos * Debug * Bash shell * Increment another way * No 2130 silly * When did incrementing get hard? * Cleanup debug * Include in reporter * Fix version input * Instantiate map * Fix OCR2 job names * Change default intpus * Bridge work * Build pair IDs properly * Cleanup paths * Build more bridges * Fix configuration * Fix config build * Fix import --- .github/workflows/on-demand-ocr-soak-test.yml | 45 ++- integration-tests/actions/ocr2_helpers.go | 146 +++++++-- .../actions/ocr2_helpers_local.go | 9 +- integration-tests/actions/ocr_helpers.go | 2 +- .../actions/ocr_helpers_local.go | 2 +- integration-tests/client/chainlink.go | 9 +- .../contracts/contract_deployer.go | 20 ++ integration-tests/load/README.md | 17 +- integration-tests/load/ocr/README.md | 15 +- integration-tests/load/ocr/ocr_test.go | 5 +- integration-tests/load/ocr/vu.go | 1 + integration-tests/scripts/entrypoint | 4 + integration-tests/testreporters/ocr.go | 7 +- integration-tests/testsetups/ocr.go | 298 +++++++++++++----- 14 files changed, 447 insertions(+), 133 deletions(-) diff --git a/.github/workflows/on-demand-ocr-soak-test.yml b/.github/workflows/on-demand-ocr-soak-test.yml index 567d9510de9..a4289dd0129 100644 --- a/.github/workflows/on-demand-ocr-soak-test.yml +++ b/.github/workflows/on-demand-ocr-soak-test.yml @@ -55,18 +55,16 @@ on: description: Container image version for the Chainlink nodes required: true default: "2.7.0" - testDuration: - description: Duration of the test (time string) - required: false - default: 15m - chainlinkNodeFunding: - description: How much to fund each Chainlink node (in ETH) - required: false - default: ".001" - timeBetweenRounds: - description: How long to wait before starting a new round + ocrVersion: + description: Version of OCR to Use + type: choice + options: + - 1 + - 2 + testInputs: + description: Duration;Funding;TimeBetweenRounds required: false - default: 1m + default: "10m;.1;1m" jobs: ocr_soak_test: @@ -84,9 +82,7 @@ jobs: SELECTED_NETWORKS: ${{ inputs.network }} SLACK_API_KEY: ${{ secrets.QA_SLACK_API_KEY }} SLACK_CHANNEL: ${{ secrets.QA_SLACK_CHANNEL }} - OCR_TEST_DURATION: ${{ inputs.testDuration }} - OCR_CHAINLINK_NODE_FUNDING: ${{ inputs.chainlinkNodeFunding }} - OCR_TIME_BETWEEN_ROUNDS: ${{ inputs.timeBetweenRounds }} + OCR_VERSION: ${{ inputs.ocrVersion }} TEST_LOG_LEVEL: debug REF_NAME: ${{ github.head_ref || github.ref_name }} ENV_JOB_IMAGE_BASE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-tests @@ -101,6 +97,7 @@ jobs: continue-on-error: true - name: Get Inputs run: | + # Mask the sensitive inputs EVM_URLS=$(jq -r '.inputs.wsURL' $GITHUB_EVENT_PATH) EVM_HTTP_URLS=$(jq -r '.inputs.httpURL' $GITHUB_EVENT_PATH) EVM_KEYS=$(jq -r '.inputs.fundingPrivateKey' $GITHUB_EVENT_PATH) @@ -115,6 +112,26 @@ jobs: echo EVM_HTTP_URLS=$EVM_HTTP_URLS >> $GITHUB_ENV echo EVM_KEYS=$EVM_KEYS >> $GITHUB_ENV echo SLACK_USER=$SLACK_USER >> $GITHUB_ENV + + # Read in our test inputs + IFS=';' read -ra parts <<< "${{ inputs.testInputs }}" + index=0 + for part in "${parts[@]}"; do + # A little hacky, but good enough for this + if [ $index -eq 0 ]; then + echo "OCR_TEST_DURATION=$part" + echo "OCR_TEST_DURATION=$part" >> $GITHUB_ENV + elif [ $index -eq 1 ]; then + echo "OCR_CHAINLINK_NODE_FUNDING=$part" + echo "OCR_CHAINLINK_NODE_FUNDING=$part" >> $GITHUB_ENV + elif [ $index -eq 2 ]; then + echo "OCR_TIME_BETWEEN_ROUNDS=$part" + echo "OCR_TIME_BETWEEN_ROUNDS=$part" >> $GITHUB_ENV + else + echo "Additional Unregistered Input: $part" + fi + ((index+=1)) + done - name: Checkout the repo uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: diff --git a/integration-tests/actions/ocr2_helpers.go b/integration-tests/actions/ocr2_helpers.go index 02ce73e813e..c4bc30c7c5e 100644 --- a/integration-tests/actions/ocr2_helpers.go +++ b/integration-tests/actions/ocr2_helpers.go @@ -9,6 +9,7 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + "github.com/google/uuid" "github.com/lib/pq" "github.com/rs/zerolog" "github.com/rs/zerolog/log" @@ -23,6 +24,7 @@ import ( ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/testhelpers" "github.com/smartcontractkit/chainlink/v2/core/store/models" "github.com/smartcontractkit/chainlink/integration-tests/client" @@ -104,12 +106,15 @@ func ConfigureOCRv2AggregatorContracts( } // BuildMedianOCR2Config builds a default OCRv2 config for the given chainlink nodes for a standard median aggregation job -func BuildMedianOCR2Config(workerNodes []*client.ChainlinkK8sClient) (*contracts.OCRv2Config, error) { +func BuildMedianOCR2Config( + workerNodes []*client.ChainlinkK8sClient, + ocrOffchainOptions contracts.OffchainOptions, +) (*contracts.OCRv2Config, error) { S, oracleIdentities, err := GetOracleIdentities(workerNodes) if err != nil { return nil, err } - signerKeys, transmitterAccounts, f_, onchainConfig, offchainConfigVersion, offchainConfig, err := confighelper.ContractSetConfigArgsForTests( + signerKeys, transmitterAccounts, f_, _, offchainConfigVersion, offchainConfig, err := confighelper.ContractSetConfigArgsForTests( 30*time.Second, // deltaProgress time.Duration, 30*time.Second, // deltaResend time.Duration, 10*time.Second, // deltaRound time.Duration, @@ -149,6 +154,8 @@ func BuildMedianOCR2Config(workerNodes []*client.ChainlinkK8sClient) (*contracts transmitterAddresses = append(transmitterAddresses, common.HexToAddress(string(account))) } + onchainConfig, err := testhelpers.GenerateDefaultOCR2OnchainConfig(ocrOffchainOptions.MinimumAnswer, ocrOffchainOptions.MaximumAnswer) + return &contracts.OCRv2Config{ Signers: signerAddresses, Transmitters: transmitterAddresses, @@ -156,7 +163,7 @@ func BuildMedianOCR2Config(workerNodes []*client.ChainlinkK8sClient) (*contracts OnchainConfig: onchainConfig, OffchainConfigVersion: offchainConfigVersion, OffchainConfig: []byte(fmt.Sprintf("0x%s", offchainConfig)), - }, nil + }, err } // GetOracleIdentities retrieves all chainlink nodes' OCR2 config identities with defaul key index @@ -257,7 +264,6 @@ func CreateOCRv2Jobs( bootstrapNode *client.ChainlinkK8sClient, workerChainlinkNodes []*client.ChainlinkK8sClient, mockserver *ctfClient.MockserverClient, - mockServerPath string, // Path on the mock server for the Chainlink nodes to query mockServerValue int, // Value to get from the mock server when querying the path chainId uint64, // EVM chain ID forwardingAllowed bool, @@ -268,20 +274,28 @@ func CreateOCRv2Jobs( return err } p2pV2Bootstrapper := fmt.Sprintf("%s@%s:%d", bootstrapP2PIds.Data[0].Attributes.PeerID, bootstrapNode.InternalIP(), 6690) - // Set the value for the jobs to report on - err = mockserver.SetValuePath(mockServerPath, mockServerValue) - if err != nil { - return err - } + mockJuelsPath := "ocr2/juelsPerFeeCoinSource" // Set the juelsPerFeeCoinSource config value - err = mockserver.SetValuePath(fmt.Sprintf("%s/juelsPerFeeCoinSource", mockServerPath), mockServerValue) + err = mockserver.SetValuePath(mockJuelsPath, mockServerValue) if err != nil { return err } + // Create the juels bridge for each node only once + juelsBridge := &client.BridgeTypeAttributes{ + Name: "juels", + URL: fmt.Sprintf("%s/%s", mockserver.Config.ClusterURL, mockJuelsPath), + } + for _, chainlinkNode := range workerChainlinkNodes { + err = chainlinkNode.MustCreateBridge(juelsBridge) + if err != nil { + return fmt.Errorf("failed creating bridge %s on CL node : %w", juelsBridge.Name, err) + } + } + for _, ocrInstance := range ocrInstances { bootstrapSpec := &client.OCR2TaskJobSpec{ - Name: "ocr2 bootstrap node", + Name: fmt.Sprintf("ocr2-bootstrap-%s", ocrInstance.Address()), JobType: "bootstrap", OCR2OracleSpec: job.OCR2OracleSpec{ ContractID: ocrInstance.Address(), @@ -289,7 +303,7 @@ func CreateOCRv2Jobs( RelayConfig: map[string]interface{}{ "chainID": chainId, }, - MonitoringEndpoint: null.StringFrom(fmt.Sprintf("%s/%s", mockserver.Config.ClusterURL, mockServerPath)), + MonitoringEndpoint: null.StringFrom(fmt.Sprintf("%s/%s", mockserver.Config.ClusterURL, "ocr2")), ContractConfigTrackerPollInterval: *models.NewInterval(15 * time.Second), }, } @@ -309,25 +323,22 @@ func CreateOCRv2Jobs( } nodeOCRKeyId := nodeOCRKeys.Data[0].ID - bta := &client.BridgeTypeAttributes{ - Name: mockServerPath, - URL: fmt.Sprintf("%s/%s", mockserver.Config.ClusterURL, mockServerPath), + nodeContractPairID, err := BuildOCR2NodeContractPairID(chainlinkNode, ocrInstance) + if err != nil { + return err } - juelsBridge := &client.BridgeTypeAttributes{ - Name: "juels", - URL: fmt.Sprintf("%s/%s/juelsPerFeeCoinSource", mockserver.Config.ClusterURL, mockServerPath), + bta := &client.BridgeTypeAttributes{ + Name: nodeContractPairID, + URL: fmt.Sprintf("%s/%s", mockserver.Config.ClusterURL, strings.TrimPrefix(nodeContractPairID, "/")), } + err = chainlinkNode.MustCreateBridge(bta) if err != nil { - return fmt.Errorf("creating bridge job have failed: %w", err) - } - err = chainlinkNode.MustCreateBridge(juelsBridge) - if err != nil { - return fmt.Errorf("creating bridge job have failed: %w", err) + return fmt.Errorf("failed creating bridge %s on CL node: %w", bta.Name, err) } ocrSpec := &client.OCR2TaskJobSpec{ - Name: "ocr2", + Name: fmt.Sprintf("ocr2-%s", uuid.NewString()), JobType: "offchainreporting2", MaxTaskDuration: "1m", ObservationSource: client.ObservationSourceSpecBridge(bta), @@ -379,3 +390,90 @@ func StartNewOCR2Round( } return nil } + +// SetOCR2AdapterResponse sets a single adapter response that correlates with an ocr contract and a chainlink node +// used for OCR2 tests +func SetOCR2AdapterResponse( + response int, + ocrInstance contracts.OffchainAggregatorV2, + chainlinkNode *client.ChainlinkK8sClient, + mockserver *ctfClient.MockserverClient, +) error { + nodeContractPairID, err := BuildOCR2NodeContractPairID(chainlinkNode, ocrInstance) + if err != nil { + return err + } + path := fmt.Sprintf("/%s", nodeContractPairID) + err = mockserver.SetValuePath(path, response) + if err != nil { + return fmt.Errorf("setting mockserver value path failed: %w", err) + } + return nil +} + +// SetOCR2AllAdapterResponsesToTheSameValue sets the mock responses in mockserver that are read by chainlink nodes +// to simulate different adapters. This sets all adapter responses for each node and contract to the same response +// used for OCR2 tests +func SetOCR2AllAdapterResponsesToTheSameValue( + response int, + ocrInstances []contracts.OffchainAggregatorV2, + chainlinkNodes []*client.ChainlinkK8sClient, + mockserver *ctfClient.MockserverClient, +) error { + eg := &errgroup.Group{} + for _, o := range ocrInstances { + ocrInstance := o + for _, n := range chainlinkNodes { + node := n + eg.Go(func() error { + return SetOCR2AdapterResponse(response, ocrInstance, node, mockserver) + }) + } + } + return eg.Wait() +} + +// SetOCR2AllAdapterResponsesToDifferentValues sets the mock responses in mockserver that are read by chainlink nodes +// to simulate different adapters. This sets all adapter responses for each node and contract to different responses +// used for OCR2 tests +func SetOCR2AllAdapterResponsesToDifferentValues( + responses []int, + ocrInstances []contracts.OffchainAggregatorV2, + chainlinkNodes []*client.ChainlinkK8sClient, + mockserver *ctfClient.MockserverClient, +) error { + if len(responses) != len(ocrInstances)*len(chainlinkNodes) { + return fmt.Errorf( + "amount of responses %d should be equal to the amount of OCR instances %d times the amount of Chainlink nodes %d", + len(responses), len(ocrInstances), len(chainlinkNodes), + ) + } + eg := &errgroup.Group{} + for _, o := range ocrInstances { + ocrInstance := o + for ni := 1; ni < len(chainlinkNodes); ni++ { + nodeIndex := ni + eg.Go(func() error { + return SetOCR2AdapterResponse(responses[nodeIndex-1], ocrInstance, chainlinkNodes[nodeIndex], mockserver) + }) + } + } + return eg.Wait() +} + +// BuildOCR2NodeContractPairID builds a UUID based on a related pair of a Chainlink node and OCRv2 contract +func BuildOCR2NodeContractPairID(node *client.ChainlinkK8sClient, ocrInstance contracts.OffchainAggregatorV2) (string, error) { + if node == nil { + return "", fmt.Errorf("chainlink node is nil") + } + if ocrInstance == nil { + return "", fmt.Errorf("OCR Instance is nil") + } + nodeAddress, err := node.PrimaryEthAddress() + if err != nil { + return "", fmt.Errorf("getting chainlink node's primary ETH address failed: %w", err) + } + shortNodeAddr := nodeAddress[2:12] + shortOCRAddr := ocrInstance.Address()[2:12] + return strings.ToLower(fmt.Sprintf("node_%s_contract_%s", shortNodeAddr, shortOCRAddr)), nil +} diff --git a/integration-tests/actions/ocr2_helpers_local.go b/integration-tests/actions/ocr2_helpers_local.go index e1b470bd0d4..4a08921b8d1 100644 --- a/integration-tests/actions/ocr2_helpers_local.go +++ b/integration-tests/actions/ocr2_helpers_local.go @@ -20,12 +20,13 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" - "github.com/smartcontractkit/chainlink/integration-tests/client" - "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/testhelpers" "github.com/smartcontractkit/chainlink/v2/core/store/models" + + "github.com/smartcontractkit/chainlink/integration-tests/client" + "github.com/smartcontractkit/chainlink/integration-tests/contracts" ) func CreateOCRv2JobsLocal( @@ -95,11 +96,11 @@ func CreateOCRv2JobsLocal( } err = chainlinkNode.MustCreateBridge(bta) if err != nil { - return fmt.Errorf("creating bridge job have failed: %w", err) + return fmt.Errorf("creating bridge on CL node failed: %w", err) } err = chainlinkNode.MustCreateBridge(juelsBridge) if err != nil { - return fmt.Errorf("creating bridge job have failed: %w", err) + return fmt.Errorf("creating bridge on CL node failed: %w", err) } ocrSpec := &client.OCR2TaskJobSpec{ diff --git a/integration-tests/actions/ocr_helpers.go b/integration-tests/actions/ocr_helpers.go index 4f713dcdd6d..17e536ec839 100644 --- a/integration-tests/actions/ocr_helpers.go +++ b/integration-tests/actions/ocr_helpers.go @@ -236,7 +236,7 @@ func CreateOCRJobs( } err = node.MustCreateBridge(bta) if err != nil { - return fmt.Errorf("creating bridge job have failed: %w", err) + return fmt.Errorf("creating bridge on CL node failed: %w", err) } bootstrapPeers := []*client.ChainlinkClient{bootstrapNode.ChainlinkClient} diff --git a/integration-tests/actions/ocr_helpers_local.go b/integration-tests/actions/ocr_helpers_local.go index fb0fd0bd47d..e9cad3f67ea 100644 --- a/integration-tests/actions/ocr_helpers_local.go +++ b/integration-tests/actions/ocr_helpers_local.go @@ -196,7 +196,7 @@ func CreateOCRJobsLocal( } err = node.MustCreateBridge(bta) if err != nil { - return fmt.Errorf("creating bridge job have failed: %w", err) + return fmt.Errorf("creating bridge on CL node failed: %w", err) } bootstrapPeers := []*client.ChainlinkClient{bootstrapNode} diff --git a/integration-tests/client/chainlink.go b/integration-tests/client/chainlink.go index 16299a1ac8a..56670812fbc 100644 --- a/integration-tests/client/chainlink.go +++ b/integration-tests/client/chainlink.go @@ -267,6 +267,7 @@ func (c *ChainlinkClient) DeleteSpec(id string) (*http.Response, error) { // MustCreateBridge creates a bridge on the Chainlink node based on the provided attributes and returns error if // the request is unsuccessful func (c *ChainlinkClient) MustCreateBridge(bta *BridgeTypeAttributes) error { + c.l.Debug().Str(NodeURL, c.Config.URL).Str("Name", bta.Name).Msg("Creating Bridge") resp, err := c.CreateBridge(bta) if err != nil { return err @@ -275,7 +276,7 @@ func (c *ChainlinkClient) MustCreateBridge(bta *BridgeTypeAttributes) error { } func (c *ChainlinkClient) CreateBridge(bta *BridgeTypeAttributes) (*http.Response, error) { - c.l.Info().Str(NodeURL, c.Config.URL).Str("Name", bta.Name).Msg("Creating Bridge") + c.l.Debug().Str(NodeURL, c.Config.URL).Str("Name", bta.Name).Msg("Creating Bridge") resp, err := c.APIClient.R(). SetBody(bta). Post("/v2/bridge_types") @@ -288,7 +289,7 @@ func (c *ChainlinkClient) CreateBridge(bta *BridgeTypeAttributes) (*http.Respons // ReadBridge reads a bridge from the Chainlink node based on the provided name func (c *ChainlinkClient) ReadBridge(name string) (*BridgeType, *http.Response, error) { bt := BridgeType{} - c.l.Info().Str(NodeURL, c.Config.URL).Str("Name", name).Msg("Reading Bridge") + c.l.Debug().Str(NodeURL, c.Config.URL).Str("Name", name).Msg("Reading Bridge") resp, err := c.APIClient.R(). SetPathParams(map[string]string{ "name": name, @@ -304,7 +305,7 @@ func (c *ChainlinkClient) ReadBridge(name string) (*BridgeType, *http.Response, // ReadBridges reads bridges from the Chainlink node func (c *ChainlinkClient) ReadBridges() (*Bridges, *resty.Response, error) { result := &Bridges{} - c.l.Info().Str(NodeURL, c.Config.URL).Msg("Getting all bridges") + c.l.Debug().Str(NodeURL, c.Config.URL).Msg("Getting all bridges") resp, err := c.APIClient.R(). SetResult(&result). Get("/v2/bridge_types") @@ -316,7 +317,7 @@ func (c *ChainlinkClient) ReadBridges() (*Bridges, *resty.Response, error) { // DeleteBridge deletes a bridge on the Chainlink node based on the provided name func (c *ChainlinkClient) DeleteBridge(name string) (*http.Response, error) { - c.l.Info().Str(NodeURL, c.Config.URL).Str("Name", name).Msg("Deleting Bridge") + c.l.Debug().Str(NodeURL, c.Config.URL).Str("Name", name).Msg("Deleting Bridge") resp, err := c.APIClient.R(). SetPathParams(map[string]string{ "name": name, diff --git a/integration-tests/contracts/contract_deployer.go b/integration-tests/contracts/contract_deployer.go index 528f07ec68e..464ae7a340b 100644 --- a/integration-tests/contracts/contract_deployer.go +++ b/integration-tests/contracts/contract_deployer.go @@ -135,6 +135,7 @@ type ContractDeployer interface { DeployOffchainAggregatorEventsMock() (OffchainAggregatorEventsMock, error) DeployMockAggregatorProxy(aggregatorAddr string) (MockAggregatorProxy, error) DeployOffchainAggregatorV2(linkAddr string, offchainOptions OffchainOptions) (OffchainAggregatorV2, error) + LoadOffChainAggregatorV2(address *common.Address) (OffchainAggregatorV2, error) DeployKeeperRegistryCheckUpkeepGasUsageWrapper(keeperRegistryAddr string) (KeeperRegistryCheckUpkeepGasUsageWrapper, error) DeployKeeperRegistry11Mock() (KeeperRegistry11Mock, error) DeployKeeperRegistrar12Mock() (KeeperRegistrar12Mock, error) @@ -1584,6 +1585,25 @@ func (e *EthereumContractDeployer) DeployOffchainAggregatorV2( }, err } +// LoadOffChainAggregatorV2 loads an already deployed offchain aggregator v2 contract +func (e *EthereumContractDeployer) LoadOffChainAggregatorV2(address *common.Address) (OffchainAggregatorV2, error) { + instance, err := e.client.LoadContract("OffChainAggregatorV2", *address, func( + address common.Address, + backend bind.ContractBackend, + ) (interface{}, error) { + return ocr2aggregator.NewOCR2Aggregator(address, backend) + }) + if err != nil { + return nil, err + } + return &EthereumOffchainAggregatorV2{ + client: e.client, + contract: instance.(*ocr2aggregator.OCR2Aggregator), + address: address, + l: e.l, + }, err +} + func (e *EthereumContractDeployer) DeployMercuryVerifierContract(verifierProxyAddr common.Address) (MercuryVerifier, error) { address, _, instance, err := e.client.DeployContract("Mercury Verifier", func( auth *bind.TransactOpts, diff --git a/integration-tests/load/README.md b/integration-tests/load/README.md index 1ed1ee8b94e..3738a1d9ace 100644 --- a/integration-tests/load/README.md +++ b/integration-tests/load/README.md @@ -1,9 +1,11 @@ -## Performance tests for CL jobs +# Performance tests for CL jobs This folder container performance e2e tests for different job types, currently implemented: + - VRFv2 All the tests have 4 groups: + - one product soak - one product load - multiple product instances soak @@ -12,11 +14,13 @@ All the tests have 4 groups: When you develop an e2e performance suite for a new product you can implement the tests one by one to answer the questions: What are performance characteristics of a one instance of a product (jobs + contracts): + - is our product stable at all, no memory leaks, no flaking performance under some RPS? (test #1) - what are the limits for one product instance, figuring out the max/optimal performance params by increasing RPS and varying configuration (test #2) - update test #1 with optimal params and workload to constantly run in CI What are performance and capacity characteristics of Chainlink node(s) that run multiple products of the same type simultaneously: + - how many products of the same type we can run at once at a stable load with optimal configuration? (test #3) - what are the limits if we add more and more products of the same type, each product have a stable RPS, we vary only amount of products - update test #3 with optimal params and workload to constantly run in CI @@ -24,9 +28,9 @@ What are performance and capacity characteristics of Chainlink node(s) that run Implementing test #1 is **mandatory** for each product. Tests #2,#3,#4 are optional if you need to figure out your product scaling or node/cluster capacity. - ## Usage -``` + +```sh export LOKI_TOKEN=... export LOKI_URL=... @@ -34,10 +38,12 @@ go test -v -run TestVRFV2Load/vrfv2_soak_test ``` ### Dashboards + Each product has its own generated dashboard in `cmd/dashboard.go` Deploying dashboard: -``` + +```sh export GRAFANA_URL=... export GRAFANA_TOKEN=... export DATA_SOURCE_NAME=grafanacloud-logs @@ -56,8 +62,9 @@ If you need to assert some metrics in `Prometheus/Loki`, here is an [example](ht Do not mix workload logic with assertions, separate them. ### Implementation + To implement a standard e2e performance suite for a new product please look at `gun.go` and `vu.go`. Gun should be working with one instance of your product. -VU(Virtual user) creates a new instance of your product and works with it in `Call()` \ No newline at end of file +VU(Virtual user) creates a new instance of your product and works with it in `Call()` diff --git a/integration-tests/load/ocr/README.md b/integration-tests/load/ocr/README.md index 61951ba700f..3c231b50278 100644 --- a/integration-tests/load/ocr/README.md +++ b/integration-tests/load/ocr/README.md @@ -1,12 +1,21 @@ -### OCR Load tests +# OCR Load tests ## Setup + These tests can connect to any cluster create with [chainlink-cluster](../../../charts/chainlink-cluster/README.md) +<<<<<<< HEAD +Create your cluster + +```sh +kubectl create ns my-cluster +devspace use namespace my-cluster +======= Create your cluster, if you already have one just use `kubefwd` ``` kubectl create ns cl-cluster devspace use namespace cl-cluster +>>>>>>> 06656fac80999d1539e16951a54b87c6df13a9c7 devspace deploy sudo kubefwd svc -n cl-cluster ``` @@ -17,7 +26,7 @@ If you haven't changed anything in [devspace.yaml](../../../charts/chainlink-clu ## Usage -``` +```sh export LOKI_TOKEN=... export LOKI_URL=... @@ -25,4 +34,4 @@ go test -v -run TestOCRLoad go test -v -run TestOCRVolume ``` -Check test configuration [here](config.toml) \ No newline at end of file +Check test configuration [here](config.toml) diff --git a/integration-tests/load/ocr/ocr_test.go b/integration-tests/load/ocr/ocr_test.go index 13aea441b2a..49e624ecd89 100644 --- a/integration-tests/load/ocr/ocr_test.go +++ b/integration-tests/load/ocr/ocr_test.go @@ -3,12 +3,13 @@ package ocr import ( "testing" - "github.com/smartcontractkit/chainlink/integration-tests/k8s" + "github.com/stretchr/testify/require" "github.com/smartcontractkit/wasp" - "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-testing-framework/logging" + + "github.com/smartcontractkit/chainlink/integration-tests/k8s" ) var ( diff --git a/integration-tests/load/ocr/vu.go b/integration-tests/load/ocr/vu.go index a905ec011df..96be77c701a 100644 --- a/integration-tests/load/ocr/vu.go +++ b/integration-tests/load/ocr/vu.go @@ -13,6 +13,7 @@ import ( "go.uber.org/ratelimit" client2 "github.com/smartcontractkit/chainlink-testing-framework/client" + "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" diff --git a/integration-tests/scripts/entrypoint b/integration-tests/scripts/entrypoint index cb5c98fde6a..d2297abaa98 100755 --- a/integration-tests/scripts/entrypoint +++ b/integration-tests/scripts/entrypoint @@ -24,6 +24,7 @@ echo "Test exit code: ${exit_code}" # 3 is the code for an interrupted test, we only want to restart the test when the test is interrupted and in a state # that it can recover from. Otherwise we mark the test as "passed" as far as K8s is concerned so it doesn't restart it. if [ $exit_code -eq 3 ]; then +echo "Test was interrupted, exiting with 1 exit code to trigger K8s to restart" exit 1 # Exiting with non-zero status to trigger pod restart fi @@ -38,3 +39,6 @@ fi if [ -n "${UPLOAD_MEM_PROFILE}" ]; then upload_to_slack memprofile.out "MEM Profile for ${TEST_NAME}" fi + +echo "Exiting with 0 exit code as test is either completed, or failed and cannot be restarted" +exit 0 \ No newline at end of file diff --git a/integration-tests/testreporters/ocr.go b/integration-tests/testreporters/ocr.go index abbb261fa74..31f5eeab1b9 100644 --- a/integration-tests/testreporters/ocr.go +++ b/integration-tests/testreporters/ocr.go @@ -21,6 +21,7 @@ import ( type OCRSoakTestReporter struct { StartTime time.Time AnomaliesDetected bool + OCRVersion string anomalies [][]string timeLine [][]string @@ -159,7 +160,7 @@ func (o *OCRSoakTestReporter) SetNamespace(namespace string) { // WriteReport writes OCR Soak test report to a CSV file and final report func (o *OCRSoakTestReporter) WriteReport(folderLocation string) error { - log.Debug().Msg("Writing OCR Soak Test Report") + log.Debug().Msgf("Writing OCRv%s Soak Test Report", o.OCRVersion) reportLocation := filepath.Join(folderLocation, "./ocr_soak_report.csv") o.csvLocation = reportLocation ocrReportFile, err := os.Create(reportLocation) @@ -170,7 +171,7 @@ func (o *OCRSoakTestReporter) WriteReport(folderLocation string) error { ocrReportWriter := csv.NewWriter(ocrReportFile) - err = ocrReportWriter.Write([]string{"OCR Soak Test Report"}) + err = ocrReportWriter.Write([]string{fmt.Sprintf("OCRv%s Soak Test Report", o.OCRVersion)}) if err != nil { return err } @@ -240,7 +241,7 @@ func (o *OCRSoakTestReporter) SendSlackNotification(t *testing.T, slackClient *s } testFailed := t.Failed() - headerText := ":white_check_mark: OCR Soak Test PASSED :white_check_mark:" + headerText := fmt.Sprintf(":white_check_mark: OCRv%s Soak Test PASSED :white_check_mark:", o.OCRVersion) if testFailed { headerText = ":x: OCR Soak Test FAILED :x:" } else if o.AnomaliesDetected { diff --git a/integration-tests/testsetups/ocr.go b/integration-tests/testsetups/ocr.go index a35d915ea92..f7e0e65d36d 100644 --- a/integration-tests/testsetups/ocr.go +++ b/integration-tests/testsetups/ocr.go @@ -25,6 +25,7 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator" + "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" @@ -72,12 +73,16 @@ type OCRSoakTest struct { ocrRoundStates []*testreporters.OCRRoundState testIssues []*testreporters.TestIssue - ocrInstances []contracts.OffchainAggregator - ocrInstanceMap map[string]contracts.OffchainAggregator // address : instance + ocrV1Instances []contracts.OffchainAggregator + ocrV1InstanceMap map[string]contracts.OffchainAggregator // address : instance + + ocrV2Instances []contracts.OffchainAggregatorV2 + ocrV2InstanceMap map[string]contracts.OffchainAggregatorV2 // address : instance } // OCRSoakTestInputs define required inputs to run an OCR soak test type OCRSoakTestInputs struct { + OCRVersion string `envconfig:"OCR_VERSION" default:"1"` // Version of OCR to use (1 or 2) TestDuration time.Duration `envconfig:"TEST_DURATION" default:"15m"` // How long to run the test for NumberOfContracts int `envconfig:"NUMBER_CONTRACTS" default:"2"` // Number of OCR contracts to launch ChainlinkNodeFunding float64 `envconfig:"CHAINLINK_NODE_FUNDING" default:".1"` // Amount of native currency to fund each chainlink node with @@ -86,6 +91,7 @@ type OCRSoakTestInputs struct { } func (i OCRSoakTestInputs) setForRemoteRunner() { + os.Setenv("TEST_OCR_VERSION", i.OCRVersion) os.Setenv("TEST_OCR_TEST_DURATION", i.TestDuration.String()) os.Setenv("TEST_OCR_NUMBER_CONTRACTS", fmt.Sprint(i.NumberOfContracts)) os.Setenv("TEST_OCR_CHAINLINK_NODE_FUNDING", strconv.FormatFloat(i.ChainlinkNodeFunding, 'f', -1, 64)) @@ -113,14 +119,16 @@ func NewOCRSoakTest(t *testing.T, forwarderFlow bool) (*OCRSoakTest, error) { Inputs: &testInputs, OperatorForwarderFlow: forwarderFlow, TestReporter: testreporters.OCRSoakTestReporter{ - StartTime: time.Now(), + OCRVersion: testInputs.OCRVersion, + StartTime: time.Now(), }, - t: t, - startTime: time.Now(), - timeLeft: testInputs.TestDuration, - log: logging.GetTestLogger(t), - ocrRoundStates: make([]*testreporters.OCRRoundState, 0), - ocrInstanceMap: make(map[string]contracts.OffchainAggregator), + t: t, + startTime: time.Now(), + timeLeft: testInputs.TestDuration, + log: logging.GetTestLogger(t), + ocrRoundStates: make([]*testreporters.OCRRoundState, 0), + ocrV1InstanceMap: make(map[string]contracts.OffchainAggregator), + ocrV2InstanceMap: make(map[string]contracts.OffchainAggregatorV2), } return test, test.ensureInputValues() } @@ -128,7 +136,7 @@ func NewOCRSoakTest(t *testing.T, forwarderFlow bool) (*OCRSoakTest, error) { // DeployEnvironment deploys the test environment, starting all Chainlink nodes and other components for the test func (o *OCRSoakTest) DeployEnvironment(customChainlinkNetworkTOML string) { network := networks.MustGetSelectedNetworksFromEnv()[0] // Environment currently being used to soak test on - nsPre := "soak-ocr-" + nsPre := fmt.Sprintf("soak-ocr-v%s-", o.Inputs.OCRVersion) if o.OperatorForwarderFlow { nsPre = fmt.Sprintf("%sforwarder-", nsPre) } @@ -140,9 +148,15 @@ func (o *OCRSoakTest) DeployEnvironment(customChainlinkNetworkTOML string) { PreventPodEviction: true, } + var conf string + if o.Inputs.OCRVersion == "1" { + conf = config.BaseOCR1Config + } else if o.Inputs.OCRVersion == "2" { + conf = config.BaseOCR2Config + } cd := chainlink.New(0, map[string]any{ "replicas": 6, - "toml": networks.AddNetworkDetailedConfig(config.BaseOCR1Config, customChainlinkNetworkTOML, network), + "toml": networks.AddNetworkDetailedConfig(conf, customChainlinkNetworkTOML, network), "db": map[string]any{ "stateful": true, // stateful DB by default for soak tests }, @@ -228,7 +242,7 @@ func (o *OCRSoakTest) Setup() { err = o.chainClient.WaitForEvents() } - o.ocrInstances = actions.DeployOCRContractsForwarderFlow( + o.ocrV1Instances = actions.DeployOCRContractsForwarderFlow( o.t, o.Inputs.NumberOfContracts, linkTokenContract, @@ -237,8 +251,8 @@ func (o *OCRSoakTest) Setup() { authorizedForwarders, o.chainClient, ) - } else { - o.ocrInstances, err = actions.DeployOCRContracts( + } else if o.Inputs.OCRVersion == "1" { + o.ocrV1Instances, err = actions.DeployOCRContracts( o.Inputs.NumberOfContracts, linkTokenContract, contractDeployer, @@ -246,13 +260,41 @@ func (o *OCRSoakTest) Setup() { o.chainClient, ) require.NoError(o.t, err) + } else if o.Inputs.OCRVersion == "2" { + var transmitters []string + for _, node := range o.workerNodes { + nodeAddress, err := node.PrimaryEthAddress() + require.NoError(o.t, err, "Error getting node's primary ETH address") + transmitters = append(transmitters, nodeAddress) + } + ocrOffchainOptions := contracts.DefaultOffChainAggregatorOptions() + o.ocrV2Instances, err = actions.DeployOCRv2Contracts( + o.Inputs.NumberOfContracts, + linkTokenContract, + contractDeployer, + transmitters, + o.chainClient, + ocrOffchainOptions, + ) + require.NoError(o.t, err, "Error deploying OCRv2 contracts") + contractConfig, err := actions.BuildMedianOCR2Config(o.workerNodes, ocrOffchainOptions) + require.NoError(o.t, err, "Error building median config") + err = actions.ConfigureOCRv2AggregatorContracts(o.chainClient, contractConfig, o.ocrV2Instances) + require.NoError(o.t, err, "Error configuring OCRv2 aggregator contracts") } err = o.chainClient.WaitForEvents() require.NoError(o.t, err, "Error waiting for OCR contracts to be deployed") - for _, ocrInstance := range o.ocrInstances { - o.ocrInstanceMap[ocrInstance.Address()] = ocrInstance + if o.Inputs.OCRVersion == "1" { + for _, ocrInstance := range o.ocrV1Instances { + o.ocrV1InstanceMap[ocrInstance.Address()] = ocrInstance + } + } else if o.Inputs.OCRVersion == "2" { + for _, ocrInstance := range o.ocrV2Instances { + o.ocrV2InstanceMap[ocrInstance.Address()] = ocrInstance + } } + o.log.Info().Msg("OCR Soak Test Setup Complete") } @@ -266,15 +308,19 @@ func (o *OCRSoakTest) Run() { startingValue := 5 if o.OperatorForwarderFlow { - actions.CreateOCRJobsWithForwarder(o.t, o.ocrInstances, o.bootstrapNode, o.workerNodes, startingValue, o.mockServer, o.chainClient.GetChainID().String()) - } else { - err := actions.CreateOCRJobs(o.ocrInstances, o.bootstrapNode, o.workerNodes, startingValue, o.mockServer, o.chainClient.GetChainID().String()) + actions.CreateOCRJobsWithForwarder(o.t, o.ocrV1Instances, o.bootstrapNode, o.workerNodes, startingValue, o.mockServer, o.chainClient.GetChainID().String()) + } else if o.Inputs.OCRVersion == "1" { + err := actions.CreateOCRJobs(o.ocrV1Instances, o.bootstrapNode, o.workerNodes, startingValue, o.mockServer, o.chainClient.GetChainID().String()) + require.NoError(o.t, err, "Error creating OCR jobs") + } else if o.Inputs.OCRVersion == "2" { + err := actions.CreateOCRv2Jobs(o.ocrV2Instances, o.bootstrapNode, o.workerNodes, o.mockServer, startingValue, o.chainClient.GetChainID().Uint64(), o.OperatorForwarderFlow) require.NoError(o.t, err, "Error creating OCR jobs") } o.log.Info(). Str("Test Duration", o.Inputs.TestDuration.Truncate(time.Second).String()). - Int("Number of OCR Contracts", len(o.ocrInstances)). + Int("Number of OCR Contracts", o.Inputs.NumberOfContracts). + Str("OCR Version", o.Inputs.OCRVersion). Msg("Starting OCR Soak Test") o.testLoop(o.Inputs.TestDuration, startingValue) @@ -306,6 +352,7 @@ type OCRSoakTestState struct { TimeRunning time.Duration `toml:"timeRunning"` TestDuration time.Duration `toml:"testDuration"` OCRContractAddresses []string `toml:"ocrContractAddresses"` + OCRVersion string `toml:"ocrVersion"` BootStrapNodeURL string `toml:"bootstrapNodeURL"` WorkerNodeURLs []string `toml:"workerNodeURLs"` @@ -315,10 +362,7 @@ type OCRSoakTestState struct { // SaveState saves the current state of the test to a TOML file func (o *OCRSoakTest) SaveState() error { - ocrAddresses := make([]string, len(o.ocrInstances)) - for i, ocrInstance := range o.ocrInstances { - ocrAddresses[i] = ocrInstance.Address() - } + ocrAddresses := o.getContractAddressesString() workerNodeURLs := make([]string, len(o.workerNodes)) for i, workerNode := range o.workerNodes { workerNodeURLs[i] = workerNode.URL() @@ -333,6 +377,7 @@ func (o *OCRSoakTest) SaveState() error { TimeRunning: time.Since(o.startTime), TestDuration: o.Inputs.TestDuration, OCRContractAddresses: ocrAddresses, + OCRVersion: o.Inputs.OCRVersion, ChainURL: o.chainClient.GetNetworkConfig().URL, MockServerURL: "http://mockserver:1080", // TODO: Make this dynamic @@ -378,7 +423,8 @@ func (o *OCRSoakTest) LoadState() error { o.namespace = testState.Namespace o.TestReporter = testreporters.OCRSoakTestReporter{ - StartTime: testState.StartTime, + OCRVersion: testState.OCRVersion, + StartTime: testState.StartTime, } o.ocrRoundStates = testState.OCRRoundStates o.testIssues = testState.TestIssues @@ -386,6 +432,7 @@ func (o *OCRSoakTest) LoadState() error { o.timeLeft = testState.TestDuration - testState.TimeRunning o.startTime = testState.StartTime o.startingBlockNum = testState.StartingBlockNum + o.Inputs.OCRVersion = testState.OCRVersion network := networks.MustGetSelectedNetworksFromEnv()[0] o.chainClient, err = blockchain.ConnectEVMClient(network, o.log) @@ -405,15 +452,28 @@ func (o *OCRSoakTest) LoadState() error { return err } - o.ocrInstances = make([]contracts.OffchainAggregator, len(testState.OCRContractAddresses)) - for i, addr := range testState.OCRContractAddresses { - address := common.HexToAddress(addr) - instance, err := contractDeployer.LoadOffChainAggregator(&address) - if err != nil { - return err + if testState.OCRVersion == "1" { + o.ocrV1Instances = make([]contracts.OffchainAggregator, len(testState.OCRContractAddresses)) + for i, addr := range testState.OCRContractAddresses { + address := common.HexToAddress(addr) + instance, err := contractDeployer.LoadOffChainAggregator(&address) + if err != nil { + return err + } + o.ocrV1Instances[i] = instance + } + } else if testState.OCRVersion == "2" { + o.ocrV2Instances = make([]contracts.OffchainAggregatorV2, len(testState.OCRContractAddresses)) + for i, addr := range testState.OCRContractAddresses { + address := common.HexToAddress(addr) + instance, err := contractDeployer.LoadOffChainAggregatorV2(&address) + if err != nil { + return err + } + o.ocrV2Instances[i] = instance } - o.ocrInstances[i] = instance } + o.mockServer, err = ctfClient.ConnectMockServerURL(testState.MockServerURL) if err != nil { return err @@ -432,16 +492,30 @@ func (o *OCRSoakTest) Resume() { Str("Time Left", o.timeLeft.String()). Msg("Resuming OCR Soak Test") - ocrAddresses := make([]common.Address, len(o.ocrInstances)) - for i, ocrInstance := range o.ocrInstances { - ocrAddresses[i] = common.HexToAddress(ocrInstance.Address()) - } - contractABI, err := offchainaggregator.OffchainAggregatorMetaData.GetAbi() - require.NoError(o.t, err, "Error retrieving OCR contract ABI") - o.filterQuery = geth.FilterQuery{ - Addresses: ocrAddresses, - Topics: [][]common.Hash{{contractABI.Events["AnswerUpdated"].ID}}, - FromBlock: big.NewInt(0).SetUint64(o.startingBlockNum), + ocrAddresses := make([]common.Address, o.Inputs.NumberOfContracts) + + if o.Inputs.OCRVersion == "1" { + for i, ocrInstance := range o.ocrV1Instances { + ocrAddresses[i] = common.HexToAddress(ocrInstance.Address()) + } + contractABI, err := offchainaggregator.OffchainAggregatorMetaData.GetAbi() + require.NoError(o.t, err, "Error retrieving OCR contract ABI") + o.filterQuery = geth.FilterQuery{ + Addresses: ocrAddresses, + Topics: [][]common.Hash{{contractABI.Events["AnswerUpdated"].ID}}, + FromBlock: big.NewInt(0).SetUint64(o.startingBlockNum), + } + } else if o.Inputs.OCRVersion == "2" { + for i, ocrInstance := range o.ocrV2Instances { + ocrAddresses[i] = common.HexToAddress(ocrInstance.Address()) + } + contractABI, err := ocr2aggregator.AggregatorInterfaceMetaData.GetAbi() + require.NoError(o.t, err, "Error retrieving OCR contract ABI") + o.filterQuery = geth.FilterQuery{ + Addresses: ocrAddresses, + Topics: [][]common.Hash{{contractABI.Events["AnswerUpdated"].ID}}, + FromBlock: big.NewInt(0).SetUint64(o.startingBlockNum), + } } startingValue := 5 @@ -449,7 +523,7 @@ func (o *OCRSoakTest) Resume() { o.log.Info().Msg("Test Complete, collecting on-chain events") - err = o.collectEvents() + err := o.collectEvents() o.log.Error().Err(err).Interface("Query", o.filterQuery).Msg("Error collecting on-chain events, expect malformed report") o.TestReporter.RecordEvents(o.ocrRoundStates, o.testIssues) } @@ -537,10 +611,7 @@ func (o *OCRSoakTest) complete() { // setFilterQuery to look for all events that happened func (o *OCRSoakTest) setFilterQuery() { - ocrAddresses := make([]common.Address, len(o.ocrInstances)) - for i, ocrInstance := range o.ocrInstances { - ocrAddresses[i] = common.HexToAddress(ocrInstance.Address()) - } + ocrAddresses := o.getContractAddresses() contractABI, err := offchainaggregator.OffchainAggregatorMetaData.GetAbi() require.NoError(o.t, err, "Error retrieving OCR contract ABI") o.filterQuery = geth.FilterQuery{ @@ -570,21 +641,39 @@ func (o *OCRSoakTest) observeOCREvents() error { for { select { case event := <-eventLogs: - answerUpdated, err := o.ocrInstances[0].ParseEventAnswerUpdated(event) - if err != nil { - o.log.Warn(). - Err(err). + if o.Inputs.OCRVersion == "1" { + answerUpdated, err := o.ocrV1Instances[0].ParseEventAnswerUpdated(event) + if err != nil { + o.log.Warn(). + Err(err). + Str("Address", event.Address.Hex()). + Uint64("Block Number", event.BlockNumber). + Msg("Error parsing event as AnswerUpdated") + continue + } + o.log.Info(). Str("Address", event.Address.Hex()). Uint64("Block Number", event.BlockNumber). - Msg("Error parsing event as AnswerUpdated") - continue + Uint64("Round ID", answerUpdated.RoundId.Uint64()). + Int64("Answer", answerUpdated.Current.Int64()). + Msg("Answer Updated Event") + } else if o.Inputs.OCRVersion == "2" { + answerUpdated, err := o.ocrV2Instances[0].ParseEventAnswerUpdated(event) + if err != nil { + o.log.Warn(). + Err(err). + Str("Address", event.Address.Hex()). + Uint64("Block Number", event.BlockNumber). + Msg("Error parsing event as AnswerUpdated") + continue + } + o.log.Info(). + Str("Address", event.Address.Hex()). + Uint64("Block Number", event.BlockNumber). + Uint64("Round ID", answerUpdated.RoundId.Uint64()). + Int64("Answer", answerUpdated.Current.Int64()). + Msg("Answer Updated Event") } - o.log.Info(). - Str("Address", event.Address.Hex()). - Uint64("Block Number", event.BlockNumber). - Uint64("Round ID", answerUpdated.RoundId.Uint64()). - Int64("Answer", answerUpdated.Current.Int64()). - Msg("Answer Updated Event") case err = <-eventSub.Err(): backoff := time.Second for err != nil { @@ -614,7 +703,12 @@ func (o *OCRSoakTest) triggerNewRound(newValue int) error { o.ocrRoundStates[len(o.ocrRoundStates)-1].EndTime = time.Now() } - err := actions.SetAllAdapterResponsesToTheSameValue(newValue, o.ocrInstances, o.workerNodes, o.mockServer) + var err error + if o.Inputs.OCRVersion == "1" { + err = actions.SetAllAdapterResponsesToTheSameValue(newValue, o.ocrV1Instances, o.workerNodes, o.mockServer) + } else if o.Inputs.OCRVersion == "2" { + err = actions.SetOCR2AllAdapterResponsesToTheSameValue(newValue, o.ocrV2Instances, o.workerNodes, o.mockServer) + } if err != nil { return err } @@ -624,9 +718,16 @@ func (o *OCRSoakTest) triggerNewRound(newValue int) error { Answer: int64(newValue), FoundEvents: make(map[string][]*testreporters.FoundEvent), } - for _, ocrInstance := range o.ocrInstances { - expectedState.FoundEvents[ocrInstance.Address()] = make([]*testreporters.FoundEvent, 0) + if o.Inputs.OCRVersion == "1" { + for _, ocrInstance := range o.ocrV1Instances { + expectedState.FoundEvents[ocrInstance.Address()] = make([]*testreporters.FoundEvent, 0) + } + } else if o.Inputs.OCRVersion == "2" { + for _, ocrInstance := range o.ocrV2Instances { + expectedState.FoundEvents[ocrInstance.Address()] = make([]*testreporters.FoundEvent, 0) + } } + o.ocrRoundStates = append(o.ocrRoundStates, expectedState) o.log.Info(). Int("Value", newValue). @@ -662,17 +763,31 @@ func (o *OCRSoakTest) collectEvents() error { sortedFoundEvents := make([]*testreporters.FoundEvent, 0) for _, event := range contractEvents { - answerUpdated, err := o.ocrInstances[0].ParseEventAnswerUpdated(event) - if err != nil { - return fmt.Errorf("error parsing EventAnswerUpdated for event: %v, %w", event, err) + if o.Inputs.OCRVersion == "1" { + answerUpdated, err := o.ocrV1Instances[0].ParseEventAnswerUpdated(event) + if err != nil { + return fmt.Errorf("error parsing EventAnswerUpdated for event: %v, %w", event, err) + } + sortedFoundEvents = append(sortedFoundEvents, &testreporters.FoundEvent{ + StartTime: time.Unix(answerUpdated.UpdatedAt.Int64(), 0), + Address: event.Address.Hex(), + Answer: answerUpdated.Current.Int64(), + RoundID: answerUpdated.RoundId.Uint64(), + BlockNumber: event.BlockNumber, + }) + } else if o.Inputs.OCRVersion == "2" { + answerUpdated, err := o.ocrV2Instances[0].ParseEventAnswerUpdated(event) + if err != nil { + return fmt.Errorf("error parsing EventAnswerUpdated for event: %v, %w", event, err) + } + sortedFoundEvents = append(sortedFoundEvents, &testreporters.FoundEvent{ + StartTime: time.Unix(answerUpdated.UpdatedAt.Int64(), 0), + Address: event.Address.Hex(), + Answer: answerUpdated.Current.Int64(), + RoundID: answerUpdated.RoundId.Uint64(), + BlockNumber: event.BlockNumber, + }) } - sortedFoundEvents = append(sortedFoundEvents, &testreporters.FoundEvent{ - StartTime: time.Unix(answerUpdated.UpdatedAt.Int64(), 0), - Address: event.Address.Hex(), - Answer: answerUpdated.Current.Int64(), - RoundID: answerUpdated.RoundId.Uint64(), - BlockNumber: event.BlockNumber, - }) } // Sort our events by time to make sure they are in order (don't trust RPCs) @@ -705,6 +820,9 @@ func (o *OCRSoakTest) collectEvents() error { // ensureValues ensures that all values needed to run the test are present func (o *OCRSoakTest) ensureInputValues() error { inputs := o.Inputs + if inputs.OCRVersion != "1" && inputs.OCRVersion != "2" { + return fmt.Errorf("OCR version must be 1 or 2, found %s", inputs.OCRVersion) + } if inputs.NumberOfContracts <= 0 { return fmt.Errorf("Number of OCR contracts must be greater than 0, found %d", inputs.NumberOfContracts) } @@ -723,3 +841,39 @@ func (o *OCRSoakTest) ensureInputValues() error { o.Inputs.bigChainlinkNodeFunding = big.NewFloat(inputs.ChainlinkNodeFunding) return nil } + +// getContractAddressesString returns the addresses of all OCR contracts deployed as a string slice +func (o *OCRSoakTest) getContractAddressesString() []string { + contractAddresses := []string{} + if len(o.ocrV1Instances) != 0 { + for _, ocrInstance := range o.ocrV1Instances { + contractAddresses = append(contractAddresses, ocrInstance.Address()) + } + } else if len(o.ocrV2Instances) != 0 { + if len(o.ocrV2Instances) != 0 { + for _, ocrInstance := range o.ocrV2Instances { + contractAddresses = append(contractAddresses, ocrInstance.Address()) + } + } + } + + return contractAddresses +} + +// getContractAddresses returns the addresses of all OCR contracts deployed +func (o *OCRSoakTest) getContractAddresses() []common.Address { + contractAddresses := []common.Address{} + if len(o.ocrV1Instances) != 0 { + for _, ocrInstance := range o.ocrV1Instances { + contractAddresses = append(contractAddresses, common.HexToAddress(ocrInstance.Address())) + } + } else if len(o.ocrV2Instances) != 0 { + if len(o.ocrV2Instances) != 0 { + for _, ocrInstance := range o.ocrV2Instances { + contractAddresses = append(contractAddresses, common.HexToAddress(ocrInstance.Address())) + } + } + } + + return contractAddresses +} From 862f79ab2f469a36bae5f6623432ba37878d6be3 Mon Sep 17 00:00:00 2001 From: Jordan Krage Date: Wed, 13 Dec 2023 12:18:35 -0600 Subject: [PATCH 16/29] bump common; use SugaredLogger methods (#11556) --- common/client/multi_node.go | 17 +++-- common/client/node_lifecycle.go | 29 +++++---- common/headtracker/head_tracker.go | 8 +-- common/txmgr/broadcaster.go | 18 +++--- common/txmgr/confirmer.go | 23 ++++--- common/txmgr/resender.go | 4 +- common/txmgr/txmgr.go | 10 +-- common/txmgr/types/client.go | 4 +- common/txmgr/types/tx.go | 6 +- core/chains/evm/client/chain_client.go | 8 +-- core/chains/evm/client/client.go | 8 +-- core/chains/evm/client/errors.go | 8 +-- core/chains/evm/client/helpers_test.go | 2 +- core/chains/evm/client/node.go | 61 +++++++++--------- core/chains/evm/client/node_lifecycle.go | 29 +++++---- core/chains/evm/client/pool.go | 12 ++-- core/chains/evm/client/rpc_client.go | 63 +++++++++---------- .../chains/evm/gas/block_history_estimator.go | 16 ++--- .../evm/gas/rollups/l1_gas_price_oracle.go | 6 +- core/chains/evm/log/helpers_test.go | 6 +- core/chains/evm/log/registrations.go | 24 +++---- core/chains/evm/logpoller/log_poller.go | 8 +-- core/chains/evm/txmgr/broadcaster_test.go | 2 +- core/chains/evm/txmgr/client.go | 8 +-- core/chains/evm/txmgr/evm_tx_store.go | 6 +- core/chains/evm/txmgr/transmitchecker.go | 10 +-- core/chains/evm/txmgr/transmitchecker_test.go | 2 +- core/scripts/go.mod | 2 +- core/scripts/go.sum | 4 +- core/services/pg/q.go | 6 +- go.mod | 2 +- go.sum | 4 +- integration-tests/go.mod | 2 +- integration-tests/go.sum | 5 +- 34 files changed, 203 insertions(+), 220 deletions(-) diff --git a/common/client/multi_node.go b/common/client/multi_node.go index dfd6585b642..7d55784e68f 100644 --- a/common/client/multi_node.go +++ b/common/client/multi_node.go @@ -86,7 +86,7 @@ type multiNode[ sendonlys []SendOnlyNode[CHAIN_ID, RPC_CLIENT] chainID CHAIN_ID chainType config.ChainType - lggr logger.Logger + lggr logger.SugaredLogger selectionMode string noNewHeadsThreshold time.Duration nodeSelector NodeSelector[CHAIN_ID, HEAD, RPC_CLIENT] @@ -118,7 +118,7 @@ func NewMultiNode[ HEAD types.Head[BLOCK_HASH], RPC_CLIENT RPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD], ]( - l logger.Logger, + lggr logger.Logger, selectionMode string, leaseDuration time.Duration, noNewHeadsThreshold time.Duration, @@ -131,9 +131,6 @@ func NewMultiNode[ ) MultiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT] { nodeSelector := newNodeSelector(selectionMode, nodes) - lggr := logger.Named(l, "MultiNode") - lggr = logger.With(lggr, "chainID", chainID.String()) - // Prometheus' default interval is 15s, set this to under 7.5s to avoid // aliasing (see: https://en.wikipedia.org/wiki/Nyquist_frequency) const reportInterval = 6500 * time.Millisecond @@ -142,7 +139,7 @@ func NewMultiNode[ sendonlys: sendonlys, chainID: chainID, chainType: chainType, - lggr: lggr, + lggr: logger.Sugared(lggr).Named("MultiNode").With("chainID", chainID.String()), selectionMode: selectionMode, noNewHeadsThreshold: noNewHeadsThreshold, nodeSelector: nodeSelector, @@ -249,7 +246,7 @@ func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OP c.activeNode = c.nodeSelector.Select() if c.activeNode == nil { - logger.Criticalw(c.lggr, "No live RPC nodes available", "NodeSelectionMode", c.nodeSelector.Name()) + c.lggr.Criticalw("No live RPC nodes available", "NodeSelectionMode", c.nodeSelector.Name()) errmsg := fmt.Errorf("no live nodes available for chain %s", c.chainID.String()) c.SvcErrBuffer.Append(errmsg) err = ErroringNodeError @@ -351,10 +348,10 @@ func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OP } live := total - dead - logger.Tracew(c.lggr, fmt.Sprintf("MultiNode state: %d/%d nodes are alive", live, total), "nodeStates", nodeStates) + c.lggr.Tracew(fmt.Sprintf("MultiNode state: %d/%d nodes are alive", live, total), "nodeStates", nodeStates) if total == dead { rerr := fmt.Errorf("no primary nodes available: 0/%d nodes are alive", total) - logger.Criticalw(c.lggr, rerr.Error(), "nodeStates", nodeStates) + c.lggr.Criticalw(rerr.Error(), "nodeStates", nodeStates) c.SvcErrBuffer.Append(rerr) } else if dead > 0 { c.lggr.Errorw(fmt.Sprintf("At least one primary node is dead: %d/%d nodes are alive", live, total), "nodeStates", nodeStates) @@ -405,7 +402,7 @@ func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OP if err != nil { c.lggr.Debugw("Secondary node BatchCallContext failed", "err", err) } else { - logger.Trace(c.lggr, "Secondary node BatchCallContext success") + c.lggr.Trace("Secondary node BatchCallContext success") } }(n) } diff --git a/common/client/node_lifecycle.go b/common/client/node_lifecycle.go index eda137d5100..af8f27d498d 100644 --- a/common/client/node_lifecycle.go +++ b/common/client/node_lifecycle.go @@ -93,9 +93,8 @@ func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() { pollFailureThreshold := n.nodePoolCfg.PollFailureThreshold() pollInterval := n.nodePoolCfg.PollInterval() - lggr := logger.Named(n.lfcLog, "Alive") - lggr = logger.With(lggr, "noNewHeadsTimeoutThreshold", noNewHeadsTimeoutThreshold, "pollInterval", pollInterval, "pollFailureThreshold", pollFailureThreshold) - logger.Tracew(lggr, "Alive loop starting", "nodeState", n.State()) + lggr := logger.Sugared(n.lfcLog).Named("Alive").With("noNewHeadsTimeoutThreshold", noNewHeadsTimeoutThreshold, "pollInterval", pollInterval, "pollFailureThreshold", pollFailureThreshold) + lggr.Tracew("Alive loop starting", "nodeState", n.State()) headsC := make(chan HEAD) sub, err := n.rpc.Subscribe(n.nodeCtx, headsC, rpcSubscriptionMethodNewHeads) @@ -146,7 +145,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() { case <-pollCh: var version string promPoolRPCNodePolls.WithLabelValues(n.chainID.String(), n.name).Inc() - logger.Tracew(lggr, "Polling for version", "nodeState", n.State(), "pollFailures", pollFailures) + lggr.Tracew("Polling for version", "nodeState", n.State(), "pollFailures", pollFailures) ctx, cancel := context.WithTimeout(n.nodeCtx, pollInterval) version, err := n.RPC().ClientVersion(ctx) cancel() @@ -166,7 +165,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() { lggr.Errorw(fmt.Sprintf("RPC endpoint failed to respond to %d consecutive polls", pollFailures), "pollFailures", pollFailures, "nodeState", n.State()) if n.nLiveNodes != nil { if l, _, _ := n.nLiveNodes(); l < 2 { - logger.Criticalf(lggr, "RPC endpoint failed to respond to polls; %s %s", msgCannotDisable, msgDegradedState) + lggr.Criticalf("RPC endpoint failed to respond to polls; %s %s", msgCannotDisable, msgDegradedState) continue } } @@ -178,7 +177,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() { // note: there must be another live node for us to be out of sync lggr.Errorw("RPC endpoint has fallen behind", "blockNumber", num, "totalDifficulty", td, "nodeState", n.State()) if liveNodes < 2 { - logger.Criticalf(lggr, "RPC endpoint has fallen behind; %s %s", msgCannotDisable, msgDegradedState) + lggr.Criticalf("RPC endpoint has fallen behind; %s %s", msgCannotDisable, msgDegradedState) continue } n.declareOutOfSync(n.isOutOfSync) @@ -191,13 +190,13 @@ func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() { return } promPoolRPCNodeNumSeenBlocks.WithLabelValues(n.chainID.String(), n.name).Inc() - logger.Tracew(lggr, "Got head", "head", bh) + lggr.Tracew("Got head", "head", bh) if bh.BlockNumber() > highestReceivedBlockNumber { promPoolRPCNodeHighestSeenBlock.WithLabelValues(n.chainID.String(), n.name).Set(float64(bh.BlockNumber())) - logger.Tracew(lggr, "Got higher block number, resetting timer", "latestReceivedBlockNumber", highestReceivedBlockNumber, "blockNumber", bh.BlockNumber(), "nodeState", n.State()) + lggr.Tracew("Got higher block number, resetting timer", "latestReceivedBlockNumber", highestReceivedBlockNumber, "blockNumber", bh.BlockNumber(), "nodeState", n.State()) highestReceivedBlockNumber = bh.BlockNumber() } else { - logger.Tracew(lggr, "Ignoring previously seen block number", "latestReceivedBlockNumber", highestReceivedBlockNumber, "blockNumber", bh.BlockNumber(), "nodeState", n.State()) + lggr.Tracew("Ignoring previously seen block number", "latestReceivedBlockNumber", highestReceivedBlockNumber, "blockNumber", bh.BlockNumber(), "nodeState", n.State()) } if outOfSyncT != nil { outOfSyncT.Reset(noNewHeadsTimeoutThreshold) @@ -213,7 +212,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() { lggr.Errorw(fmt.Sprintf("RPC endpoint detected out of sync; no new heads received for %s (last head received was %v)", noNewHeadsTimeoutThreshold, highestReceivedBlockNumber), "nodeState", n.State(), "latestReceivedBlockNumber", highestReceivedBlockNumber, "noNewHeadsTimeoutThreshold", noNewHeadsTimeoutThreshold) if n.nLiveNodes != nil { if l, _, _ := n.nLiveNodes(); l < 2 { - logger.Criticalf(lggr, "RPC endpoint detected out of sync; %s %s", msgCannotDisable, msgDegradedState) + lggr.Criticalf("RPC endpoint detected out of sync; %s %s", msgCannotDisable, msgDegradedState) // We don't necessarily want to wait the full timeout to check again, we should // check regularly and log noisily in this state outOfSyncT.Reset(zombieNodeCheckInterval(n.noNewHeadsThreshold)) @@ -279,7 +278,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) outOfSyncLoop(isOutOfSync func(num int64, td outOfSyncAt := time.Now() - lggr := logger.Named(n.lfcLog, "OutOfSync") + lggr := logger.Sugared(logger.Named(n.lfcLog, "OutOfSync")) lggr.Debugw("Trying to revive out-of-sync RPC node", "nodeState", n.State()) // Need to redial since out-of-sync nodes are automatically disconnected @@ -296,7 +295,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) outOfSyncLoop(isOutOfSync func(num int64, td return } - logger.Tracew(lggr, "Successfully subscribed to heads feed on out-of-sync RPC node", "nodeState", n.State()) + lggr.Tracew("Successfully subscribed to heads feed on out-of-sync RPC node", "nodeState", n.State()) ch := make(chan HEAD) sub, err := n.rpc.Subscribe(n.nodeCtx, ch, rpcSubscriptionMethodNewHeads) @@ -328,7 +327,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) outOfSyncLoop(isOutOfSync func(num int64, td case <-time.After(zombieNodeCheckInterval(n.noNewHeadsThreshold)): if n.nLiveNodes != nil { if l, _, _ := n.nLiveNodes(); l < 1 { - logger.Critical(lggr, "RPC endpoint is still out of sync, but there are no other available nodes. This RPC node will be forcibly moved back into the live pool in a degraded state") + lggr.Critical("RPC endpoint is still out of sync, but there are no other available nodes. This RPC node will be forcibly moved back into the live pool in a degraded state") n.declareInSync() return } @@ -358,7 +357,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) unreachableLoop() { unreachableAt := time.Now() - lggr := logger.Named(n.lfcLog, "Unreachable") + lggr := logger.Sugared(logger.Named(n.lfcLog, "Unreachable")) lggr.Debugw("Trying to revive unreachable RPC node", "nodeState", n.State()) dialRetryBackoff := iutils.NewRedialBackoff() @@ -368,7 +367,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) unreachableLoop() { case <-n.nodeCtx.Done(): return case <-time.After(dialRetryBackoff.Duration()): - logger.Tracew(lggr, "Trying to re-dial RPC node", "nodeState", n.State()) + lggr.Tracew("Trying to re-dial RPC node", "nodeState", n.State()) err := n.rpc.Dial(n.nodeCtx) if err != nil { diff --git a/common/headtracker/head_tracker.go b/common/headtracker/head_tracker.go index 373aa5a958f..4cc152fb9fe 100644 --- a/common/headtracker/head_tracker.go +++ b/common/headtracker/head_tracker.go @@ -40,7 +40,7 @@ type HeadTracker[ BLOCK_HASH types.Hashable, ] struct { services.StateMachine - log logger.Logger + log logger.SugaredLogger headBroadcaster types.HeadBroadcaster[HTH, BLOCK_HASH] headSaver types.HeadSaver[HTH, BLOCK_HASH] mailMon *mailbox.Monitor @@ -81,7 +81,7 @@ func NewHeadTracker[ chainID: client.ConfiguredChainID(), config: config, htConfig: htConfig, - log: lggr, + log: logger.Sugared(lggr), backfillMB: mailbox.NewSingle[HTH](), broadcastMB: mailbox.New[HTH](HeadsBufferSize), chStop: chStop, @@ -227,7 +227,7 @@ func (ht *HeadTracker[HTH, S, ID, BLOCK_HASH]) handleNewHead(ctx context.Context prevUnFinalizedHead := prevHead.BlockNumber() - int64(ht.config.FinalityDepth()) if head.BlockNumber() < prevUnFinalizedHead { promOldHead.WithLabelValues(ht.chainID.String()).Inc() - logger.Criticalf(ht.log, "Got very old block with number %d (highest seen was %d). This is a problem and either means a very deep re-org occurred, one of the RPC nodes has gotten far out of sync, or the chain went backwards in block numbers. This node may not function correctly without manual intervention.", head.BlockNumber(), prevHead.BlockNumber()) + ht.log.Criticalf("Got very old block with number %d (highest seen was %d). This is a problem and either means a very deep re-org occurred, one of the RPC nodes has gotten far out of sync, or the chain went backwards in block numbers. This node may not function correctly without manual intervention.", head.BlockNumber(), prevHead.BlockNumber()) ht.SvcErrBuffer.Append(errors.New("got very old block")) } } @@ -310,7 +310,7 @@ func (ht *HeadTracker[HTH, S, ID, BLOCK_HASH]) backfill(ctx context.Context, hea } mark := time.Now() fetched := 0 - l := logger.With(ht.log, "blockNumber", headBlockNumber, + l := ht.log.With("blockNumber", headBlockNumber, "n", headBlockNumber-baseHeight, "fromBlockHeight", baseHeight, "toBlockHeight", headBlockNumber-1) diff --git a/common/txmgr/broadcaster.go b/common/txmgr/broadcaster.go index dba2b976c33..a62b3df8699 100644 --- a/common/txmgr/broadcaster.go +++ b/common/txmgr/broadcaster.go @@ -82,7 +82,7 @@ type TransmitChecker[ // is returned. Errors should only be returned if the checker can confirm that a transaction // should not be sent, other errors (for example connection or other unexpected errors) should // be logged and swallowed. - Check(ctx context.Context, l logger.Logger, tx txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], a txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) error + Check(ctx context.Context, l logger.SugaredLogger, tx txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], a txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) error } // Broadcaster monitors txes for transactions that need to @@ -108,7 +108,7 @@ type Broadcaster[ FEE feetypes.Fee, ] struct { services.StateMachine - lggr logger.Logger + lggr logger.SugaredLogger txStore txmgrtypes.TransactionStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, SEQ, FEE] client txmgrtypes.TransactionClient[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] txmgrtypes.TxAttemptBuilder[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] @@ -172,7 +172,7 @@ func NewBroadcaster[ ) *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] { lggr = logger.Named(lggr, "Broadcaster") b := &Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]{ - lggr: lggr, + lggr: logger.Sugared(lggr), txStore: txStore, client: client, TxAttemptBuilder: txAttemptBuilder, @@ -311,7 +311,7 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) getS if err == nil { return seq, nil } - logger.Criticalw(eb.lggr, "failed to retrieve next sequence from on-chain for address: ", "address", address.String()) + eb.lggr.Criticalw("failed to retrieve next sequence from on-chain for address: ", "address", address.String()) return seq, err } @@ -399,7 +399,7 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) Sync localSequence, err := eb.GetNextSequence(ctx, addr) // Address not found in map so skip sync if err != nil { - logger.Criticalw(eb.lggr, "Failed to retrieve local next sequence for address", "address", addr.String(), "err", err) + eb.lggr.Criticalw("Failed to retrieve local next sequence for address", "address", addr.String(), "err", err) return } @@ -414,7 +414,7 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) Sync newNextSequence, err := eb.sequenceSyncer.Sync(ctx, addr, localSequence) if err != nil { if attempt > 5 { - logger.Criticalw(eb.lggr, "Failed to sync with on-chain sequence", "address", addr.String(), "attempt", attempt, "err", err) + eb.lggr.Criticalw("Failed to sync with on-chain sequence", "address", addr.String(), "attempt", attempt, "err", err) eb.SvcErrBuffer.Append(err) } else { eb.lggr.Warnw("Failed to sync with on-chain sequence", "address", addr.String(), "attempt", attempt, "err", err) @@ -537,7 +537,7 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) hand return fmt.Errorf("building transmit checker: %w", err), false } - lgr := etx.GetLogger(logger.With(eb.lggr, "fee", attempt.TxFee)) + lgr := etx.GetLogger(eb.lggr.With("fee", attempt.TxFee)) // If the transmit check does not complete within the timeout, the transaction will be sent // anyway. @@ -647,14 +647,14 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) hand // If there is only one RPC node, or all RPC nodes have the same // configured cap, this transaction will get stuck and keep repeating // forever until the issue is resolved. - logger.Criticalw(lgr, `RPC node rejected this tx as outside Fee Cap`) + lgr.Criticalw(`RPC node rejected this tx as outside Fee Cap`) fallthrough default: // Every error that doesn't fall under one of the above categories will be treated as Unknown. fallthrough case client.Unknown: eb.SvcErrBuffer.Append(err) - logger.Criticalw(lgr, `Unknown error occurred while handling tx queue in ProcessUnstartedTxs. This chain/RPC client may not be supported. `+ + lgr.Criticalw(`Unknown error occurred while handling tx queue in ProcessUnstartedTxs. This chain/RPC client may not be supported. `+ `Urgent resolution required, Chainlink is currently operating in a degraded state and may miss transactions`, "err", err, "etx", etx, "attempt", attempt) nextSequence, e := eb.client.PendingSequenceAt(ctx, etx.FromAddress) if e != nil { diff --git a/common/txmgr/confirmer.go b/common/txmgr/confirmer.go index aabdf45ae32..fbc6ea8a108 100644 --- a/common/txmgr/confirmer.go +++ b/common/txmgr/confirmer.go @@ -118,7 +118,7 @@ type Confirmer[ ] struct { services.StateMachine txStore txmgrtypes.TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] - lggr logger.Logger + lggr logger.SugaredLogger client txmgrtypes.TxmClient[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE] txmgrtypes.TxAttemptBuilder[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] resumeCallback ResumeCallback @@ -166,7 +166,7 @@ func NewConfirmer[ lggr = logger.Named(lggr, "Confirmer") return &Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]{ txStore: txStore, - lggr: lggr, + lggr: logger.Sugared(lggr), client: client, TxAttemptBuilder: txAttemptBuilder, resumeCallback: nil, @@ -520,8 +520,7 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) bat } } - lggr := logger.Named(ec.lggr, "BatchFetchReceipts") - lggr = logger.With(lggr, "blockNum", blockNum) + lggr := ec.lggr.Named("BatchFetchReceipts").With("blockNum", blockNum) txReceipts, txErrs, err := ec.client.BatchGetReceipts(ctx, attempts) if err != nil { @@ -533,9 +532,9 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) bat receipt := txReceipts[i] err := txErrs[i] - l := logger.Sugared(logger.With(attempt.Tx.GetLogger(lggr), "txHash", attempt.Hash.String(), "txAttemptID", attempt.ID, + l := attempt.Tx.GetLogger(lggr).With("txHash", attempt.Hash.String(), "txAttemptID", attempt.ID, "txID", attempt.TxID, "err", err, "sequence", attempt.Tx.Sequence, - )) + ) if err != nil { l.Error("FetchReceipt failed") @@ -554,7 +553,7 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) bat continue } - l = logger.Sugared(logger.With(l, "blockHash", receipt.GetBlockHash().String(), "status", receipt.GetStatus(), "transactionIndex", receipt.GetTransactionIndex())) + l = l.With("blockHash", receipt.GetBlockHash().String(), "status", receipt.GetStatus(), "transactionIndex", receipt.GetTransactionIndex()) if receipt.IsUnmined() { l.Debug("Got receipt for transaction but it's still in the mempool and not included in a block yet") @@ -811,7 +810,7 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) bum return bumpedAttempt, fmt.Errorf("error bumping gas: %w", err) } -func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) handleInProgressAttempt(ctx context.Context, lggr logger.Logger, etx txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], attempt txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], blockHeight int64) error { +func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) handleInProgressAttempt(ctx context.Context, lggr logger.SugaredLogger, etx txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], attempt txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], blockHeight int64) error { if attempt.State != txmgrtypes.TxAttemptInProgress { return fmt.Errorf("invariant violation: expected tx_attempt %v to be in_progress, it was %s", attempt.ID, attempt.State) @@ -833,12 +832,12 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) han } if len(etx.TxAttempts) == 0 { err := errors.New("expected to find at least 1 attempt") - logger.Sugared(ec.lggr).AssumptionViolationw(err.Error(), "err", err, "attempt", attempt) + ec.lggr.AssumptionViolationw(err.Error(), "err", err, "attempt", attempt) return err } if attempt.ID != etx.TxAttempts[0].ID { err := errors.New("expected highest priced attempt to be the current in_progress attempt") - logger.Sugared(ec.lggr).AssumptionViolationw(err.Error(), "err", err, "attempt", attempt, "txAttempts", etx.TxAttempts) + ec.lggr.AssumptionViolationw(err.Error(), "err", err, "attempt", attempt, "txAttempts", etx.TxAttempts) return err } replacementAttempt, err := ec.bumpGas(ctx, etx, etx.TxAttempts) @@ -846,7 +845,7 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) han return fmt.Errorf("could not bump gas for terminally underpriced transaction: %w", err) } promNumGasBumps.WithLabelValues(ec.chainID.String()).Inc() - logger.With(lggr, + lggr.With( "sendError", sendError, "maxGasPriceConfig", ec.feeConfig.MaxFeePrice(), "previousAttempt", attempt, @@ -867,7 +866,7 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) han // Should NEVER be fatal this is an invariant violation. The // Broadcaster can never create a TxAttempt that will // fatally error. - logger.Criticalw(lggr, "Invariant violation: fatal error while re-attempting transaction", + lggr.Criticalw("Invariant violation: fatal error while re-attempting transaction", "err", sendError, "fee", attempt.TxFee, "feeLimit", etx.FeeLimit, diff --git a/common/txmgr/resender.go b/common/txmgr/resender.go index 74cf3d1389c..dded59f55d4 100644 --- a/common/txmgr/resender.go +++ b/common/txmgr/resender.go @@ -53,7 +53,7 @@ type Resender[ interval time.Duration config txmgrtypes.ResenderChainConfig txConfig txmgrtypes.ResenderTransactionsConfig - logger logger.Logger + logger logger.SugaredLogger lastAlertTimestamps map[string]time.Time ctx context.Context @@ -93,7 +93,7 @@ func NewResender[ pollInterval, config, txConfig, - logger.Named(lggr, "Resender"), + logger.Sugared(logger.Named(lggr, "Resender")), make(map[string]time.Time), ctx, cancel, diff --git a/common/txmgr/txmgr.go b/common/txmgr/txmgr.go index e43a16b29ef..36a6a1304ae 100644 --- a/common/txmgr/txmgr.go +++ b/common/txmgr/txmgr.go @@ -82,7 +82,7 @@ type Txm[ FEE feetypes.Fee, ] struct { services.StateMachine - logger logger.Logger + logger logger.SugaredLogger txStore txmgrtypes.TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] config txmgrtypes.TransactionManagerChainConfig txConfig txmgrtypes.TransactionManagerTransactionsConfig @@ -142,7 +142,7 @@ func NewTxm[ tracker *Tracker[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE], ) *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { b := Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]{ - logger: lggr, + logger: logger.Sugared(lggr), txStore: txStore, config: cfg, txConfig: txCfg, @@ -349,7 +349,7 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) runLoop() select { case <-time.After(backoff.Duration()): if err := b.broadcaster.startInternal(ctx); err != nil { - logger.Criticalw(b.logger, "Failed to start Broadcaster", "err", err) + b.logger.Criticalw("Failed to start Broadcaster", "err", err) b.SvcErrBuffer.Append(err) continue } @@ -368,7 +368,7 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) runLoop() select { case <-time.After(backoff.Duration()): if err := b.confirmer.startInternal(); err != nil { - logger.Criticalw(b.logger, "Failed to start Confirmer", "err", err) + b.logger.Criticalw("Failed to start Confirmer", "err", err) b.SvcErrBuffer.Append(err) continue } @@ -433,7 +433,7 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) runLoop() } enabledAddresses, err := b.keyStore.EnabledAddressesForChain(b.chainID) if err != nil { - logger.Criticalf(b.logger, "Failed to reload key states after key change") + b.logger.Critical("Failed to reload key states after key change") b.SvcErrBuffer.Append(err) continue } diff --git a/common/txmgr/types/client.go b/common/txmgr/types/client.go index b44c41e4176..0db50e97ad3 100644 --- a/common/txmgr/types/client.go +++ b/common/txmgr/types/client.go @@ -47,7 +47,7 @@ type TransactionClient[ ctx context.Context, attempts []TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], bathSize int, - lggr logger.Logger, + lggr logger.SugaredLogger, ) ( txCodes []client.SendTxReturnCode, txErrs []error, @@ -58,7 +58,7 @@ type TransactionClient[ ctx context.Context, tx Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], attempt TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], - lggr logger.Logger, + lggr logger.SugaredLogger, ) (client.SendTxReturnCode, error) SendEmptyTransaction( ctx context.Context, diff --git a/common/txmgr/types/tx.go b/common/txmgr/types/tx.go index caac763fc0f..0f5d651ae29 100644 --- a/common/txmgr/types/tx.go +++ b/common/txmgr/types/tx.go @@ -254,7 +254,7 @@ func (e *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) GetMeta() (*TxMeta[A } // GetLogger returns a new logger with metadata fields. -func (e *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) GetLogger(lgr logger.Logger) logger.Logger { +func (e *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) GetLogger(lgr logger.Logger) logger.SugaredLogger { lgr = logger.With(lgr, "txID", e.ID, "sequence", e.Sequence, @@ -265,7 +265,7 @@ func (e *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) GetLogger(lgr logger meta, err := e.GetMeta() if err != nil { lgr.Errorw("failed to get meta of the transaction", "err", err) - return lgr + return logger.Sugared(lgr) } if meta != nil { @@ -315,7 +315,7 @@ func (e *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) GetLogger(lgr logger } } - return lgr + return logger.Sugared(lgr) } // GetChecker returns an Tx's transmit checker spec in struct form, unmarshalling it from JSON diff --git a/core/chains/evm/client/chain_client.go b/core/chains/evm/client/chain_client.go index 3efc5645e22..255d802720a 100644 --- a/core/chains/evm/client/chain_client.go +++ b/core/chains/evm/client/chain_client.go @@ -37,11 +37,11 @@ type chainClient struct { *evmtypes.Head, RPCCLient, ] - logger logger.Logger + logger logger.SugaredLogger } func NewChainClient( - logger logger.Logger, + lggr logger.Logger, selectionMode string, leaseDuration time.Duration, noNewHeadsThreshold time.Duration, @@ -64,7 +64,7 @@ func NewChainClient( *evmtypes.Head, RPCCLient, ]( - logger, + lggr, selectionMode, leaseDuration, noNewHeadsThreshold, @@ -77,7 +77,7 @@ func NewChainClient( ) return &chainClient{ multiNode: multiNode, - logger: logger, + logger: logger.Sugared(lggr), } } diff --git a/core/chains/evm/client/client.go b/core/chains/evm/client/client.go index b85331a62a1..f32ec011445 100644 --- a/core/chains/evm/client/client.go +++ b/core/chains/evm/client/client.go @@ -102,7 +102,7 @@ func ContextWithDefaultTimeout() (ctx context.Context, cancel context.CancelFunc // client represents an abstract client that manages connections to // multiple nodes for a single chain id type client struct { - logger logger.Logger + logger logger.SugaredLogger pool *Pool } @@ -113,10 +113,10 @@ var _ htrktypes.Client[*evmtypes.Head, ethereum.Subscription, *big.Int, common.H // Currently only supports one primary // // Deprecated: use [NewChainClient] -func NewClientWithNodes(logger logger.Logger, selectionMode string, leaseDuration time.Duration, noNewHeadsThreshold time.Duration, primaryNodes []Node, sendOnlyNodes []SendOnlyNode, chainID *big.Int, chainType config.ChainType) (*client, error) { - pool := NewPool(logger, selectionMode, leaseDuration, noNewHeadsThreshold, primaryNodes, sendOnlyNodes, chainID, chainType) +func NewClientWithNodes(lggr logger.Logger, selectionMode string, leaseDuration time.Duration, noNewHeadsThreshold time.Duration, primaryNodes []Node, sendOnlyNodes []SendOnlyNode, chainID *big.Int, chainType config.ChainType) (*client, error) { + pool := NewPool(lggr, selectionMode, leaseDuration, noNewHeadsThreshold, primaryNodes, sendOnlyNodes, chainID, chainType) return &client{ - logger: logger, + logger: logger.Sugared(lggr), pool: pool, }, nil } diff --git a/core/chains/evm/client/errors.go b/core/chains/evm/client/errors.go index 143a5f8806f..66cc30f74b4 100644 --- a/core/chains/evm/client/errors.go +++ b/core/chains/evm/client/errors.go @@ -413,13 +413,13 @@ func ExtractRPCError(baseErr error) (*JsonError, error) { return &jErr, nil } -func ClassifySendError(err error, lggr logger.Logger, tx *types.Transaction, fromAddress common.Address, isL2 bool) (commonclient.SendTxReturnCode, error) { +func ClassifySendError(err error, lggr logger.SugaredLogger, tx *types.Transaction, fromAddress common.Address, isL2 bool) (commonclient.SendTxReturnCode, error) { sendError := NewSendError(err) if sendError == nil { return commonclient.Successful, err } if sendError.Fatal() { - logger.Criticalw(lggr, "Fatal error sending transaction", "err", sendError, "etx", tx) + lggr.Criticalw("Fatal error sending transaction", "err", sendError, "etx", tx) // Attempt is thrown away in this case; we don't need it since it never got accepted by a node return commonclient.Fatal, err } @@ -462,7 +462,7 @@ func ClassifySendError(err error, lggr logger.Logger, tx *types.Transaction, fro return commonclient.Retryable, err } if sendError.IsInsufficientEth() { - logger.Criticalw(lggr, fmt.Sprintf("Tx %x with type 0x%d was rejected due to insufficient eth: %s\n"+ + lggr.Criticalw(fmt.Sprintf("Tx %x with type 0x%d was rejected due to insufficient eth: %s\n"+ "ACTION REQUIRED: Chainlink wallet with address 0x%x is OUT OF FUNDS", tx.Hash(), tx.Type(), sendError.Error(), fromAddress, ), "err", sendError) @@ -472,7 +472,7 @@ func ClassifySendError(err error, lggr logger.Logger, tx *types.Transaction, fro return commonclient.Retryable, errors.Wrapf(sendError, "timeout while sending transaction %s", tx.Hash().Hex()) } if sendError.IsTxFeeExceedsCap() { - logger.Criticalw(lggr, fmt.Sprintf("Sending transaction failed: %s", label.RPCTxFeeCapConfiguredIncorrectlyWarning), + lggr.Criticalw(fmt.Sprintf("Sending transaction failed: %s", label.RPCTxFeeCapConfiguredIncorrectlyWarning), "etx", tx, "err", sendError, "id", "RPCTxFeeCapExceeded", diff --git a/core/chains/evm/client/helpers_test.go b/core/chains/evm/client/helpers_test.go index 27b335534da..c2f60e13f55 100644 --- a/core/chains/evm/client/helpers_test.go +++ b/core/chains/evm/client/helpers_test.go @@ -42,7 +42,7 @@ func NewClientWithTestNode(t *testing.T, nodePoolCfg config.NodePool, noNewHeads return nil, errors.Errorf("ethereum url scheme must be websocket: %s", parsed.String()) } - lggr := logger.Test(t) + lggr := logger.Sugared(logger.Test(t)) n := NewNode(nodePoolCfg, noNewHeadsThreshold, lggr, *parsed, rpcHTTPURL, "eth-primary-0", id, chainID, 1) n.(*node).setLatestReceived(0, big.NewInt(0)) primaries := []Node{n} diff --git a/core/chains/evm/client/node.go b/core/chains/evm/client/node.go index a2c8b807ba2..a27321535ed 100644 --- a/core/chains/evm/client/node.go +++ b/core/chains/evm/client/node.go @@ -137,7 +137,7 @@ type rawclient struct { type node struct { services.StateMachine lfcLog logger.Logger - rpcLog logger.Logger + rpcLog logger.SugaredLogger name string id int32 chainID *big.Int @@ -206,7 +206,7 @@ func NewNode(nodeCfg config.NodePool, noNewHeadsThreshold time.Duration, lggr lo "mode", n.getNodeMode(), ) n.lfcLog = logger.Named(lggr, "Lifecycle") - n.rpcLog = logger.Named(lggr, "RPC") + n.rpcLog = logger.Sugared(lggr).Named("RPC") n.stateLatestBlockNumber = -1 return n @@ -453,7 +453,7 @@ func (n *node) CallContext(ctx context.Context, result interface{}, method strin return err } defer cancel() - lggr := logger.With(n.newRqLggr(), + lggr := n.newRqLggr().With( "method", method, "args", args, ) @@ -478,9 +478,9 @@ func (n *node) BatchCallContext(ctx context.Context, b []rpc.BatchElem) error { return err } defer cancel() - lggr := logger.With(n.newRqLggr(), "nBatchElems", len(b), "batchElems", b) + lggr := n.newRqLggr().With("nBatchElems", len(b), "batchElems", b) - logger.Trace(lggr, "RPC call: evmclient.Client#BatchCallContext") + lggr.Trace("RPC call: evmclient.Client#BatchCallContext") start := time.Now() if http != nil { err = n.wrapHTTP(http.rpc.BatchCallContext(ctx, b)) @@ -500,7 +500,7 @@ func (n *node) EthSubscribe(ctx context.Context, channel chan<- *evmtypes.Head, return nil, err } defer cancel() - lggr := logger.With(n.newRqLggr(), "args", args) + lggr := n.newRqLggr().With("args", args) lggr.Debug("RPC call: evmclient.Client#EthSubscribe") start := time.Now() @@ -523,7 +523,7 @@ func (n *node) TransactionReceipt(ctx context.Context, txHash common.Hash) (rece return nil, err } defer cancel() - lggr := logger.With(n.newRqLggr(), "txHash", txHash) + lggr := n.newRqLggr().With("txHash", txHash) lggr.Debug("RPC call: evmclient.Client#TransactionReceipt") @@ -550,7 +550,7 @@ func (n *node) TransactionByHash(ctx context.Context, txHash common.Hash) (tx *t return nil, err } defer cancel() - lggr := logger.With(n.newRqLggr(), "txHash", txHash) + lggr := n.newRqLggr().With("txHash", txHash) lggr.Debug("RPC call: evmclient.Client#TransactionByHash") @@ -577,7 +577,7 @@ func (n *node) HeaderByNumber(ctx context.Context, number *big.Int) (header *typ return nil, err } defer cancel() - lggr := logger.With(n.newRqLggr(), "number", number) + lggr := n.newRqLggr().With("number", number) lggr.Debug("RPC call: evmclient.Client#HeaderByNumber") start := time.Now() @@ -601,7 +601,7 @@ func (n *node) HeaderByHash(ctx context.Context, hash common.Hash) (header *type return nil, err } defer cancel() - lggr := logger.With(n.newRqLggr(), "hash", hash) + lggr := n.newRqLggr().With("hash", hash) lggr.Debug("RPC call: evmclient.Client#HeaderByHash") start := time.Now() @@ -627,7 +627,7 @@ func (n *node) SendTransaction(ctx context.Context, tx *types.Transaction) error return err } defer cancel() - lggr := logger.With(n.newRqLggr(), "tx", tx) + lggr := n.newRqLggr().With("tx", tx) lggr.Debug("RPC call: evmclient.Client#SendTransaction") start := time.Now() @@ -650,7 +650,7 @@ func (n *node) PendingNonceAt(ctx context.Context, account common.Address) (nonc return 0, err } defer cancel() - lggr := logger.With(n.newRqLggr(), "account", account) + lggr := n.newRqLggr().With("account", account) lggr.Debug("RPC call: evmclient.Client#PendingNonceAt") start := time.Now() @@ -679,7 +679,7 @@ func (n *node) NonceAt(ctx context.Context, account common.Address, blockNumber return 0, err } defer cancel() - lggr := logger.With(n.newRqLggr(), "account", account, "blockNumber", blockNumber) + lggr := n.newRqLggr().With("account", account, "blockNumber", blockNumber) lggr.Debug("RPC call: evmclient.Client#NonceAt") start := time.Now() @@ -705,7 +705,7 @@ func (n *node) PendingCodeAt(ctx context.Context, account common.Address) (code return nil, err } defer cancel() - lggr := logger.With(n.newRqLggr(), "account", account) + lggr := n.newRqLggr().With("account", account) lggr.Debug("RPC call: evmclient.Client#PendingCodeAt") start := time.Now() @@ -731,7 +731,7 @@ func (n *node) CodeAt(ctx context.Context, account common.Address, blockNumber * return nil, err } defer cancel() - lggr := logger.With(n.newRqLggr(), "account", account, "blockNumber", blockNumber) + lggr := n.newRqLggr().With("account", account, "blockNumber", blockNumber) lggr.Debug("RPC call: evmclient.Client#CodeAt") start := time.Now() @@ -757,7 +757,7 @@ func (n *node) EstimateGas(ctx context.Context, call ethereum.CallMsg) (gas uint return 0, err } defer cancel() - lggr := logger.With(n.newRqLggr(), "call", call) + lggr := n.newRqLggr().With("call", call) lggr.Debug("RPC call: evmclient.Client#EstimateGas") start := time.Now() @@ -809,7 +809,7 @@ func (n *node) CallContract(ctx context.Context, msg ethereum.CallMsg, blockNumb return nil, err } defer cancel() - lggr := logger.With(n.newRqLggr(), "callMsg", msg, "blockNumber", blockNumber) + lggr := n.newRqLggr().With("callMsg", msg, "blockNumber", blockNumber) lggr.Debug("RPC call: evmclient.Client#CallContract") start := time.Now() @@ -836,7 +836,7 @@ func (n *node) BlockByNumber(ctx context.Context, number *big.Int) (b *types.Blo return nil, err } defer cancel() - lggr := logger.With(n.newRqLggr(), "number", number) + lggr := n.newRqLggr().With("number", number) lggr.Debug("RPC call: evmclient.Client#BlockByNumber") start := time.Now() @@ -862,7 +862,7 @@ func (n *node) BlockByHash(ctx context.Context, hash common.Hash) (b *types.Bloc return nil, err } defer cancel() - lggr := logger.With(n.newRqLggr(), "hash", hash) + lggr := n.newRqLggr().With("hash", hash) lggr.Debug("RPC call: evmclient.Client#BlockByHash") start := time.Now() @@ -914,7 +914,7 @@ func (n *node) BalanceAt(ctx context.Context, account common.Address, blockNumbe return nil, err } defer cancel() - lggr := logger.With(n.newRqLggr(), "account", account.Hex(), "blockNumber", blockNumber) + lggr := n.newRqLggr().With("account", account.Hex(), "blockNumber", blockNumber) lggr.Debug("RPC call: evmclient.Client#BalanceAt") start := time.Now() @@ -940,7 +940,7 @@ func (n *node) FilterLogs(ctx context.Context, q ethereum.FilterQuery) (l []type return nil, err } defer cancel() - lggr := logger.With(n.newRqLggr(), "q", q) + lggr := n.newRqLggr().With("q", q) lggr.Debug("RPC call: evmclient.Client#FilterLogs") start := time.Now() @@ -966,7 +966,7 @@ func (n *node) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, return nil, err } defer cancel() - lggr := logger.With(n.newRqLggr(), "q", q) + lggr := n.newRqLggr().With("q", q) lggr.Debug("RPC call: evmclient.Client#SubscribeFilterLogs") start := time.Now() @@ -1011,10 +1011,8 @@ func (n *node) SuggestGasTipCap(ctx context.Context) (tipCap *big.Int, err error func (n *node) ChainID() (chainID *big.Int) { return n.chainID } // newRqLggr generates a new logger with a unique request ID -func (n *node) newRqLggr() logger.Logger { - return logger.With(n.rpcLog, - "requestID", uuid.New(), - ) +func (n *node) newRqLggr() logger.SugaredLogger { + return n.rpcLog.With("requestID", uuid.New()) } func (n *node) logResult( @@ -1025,17 +1023,14 @@ func (n *node) logResult( callName string, results ...interface{}, ) { - lggr = logger.With(lggr, "duration", callDuration, "rpcDomain", rpcDomain, "callName", callName) + slggr := logger.Sugared(lggr).With("duration", callDuration, "rpcDomain", rpcDomain, "callName", callName) promEVMPoolRPCNodeCalls.WithLabelValues(n.chainID.String(), n.name).Inc() if err == nil { promEVMPoolRPCNodeCallsSuccess.WithLabelValues(n.chainID.String(), n.name).Inc() - logger.Tracew(lggr, - fmt.Sprintf("evmclient.Client#%s RPC call success", callName), - results..., - ) + slggr.Tracew(fmt.Sprintf("evmclient.Client#%s RPC call success", callName), results...) } else { promEVMPoolRPCNodeCallsFailed.WithLabelValues(n.chainID.String(), n.name).Inc() - lggr.Debugw( + slggr.Debugw( fmt.Sprintf("evmclient.Client#%s RPC call failure", callName), append(results, "err", err)..., ) @@ -1062,7 +1057,7 @@ func (n *node) wrapHTTP(err error) error { if err != nil { n.rpcLog.Debugw("Call failed", "err", err) } else { - logger.Trace(n.rpcLog, "Call succeeded") + n.rpcLog.Trace("Call succeeded") } return err } diff --git a/core/chains/evm/client/node_lifecycle.go b/core/chains/evm/client/node_lifecycle.go index 4e984de00f0..f2232a14935 100644 --- a/core/chains/evm/client/node_lifecycle.go +++ b/core/chains/evm/client/node_lifecycle.go @@ -92,9 +92,8 @@ func (n *node) aliveLoop() { pollFailureThreshold := n.nodePoolCfg.PollFailureThreshold() pollInterval := n.nodePoolCfg.PollInterval() - lggr := logger.Named(n.lfcLog, "Alive") - lggr = logger.With(lggr, "noNewHeadsTimeoutThreshold", noNewHeadsTimeoutThreshold, "pollInterval", pollInterval, "pollFailureThreshold", pollFailureThreshold) - logger.Tracew(lggr, "Alive loop starting", "nodeState", n.State()) + lggr := logger.Sugared(n.lfcLog).Named("Alive").With("noNewHeadsTimeoutThreshold", noNewHeadsTimeoutThreshold, "pollInterval", pollInterval, "pollFailureThreshold", pollFailureThreshold) + lggr.Tracew("Alive loop starting", "nodeState", n.State()) headsC := make(chan *evmtypes.Head) sub, err := n.EthSubscribe(n.nodeCtx, headsC, "newHeads") @@ -143,7 +142,7 @@ func (n *node) aliveLoop() { case <-pollCh: var version string promEVMPoolRPCNodePolls.WithLabelValues(n.chainID.String(), n.name).Inc() - logger.Tracew(lggr, "Polling for version", "nodeState", n.State(), "pollFailures", pollFailures) + lggr.Tracew("Polling for version", "nodeState", n.State(), "pollFailures", pollFailures) ctx, cancel := context.WithTimeout(n.nodeCtx, pollInterval) ctx, cancel2 := n.makeQueryCtx(ctx) err := n.CallContext(ctx, &version, "web3_clientVersion") @@ -165,7 +164,7 @@ func (n *node) aliveLoop() { lggr.Errorw(fmt.Sprintf("RPC endpoint failed to respond to %d consecutive polls", pollFailures), "pollFailures", pollFailures, "nodeState", n.State()) if n.nLiveNodes != nil { if l, _, _ := n.nLiveNodes(); l < 2 { - logger.Criticalf(lggr, "RPC endpoint failed to respond to polls; %s %s", msgCannotDisable, msgDegradedState) + lggr.Criticalf("RPC endpoint failed to respond to polls; %s %s", msgCannotDisable, msgDegradedState) continue } } @@ -177,7 +176,7 @@ func (n *node) aliveLoop() { // note: there must be another live node for us to be out of sync lggr.Errorw("RPC endpoint has fallen behind", "blockNumber", num, "totalDifficulty", td, "nodeState", n.State()) if liveNodes < 2 { - logger.Criticalf(lggr, "RPC endpoint has fallen behind; %s %s", msgCannotDisable, msgDegradedState) + lggr.Criticalf("RPC endpoint has fallen behind; %s %s", msgCannotDisable, msgDegradedState) continue } n.declareOutOfSync(n.isOutOfSync) @@ -190,13 +189,13 @@ func (n *node) aliveLoop() { return } promEVMPoolRPCNodeNumSeenBlocks.WithLabelValues(n.chainID.String(), n.name).Inc() - logger.Tracew(lggr, "Got head", "head", bh) + lggr.Tracew("Got head", "head", bh) if bh.Number > highestReceivedBlockNumber { promEVMPoolRPCNodeHighestSeenBlock.WithLabelValues(n.chainID.String(), n.name).Set(float64(bh.Number)) - logger.Tracew(lggr, "Got higher block number, resetting timer", "latestReceivedBlockNumber", highestReceivedBlockNumber, "blockNumber", bh.Number, "nodeState", n.State()) + lggr.Tracew("Got higher block number, resetting timer", "latestReceivedBlockNumber", highestReceivedBlockNumber, "blockNumber", bh.Number, "nodeState", n.State()) highestReceivedBlockNumber = bh.Number } else { - logger.Tracew(lggr, "Ignoring previously seen block number", "latestReceivedBlockNumber", highestReceivedBlockNumber, "blockNumber", bh.Number, "nodeState", n.State()) + lggr.Tracew("Ignoring previously seen block number", "latestReceivedBlockNumber", highestReceivedBlockNumber, "blockNumber", bh.Number, "nodeState", n.State()) } if outOfSyncT != nil { outOfSyncT.Reset(noNewHeadsTimeoutThreshold) @@ -212,7 +211,7 @@ func (n *node) aliveLoop() { lggr.Errorw(fmt.Sprintf("RPC endpoint detected out of sync; no new heads received for %s (last head received was %v)", noNewHeadsTimeoutThreshold, highestReceivedBlockNumber), "nodeState", n.State(), "latestReceivedBlockNumber", highestReceivedBlockNumber, "noNewHeadsTimeoutThreshold", noNewHeadsTimeoutThreshold) if n.nLiveNodes != nil { if l, _, _ := n.nLiveNodes(); l < 2 { - logger.Criticalf(lggr, "RPC endpoint detected out of sync; %s %s", msgCannotDisable, msgDegradedState) + lggr.Criticalf("RPC endpoint detected out of sync; %s %s", msgCannotDisable, msgDegradedState) // We don't necessarily want to wait the full timeout to check again, we should // check regularly and log noisily in this state outOfSyncT.Reset(zombieNodeCheckInterval(n.noNewHeadsThreshold)) @@ -278,7 +277,7 @@ func (n *node) outOfSyncLoop(isOutOfSync func(num int64, td *big.Int) bool) { outOfSyncAt := time.Now() - lggr := logger.Named(n.lfcLog, "OutOfSync") + lggr := logger.Sugared(logger.Named(n.lfcLog, "OutOfSync")) lggr.Debugw("Trying to revive out-of-sync RPC node", "nodeState", n.State()) // Need to redial since out-of-sync nodes are automatically disconnected @@ -295,7 +294,7 @@ func (n *node) outOfSyncLoop(isOutOfSync func(num int64, td *big.Int) bool) { return } - logger.Tracew(lggr, "Successfully subscribed to heads feed on out-of-sync RPC node", "nodeState", n.State()) + lggr.Tracew("Successfully subscribed to heads feed on out-of-sync RPC node", "nodeState", n.State()) ch := make(chan *evmtypes.Head) subCtx, cancel := n.makeQueryCtx(n.nodeCtx) @@ -330,7 +329,7 @@ func (n *node) outOfSyncLoop(isOutOfSync func(num int64, td *big.Int) bool) { case <-time.After(zombieNodeCheckInterval(n.noNewHeadsThreshold)): if n.nLiveNodes != nil { if l, _, _ := n.nLiveNodes(); l < 1 { - logger.Critical(lggr, "RPC endpoint is still out of sync, but there are no other available nodes. This RPC node will be forcibly moved back into the live pool in a degraded state") + lggr.Critical("RPC endpoint is still out of sync, but there are no other available nodes. This RPC node will be forcibly moved back into the live pool in a degraded state") n.declareInSync() return } @@ -360,7 +359,7 @@ func (n *node) unreachableLoop() { unreachableAt := time.Now() - lggr := logger.Named(n.lfcLog, "Unreachable") + lggr := logger.Sugared(logger.Named(n.lfcLog, "Unreachable")) lggr.Debugw("Trying to revive unreachable RPC node", "nodeState", n.State()) dialRetryBackoff := utils.NewRedialBackoff() @@ -370,7 +369,7 @@ func (n *node) unreachableLoop() { case <-n.nodeCtx.Done(): return case <-time.After(dialRetryBackoff.Duration()): - logger.Tracew(lggr, "Trying to re-dial RPC node", "nodeState", n.State()) + lggr.Tracew("Trying to re-dial RPC node", "nodeState", n.State()) err := n.dial(n.nodeCtx) if err != nil { diff --git a/core/chains/evm/client/pool.go b/core/chains/evm/client/pool.go index afe592533c3..b2d5a4847a5 100644 --- a/core/chains/evm/client/pool.go +++ b/core/chains/evm/client/pool.go @@ -68,7 +68,7 @@ type Pool struct { sendonlys []SendOnlyNode chainID *big.Int chainType config.ChainType - logger logger.Logger + logger logger.SugaredLogger selectionMode string noNewHeadsThreshold time.Duration nodeSelector NodeSelector @@ -113,7 +113,7 @@ func NewPool(lggr logger.Logger, selectionMode string, leaseDuration time.Durati sendonlys: sendonlys, chainID: chainID, chainType: chainType, - logger: lggr, + logger: logger.Sugared(lggr), selectionMode: selectionMode, noNewHeadsThreshold: noNewHeadsTreshold, nodeSelector: nodeSelector, @@ -272,10 +272,10 @@ func (p *Pool) report() { } live := total - dead - logger.Tracew(p.logger, fmt.Sprintf("Pool state: %d/%d nodes are alive", live, total), "nodeStates", nodeStates) + p.logger.Tracew(fmt.Sprintf("Pool state: %d/%d nodes are alive", live, total), "nodeStates", nodeStates) if total == dead { rerr := fmt.Errorf("no EVM primary nodes available: 0/%d nodes are alive", total) - logger.Criticalw(p.logger, rerr.Error(), "nodeStates", nodeStates) + p.logger.Criticalw(rerr.Error(), "nodeStates", nodeStates) p.SvcErrBuffer.Append(rerr) } else if dead > 0 { p.logger.Errorw(fmt.Sprintf("At least one EVM primary node is dead: %d/%d nodes are alive", live, total), "nodeStates", nodeStates) @@ -320,7 +320,7 @@ func (p *Pool) selectNode() (node Node) { p.activeNode = p.nodeSelector.Select() if p.activeNode == nil { - logger.Criticalw(p.logger, "No live RPC nodes available", "NodeSelectionMode", p.nodeSelector.Name()) + p.logger.Criticalw("No live RPC nodes available", "NodeSelectionMode", p.nodeSelector.Name()) errmsg := fmt.Errorf("no live nodes available for chain %s", p.chainID.String()) p.SvcErrBuffer.Append(errmsg) return &erroringNode{errMsg: errmsg.Error()} @@ -367,7 +367,7 @@ func (p *Pool) BatchCallContextAll(ctx context.Context, b []rpc.BatchElem) error if err != nil { p.logger.Debugw("Secondary node BatchCallContext failed", "err", err) } else { - logger.Trace(p.logger, "Secondary node BatchCallContext success") + p.logger.Trace("Secondary node BatchCallContext success") } }(n) } diff --git a/core/chains/evm/client/rpc_client.go b/core/chains/evm/client/rpc_client.go index 3cc90c4d8d9..627a2833109 100644 --- a/core/chains/evm/client/rpc_client.go +++ b/core/chains/evm/client/rpc_client.go @@ -55,7 +55,7 @@ type RPCCLient interface { } type rpcClient struct { - rpcLog logger.Logger + rpcLog logger.SugaredLogger name string id int32 chainID *big.Int @@ -106,7 +106,7 @@ func NewRPCClient( "client", r.String(), "evmChainID", chainID, ) - r.rpcLog = logger.Named(lggr, "RPC") + r.rpcLog = logger.Sugared(lggr).Named("RPC") return r } @@ -117,9 +117,9 @@ func (r *rpcClient) Dial(callerCtx context.Context) error { defer cancel() promEVMPoolRPCNodeDials.WithLabelValues(r.chainID.String(), r.name).Inc() - lggr := logger.With(r.rpcLog, "wsuri", r.ws.uri.Redacted()) + lggr := r.rpcLog.With("wsuri", r.ws.uri.Redacted()) if r.http != nil { - lggr = logger.With(lggr, "httpuri", r.http.uri.Redacted()) + lggr = lggr.With("httpuri", r.http.uri.Redacted()) } lggr.Debugw("RPC dial: evmclient.Client#dial") @@ -148,7 +148,7 @@ func (r *rpcClient) Dial(callerCtx context.Context) error { // It can only return error if the URL is malformed. func (r *rpcClient) DialHTTP() error { promEVMPoolRPCNodeDials.WithLabelValues(r.chainID.String(), r.name).Inc() - lggr := logger.With(r.rpcLog, "httpuri", r.ws.uri.Redacted()) + lggr := r.rpcLog.With("httpuri", r.ws.uri.Redacted()) lggr.Debugw("RPC dial: evmclient.Client#dial") var httprpc *rpc.Client @@ -206,10 +206,7 @@ func (r *rpcClient) logResult( promEVMPoolRPCNodeCalls.WithLabelValues(r.chainID.String(), r.name).Inc() if err == nil { promEVMPoolRPCNodeCallsSuccess.WithLabelValues(r.chainID.String(), r.name).Inc() - logger.Tracew(lggr, - fmt.Sprintf("evmclient.Client#%s RPC call success", callName), - results..., - ) + logger.Sugared(lggr).Tracew(fmt.Sprintf("evmclient.Client#%s RPC call success", callName), results...) } else { promEVMPoolRPCNodeCallsFailed.WithLabelValues(r.chainID.String(), r.name).Inc() lggr.Debugw( @@ -299,7 +296,7 @@ func (r *rpcClient) CallContext(ctx context.Context, result interface{}, method return err } defer cancel() - lggr := logger.With(r.newRqLggr(), + lggr := r.newRqLggr().With( "method", method, "args", args, ) @@ -328,9 +325,9 @@ func (r *rpcClient) BatchCallContext(ctx context.Context, b []any) error { batch[i] = arg.(rpc.BatchElem) } defer cancel() - lggr := logger.With(r.newRqLggr(), "nBatchElems", len(b), "batchElems", b) + lggr := r.newRqLggr().With("nBatchElems", len(b), "batchElems", b) - logger.Trace(lggr, "RPC call: evmclient.Client#BatchCallContext") + lggr.Trace("RPC call: evmclient.Client#BatchCallContext") start := time.Now() if http != nil { err = r.wrapHTTP(http.rpc.BatchCallContext(ctx, batch)) @@ -350,7 +347,7 @@ func (r *rpcClient) Subscribe(ctx context.Context, channel chan<- *evmtypes.Head return nil, err } defer cancel() - lggr := logger.With(r.newRqLggr(), "args", args) + lggr := r.newRqLggr().With("args", args) lggr.Debug("RPC call: evmclient.Client#EthSubscribe") start := time.Now() @@ -385,7 +382,7 @@ func (r *rpcClient) TransactionReceiptGeth(ctx context.Context, txHash common.Ha return nil, err } defer cancel() - lggr := logger.With(r.newRqLggr(), "txHash", txHash) + lggr := r.newRqLggr().With("txHash", txHash) lggr.Debug("RPC call: evmclient.Client#TransactionReceipt") @@ -411,7 +408,7 @@ func (r *rpcClient) TransactionByHash(ctx context.Context, txHash common.Hash) ( return nil, err } defer cancel() - lggr := logger.With(r.newRqLggr(), "txHash", txHash) + lggr := r.newRqLggr().With("txHash", txHash) lggr.Debug("RPC call: evmclient.Client#TransactionByHash") @@ -438,7 +435,7 @@ func (r *rpcClient) HeaderByNumber(ctx context.Context, number *big.Int) (header return nil, err } defer cancel() - lggr := logger.With(r.newRqLggr(), "number", number) + lggr := r.newRqLggr().With("number", number) lggr.Debug("RPC call: evmclient.Client#HeaderByNumber") start := time.Now() @@ -462,7 +459,7 @@ func (r *rpcClient) HeaderByHash(ctx context.Context, hash common.Hash) (header return nil, err } defer cancel() - lggr := logger.With(r.newRqLggr(), "hash", hash) + lggr := r.newRqLggr().With("hash", hash) lggr.Debug("RPC call: evmclient.Client#HeaderByHash") start := time.Now() @@ -515,7 +512,7 @@ func (r *rpcClient) BlockByHashGeth(ctx context.Context, hash common.Hash) (bloc return nil, err } defer cancel() - lggr := logger.With(r.newRqLggr(), "hash", hash) + lggr := r.newRqLggr().With("hash", hash) lggr.Debug("RPC call: evmclient.Client#BlockByHash") start := time.Now() @@ -541,7 +538,7 @@ func (r *rpcClient) BlockByNumberGeth(ctx context.Context, number *big.Int) (blo return nil, err } defer cancel() - lggr := logger.With(r.newRqLggr(), "number", number) + lggr := r.newRqLggr().With("number", number) lggr.Debug("RPC call: evmclient.Client#BlockByNumber") start := time.Now() @@ -567,7 +564,7 @@ func (r *rpcClient) SendTransaction(ctx context.Context, tx *types.Transaction) return err } defer cancel() - lggr := logger.With(r.newRqLggr(), "tx", tx) + lggr := r.newRqLggr().With("tx", tx) lggr.Debug("RPC call: evmclient.Client#SendTransaction") start := time.Now() @@ -607,7 +604,7 @@ func (r *rpcClient) PendingSequenceAt(ctx context.Context, account common.Addres return 0, err } defer cancel() - lggr := logger.With(r.newRqLggr(), "account", account) + lggr := r.newRqLggr().With("account", account) lggr.Debug("RPC call: evmclient.Client#PendingNonceAt") start := time.Now() @@ -639,7 +636,7 @@ func (r *rpcClient) SequenceAt(ctx context.Context, account common.Address, bloc return 0, err } defer cancel() - lggr := logger.With(r.newRqLggr(), "account", account, "blockNumber", blockNumber) + lggr := r.newRqLggr().With("account", account, "blockNumber", blockNumber) lggr.Debug("RPC call: evmclient.Client#NonceAt") start := time.Now() @@ -668,7 +665,7 @@ func (r *rpcClient) PendingCodeAt(ctx context.Context, account common.Address) ( return nil, err } defer cancel() - lggr := logger.With(r.newRqLggr(), "account", account) + lggr := r.newRqLggr().With("account", account) lggr.Debug("RPC call: evmclient.Client#PendingCodeAt") start := time.Now() @@ -694,7 +691,7 @@ func (r *rpcClient) CodeAt(ctx context.Context, account common.Address, blockNum return nil, err } defer cancel() - lggr := logger.With(r.newRqLggr(), "account", account, "blockNumber", blockNumber) + lggr := r.newRqLggr().With("account", account, "blockNumber", blockNumber) lggr.Debug("RPC call: evmclient.Client#CodeAt") start := time.Now() @@ -721,7 +718,7 @@ func (r *rpcClient) EstimateGas(ctx context.Context, c interface{}) (gas uint64, } defer cancel() call := c.(ethereum.CallMsg) - lggr := logger.With(r.newRqLggr(), "call", call) + lggr := r.newRqLggr().With("call", call) lggr.Debug("RPC call: evmclient.Client#EstimateGas") start := time.Now() @@ -773,7 +770,7 @@ func (r *rpcClient) CallContract(ctx context.Context, msg interface{}, blockNumb return nil, err } defer cancel() - lggr := logger.With(r.newRqLggr(), "callMsg", msg, "blockNumber", blockNumber) + lggr := r.newRqLggr().With("callMsg", msg, "blockNumber", blockNumber) message := msg.(ethereum.CallMsg) lggr.Debug("RPC call: evmclient.Client#CallContract") @@ -833,7 +830,7 @@ func (r *rpcClient) BalanceAt(ctx context.Context, account common.Address, block return nil, err } defer cancel() - lggr := logger.With(r.newRqLggr(), "account", account.Hex(), "blockNumber", blockNumber) + lggr := r.newRqLggr().With("account", account.Hex(), "blockNumber", blockNumber) lggr.Debug("RPC call: evmclient.Client#BalanceAt") start := time.Now() @@ -892,7 +889,7 @@ func (r *rpcClient) FilterLogs(ctx context.Context, q ethereum.FilterQuery) (l [ return nil, err } defer cancel() - lggr := logger.With(r.newRqLggr(), "q", q) + lggr := r.newRqLggr().With("q", q) lggr.Debug("RPC call: evmclient.Client#FilterLogs") start := time.Now() @@ -923,7 +920,7 @@ func (r *rpcClient) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQu return nil, err } defer cancel() - lggr := logger.With(r.newRqLggr(), "q", q) + lggr := r.newRqLggr().With("q", q) lggr.Debug("RPC call: evmclient.Client#SubscribeFilterLogs") start := time.Now() @@ -983,10 +980,8 @@ func (r *rpcClient) ChainID(ctx context.Context) (chainID *big.Int, err error) { } // newRqLggr generates a new logger with a unique request ID -func (r *rpcClient) newRqLggr() logger.Logger { - return logger.With(r.rpcLog, - "requestID", uuid.New(), - ) +func (r *rpcClient) newRqLggr() logger.SugaredLogger { + return r.rpcLog.With("requestID", uuid.New()) } func wrapCallError(err error, tp string) error { @@ -1009,7 +1004,7 @@ func (r *rpcClient) wrapHTTP(err error) error { if err != nil { r.rpcLog.Debugw("Call failed", "err", err) } else { - logger.Trace(r.rpcLog, "Call succeeded") + r.rpcLog.Trace("Call succeeded") } return err } diff --git a/core/chains/evm/gas/block_history_estimator.go b/core/chains/evm/gas/block_history_estimator.go index 844b9e547f2..dc95240fd42 100644 --- a/core/chains/evm/gas/block_history_estimator.go +++ b/core/chains/evm/gas/block_history_estimator.go @@ -198,7 +198,7 @@ func (b *BlockHistoryEstimator) getBlocks() []evmtypes.Block { // The provided context can be used to terminate Start sequence. func (b *BlockHistoryEstimator) Start(ctx context.Context) error { return b.StartOnce("BlockHistoryEstimator", func() error { - logger.Trace(b.logger, "Starting") + b.logger.Trace("Starting") if b.bhConfig.CheckInclusionBlocks() > 0 { b.logger.Infof("Inclusion checking enabled, bumping will be prevented on transactions that have been priced above the %d percentile for %d blocks", b.bhConfig.CheckInclusionPercentile(), b.bhConfig.CheckInclusionBlocks()) @@ -228,7 +228,7 @@ func (b *BlockHistoryEstimator) Start(ctx context.Context) error { b.wg.Add(1) go b.runLoop() - logger.Trace(b.logger, "Started") + b.logger.Trace("Started") return nil }) } @@ -291,7 +291,7 @@ func (b *BlockHistoryEstimator) BumpLegacyGas(_ context.Context, originalGasPric if b.bhConfig.CheckInclusionBlocks() > 0 { if err = b.checkConnectivity(attempts); err != nil { if errors.Is(err, commonfee.ErrConnectivity) { - logger.Criticalw(b.logger, BumpingHaltedLabel, "err", err) + b.logger.Criticalw(BumpingHaltedLabel, "err", err) b.SvcErrBuffer.Append(err) promBlockHistoryEstimatorConnectivityFailureCount.WithLabelValues(b.chainID.String(), "legacy").Inc() } @@ -467,7 +467,7 @@ func (b *BlockHistoryEstimator) BumpDynamicFee(_ context.Context, originalFee Dy if b.bhConfig.CheckInclusionBlocks() > 0 { if err = b.checkConnectivity(attempts); err != nil { if errors.Is(err, commonfee.ErrConnectivity) { - logger.Criticalw(b.logger, BumpingHaltedLabel, "err", err) + b.logger.Criticalw(BumpingHaltedLabel, "err", err) b.SvcErrBuffer.Append(err) promBlockHistoryEstimatorConnectivityFailureCount.WithLabelValues(b.chainID.String(), "eip1559").Inc() } @@ -508,7 +508,7 @@ func (b *BlockHistoryEstimator) FetchBlocksAndRecalculate(ctx context.Context, h func (b *BlockHistoryEstimator) Recalculate(head *evmtypes.Head) { percentile := int(b.bhConfig.TransactionPercentile()) - lggr := logger.With(b.logger, "head", head) + lggr := b.logger.With("head", head) blockHistory := b.getBlocks() if len(blockHistory) == 0 { @@ -630,9 +630,9 @@ func (b *BlockHistoryEstimator) FetchBlocks(ctx context.Context, head *evmtypes. reqs = append(reqs, req) } - lggr := logger.With(b.logger, "head", head) + lggr := b.logger.With("head", head) - logger.Tracew(lggr, fmt.Sprintf("Fetching %v blocks (%v in local history)", len(reqs), len(blocks)), "n", len(reqs), "inHistory", len(blocks), "blockNum", head.Number) + lggr.Tracew(fmt.Sprintf("Fetching %v blocks (%v in local history)", len(reqs), len(blocks)), "n", len(reqs), "inHistory", len(blocks), "blockNum", head.Number) if err := b.batchFetch(ctx, reqs); err != nil { return err } @@ -713,7 +713,7 @@ func (b *BlockHistoryEstimator) batchFetch(ctx context.Context, reqs []rpc.Batch j = len(reqs) } - logger.Tracew(b.logger, fmt.Sprintf("Batch fetching blocks %v thru %v", HexToInt64(reqs[i].Args[0]), HexToInt64(reqs[j-1].Args[0]))) + b.logger.Tracew(fmt.Sprintf("Batch fetching blocks %v thru %v", HexToInt64(reqs[i].Args[0]), HexToInt64(reqs[j-1].Args[0]))) err := b.ethClient.BatchCallContext(ctx, reqs[i:j]) if errors.Is(err, context.DeadlineExceeded) { diff --git a/core/chains/evm/gas/rollups/l1_gas_price_oracle.go b/core/chains/evm/gas/rollups/l1_gas_price_oracle.go index 6a384fa9c54..ce1a50aa320 100644 --- a/core/chains/evm/gas/rollups/l1_gas_price_oracle.go +++ b/core/chains/evm/gas/rollups/l1_gas_price_oracle.go @@ -31,7 +31,7 @@ type l1GasPriceOracle struct { services.StateMachine client ethClient pollPeriod time.Duration - logger logger.Logger + logger logger.SugaredLogger address string callArgs string @@ -94,7 +94,7 @@ func NewL1GasPriceOracle(lggr logger.Logger, ethClient ethClient, chainType conf return &l1GasPriceOracle{ client: ethClient, pollPeriod: PollPeriod, - logger: logger.Named(lggr, fmt.Sprintf("L1GasPriceOracle(%s)", chainType)), + logger: logger.Sugared(logger.Named(lggr, fmt.Sprintf("L1GasPriceOracle(%s)", chainType))), address: address, callArgs: callArgs, chInitialised: make(chan struct{}), @@ -159,7 +159,7 @@ func (o *l1GasPriceOracle) refresh() (t *time.Timer) { } if len(b) != 32 { // returns uint256; - logger.Criticalf(o.logger, "return data length (%d) different than expected (%d)", len(b), 32) + o.logger.Criticalf("return data length (%d) different than expected (%d)", len(b), 32) return } price := new(big.Int).SetBytes(b) diff --git a/core/chains/evm/log/helpers_test.go b/core/chains/evm/log/helpers_test.go index 13dfe1ffab6..cea2e361184 100644 --- a/core/chains/evm/log/helpers_test.go +++ b/core/chains/evm/log/helpers_test.go @@ -241,7 +241,7 @@ func (rec *received) logsOnBlocks() []logOnBlock { type simpleLogListener struct { name string - lggr logger.Logger + lggr logger.SugaredLogger cfg pg.QConfig received *received t *testing.T @@ -266,7 +266,7 @@ func (helper *broadcasterHelper) newLogListenerWithJob(name string) *simpleLogLi var rec received return &simpleLogListener{ db: db, - lggr: logger.Test(t), + lggr: logger.Sugared(logger.Test(t)), cfg: helper.config.Database(), name: name, received: &rec, @@ -282,7 +282,7 @@ func (listener *simpleLogListener) SkipMarkingConsumed(skip bool) { func (listener *simpleLogListener) HandleLog(lb log.Broadcast) { listener.received.Lock() defer listener.received.Unlock() - logger.Tracef(listener.lggr, "Listener %v HandleLog for block %v %v received at %v %v", listener.name, lb.RawLog().BlockNumber, lb.RawLog().BlockHash, lb.LatestBlockNumber(), lb.LatestBlockHash()) + listener.lggr.Tracef("Listener %v HandleLog for block %v %v received at %v %v", listener.name, lb.RawLog().BlockNumber, lb.RawLog().BlockHash, lb.LatestBlockNumber(), lb.LatestBlockHash()) listener.received.logs = append(listener.received.logs, lb.RawLog()) listener.received.broadcasts = append(listener.received.broadcasts, lb) diff --git a/core/chains/evm/log/registrations.go b/core/chains/evm/log/registrations.go index 73f197a6ab6..346a6776e86 100644 --- a/core/chains/evm/log/registrations.go +++ b/core/chains/evm/log/registrations.go @@ -46,7 +46,7 @@ type ( // handlersByConfs maps numConfirmations => *handler handlersByConfs map[uint32]*handler - logger logger.Logger + logger logger.SugaredLogger evmChainID big.Int // highest 'NumConfirmations' per all listeners, used to decide about deleting older logs if it's higher than EvmFinalityDepth @@ -57,7 +57,7 @@ type ( handler struct { lookupSubs map[common.Address]map[common.Hash]subscribers // contractAddress => logTopic => *subscriber => topicValueFilters evmChainID big.Int - logger logger.Logger + logger logger.SugaredLogger } // The Listener responds to log events through HandleLog. @@ -76,7 +76,7 @@ func newRegistrations(lggr logger.Logger, evmChainID big.Int) *registrations { jobIDAddrs: make(map[int32]map[common.Address]struct{}), handlersByConfs: make(map[uint32]*handler), evmChainID: evmChainID, - logger: logger.Named(lggr, "Registrations"), + logger: logger.Sugared(logger.Named(lggr, "Registrations")), } } @@ -85,7 +85,7 @@ func (r *registrations) addSubscriber(sub *subscriber) (needsResubscribe bool) { r.logger.Panicw(err.Error(), "err", err, "addr", sub.opts.Contract.Hex(), "jobID", sub.listener.JobID()) } - logger.Tracef(r.logger, "Added subscription %p with job ID %v", sub, sub.listener.JobID()) + r.logger.Tracef("Added subscription %p with job ID %v", sub, sub.listener.JobID()) handler, exists := r.handlersByConfs[sub.opts.MinIncomingConfirmations] if !exists { @@ -142,7 +142,7 @@ func (r *registrations) removeSubscriber(sub *subscriber) (needsResubscribe bool if err := r.checkRemoveSubscriber(sub); err != nil { r.logger.Panicw(err.Error(), "err", err, "addr", sub.opts.Contract.Hex(), "jobID", sub.listener.JobID()) } - logger.Tracef(r.logger, "Removed subscription %p with job ID %v", sub, sub.listener.JobID()) + r.logger.Tracef("Removed subscription %p with job ID %v", sub, sub.listener.JobID()) handlers, exists := r.handlersByConfs[sub.opts.MinIncomingConfirmations] if !exists { @@ -263,7 +263,7 @@ func filtersContainValues(topicValues []common.Hash, filters [][]Topic) bool { return true } -func newHandler(lggr logger.Logger, evmChainID big.Int) *handler { +func newHandler(lggr logger.SugaredLogger, evmChainID big.Int) *handler { return &handler{ lookupSubs: make(map[common.Address]map[common.Hash]subscribers), evmChainID: evmChainID, @@ -284,7 +284,7 @@ func (r *handler) addSubscriber(sub *subscriber, handlersWithGreaterConfs []*han for topic, topicValueFilters := range sub.opts.LogsWithTopics { if _, exists := r.lookupSubs[addr][topic]; !exists { - logger.Tracef(r.logger, "No existing sub for addr %s and topic %s at this MinIncomingConfirmations of %v", addr.Hex(), topic.Hex(), sub.opts.MinIncomingConfirmations) + r.logger.Tracef("No existing sub for addr %s and topic %s at this MinIncomingConfirmations of %v", addr.Hex(), topic.Hex(), sub.opts.MinIncomingConfirmations) r.lookupSubs[addr][topic] = make(subscribers) func() { @@ -295,11 +295,11 @@ func (r *handler) addSubscriber(sub *subscriber, handlersWithGreaterConfs []*han // again since even the worst case lookback is already covered for _, existingHandler := range handlersWithGreaterConfs { if _, exists := existingHandler.lookupSubs[addr][topic]; exists { - logger.Tracef(r.logger, "Sub already exists for addr %s and topic %s at greater than this MinIncomingConfirmations of %v. Resubscribe is not required", addr.Hex(), topic.Hex(), sub.opts.MinIncomingConfirmations) + r.logger.Tracef("Sub already exists for addr %s and topic %s at greater than this MinIncomingConfirmations of %v. Resubscribe is not required", addr.Hex(), topic.Hex(), sub.opts.MinIncomingConfirmations) return } } - logger.Tracef(r.logger, "No sub exists for addr %s and topic %s at this or greater MinIncomingConfirmations of %v. Resubscribe is required", addr.Hex(), topic.Hex(), sub.opts.MinIncomingConfirmations) + r.logger.Tracef("No sub exists for addr %s and topic %s at this or greater MinIncomingConfirmations of %v. Resubscribe is required", addr.Hex(), topic.Hex(), sub.opts.MinIncomingConfirmations) needsResubscribe = true } }() @@ -332,7 +332,7 @@ func (r *handler) removeSubscriber(sub *subscriber, allHandlers map[uint32]*hand // cleanup and resubscribe if necessary if len(topicMap) == 0 { - logger.Tracef(r.logger, "No subs left for addr %s and topic %s at this MinIncomingConfirmations of %v", addr.Hex(), topic.Hex(), sub.opts.MinIncomingConfirmations) + r.logger.Tracef("No subs left for addr %s and topic %s at this MinIncomingConfirmations of %v", addr.Hex(), topic.Hex(), sub.opts.MinIncomingConfirmations) func() { if !needsResubscribe { @@ -344,12 +344,12 @@ func (r *handler) removeSubscriber(sub *subscriber, allHandlers map[uint32]*hand continue } if _, exists := otherHandler.lookupSubs[addr][topic]; exists { - logger.Tracef(r.logger, "Sub still exists for addr %s and topic %s. Resubscribe will not be performed", addr.Hex(), topic.Hex()) + r.logger.Tracef("Sub still exists for addr %s and topic %s. Resubscribe will not be performed", addr.Hex(), topic.Hex()) return } } - logger.Tracef(r.logger, "No sub exists for addr %s and topic %s. Resubscribe will be performed", addr.Hex(), topic.Hex()) + r.logger.Tracef("No sub exists for addr %s and topic %s. Resubscribe will be performed", addr.Hex(), topic.Hex()) needsResubscribe = true } }() diff --git a/core/chains/evm/logpoller/log_poller.go b/core/chains/evm/logpoller/log_poller.go index 991cc8d4309..7bc131afef4 100644 --- a/core/chains/evm/logpoller/log_poller.go +++ b/core/chains/evm/logpoller/log_poller.go @@ -98,7 +98,7 @@ type logPoller struct { services.StateMachine ec Client orm ORM - lggr logger.Logger + lggr logger.SugaredLogger pollPeriod time.Duration // poll period set by block production rate useFinalityTag bool // indicates whether logPoller should use chain's finality or pick a fixed depth for finality finalityDepth int64 // finality depth is taken to mean that block (head - finality) is finalized. If `useFinalityTag` is set to true, this value is ignored, because finalityDepth is fetched from chain @@ -138,7 +138,7 @@ func NewLogPoller(orm ORM, ec Client, lggr logger.Logger, pollPeriod time.Durati cancel: cancel, ec: ec, orm: orm, - lggr: logger.Named(lggr, "LogPoller"), + lggr: logger.Sugared(logger.Named(lggr, "LogPoller")), replayStart: make(chan int64), replayComplete: make(chan error), pollPeriod: pollPeriod, @@ -666,7 +666,7 @@ func (lp *logPoller) backfill(ctx context.Context, start, end int64) error { } } if batchSize == 1 { - logger.Criticalw(lp.lggr, "Too many log results in a single block, failed to retrieve logs! Node may be running in a degraded state.", "err", err, "from", from, "to", to, "LogBackfillBatchSize", lp.backfillBatchSize) + lp.lggr.Criticalw("Too many log results in a single block, failed to retrieve logs! Node may be running in a degraded state.", "err", err, "from", from, "to", to, "LogBackfillBatchSize", lp.backfillBatchSize) return err } batchSize /= 2 @@ -921,7 +921,7 @@ func (lp *logPoller) findBlockAfterLCA(ctx context.Context, current *evmtypes.He return nil, err } } - logger.Criticalw(lp.lggr, "Reorg greater than finality depth detected", "finalityTag", lp.useFinalityTag, "current", current.Number, "latestFinalized", latestFinalizedBlockNumber) + lp.lggr.Criticalw("Reorg greater than finality depth detected", "finalityTag", lp.useFinalityTag, "current", current.Number, "latestFinalized", latestFinalizedBlockNumber) rerr := errors.New("Reorg greater than finality depth") lp.SvcErrBuffer.Append(rerr) return nil, rerr diff --git a/core/chains/evm/txmgr/broadcaster_test.go b/core/chains/evm/txmgr/broadcaster_test.go index f676d3d18e2..68a81299bf9 100644 --- a/core/chains/evm/txmgr/broadcaster_test.go +++ b/core/chains/evm/txmgr/broadcaster_test.go @@ -2033,7 +2033,7 @@ type testChecker struct { func (t *testChecker) Check( _ context.Context, - _ logger.Logger, + _ logger.SugaredLogger, _ txmgr.Tx, _ txmgr.TxAttempt, ) error { diff --git a/core/chains/evm/txmgr/client.go b/core/chains/evm/txmgr/client.go index d08274f74b6..dc7b62647c0 100644 --- a/core/chains/evm/txmgr/client.go +++ b/core/chains/evm/txmgr/client.go @@ -43,7 +43,7 @@ func (c *evmTxmClient) BatchSendTransactions( ctx context.Context, attempts []TxAttempt, batchSize int, - lggr logger.Logger, + lggr logger.SugaredLogger, ) ( codes []commonclient.SendTxReturnCode, txErrs []error, @@ -62,7 +62,7 @@ func (c *evmTxmClient) BatchSendTransactions( if len(reqs) != len(attempts) { lenErr := fmt.Errorf("Returned request data length (%d) != number of tx attempts (%d)", len(reqs), len(attempts)) err = errors.Join(err, lenErr) - logger.Criticalw(lggr, "Mismatched length", "err", err) + lggr.Criticalw("Mismatched length", "err", err) return } @@ -88,10 +88,10 @@ func (c *evmTxmClient) BatchSendTransactions( return } -func (c *evmTxmClient) SendTransactionReturnCode(ctx context.Context, etx Tx, attempt TxAttempt, lggr logger.Logger) (commonclient.SendTxReturnCode, error) { +func (c *evmTxmClient) SendTransactionReturnCode(ctx context.Context, etx Tx, attempt TxAttempt, lggr logger.SugaredLogger) (commonclient.SendTxReturnCode, error) { signedTx, err := GetGethSignedTx(attempt.SignedRawTx) if err != nil { - logger.Criticalw(lggr, "Fatal error signing transaction", "err", err, "etx", etx) + lggr.Criticalw("Fatal error signing transaction", "err", err, "etx", etx) return commonclient.Fatal, err } return c.client.SendTransactionReturnCode(ctx, signedTx, etx.FromAddress) diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go index bb2a30e51dd..f9014163675 100644 --- a/core/chains/evm/txmgr/evm_tx_store.go +++ b/core/chains/evm/txmgr/evm_tx_store.go @@ -75,7 +75,7 @@ type TestEvmTxStore interface { type evmTxStore struct { q pg.Q - logger logger.Logger + logger logger.SugaredLogger ctx context.Context ctxCancel context.CancelFunc } @@ -340,7 +340,7 @@ func NewTxStore( q := pg.NewQ(db, namedLogger, cfg, pg.WithParentCtx(ctx)) return &evmTxStore{ q: q, - logger: namedLogger, + logger: logger.Sugared(namedLogger), ctx: ctx, ctxCancel: cancel, } @@ -1499,7 +1499,7 @@ GROUP BY e.id txHashesHex[i] = common.BytesToAddress(r.TxHashes[i]) } - logger.Criticalw(o.logger, fmt.Sprintf("eth_tx with ID %v expired without ever getting a receipt for any of our attempts. "+ + o.logger.Criticalw(fmt.Sprintf("eth_tx with ID %v expired without ever getting a receipt for any of our attempts. "+ "Current block height is %v, transaction was broadcast before block height %v. This transaction may not have not been sent and will be marked as fatally errored. "+ "This can happen if there is another instance of chainlink running that is using the same private key, or if "+ "an external wallet has been used to send a transaction from account %s with nonce %v."+ diff --git a/core/chains/evm/txmgr/transmitchecker.go b/core/chains/evm/txmgr/transmitchecker.go index 76dfcb9d51c..919fb509fee 100644 --- a/core/chains/evm/txmgr/transmitchecker.go +++ b/core/chains/evm/txmgr/transmitchecker.go @@ -110,7 +110,7 @@ type noChecker struct{} // Check satisfies the TransmitChecker interface. func (noChecker) Check( _ context.Context, - _ logger.Logger, + _ logger.SugaredLogger, _ Tx, _ TxAttempt, ) error { @@ -125,7 +125,7 @@ type SimulateChecker struct { // Check satisfies the TransmitChecker interface. func (s *SimulateChecker) Check( ctx context.Context, - l logger.Logger, + l logger.SugaredLogger, tx Tx, a TxAttempt, ) error { @@ -148,7 +148,7 @@ func (s *SimulateChecker) Check( err := s.Client.CallContext(ctx, &b, "eth_call", callArg, evmclient.ToBlockNumArg(nil)) if err != nil { if jErr := evmclient.ExtractRPCErrorOrNil(err); jErr != nil { - logger.Criticalw(l, "Transaction reverted during simulation", + l.Criticalw("Transaction reverted during simulation", "ethTxAttemptID", a.ID, "txHash", a.Hash, "err", err, "rpcErr", jErr.String(), "returnValue", b.String()) return errors.Errorf("transaction reverted during simulation: %s", jErr.String()) } @@ -175,7 +175,7 @@ type VRFV1Checker struct { // Check satisfies the TransmitChecker interface. func (v *VRFV1Checker) Check( ctx context.Context, - l logger.Logger, + l logger.SugaredLogger, tx Tx, _ TxAttempt, ) error { @@ -284,7 +284,7 @@ type VRFV2Checker struct { // Check satisfies the TransmitChecker interface. func (v *VRFV2Checker) Check( ctx context.Context, - l logger.Logger, + l logger.SugaredLogger, tx Tx, _ TxAttempt, ) error { diff --git a/core/chains/evm/txmgr/transmitchecker_test.go b/core/chains/evm/txmgr/transmitchecker_test.go index 6dd4edd91c6..d2f668da11b 100644 --- a/core/chains/evm/txmgr/transmitchecker_test.go +++ b/core/chains/evm/txmgr/transmitchecker_test.go @@ -106,7 +106,7 @@ func TestFactory(t *testing.T) { func TestTransmitCheckers(t *testing.T) { client := evmtest.NewEthClientMockWithDefaultChain(t) - log := logger.Test(t) + log := logger.Sugared(logger.Test(t)) ctx := testutils.Context(t) t.Run("no checker", func(t *testing.T) { diff --git a/core/scripts/go.mod b/core/scripts/go.mod index c5327596272..db71535723e 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -237,7 +237,7 @@ require ( github.com/shirou/gopsutil/v3 v3.23.11 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect - github.com/smartcontractkit/chainlink-common v0.1.7-0.20231206181640-faad3f11cfad // indirect + github.com/smartcontractkit/chainlink-common v0.1.7-0.20231213134506-b6c433e6c490 // indirect github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231206164210-03f8b219402e // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20231204152908-a6e3fe8ff2a1 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20231127231053-2232d3a6766d // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 28750a076d5..1c48074ea3a 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1148,8 +1148,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M= github.com/smartcontractkit/chainlink-automation v1.0.1 h1:vVjBFq2Zsz21kPy1Pb0wpjF9zrbJX+zjXphDeeR4XZk= github.com/smartcontractkit/chainlink-automation v1.0.1/go.mod h1:INSchkV3ntyDdlZKGWA030MPDpp6pbeuiRkRKYFCm2k= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20231206181640-faad3f11cfad h1:ysPjfbCPJuVxxFZa1Ifv8OPE20pzvnEHjJrPDUo4gT0= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20231206181640-faad3f11cfad/go.mod h1:IdlfCN9rUs8Q/hrOYe8McNBIwEOHEsi0jilb3Cw77xs= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20231213134506-b6c433e6c490 h1:lSYiaiIfAA+5ac45/UD8ciytlNw/S6fnhK7bxFHYI88= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20231213134506-b6c433e6c490/go.mod h1:IdlfCN9rUs8Q/hrOYe8McNBIwEOHEsi0jilb3Cw77xs= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231206164210-03f8b219402e h1:xvqffqFec2HkEcUKrCkm4FDJRnn/+gHmvrE/dz3Zlw8= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231206164210-03f8b219402e/go.mod h1:soVgcl4CbfR6hC9UptjuCQhz19HJaFEjwnOpiySkxg0= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20231204152908-a6e3fe8ff2a1 h1:xYqRgZO0nMSO8CBCMR0r3WA+LZ4kNL8a6bnbyk/oBtQ= diff --git a/core/services/pg/q.go b/core/services/pg/q.go index 050606c7937..e69e16ec48f 100644 --- a/core/services/pg/q.go +++ b/core/services/pg/q.go @@ -118,7 +118,7 @@ type Q struct { Queryer ParentCtx context.Context db *sqlx.DB - logger logger.Logger + logger logger.SugaredLogger config QConfig QueryTimeout time.Duration } @@ -130,7 +130,7 @@ func NewQ(db *sqlx.DB, lggr logger.Logger, config QConfig, qopts ...QOpt) (q Q) q.db = db // skip two levels since we use internal helpers and also want to point up the stack to the caller of the Q method. - q.logger = logger.Helper(lggr, 2) + q.logger = logger.Sugared(logger.Helper(lggr, 2)) q.config = config if q.Queryer == nil { @@ -356,7 +356,7 @@ func (q *queryLogger) postSqlLog(ctx context.Context, begin time.Time) { kvs := []any{"ms", elapsed.Milliseconds(), "timeout", timeout.Milliseconds(), "percent", strconv.FormatFloat(pct, 'f', 1, 64), "sql", q} if elapsed >= timeout { - logger.Criticalw(q.logger, "SLOW SQL QUERY", kvs...) + q.logger.Criticalw("SLOW SQL QUERY", kvs...) } else if errThreshold := timeout / 5; errThreshold > 0 && elapsed > errThreshold { q.logger.Errorw("SLOW SQL QUERY", kvs...) } else if warnThreshold := timeout / 10; warnThreshold > 0 && elapsed > warnThreshold { diff --git a/go.mod b/go.mod index e7b93c40bdb..c71705d9c92 100644 --- a/go.mod +++ b/go.mod @@ -65,7 +65,7 @@ require ( github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 github.com/smartcontractkit/chainlink-automation v1.0.1 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20231206181640-faad3f11cfad + github.com/smartcontractkit/chainlink-common v0.1.7-0.20231213134506-b6c433e6c490 github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231206164210-03f8b219402e github.com/smartcontractkit/chainlink-data-streams v0.0.0-20231204152908-a6e3fe8ff2a1 github.com/smartcontractkit/chainlink-feeds v0.0.0-20231127231053-2232d3a6766d diff --git a/go.sum b/go.sum index e9a7f0267ad..b38b7ac2632 100644 --- a/go.sum +++ b/go.sum @@ -1134,8 +1134,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M= github.com/smartcontractkit/chainlink-automation v1.0.1 h1:vVjBFq2Zsz21kPy1Pb0wpjF9zrbJX+zjXphDeeR4XZk= github.com/smartcontractkit/chainlink-automation v1.0.1/go.mod h1:INSchkV3ntyDdlZKGWA030MPDpp6pbeuiRkRKYFCm2k= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20231206181640-faad3f11cfad h1:ysPjfbCPJuVxxFZa1Ifv8OPE20pzvnEHjJrPDUo4gT0= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20231206181640-faad3f11cfad/go.mod h1:IdlfCN9rUs8Q/hrOYe8McNBIwEOHEsi0jilb3Cw77xs= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20231213134506-b6c433e6c490 h1:lSYiaiIfAA+5ac45/UD8ciytlNw/S6fnhK7bxFHYI88= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20231213134506-b6c433e6c490/go.mod h1:IdlfCN9rUs8Q/hrOYe8McNBIwEOHEsi0jilb3Cw77xs= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231206164210-03f8b219402e h1:xvqffqFec2HkEcUKrCkm4FDJRnn/+gHmvrE/dz3Zlw8= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231206164210-03f8b219402e/go.mod h1:soVgcl4CbfR6hC9UptjuCQhz19HJaFEjwnOpiySkxg0= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20231204152908-a6e3fe8ff2a1 h1:xYqRgZO0nMSO8CBCMR0r3WA+LZ4kNL8a6bnbyk/oBtQ= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 84da65e9a5d..9f0ff1b384c 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -24,7 +24,7 @@ require ( github.com/segmentio/ksuid v1.0.4 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.1 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20231206181640-faad3f11cfad + github.com/smartcontractkit/chainlink-common v0.1.7-0.20231213134506-b6c433e6c490 github.com/smartcontractkit/chainlink-testing-framework v1.22.0 github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 854978e3353..f8a9529a4cc 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1411,7 +1411,6 @@ github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMT github.com/shirou/gopsutil/v3 v3.23.11 h1:i3jP9NjCPUz7FiZKxlMnODZkdSIp2gnzfrvsu9CuWEQ= github.com/shirou/gopsutil/v3 v3.23.11/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= -github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= @@ -1433,8 +1432,8 @@ github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumv github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M= github.com/smartcontractkit/chainlink-automation v1.0.1 h1:vVjBFq2Zsz21kPy1Pb0wpjF9zrbJX+zjXphDeeR4XZk= github.com/smartcontractkit/chainlink-automation v1.0.1/go.mod h1:INSchkV3ntyDdlZKGWA030MPDpp6pbeuiRkRKYFCm2k= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20231206181640-faad3f11cfad h1:ysPjfbCPJuVxxFZa1Ifv8OPE20pzvnEHjJrPDUo4gT0= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20231206181640-faad3f11cfad/go.mod h1:IdlfCN9rUs8Q/hrOYe8McNBIwEOHEsi0jilb3Cw77xs= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20231213134506-b6c433e6c490 h1:lSYiaiIfAA+5ac45/UD8ciytlNw/S6fnhK7bxFHYI88= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20231213134506-b6c433e6c490/go.mod h1:IdlfCN9rUs8Q/hrOYe8McNBIwEOHEsi0jilb3Cw77xs= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231206164210-03f8b219402e h1:xvqffqFec2HkEcUKrCkm4FDJRnn/+gHmvrE/dz3Zlw8= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20231206164210-03f8b219402e/go.mod h1:soVgcl4CbfR6hC9UptjuCQhz19HJaFEjwnOpiySkxg0= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20231204152908-a6e3fe8ff2a1 h1:xYqRgZO0nMSO8CBCMR0r3WA+LZ4kNL8a6bnbyk/oBtQ= From 7cb552e9dfd7c344bfd3c180bb3253a486ad7b91 Mon Sep 17 00:00:00 2001 From: Ilja Pavlovs Date: Wed, 13 Dec 2023 21:02:27 +0200 Subject: [PATCH 17/29] =?UTF-8?q?VRF-798:=20fix=20"nonce=20too=20low"=20in?= =?UTF-8?q?=20load=20test=20setup=20when=20creating=20a=20subsc=E2=80=A6?= =?UTF-8?q?=20(#11560)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * VRF-798: fix "nonce too low" in load test setup when creating a subscription * VRF-798: fix runtime issue * VRF-798: PR comments --- integration-tests/load/vrfv2/vrfv2_test.go | 6 ++++++ .../load/vrfv2plus/vrfv2plus_test.go | 15 +++++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/integration-tests/load/vrfv2/vrfv2_test.go b/integration-tests/load/vrfv2/vrfv2_test.go index 86f9b8d61f6..ec0f945870d 100644 --- a/integration-tests/load/vrfv2/vrfv2_test.go +++ b/integration-tests/load/vrfv2/vrfv2_test.go @@ -115,6 +115,12 @@ func TestVRFV2Performance(t *testing.T) { require.NoError(t, err) consumers, err = vrfv2_actions.DeployVRFV2Consumers(env.ContractDeployer, coordinator, 1) require.NoError(t, err) + err = env.EVMClient.WaitForEvents() + require.NoError(t, err, vrfv2_actions.ErrWaitTXsComplete) + l.Info(). + Str("Coordinator", cfg.ExistingEnvConfig.CoordinatorAddress). + Int("Number of Subs to create", vrfv2Config.NumberOfSubToCreate). + Msg("Creating and funding subscriptions, deploying and adding consumers to subs") subIDs, err = vrfv2_actions.CreateFundSubsAndAddConsumers( env, vrfv2Config, diff --git a/integration-tests/load/vrfv2plus/vrfv2plus_test.go b/integration-tests/load/vrfv2plus/vrfv2plus_test.go index 6fe0d06e7da..6d298e075f0 100644 --- a/integration-tests/load/vrfv2plus/vrfv2plus_test.go +++ b/integration-tests/load/vrfv2plus/vrfv2plus_test.go @@ -8,7 +8,6 @@ import ( "testing" "time" - "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/kelseyhightower/envconfig" "github.com/rs/zerolog" @@ -117,6 +116,12 @@ func TestVRFV2PlusPerformance(t *testing.T) { require.NoError(t, err) consumers, err = vrfv2plus.DeployVRFV2PlusConsumers(env.ContractDeployer, coordinator, 1) require.NoError(t, err) + err = env.EVMClient.WaitForEvents() + require.NoError(t, err, vrfv2plus.ErrWaitTXsComplete) + l.Info(). + Str("Coordinator", cfg.ExistingEnvConfig.CoordinatorAddress). + Int("Number of Subs to create", vrfv2PlusConfig.NumberOfSubToCreate). + Msg("Creating and funding subscriptions, deploying and adding consumers to subs") subIDs, err = vrfv2plus.CreateFundSubsAndAddConsumers( env, vrfv2PlusConfig, @@ -308,13 +313,7 @@ func FundNodesIfNeeded(cfg *PerformanceConfig, client blockchain.EVMClient, l ze Str("Should have at least", fundingAtLeast.String()). Str("Funding Amount in ETH", fundingToSendEth.String()). Msg("Funding Node's Sending Key") - gasEstimates, err := client.EstimateGas(ethereum.CallMsg{ - To: &address, - }) - if err != nil { - return err - } - err = client.Fund(sendingKey, fundingToSendEth, gasEstimates) + err := actions.FundAddress(client, sendingKey, fundingToSendEth) if err != nil { return err } From 43e9f277d4c42b224f83870586150ff5c02a8ced Mon Sep 17 00:00:00 2001 From: Makram Date: Wed, 13 Dec 2023 22:01:04 +0200 Subject: [PATCH 18/29] feat: add liquidity balancer specs table (#11564) Add the liquidity balancer specs table. This table will be used to house the specs for the liquidity balancer job which will be implemented in ccip rather than core. The entirety of the spec's content will be in the `liquidity_balancer_config` field. This is done to minimize future migrations. This doesn't mean we won't be doing strict checks on the contents of the config during the validation process. --- core/services/job/models.go | 8 +++ .../0213_liquidity_balancer_specs.sql | 49 +++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 core/store/migrate/migrations/0213_liquidity_balancer_specs.sql diff --git a/core/services/job/models.go b/core/services/job/models.go index b21ecc12e72..3c869f76056 100644 --- a/core/services/job/models.go +++ b/core/services/job/models.go @@ -152,6 +152,8 @@ type Job struct { GatewaySpecID *int32 EALSpec *EALSpec EALSpecID *int32 + LiquidityBalancerSpec *LiquidityBalancerSpec + LiquidityBalancerSpecID *int32 PipelineSpecID int32 PipelineSpec *pipeline.Spec JobSpecErrors []SpecError @@ -793,3 +795,9 @@ type EALSpec struct { // UpdatedAt is the time this job was last updated. UpdatedAt time.Time `toml:"-"` } + +type LiquidityBalancerSpec struct { + ID int32 + + LiquidityBalancerConfig string `toml:"liquidityBalancerConfig" db:"liquidity_balancer_config"` +} diff --git a/core/store/migrate/migrations/0213_liquidity_balancer_specs.sql b/core/store/migrate/migrations/0213_liquidity_balancer_specs.sql new file mode 100644 index 00000000000..cd717181f58 --- /dev/null +++ b/core/store/migrate/migrations/0213_liquidity_balancer_specs.sql @@ -0,0 +1,49 @@ +-- +goose Up +CREATE TABLE liquidity_balancer_specs ( + id BIGSERIAL PRIMARY KEY, + liquidity_balancer_config JSONB NOT NULL +); + +ALTER TABLE + jobs +ADD COLUMN + liquidity_balancer_spec_id BIGINT REFERENCES liquidity_balancer_specs(id), +DROP CONSTRAINT chk_only_one_spec, +ADD CONSTRAINT chk_only_one_spec CHECK ( + num_nonnulls( + ocr_oracle_spec_id, ocr2_oracle_spec_id, + direct_request_spec_id, flux_monitor_spec_id, + keeper_spec_id, cron_spec_id, webhook_spec_id, + vrf_spec_id, blockhash_store_spec_id, + block_header_feeder_spec_id, bootstrap_spec_id, + gateway_spec_id, + legacy_gas_station_server_spec_id, + legacy_gas_station_sidecar_spec_id, + eal_spec_id, + liquidity_balancer_spec_id + ) = 1 +); + +-- +goose Down +ALTER TABLE + jobs +DROP CONSTRAINT chk_only_one_spec, +ADD CONSTRAINT chk_only_one_spec CHECK ( + num_nonnulls( + ocr_oracle_spec_id, ocr2_oracle_spec_id, + direct_request_spec_id, flux_monitor_spec_id, + keeper_spec_id, cron_spec_id, webhook_spec_id, + vrf_spec_id, blockhash_store_spec_id, + block_header_feeder_spec_id, bootstrap_spec_id, + gateway_spec_id, + legacy_gas_station_server_spec_id, + legacy_gas_station_sidecar_spec_id, + eal_spec_id + ) = 1 +); +ALTER TABLE + jobs +DROP COLUMN + liquidity_balancer_spec_id; +DROP TABLE + liquidity_balancer_specs; From 19c7ccac1714dae991d7b3aecc864f99d722b2d4 Mon Sep 17 00:00:00 2001 From: Lei Date: Wed, 13 Dec 2023 12:07:31 -0800 Subject: [PATCH 19/29] Auto 8087 modular streams (#11489) * make streams lookup modular * polish * address comment to use pointer instead of array/map * rebase * get rid of slice * keep using array and index * remove duplicate logging * address err re-declarion lint issues --- core/scripts/chaincli/handler/debug.go | 223 +++++--- .../handler/mercury_lookup_handler.go | 536 ------------------ core/scripts/go.mod | 3 +- core/scripts/go.sum | 2 - .../v21/mercury/streams/streams.go | 105 ++-- .../v21/mercury/streams/streams_test.go | 20 +- 6 files changed, 222 insertions(+), 667 deletions(-) delete mode 100644 core/scripts/chaincli/handler/mercury_lookup_handler.go diff --git a/core/scripts/chaincli/handler/debug.go b/core/scripts/chaincli/handler/debug.go index 5947337b187..815a0c9a030 100644 --- a/core/scripts/chaincli/handler/debug.go +++ b/core/scripts/chaincli/handler/debug.go @@ -18,13 +18,19 @@ import ( gethcommon "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types" + evm21 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury" + "github.com/smartcontractkit/chainlink/core/scripts/chaincli/config" "github.com/smartcontractkit/chainlink/core/scripts/common" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_utils_2_1" iregistry21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1" + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/models" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/core" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams" @@ -35,12 +41,7 @@ import ( const ( ConditionTrigger uint8 = iota LogTrigger - - blockNumber = "blockNumber" expectedTypeAndVersion = "KeeperRegistry 2.1.0" - feedIdHex = "feedIdHex" - feedIDs = "feedIDs" - timestamp = "timestamp" ) var packer = encoding.NewAbiPacker() @@ -51,24 +52,29 @@ func (k *Keeper) Debug(ctx context.Context, args []string) { if len(args) < 1 { failCheckArgs("no upkeepID supplied", nil) } + // test that we are connected to an archive node _, err := k.client.BalanceAt(ctx, gethcommon.Address{}, big.NewInt(1)) if err != nil { failCheckConfig("you are not connected to an archive node; try using infura or alchemy", err) } + chainIDBig, err := k.client.ChainID(ctx) if err != nil { failUnknown("unable to retrieve chainID from rpc client", err) } chainID := chainIDBig.Int64() + + var triggerCallOpts *bind.CallOpts // use latest block for conditionals, but use block from tx for log triggers + latestCallOpts := &bind.CallOpts{Context: ctx} // always use latest block + // connect to registry contract - latestCallOpts := &bind.CallOpts{Context: ctx} // always use latest block - triggerCallOpts := &bind.CallOpts{Context: ctx} // use latest block for conditionals, but use block from tx for log triggers registryAddress := gethcommon.HexToAddress(k.cfg.RegistryAddress) keeperRegistry21, err := iregistry21.NewIKeeperRegistryMaster(registryAddress, k.client) if err != nil { failUnknown("failed to connect to registry contract", err) } + // verify contract is correct typeAndVersion, err := keeperRegistry21.TypeAndVersion(latestCallOpts) if err != nil { @@ -124,17 +130,21 @@ func (k *Keeper) Debug(ctx context.Context, args []string) { var checkResult iregistry21.CheckUpkeep var blockNum uint64 var performData []byte + var workID [32]byte + var trigger ocr2keepers.Trigger upkeepNeeded := false // check upkeep if triggerType == ConditionTrigger { message("upkeep identified as conditional trigger") - tmpCheckResult, err := keeperRegistry21.CheckUpkeep0(latestCallOpts, upkeepID) + var tmpCheckResult iregistry21.CheckUpkeep0 + tmpCheckResult, err = keeperRegistry21.CheckUpkeep0(latestCallOpts, upkeepID) if err != nil { failUnknown("failed to check upkeep: ", err) } checkResult = iregistry21.CheckUpkeep(tmpCheckResult) // do tenderly simulation - rawCall, err := core.RegistryABI.Pack("checkUpkeep", upkeepID, []byte{}) + var rawCall []byte + rawCall, err = core.RegistryABI.Pack("checkUpkeep", upkeepID, []byte{}) if err != nil { failUnknown("failed to pack raw checkUpkeep call", err) } @@ -146,19 +156,26 @@ func (k *Keeper) Debug(ctx context.Context, args []string) { failCheckArgs("txHash and log index must be supplied to command in order to debug log triggered upkeeps", nil) } txHash := gethcommon.HexToHash(args[1]) - logIndex, err := strconv.ParseInt(args[2], 10, 64) + + var logIndex int64 + logIndex, err = strconv.ParseInt(args[2], 10, 64) if err != nil { failCheckArgs("unable to parse log index", err) } - // find transaction receipt - _, isPending, err := k.client.TransactionByHash(ctx, txHash) + + // check that tx is confirmed + var isPending bool + _, isPending, err = k.client.TransactionByHash(ctx, txHash) if err != nil { log.Fatal("failed to get tx by hash", err) } if isPending { resolveIneligible(fmt.Sprintf("tx %s is still pending confirmation", txHash)) } - receipt, err := k.client.TransactionReceipt(ctx, txHash) + + // find transaction receipt + var receipt *types.Receipt + receipt, err = k.client.TransactionReceipt(ctx, txHash) if err != nil { failCheckArgs("failed to fetch tx receipt", err) } @@ -176,9 +193,11 @@ func (k *Keeper) Debug(ctx context.Context, args []string) { } // check that tx for this upkeep / tx was not already performed message(fmt.Sprintf("LogTrigger{blockNum: %d, blockHash: %s, txHash: %s, logIndex: %d}", blockNum, receipt.BlockHash.Hex(), txHash, logIndex)) - workID := mustUpkeepWorkID(upkeepID, blockNum, receipt.BlockHash, txHash, logIndex) + trigger = mustAutomationTrigger(txHash, logIndex, blockNum, receipt.BlockHash) + workID = mustUpkeepWorkID(upkeepID, trigger) message(fmt.Sprintf("workID computed: %s", hex.EncodeToString(workID[:]))) - hasKey, err := keeperRegistry21.HasDedupKey(latestCallOpts, workID) + var hasKey bool + hasKey, err = keeperRegistry21.HasDedupKey(latestCallOpts, workID) if err != nil { failUnknown("failed to check if upkeep was already performed: ", err) } @@ -186,11 +205,13 @@ func (k *Keeper) Debug(ctx context.Context, args []string) { resolveIneligible("upkeep was already performed") } triggerCallOpts = &bind.CallOpts{Context: ctx, BlockNumber: big.NewInt(receipt.BlockNumber.Int64())} - rawTriggerConfig, err := keeperRegistry21.GetUpkeepTriggerConfig(triggerCallOpts, upkeepID) + var rawTriggerConfig []byte + rawTriggerConfig, err = keeperRegistry21.GetUpkeepTriggerConfig(triggerCallOpts, upkeepID) if err != nil { failUnknown("failed to fetch trigger config for upkeep", err) } - triggerConfig, err := packer.UnpackLogTriggerConfig(rawTriggerConfig) + var triggerConfig automation_utils_2_1.LogTriggerConfig + triggerConfig, err = packer.UnpackLogTriggerConfig(rawTriggerConfig) if err != nil { failUnknown("failed to unpack trigger config", err) } @@ -200,11 +221,13 @@ func (k *Keeper) Debug(ctx context.Context, args []string) { if !logMatchesTriggerConfig(triggeringEvent, triggerConfig) { resolveIneligible("log does not match trigger config") } - header, err := k.client.HeaderByHash(ctx, receipt.BlockHash) + var header *types.Header + header, err = k.client.HeaderByHash(ctx, receipt.BlockHash) if err != nil { failUnknown("failed to find block", err) } - triggerData, err := packTriggerData(triggeringEvent, header.Time) + var triggerData []byte + triggerData, err = packTriggerData(triggeringEvent, header.Time) if err != nil { failUnknown("failed to pack trigger data", err) } @@ -213,7 +236,8 @@ func (k *Keeper) Debug(ctx context.Context, args []string) { failUnknown("failed to check upkeep", err) } // do tenderly simulations - rawCall, err := core.RegistryABI.Pack("checkUpkeep", upkeepID, triggerData) + var rawCall []byte + rawCall, err = core.RegistryABI.Pack("checkUpkeep", upkeepID, triggerData) if err != nil { failUnknown("failed to pack raw checkUpkeep call", err) } @@ -228,73 +252,88 @@ func (k *Keeper) Debug(ctx context.Context, args []string) { if checkResult.UpkeepFailureReason != 0 { message(fmt.Sprintf("checkUpkeep failed with UpkeepFailureReason %d", checkResult.UpkeepFailureReason)) } + if checkResult.UpkeepFailureReason == uint8(encoding.UpkeepFailureReasonTargetCheckReverted) { - // TODO use the new streams lookup lib - //mc := &models.MercuryCredentials{k.cfg.MercuryLegacyURL, k.cfg.MercuryURL, k.cfg.MercuryID, k.cfg.MercuryKey} - //mercuryConfig := evm.NewMercuryConfig(mc, core.StreamsCompatibleABI) - //lggr, _ := logger.NewLogger() - //blockSub := &blockSubscriber{k.client} - //_ = streams.NewStreamsLookup(packer, mercuryConfig, blockSub, keeperRegistry21, k.rpcClient, lggr) - - streamsLookupErr, err := packer.DecodeStreamsLookupRequest(checkResult.PerformData) + mc := &models.MercuryCredentials{LegacyURL: k.cfg.MercuryLegacyURL, URL: k.cfg.MercuryURL, Username: k.cfg.MercuryID, Password: k.cfg.MercuryKey} + mercuryConfig := evm21.NewMercuryConfig(mc, core.StreamsCompatibleABI) + lggr, _ := logger.NewLogger() + blockSub := &blockSubscriber{k.client} + streams := streams.NewStreamsLookup(packer, mercuryConfig, blockSub, k.rpcClient, keeperRegistry21, lggr) + + var streamsLookupErr *mercury.StreamsLookupError + streamsLookupErr, err = packer.DecodeStreamsLookupRequest(checkResult.PerformData) if err == nil { message("upkeep reverted with StreamsLookup") message(fmt.Sprintf("StreamsLookup data: {FeedParamKey: %s, Feeds: %v, TimeParamKey: %s, Time: %d, ExtraData: %s}", streamsLookupErr.FeedParamKey, streamsLookupErr.Feeds, streamsLookupErr.TimeParamKey, streamsLookupErr.Time.Uint64(), hexutil.Encode(streamsLookupErr.ExtraData))) - if streamsLookupErr.FeedParamKey == feedIdHex && streamsLookupErr.TimeParamKey == blockNumber { + + streamsLookup := &mercury.StreamsLookup{ + StreamsLookupError: &mercury.StreamsLookupError{ + FeedParamKey: streamsLookupErr.FeedParamKey, + Feeds: streamsLookupErr.Feeds, + TimeParamKey: streamsLookupErr.TimeParamKey, + Time: streamsLookupErr.Time, + ExtraData: streamsLookupErr.ExtraData, + }, + UpkeepId: upkeepID, + Block: blockNum, + } + + if streamsLookup.IsMercuryV02() { message("using mercury lookup v0.2") - // handle v0.2 - cfg, err := keeperRegistry21.GetUpkeepPrivilegeConfig(triggerCallOpts, upkeepID) + // check if upkeep is allowed to use mercury v0.2 + var allowed bool + _, _, _, allowed, err = streams.AllowedToUseMercury(latestCallOpts, upkeepID) if err != nil { - failUnknown("failed to get upkeep privilege config ", err) - } - allowed := false - if len(cfg) > 0 { - var privilegeConfig streams.UpkeepPrivilegeConfig - if err := json.Unmarshal(cfg, &privilegeConfig); err != nil { - failUnknown("failed to unmarshal privilege config ", err) - } - allowed = privilegeConfig.MercuryEnabled + failUnknown("failed to check if upkeep is allowed to use mercury", err) } if !allowed { resolveIneligible("upkeep reverted with StreamsLookup but is not allowed to access streams") } - } else if streamsLookupErr.FeedParamKey != feedIDs || streamsLookupErr.TimeParamKey != timestamp { + } else if streamsLookup.IsMercuryV03() { // handle v0.3 - resolveIneligible("upkeep reverted with StreamsLookup but the configuration is invalid") - } else { message("using mercury lookup v0.3") + } else { + resolveIneligible("upkeep reverted with StreamsLookup but the configuration is invalid") } - streamsLookup := &StreamsLookup{streamsLookupErr.FeedParamKey, streamsLookupErr.Feeds, streamsLookupErr.TimeParamKey, streamsLookupErr.Time, streamsLookupErr.ExtraData, upkeepID, blockNum} if k.cfg.MercuryLegacyURL == "" || k.cfg.MercuryURL == "" || k.cfg.MercuryID == "" || k.cfg.MercuryKey == "" { failCheckConfig("Mercury configs not set properly, check your MERCURY_LEGACY_URL, MERCURY_URL, MERCURY_ID and MERCURY_KEY", nil) } - handler := NewMercuryLookupHandler(&MercuryCredentials{k.cfg.MercuryLegacyURL, k.cfg.MercuryURL, k.cfg.MercuryID, k.cfg.MercuryKey}, k.rpcClient) - state, failureReason, values, _, err := handler.doMercuryRequest(ctx, streamsLookup) - if failureReason == UpkeepFailureReasonInvalidRevertDataInput { + + // do mercury request + automationCheckResult := mustAutomationCheckResult(upkeepID, checkResult, trigger) + checkResults := []ocr2keepers.CheckResult{automationCheckResult} + + var values [][]byte + values, err = streams.DoMercuryRequest(ctx, streamsLookup, checkResults, 0) + + if automationCheckResult.IneligibilityReason == uint8(mercury.MercuryUpkeepFailureReasonInvalidRevertDataInput) { resolveIneligible("upkeep used invalid revert data") } - if state == InvalidMercuryRequest { + if automationCheckResult.PipelineExecutionState == uint8(mercury.InvalidMercuryRequest) { resolveIneligible("the mercury request data is invalid") } if err != nil { failCheckConfig("failed to do mercury request ", err) } - callbackResult, err := keeperRegistry21.CheckCallback(triggerCallOpts, upkeepID, values, streamsLookup.extraData) + + // do checkCallback + err = streams.CheckCallback(ctx, values, streamsLookup, checkResults, 0) if err != nil { failUnknown("failed to execute mercury callback ", err) } - if callbackResult.UpkeepFailureReason != 0 { - message(fmt.Sprintf("checkCallback failed with UpkeepFailureReason %d", checkResult.UpkeepFailureReason)) + if automationCheckResult.IneligibilityReason != 0 { + message(fmt.Sprintf("checkCallback failed with UpkeepFailureReason %d", automationCheckResult.IneligibilityReason)) } - upkeepNeeded, performData = callbackResult.UpkeepNeeded, callbackResult.PerformData - // do tenderly simulations - rawCall, err := core.RegistryABI.Pack("checkCallback", upkeepID, values, streamsLookup.extraData) + upkeepNeeded, performData = automationCheckResult.Eligible, automationCheckResult.PerformData + // do tenderly simulations for checkCallback + var rawCall []byte + rawCall, err = core.RegistryABI.Pack("checkCallback", upkeepID, values, streamsLookup.ExtraData) if err != nil { failUnknown("failed to pack raw checkCallback call", err) } addLink("checkCallback simulation", tenderlySimLink(k.cfg, chainID, blockNum, rawCall, registryAddress)) - rawCall, err = core.StreamsCompatibleABI.Pack("checkCallback", values, streamsLookup.extraData) + rawCall, err = core.StreamsCompatibleABI.Pack("checkCallback", values, streamsLookup.ExtraData) if err != nil { failUnknown("failed to pack raw checkCallback (direct) call", err) } @@ -316,6 +355,39 @@ func (k *Keeper) Debug(ctx context.Context, args []string) { } } +func mustAutomationCheckResult(upkeepID *big.Int, checkResult iregistry21.CheckUpkeep, trigger ocr2keepers.Trigger) ocr2keepers.CheckResult { + upkeepIdentifier := mustUpkeepIdentifier(upkeepID) + checkResult2 := ocr2keepers.CheckResult{ + Eligible: checkResult.UpkeepNeeded, + IneligibilityReason: checkResult.UpkeepFailureReason, + UpkeepID: upkeepIdentifier, + Trigger: trigger, + WorkID: core.UpkeepWorkID(upkeepIdentifier, trigger), + GasAllocated: 0, + PerformData: checkResult.PerformData, + FastGasWei: checkResult.FastGasWei, + LinkNative: checkResult.LinkNative, + } + + return checkResult2 +} + +type blockSubscriber struct { + ethClient *ethclient.Client +} + +func (bs *blockSubscriber) LatestBlock() *ocr2keepers.BlockKey { + header, err := bs.ethClient.HeaderByNumber(context.Background(), nil) + if err != nil { + return nil + } + + return &ocr2keepers.BlockKey{ + Number: ocr2keepers.BlockNumber(header.Number.Uint64()), + Hash: header.Hash(), + } +} + func logMatchesTriggerConfig(log *types.Log, config automation_utils_2_1.LogTriggerConfig) bool { if log.Topics[0] != config.Topic0 { return false @@ -353,9 +425,27 @@ func packTriggerData(log *types.Log, blockTime uint64) ([]byte, error) { return b, nil } -func mustUpkeepWorkID(upkeepID *big.Int, blockNum uint64, blockHash [32]byte, txHash [32]byte, logIndex int64) [32]byte { - // TODO - this is a copy of the code in core.UpkeepWorkID - // We should refactor that code to be more easily exported ex not rely on Trigger structs +func mustUpkeepWorkID(upkeepID *big.Int, trigger ocr2keepers.Trigger) [32]byte { + upkeepIdentifier := mustUpkeepIdentifier(upkeepID) + + workID := core.UpkeepWorkID(upkeepIdentifier, trigger) + workIDBytes, err := hex.DecodeString(workID) + if err != nil { + failUnknown("failed to decode workID", err) + } + + var result [32]byte + copy(result[:], workIDBytes[:]) + return result +} + +func mustUpkeepIdentifier(upkeepID *big.Int) ocr2keepers.UpkeepIdentifier { + upkeepIdentifier := &ocr2keepers.UpkeepIdentifier{} + upkeepIdentifier.FromBigInt(upkeepID) + return *upkeepIdentifier +} + +func mustAutomationTrigger(txHash [32]byte, logIndex int64, blockNum uint64, blockHash [32]byte) ocr2keepers.Trigger { trigger := ocr2keepers.Trigger{ LogTriggerExtension: &ocr2keepers.LogTriggerExtension{ TxHash: txHash, @@ -364,16 +454,7 @@ func mustUpkeepWorkID(upkeepID *big.Int, blockNum uint64, blockHash [32]byte, tx BlockHash: blockHash, }, } - upkeepIdentifier := &ocr2keepers.UpkeepIdentifier{} - upkeepIdentifier.FromBigInt(upkeepID) - workID := core.UpkeepWorkID(*upkeepIdentifier, trigger) - workIDBytes, err := hex.DecodeString(workID) - if err != nil { - failUnknown("failed to decode workID", err) - } - var result [32]byte - copy(result[:], workIDBytes[:]) - return result + return trigger } func message(msg string) { @@ -385,11 +466,11 @@ func warning(msg string) { } func resolveIneligible(msg string) { - exit(fmt.Sprintf("✅ %s: this upkeep is not currently elligible", msg), nil, 0) + exit(fmt.Sprintf("✅ %s: this upkeep is not currently eligible", msg), nil, 0) } func resolveEligible() { - exit("❌ this upkeep is currently elligible", nil, 0) + exit("❌ this upkeep is currently eligible", nil, 0) } func rerun(msg string, err error) { @@ -490,5 +571,3 @@ func tenderlySimLink(cfg *config.Config, chainID int64, blockNumber uint64, inpu } return common.TenderlySimLink(responseJSON.Simulation.Id) } - -// TODO - link to performUpkeep tx if exists diff --git a/core/scripts/chaincli/handler/mercury_lookup_handler.go b/core/scripts/chaincli/handler/mercury_lookup_handler.go deleted file mode 100644 index 1165d83921d..00000000000 --- a/core/scripts/chaincli/handler/mercury_lookup_handler.go +++ /dev/null @@ -1,536 +0,0 @@ -package handler - -import ( - "context" - "crypto/hmac" - "crypto/sha256" - "encoding/hex" - "encoding/json" - "fmt" - "io" - "math/big" - "net/http" - "net/url" - "strconv" - "strings" - "time" - - "github.com/avast/retry-go" - ethabi "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/rpc" - "github.com/pkg/errors" -) - -// MercuryLookupHandler is responsible for initiating the calls to the Mercury server -// to determine whether the upkeeps are eligible -type MercuryLookupHandler struct { - credentials *MercuryCredentials - httpClient HttpClient - rpcClient *rpc.Client -} - -func NewMercuryLookupHandler( - credentials *MercuryCredentials, - rpcClient *rpc.Client, -) *MercuryLookupHandler { - return &MercuryLookupHandler{ - credentials: credentials, - httpClient: http.DefaultClient, - rpcClient: rpcClient, - } -} - -type MercuryVersion string - -type StreamsLookup struct { - feedParamKey string - feeds []string - timeParamKey string - time *big.Int - extraData []byte - upkeepId *big.Int - block uint64 -} - -//go:generate mockery --quiet --name HttpClient --output ./mocks/ --case=underscore -type HttpClient interface { - Do(req *http.Request) (*http.Response, error) -} - -type MercuryCredentials struct { - LegacyURL string - URL string - ClientID string - ClientKey string -} - -func (mc *MercuryCredentials) Validate() bool { - return mc.URL != "" && mc.ClientID != "" && mc.ClientKey != "" -} - -type MercuryData struct { - Index int - Error error - Retryable bool - Bytes [][]byte - State PipelineExecutionState -} - -// MercuryV02Response represents a JSON structure used by Mercury v0.2 -type MercuryV02Response struct { - ChainlinkBlob string `json:"chainlinkBlob"` -} - -// MercuryV03Response represents a JSON structure used by Mercury v0.3 -type MercuryV03Response struct { - Reports []MercuryV03Report `json:"reports"` -} - -type MercuryV03Report struct { - FeedID string `json:"feedID"` // feed id in hex encoded - ValidFromTimestamp uint32 `json:"validFromTimestamp"` - ObservationsTimestamp uint32 `json:"observationsTimestamp"` - FullReport string `json:"fullReport"` // the actual hex encoded mercury report of this feed, can be sent to verifier -} - -const ( - // DefaultAllowListExpiration decides how long an upkeep's allow list info will be valid for. - DefaultAllowListExpiration = 20 * time.Minute - // CleanupInterval decides when the expired items in cache will be deleted. - CleanupInterval = 25 * time.Minute -) - -const ( - ApplicationJson = "application/json" - BlockNumber = "blockNumber" // valid for v0.2 - FeedIDs = "feedIDs" // valid for v0.3 - FeedIdHex = "feedIdHex" // valid for v0.2 - HeaderAuthorization = "Authorization" - HeaderContentType = "Content-Type" - HeaderTimestamp = "X-Authorization-Timestamp" - HeaderSignature = "X-Authorization-Signature-SHA256" - HeaderUpkeepId = "X-Authorization-Upkeep-Id" - MercuryPathV2 = "/client?" // only used to access mercury v0.2 server - MercuryBatchPathV3 = "/api/v1/reports/bulk?" // only used to access mercury v0.3 server - RetryDelay = 500 * time.Millisecond - Timestamp = "timestamp" // valid for v0.3 - TotalAttempt = 3 - UserId = "userId" -) - -type UpkeepFailureReason uint8 -type PipelineExecutionState uint8 - -const ( - // upkeep failure onchain reasons - UpkeepFailureReasonNone UpkeepFailureReason = 0 - UpkeepFailureReasonUpkeepCancelled UpkeepFailureReason = 1 - UpkeepFailureReasonUpkeepPaused UpkeepFailureReason = 2 - UpkeepFailureReasonTargetCheckReverted UpkeepFailureReason = 3 - UpkeepFailureReasonUpkeepNotNeeded UpkeepFailureReason = 4 - UpkeepFailureReasonPerformDataExceedsLimit UpkeepFailureReason = 5 - UpkeepFailureReasonInsufficientBalance UpkeepFailureReason = 6 - UpkeepFailureReasonMercuryCallbackReverted UpkeepFailureReason = 7 - UpkeepFailureReasonRevertDataExceedsLimit UpkeepFailureReason = 8 - UpkeepFailureReasonRegistryPaused UpkeepFailureReason = 9 - // leaving a gap here for more onchain failure reasons in the future - // upkeep failure offchain reasons - UpkeepFailureReasonMercuryAccessNotAllowed UpkeepFailureReason = 32 - UpkeepFailureReasonTxHashNoLongerExists UpkeepFailureReason = 33 - UpkeepFailureReasonInvalidRevertDataInput UpkeepFailureReason = 34 - UpkeepFailureReasonSimulationFailed UpkeepFailureReason = 35 - UpkeepFailureReasonTxHashReorged UpkeepFailureReason = 36 - - // pipeline execution error - NoPipelineError PipelineExecutionState = 0 - CheckBlockTooOld PipelineExecutionState = 1 - CheckBlockInvalid PipelineExecutionState = 2 - RpcFlakyFailure PipelineExecutionState = 3 - MercuryFlakyFailure PipelineExecutionState = 4 - PackUnpackDecodeFailed PipelineExecutionState = 5 - MercuryUnmarshalError PipelineExecutionState = 6 - InvalidMercuryRequest PipelineExecutionState = 7 - InvalidMercuryResponse PipelineExecutionState = 8 // this will only happen if Mercury server sends bad responses - UpkeepNotAuthorized PipelineExecutionState = 9 -) - -// UpkeepPrivilegeConfig represents the administrative offchain config for each upkeep. It can be set by s_upkeepPrivilegeManager -// role on the registry. Upkeeps allowed to use Mercury server will have this set to true. -type UpkeepPrivilegeConfig struct { - MercuryEnabled bool `json:"mercuryEnabled"` -} - -// generateHMAC calculates a user HMAC for Mercury server authentication. -func (mlh *MercuryLookupHandler) generateHMAC(method string, path string, body []byte, clientId string, secret string, ts int64) string { - bodyHash := sha256.New() - bodyHash.Write(body) - hashString := fmt.Sprintf("%s %s %s %s %d", - method, - path, - hex.EncodeToString(bodyHash.Sum(nil)), - clientId, - ts) - signedMessage := hmac.New(sha256.New, []byte(secret)) - signedMessage.Write([]byte(hashString)) - userHmac := hex.EncodeToString(signedMessage.Sum(nil)) - return userHmac -} - -// singleFeedRequest sends a v0.2 Mercury request for a single feed report. -func (mlh *MercuryLookupHandler) singleFeedRequest(ctx context.Context, ch chan<- MercuryData, index int, ml *StreamsLookup) { - q := url.Values{ - ml.feedParamKey: {ml.feeds[index]}, - ml.timeParamKey: {ml.time.String()}, - } - mercuryURL := mlh.credentials.LegacyURL - reqUrl := fmt.Sprintf("%s%s%s", mercuryURL, MercuryPathV2, q.Encode()) - // mlh.logger.Debugf("request URL for upkeep %s feed %s: %s", ml.upkeepId.String(), ml.feeds[index], reqUrl) - - req, err := http.NewRequestWithContext(ctx, http.MethodGet, reqUrl, nil) - if err != nil { - ch <- MercuryData{Index: index, Error: err, Retryable: false, State: InvalidMercuryRequest} - return - } - - ts := time.Now().UTC().UnixMilli() - signature := mlh.generateHMAC(http.MethodGet, MercuryPathV2+q.Encode(), []byte{}, mlh.credentials.ClientID, mlh.credentials.ClientKey, ts) - req.Header.Set(HeaderContentType, ApplicationJson) - req.Header.Set(HeaderAuthorization, mlh.credentials.ClientID) - req.Header.Set(HeaderTimestamp, strconv.FormatInt(ts, 10)) - req.Header.Set(HeaderSignature, signature) - - // in the case of multiple retries here, use the last attempt's data - state := NoPipelineError - retryable := false - sent := false - retryErr := retry.Do( - func() error { - retryable = false - resp, err1 := mlh.httpClient.Do(req) - if err1 != nil { - // mlh.logger.Errorw("StreamsLookup GET request failed", "upkeepID", ml.upkeepId.String(), "time", ml.time.String(), "feed", ml.feeds[index], "error", err1) - retryable = true - state = MercuryFlakyFailure - return err1 - } - defer func(Body io.ReadCloser) { - err := Body.Close() - if err != nil { - _ = "" // placate linter - // mlh.logger.Errorf("Encountered error when closing the body of the response in single feed: %s", err) - } - }(resp.Body) - - body, err1 := io.ReadAll(resp.Body) - if err1 != nil { - retryable = false - state = InvalidMercuryResponse - return err1 - } - - if resp.StatusCode == http.StatusNotFound || resp.StatusCode == http.StatusInternalServerError { - // mlh.logger.Errorw("StreamsLookup received retryable status code", "upkeepID", ml.upkeepId.String(), "time", ml.time.String(), "statusCode", resp.StatusCode, "feed", ml.feeds[index]) - retryable = true - state = MercuryFlakyFailure - return errors.New(strconv.FormatInt(int64(resp.StatusCode), 10)) - } else if resp.StatusCode != http.StatusOK { - retryable = false - state = InvalidMercuryRequest - return fmt.Errorf("StreamsLookup upkeep %s block %s received status code %d for feed %s", ml.upkeepId.String(), ml.time.String(), resp.StatusCode, ml.feeds[index]) - } - - // mlh.logger.Debugf("at block %s upkeep %s received status code %d from mercury v0.2 with BODY=%s", ml.time.String(), ml.upkeepId.String(), resp.StatusCode, hexutil.Encode(body)) - - var m MercuryV02Response - err1 = json.Unmarshal(body, &m) - if err1 != nil { - // mlh.logger.Errorw("StreamsLookup failed to unmarshal body to MercuryResponse", "upkeepID", ml.upkeepId.String(), "time", ml.time.String(), "feed", ml.feeds[index], "error", err1) - retryable = false - state = MercuryUnmarshalError - return err1 - } - blobBytes, err1 := hexutil.Decode(m.ChainlinkBlob) - if err1 != nil { - // mlh.logger.Errorw("StreamsLookup failed to decode chainlinkBlob for feed", "upkeepID", ml.upkeepId.String(), "time", ml.time.String(), "blob", m.ChainlinkBlob, "feed", ml.feeds[index], "error", err1) - retryable = false - state = InvalidMercuryResponse - return err1 - } - ch <- MercuryData{ - Index: index, - Bytes: [][]byte{blobBytes}, - Retryable: false, - State: NoPipelineError, - } - sent = true - return nil - }, - // only retry when the error is 404 Not Found or 500 Internal Server Error - retry.RetryIf(func(err error) bool { - return err.Error() == fmt.Sprintf("%d", http.StatusNotFound) || err.Error() == fmt.Sprintf("%d", http.StatusInternalServerError) - }), - retry.Context(ctx), - retry.Delay(RetryDelay), - retry.Attempts(TotalAttempt)) - - if !sent { - md := MercuryData{ - Index: index, - Bytes: [][]byte{}, - Retryable: retryable, - Error: fmt.Errorf("failed to request feed for %s: %w", ml.feeds[index], retryErr), - State: state, - } - ch <- md - } -} - -// multiFeedsRequest sends a Mercury v0.3 request for a multi-feed report -func (mlh *MercuryLookupHandler) multiFeedsRequest(ctx context.Context, ch chan<- MercuryData, ml *StreamsLookup) { - params := fmt.Sprintf("%s=%s&%s=%s", FeedIDs, strings.Join(ml.feeds, ","), Timestamp, ml.time.String()) - reqUrl := fmt.Sprintf("%s%s%s", mlh.credentials.URL, MercuryBatchPathV3, params) - // mlh.logger.Debugf("request URL for upkeep %s userId %s: %s", ml.upkeepId.String(), mlh.credentials.ClientID, reqUrl) - - req, err := http.NewRequestWithContext(ctx, http.MethodGet, reqUrl, nil) - if err != nil { - ch <- MercuryData{Index: 0, Error: err, Retryable: false, State: InvalidMercuryRequest} - return - } - - ts := time.Now().UTC().UnixMilli() - signature := mlh.generateHMAC(http.MethodGet, MercuryBatchPathV3+params, []byte{}, mlh.credentials.ClientID, mlh.credentials.ClientKey, ts) - req.Header.Set(HeaderContentType, ApplicationJson) - // username here is often referred to as user id - req.Header.Set(HeaderAuthorization, mlh.credentials.ClientID) - req.Header.Set(HeaderTimestamp, strconv.FormatInt(ts, 10)) - req.Header.Set(HeaderSignature, signature) - // mercury will inspect authorization headers above to make sure this user (in automation's context, this node) is eligible to access mercury - // and if it has an automation role. it will then look at this upkeep id to check if it has access to all the requested feeds. - req.Header.Set(HeaderUpkeepId, ml.upkeepId.String()) - - // in the case of multiple retries here, use the last attempt's data - state := NoPipelineError - retryable := false - sent := false - retryErr := retry.Do( - func() error { - retryable = false - resp, err1 := mlh.httpClient.Do(req) - if err1 != nil { - // mlh.logger.Errorw("StreamsLookup GET request fails for multi feed", "upkeepID", ml.upkeepId.String(), "time", ml.time.String(), "error", err1) - retryable = true - state = MercuryFlakyFailure - return err1 - } - defer func(Body io.ReadCloser) { - err := Body.Close() - if err != nil { - _ = "" // placate linter - // mlh.logger.Errorf("Encountered error when closing the body of the response in the multi feed: %s", err) - } - }(resp.Body) - body, err1 := io.ReadAll(resp.Body) - if err1 != nil { - retryable = false - state = InvalidMercuryResponse - return err1 - } - - // mlh.logger.Infof("at timestamp %s upkeep %s received status code %d from mercury v0.3", ml.time.String(), ml.upkeepId.String(), resp.StatusCode) - if resp.StatusCode == http.StatusUnauthorized { - retryable = false - state = UpkeepNotAuthorized - return fmt.Errorf("at timestamp %s upkeep %s received status code %d from mercury v0.3, most likely this is caused by unauthorized upkeep", ml.time.String(), ml.upkeepId.String(), resp.StatusCode) - } else if resp.StatusCode == http.StatusBadRequest { - retryable = false - state = InvalidMercuryRequest - return fmt.Errorf("at timestamp %s upkeep %s received status code %d from mercury v0.3, most likely this is caused by invalid format of timestamp", ml.time.String(), ml.upkeepId.String(), resp.StatusCode) - } else if resp.StatusCode == http.StatusInternalServerError { - retryable = true - state = MercuryFlakyFailure - return fmt.Errorf("%d", http.StatusInternalServerError) - } else if resp.StatusCode == 420 { - // in 0.3, this will happen when missing/malformed query args, missing or bad required headers, non-existent feeds, or no permissions for feeds - retryable = false - state = InvalidMercuryRequest - return fmt.Errorf("at timestamp %s upkeep %s received status code %d from mercury v0.3, most likely this is caused by missing/malformed query args, missing or bad required headers, non-existent feeds, or no permissions for feeds", ml.time.String(), ml.upkeepId.String(), resp.StatusCode) - } else if resp.StatusCode != http.StatusOK { - retryable = false - state = InvalidMercuryRequest - return fmt.Errorf("at timestamp %s upkeep %s received status code %d from mercury v0.3", ml.time.String(), ml.upkeepId.String(), resp.StatusCode) - } - - var response MercuryV03Response - err1 = json.Unmarshal(body, &response) - if err1 != nil { - // mlh.logger.Errorw("StreamsLookup failed to unmarshal body to MercuryResponse for multi feed", "upkeepID", ml.upkeepId.String(), "time", ml.time.String(), "error", err1) - retryable = false - state = MercuryUnmarshalError - return err1 - } - // in v0.3, if some feeds are not available, the server will only return available feeds, but we need to make sure ALL feeds are retrieved before calling user contract - // hence, retry in this case. retry will help when we send a very new timestamp and reports are not yet generated - if len(response.Reports) != len(ml.feeds) { - // TODO: AUTO-5044: calculate what reports are missing and log a warning - retryable = true - state = MercuryFlakyFailure - return fmt.Errorf("%d", http.StatusNotFound) - } - var reportBytes [][]byte - for _, rsp := range response.Reports { - b, err := hexutil.Decode(rsp.FullReport) - if err != nil { - retryable = false - state = InvalidMercuryResponse - return err - } - reportBytes = append(reportBytes, b) - } - ch <- MercuryData{ - Index: 0, - Bytes: reportBytes, - Retryable: false, - State: NoPipelineError, - } - sent = true - return nil - }, - // only retry when the error is 404 Not Found or 500 Internal Server Error - retry.RetryIf(func(err error) bool { - return err.Error() == fmt.Sprintf("%d", http.StatusNotFound) || err.Error() == fmt.Sprintf("%d", http.StatusInternalServerError) - }), - retry.Context(ctx), - retry.Delay(RetryDelay), - retry.Attempts(TotalAttempt)) - - if !sent { - md := MercuryData{ - Index: 0, - Bytes: [][]byte{}, - Retryable: retryable, - Error: retryErr, - State: state, - } - ch <- md - } -} - -// doMercuryRequest sends requests to Mercury API to retrieve ChainlinkBlob. -func (mlh *MercuryLookupHandler) doMercuryRequest(ctx context.Context, ml *StreamsLookup) (PipelineExecutionState, UpkeepFailureReason, [][]byte, bool, error) { - var isMercuryV03 bool - resultLen := len(ml.feeds) - ch := make(chan MercuryData, resultLen) - if len(ml.feeds) == 0 { - return NoPipelineError, UpkeepFailureReasonInvalidRevertDataInput, nil, false, fmt.Errorf("invalid revert data input: feed param key %s, time param key %s, feeds %s", ml.feedParamKey, ml.timeParamKey, ml.feeds) - } - if ml.feedParamKey == FeedIdHex && ml.timeParamKey == BlockNumber { - // only v0.2 - for i := range ml.feeds { - go mlh.singleFeedRequest(ctx, ch, i, ml) - } - } else if ml.feedParamKey == FeedIDs && ml.timeParamKey == Timestamp { - // only v0.3 - resultLen = 1 - isMercuryV03 = true - ch = make(chan MercuryData, resultLen) - go mlh.multiFeedsRequest(ctx, ch, ml) - } else { - return NoPipelineError, UpkeepFailureReasonInvalidRevertDataInput, nil, false, fmt.Errorf("invalid revert data input: feed param key %s, time param key %s, feeds %s", ml.feedParamKey, ml.timeParamKey, ml.feeds) - } - - var reqErr error - results := make([][]byte, len(ml.feeds)) - retryable := true - allSuccess := true - // in v0.2, use the last execution error as the state, if no execution errors, state will be no error - state := NoPipelineError - for i := 0; i < resultLen; i++ { - m := <-ch - if m.Error != nil { - if reqErr == nil { - reqErr = errors.New(m.Error.Error()) - } else { - reqErr = errors.New(reqErr.Error() + m.Error.Error()) - } - retryable = retryable && m.Retryable - allSuccess = false - if m.State != NoPipelineError { - state = m.State - } - continue - } - if isMercuryV03 { - results = m.Bytes - } else { - results[m.Index] = m.Bytes[0] - } - } - // only retry when not all successful AND none are not retryable - return state, UpkeepFailureReasonNone, results, retryable && !allSuccess, reqErr -} - -// decodeStreamsLookup decodes the revert error StreamsLookup(string feedParamKey, string[] feeds, string timeParamKey, uint256 time, byte[] extraData) -// func (mlh *MercuryLookupHandler) decodeStreamsLookup(data []byte) (*StreamsLookup, error) { -// e := mlh.mercuryConfig.Abi.Errors["StreamsLookup"] -// unpack, err := e.Unpack(data) -// if err != nil { -// return nil, fmt.Errorf("unpack error: %w", err) -// } -// errorParameters := unpack.([]interface{}) - -// return &StreamsLookup{ -// feedParamKey: *abi.ConvertType(errorParameters[0], new(string)).(*string), -// feeds: *abi.ConvertType(errorParameters[1], new([]string)).(*[]string), -// timeParamKey: *abi.ConvertType(errorParameters[2], new(string)).(*string), -// time: *abi.ConvertType(errorParameters[3], new(*big.Int)).(**big.Int), -// extraData: *abi.ConvertType(errorParameters[4], new([]byte)).(*[]byte), -// }, nil -// } - -// allowedToUseMercury retrieves upkeep's administrative offchain config and decode a mercuryEnabled bool to indicate if -// this upkeep is allowed to use Mercury service. -// func (mlh *MercuryLookupHandler) allowedToUseMercury(upkeep models.Upkeep) (bool, error) { -// allowed, ok := mlh.mercuryConfig.AllowListCache.Get(upkeep.Admin.Hex()) -// if ok { -// return allowed.(bool), nil -// } - -// if upkeep.UpkeepPrivilegeConfig == nil { -// return false, fmt.Errorf("the upkeep privilege config was not retrieved for upkeep with ID %s", upkeep.UpkeepID) -// } - -// if len(upkeep.UpkeepPrivilegeConfig) == 0 { -// return false, fmt.Errorf("the upkeep privilege config is empty") -// } - -// var a UpkeepPrivilegeConfig -// err := json.Unmarshal(upkeep.UpkeepPrivilegeConfig, &a) -// if err != nil { -// return false, fmt.Errorf("failed to unmarshal privilege config for upkeep ID %s: %v", upkeep.UpkeepID, err) -// } - -// mlh.mercuryConfig.AllowListCache.Set(upkeep.Admin.Hex(), a.MercuryEnabled, cache.DefaultExpiration) -// return a.MercuryEnabled, nil -// } - -func (mlh *MercuryLookupHandler) CheckCallback(ctx context.Context, values [][]byte, lookup *StreamsLookup, registryABI ethabi.ABI, registryAddress common.Address) (hexutil.Bytes, error) { - payload, err := registryABI.Pack("checkCallback", lookup.upkeepId, values, lookup.extraData) - if err != nil { - return nil, err - } - - var theBytes hexutil.Bytes - args := map[string]interface{}{ - "to": registryAddress.Hex(), - "data": hexutil.Bytes(payload), - } - - // call checkCallback function at the block which OCR3 has agreed upon - err = mlh.rpcClient.CallContext(ctx, &theBytes, "eth_call", args, hexutil.EncodeUint64(lookup.block)) - if err != nil { - return nil, err - } - return theBytes, nil -} diff --git a/core/scripts/go.mod b/core/scripts/go.mod index db71535723e..895363a53f8 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -6,7 +6,6 @@ go 1.21.3 replace github.com/smartcontractkit/chainlink/v2 => ../../ require ( - github.com/avast/retry-go v3.0.0+incompatible github.com/docker/docker v24.0.7+incompatible github.com/docker/go-connections v0.4.0 github.com/ethereum/go-ethereum v1.12.0 @@ -18,7 +17,6 @@ require ( github.com/montanaflynn/stats v0.7.1 github.com/olekukonko/tablewriter v0.0.5 github.com/pelletier/go-toml/v2 v2.1.1 - github.com/pkg/errors v0.9.1 github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/chainlink-automation v1.0.1 github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 @@ -217,6 +215,7 @@ require ( github.com/patrickmn/go-cache v2.1.0+incompatible // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/pressly/goose/v3 v3.16.0 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 1c48074ea3a..dcf47d392cc 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -145,8 +145,6 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0= -github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY= github.com/avast/retry-go/v4 v4.5.1 h1:AxIx0HGi4VZ3I02jr78j5lZ3M6x1E0Ivxa6b0pUUh7o= github.com/avast/retry-go/v4 v4.5.1/go.mod h1:/sipNsvNB3RRuT5iNcb6h73nw3IBmXJ/H3XrCQYSOpc= github.com/aws/aws-sdk-go v1.22.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams/streams.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams/streams.go index 70db40c26bb..d64a9e7ef83 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams/streams.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams/streams.go @@ -16,7 +16,6 @@ import ( "github.com/patrickmn/go-cache" ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types" - "github.com/smartcontractkit/chainlink-common/pkg/services" iregistry21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1" @@ -131,7 +130,6 @@ func (s *streams) buildResult(ctx context.Context, i int, checkResult ocr2keeper // tried to call mercury lookupLggr.Infof("at block %d upkeep %s trying to DecodeStreamsLookupRequest performData=%s", block, upkeepId, hexutil.Encode(checkResults[i].PerformData)) streamsLookupErr, err := s.packer.DecodeStreamsLookupRequest(checkResult.PerformData) - if err != nil { lookupLggr.Debugf("at block %d upkeep %s DecodeStreamsLookupRequest failed: %v", block, upkeepId, err) // user contract did not revert with StreamsLookup error @@ -149,7 +147,7 @@ func (s *streams) buildResult(ctx context.Context, i int, checkResult ocr2keeper if streamsLookupResponse.IsMercuryV02() { // check permission on the registry for mercury v0.2 opts := s.buildCallOpts(ctx, block) - if state, reason, retryable, allowed, err := s.allowedToUseMercury(opts, upkeepId.BigInt()); err != nil { + if state, reason, retryable, allowed, err := s.AllowedToUseMercury(opts, upkeepId.BigInt()); err != nil { lookupLggr.Warnf("at block %s upkeep %s failed to query mercury allow list: %s", block, upkeepId, err) checkResults[i].PipelineExecutionState = uint8(state) checkResults[i].IneligibilityReason = uint8(reason) @@ -178,65 +176,93 @@ func (s *streams) buildResult(ctx context.Context, i int, checkResult ocr2keeper func (s *streams) doLookup(ctx context.Context, wg *sync.WaitGroup, lookup *mercury.StreamsLookup, i int, checkResults []ocr2keepers.CheckResult) { defer wg.Done() - state, reason, values, retryable, retryInterval, err := mercury.NoPipelineError, mercury.MercuryUpkeepFailureReasonInvalidRevertDataInput, [][]byte{}, false, 0*time.Second, fmt.Errorf("invalid revert data input: feed param key %s, time param key %s, feeds %s", lookup.FeedParamKey, lookup.TimeParamKey, lookup.Feeds) - pluginRetryKey := generatePluginRetryKey(checkResults[i].WorkID, lookup.Block) + values, err := s.DoMercuryRequest(ctx, lookup, checkResults, i) + if err != nil { + s.lggr.Errorf("at block %d upkeep %s requested time %s DoMercuryRequest err: %s", lookup.Block, lookup.UpkeepId, lookup.Time, err.Error()) + } - if lookup.IsMercuryV02() { - state, reason, values, retryable, retryInterval, err = s.v02Client.DoRequest(ctx, lookup, pluginRetryKey) - } else if lookup.IsMercuryV03() { - state, reason, values, retryable, retryInterval, err = s.v03Client.DoRequest(ctx, lookup, pluginRetryKey) + if err := s.CheckCallback(ctx, values, lookup, checkResults, i); err != nil { + s.lggr.Errorf("at block %d upkeep %s requested time %s CheckCallback err: %s", lookup.Block, lookup.UpkeepId, lookup.Time, err.Error()) } +} +func (s *streams) CheckCallback(ctx context.Context, values [][]byte, lookup *mercury.StreamsLookup, checkResults []ocr2keepers.CheckResult, i int) error { + payload, err := s.abi.Pack("checkCallback", lookup.UpkeepId, values, lookup.ExtraData) if err != nil { - s.lggr.Errorf("at block %d upkeep %s requested time %s retryable %v retryInterval %s doMercuryRequest: %s", lookup.Block, lookup.UpkeepId, lookup.Time, retryable, retryInterval, err.Error()) - checkResults[i].Retryable = retryable - checkResults[i].RetryInterval = retryInterval - checkResults[i].PipelineExecutionState = uint8(state) - checkResults[i].IneligibilityReason = uint8(reason) - return + checkResults[i].Retryable = false + checkResults[i].PipelineExecutionState = uint8(mercury.PackUnpackDecodeFailed) + return err } - for j, v := range values { - s.lggr.Infof("at block %d upkeep %s requested time %s doMercuryRequest values[%d]: %s", lookup.Block, lookup.UpkeepId, lookup.Time, j, hexutil.Encode(v)) + var mercuryBytes hexutil.Bytes + args := map[string]interface{}{ + "to": s.registry.Address().Hex(), + "data": hexutil.Bytes(payload), } - state, retryable, mercuryBytes, err := s.checkCallback(ctx, values, lookup) - if err != nil { - s.lggr.Errorf("at block %d upkeep %s checkCallback err: %s", lookup.Block, lookup.UpkeepId, err.Error()) - checkResults[i].Retryable = retryable - checkResults[i].PipelineExecutionState = uint8(state) - return + // call checkCallback function at the block which OCR3 has agreed upon + if err = s.client.CallContext(ctx, &mercuryBytes, "eth_call", args, hexutil.EncodeUint64(lookup.Block)); err != nil { + checkResults[i].Retryable = true + checkResults[i].PipelineExecutionState = uint8(mercury.RpcFlakyFailure) + return err } + s.lggr.Infof("at block %d upkeep %s requested time %s checkCallback mercuryBytes: %s", lookup.Block, lookup.UpkeepId, lookup.Time, hexutil.Encode(mercuryBytes)) unpackCallBackState, needed, performData, failureReason, _, err := s.packer.UnpackCheckCallbackResult(mercuryBytes) if err != nil { - s.lggr.Errorf("at block %d upkeep %s requested time %s UnpackCheckCallbackResult err: %s", lookup.Block, lookup.UpkeepId, lookup.Time, err.Error()) checkResults[i].PipelineExecutionState = unpackCallBackState - return + return err } if failureReason == uint8(mercury.MercuryUpkeepFailureReasonMercuryCallbackReverted) { checkResults[i].IneligibilityReason = uint8(mercury.MercuryUpkeepFailureReasonMercuryCallbackReverted) s.lggr.Debugf("at block %d upkeep %s requested time %s mercury callback reverts", lookup.Block, lookup.UpkeepId, lookup.Time) - return + return nil + } if !needed { checkResults[i].IneligibilityReason = uint8(mercury.MercuryUpkeepFailureReasonUpkeepNotNeeded) s.lggr.Debugf("at block %d upkeep %s requested time %s callback reports upkeep not needed", lookup.Block, lookup.UpkeepId, lookup.Time) - return + return nil } checkResults[i].IneligibilityReason = uint8(mercury.MercuryUpkeepFailureReasonNone) checkResults[i].Eligible = true checkResults[i].PerformData = performData s.lggr.Infof("at block %d upkeep %s requested time %s successful with perform data: %s", lookup.Block, lookup.UpkeepId, lookup.Time, hexutil.Encode(performData)) + + return nil } -// allowedToUseMercury retrieves upkeep's administrative offchain config and decode a mercuryEnabled bool to indicate if +func (s *streams) DoMercuryRequest(ctx context.Context, lookup *mercury.StreamsLookup, checkResults []ocr2keepers.CheckResult, i int) ([][]byte, error) { + state, reason, values, retryable, retryInterval, err := mercury.NoPipelineError, mercury.MercuryUpkeepFailureReasonInvalidRevertDataInput, [][]byte{}, false, 0*time.Second, fmt.Errorf("invalid revert data input: feed param key %s, time param key %s, feeds %s", lookup.FeedParamKey, lookup.TimeParamKey, lookup.Feeds) + pluginRetryKey := generatePluginRetryKey(checkResults[i].WorkID, lookup.Block) + + if lookup.IsMercuryV02() { + state, reason, values, retryable, retryInterval, err = s.v02Client.DoRequest(ctx, lookup, pluginRetryKey) + } else if lookup.IsMercuryV03() { + state, reason, values, retryable, retryInterval, err = s.v03Client.DoRequest(ctx, lookup, pluginRetryKey) + } + + if err != nil { + checkResults[i].Retryable = retryable + checkResults[i].RetryInterval = retryInterval + checkResults[i].PipelineExecutionState = uint8(state) + checkResults[i].IneligibilityReason = uint8(reason) + return nil, err + } + + for j, v := range values { + s.lggr.Infof("at block %d upkeep %s requested time %s doMercuryRequest values[%d]: %s", lookup.Block, lookup.UpkeepId, lookup.Time, j, hexutil.Encode(v)) + } + return values, nil +} + +// AllowedToUseMercury retrieves upkeep's administrative offchain config and decode a mercuryEnabled bool to indicate if // this upkeep is allowed to use Mercury service. -func (s *streams) allowedToUseMercury(opts *bind.CallOpts, upkeepId *big.Int) (state mercury.MercuryUpkeepState, reason mercury.MercuryUpkeepFailureReason, retryable bool, allow bool, err error) { +func (s *streams) AllowedToUseMercury(opts *bind.CallOpts, upkeepId *big.Int) (state mercury.MercuryUpkeepState, reason mercury.MercuryUpkeepFailureReason, retryable bool, allow bool, err error) { allowed, ok := s.mercuryConfig.IsUpkeepAllowed(upkeepId.String()) if ok { return mercury.NoPipelineError, mercury.MercuryUpkeepFailureReasonNone, false, allowed.(bool), nil @@ -256,7 +282,6 @@ func (s *streams) allowedToUseMercury(opts *bind.CallOpts, upkeepId *big.Int) (s "data": hexutil.Bytes(payload), } - // call checkCallback function at the block which OCR3 has agreed upon if err = s.client.CallContext(opts.Context, &resultBytes, "eth_call", args, hexutil.EncodeBig(opts.BlockNumber)); err != nil { return mercury.RpcFlakyFailure, mercury.MercuryUpkeepFailureReasonNone, true, false, fmt.Errorf("failed to get upkeep privilege config: %v", err) } @@ -282,26 +307,6 @@ func (s *streams) allowedToUseMercury(opts *bind.CallOpts, upkeepId *big.Int) (s return mercury.NoPipelineError, mercury.MercuryUpkeepFailureReasonNone, false, privilegeConfig.MercuryEnabled, nil } -func (s *streams) checkCallback(ctx context.Context, values [][]byte, lookup *mercury.StreamsLookup) (mercury.MercuryUpkeepState, bool, hexutil.Bytes, error) { - payload, err := s.abi.Pack("checkCallback", lookup.UpkeepId, values, lookup.ExtraData) - if err != nil { - return mercury.PackUnpackDecodeFailed, false, nil, err - } - - var b hexutil.Bytes - args := map[string]interface{}{ - "to": s.registry.Address().Hex(), - "data": hexutil.Bytes(payload), - } - - // call checkCallback function at the block which OCR3 has agreed upon - if err := s.client.CallContext(ctx, &b, "eth_call", args, hexutil.EncodeUint64(lookup.Block)); err != nil { - return mercury.RpcFlakyFailure, true, nil, err - } - - return mercury.NoPipelineError, false, b, nil -} - func (s *streams) buildCallOpts(ctx context.Context, block *big.Int) *bind.CallOpts { opts := bind.CallOpts{ Context: ctx, diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams/streams_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams/streams_test.go index 32041d0f18b..caa3efb974b 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams/streams_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams/streams_test.go @@ -127,6 +127,7 @@ func TestStreams_CheckCallback(t *testing.T) { tests := []struct { name string lookup *mercury.StreamsLookup + input []ocr2keepers.CheckResult values [][]byte statusCode int @@ -154,6 +155,9 @@ func TestStreams_CheckCallback(t *testing.T) { UpkeepId: upkeepId, Block: bn, }, + input: []ocr2keepers.CheckResult{ + {}, + }, values: values, statusCode: http.StatusOK, callbackResp: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 48, 120, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, @@ -186,6 +190,9 @@ func TestStreams_CheckCallback(t *testing.T) { UpkeepId: upkeepId, Block: bn, }, + input: []ocr2keepers.CheckResult{ + {}, + }, values: values, statusCode: http.StatusOK, callbackResp: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, @@ -217,6 +224,9 @@ func TestStreams_CheckCallback(t *testing.T) { UpkeepId: upkeepId, Block: bn, }, + input: []ocr2keepers.CheckResult{ + {}, + }, values: values, statusCode: http.StatusOK, callbackResp: []byte{}, @@ -256,10 +266,10 @@ func TestStreams_CheckCallback(t *testing.T) { }).Once() s.client = client - state, retryable, _, err := s.checkCallback(testutils.Context(t), tt.values, tt.lookup) - tt.wantErr(t, err, fmt.Sprintf("Error asserion failed: %v", tt.name)) - assert.Equal(t, tt.state, state) - assert.Equal(t, tt.retryable, retryable) + err = s.CheckCallback(testutils.Context(t), tt.values, tt.lookup, tt.input, 0) + tt.wantErr(t, err, fmt.Sprintf("Error assertion failed: %v", tt.name)) + assert.Equal(t, uint8(tt.state), tt.input[0].PipelineExecutionState) + assert.Equal(t, tt.retryable, tt.input[0].Retryable) }) } } @@ -435,7 +445,7 @@ func TestStreams_AllowedToUseMercury(t *testing.T) { BlockNumber: big.NewInt(10), } - state, reason, retryable, allowed, err := s.allowedToUseMercury(opts, upkeepId) + state, reason, retryable, allowed, err := s.AllowedToUseMercury(opts, upkeepId) assert.Equal(t, tt.err, err) assert.Equal(t, tt.allowed, allowed) assert.Equal(t, tt.state, state) From ee2996fa748812dc406fd6147d54f2c1e53a4ade Mon Sep 17 00:00:00 2001 From: Adam Hamrick Date: Wed, 13 Dec 2023 16:26:36 -0500 Subject: [PATCH 20/29] Adds MAKE Command for Building Plugin Image (#11567) --- integration-tests/Makefile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/integration-tests/Makefile b/integration-tests/Makefile index fb4bfa74f3e..86a266a996a 100644 --- a/integration-tests/Makefile +++ b/integration-tests/Makefile @@ -192,6 +192,12 @@ test_reorg_automation: ## Run the automation reorg tests build_docker_image: docker build -f ../core/chainlink.Dockerfile --build-arg COMMIT_SHA=$(git rev-parse HEAD) --build-arg CHAINLINK_USER=chainlink -t $(image):$(tag) ../ +# image: the name for the chainlink image being built, example: image=chainlink +# tag: the tag for the chainlink image being built, example: tag=latest +# example usage: make build_docker_image image=chainlink tag=latest +.PHONY: build_plugin_docker_image +build_docker_image: + docker build -f ../plugins/chainlink.Dockerfile --build-arg COMMIT_SHA=$(git rev-parse HEAD) --build-arg CHAINLINK_USER=chainlink -t localhost:5000/chainlink:develop ../ # image: the name for the chainlink image being built, example: image=chainlink # tag: the tag for the chainlink image being built, example: tag=latest From 8b2c48dbcdd31ed5defff930f66b8cc7a49b9817 Mon Sep 17 00:00:00 2001 From: Lei Date: Wed, 13 Dec 2023 14:42:33 -0800 Subject: [PATCH 21/29] Mercury Packer (#11521) * Refactor encoding.Packer to have Mercury control its own interface and function implementations * rebase and update --- core/scripts/chaincli/handler/debug.go | 37 ++-- .../evmregistry/v21/encoding/interface.go | 7 - .../evmregistry/v21/encoding/packer.go | 48 ----- .../evmregistry/v21/encoding/packer_test.go | 186 ----------------- .../evmregistry/v21/mercury/mercury.go | 75 ++++++- .../evmregistry/v21/mercury/mercury_test.go | 193 ++++++++++++++++++ .../v21/mercury/streams/streams.go | 6 +- .../v21/mercury/streams/streams_test.go | 2 - .../ocr2keeper/evmregistry/v21/registry.go | 3 +- 9 files changed, 290 insertions(+), 267 deletions(-) diff --git a/core/scripts/chaincli/handler/debug.go b/core/scripts/chaincli/handler/debug.go index 815a0c9a030..3e8bd6d597e 100644 --- a/core/scripts/chaincli/handler/debug.go +++ b/core/scripts/chaincli/handler/debug.go @@ -23,7 +23,6 @@ import ( ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types" evm21 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury" "github.com/smartcontractkit/chainlink/core/scripts/chaincli/config" "github.com/smartcontractkit/chainlink/core/scripts/common" @@ -33,6 +32,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/models" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/core" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams" "github.com/smartcontractkit/chainlink/v2/core/utils" bigmath "github.com/smartcontractkit/chainlink/v2/core/utils/big_math" @@ -44,6 +44,7 @@ const ( expectedTypeAndVersion = "KeeperRegistry 2.1.0" ) +var mercuryPacker = mercury.NewAbiPacker() var packer = encoding.NewAbiPacker() var links []string @@ -258,10 +259,10 @@ func (k *Keeper) Debug(ctx context.Context, args []string) { mercuryConfig := evm21.NewMercuryConfig(mc, core.StreamsCompatibleABI) lggr, _ := logger.NewLogger() blockSub := &blockSubscriber{k.client} - streams := streams.NewStreamsLookup(packer, mercuryConfig, blockSub, k.rpcClient, keeperRegistry21, lggr) + streams := streams.NewStreamsLookup(mercuryConfig, blockSub, k.rpcClient, keeperRegistry21, lggr) var streamsLookupErr *mercury.StreamsLookupError - streamsLookupErr, err = packer.DecodeStreamsLookupRequest(checkResult.PerformData) + streamsLookupErr, err = mercuryPacker.DecodeStreamsLookupRequest(checkResult.PerformData) if err == nil { message("upkeep reverted with StreamsLookup") message(fmt.Sprintf("StreamsLookup data: {FeedParamKey: %s, Feeds: %v, TimeParamKey: %s, Time: %d, ExtraData: %s}", streamsLookupErr.FeedParamKey, streamsLookupErr.Feeds, streamsLookupErr.TimeParamKey, streamsLookupErr.Time.Uint64(), hexutil.Encode(streamsLookupErr.ExtraData))) @@ -282,7 +283,7 @@ func (k *Keeper) Debug(ctx context.Context, args []string) { message("using mercury lookup v0.2") // check if upkeep is allowed to use mercury v0.2 var allowed bool - _, _, _, allowed, err = streams.AllowedToUseMercury(latestCallOpts, upkeepID) + _, _, _, allowed, err = streams.AllowedToUseMercury(triggerCallOpts, upkeepID) if err != nil { failUnknown("failed to check if upkeep is allowed to use mercury", err) } @@ -307,10 +308,10 @@ func (k *Keeper) Debug(ctx context.Context, args []string) { var values [][]byte values, err = streams.DoMercuryRequest(ctx, streamsLookup, checkResults, 0) - if automationCheckResult.IneligibilityReason == uint8(mercury.MercuryUpkeepFailureReasonInvalidRevertDataInput) { + if checkResults[0].IneligibilityReason == uint8(mercury.MercuryUpkeepFailureReasonInvalidRevertDataInput) { resolveIneligible("upkeep used invalid revert data") } - if automationCheckResult.PipelineExecutionState == uint8(mercury.InvalidMercuryRequest) { + if checkResults[0].PipelineExecutionState == uint8(mercury.InvalidMercuryRequest) { resolveIneligible("the mercury request data is invalid") } if err != nil { @@ -322,10 +323,10 @@ func (k *Keeper) Debug(ctx context.Context, args []string) { if err != nil { failUnknown("failed to execute mercury callback ", err) } - if automationCheckResult.IneligibilityReason != 0 { - message(fmt.Sprintf("checkCallback failed with UpkeepFailureReason %d", automationCheckResult.IneligibilityReason)) + if checkResults[0].IneligibilityReason != 0 { + message(fmt.Sprintf("checkCallback failed with UpkeepFailureReason %d", checkResults[0].IneligibilityReason)) } - upkeepNeeded, performData = automationCheckResult.Eligible, automationCheckResult.PerformData + upkeepNeeded, performData = checkResults[0].Eligible, checkResults[0].PerformData // do tenderly simulations for checkCallback var rawCall []byte rawCall, err = core.RegistryABI.Pack("checkCallback", upkeepID, values, streamsLookup.ExtraData) @@ -345,13 +346,23 @@ func (k *Keeper) Debug(ctx context.Context, args []string) { if !upkeepNeeded { resolveIneligible("upkeep is not needed") } - // simulate perform ukeep - simulateResult, err := keeperRegistry21.SimulatePerformUpkeep(latestCallOpts, upkeepID, performData) + // simulate perform upkeep + simulateResult, err := keeperRegistry21.SimulatePerformUpkeep(triggerCallOpts, upkeepID, performData) if err != nil { failUnknown("failed to simulate perform upkeep: ", err) } + + // do tenderly simulation + rawCall, err := core.RegistryABI.Pack("simulatePerformUpkeep", upkeepID, performData) + if err != nil { + failUnknown("failed to pack raw simulatePerformUpkeep call", err) + } + addLink("simulatePerformUpkeep simulation", tenderlySimLink(k.cfg, chainID, blockNum, rawCall, registryAddress)) + if simulateResult.Success { resolveEligible() + } else { + resolveIneligible("simulate perform upkeep unsuccessful") } } @@ -466,11 +477,11 @@ func warning(msg string) { } func resolveIneligible(msg string) { - exit(fmt.Sprintf("✅ %s: this upkeep is not currently eligible", msg), nil, 0) + exit(fmt.Sprintf("❌ this upkeep is not eligible: %s", msg), nil, 0) } func resolveEligible() { - exit("❌ this upkeep is currently eligible", nil, 0) + exit("✅ this upkeep is eligible", nil, 0) } func rerun(msg string, err error) { diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding/interface.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding/interface.go index 06a3e7b106b..ed3218ea405 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding/interface.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding/interface.go @@ -1,13 +1,10 @@ package encoding import ( - "math/big" - ocr2keepers "github.com/smartcontractkit/chainlink-automation/pkg/v3/types" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_utils_2_1" iregistry21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury" ) const ( @@ -51,12 +48,8 @@ type UpkeepInfo = iregistry21.KeeperRegistryBase21UpkeepInfo type Packer interface { UnpackCheckResult(payload ocr2keepers.UpkeepPayload, raw string) (ocr2keepers.CheckResult, error) - UnpackCheckCallbackResult(callbackResp []byte) (uint8, bool, []byte, uint8, *big.Int, error) UnpackPerformResult(raw string) (uint8, bool, error) UnpackLogTriggerConfig(raw []byte) (automation_utils_2_1.LogTriggerConfig, error) PackReport(report automation_utils_2_1.KeeperRegistryBase21Report) ([]byte, error) UnpackReport(raw []byte) (automation_utils_2_1.KeeperRegistryBase21Report, error) - PackGetUpkeepPrivilegeConfig(upkeepId *big.Int) ([]byte, error) - UnpackGetUpkeepPrivilegeConfig(resp []byte) ([]byte, error) - DecodeStreamsLookupRequest(data []byte) (*mercury.StreamsLookupError, error) } diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding/packer.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding/packer.go index 57013a6277a..4a92b4a17ec 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding/packer.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding/packer.go @@ -11,7 +11,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_utils_2_1" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/core" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury" ) // triggerWrapper is a wrapper for the different trigger types (log and condition triggers). @@ -67,35 +66,6 @@ func (p *abiPacker) UnpackCheckResult(payload ocr2keepers.UpkeepPayload, raw str return result, nil } -func (p *abiPacker) PackGetUpkeepPrivilegeConfig(upkeepId *big.Int) ([]byte, error) { - return p.registryABI.Pack("getUpkeepPrivilegeConfig", upkeepId) -} - -func (p *abiPacker) UnpackGetUpkeepPrivilegeConfig(resp []byte) ([]byte, error) { - out, err := p.registryABI.Methods["getUpkeepPrivilegeConfig"].Outputs.UnpackValues(resp) - if err != nil { - return nil, fmt.Errorf("%w: unpack getUpkeepPrivilegeConfig return", err) - } - - bts := *abi.ConvertType(out[0], new([]byte)).(*[]byte) - - return bts, nil -} - -func (p *abiPacker) UnpackCheckCallbackResult(callbackResp []byte) (uint8, bool, []byte, uint8, *big.Int, error) { - out, err := p.registryABI.Methods["checkCallback"].Outputs.UnpackValues(callbackResp) - if err != nil { - return PackUnpackDecodeFailed, false, nil, 0, nil, fmt.Errorf("%w: unpack checkUpkeep return: %s", err, hexutil.Encode(callbackResp)) - } - - upkeepNeeded := *abi.ConvertType(out[0], new(bool)).(*bool) - rawPerformData := *abi.ConvertType(out[1], new([]byte)).(*[]byte) - failureReason := *abi.ConvertType(out[2], new(uint8)).(*uint8) - gasUsed := *abi.ConvertType(out[3], new(*big.Int)).(**big.Int) - - return NoPipelineError, upkeepNeeded, rawPerformData, failureReason, gasUsed, nil -} - func (p *abiPacker) UnpackPerformResult(raw string) (uint8, bool, error) { b, err := hexutil.Decode(raw) if err != nil { @@ -163,24 +133,6 @@ func (p *abiPacker) UnpackReport(raw []byte) (automation_utils_2_1.KeeperRegistr return report, nil } -// DecodeStreamsLookupRequest decodes the revert error StreamsLookup(string feedParamKey, string[] feeds, string feedParamKey, uint256 time, byte[] extraData) -func (p *abiPacker) DecodeStreamsLookupRequest(data []byte) (*mercury.StreamsLookupError, error) { - e := p.streamsABI.Errors["StreamsLookup"] - unpack, err := e.Unpack(data) - if err != nil { - return nil, fmt.Errorf("unpack error: %w", err) - } - errorParameters := unpack.([]interface{}) - - return &mercury.StreamsLookupError{ - FeedParamKey: *abi.ConvertType(errorParameters[0], new(string)).(*string), - Feeds: *abi.ConvertType(errorParameters[1], new([]string)).(*[]string), - TimeParamKey: *abi.ConvertType(errorParameters[2], new(string)).(*string), - Time: *abi.ConvertType(errorParameters[3], new(*big.Int)).(**big.Int), - ExtraData: *abi.ConvertType(errorParameters[4], new([]byte)).(*[]byte), - }, nil -} - // GetIneligibleCheckResultWithoutPerformData returns an ineligible check result with ineligibility reason and pipeline execution state but without perform data func GetIneligibleCheckResultWithoutPerformData(p ocr2keepers.UpkeepPayload, reason uint8, state uint8, retryable bool) ocr2keepers.CheckResult { return ocr2keepers.CheckResult{ diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding/packer_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding/packer_test.go index 42fcd40d618..71c2755f150 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding/packer_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding/packer_test.go @@ -1,8 +1,6 @@ package encoding import ( - "encoding/json" - "errors" "fmt" "math/big" "testing" @@ -17,7 +15,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_utils_2_1" automation21Utils "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_utils_2_1" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/core" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury" ) func TestPacker_PackReport(t *testing.T) { @@ -231,62 +228,6 @@ func TestPacker_UnpackPerformResult(t *testing.T) { } } -func TestPacker_UnpackCheckCallbackResult(t *testing.T) { - tests := []struct { - Name string - CallbackResp []byte - UpkeepNeeded bool - PerformData []byte - FailureReason uint8 - GasUsed *big.Int - ErrorString string - State uint8 - }{ - { - Name: "unpack upkeep needed", - CallbackResp: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 10, 11, 21, 31, 41, 15, 16, 17, 18, 19, 13, 14, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 120, 111, 101, 122, 90, 54, 44, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - UpkeepNeeded: true, - PerformData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 10, 11, 21, 31, 41, 15, 16, 17, 18, 19, 13, 14, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 120, 111, 101, 122, 90, 54, 44, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - FailureReason: uint8(UpkeepFailureReasonNone), - GasUsed: big.NewInt(11796), - }, - { - Name: "unpack upkeep not needed", - CallbackResp: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 10, 11, 21, 31, 41, 15, 16, 17, 18, 19, 13, 14, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 120, 111, 101, 122, 90, 54, 44, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - UpkeepNeeded: false, - PerformData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 10, 11, 21, 31, 41, 15, 16, 17, 18, 19, 13, 14, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 120, 111, 101, 122, 90, 54, 44, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - FailureReason: uint8(UpkeepFailureReasonUpkeepNotNeeded), - GasUsed: big.NewInt(13008), - }, - { - Name: "unpack malformed data", - CallbackResp: []byte{0, 0, 0, 23, 4, 163, 66, 91, 228, 102, 200, 84, 144, 233, 218, 44, 168, 192, 191, 253, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - UpkeepNeeded: false, - PerformData: nil, - ErrorString: "abi: improperly encoded boolean value: unpack checkUpkeep return: ", - State: PackUnpackDecodeFailed, - }, - } - for _, test := range tests { - t.Run(test.Name, func(t *testing.T) { - packer := NewAbiPacker() - - state, needed, pd, failureReason, gasUsed, err := packer.UnpackCheckCallbackResult(test.CallbackResp) - - if test.ErrorString != "" { - assert.EqualError(t, err, test.ErrorString+hexutil.Encode(test.CallbackResp)) - } else { - assert.Nil(t, err) - } - assert.Equal(t, test.UpkeepNeeded, needed) - assert.Equal(t, test.PerformData, pd) - assert.Equal(t, test.FailureReason, failureReason) - assert.Equal(t, test.GasUsed, gasUsed) - assert.Equal(t, test.State, state) - }) - } -} - func TestPacker_UnpackLogTriggerConfig(t *testing.T) { tests := []struct { name string @@ -349,130 +290,3 @@ func TestPacker_PackReport_UnpackReport(t *testing.T) { expected := "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000040102030400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000405060708000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000004050607080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040102030400000000000000000000000000000000000000000000000000000000" assert.Equal(t, hexutil.Encode(res), expected) } - -func TestPacker_PackGetUpkeepPrivilegeConfig(t *testing.T) { - tests := []struct { - name string - upkeepId *big.Int - raw []byte - errored bool - }{ - { - name: "happy path", - upkeepId: func() *big.Int { - id, _ := new(big.Int).SetString("52236098515066839510538748191966098678939830769967377496848891145101407612976", 10) - - return id - }(), - raw: func() []byte { - b, _ := hexutil.Decode("0x19d97a94737c9583000000000000000000000001ea8ed6d0617dd5b3b87374020efaf030") - - return b - }(), - errored: false, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - packer := NewAbiPacker() - - b, err := packer.PackGetUpkeepPrivilegeConfig(test.upkeepId) - - if !test.errored { - require.NoError(t, err, "no error expected from packing") - - assert.Equal(t, test.raw, b, "raw bytes for output should match expected") - } else { - assert.NotNil(t, err, "error expected from packing function") - } - }) - } -} - -func TestPacker_UnpackGetUpkeepPrivilegeConfig(t *testing.T) { - tests := []struct { - name string - raw []byte - errored bool - }{ - { - name: "happy path", - raw: func() []byte { - b, _ := hexutil.Decode("0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000177b226d657263757279456e61626c6564223a747275657d000000000000000000") - - return b - }(), - errored: false, - }, - { - name: "error empty config", - raw: func() []byte { - b, _ := hexutil.Decode("0x") - - return b - }(), - errored: true, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - packer := NewAbiPacker() - - b, err := packer.UnpackGetUpkeepPrivilegeConfig(test.raw) - - if !test.errored { - require.NoError(t, err, "should unpack bytes from abi encoded value") - - // the actual struct to unmarshal into is not available to this - // package so basic json encoding is the limit of the following test - var data map[string]interface{} - err = json.Unmarshal(b, &data) - - assert.NoError(t, err, "packed data should unmarshal using json encoding") - assert.Equal(t, []byte(`{"mercuryEnabled":true}`), b) - } else { - assert.NotNil(t, err, "error expected from unpack function") - } - }) - } -} - -func TestPacker_DecodeStreamsLookupRequest(t *testing.T) { - tests := []struct { - name string - data []byte - expected *mercury.StreamsLookupError - state uint8 - err error - }{ - { - name: "success - decode to streams lookup", - data: hexutil.MustDecode("0xf055e4a200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000002435eb50000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000000966656564496448657800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000423078343535343438326435353533343432643431353234323439353435323535346432643534343535333534346534353534303030303030303030303030303030300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042307834323534343332643535353334343264343135323432343935343532353534643264353434353533353434653435353430303030303030303030303030303030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b626c6f636b4e756d62657200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000064000000000000000000000000"), - expected: &mercury.StreamsLookupError{ - FeedParamKey: "feedIdHex", - Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000", "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000"}, - TimeParamKey: "blockNumber", - Time: big.NewInt(37969589), - ExtraData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100}, - }, - }, - { - name: "failure - unpack error", - data: []byte{1, 2, 3, 4}, - err: errors.New("unpack error: invalid data for unpacking"), - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - packer := NewAbiPacker() - fl, err := packer.DecodeStreamsLookupRequest(tt.data) - assert.Equal(t, tt.expected, fl) - if tt.err != nil { - assert.Equal(t, tt.err.Error(), err.Error()) - } - }) - } -} diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/mercury.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/mercury.go index f9a3c001c66..10e77bf50ce 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/mercury.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/mercury.go @@ -10,9 +10,13 @@ import ( "net/http" "time" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/patrickmn/go-cache" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/models" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/core" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding" ) const ( @@ -68,13 +72,6 @@ type MercuryData struct { State MercuryUpkeepState } -type Packer interface { - UnpackCheckCallbackResult(callbackResp []byte) (uint8, bool, []byte, uint8, *big.Int, error) - PackGetUpkeepPrivilegeConfig(upkeepId *big.Int) ([]byte, error) - UnpackGetUpkeepPrivilegeConfig(resp []byte) ([]byte, error) - DecodeStreamsLookupRequest(data []byte) (*StreamsLookupError, error) -} - type MercuryConfigProvider interface { Credentials() *models.MercuryCredentials IsUpkeepAllowed(string) (interface{}, bool) @@ -113,6 +110,70 @@ func (l *StreamsLookup) IsMercuryV03() bool { return l.FeedParamKey == FeedIDs } +// IsMercuryV03UsingBlockNumber is used to distinguish the batch path. It is used for Mercury V03 only func (l *StreamsLookup) IsMercuryV03UsingBlockNumber() bool { return l.TimeParamKey == BlockNumber } + +type Packer interface { + UnpackCheckCallbackResult(callbackResp []byte) (uint8, bool, []byte, uint8, *big.Int, error) + PackGetUpkeepPrivilegeConfig(upkeepId *big.Int) ([]byte, error) + UnpackGetUpkeepPrivilegeConfig(resp []byte) ([]byte, error) + DecodeStreamsLookupRequest(data []byte) (*StreamsLookupError, error) +} + +type abiPacker struct { + registryABI abi.ABI + streamsABI abi.ABI +} + +func NewAbiPacker() *abiPacker { + return &abiPacker{registryABI: core.RegistryABI, streamsABI: core.StreamsCompatibleABI} +} + +// DecodeStreamsLookupRequest decodes the revert error StreamsLookup(string feedParamKey, string[] feeds, string feedParamKey, uint256 time, byte[] extraData) +func (p *abiPacker) DecodeStreamsLookupRequest(data []byte) (*StreamsLookupError, error) { + e := p.streamsABI.Errors["StreamsLookup"] + unpack, err := e.Unpack(data) + if err != nil { + return nil, fmt.Errorf("unpack error: %w", err) + } + errorParameters := unpack.([]interface{}) + + return &StreamsLookupError{ + FeedParamKey: *abi.ConvertType(errorParameters[0], new(string)).(*string), + Feeds: *abi.ConvertType(errorParameters[1], new([]string)).(*[]string), + TimeParamKey: *abi.ConvertType(errorParameters[2], new(string)).(*string), + Time: *abi.ConvertType(errorParameters[3], new(*big.Int)).(**big.Int), + ExtraData: *abi.ConvertType(errorParameters[4], new([]byte)).(*[]byte), + }, nil +} + +func (p *abiPacker) UnpackCheckCallbackResult(callbackResp []byte) (uint8, bool, []byte, uint8, *big.Int, error) { + out, err := p.registryABI.Methods["checkCallback"].Outputs.UnpackValues(callbackResp) + if err != nil { + return encoding.PackUnpackDecodeFailed, false, nil, 0, nil, fmt.Errorf("%w: unpack checkUpkeep return: %s", err, hexutil.Encode(callbackResp)) + } + + upkeepNeeded := *abi.ConvertType(out[0], new(bool)).(*bool) + rawPerformData := *abi.ConvertType(out[1], new([]byte)).(*[]byte) + failureReason := *abi.ConvertType(out[2], new(uint8)).(*uint8) + gasUsed := *abi.ConvertType(out[3], new(*big.Int)).(**big.Int) + + return encoding.NoPipelineError, upkeepNeeded, rawPerformData, failureReason, gasUsed, nil +} + +func (p *abiPacker) UnpackGetUpkeepPrivilegeConfig(resp []byte) ([]byte, error) { + out, err := p.registryABI.Methods["getUpkeepPrivilegeConfig"].Outputs.UnpackValues(resp) + if err != nil { + return nil, fmt.Errorf("%w: unpack getUpkeepPrivilegeConfig return", err) + } + + bts := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return bts, nil +} + +func (p *abiPacker) PackGetUpkeepPrivilegeConfig(upkeepId *big.Int) ([]byte, error) { + return p.registryABI.Pack("getUpkeepPrivilegeConfig", upkeepId) +} diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/mercury_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/mercury_test.go index baa939dbecc..6095e7b9466 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/mercury_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/mercury_test.go @@ -1,7 +1,17 @@ package mercury import ( + "encoding/json" + "errors" + "math/big" "testing" + + "github.com/stretchr/testify/require" + + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/stretchr/testify/assert" + + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding" ) func TestGenerateHMACFn(t *testing.T) { @@ -47,3 +57,186 @@ func TestGenerateHMACFn(t *testing.T) { }) } } + +func TestPacker_DecodeStreamsLookupRequest(t *testing.T) { + tests := []struct { + name string + data []byte + expected *StreamsLookupError + state uint8 + err error + }{ + { + name: "success - decode to streams lookup", + data: hexutil.MustDecode("0xf055e4a200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000002435eb50000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000000966656564496448657800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000423078343535343438326435353533343432643431353234323439353435323535346432643534343535333534346534353534303030303030303030303030303030300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042307834323534343332643535353334343264343135323432343935343532353534643264353434353533353434653435353430303030303030303030303030303030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b626c6f636b4e756d62657200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000064000000000000000000000000"), + expected: &StreamsLookupError{ + FeedParamKey: "feedIdHex", + Feeds: []string{"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000", "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000"}, + TimeParamKey: "blockNumber", + Time: big.NewInt(37969589), + ExtraData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100}, + }, + }, + { + name: "failure - unpack error", + data: []byte{1, 2, 3, 4}, + err: errors.New("unpack error: invalid data for unpacking"), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + packer := NewAbiPacker() + fl, err := packer.DecodeStreamsLookupRequest(tt.data) + assert.Equal(t, tt.expected, fl) + if tt.err != nil { + assert.Equal(t, tt.err.Error(), err.Error()) + } + }) + } +} + +func TestPacker_UnpackGetUpkeepPrivilegeConfig(t *testing.T) { + tests := []struct { + name string + raw []byte + errored bool + }{ + { + name: "happy path", + raw: func() []byte { + b, _ := hexutil.Decode("0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000177b226d657263757279456e61626c6564223a747275657d000000000000000000") + + return b + }(), + errored: false, + }, + { + name: "error empty config", + raw: func() []byte { + b, _ := hexutil.Decode("0x") + + return b + }(), + errored: true, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + packer := NewAbiPacker() + + b, err := packer.UnpackGetUpkeepPrivilegeConfig(test.raw) + + if !test.errored { + require.NoError(t, err, "should unpack bytes from abi encoded value") + + // the actual struct to unmarshal into is not available to this + // package so basic json encoding is the limit of the following test + var data map[string]interface{} + err = json.Unmarshal(b, &data) + + assert.NoError(t, err, "packed data should unmarshal using json encoding") + assert.Equal(t, []byte(`{"mercuryEnabled":true}`), b) + } else { + assert.NotNil(t, err, "error expected from unpack function") + } + }) + } +} + +func TestPacker_PackGetUpkeepPrivilegeConfig(t *testing.T) { + tests := []struct { + name string + upkeepId *big.Int + raw []byte + errored bool + }{ + { + name: "happy path", + upkeepId: func() *big.Int { + id, _ := new(big.Int).SetString("52236098515066839510538748191966098678939830769967377496848891145101407612976", 10) + + return id + }(), + raw: func() []byte { + b, _ := hexutil.Decode("0x19d97a94737c9583000000000000000000000001ea8ed6d0617dd5b3b87374020efaf030") + + return b + }(), + errored: false, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + packer := NewAbiPacker() + + b, err := packer.PackGetUpkeepPrivilegeConfig(test.upkeepId) + + if !test.errored { + require.NoError(t, err, "no error expected from packing") + + assert.Equal(t, test.raw, b, "raw bytes for output should match expected") + } else { + assert.NotNil(t, err, "error expected from packing function") + } + }) + } +} + +func TestPacker_UnpackCheckCallbackResult(t *testing.T) { + tests := []struct { + Name string + CallbackResp []byte + UpkeepNeeded bool + PerformData []byte + FailureReason uint8 + GasUsed *big.Int + ErrorString string + State uint8 + }{ + { + Name: "unpack upkeep needed", + CallbackResp: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 10, 11, 21, 31, 41, 15, 16, 17, 18, 19, 13, 14, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 120, 111, 101, 122, 90, 54, 44, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + UpkeepNeeded: true, + PerformData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 10, 11, 21, 31, 41, 15, 16, 17, 18, 19, 13, 14, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 120, 111, 101, 122, 90, 54, 44, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + FailureReason: uint8(encoding.UpkeepFailureReasonNone), + GasUsed: big.NewInt(11796), + }, + { + Name: "unpack upkeep not needed", + CallbackResp: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 10, 11, 21, 31, 41, 15, 16, 17, 18, 19, 13, 14, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 120, 111, 101, 122, 90, 54, 44, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + UpkeepNeeded: false, + PerformData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 10, 11, 21, 31, 41, 15, 16, 17, 18, 19, 13, 14, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 120, 111, 101, 122, 90, 54, 44, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + FailureReason: uint8(encoding.UpkeepFailureReasonUpkeepNotNeeded), + GasUsed: big.NewInt(13008), + }, + { + Name: "unpack malformed data", + CallbackResp: []byte{0, 0, 0, 23, 4, 163, 66, 91, 228, 102, 200, 84, 144, 233, 218, 44, 168, 192, 191, 253, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + UpkeepNeeded: false, + PerformData: nil, + ErrorString: "abi: improperly encoded boolean value: unpack checkUpkeep return: ", + State: encoding.PackUnpackDecodeFailed, + }, + } + for _, test := range tests { + t.Run(test.Name, func(t *testing.T) { + packer := NewAbiPacker() + + state, needed, pd, failureReason, gasUsed, err := packer.UnpackCheckCallbackResult(test.CallbackResp) + + if test.ErrorString != "" { + assert.EqualError(t, err, test.ErrorString+hexutil.Encode(test.CallbackResp)) + } else { + assert.Nil(t, err) + } + assert.Equal(t, test.UpkeepNeeded, needed) + assert.Equal(t, test.PerformData, pd) + assert.Equal(t, test.FailureReason, failureReason) + assert.Equal(t, test.GasUsed, gasUsed) + assert.Equal(t, test.State, state) + }) + } +} diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams/streams.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams/streams.go index d64a9e7ef83..e1bb69f33d8 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams/streams.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams/streams.go @@ -66,7 +66,6 @@ type UpkeepPrivilegeConfig struct { } func NewStreamsLookup( - packer mercury.Packer, mercuryConfig mercury.MercuryConfigProvider, blockSubscriber latestBlockProvider, client contextCaller, @@ -74,6 +73,8 @@ func NewStreamsLookup( lggr logger.Logger) *streams { httpClient := http.DefaultClient threadCtrl := utils.NewThreadControl() + packer := mercury.NewAbiPacker() + return &streams{ packer: packer, mercuryConfig: mercuryConfig, @@ -231,7 +232,7 @@ func (s *streams) CheckCallback(ctx context.Context, values [][]byte, lookup *me checkResults[i].IneligibilityReason = uint8(mercury.MercuryUpkeepFailureReasonNone) checkResults[i].Eligible = true checkResults[i].PerformData = performData - s.lggr.Infof("at block %d upkeep %s requested time %s successful with perform data: %s", lookup.Block, lookup.UpkeepId, lookup.Time, hexutil.Encode(performData)) + s.lggr.Infof("at block %d upkeep %s requested time %s CheckCallback successful with perform data: %s", lookup.Block, lookup.UpkeepId, lookup.Time, hexutil.Encode(performData)) return nil } @@ -288,6 +289,7 @@ func (s *streams) AllowedToUseMercury(opts *bind.CallOpts, upkeepId *big.Int) (s var upkeepPrivilegeConfigBytes []byte upkeepPrivilegeConfigBytes, err = s.packer.UnpackGetUpkeepPrivilegeConfig(resultBytes) + if err != nil { return mercury.PackUnpackDecodeFailed, mercury.MercuryUpkeepFailureReasonNone, false, false, fmt.Errorf("failed to get upkeep privilege config: %v", err) } diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams/streams_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams/streams_test.go index caa3efb974b..54124b7c1a3 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams/streams_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams/streams_test.go @@ -102,14 +102,12 @@ func (r *mockRegistry) CheckCallback(opts *bind.CallOpts, id *big.Int, values [] // setups up a streams object for tests. func setupStreams(t *testing.T) *streams { lggr := logger.TestLogger(t) - packer := encoding.NewAbiPacker() mercuryConfig := new(MockMercuryConfigProvider) blockSubscriber := new(MockBlockSubscriber) registry := &mockRegistry{} client := evmClientMocks.NewClient(t) streams := NewStreamsLookup( - packer, mercuryConfig, blockSubscriber, client, diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry.go index bb05b8029fe..39862bb7539 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry.go @@ -94,7 +94,6 @@ func NewEvmRegistry( AllowListCache: cache.New(defaultAllowListExpiration, cleanupInterval), pluginRetryCache: cache.New(defaultPluginRetryExpiration, cleanupInterval), } - hc := http.DefaultClient return &EvmRegistry{ @@ -115,7 +114,7 @@ func NewEvmRegistry( logEventProvider: logEventProvider, bs: blockSub, finalityDepth: finalityDepth, - streams: streams.NewStreamsLookup(packer, mercuryConfig, blockSub, client.Client(), registry, lggr), + streams: streams.NewStreamsLookup(mercuryConfig, blockSub, client.Client(), registry, lggr), } } From c274c23eabc7fade1b1a5e7649187c56f218cc77 Mon Sep 17 00:00:00 2001 From: Sri Kidambi <1702865+kidambisrinivas@users.noreply.github.com> Date: Wed, 13 Dec 2023 23:45:38 +0000 Subject: [PATCH 22/29] Introduce job spec flag for custom reverted pipeline (#11529) * Introduce job spec flag for custom reverted pipeline * Disable the flag for V2+ * Rename file after merge conflict --- core/services/job/job_orm_test.go | 21 +++-- core/services/job/models.go | 3 + core/services/job/orm.go | 4 +- core/services/job/validate.go | 1 + core/services/vrf/delegate.go | 3 + .../0214_add_custom_reverts_vrf.sql | 5 ++ core/testdata/testspecs/v2_specs.go | 3 + core/web/presenters/job.go | 38 ++++---- core/web/presenters/job_test.go | 87 +++++++++++++++++++ core/web/resolver/spec.go | 5 ++ core/web/resolver/spec_test.go | 3 + core/web/schema/type/spec.graphql | 1 + 12 files changed, 149 insertions(+), 25 deletions(-) create mode 100644 core/store/migrate/migrations/0214_add_custom_reverts_vrf.sql diff --git a/core/services/job/job_orm_test.go b/core/services/job/job_orm_test.go index c0622ba8066..768d16ddeb7 100644 --- a/core/services/job/job_orm_test.go +++ b/core/services/job/job_orm_test.go @@ -454,6 +454,9 @@ func TestORM_CreateJob_VRFV2(t *testing.T) { var batchFulfillmentEnabled bool require.NoError(t, db.Get(&batchFulfillmentEnabled, `SELECT batch_fulfillment_enabled FROM vrf_specs LIMIT 1`)) require.False(t, batchFulfillmentEnabled) + var customRevertsPipelineEnabled bool + require.NoError(t, db.Get(&customRevertsPipelineEnabled, `SELECT custom_reverts_pipeline_enabled FROM vrf_specs LIMIT 1`)) + require.False(t, customRevertsPipelineEnabled) var batchFulfillmentGasMultiplier float64 require.NoError(t, db.Get(&batchFulfillmentGasMultiplier, `SELECT batch_fulfillment_gas_multiplier FROM vrf_specs LIMIT 1`)) require.Equal(t, float64(1.0), batchFulfillmentGasMultiplier) @@ -514,13 +517,14 @@ func TestORM_CreateJob_VRFV2Plus(t *testing.T) { fromAddresses := []string{cltest.NewEIP55Address().String(), cltest.NewEIP55Address().String()} jb, err := vrfcommon.ValidatedVRFSpec(testspecs.GenerateVRFSpec( testspecs.VRFSpecParams{ - VRFVersion: vrfcommon.V2Plus, - RequestedConfsDelay: 10, - FromAddresses: fromAddresses, - ChunkSize: 25, - BackoffInitialDelay: time.Minute, - BackoffMaxDelay: time.Hour, - GasLanePrice: assets.GWei(100), + VRFVersion: vrfcommon.V2Plus, + RequestedConfsDelay: 10, + FromAddresses: fromAddresses, + ChunkSize: 25, + BackoffInitialDelay: time.Minute, + BackoffMaxDelay: time.Hour, + GasLanePrice: assets.GWei(100), + CustomRevertsPipelineEnabled: true, }). Toml()) require.NoError(t, err) @@ -534,6 +538,9 @@ func TestORM_CreateJob_VRFV2Plus(t *testing.T) { var batchFulfillmentEnabled bool require.NoError(t, db.Get(&batchFulfillmentEnabled, `SELECT batch_fulfillment_enabled FROM vrf_specs LIMIT 1`)) require.False(t, batchFulfillmentEnabled) + var customRevertsPipelineEnabled bool + require.NoError(t, db.Get(&customRevertsPipelineEnabled, `SELECT custom_reverts_pipeline_enabled FROM vrf_specs LIMIT 1`)) + require.True(t, customRevertsPipelineEnabled) var batchFulfillmentGasMultiplier float64 require.NoError(t, db.Get(&batchFulfillmentGasMultiplier, `SELECT batch_fulfillment_gas_multiplier FROM vrf_specs LIMIT 1`)) require.Equal(t, float64(1.0), batchFulfillmentGasMultiplier) diff --git a/core/services/job/models.go b/core/services/job/models.go index 3c869f76056..f60e0a12981 100644 --- a/core/services/job/models.go +++ b/core/services/job/models.go @@ -503,6 +503,9 @@ type VRFSpec struct { // for fulfilling requests. If set to true, batchCoordinatorAddress must be set in // the job spec. BatchFulfillmentEnabled bool `toml:"batchFulfillmentEnabled"` + // CustomRevertsPipelineEnabled indicates to the vrf job to run the + // custom reverted txns pipeline along with VRF listener + CustomRevertsPipelineEnabled bool `toml:"customRevertsPipelineEnabled"` // BatchFulfillmentGasMultiplier is used to determine the final gas estimate for the batch // fulfillment. BatchFulfillmentGasMultiplier tomlutils.Float64 `toml:"batchFulfillmentGasMultiplier"` diff --git a/core/services/job/orm.go b/core/services/job/orm.go index b2cf2b2af4b..6c5a879ebd0 100644 --- a/core/services/job/orm.go +++ b/core/services/job/orm.go @@ -326,14 +326,14 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { evm_chain_id, from_addresses, poll_period, requested_confs_delay, request_timeout, chunk_size, batch_coordinator_address, batch_fulfillment_enabled, batch_fulfillment_gas_multiplier, backoff_initial_delay, backoff_max_delay, gas_lane_price, - vrf_owner_address, + vrf_owner_address, custom_reverts_pipeline_enabled, created_at, updated_at) VALUES ( :coordinator_address, :public_key, :min_incoming_confirmations, :evm_chain_id, :from_addresses, :poll_period, :requested_confs_delay, :request_timeout, :chunk_size, :batch_coordinator_address, :batch_fulfillment_enabled, :batch_fulfillment_gas_multiplier, :backoff_initial_delay, :backoff_max_delay, :gas_lane_price, - :vrf_owner_address, + :vrf_owner_address, :custom_reverts_pipeline_enabled, NOW(), NOW()) RETURNING id;` diff --git a/core/services/job/validate.go b/core/services/job/validate.go index 8f559fdb02d..b7a1dca3616 100644 --- a/core/services/job/validate.go +++ b/core/services/job/validate.go @@ -63,6 +63,7 @@ func ValidateSpec(ts string) (Type, error) { if jb.Pipeline.RequiresPreInsert() && !jb.Type.SupportsAsync() { return "", errors.Errorf("async=true tasks are not supported for %v", jb.Type) } + // spec.CustomRevertsPipelineEnabled == false, default is custom reverted txns pipeline disabled if strings.Contains(ts, "<{}>") { return "", errors.Errorf("'<{}>' syntax is not supported. Please use \"{}\" instead") diff --git a/core/services/vrf/delegate.go b/core/services/vrf/delegate.go index 03e40614a10..ba28e83bf3f 100644 --- a/core/services/vrf/delegate.go +++ b/core/services/vrf/delegate.go @@ -142,6 +142,9 @@ func (d *Delegate) ServicesForSpec(jb job.Job) ([]job.ServiceCtx, error) { if vrfOwner != nil { return nil, errors.New("VRF Owner is not supported for VRF V2 Plus") } + if jb.VRFSpec.CustomRevertsPipelineEnabled { + return nil, errors.New("Custom Reverted Txns Pipeline is not supported for VRF V2 Plus") + } // Get the LINKNATIVEFEED address with retries // This is needed because the RPC endpoint may be down so we need to diff --git a/core/store/migrate/migrations/0214_add_custom_reverts_vrf.sql b/core/store/migrate/migrations/0214_add_custom_reverts_vrf.sql new file mode 100644 index 00000000000..a2865fce816 --- /dev/null +++ b/core/store/migrate/migrations/0214_add_custom_reverts_vrf.sql @@ -0,0 +1,5 @@ +-- +goose Up +ALTER TABLE vrf_specs ADD COLUMN custom_reverts_pipeline_enabled boolean DEFAULT FALSE NOT NULL; + +-- +goose Down +ALTER TABLE vrf_specs DROP COLUMN custom_reverts_pipeline_enabled; diff --git a/core/testdata/testspecs/v2_specs.go b/core/testdata/testspecs/v2_specs.go index 00297ebdb12..e9dd25fa0f7 100644 --- a/core/testdata/testspecs/v2_specs.go +++ b/core/testdata/testspecs/v2_specs.go @@ -234,6 +234,7 @@ type VRFSpecParams struct { BatchCoordinatorAddress string VRFOwnerAddress string BatchFulfillmentEnabled bool + CustomRevertsPipelineEnabled bool BatchFulfillmentGasMultiplier float64 MinIncomingConfirmations int FromAddresses []string @@ -403,6 +404,7 @@ evmChainID = "%s" batchCoordinatorAddress = "%s" batchFulfillmentEnabled = %v batchFulfillmentGasMultiplier = %s +customRevertsPipelineEnabled = %v minIncomingConfirmations = %d requestedConfsDelay = %d requestTimeout = "%s" @@ -419,6 +421,7 @@ observationSource = """ toml := fmt.Sprintf(template, jobID, name, coordinatorAddress, params.EVMChainID, batchCoordinatorAddress, params.BatchFulfillmentEnabled, strconv.FormatFloat(batchFulfillmentGasMultiplier, 'f', 2, 64), + params.CustomRevertsPipelineEnabled, confirmations, params.RequestedConfsDelay, requestTimeout.String(), publicKey, chunkSize, params.BackoffInitialDelay.String(), params.BackoffMaxDelay.String(), gasLanePrice.String(), pollPeriod.String(), observationSource) diff --git a/core/web/presenters/job.go b/core/web/presenters/job.go index a2a9e70c793..e9b63c73615 100644 --- a/core/web/presenters/job.go +++ b/core/web/presenters/job.go @@ -267,6 +267,7 @@ func NewCronSpec(spec *job.CronSpec) *CronSpec { type VRFSpec struct { BatchCoordinatorAddress *ethkey.EIP55Address `json:"batchCoordinatorAddress"` BatchFulfillmentEnabled bool `json:"batchFulfillmentEnabled"` + CustomRevertsPipelineEnabled *bool `json:"customRevertsPipelineEnabled,omitempty"` BatchFulfillmentGasMultiplier float64 `json:"batchFulfillmentGasMultiplier"` CoordinatorAddress ethkey.EIP55Address `json:"coordinatorAddress"` PublicKey secp256k1.PublicKey `json:"publicKey"` @@ -281,26 +282,31 @@ type VRFSpec struct { BackoffInitialDelay models.Duration `json:"backoffInitialDelay"` BackoffMaxDelay models.Duration `json:"backoffMaxDelay"` GasLanePrice *assets.Wei `json:"gasLanePrice"` - VRFOwnerAddress *ethkey.EIP55Address `json:"vrfOwnerAddress"` + RequestedConfsDelay int64 `json:"requestedConfsDelay"` + VRFOwnerAddress *ethkey.EIP55Address `json:"vrfOwnerAddress,omitempty"` } func NewVRFSpec(spec *job.VRFSpec) *VRFSpec { return &VRFSpec{ - BatchCoordinatorAddress: spec.BatchCoordinatorAddress, - BatchFulfillmentEnabled: spec.BatchFulfillmentEnabled, - CoordinatorAddress: spec.CoordinatorAddress, - PublicKey: spec.PublicKey, - FromAddresses: spec.FromAddresses, - PollPeriod: models.MustMakeDuration(spec.PollPeriod), - MinIncomingConfirmations: spec.MinIncomingConfirmations, - CreatedAt: spec.CreatedAt, - UpdatedAt: spec.UpdatedAt, - EVMChainID: spec.EVMChainID, - ChunkSize: spec.ChunkSize, - RequestTimeout: models.MustMakeDuration(spec.RequestTimeout), - BackoffInitialDelay: models.MustMakeDuration(spec.BackoffInitialDelay), - BackoffMaxDelay: models.MustMakeDuration(spec.BackoffMaxDelay), - GasLanePrice: spec.GasLanePrice, + BatchCoordinatorAddress: spec.BatchCoordinatorAddress, + BatchFulfillmentEnabled: spec.BatchFulfillmentEnabled, + BatchFulfillmentGasMultiplier: float64(spec.BatchFulfillmentGasMultiplier), + CustomRevertsPipelineEnabled: &spec.CustomRevertsPipelineEnabled, + CoordinatorAddress: spec.CoordinatorAddress, + PublicKey: spec.PublicKey, + FromAddresses: spec.FromAddresses, + PollPeriod: models.MustMakeDuration(spec.PollPeriod), + MinIncomingConfirmations: spec.MinIncomingConfirmations, + CreatedAt: spec.CreatedAt, + UpdatedAt: spec.UpdatedAt, + EVMChainID: spec.EVMChainID, + ChunkSize: spec.ChunkSize, + RequestTimeout: models.MustMakeDuration(spec.RequestTimeout), + BackoffInitialDelay: models.MustMakeDuration(spec.BackoffInitialDelay), + BackoffMaxDelay: models.MustMakeDuration(spec.BackoffMaxDelay), + GasLanePrice: spec.GasLanePrice, + RequestedConfsDelay: spec.RequestedConfsDelay, + VRFOwnerAddress: spec.VRFOwnerAddress, } } diff --git a/core/web/presenters/job_test.go b/core/web/presenters/job_test.go index a5d6db0df18..b782452948b 100644 --- a/core/web/presenters/job_test.go +++ b/core/web/presenters/job_test.go @@ -14,11 +14,13 @@ import ( "gopkg.in/guregu/null.v4" "github.com/smartcontractkit/chainlink-common/pkg/assets" + evmassets "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" clnull "github.com/smartcontractkit/chainlink/v2/core/null" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" + "github.com/smartcontractkit/chainlink/v2/core/services/signatures/secp256k1" "github.com/smartcontractkit/chainlink/v2/core/store/models" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) @@ -58,6 +60,7 @@ func TestJob(t *testing.T) { trustedBlockhashStoreBatchSize := int32(20) var specGasLimit uint32 = 1000 + vrfPubKey, _ := secp256k1.NewPublicKeyFromHex("0xede539e216e3a50e69d1c68aa9cc472085876c4002f6e1e6afee0ea63b50a78b00") testCases := []struct { name string @@ -469,6 +472,90 @@ func TestJob(t *testing.T) { } }`, }, + { + name: "vrf job spec", + job: job.Job{ + ID: 1, + Name: null.StringFrom("vrf_test"), + Type: job.VRF, + SchemaVersion: 1, + ExternalJobID: uuid.MustParse("0eec7e1d-d0d2-476c-a1a8-72dfb6633f47"), + VRFSpec: &job.VRFSpec{ + BatchCoordinatorAddress: &contractAddress, + BatchFulfillmentEnabled: true, + CustomRevertsPipelineEnabled: true, + MinIncomingConfirmations: 1, + CoordinatorAddress: contractAddress, + CreatedAt: timestamp, + UpdatedAt: timestamp, + EVMChainID: evmChainID, + FromAddresses: []ethkey.EIP55Address{fromAddress}, + PublicKey: vrfPubKey, + RequestedConfsDelay: 10, + ChunkSize: 25, + BatchFulfillmentGasMultiplier: 1, + GasLanePrice: evmassets.GWei(200), + VRFOwnerAddress: nil, + }, + PipelineSpec: &pipeline.Spec{ + ID: 1, + DotDagSource: "", + }, + }, + want: fmt.Sprintf(` + { + "data": { + "type": "jobs", + "id": "1", + "attributes": { + "name": "vrf_test", + "type": "vrf", + "schemaVersion": 1, + "maxTaskDuration": "0s", + "externalJobID": "0eec7e1d-d0d2-476c-a1a8-72dfb6633f47", + "directRequestSpec": null, + "fluxMonitorSpec": null, + "gasLimit": null, + "forwardingAllowed": false, + "cronSpec": null, + "offChainReportingOracleSpec": null, + "offChainReporting2OracleSpec": null, + "keeperSpec": null, + "vrfSpec": { + "batchCoordinatorAddress": "%s", + "batchFulfillmentEnabled": true, + "customRevertsPipelineEnabled": true, + "confirmations": 1, + "coordinatorAddress": "%s", + "createdAt": "2000-01-01T00:00:00Z", + "updatedAt": "2000-01-01T00:00:00Z", + "evmChainID": "42", + "fromAddresses": ["%s"], + "pollPeriod": "0s", + "publicKey": "%s", + "requestedConfsDelay": 10, + "requestTimeout": "0s", + "chunkSize": 25, + "batchFulfillmentGasMultiplier": 1, + "backoffInitialDelay": "0s", + "backoffMaxDelay": "0s", + "gasLanePrice": "200 gwei" + }, + "webhookSpec": null, + "blockhashStoreSpec": null, + "blockHeaderFeederSpec": null, + "bootstrapSpec": null, + "pipelineSpec": { + "id": 1, + "jobID": 0, + "dotDagSource": "" + }, + "gatewaySpec": null, + "errors": [] + } + } + }`, contractAddress, contractAddress, fromAddress, vrfPubKey.String()), + }, { name: "blockhash store spec", job: job.Job{ diff --git a/core/web/resolver/spec.go b/core/web/resolver/spec.go index 3e93ea38eab..5e8937dbb96 100644 --- a/core/web/resolver/spec.go +++ b/core/web/resolver/spec.go @@ -641,6 +641,11 @@ func (r *VRFSpecResolver) BatchFulfillmentGasMultiplier() float64 { return float64(r.spec.BatchFulfillmentGasMultiplier) } +// CustomRevertsPipelineEnabled resolves the spec's custom reverts pipeline enabled flag. +func (r *VRFSpecResolver) CustomRevertsPipelineEnabled() *bool { + return &r.spec.CustomRevertsPipelineEnabled +} + // ChunkSize resolves the spec's chunk size. func (r *VRFSpecResolver) ChunkSize() int32 { return int32(r.spec.ChunkSize) diff --git a/core/web/resolver/spec_test.go b/core/web/resolver/spec_test.go index 277aac851a6..a4fb9cdb338 100644 --- a/core/web/resolver/spec_test.go +++ b/core/web/resolver/spec_test.go @@ -581,6 +581,7 @@ func TestResolver_VRFSpec(t *testing.T) { VRFSpec: &job.VRFSpec{ BatchCoordinatorAddress: &batchCoordinatorAddress, BatchFulfillmentEnabled: true, + CustomRevertsPipelineEnabled: true, MinIncomingConfirmations: 1, CoordinatorAddress: coordinatorAddress, CreatedAt: f.Timestamp(), @@ -617,6 +618,7 @@ func TestResolver_VRFSpec(t *testing.T) { batchCoordinatorAddress batchFulfillmentEnabled batchFulfillmentGasMultiplier + customRevertsPipelineEnabled chunkSize backoffInitialDelay backoffMaxDelay @@ -644,6 +646,7 @@ func TestResolver_VRFSpec(t *testing.T) { "batchCoordinatorAddress": "0x0ad9FE7a58216242a8475ca92F222b0640E26B63", "batchFulfillmentEnabled": true, "batchFulfillmentGasMultiplier": 1, + "customRevertsPipelineEnabled": true, "chunkSize": 25, "backoffInitialDelay": "1m0s", "backoffMaxDelay": "1h0m0s", diff --git a/core/web/schema/type/spec.graphql b/core/web/schema/type/spec.graphql index 81244478637..5e24f7c3fa8 100644 --- a/core/web/schema/type/spec.graphql +++ b/core/web/schema/type/spec.graphql @@ -97,6 +97,7 @@ type VRFSpec { batchCoordinatorAddress: String batchFulfillmentEnabled: Boolean! batchFulfillmentGasMultiplier: Float! + customRevertsPipelineEnabled: Boolean chunkSize: Int! backoffInitialDelay: String! backoffMaxDelay: String! From 917b74f3a67395f4106f60f70949043f0d989bdf Mon Sep 17 00:00:00 2001 From: Anindita Ghosh <88458927+AnieeG@users.noreply.github.com> Date: Wed, 13 Dec 2023 15:47:26 -0800 Subject: [PATCH 23/29] options to include customized pg and chainlink image (#11570) --- integration-tests/docker/test_env/cl_node.go | 23 ++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/integration-tests/docker/test_env/cl_node.go b/integration-tests/docker/test_env/cl_node.go index b79bb91c70e..d6ab22957a2 100644 --- a/integration-tests/docker/test_env/cl_node.go +++ b/integration-tests/docker/test_env/cl_node.go @@ -25,6 +25,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/logstream" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" @@ -83,6 +84,28 @@ func WithLogStream(ls *logstream.LogStream) ClNodeOption { } } +func WithImage(image string) ClNodeOption { + return func(c *ClNode) { + c.ContainerImage = image + } +} + +func WithVersion(version string) ClNodeOption { + return func(c *ClNode) { + c.ContainerVersion = version + } +} + +func WithPgDBOptions(opts ...test_env.PostgresDbOption) ClNodeOption { + return func(c *ClNode) { + var err error + c.PostgresDb, err = test_env.NewPostgresDb(c.EnvComponent.Networks, opts...) + if err != nil { + c.t.Fatalf("failed to create postgres db: %v", err) + } + } +} + func NewClNode(networks []string, imageName, imageVersion string, nodeConfig *chainlink.Config, opts ...ClNodeOption) (*ClNode, error) { nodeDefaultCName := fmt.Sprintf("%s-%s", "cl-node", uuid.NewString()[0:8]) pgDefaultCName := fmt.Sprintf("pg-%s", nodeDefaultCName) From 7a0704f436a4be1fa0d5c607b901265056c69f2d Mon Sep 17 00:00:00 2001 From: Lei Date: Wed, 13 Dec 2023 17:45:54 -0800 Subject: [PATCH 24/29] add readme (#11535) --- core/scripts/chaincli/README.md | 91 ++++++++++++++++++++++++++ core/scripts/chaincli/handler/debug.go | 6 +- 2 files changed, 94 insertions(+), 3 deletions(-) diff --git a/core/scripts/chaincli/README.md b/core/scripts/chaincli/README.md index da7aa7cc777..bcf407b684b 100644 --- a/core/scripts/chaincli/README.md +++ b/core/scripts/chaincli/README.md @@ -122,3 +122,94 @@ You can use the `grep` and `grepv` flags to filter log lines, e.g. to only show ```shell ./chaincli keeper logs --grep keepers-plugin ``` + +--- + +## ChainCLI Automation Debugging Script + +### Context + +The debugging script is a tool within ChainCLI designed to facilitate the debugging of upkeeps in Automation v21, covering both conditional and log-based scenarios. + +### Configuration + +#### Mandatory Fields + +Ensure the following fields are provided in your `.env` file: + +- `NODE_URL`: Archival node URL +- `KEEPER_REGISTRY_ADDRESS`: Address of the Keeper Registry contract. Refer to the [Supported Networks](https://docs.chain.link/chainlink-automation/overview/supported-networks#configurations) doc for addresses. + +#### Additional Fields (Streams Lookup) + +If your targeted upkeep involves streams lookup, include the following information: + +- `MERCURY_ID` +- `MERCURY_KEY` +- `MERCURY_LEGACY_URL` +- `MERCURY_URL` + +#### Tenderly Integration + +For detailed transaction simulation logs, set up Tenderly credentials. Refer to the [Tenderly Documentation](https://docs.tenderly.co/other/platform-access/how-to-generate-api-access-tokens) for creating an API key, account name, and project name. + +- `TENDERLY_KEY` +- `TENDERLY_ACCOUNT_NAME` +- `TENDERLY_PROJECT_NAME` + +### Usage + +Execute the following command based on your upkeep type: + +- For conditional upkeep: + + ```bash + go run main.go keeper debug UPKEEP_ID + ``` + +- For log trigger upkeep: + + ```bash + go run main.go keeper debug UPKEEP_ID TX_HASH LOG_INDEX + ``` + +### Checks Performed by the Debugging Script + +1. **Fetch and Sanity Check Upkeep:** + - Verify upkeep status: active, paused, or canceled + - Check upkeep balance + +2. **For Conditional Upkeep:** + - Check conditional upkeep + - Simulate `performUpkeep` + +3. **For Log Trigger Upkeep:** + - Check if the upkeep has already run for log-trigger-based upkeep + - Verify if log matches trigger configuration + - Check upkeep + - If check result indicates a streams lookup is required (TargetCheckReverted): + - Verify if the upkeep is allowed to use Mercury + - Execute Mercury request + - Execute check callback + + - Simulate `performUpkeep` + +### Examples +- Eligible and log trigger based and using mercury lookup v0.3: + + ```bash + go run main.go keeper debug 5591498142036749453487419299781783197030971023186134955311257372668222176389 0xdc6d0e547a5aa85fefa5b0f3a37e3493eafb5aeba8b5f3071ce53c9e9a539e9c 0 + ``` + +- Ineligible and conditional upkeep: + + ```bash + go run main.go keeper debug 52635131310730056105456985154251306793887717546629785340977553840883117540096 + ``` + +- Ineligible and Log does not match trigger config: + + ```bash + go run main.go keeper debug 5591498142036749453487419299781783197030971023186134955311257372668222176389 0xc0686ae85d2a7a976ef46df6c613517b9fd46f23340ac583be4e44f5c8b7a186 1 + ``` +--- \ No newline at end of file diff --git a/core/scripts/chaincli/handler/debug.go b/core/scripts/chaincli/handler/debug.go index 3e8bd6d597e..288c7a68b80 100644 --- a/core/scripts/chaincli/handler/debug.go +++ b/core/scripts/chaincli/handler/debug.go @@ -111,8 +111,8 @@ func (k *Keeper) Debug(ctx context.Context, args []string) { if (upkeepInfo.Target == gethcommon.Address{}) { failCheckArgs("this upkeep does not exist on this registry", nil) } - addLink("upkeep", common.UpkeepLink(chainID, upkeepID)) - addLink("target", common.ContractExplorerLink(chainID, upkeepInfo.Target)) + addLink("upkeep link", common.UpkeepLink(chainID, upkeepID)) + addLink("upkeep contract address", common.ContractExplorerLink(chainID, upkeepInfo.Target)) if upkeepInfo.Paused { resolveIneligible("upkeep is paused") } @@ -180,7 +180,7 @@ func (k *Keeper) Debug(ctx context.Context, args []string) { if err != nil { failCheckArgs("failed to fetch tx receipt", err) } - addLink("trigger", common.ExplorerLink(chainID, txHash)) + addLink("trigger transaction", common.ExplorerLink(chainID, txHash)) blockNum = receipt.BlockNumber.Uint64() // find matching log event in tx var triggeringEvent *types.Log From f874ea608e835edd616937f852b193752cd48db8 Mon Sep 17 00:00:00 2001 From: Adam Hamrick Date: Thu, 14 Dec 2023 05:42:05 -0500 Subject: [PATCH 25/29] Little Docs Updates (#11569) * Little Docs Updates * Addition --- integration-tests/README.md | 6 ++++++ integration-tests/example.env | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/integration-tests/README.md b/integration-tests/README.md index c0b673fa92b..37a8fa19ed3 100644 --- a/integration-tests/README.md +++ b/integration-tests/README.md @@ -26,10 +26,16 @@ e.g. `make build_docker_image image=chainlink tag=test-tag` +You'll want to set the `CHAINLINK_IMAGE` and `CHAINLINK_VERSION` env values appropriately as well. See [example.env](./example.env) for more details. + ## Run `go test ./smoke/_test.go` +Most test files have a couple of tests, it's recommended to look into the file and focus on a specific one if possible. 90% of the time this will probably be the `Basic` test. See [ocr_test.go](./smoke/ocr_test.go) for example, which contains the `TestOCRBasic` test. + +`go test ./smoke/ocr_test.go -run TestOCRBasic` + It's generally recommended to run only one test at a time on a local machine as it needs a lot of docker containers and can peg your resources otherwise. You will see docker containers spin up on your machine for each component of the test where you can inspect logs. ## Analyze diff --git a/integration-tests/example.env b/integration-tests/example.env index 3e27ac2c7ab..bbc76bb0c09 100644 --- a/integration-tests/example.env +++ b/integration-tests/example.env @@ -30,15 +30,16 @@ export TEST_UPGRADE_VERSION="2.0.0" # Version of the Chainlink image to upgrade ########## Network Settings ########## +# If running on a live network, you must set the following values # Select a pre-defined network(s) export SELECTED_NETWORKS="SIMULATED" - # General private values that will be retrieved when running on non-simulated networks export EVM_URLS="wss://evm.url,wss://other.url" # Comma-sparated list of websocket URLs to use when running on live networks export EVM_HTTP_URLS="https://evm.url,https://other.url" # Comma-sparated list of HTTP URLs to use when running on live networks export EVM_KEYS="private,funding,keys" # Comma-separated list of private keys to use when running on live networks # Specific private values retrieved when running on specified chains +# Will override the general values above if the SELECTED_NETWORKS contains the network name # Goerli export GOERLI_URLS="wss://goerli.io/ws" export GOERLI_HTTP_URLS="http://goerli.io/ws" From 71e1a796ee3450cd1a0cb20fff8e5f1d46690972 Mon Sep 17 00:00:00 2001 From: Lei Date: Thu, 14 Dec 2023 03:12:22 -0800 Subject: [PATCH 26/29] add unit test to cover 2 check results (#11490) --- .../v21/mercury/streams/streams_test.go | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams/streams_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams/streams_test.go index 54124b7c1a3..40f32751161 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams/streams_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams/streams_test.go @@ -521,6 +521,69 @@ func TestStreams_StreamsLookup(t *testing.T) { }, }, }, + { + name: "two CheckResults: Mercury success E2E and No Mercury because of insufficient balance", + input: []ocr2keepers.CheckResult{ + { + PerformData: []byte{}, + UpkeepID: upkeepIdentifier, + Trigger: ocr2keepers.Trigger{ + BlockNumber: 26046145, + }, + IneligibilityReason: uint8(encoding.UpkeepFailureReasonInsufficientBalance), + }, + { + PerformData: hexutil.MustDecode("0xf055e4a200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000000966656564496448657800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000423078343535343438326435353533343432643431353234323439353435323535346432643534343535333534346534353534303030303030303030303030303030300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042307834323534343332643535353334343264343135323432343935343532353534643264353434353533353434653435353430303030303030303030303030303030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b626c6f636b4e756d62657200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000064000000000000000000000000"), + UpkeepID: upkeepIdentifier, + Trigger: ocr2keepers.Trigger{ + BlockNumber: blockNum, + }, + IneligibilityReason: uint8(mercury.MercuryUpkeepFailureReasonTargetCheckReverted), + }, + }, + blobs: map[string]string{ + "0x4554482d5553442d415242495452554d2d544553544e45540000000000000000": "0x00066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000004555638000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000000269ecbb83b000000000000000000000000000000000000000000000000000000269e4a4e14000000000000000000000000000000000000000000000000000000269f4d0edb000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002381e91cffa9502c20de1ddcee350db3f715a5ab449448e3184a5b03c682356c6e2115f20663b3731e373cf33465a96da26f2876debb548f281e62e48f64c374200000000000000000000000000000000000000000000000000000000000000027db99e34135098d4e0bb9ae143ec9cd72fd63150c6d0cc5b38f4aa1aa42408377e8fe8e5ac489c9b7f62ff5aa7b05d2e892e7dee4cac631097247969b3b03fa3", + "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000": "0x0006da4a86c4933dd4a87b21dd2871aea29f706bcde43c70039355ac5b664fb5000000000000000000000000000000000000000000000000000000000454d118000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204254432d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000002645f00877a000000000000000000000000000000000000000000000000000002645e1e1010000000000000000000000000000000000000000000000000000002645fe2fee4000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002a0373c0bce7393673f819eb9681cac2773c2d718ce933eb858252195b17a9c832d7b0bee173c02c3c25fb65912b8b13b9302ede8423bab3544cb7a8928d5eb3600000000000000000000000000000000000000000000000000000000000000027d7b79d7646383a5dbf51edf14d53bd3ad0a9f3ca8affab3165e89d3ddce9cb17b58e892fafe4ecb24d2fde07c6a756029e752a5114c33c173df4e7d309adb4d", + }, + cachedAdminCfg: false, + extraData: hexutil.MustDecode("0x0000000000000000000000000000000000000064"), + callbackNeeded: true, + checkCallbackResp: hexutil.MustDecode("0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000063a400000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000002e000066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000004555638000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000000269ecbb83b000000000000000000000000000000000000000000000000000000269e4a4e14000000000000000000000000000000000000000000000000000000269f4d0edb000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002381e91cffa9502c20de1ddcee350db3f715a5ab449448e3184a5b03c682356c6e2115f20663b3731e373cf33465a96da26f2876debb548f281e62e48f64c374200000000000000000000000000000000000000000000000000000000000000027db99e34135098d4e0bb9ae143ec9cd72fd63150c6d0cc5b38f4aa1aa42408377e8fe8e5ac489c9b7f62ff5aa7b05d2e892e7dee4cac631097247969b3b03fa300000000000000000000000000000000000000000000000000000000000002e00006da4a86c4933dd4a87b21dd2871aea29f706bcde43c70039355ac5b664fb5000000000000000000000000000000000000000000000000000000000454d118000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204254432d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000002645f00877a000000000000000000000000000000000000000000000000000002645e1e1010000000000000000000000000000000000000000000000000000002645fe2fee4000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002a0373c0bce7393673f819eb9681cac2773c2d718ce933eb858252195b17a9c832d7b0bee173c02c3c25fb65912b8b13b9302ede8423bab3544cb7a8928d5eb3600000000000000000000000000000000000000000000000000000000000000027d7b79d7646383a5dbf51edf14d53bd3ad0a9f3ca8affab3165e89d3ddce9cb17b58e892fafe4ecb24d2fde07c6a756029e752a5114c33c173df4e7d309adb4d00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000064000000000000000000000000"), + values: [][]byte{hexutil.MustDecode("0x00066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000004555638000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000000269ecbb83b000000000000000000000000000000000000000000000000000000269e4a4e14000000000000000000000000000000000000000000000000000000269f4d0edb000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002381e91cffa9502c20de1ddcee350db3f715a5ab449448e3184a5b03c682356c6e2115f20663b3731e373cf33465a96da26f2876debb548f281e62e48f64c374200000000000000000000000000000000000000000000000000000000000000027db99e34135098d4e0bb9ae143ec9cd72fd63150c6d0cc5b38f4aa1aa42408377e8fe8e5ac489c9b7f62ff5aa7b05d2e892e7dee4cac631097247969b3b03fa3"), hexutil.MustDecode("0x0006da4a86c4933dd4a87b21dd2871aea29f706bcde43c70039355ac5b664fb5000000000000000000000000000000000000000000000000000000000454d118000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204254432d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000002645f00877a000000000000000000000000000000000000000000000000000002645e1e1010000000000000000000000000000000000000000000000000000002645fe2fee4000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002a0373c0bce7393673f819eb9681cac2773c2d718ce933eb858252195b17a9c832d7b0bee173c02c3c25fb65912b8b13b9302ede8423bab3544cb7a8928d5eb3600000000000000000000000000000000000000000000000000000000000000027d7b79d7646383a5dbf51edf14d53bd3ad0a9f3ca8affab3165e89d3ddce9cb17b58e892fafe4ecb24d2fde07c6a756029e752a5114c33c173df4e7d309adb4d")}, + expectedResults: []ocr2keepers.CheckResult{ + { + Eligible: false, + PerformData: []byte{}, + UpkeepID: upkeepIdentifier, + Trigger: ocr2keepers.Trigger{ + BlockNumber: 26046145, + }, + IneligibilityReason: uint8(encoding.UpkeepFailureReasonInsufficientBalance), + }, + { + Eligible: true, + PerformData: hexutil.MustDecode("0x000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000002e000066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000004555638000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000000269ecbb83b000000000000000000000000000000000000000000000000000000269e4a4e14000000000000000000000000000000000000000000000000000000269f4d0edb000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002381e91cffa9502c20de1ddcee350db3f715a5ab449448e3184a5b03c682356c6e2115f20663b3731e373cf33465a96da26f2876debb548f281e62e48f64c374200000000000000000000000000000000000000000000000000000000000000027db99e34135098d4e0bb9ae143ec9cd72fd63150c6d0cc5b38f4aa1aa42408377e8fe8e5ac489c9b7f62ff5aa7b05d2e892e7dee4cac631097247969b3b03fa300000000000000000000000000000000000000000000000000000000000002e00006da4a86c4933dd4a87b21dd2871aea29f706bcde43c70039355ac5b664fb5000000000000000000000000000000000000000000000000000000000454d118000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204254432d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000002645f00877a000000000000000000000000000000000000000000000000000002645e1e1010000000000000000000000000000000000000000000000000000002645fe2fee4000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002a0373c0bce7393673f819eb9681cac2773c2d718ce933eb858252195b17a9c832d7b0bee173c02c3c25fb65912b8b13b9302ede8423bab3544cb7a8928d5eb3600000000000000000000000000000000000000000000000000000000000000027d7b79d7646383a5dbf51edf14d53bd3ad0a9f3ca8affab3165e89d3ddce9cb17b58e892fafe4ecb24d2fde07c6a756029e752a5114c33c173df4e7d309adb4d00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000064000000000000000000000000"), + UpkeepID: upkeepIdentifier, + Trigger: ocr2keepers.Trigger{ + BlockNumber: blockNum, + }, + IneligibilityReason: uint8(encoding.UpkeepFailureReasonNone), + }, + }, + hasPermission: true, + v3: false, + registry: &mockRegistry{ + GetUpkeepPrivilegeConfigFn: func(opts *bind.CallOpts, upkeepId *big.Int) ([]byte, error) { + return []byte(`{"mercuryEnabled":true}`), nil + }, + CheckCallbackFn: func(opts *bind.CallOpts, id *big.Int, values [][]byte, extraData []byte) (iregistry21.CheckCallback, error) { + return iregistry21.CheckCallback{ + UpkeepNeeded: true, + PerformData: hexutil.MustDecode("0x000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000002e000066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000004555638000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000000269ecbb83b000000000000000000000000000000000000000000000000000000269e4a4e14000000000000000000000000000000000000000000000000000000269f4d0edb000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002381e91cffa9502c20de1ddcee350db3f715a5ab449448e3184a5b03c682356c6e2115f20663b3731e373cf33465a96da26f2876debb548f281e62e48f64c374200000000000000000000000000000000000000000000000000000000000000027db99e34135098d4e0bb9ae143ec9cd72fd63150c6d0cc5b38f4aa1aa42408377e8fe8e5ac489c9b7f62ff5aa7b05d2e892e7dee4cac631097247969b3b03fa300000000000000000000000000000000000000000000000000000000000002e00006da4a86c4933dd4a87b21dd2871aea29f706bcde43c70039355ac5b664fb5000000000000000000000000000000000000000000000000000000000454d118000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204254432d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064f0d4a0000000000000000000000000000000000000000000000000000002645f00877a000000000000000000000000000000000000000000000000000002645e1e1010000000000000000000000000000000000000000000000000000002645fe2fee4000000000000000000000000000000000000000000000000000000000243716664b42d20423a47fb13ad3098b49b37f667548e6745fff958b663afe25a845f6100000000000000000000000000000000000000000000000000000000024371660000000000000000000000000000000000000000000000000000000064f0d4a00000000000000000000000000000000000000000000000000000000000000002a0373c0bce7393673f819eb9681cac2773c2d718ce933eb858252195b17a9c832d7b0bee173c02c3c25fb65912b8b13b9302ede8423bab3544cb7a8928d5eb3600000000000000000000000000000000000000000000000000000000000000027d7b79d7646383a5dbf51edf14d53bd3ad0a9f3ca8affab3165e89d3ddce9cb17b58e892fafe4ecb24d2fde07c6a756029e752a5114c33c173df4e7d309adb4d00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000064000000000000000000000000"), + }, nil + }, + }, + }, { name: "success - happy path no cache - v0.3", input: []ocr2keepers.CheckResult{ From e427abbf4baf54e39281ee83495352c2de0ff02d Mon Sep 17 00:00:00 2001 From: frank zhu Date: Thu, 14 Dec 2023 06:41:44 -0800 Subject: [PATCH 27/29] add CI test for core/scripts (#11466) * add CI test for core/scripts * refactor * refactor golangci-lint build binary step * add ubig pkg * refactor based on suggestions --- .github/actions/golangci-lint/action.yml | 7 +--- .github/workflows/ci-chaincli.yml | 22 ------------ .github/workflows/ci-scripts.yml | 46 ++++++++++++++++++++++++ core/scripts/functions/src/fetching.go | 1 + 4 files changed, 48 insertions(+), 28 deletions(-) delete mode 100644 .github/workflows/ci-chaincli.yml create mode 100644 .github/workflows/ci-scripts.yml diff --git a/.github/actions/golangci-lint/action.yml b/.github/actions/golangci-lint/action.yml index 055960ff282..0047c6a54bd 100644 --- a/.github/actions/golangci-lint/action.yml +++ b/.github/actions/golangci-lint/action.yml @@ -42,14 +42,9 @@ runs: shell: bash run: mkdir -p core/web/assets && touch core/web/assets/index.html - name: Build binary - if: ${{ inputs.go-directory == '.' }} - shell: bash - run: go build ./... - - name: Build binary - if: ${{ inputs.go-directory != '.' }} working-directory: ${{ inputs.go-directory }} shell: bash - run: go build + run: go build ./... - name: golangci-lint uses: golangci/golangci-lint-action@3a919529898de77ec3da873e3063ca4b10e7f5cc # v3.7.0 with: diff --git a/.github/workflows/ci-chaincli.yml b/.github/workflows/ci-chaincli.yml deleted file mode 100644 index 8a9ab03d766..00000000000 --- a/.github/workflows/ci-chaincli.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: chaincli CI - -on: - push: - pull_request: - -jobs: - golangci: - if: ${{ github.event_name == 'pull_request' || github.event_name == 'schedule' }} - name: chaincli-lint - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - name: Golang Lint - uses: ./.github/actions/golangci-lint - with: - name: chaincli-lint - go-directory: core/scripts/chaincli - go-version-file: core/scripts/go.mod - go-module-file: core/scripts/go.sum - gc-basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }} - gc-host: ${{ secrets.GRAFANA_CLOUD_HOST }} diff --git a/.github/workflows/ci-scripts.yml b/.github/workflows/ci-scripts.yml new file mode 100644 index 00000000000..e83c22520cd --- /dev/null +++ b/.github/workflows/ci-scripts.yml @@ -0,0 +1,46 @@ +name: CI Scripts + +on: + push: + pull_request: + +jobs: + golangci: + if: ${{ github.event_name == 'pull_request' }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: Golang Lint + uses: ./.github/actions/golangci-lint + with: + name: scripts-lint + go-directory: core/scripts + go-version-file: core/scripts/go.mod + go-module-file: core/scripts/go.sum + gc-basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }} + gc-host: ${{ secrets.GRAFANA_CLOUD_HOST }} + + test: + if: ${{ github.event_name == 'pull_request' }} + name: scripts-test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: Setup Go + uses: ./.github/actions/setup-go + with: + go-version-file: core/scripts/go.mod + go-module-file: core/scripts/go.sum + - name: Run Tests + shell: bash + working-directory: core/scripts + run: go test ./... + - name: Collect Metrics + if: always() + id: collect-gha-metrics + uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2 + with: + basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }} + hostname: ${{ secrets.GRAFANA_CLOUD_HOST }} + this-job-name: scripts-test + continue-on-error: true diff --git a/core/scripts/functions/src/fetching.go b/core/scripts/functions/src/fetching.go index 9be624a40b6..cbe491fff5e 100644 --- a/core/scripts/functions/src/fetching.go +++ b/core/scripts/functions/src/fetching.go @@ -11,6 +11,7 @@ import ( "github.com/urfave/cli" helpers "github.com/smartcontractkit/chainlink/core/scripts/common" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) From b2e163b4e5079e204489e29cd8587878233ab656 Mon Sep 17 00:00:00 2001 From: Rens Rooimans Date: Thu, 14 Dec 2023 18:14:31 +0100 Subject: [PATCH 28/29] bump npm packages (#11572) --- contracts/package.json | 26 +-- contracts/pnpm-lock.yaml | 404 +++++++++++++++++++-------------------- 2 files changed, 215 insertions(+), 215 deletions(-) diff --git a/contracts/package.json b/contracts/package.json index abbf722140c..4dabbdb0509 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -43,49 +43,49 @@ "@nomiclabs/hardhat-etherscan": "^3.1.7", "@nomiclabs/hardhat-waffle": "2.0.6", "@openzeppelin/hardhat-upgrades": "1.28.0", - "@scroll-tech/contracts": "0.1.0", "@openzeppelin/test-helpers": "^0.5.16", "@typechain/ethers-v5": "^7.2.0", "@typechain/hardhat": "^7.0.0", "@types/cbor": "5.0.1", - "@types/chai": "^4.3.10", + "@types/chai": "^4.3.11", "@types/debug": "^4.1.12", "@types/deep-equal-in-any-order": "^1.0.3", - "@types/mocha": "^10.0.4", - "@types/node": "^16.18.61", - "@typescript-eslint/eslint-plugin": "^6.11.0", - "@typescript-eslint/parser": "^6.11.0", + "@types/mocha": "^10.0.6", + "@types/node": "^16.18.68", + "@typescript-eslint/eslint-plugin": "^6.14.0", + "@typescript-eslint/parser": "^6.14.0", "abi-to-sol": "^0.6.6", "cbor": "^5.2.0", "chai": "^4.3.10", "debug": "^4.3.4", - "eslint": "^8.53.0", - "eslint-config-prettier": "^9.0.0", + "eslint": "^8.55.0", + "eslint-config-prettier": "^9.1.0", "deep-equal-in-any-order": "^2.0.6", "eslint-plugin-prettier": "^5.0.1", "ethereum-waffle": "^3.4.4", "ethers": "~5.7.2", - "hardhat": "~2.19.1", + "hardhat": "~2.19.2", "hardhat-abi-exporter": "^2.10.1", "hardhat-contract-sizer": "^2.10.0", "hardhat-gas-reporter": "^1.0.9", "hardhat-ignore-warnings": "^0.2.6", "istanbul": "^0.4.5", "moment": "^2.29.4", - "prettier": "^3.1.0", + "prettier": "^3.1.1", "prettier-plugin-solidity": "1.2.0", "rlp": "^2.2.7", "solhint": "^4.0.0", "solhint-plugin-chainlink-solidity": "git+https://github.com/smartcontractkit/chainlink-solhint-rules.git#v1.2.0", "solhint-plugin-prettier": "^0.1.0", "solidity-coverage": "^0.8.5", - "ts-node": "^10.9.1", + "ts-node": "^10.9.2", "tslib": "^2.6.2", "typechain": "^8.2.1", - "typescript": "^5.2.2" + "typescript": "^5.3.3" }, "dependencies": { - "@eth-optimism/contracts": "0.5.37", + "@eth-optimism/contracts": "0.6.0", + "@scroll-tech/contracts": "0.1.0", "@openzeppelin/contracts": "4.9.3", "@openzeppelin/contracts-upgradeable": "4.9.3" } diff --git a/contracts/pnpm-lock.yaml b/contracts/pnpm-lock.yaml index dffcb0a7c7c..1b18835dc2e 100644 --- a/contracts/pnpm-lock.yaml +++ b/contracts/pnpm-lock.yaml @@ -9,14 +9,17 @@ overrides: dependencies: '@eth-optimism/contracts': - specifier: 0.5.37 - version: 0.5.37(ethers@5.7.2) + specifier: 0.6.0 + version: 0.6.0(ethers@5.7.2) '@openzeppelin/contracts': specifier: 4.9.3 version: 4.9.3 '@openzeppelin/contracts-upgradeable': specifier: 4.9.3 version: 4.9.3 + '@scroll-tech/contracts': + specifier: 0.1.0 + version: 0.1.0 devDependencies: '@ethereum-waffle/mock-contract': @@ -39,37 +42,34 @@ devDependencies: version: 5.7.0 '@nomicfoundation/hardhat-network-helpers': specifier: ^1.0.9 - version: 1.0.9(hardhat@2.19.1) + version: 1.0.9(hardhat@2.19.2) '@nomiclabs/hardhat-ethers': specifier: ^2.2.3 - version: 2.2.3(ethers@5.7.2)(hardhat@2.19.1) + version: 2.2.3(ethers@5.7.2)(hardhat@2.19.2) '@nomiclabs/hardhat-etherscan': specifier: ^3.1.7 - version: 3.1.7(hardhat@2.19.1) + version: 3.1.7(hardhat@2.19.2) '@nomiclabs/hardhat-waffle': specifier: 2.0.6 - version: 2.0.6(@nomiclabs/hardhat-ethers@2.2.3)(@types/sinon-chai@3.2.8)(ethereum-waffle@3.4.4)(ethers@5.7.2)(hardhat@2.19.1) + version: 2.0.6(@nomiclabs/hardhat-ethers@2.2.3)(@types/sinon-chai@3.2.8)(ethereum-waffle@3.4.4)(ethers@5.7.2)(hardhat@2.19.2) '@openzeppelin/hardhat-upgrades': specifier: 1.28.0 - version: 1.28.0(@nomiclabs/hardhat-ethers@2.2.3)(@nomiclabs/hardhat-etherscan@3.1.7)(ethers@5.7.2)(hardhat@2.19.1) + version: 1.28.0(@nomiclabs/hardhat-ethers@2.2.3)(@nomiclabs/hardhat-etherscan@3.1.7)(ethers@5.7.2)(hardhat@2.19.2) '@openzeppelin/test-helpers': specifier: ^0.5.16 version: 0.5.16(bn.js@4.12.0) - '@scroll-tech/contracts': - specifier: 0.1.0 - version: 0.1.0 '@typechain/ethers-v5': specifier: ^7.2.0 - version: 7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@5.2.2) + version: 7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@5.3.3) '@typechain/hardhat': specifier: ^7.0.0 - version: 7.0.0(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@7.2.0)(ethers@5.7.2)(hardhat@2.19.1)(typechain@8.3.2) + version: 7.0.0(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@7.2.0)(ethers@5.7.2)(hardhat@2.19.2)(typechain@8.3.2) '@types/cbor': specifier: 5.0.1 version: 5.0.1 '@types/chai': - specifier: ^4.3.10 - version: 4.3.10 + specifier: ^4.3.11 + version: 4.3.11 '@types/debug': specifier: ^4.1.12 version: 4.1.12 @@ -77,17 +77,17 @@ devDependencies: specifier: ^1.0.3 version: 1.0.3 '@types/mocha': - specifier: ^10.0.4 - version: 10.0.4 + specifier: ^10.0.6 + version: 10.0.6 '@types/node': - specifier: ^16.18.61 - version: 16.18.61 + specifier: ^16.18.68 + version: 16.18.68 '@typescript-eslint/eslint-plugin': - specifier: ^6.11.0 - version: 6.11.0(@typescript-eslint/parser@6.11.0)(eslint@8.53.0)(typescript@5.2.2) + specifier: ^6.14.0 + version: 6.14.0(@typescript-eslint/parser@6.14.0)(eslint@8.55.0)(typescript@5.3.3) '@typescript-eslint/parser': - specifier: ^6.11.0 - version: 6.11.0(eslint@8.53.0)(typescript@5.2.2) + specifier: ^6.14.0 + version: 6.14.0(eslint@8.55.0)(typescript@5.3.3) abi-to-sol: specifier: ^0.6.6 version: 0.6.6 @@ -104,32 +104,32 @@ devDependencies: specifier: ^2.0.6 version: 2.0.6 eslint: - specifier: ^8.53.0 - version: 8.53.0 + specifier: ^8.55.0 + version: 8.55.0 eslint-config-prettier: - specifier: ^9.0.0 - version: 9.0.0(eslint@8.53.0) + specifier: ^9.1.0 + version: 9.1.0(eslint@8.55.0) eslint-plugin-prettier: specifier: ^5.0.1 - version: 5.0.1(eslint-config-prettier@9.0.0)(eslint@8.53.0)(prettier@3.1.0) + version: 5.0.1(eslint-config-prettier@9.1.0)(eslint@8.55.0)(prettier@3.1.1) ethereum-waffle: specifier: ^3.4.4 - version: 3.4.4(typescript@5.2.2) + version: 3.4.4(typescript@5.3.3) ethers: specifier: ~5.7.2 version: 5.7.2 hardhat: - specifier: ~2.19.1 - version: 2.19.1(ts-node@10.9.1)(typescript@5.2.2) + specifier: ~2.19.2 + version: 2.19.2(ts-node@10.9.2)(typescript@5.3.3) hardhat-abi-exporter: specifier: ^2.10.1 - version: 2.10.1(hardhat@2.19.1) + version: 2.10.1(hardhat@2.19.2) hardhat-contract-sizer: specifier: ^2.10.0 - version: 2.10.0(hardhat@2.19.1) + version: 2.10.0(hardhat@2.19.2) hardhat-gas-reporter: specifier: ^1.0.9 - version: 1.0.9(debug@4.3.4)(hardhat@2.19.1) + version: 1.0.9(debug@4.3.4)(hardhat@2.19.2) hardhat-ignore-warnings: specifier: ^0.2.6 version: 0.2.9 @@ -140,11 +140,11 @@ devDependencies: specifier: ^2.29.4 version: 2.29.4 prettier: - specifier: ^3.1.0 - version: 3.1.0 + specifier: ^3.1.1 + version: 3.1.1 prettier-plugin-solidity: specifier: 1.2.0 - version: 1.2.0(prettier@3.1.0) + version: 1.2.0(prettier@3.1.1) rlp: specifier: ^2.2.7 version: 2.2.7 @@ -156,22 +156,22 @@ devDependencies: version: github.com/smartcontractkit/chainlink-solhint-rules/cfc50b32f95b730304a50deb2e27e88d87115874 solhint-plugin-prettier: specifier: ^0.1.0 - version: 0.1.0(prettier-plugin-solidity@1.2.0)(prettier@3.1.0) + version: 0.1.0(prettier-plugin-solidity@1.2.0)(prettier@3.1.1) solidity-coverage: specifier: ^0.8.5 - version: 0.8.5(hardhat@2.19.1) + version: 0.8.5(hardhat@2.19.2) ts-node: - specifier: ^10.9.1 - version: 10.9.1(@types/node@16.18.61)(typescript@5.2.2) + specifier: ^10.9.2 + version: 10.9.2(@types/node@16.18.68)(typescript@5.3.3) tslib: specifier: ^2.6.2 version: 2.6.2 typechain: specifier: ^8.2.1 - version: 8.3.2(typescript@5.2.2) + version: 8.3.2(typescript@5.3.3) typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.3 + version: 5.3.3 packages: @@ -327,13 +327,13 @@ packages: deprecated: Please use @ensdomains/ens-contracts dev: true - /@eslint-community/eslint-utils@4.4.0(eslint@8.53.0): + /@eslint-community/eslint-utils@4.4.0(eslint@8.55.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 dependencies: - eslint: 8.53.0 + eslint: 8.55.0 eslint-visitor-keys: 3.4.3 dev: true @@ -342,8 +342,8 @@ packages: engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} dev: true - /@eslint/eslintrc@2.1.3: - resolution: {integrity: sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==} + /@eslint/eslintrc@2.1.4: + resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: ajv: 6.12.6 @@ -359,17 +359,17 @@ packages: - supports-color dev: true - /@eslint/js@8.53.0: - resolution: {integrity: sha512-Kn7K8dx/5U6+cT1yEhpX1w4PCSg0M+XyRILPgvwcEBjerFWCwQj5sbr3/VmxqV0JGHCBCzyd6LxypEuehypY1w==} + /@eslint/js@8.55.0: + resolution: {integrity: sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /@eth-optimism/contracts@0.5.37(ethers@5.7.2): - resolution: {integrity: sha512-HbNUUDIM1dUAM0hWPfGp3l9/Zte40zi8QhVbUSIwdYRA7jG7cZgbteqavrjW8wwFqxkWX9IrtA0KAR7pNlSAIQ==} + /@eth-optimism/contracts@0.6.0(ethers@5.7.2): + resolution: {integrity: sha512-vQ04wfG9kMf1Fwy3FEMqH2QZbgS0gldKhcBeBUPfO8zu68L61VI97UDXmsMQXzTsEAxK8HnokW3/gosl4/NW3w==} peerDependencies: ethers: ^5 dependencies: - '@eth-optimism/core-utils': 0.10.1 + '@eth-optimism/core-utils': 0.12.0 '@ethersproject/abstract-provider': 5.7.0 '@ethersproject/abstract-signer': 5.7.0 ethers: 5.7.2 @@ -378,8 +378,8 @@ packages: - utf-8-validate dev: false - /@eth-optimism/core-utils@0.10.1: - resolution: {integrity: sha512-IJvG5UtYvyz6An9QdohlCLoeB3NBFxx2lRJKlPzvYYlfugUNNCHsajRIWIwJTcPRRma0WPd46JUsKACLJDdNrA==} + /@eth-optimism/core-utils@0.12.0: + resolution: {integrity: sha512-qW+7LZYCz7i8dRa7SRlUKIo1VBU8lvN0HeXCxJR+z+xtMzMQpPds20XJNCMclszxYQHkXY00fOT6GvFw9ZL6nw==} dependencies: '@ethersproject/abi': 5.7.0 '@ethersproject/abstract-provider': 5.7.0 @@ -415,7 +415,7 @@ packages: - utf-8-validate dev: true - /@ethereum-waffle/compiler@3.4.4(typescript@5.2.2): + /@ethereum-waffle/compiler@3.4.4(typescript@5.3.3): resolution: {integrity: sha512-RUK3axJ8IkD5xpWjWoJgyHclOeEzDLQFga6gKpeGxiS/zBu+HB0W2FvsrrLalTFIaPw/CGYACRBSIxqiCqwqTQ==} engines: {node: '>=10.0'} dependencies: @@ -429,7 +429,7 @@ packages: node-fetch: 2.6.7 solc: 0.6.12 ts-generator: 0.1.1 - typechain: 3.0.0(typescript@5.2.2) + typechain: 3.0.0(typescript@5.3.3) transitivePeerDependencies: - bufferutil - encoding @@ -1040,13 +1040,13 @@ packages: - utf-8-validate dev: true - /@nomicfoundation/hardhat-network-helpers@1.0.9(hardhat@2.19.1): + /@nomicfoundation/hardhat-network-helpers@1.0.9(hardhat@2.19.2): resolution: {integrity: sha512-OXWCv0cHpwLUO2u7bFxBna6dQtCC2Gg/aN/KtJLO7gmuuA28vgmVKYFRCDUqrbjujzgfwQ2aKyZ9Y3vSmDqS7Q==} peerDependencies: hardhat: ^2.9.5 dependencies: ethereumjs-util: 7.1.5 - hardhat: 2.19.1(ts-node@10.9.1)(typescript@5.2.2) + hardhat: 2.19.2(ts-node@10.9.2)(typescript@5.3.3) dev: true /@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.0: @@ -1155,17 +1155,17 @@ packages: '@nomicfoundation/solidity-analyzer-win32-x64-msvc': 0.1.0 dev: true - /@nomiclabs/hardhat-ethers@2.2.3(ethers@5.7.2)(hardhat@2.19.1): + /@nomiclabs/hardhat-ethers@2.2.3(ethers@5.7.2)(hardhat@2.19.2): resolution: {integrity: sha512-YhzPdzb612X591FOe68q+qXVXGG2ANZRvDo0RRUtimev85rCrAlv/TLMEZw5c+kq9AbzocLTVX/h2jVIFPL9Xg==} peerDependencies: ethers: ^5.0.0 hardhat: ^2.0.0 dependencies: ethers: 5.7.2 - hardhat: 2.19.1(ts-node@10.9.1)(typescript@5.2.2) + hardhat: 2.19.2(ts-node@10.9.2)(typescript@5.3.3) dev: true - /@nomiclabs/hardhat-etherscan@3.1.7(hardhat@2.19.1): + /@nomiclabs/hardhat-etherscan@3.1.7(hardhat@2.19.2): resolution: {integrity: sha512-tZ3TvSgpvsQ6B6OGmo1/Au6u8BrAkvs1mIC/eURA3xgIfznUZBhmpne8hv7BXUzw9xNL3fXdpOYgOQlVMTcoHQ==} peerDependencies: hardhat: ^2.0.4 @@ -1176,7 +1176,7 @@ packages: chalk: 2.4.2 debug: 4.3.4(supports-color@8.1.1) fs-extra: 7.0.1 - hardhat: 2.19.1(ts-node@10.9.1)(typescript@5.2.2) + hardhat: 2.19.2(ts-node@10.9.2)(typescript@5.3.3) lodash: 4.17.21 semver: 6.3.0 table: 6.8.1 @@ -1185,7 +1185,7 @@ packages: - supports-color dev: true - /@nomiclabs/hardhat-waffle@2.0.6(@nomiclabs/hardhat-ethers@2.2.3)(@types/sinon-chai@3.2.8)(ethereum-waffle@3.4.4)(ethers@5.7.2)(hardhat@2.19.1): + /@nomiclabs/hardhat-waffle@2.0.6(@nomiclabs/hardhat-ethers@2.2.3)(@types/sinon-chai@3.2.8)(ethereum-waffle@3.4.4)(ethers@5.7.2)(hardhat@2.19.2): resolution: {integrity: sha512-+Wz0hwmJGSI17B+BhU/qFRZ1l6/xMW82QGXE/Gi+WTmwgJrQefuBs1lIf7hzQ1hLk6hpkvb/zwcNkpVKRYTQYg==} peerDependencies: '@nomiclabs/hardhat-ethers': ^2.0.0 @@ -1194,11 +1194,11 @@ packages: ethers: ^5.0.0 hardhat: ^2.0.0 dependencies: - '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.19.1) + '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.19.2) '@types/sinon-chai': 3.2.8 - ethereum-waffle: 3.4.4(typescript@5.2.2) + ethereum-waffle: 3.4.4(typescript@5.3.3) ethers: 5.7.2 - hardhat: 2.19.1(ts-node@10.9.1)(typescript@5.2.2) + hardhat: 2.19.2(ts-node@10.9.2)(typescript@5.3.3) dev: true /@openzeppelin/contract-loader@0.6.3: @@ -1229,7 +1229,7 @@ packages: - encoding dev: true - /@openzeppelin/hardhat-upgrades@1.28.0(@nomiclabs/hardhat-ethers@2.2.3)(@nomiclabs/hardhat-etherscan@3.1.7)(ethers@5.7.2)(hardhat@2.19.1): + /@openzeppelin/hardhat-upgrades@1.28.0(@nomiclabs/hardhat-ethers@2.2.3)(@nomiclabs/hardhat-etherscan@3.1.7)(ethers@5.7.2)(hardhat@2.19.2): resolution: {integrity: sha512-7sb/Jf+X+uIufOBnmHR0FJVWuxEs2lpxjJnLNN6eCJCP8nD0v+Ot5lTOW2Qb/GFnh+fLvJtEkhkowz4ZQ57+zQ==} hasBin: true peerDependencies: @@ -1242,15 +1242,15 @@ packages: '@nomiclabs/harhdat-etherscan': optional: true dependencies: - '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.19.1) - '@nomiclabs/hardhat-etherscan': 3.1.7(hardhat@2.19.1) + '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.19.2) + '@nomiclabs/hardhat-etherscan': 3.1.7(hardhat@2.19.2) '@openzeppelin/defender-base-client': 1.49.0(debug@4.3.4) '@openzeppelin/platform-deploy-client': 0.8.0(debug@4.3.4) '@openzeppelin/upgrades-core': 1.30.1 chalk: 4.1.2 debug: 4.3.4(supports-color@8.1.1) ethers: 5.7.2 - hardhat: 2.19.1(ts-node@10.9.1)(typescript@5.2.2) + hardhat: 2.19.2(ts-node@10.9.2)(typescript@5.3.3) proper-lockfile: 4.1.2 transitivePeerDependencies: - encoding @@ -1341,12 +1341,12 @@ packages: config-chain: 1.1.13 dev: true - /@prettier/sync@0.3.0(prettier@3.1.0): + /@prettier/sync@0.3.0(prettier@3.1.1): resolution: {integrity: sha512-3dcmCyAxIcxy036h1I7MQU/uEEBq8oLwf1CE3xeze+MPlgkdlb/+w6rGR/1dhp6Hqi17fRS6nvwnOzkESxEkOw==} peerDependencies: prettier: ^3.0.0 dependencies: - prettier: 3.1.0 + prettier: 3.1.1 dev: true /@resolver-engine/core@0.3.3: @@ -1392,7 +1392,7 @@ packages: /@scroll-tech/contracts@0.1.0: resolution: {integrity: sha512-aBbDOc3WB/WveZdpJYcrfvMYMz7ZTEiW8M9XMJLba8p9FAR5KGYB/cV+8+EUsq3MKt7C1BfR+WnXoTVdvwIY6w==} - dev: true + dev: false /@scure/base@1.1.1: resolution: {integrity: sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==} @@ -1667,10 +1667,10 @@ packages: typechain: ^3.0.0 dependencies: ethers: 5.7.2 - typechain: 3.0.0(typescript@5.2.2) + typechain: 3.0.0(typescript@5.3.3) dev: true - /@typechain/ethers-v5@7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@5.2.2): + /@typechain/ethers-v5@7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@5.3.3): resolution: {integrity: sha512-jfcmlTvaaJjng63QsT49MT6R1HFhtO/TBMWbyzPFSzMmVIqb2tL6prnKBs4ZJrSvmgIXWy+ttSjpaxCTq8D/Tw==} peerDependencies: '@ethersproject/abi': ^5.0.0 @@ -1685,12 +1685,12 @@ packages: '@ethersproject/providers': 5.7.2 ethers: 5.7.2 lodash: 4.17.21 - ts-essentials: 7.0.3(typescript@5.2.2) - typechain: 8.3.2(typescript@5.2.2) - typescript: 5.2.2 + ts-essentials: 7.0.3(typescript@5.3.3) + typechain: 8.3.2(typescript@5.3.3) + typescript: 5.3.3 dev: true - /@typechain/hardhat@7.0.0(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@7.2.0)(ethers@5.7.2)(hardhat@2.19.1)(typechain@8.3.2): + /@typechain/hardhat@7.0.0(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@7.2.0)(ethers@5.7.2)(hardhat@2.19.2)(typechain@8.3.2): resolution: {integrity: sha512-XB79i5ewg9Met7gMVGfgVkmypicbnI25T5clJBEooMoW2161p4zvKFpoS2O+lBppQyMrPIZkdvl2M3LMDayVcA==} peerDependencies: '@ethersproject/abi': ^5.4.7 @@ -1702,23 +1702,23 @@ packages: dependencies: '@ethersproject/abi': 5.7.0 '@ethersproject/providers': 5.7.2 - '@typechain/ethers-v5': 7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@5.2.2) + '@typechain/ethers-v5': 7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@5.3.3) ethers: 5.7.2 fs-extra: 9.1.0 - hardhat: 2.19.1(ts-node@10.9.1)(typescript@5.2.2) - typechain: 8.3.2(typescript@5.2.2) + hardhat: 2.19.2(ts-node@10.9.2)(typescript@5.3.3) + typechain: 8.3.2(typescript@5.3.3) dev: true /@types/bn.js@4.11.6: resolution: {integrity: sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==} dependencies: - '@types/node': 16.18.61 + '@types/node': 16.18.68 dev: true /@types/bn.js@5.1.1: resolution: {integrity: sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g==} dependencies: - '@types/node': 16.18.61 + '@types/node': 16.18.68 dev: true /@types/cacheable-request@6.0.2: @@ -1726,24 +1726,24 @@ packages: dependencies: '@types/http-cache-semantics': 4.0.1 '@types/keyv': 3.1.4 - '@types/node': 16.18.61 + '@types/node': 16.18.68 '@types/responselike': 1.0.0 dev: true /@types/cbor@5.0.1: resolution: {integrity: sha512-zVqJy2KzusZPLOgyGJDnOIbu3DxIGGqxYbEwtEEe4Z+la8jwIhOyb+GMrlHafs5tvKruwf8f8qOYP6zTvse/pw==} dependencies: - '@types/node': 16.18.61 + '@types/node': 16.18.68 dev: true - /@types/chai@4.3.10: - resolution: {integrity: sha512-of+ICnbqjmFCiixUnqRulbylyXQrPqIGf/B3Jax1wIF3DvSheysQxAWvqHhZiW3IQrycvokcLcFQlveGp+vyNg==} + /@types/chai@4.3.11: + resolution: {integrity: sha512-qQR1dr2rGIHYlJulmr8Ioq3De0Le9E4MJ5AiaeAETJJpndT1uUNHsGFK3L/UIu+rbkQSdj8J/w2bCsBZc/Y5fQ==} dev: true /@types/concat-stream@1.6.1: resolution: {integrity: sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA==} dependencies: - '@types/node': 16.18.61 + '@types/node': 16.18.68 dev: true /@types/debug@4.1.12: @@ -1763,7 +1763,7 @@ packages: /@types/form-data@0.0.33: resolution: {integrity: sha512-8BSvG1kGm83cyJITQMZSulnl6QV8jqAGreJsc5tPu1Jq0vTSOiY/k24Wx82JRpWwZSqrala6sd5rWi6aNXvqcw==} dependencies: - '@types/node': 16.18.61 + '@types/node': 16.18.68 dev: true /@types/glob@7.1.1: @@ -1771,7 +1771,7 @@ packages: dependencies: '@types/events': 3.0.0 '@types/minimatch': 3.0.3 - '@types/node': 16.18.61 + '@types/node': 16.18.68 dev: true /@types/http-cache-semantics@4.0.1: @@ -1785,7 +1785,7 @@ packages: /@types/keyv@3.1.4: resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} dependencies: - '@types/node': 16.18.61 + '@types/node': 16.18.68 dev: true /@types/lru-cache@5.1.1: @@ -1799,11 +1799,11 @@ packages: /@types/mkdirp@0.5.2: resolution: {integrity: sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg==} dependencies: - '@types/node': 16.18.61 + '@types/node': 16.18.68 dev: true - /@types/mocha@10.0.4: - resolution: {integrity: sha512-xKU7bUjiFTIttpWaIZ9qvgg+22O1nmbA+HRxdlR+u6TWsGfmFdXrheJoK4fFxrHNVIOBDvDNKZG+LYBpMHpX3w==} + /@types/mocha@10.0.6: + resolution: {integrity: sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==} dev: true /@types/ms@0.7.31: @@ -1813,7 +1813,7 @@ packages: /@types/node-fetch@2.6.2: resolution: {integrity: sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==} dependencies: - '@types/node': 16.18.61 + '@types/node': 16.18.68 form-data: 3.0.1 dev: true @@ -1825,8 +1825,8 @@ packages: resolution: {integrity: sha512-7xHmXm/QJ7cbK2laF+YYD7gb5MggHIIQwqyjin3bpEGiSuvScMQ5JZZXPvRipi1MwckTQbJZROMns/JxdnIL1Q==} dev: true - /@types/node@16.18.61: - resolution: {integrity: sha512-k0N7BqGhJoJzdh6MuQg1V1ragJiXTh8VUBAZTWjJ9cUq23SG0F0xavOwZbhiP4J3y20xd6jxKx+xNUhkMAi76Q==} + /@types/node@16.18.68: + resolution: {integrity: sha512-sG3hPIQwJLoewrN7cr0dwEy+yF5nD4D/4FxtQpFciRD/xwUzgD+G05uxZHv5mhfXo4F9Jkp13jjn0CC2q325sg==} dev: true /@types/node@8.10.66: @@ -1836,7 +1836,7 @@ packages: /@types/pbkdf2@3.1.0: resolution: {integrity: sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==} dependencies: - '@types/node': 16.18.61 + '@types/node': 16.18.68 dev: true /@types/prettier@2.7.1: @@ -1850,26 +1850,26 @@ packages: /@types/readable-stream@2.3.15: resolution: {integrity: sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ==} dependencies: - '@types/node': 16.18.61 + '@types/node': 16.18.68 safe-buffer: 5.1.2 dev: true /@types/resolve@0.0.8: resolution: {integrity: sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==} dependencies: - '@types/node': 16.18.61 + '@types/node': 16.18.68 dev: true /@types/responselike@1.0.0: resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==} dependencies: - '@types/node': 16.18.61 + '@types/node': 16.18.68 dev: true /@types/secp256k1@4.0.3: resolution: {integrity: sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w==} dependencies: - '@types/node': 16.18.61 + '@types/node': 16.18.68 dev: true /@types/semver@7.5.0: @@ -1879,7 +1879,7 @@ packages: /@types/sinon-chai@3.2.8: resolution: {integrity: sha512-d4ImIQbT/rKMG8+AXpmcan5T2/PNeSjrYhvkwet6z0p8kzYtfgA32xzOBlbU0yqJfq+/0Ml805iFoODO0LP5/g==} dependencies: - '@types/chai': 4.3.10 + '@types/chai': 4.3.11 '@types/sinon': 10.0.13 dev: true @@ -1893,8 +1893,8 @@ packages: resolution: {integrity: sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA==} dev: true - /@typescript-eslint/eslint-plugin@6.11.0(@typescript-eslint/parser@6.11.0)(eslint@8.53.0)(typescript@5.2.2): - resolution: {integrity: sha512-uXnpZDc4VRjY4iuypDBKzW1rz9T5YBBK0snMn8MaTSNd2kMlj50LnLBABELjJiOL5YHk7ZD8hbSpI9ubzqYI0w==} + /@typescript-eslint/eslint-plugin@6.14.0(@typescript-eslint/parser@6.14.0)(eslint@8.55.0)(typescript@5.3.3): + resolution: {integrity: sha512-1ZJBykBCXaSHG94vMMKmiHoL0MhNHKSVlcHVYZNw+BKxufhqQVTOawNpwwI1P5nIFZ/4jLVop0mcY6mJJDFNaw==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha @@ -1905,25 +1905,25 @@ packages: optional: true dependencies: '@eslint-community/regexpp': 4.8.0 - '@typescript-eslint/parser': 6.11.0(eslint@8.53.0)(typescript@5.2.2) - '@typescript-eslint/scope-manager': 6.11.0 - '@typescript-eslint/type-utils': 6.11.0(eslint@8.53.0)(typescript@5.2.2) - '@typescript-eslint/utils': 6.11.0(eslint@8.53.0)(typescript@5.2.2) - '@typescript-eslint/visitor-keys': 6.11.0 + '@typescript-eslint/parser': 6.14.0(eslint@8.55.0)(typescript@5.3.3) + '@typescript-eslint/scope-manager': 6.14.0 + '@typescript-eslint/type-utils': 6.14.0(eslint@8.55.0)(typescript@5.3.3) + '@typescript-eslint/utils': 6.14.0(eslint@8.55.0)(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 6.14.0 debug: 4.3.4(supports-color@8.1.1) - eslint: 8.53.0 + eslint: 8.55.0 graphemer: 1.4.0 ignore: 5.2.4 natural-compare: 1.4.0 semver: 7.5.4 - ts-api-utils: 1.0.3(typescript@5.2.2) - typescript: 5.2.2 + ts-api-utils: 1.0.3(typescript@5.3.3) + typescript: 5.3.3 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/parser@6.11.0(eslint@8.53.0)(typescript@5.2.2): - resolution: {integrity: sha512-+whEdjk+d5do5nxfxx73oanLL9ghKO3EwM9kBCkUtWMRwWuPaFv9ScuqlYfQ6pAD6ZiJhky7TZ2ZYhrMsfMxVQ==} + /@typescript-eslint/parser@6.14.0(eslint@8.55.0)(typescript@5.3.3): + resolution: {integrity: sha512-QjToC14CKacd4Pa7JK4GeB/vHmWFJckec49FR4hmIRf97+KXole0T97xxu9IFiPxVQ1DBWrQ5wreLwAGwWAVQA==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -1932,27 +1932,27 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 6.11.0 - '@typescript-eslint/types': 6.11.0 - '@typescript-eslint/typescript-estree': 6.11.0(typescript@5.2.2) - '@typescript-eslint/visitor-keys': 6.11.0 + '@typescript-eslint/scope-manager': 6.14.0 + '@typescript-eslint/types': 6.14.0 + '@typescript-eslint/typescript-estree': 6.14.0(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 6.14.0 debug: 4.3.4(supports-color@8.1.1) - eslint: 8.53.0 - typescript: 5.2.2 + eslint: 8.55.0 + typescript: 5.3.3 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/scope-manager@6.11.0: - resolution: {integrity: sha512-0A8KoVvIURG4uhxAdjSaxy8RdRE//HztaZdG8KiHLP8WOXSk0vlF7Pvogv+vlJA5Rnjj/wDcFENvDaHb+gKd1A==} + /@typescript-eslint/scope-manager@6.14.0: + resolution: {integrity: sha512-VT7CFWHbZipPncAZtuALr9y3EuzY1b1t1AEkIq2bTXUPKw+pHoXflGNG5L+Gv6nKul1cz1VH8fz16IThIU0tdg==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 6.11.0 - '@typescript-eslint/visitor-keys': 6.11.0 + '@typescript-eslint/types': 6.14.0 + '@typescript-eslint/visitor-keys': 6.14.0 dev: true - /@typescript-eslint/type-utils@6.11.0(eslint@8.53.0)(typescript@5.2.2): - resolution: {integrity: sha512-nA4IOXwZtqBjIoYrJcYxLRO+F9ri+leVGoJcMW1uqr4r1Hq7vW5cyWrA43lFbpRvQ9XgNrnfLpIkO3i1emDBIA==} + /@typescript-eslint/type-utils@6.14.0(eslint@8.55.0)(typescript@5.3.3): + resolution: {integrity: sha512-x6OC9Q7HfYKqjnuNu5a7kffIYs3No30isapRBJl1iCHLitD8O0lFbRcVGiOcuyN837fqXzPZ1NS10maQzZMKqw==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -1961,23 +1961,23 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 6.11.0(typescript@5.2.2) - '@typescript-eslint/utils': 6.11.0(eslint@8.53.0)(typescript@5.2.2) + '@typescript-eslint/typescript-estree': 6.14.0(typescript@5.3.3) + '@typescript-eslint/utils': 6.14.0(eslint@8.55.0)(typescript@5.3.3) debug: 4.3.4(supports-color@8.1.1) - eslint: 8.53.0 - ts-api-utils: 1.0.3(typescript@5.2.2) - typescript: 5.2.2 + eslint: 8.55.0 + ts-api-utils: 1.0.3(typescript@5.3.3) + typescript: 5.3.3 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/types@6.11.0: - resolution: {integrity: sha512-ZbEzuD4DwEJxwPqhv3QULlRj8KYTAnNsXxmfuUXFCxZmO6CF2gM/y+ugBSAQhrqaJL3M+oe4owdWunaHM6beqA==} + /@typescript-eslint/types@6.14.0: + resolution: {integrity: sha512-uty9H2K4Xs8E47z3SnXEPRNDfsis8JO27amp2GNCnzGETEW3yTqEIVg5+AI7U276oGF/tw6ZA+UesxeQ104ceA==} engines: {node: ^16.0.0 || >=18.0.0} dev: true - /@typescript-eslint/typescript-estree@6.11.0(typescript@5.2.2): - resolution: {integrity: sha512-Aezzv1o2tWJwvZhedzvD5Yv7+Lpu1by/U1LZ5gLc4tCx8jUmuSCMioPFRjliN/6SJIvY6HpTtJIWubKuYYYesQ==} + /@typescript-eslint/typescript-estree@6.14.0(typescript@5.3.3): + resolution: {integrity: sha512-yPkaLwK0yH2mZKFE/bXkPAkkFgOv15GJAUzgUVonAbv0Hr4PK/N2yaA/4XQbTZQdygiDkpt5DkxPELqHguNvyw==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: typescript: '*' @@ -1985,42 +1985,42 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/types': 6.11.0 - '@typescript-eslint/visitor-keys': 6.11.0 + '@typescript-eslint/types': 6.14.0 + '@typescript-eslint/visitor-keys': 6.14.0 debug: 4.3.4(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 semver: 7.5.4 - ts-api-utils: 1.0.3(typescript@5.2.2) - typescript: 5.2.2 + ts-api-utils: 1.0.3(typescript@5.3.3) + typescript: 5.3.3 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/utils@6.11.0(eslint@8.53.0)(typescript@5.2.2): - resolution: {integrity: sha512-p23ibf68fxoZy605dc0dQAEoUsoiNoP3MD9WQGiHLDuTSOuqoTsa4oAy+h3KDkTcxbbfOtUjb9h3Ta0gT4ug2g==} + /@typescript-eslint/utils@6.14.0(eslint@8.55.0)(typescript@5.3.3): + resolution: {integrity: sha512-XwRTnbvRr7Ey9a1NT6jqdKX8y/atWG+8fAIu3z73HSP8h06i3r/ClMhmaF/RGWGW1tHJEwij1uEg2GbEmPYvYg==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.53.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.55.0) '@types/json-schema': 7.0.12 '@types/semver': 7.5.0 - '@typescript-eslint/scope-manager': 6.11.0 - '@typescript-eslint/types': 6.11.0 - '@typescript-eslint/typescript-estree': 6.11.0(typescript@5.2.2) - eslint: 8.53.0 + '@typescript-eslint/scope-manager': 6.14.0 + '@typescript-eslint/types': 6.14.0 + '@typescript-eslint/typescript-estree': 6.14.0(typescript@5.3.3) + eslint: 8.55.0 semver: 7.5.4 transitivePeerDependencies: - supports-color - typescript dev: true - /@typescript-eslint/visitor-keys@6.11.0: - resolution: {integrity: sha512-+SUN/W7WjBr05uRxPggJPSzyB8zUpaYo2hByKasWbqr3PM8AXfZt8UHdNpBS1v9SA62qnSSMF3380SwDqqprgQ==} + /@typescript-eslint/visitor-keys@6.14.0: + resolution: {integrity: sha512-fB5cw6GRhJUz03MrROVuj5Zm/Q+XWlVdIsFj+Zb1Hvqouc8t+XP2H5y53QYU/MGtd2dPg6/vJJlhoX3xc2ehfw==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 6.11.0 + '@typescript-eslint/types': 6.14.0 eslint-visitor-keys: 3.4.3 dev: true @@ -4714,16 +4714,16 @@ packages: source-map: 0.2.0 dev: true - /eslint-config-prettier@9.0.0(eslint@8.53.0): - resolution: {integrity: sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==} + /eslint-config-prettier@9.1.0(eslint@8.55.0): + resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} hasBin: true peerDependencies: eslint: '>=7.0.0' dependencies: - eslint: 8.53.0 + eslint: 8.55.0 dev: true - /eslint-plugin-prettier@5.0.1(eslint-config-prettier@9.0.0)(eslint@8.53.0)(prettier@3.1.0): + /eslint-plugin-prettier@5.0.1(eslint-config-prettier@9.1.0)(eslint@8.55.0)(prettier@3.1.1): resolution: {integrity: sha512-m3u5RnR56asrwV/lDC4GHorlW75DsFfmUcjfCYylTUs85dBRnB7VM6xG8eCMJdeDRnppzmxZVf1GEPJvl1JmNg==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: @@ -4737,9 +4737,9 @@ packages: eslint-config-prettier: optional: true dependencies: - eslint: 8.53.0 - eslint-config-prettier: 9.0.0(eslint@8.53.0) - prettier: 3.1.0 + eslint: 8.55.0 + eslint-config-prettier: 9.1.0(eslint@8.55.0) + prettier: 3.1.1 prettier-linter-helpers: 1.0.0 synckit: 0.8.5 dev: true @@ -4757,15 +4757,15 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /eslint@8.53.0: - resolution: {integrity: sha512-N4VuiPjXDUa4xVeV/GC/RV3hQW9Nw+Y463lkWaKKXKYMvmRiRDAtfpuPFLN+E1/6ZhyR8J2ig+eVREnYgUsiag==} + /eslint@8.55.0: + resolution: {integrity: sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.53.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.55.0) '@eslint-community/regexpp': 4.8.0 - '@eslint/eslintrc': 2.1.3 - '@eslint/js': 8.53.0 + '@eslint/eslintrc': 2.1.4 + '@eslint/js': 8.55.0 '@humanwhocodes/config-array': 0.11.13 '@humanwhocodes/module-importer': 1.0.1 '@nodelib/fs.walk': 1.2.8 @@ -5060,13 +5060,13 @@ packages: '@scure/bip39': 1.1.0 dev: true - /ethereum-waffle@3.4.4(typescript@5.2.2): + /ethereum-waffle@3.4.4(typescript@5.3.3): resolution: {integrity: sha512-PA9+jCjw4WC3Oc5ocSMBj5sXvueWQeAbvCA+hUlb6oFgwwKyq5ka3bWQ7QZcjzIX+TdFkxP4IbFmoY2D8Dkj9Q==} engines: {node: '>=10.0'} hasBin: true dependencies: '@ethereum-waffle/chai': 3.4.4 - '@ethereum-waffle/compiler': 3.4.4(typescript@5.2.2) + '@ethereum-waffle/compiler': 3.4.4(typescript@5.3.3) '@ethereum-waffle/mock-contract': 3.4.4 '@ethereum-waffle/provider': 3.4.4 ethers: 5.7.2 @@ -6218,7 +6218,7 @@ packages: har-schema: 2.0.0 dev: true - /hardhat-abi-exporter@2.10.1(hardhat@2.19.1): + /hardhat-abi-exporter@2.10.1(hardhat@2.19.2): resolution: {integrity: sha512-X8GRxUTtebMAd2k4fcPyVnCdPa6dYK4lBsrwzKP5yiSq4i+WadWPIumaLfce53TUf/o2TnLpLOduyO1ylE2NHQ==} engines: {node: '>=14.14.0'} peerDependencies: @@ -6226,28 +6226,28 @@ packages: dependencies: '@ethersproject/abi': 5.7.0 delete-empty: 3.0.0 - hardhat: 2.19.1(ts-node@10.9.1)(typescript@5.2.2) + hardhat: 2.19.2(ts-node@10.9.2)(typescript@5.3.3) dev: true - /hardhat-contract-sizer@2.10.0(hardhat@2.19.1): + /hardhat-contract-sizer@2.10.0(hardhat@2.19.2): resolution: {integrity: sha512-QiinUgBD5MqJZJh1hl1jc9dNnpJg7eE/w4/4GEnrcmZJJTDbVFNe3+/3Ep24XqISSkYxRz36czcPHKHd/a0dwA==} peerDependencies: hardhat: ^2.0.0 dependencies: chalk: 4.1.2 cli-table3: 0.6.3 - hardhat: 2.19.1(ts-node@10.9.1)(typescript@5.2.2) + hardhat: 2.19.2(ts-node@10.9.2)(typescript@5.3.3) strip-ansi: 6.0.1 dev: true - /hardhat-gas-reporter@1.0.9(debug@4.3.4)(hardhat@2.19.1): + /hardhat-gas-reporter@1.0.9(debug@4.3.4)(hardhat@2.19.2): resolution: {integrity: sha512-INN26G3EW43adGKBNzYWOlI3+rlLnasXTwW79YNnUhXPDa+yHESgt639dJEs37gCjhkbNKcRRJnomXEuMFBXJg==} peerDependencies: hardhat: ^2.0.2 dependencies: array-uniq: 1.0.3 eth-gas-reporter: 0.2.27(debug@4.3.4) - hardhat: 2.19.1(ts-node@10.9.1)(typescript@5.2.2) + hardhat: 2.19.2(ts-node@10.9.2)(typescript@5.3.3) sha1: 1.1.1 transitivePeerDependencies: - '@codechecks/client' @@ -6264,8 +6264,8 @@ packages: solidity-comments: 0.0.2 dev: true - /hardhat@2.19.1(ts-node@10.9.1)(typescript@5.2.2): - resolution: {integrity: sha512-bsWa63g1GB78ZyMN08WLhFElLPA+J+pShuKD1BFO2+88g3l+BL3R07vj9deIi9dMbssxgE714Gof1dBEDGqnCw==} + /hardhat@2.19.2(ts-node@10.9.2)(typescript@5.3.3): + resolution: {integrity: sha512-CRU3+0Cc8Qh9UpxKd8cLADDPes7ZDtKj4dTK+ERtLBomEzhRPLWklJn4VKOwjre9/k8GNd/e9DYxpfuzcxbXPQ==} hasBin: true peerDependencies: ts-node: '*' @@ -6320,9 +6320,9 @@ packages: solc: 0.7.3(debug@4.3.4) source-map-support: 0.5.21 stacktrace-parser: 0.1.10 - ts-node: 10.9.1(@types/node@16.18.61)(typescript@5.2.2) + ts-node: 10.9.2(@types/node@16.18.68)(typescript@5.3.3) tsort: 0.0.1 - typescript: 5.2.2 + typescript: 5.3.3 undici: 5.19.1 uuid: 8.3.2 ws: 7.5.9 @@ -8909,14 +8909,14 @@ packages: dev: true optional: true - /prettier-plugin-solidity@1.2.0(prettier@3.1.0): + /prettier-plugin-solidity@1.2.0(prettier@3.1.1): resolution: {integrity: sha512-fgxcUZpVAP+LlRfy5JI5oaAkXGkmsje2VJ5krv/YMm+rcTZbIUwFguSw5f+WFuttMjpDm6wB4UL7WVkArEfiVA==} engines: {node: '>=16'} peerDependencies: prettier: '>=2.3.0' dependencies: '@solidity-parser/parser': 0.16.2 - prettier: 3.1.0 + prettier: 3.1.1 semver: 7.5.4 solidity-comments-extractor: 0.0.7 dev: true @@ -8927,8 +8927,8 @@ packages: hasBin: true dev: true - /prettier@3.1.0: - resolution: {integrity: sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==} + /prettier@3.1.1: + resolution: {integrity: sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==} engines: {node: '>=14'} hasBin: true dev: true @@ -9960,16 +9960,16 @@ packages: - debug dev: true - /solhint-plugin-prettier@0.1.0(prettier-plugin-solidity@1.2.0)(prettier@3.1.0): + /solhint-plugin-prettier@0.1.0(prettier-plugin-solidity@1.2.0)(prettier@3.1.1): resolution: {integrity: sha512-SDOTSM6tZxZ6hamrzl3GUgzF77FM6jZplgL2plFBclj/OjKP8Z3eIPojKU73gRr0MvOS8ACZILn8a5g0VTz/Gw==} peerDependencies: prettier: ^3.0.0 prettier-plugin-solidity: ^1.0.0 dependencies: - '@prettier/sync': 0.3.0(prettier@3.1.0) - prettier: 3.1.0 + '@prettier/sync': 0.3.0(prettier@3.1.1) + prettier: 3.1.1 prettier-linter-helpers: 1.0.0 - prettier-plugin-solidity: 1.2.0(prettier@3.1.0) + prettier-plugin-solidity: 1.2.0(prettier@3.1.1) dev: true /solhint@4.0.0: @@ -10114,7 +10114,7 @@ packages: solidity-comments-win32-x64-msvc: 0.0.2 dev: true - /solidity-coverage@0.8.5(hardhat@2.19.1): + /solidity-coverage@0.8.5(hardhat@2.19.2): resolution: {integrity: sha512-6C6N6OV2O8FQA0FWA95FdzVH+L16HU94iFgg5wAFZ29UpLFkgNI/DRR2HotG1bC0F4gAc/OMs2BJI44Q/DYlKQ==} hasBin: true peerDependencies: @@ -10130,7 +10130,7 @@ packages: ghost-testrpc: 0.0.2 global-modules: 2.0.0 globby: 10.0.2 - hardhat: 2.19.1(ts-node@10.9.1)(typescript@5.2.2) + hardhat: 2.19.2(ts-node@10.9.2)(typescript@5.3.3) jsonschema: 1.4.0 lodash: 4.17.21 mocha: 10.2.0 @@ -10719,13 +10719,13 @@ packages: engines: {node: '>=0.10.0'} dev: true - /ts-api-utils@1.0.3(typescript@5.2.2): + /ts-api-utils@1.0.3(typescript@5.3.3): resolution: {integrity: sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==} engines: {node: '>=16.13.0'} peerDependencies: typescript: '>=4.2.0' dependencies: - typescript: 5.2.2 + typescript: 5.3.3 dev: true /ts-command-line-args@2.5.1: @@ -10742,20 +10742,20 @@ packages: resolution: {integrity: sha512-q3N1xS4vZpRouhYHDPwO0bDW3EZ6SK9CrrDHxi/D6BPReSjpVgWIOpLS2o0gSBZm+7q/wyKp6RVM1AeeW7uyfQ==} dev: true - /ts-essentials@6.0.7(typescript@5.2.2): + /ts-essentials@6.0.7(typescript@5.3.3): resolution: {integrity: sha512-2E4HIIj4tQJlIHuATRHayv0EfMGK3ris/GRk1E3CFnsZzeNV+hUmelbaTZHLtXaZppM5oLhHRtO04gINC4Jusw==} peerDependencies: typescript: '>=3.7.0' dependencies: - typescript: 5.2.2 + typescript: 5.3.3 dev: true - /ts-essentials@7.0.3(typescript@5.2.2): + /ts-essentials@7.0.3(typescript@5.3.3): resolution: {integrity: sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==} peerDependencies: typescript: '>=3.7.0' dependencies: - typescript: 5.2.2 + typescript: 5.3.3 dev: true /ts-generator@0.1.1: @@ -10773,8 +10773,8 @@ packages: ts-essentials: 1.0.4 dev: true - /ts-node@10.9.1(@types/node@16.18.61)(typescript@5.2.2): - resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} + /ts-node@10.9.2(@types/node@16.18.68)(typescript@5.3.3): + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} hasBin: true peerDependencies: '@swc/core': '>=1.2.50' @@ -10792,14 +10792,14 @@ packages: '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.3 - '@types/node': 16.18.61 + '@types/node': 16.18.68 acorn: 8.10.0 acorn-walk: 8.2.0 arg: 4.1.3 create-require: 1.1.1 diff: 4.0.2 make-error: 1.3.6 - typescript: 5.2.2 + typescript: 5.3.3 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 dev: true @@ -10884,7 +10884,7 @@ packages: resolution: {integrity: sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==} dev: true - /typechain@3.0.0(typescript@5.2.2): + /typechain@3.0.0(typescript@5.3.3): resolution: {integrity: sha512-ft4KVmiN3zH4JUFu2WJBrwfHeDf772Tt2d8bssDTo/YcckKW2D+OwFrHXRC6hJvO3mHjFQTihoMV6fJOi0Hngg==} hasBin: true dependencies: @@ -10893,14 +10893,14 @@ packages: fs-extra: 7.0.1 js-sha3: 0.8.0 lodash: 4.17.21 - ts-essentials: 6.0.7(typescript@5.2.2) + ts-essentials: 6.0.7(typescript@5.3.3) ts-generator: 0.1.1 transitivePeerDependencies: - supports-color - typescript dev: true - /typechain@8.3.2(typescript@5.2.2): + /typechain@8.3.2(typescript@5.3.3): resolution: {integrity: sha512-x/sQYr5w9K7yv3es7jo4KTX05CLxOf7TRWwoHlrjRh8H82G64g+k7VuWPJlgMo6qrjfCulOdfBjiaDtmhFYD/Q==} hasBin: true peerDependencies: @@ -10915,8 +10915,8 @@ packages: mkdirp: 1.0.4 prettier: 2.8.8 ts-command-line-args: 2.5.1 - ts-essentials: 7.0.3(typescript@5.2.2) - typescript: 5.2.2 + ts-essentials: 7.0.3(typescript@5.3.3) + typescript: 5.3.3 transitivePeerDependencies: - supports-color dev: true @@ -10969,8 +10969,8 @@ packages: resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} dev: true - /typescript@5.2.2: - resolution: {integrity: sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==} + /typescript@5.3.3: + resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==} engines: {node: '>=14.17'} hasBin: true dev: true From 7dd42eb8a8326c6c440e4346fe24c1aebc1cf076 Mon Sep 17 00:00:00 2001 From: Adam Hamrick Date: Thu, 14 Dec 2023 13:49:14 -0500 Subject: [PATCH 29/29] Fix Makefile Oversight (#11568) * Adds MAKE Command for Building Plugin Image * Makefile Oversight --- integration-tests/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/Makefile b/integration-tests/Makefile index 86a266a996a..5e34b059b68 100644 --- a/integration-tests/Makefile +++ b/integration-tests/Makefile @@ -196,7 +196,7 @@ build_docker_image: # tag: the tag for the chainlink image being built, example: tag=latest # example usage: make build_docker_image image=chainlink tag=latest .PHONY: build_plugin_docker_image -build_docker_image: +build_plugin_docker_image: docker build -f ../plugins/chainlink.Dockerfile --build-arg COMMIT_SHA=$(git rev-parse HEAD) --build-arg CHAINLINK_USER=chainlink -t localhost:5000/chainlink:develop ../ # image: the name for the chainlink image being built, example: image=chainlink