-
Notifications
You must be signed in to change notification settings - Fork 170
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
zoneconcierge/epoching: proof that a header is in an epoch #248
Conversation
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.
Wonderful! Minor comments:
epoch := k.GetEpoch(ctx) | ||
if !epoch.IsLastBlock(ctx) { | ||
panic("RecordLastBlockHeader can only be invoked at the last block of an epoch") | ||
return sdkerrors.Wrapf(types.ErrInvalidHeight, "RecordLastBlockHeader can only be invoked at the last block of an epoch") | ||
} |
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.
As the name implies, the caller should ensure that it is this is the last block of the epoch. So maybe we don't need to check it here again. We can add a note about calling this function tho.
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.
Hmm yeah such a contract can do the job as well, but I feel checking it here again can be a better precaution for misuses. Now constructing the full epoch metadata becomes quite cryptic with the following steps:
- Upon the first block of epoch
i
, create the epoch metadata with emptyLastBlockheader
,AppHashRoot
, andSealerHeader
. - Upon the last block of epoch
i
, fillLastBlockHeader
andAppHashRoot
- Upon the 2nd block of epoch
i+1
, fillSealerHeader
for epochi
So I feel it might be better to impose as many restrictions to these functions as possible.
x/epoching/abci.go
Outdated
if err := k.RecordLastBlockHeader(ctx); err != nil { | ||
panic(err) | ||
} | ||
// record the Merkle root of all AppHashs in this epoch | ||
if err := k.RecordAppHashRoot(ctx); err != nil { | ||
panic(err) | ||
} |
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 seems that the epoch info is stored twice in the two functions. Is it possible to combine the two into one like RecordEpochInfo
?
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.
Yep that's a good idea. Merged them to RecordLastHeaderAndAppHashRoot
so that we only write to DB once 👍
x/epoching/keeper/apphash_chain.go
Outdated
if err != nil { | ||
return nil, err | ||
} | ||
if height < epoch.FirstBlockHeight || uint64(epoch.LastBlockHeader.Height) < height { |
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.
if height < epoch.FirstBlockHeight || uint64(epoch.LastBlockHeader.Height) < height { | |
if height < epoch.FirstBlockHeight || height > uint64(epoch.LastBlockHeader.Height) { |
Same thing but seems more intuitive. To be cleaner, maybe we can add a method to Epoch
like WithinBoundary(height uint64) bool
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 WithinBoundary
is really a good idea! Done 👍
x/epoching/keeper/apphash_chain.go
Outdated
|
||
unwrappedProof, err := merkle.ProofFromProto(proof) | ||
if err != nil { | ||
return err |
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.
return err | |
return fmt.Errorf("failed to unwrap proof: %w", err) |
Just to be more informative
Fixes BM-302
This PR implements
ProofHeaderInEpoch
, the proof that a header is in an epoch. The proof is constructed by a Merkle proof that the header'sAppHash
is committed to the Merkle root of allAppHash
s in the epoch. Along the way, this PR implements:AppHash
at every height.AppHash
s in an epoch, and stores the Merkle root to the epoch metadataAppHash
is committed to the Merkle rootProofHeaderInEpoch
In addition, since this PR modifies many Protobuf schemas, this PR performed
make proto-swagger-gen
to regenerate Swagger yml files.