-
Notifications
You must be signed in to change notification settings - Fork 186
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
[v2] Read blob version params from chain #922
Conversation
|
b9796f9
to
132150e
Compare
6b0eba4
to
a888892
Compare
@@ -0,0 +1,26 @@ | |||
package common | |||
|
|||
type ReadOnlyMap[K comparable, V any] struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah I'd wish golang has const
which will make it self-explain and enforced
node/node.go
Outdated
|
||
// BlobVersionParams is a map of blob version parameters loaded from the chain. | ||
// It is used to determine blob parameters based on the version number. | ||
BlobVersionParams *corev2.BlobVersionParameterMap |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs mutex protection for concurrent read/write
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The underlying map is read only and this pointer to the read only map gets swapped out atomically occasionally. Do we need synchronization here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it needs to, this pointer (the address itself) may be undefined if it's not synchronized among threads (not sure how it's atomic swap if no mutex)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you're right. Converted these into atomic.Pointer
node/node_v2.go
Outdated
@@ -61,7 +65,11 @@ func (n *Node) DownloadBundles(ctx context.Context, batch *corev2.Batch, operato | |||
relayIndex := rand.Intn(len(cert.RelayKeys)) | |||
relayKey := cert.RelayKeys[relayIndex] | |||
for _, quorum := range cert.BlobHeader.QuorumNumbers { | |||
assgn, err := corev2.GetAssignment(operatorState, batch.BlobCertificates[0].BlobHeader.BlobVersion, quorum, n.Config.ID) | |||
blobParams, ok := n.BlobVersionParams.Get(cert.BlobHeader.BlobVersion) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks when there is a new version upgrade, it may have an outage since different dispersers/nodes up to the different versions (and potentially cannot reach quorum threshold)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. The blob version needs to be registered onchain well before new blobs start using the new version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So it's like: 1) add new version of params to smart contracts; 2) let sufficient num of operators upgrade; 3) let disperser(s) upgrade ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Add new blob version onchain (multisig transaction)
- Wait for
OnchainStateRefreshInterval
(practically, wait for a lot more than this duration). If operator nodes, use the default value (1h), all parts of system will be aware of the new version within this time - Let disperser & relay be aware of the blob version
- Blob with new version can be dispersed
a888892
to
385f7c2
Compare
@@ -224,6 +224,13 @@ var ( | |||
Required: false, | |||
EnvVar: common.PrefixEnvVar(EnvVarPrefix, "ENABLE_V2"), | |||
} | |||
OnchainStateRefreshIntervalFlag = cli.DurationFlag{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This may have an issue about having a single control for all onchain state refresh. It's possible we need to refresh different states (e.g. blob's store duration), and maybe at different intervals. Shall we just call this BlobParamsRefreshInterval?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was going to have this control onchain state that changes very infrequently, for now such as relay addresses.
Maybe we can keep this name, and if we need to add other state that needs to be refreshed at different rate, we can add separate controls for those?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This reminds me that blob store duration isn't getting refreshed at all. It only gets read on bootup. Probably fine as they don't really change, but should we refresh those as part of this loop?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They also change very infrequently, maybe at similar level as blob params. SG to include them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will include them in a follow up PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
few small comments
core/v2/assignment.go
Outdated
} | ||
|
||
ops, ok := state.Operators[quorum] | ||
if !ok { | ||
return nil, fmt.Errorf("no operators found for quorum %d", quorum) | ||
} | ||
|
||
if len(ops) > int(params.MaxNumOperators()) { | ||
return nil, fmt.Errorf("too many operators for blob version %d", blobVersion) | ||
if len(ops) > int(blobParams.MaxNumOperators) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use uint32 ?
} | ||
|
||
numOperators := big.NewInt(int64(len(ops))) | ||
numChunks := big.NewInt(int64(params.NumChunks)) | ||
numChunks := big.NewInt(int64(blobParams.NumChunks)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use uint64?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is to convert uint64 to bigint. Do you mean use uint64 to represent numChunks instead of bigint?
@@ -58,9 +56,9 @@ func GetAssignments(state *core.OperatorState, blobVersion BlobVersion, quorum u | |||
mp += int(a.chunks) | |||
} | |||
|
|||
delta := int(params.NumChunks) - mp | |||
delta := int(blobParams.NumChunks) - mp |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same, using uint instead of int.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it should be int. Otherwise, delta
can underflow if mp > numChunks
} | ||
chunks, assignment, err := v.validateBlobQuorum(quorum, blob, blobParams, state) | ||
if errors.Is(err, ErrBlobQuorumSkip) { | ||
continue |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
worth adding a log here?
validVersions := make([]int32, 0, len(s.onchainState.BlobVersionParameters)) | ||
for version := range s.onchainState.BlobVersionParameters { | ||
if _, ok := onchainState.BlobVersionParameters.Get(corev2.BlobVersion(blobHeaderProto.GetVersion())); !ok { | ||
validVersions := make([]int32, 0, onchainState.BlobVersionParameters.Len()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we use uint32's?
385f7c2
to
b678db5
Compare
Why are these changes needed?
Remove hardcoded blob version params map, and read the values from chain.
Checks