Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

commit plugin - support batch sizes greater than one #131

Merged
merged 9 commits into from
Sep 19, 2024

Conversation

dimkouv
Copy link
Contributor

@dimkouv dimkouv commented Sep 18, 2024

So far commit plugin did not support batch sizes greater than 1, meaning that the reported sequence number ranges were always of size 1 e.g. chain1: [123, 123].


In this PR I use the ccipReader to observe the onRamp sequence numbers to increase the batch sizes.

Since every onRamp exists on a different chain we cannot use batch calls, goroutines are spawned instead for each source chain using errgroup.

If for a specific source chain we cannot get the onRamp sequence number, onRamp sequence numbers observation stops.

Commit plugin should limit the amount of data it can process in a round. In a scenario when we have too many pending messages, e.g. [123, 10000] we limit this ranges up to a specific configured batch size which is set to a default of 256.

Limits can be configured on plugin initialization.

@dimkouv dimkouv marked this pull request as ready for review September 18, 2024 10:40
@dimkouv dimkouv requested a review from a team as a code owner September 18, 2024 10:40
@dimkouv dimkouv requested a review from 0xnogo September 18, 2024 12:36

latestOnRampSeqNums[i] = plugintypes.SeqNumChain{
ChainSel: sourceChain,
SeqNum: nextOnRampSeqNum - 1, // Latest is the next one minus one.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

latestOnRampSeqNum would be set to 0 for a new chain. Is that OK?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, in that case there won't be any range reported, since (onRampMax < offRampNext).

import "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3"

// SeqNumRangeLimit limits the range to n elements by truncating the end if necessary.
func SeqNumRangeLimit(rng ccipocr3.SeqNumRange, n uint64) ccipocr3.SeqNumRange {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: could add a .Limit function to the SeqNumRange type in chainlink-common.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}
rangesToReport = append(rangesToReport, chainRange)

if wasTruncated := rng.End() != chainRange.SeqNumRange.End(); wasTruncated {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if wasTruncated := rng.End() != chainRange.SeqNumRange.End(); wasTruncated {
// check if the range was truncated.
if rng.End() != chainRange.SeqNumRange.End() {

@@ -15,6 +15,10 @@ import (
"github.com/smartcontractkit/chainlink-ccip/shared"
)

// DefaultSeqNumsBatchLimit is the default number of max new messages to scan, we use this value when
// the config is not set for a specific chain.
const DefaultSeqNumsBatchLimit = 256
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MaxNumberTreeLeaves

Suggested change
const DefaultSeqNumsBatchLimit = 256
const DefaultSeqNumsBatchLimit = merklemulti.MaxNumberTreeLeaves

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not be here, this should be in offchain config

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And make sure to prefix it with EVM/have EVM somewhere in the name

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this the default unless there's an override? Or you're saying there should be no default and the system needs to crash if the config is missing?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally the latter (IMO defaults are often more trouble than they're worth in this scenario, because people would just use the default even though it might be wrong) but to start with we could fall back to the default and enforce that its provided later if we decide to do so

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added EVM prefix and moved to pluginconfig package

1: 18, // off ramp next is 18, on ramp max is 20 so new msgs are: [18, 19, 20]
},
},
rangeLimitsPerSourceChain: map[cciptypes.ChainSelector]uint64{},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
rangeLimitsPerSourceChain: map[cciptypes.ChainSelector]uint64{},
rangeLimitsPerSourceChain: map[cciptypes.ChainSelector]uint64{}, // default limits

Copy link
Contributor

@winder winder left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, just some minor suggestions to consider

@@ -15,6 +15,10 @@ import (
"github.com/smartcontractkit/chainlink-ccip/shared"
)

// DefaultSeqNumsBatchLimit is the default number of max new messages to scan, we use this value when
// the config is not set for a specific chain.
const DefaultSeqNumsBatchLimit = 256
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not be here, this should be in offchain config

@@ -15,6 +15,10 @@ import (
"github.com/smartcontractkit/chainlink-ccip/shared"
)

// DefaultSeqNumsBatchLimit is the default number of max new messages to scan, we use this value when
// the config is not set for a specific chain.
const DefaultSeqNumsBatchLimit = 256
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And make sure to prefix it with EVM/have EVM somewhere in the name

// SeqNumRangeLimit limits the range to n elements by truncating the end if necessary.
func SeqNumRangeLimit(rng ccipocr3.SeqNumRange, n uint64) ccipocr3.SeqNumRange {
numElems := rng.End() - rng.Start() + 1
if numElems <= 0 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

< 0 is impossible for unsigned types since they'd just overflow, maybe just check == 0 here or have a End() >= Start() check at the top of the func to completely avoid the overflow scenario?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

< 0 is impossible but checking <= 0 instead of == 0 should be harmless. There's an overflow check below.

return rng
}

if uint64(numElems) > n {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this cast necessary? Isn't numElems already a uint64 by virtue of both End() and Start() being uint64?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess its type is cciptypes.SeqNum?

if newEnd > rng.End() { // overflow - do nothing
return rng
}
rng.SetEnd(newEnd)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a fan of mutating func inputs, why not just return a brand new SeqNumRange?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pushed to chainlink-common: https://github.com/smartcontractkit/chainlink-common/pull/781/commits
works like this

Comment on lines 44 to 47
// BatchLimits is the maximum number of messages to include in a single report for a target chain.
// If for example in the next round we have 1000 pending messages and a batch limit of 256, only 256 seq nums
// will be in the report. If a value is not set we fallback to merkleroot.DefaultSeqNumsBatchLimit.
BatchLimits map[cciptypes.ChainSelector]uint64 `json:"batchLimits"`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Batch limit is only dest dependent and doesn't have to be for all chains in the system. I also recommend we call this "max tree size" to be consistent across the system and not change jargon too much.

Suggested change
// BatchLimits is the maximum number of messages to include in a single report for a target chain.
// If for example in the next round we have 1000 pending messages and a batch limit of 256, only 256 seq nums
// will be in the report. If a value is not set we fallback to merkleroot.DefaultSeqNumsBatchLimit.
BatchLimits map[cciptypes.ChainSelector]uint64 `json:"batchLimits"`
// MaxTreeSize is the maximum size of a merkle tree to create prior to calculating the merkle root.
// If for example in the next round we have 1000 pending messages and a max tree size of 256, only 256 seq nums
// will be in the report. If a value is not set we fallback to merklemulti. MaxNumberTreeLeaves.
MaxTreeSize int `json:"maxTreeSize"`

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made it like this, one value per dest / plugin instance

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a warn log when value is not set

Copy link

Test Coverage

Branch Coverage
dk/commit-batch-size 69.4%
main 69.3%

@dimkouv dimkouv merged commit 373d64f into main Sep 19, 2024
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants