-
Notifications
You must be signed in to change notification settings - Fork 107
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
Limit finalized header gap #1156
Conversation
# Conflicts: # relayer/relays/beacon/header/header.go # relayer/relays/beacon/state/beacon_deneb_encoding.go # relayer/relays/beacon/state/beacon_encoding.go
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.
Assuming we have configured a fallback client which can fetch the beacon state for arbitrary slots. Do we still need to store the beacon state in a local db here? Is that for another kind of fallback?
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 have removed the fallback client since I encountered similar issues with Prysm that we are having with Lodestar. I think fundamentally relying on the beacon node and its config is risky. I think the beacon store adds a layer of reassurance that we'll be able to get the proofs we need if our bridge goes offline for an extended period.
relayer/chain/parachain/writer.go
Outdated
BatchCall(ctx context.Context, extrinsic string, calls []interface{}) error | ||
WriteToParachainAndRateLimit(ctx context.Context, extrinsicName string, payload ...interface{}) error | ||
WriteToParachainAndWatch(ctx context.Context, extrinsicName string, payload ...interface{}) error | ||
GetLastFinalizedHeaderState() (state.FinalizedHeader, error) | ||
GetFinalizedStateByStorageKey(key string) (scale.BeaconState, error) | ||
GetLastBasicChannelBlockNumber() (uint64, error) | ||
GetLastBasicChannelNonceByAddress(address common.Address) (uint64, error) | ||
GetFinalizedHeaderStateByBlockRoot(blockRoot types.H256) (state.FinalizedHeader, error) | ||
GetCompactExecutionHeaderStateByBlockHash(blockHash types.H256) (state.CompactExecutionHeaderState, error) | ||
GetLastFinalizedStateIndex() (types.U32, error) | ||
GetFinalizedBeaconRootByIndex(index uint32) (types.H256, error) |
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.
Extract interfaces that we can mock out in tests.
func (wr *ParachainWriter) writeToParachain(ctx context.Context, extrinsicName string, payload ...interface{}) (*author.ExtrinsicStatusSubscription, error) { | ||
extI, err := wr.prepExtrinstic(ctx, extrinsicName, payload...) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
sub, err := wr.conn.API().RPC.Author.SubmitAndWatchExtrinsic(*extI) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return sub, nil | ||
} | ||
|
||
func (wr *ParachainWriter) queryAccountNonce() (uint32, error) { | ||
key, err := types.CreateStorageKey(wr.conn.Metadata(), "System", "Account", wr.conn.Keypair().PublicKey, nil) | ||
if err != nil { | ||
return 0, err | ||
} | ||
|
||
var accountInfo types.AccountInfo | ||
ok, err := wr.conn.API().RPC.State.GetStorageLatest(key, &accountInfo) | ||
if err != nil { | ||
return 0, err | ||
} | ||
if !ok { | ||
return 0, fmt.Errorf("no account info found for %s", wr.conn.Keypair().URI) | ||
} | ||
|
||
return uint32(accountInfo.Nonce), nil | ||
} | ||
|
||
func (wr *ParachainWriter) prepExtrinstic(ctx context.Context, extrinsicName string, payload ...interface{}) (*types.Extrinsic, error) { | ||
meta, err := wr.conn.API().RPC.State.GetMetadataLatest() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
c, err := types.NewCall(meta, extrinsicName, payload...) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
latestHash, err := wr.conn.API().RPC.Chain.GetFinalizedHead() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
latestBlock, err := wr.conn.API().RPC.Chain.GetBlock(latestHash) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
ext := types.NewExtrinsic(c) | ||
era := NewMortalEra(uint64(latestBlock.Block.Header.Number)) | ||
|
||
genesisHash, err := wr.conn.API().RPC.Chain.GetBlockHash(0) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
rv, err := wr.conn.API().RPC.State.GetRuntimeVersionLatest() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
o := types.SignatureOptions{ | ||
BlockHash: latestHash, | ||
Era: era, | ||
GenesisHash: genesisHash, | ||
Nonce: types.NewUCompactFromUInt(uint64(wr.nonce)), | ||
SpecVersion: rv.SpecVersion, | ||
Tip: types.NewUCompactFromUInt(0), | ||
TransactionVersion: rv.TransactionVersion, | ||
} | ||
|
||
extI := ext | ||
|
||
err = extI.Sign(*wr.conn.Keypair(), o) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &extI, nil | ||
} | ||
|
||
func (wr *ParachainWriter) prepCall(extrinsicName string, payload ...interface{}) (*types.Call, error) { | ||
meta, err := wr.conn.API().RPC.State.GetMetadataLatest() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
c, err := types.NewCall(meta, extrinsicName, payload...) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return &c, nil | ||
} | ||
|
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.
Just reordered the private methods.
if checkpointSlot == 0 { | ||
log.WithFields(log.Fields{"calculatedCheckpointSlot": checkpointSlot}).Info("checkpoint slot not available, try with slot in next sync period instead") | ||
checkpointSlot = h.syncer.CalculateNextCheckpointSlot(slot) | ||
lastFinalizedHeaderState, err := h.writer.GetLastFinalizedHeaderState() | ||
checkpointSlot, err = h.populateCheckPointCacheWithDataFromChain(slot, checkpointSlot) |
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.
A bit weird this function is called with checkpointSlot
as const zero, then could it be simplified as h.populateCheckPointCacheWithDataFromChain(slot)
?
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.
That's a good point! de118ca
func (h *Header) getHeaderUpdateBySlot(slot uint64) (scale.HeaderUpdatePayload, error) { | ||
slot = slot + 1 |
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.
Is adding this line correctly and the smoke test register_token
still work? I don't think we need it.
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.
Good catch 😄 0da2b16
@@ -386,3 +457,40 @@ func (h *Header) isInitialSyncPeriod() bool { | |||
lastFinalizedPeriod := h.syncer.ComputeSyncPeriodAtSlot(h.cache.Finalized.LastSyncedSlot) | |||
return initialPeriod == lastFinalizedPeriod | |||
} | |||
|
|||
func (h *Header) findClosestCheckPoint(slot uint64) (state.FinalizedHeader, error) { |
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.
IIUC it's not closest anymore instead the most distant. So the previous name findCheckPointBackward
make more sense 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.
Renamed here b5334dc.
# Conflicts: # relayer/cmd/root.go # relayer/relays/beacon/header/header.go # relayer/relays/beacon/state/beacon_deneb_encoding.go # relayer/relays/beacon/state/beacon_encoding.go
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.
+1
* construct finalized update * extract interfaces for tests * mock data and tests * adds db store * completes db store * test works * cleanup and fixes * cleanup and fixes * tests * relayer progress * finish tests * formatting * move the interim finalized header check * fix ci * fix ci * adds working dir * go mod download * version * wrap go version * update * add gopath to bin * install sszgen * missing go install * remove build * skip utility tests * remove unused file * remove test line * rename method * refactor method * Fix compile error and breaking tests * clean up imports * fix duplicate import --------- Co-authored-by: claravanstaden <Cats 4 life!> Co-authored-by: ron <[email protected]>
Adds the following: