Skip to content

Commit

Permalink
feat(lib/grandpa): Warp sync provider basic structure
Browse files Browse the repository at this point in the history
  • Loading branch information
dimartiro committed Sep 23, 2024
1 parent 44f1e86 commit 17ee317
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 0 deletions.
6 changes: 6 additions & 0 deletions dot/state/block_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,9 @@ func (bs *BlockState) GetJustification(hash common.Hash) ([]byte, error) {

return data, nil
}

// GetAuthoritesChangesFromBlock retrieves blocks numbers where authority set changes happened
func (bs *BlockState) GetAuthoritesChangesFromBlock(blockNumber uint) ([]uint, error) {
// TODO: complete me
panic("not implemented")
}
30 changes: 30 additions & 0 deletions lib/grandpa/mocks_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions lib/grandpa/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ type BlockState interface {
FreeImportedBlockNotifierChannel(ch chan *types.Block)
GetFinalisedNotifierChannel() chan *types.FinalisationInfo
FreeFinalisedNotifierChannel(ch chan *types.FinalisationInfo)
GetJustification(hash common.Hash) ([]byte, error)
SetJustification(hash common.Hash, data []byte) error
GetAuthoritesChangesFromBlock(blockNumber uint) ([]uint, error)
BestBlockNumber() (blockNumber uint, err error)
GetHighestRoundAndSetID() (uint64, uint64, error)
BestBlockHash() common.Hash
Expand Down
100 changes: 100 additions & 0 deletions lib/grandpa/warp_sync.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package grandpa

import (
"github.com/ChainSafe/gossamer/dot/types"
"github.com/ChainSafe/gossamer/lib/common"
"github.com/ChainSafe/gossamer/pkg/scale"
)

const MAX_WARP_SYNC_PROOF_SIZE = 8 * 1024 * 1024

type WarpSyncFragment struct {
// The last block that the given authority set finalized. This block should contain a digest
// signalling an authority set change from which we can fetch the next authority set.
header types.Header
// A justification for the header above which proves its finality. In order to validate it the
// verifier must be aware of the authorities and set id for which the justification refers to.
justification []byte
}

type WarpSyncProof struct {
proofs []WarpSyncFragment
// indicates whether the warp sync has been completed
isFinished bool
}

type NetworkProvider struct {
backend BlockState
}

func (np *NetworkProvider) Generate(start common.Hash) ([]byte, error) {
//Generate proof
beginBlockHeader, err := np.backend.GetHeader(start)
if err != nil {
return nil, err
}
authoritySetChanges, err := np.backend.GetAuthoritesChangesFromBlock(beginBlockHeader.Number)
if err != nil {
return nil, err
}

proofsEncodedLen := 0
proofs := make([]WarpSyncFragment, 0)
limitReached := false
for _, blockNumber := range authoritySetChanges {
// the header should contains a standard scheduled change
// otherwise the set must have changed through a forced changed,
// in which case we stop collecting proofs as the chain of trust in authority handoffs was broken.

header, err := np.backend.GetHeaderByNumber(blockNumber)
if err != nil {
return nil, err
}

justification, err := np.backend.GetJustification(header.Hash()) // get the justification of such block
if err != nil {
return nil, err
}
fragment := WarpSyncFragment{header: *header, justification: justification}

// check the proof size
encodedFragment, err := scale.Marshal(fragment)
if err != nil {
return nil, err
}

if proofsEncodedLen+len(encodedFragment) >= MAX_WARP_SYNC_PROOF_SIZE {
limitReached = true
break
}

proofsEncodedLen += len(encodedFragment)
proofs = append(proofs, fragment)
}

isFinished := false
// If the limit is not reached then they retrieve the latest (best) justification
// and append in the proofs
if !limitReached {
bestLastBlockHeader, err := np.backend.BestBlockHeader()
if err != nil {
return nil, err
}
latestJustification, err := np.backend.GetJustification(bestLastBlockHeader.Hash())
if err != nil {
return nil, err
}

fragment := WarpSyncFragment{header: *bestLastBlockHeader, justification: latestJustification}
proofs = append(proofs, fragment)
isFinished = true
}

//Encode proof
finalProof := WarpSyncProof{proofs: proofs, isFinished: isFinished}
encodedProof, err := scale.Marshal(finalProof)
if err != nil {
return nil, err
}
return encodedProof, nil
}

0 comments on commit 17ee317

Please sign in to comment.