Skip to content

Commit

Permalink
feat(lib/babe): implement secondary vrf slot block production (#2307)
Browse files Browse the repository at this point in the history
* feat(lib/babe): implement secondary vrf slot

- Also merge slot claim logic
  • Loading branch information
kishansagathiya authored Feb 25, 2022
1 parent c7f1730 commit 34f2605
Show file tree
Hide file tree
Showing 26 changed files with 158 additions and 141 deletions.
2 changes: 1 addition & 1 deletion dot/core/messages_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func TestService_HandleBlockProduced(t *testing.T) {

// simulate block sent from BABE session
digest := types.NewDigest()
prd, err := types.NewBabeSecondaryPlainPreDigest(0, 1).ToPreRuntimeDigest()
prd, err := types.ToPreRuntimeDigest(*types.NewBabeSecondaryPlainPreDigest(0, 1))
require.NoError(t, err)
err = digest.Add(*prd)
require.NoError(t, err)
Expand Down
2 changes: 1 addition & 1 deletion dot/core/service_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func TestAnnounceBlock(t *testing.T) {

// simulate block sent from BABE session
digest := types.NewDigest()
prd, err := types.NewBabeSecondaryPlainPreDigest(0, 1).ToPreRuntimeDigest()
prd, err := types.ToPreRuntimeDigest(*types.NewBabeSecondaryPlainPreDigest(0, 1))
require.NoError(t, err)
err = digest.Add(*prd)
require.NoError(t, err)
Expand Down
12 changes: 6 additions & 6 deletions dot/rpc/modules/chain_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func TestChainGetHeader_Genesis(t *testing.T) {
require.NoError(t, err)

di := types.NewDigestItem()
prd, err := types.NewBabeSecondaryPlainPreDigest(0, 1).ToPreRuntimeDigest()
prd, err := types.ToPreRuntimeDigest(*types.NewBabeSecondaryPlainPreDigest(0, 1))
require.NoError(t, err)
err = di.Set(*prd)
require.NoError(t, err)
Expand Down Expand Up @@ -79,7 +79,7 @@ func TestChainGetHeader_Latest(t *testing.T) {
require.NoError(t, err)

di := types.NewDigestItem()
prd, err := types.NewBabeSecondaryPlainPreDigest(0, 1).ToPreRuntimeDigest()
prd, err := types.ToPreRuntimeDigest(*types.NewBabeSecondaryPlainPreDigest(0, 1))
require.NoError(t, err)
err = di.Set(*prd)
require.NoError(t, err)
Expand Down Expand Up @@ -127,7 +127,7 @@ func TestChainGetBlock_Genesis(t *testing.T) {
require.NoError(t, err)

di := types.NewDigestItem()
prd, err := types.NewBabeSecondaryPlainPreDigest(0, 1).ToPreRuntimeDigest()
prd, err := types.ToPreRuntimeDigest(*types.NewBabeSecondaryPlainPreDigest(0, 1))
require.NoError(t, err)
err = di.Set(*prd)
require.NoError(t, err)
Expand Down Expand Up @@ -171,7 +171,7 @@ func TestChainGetBlock_Latest(t *testing.T) {
require.NoError(t, err)

di := types.NewDigestItem()
prd, err := types.NewBabeSecondaryPlainPreDigest(0, 1).ToPreRuntimeDigest()
prd, err := types.ToPreRuntimeDigest(*types.NewBabeSecondaryPlainPreDigest(0, 1))
require.NoError(t, err)
err = di.Set(*prd)
require.NoError(t, err)
Expand Down Expand Up @@ -315,7 +315,7 @@ func TestChainGetFinalizedHeadByRound(t *testing.T) {
require.Equal(t, common.BytesToHex(expected[:]), res)

digest := types.NewDigest()
prd, err := types.NewBabeSecondaryPlainPreDigest(0, 1).ToPreRuntimeDigest()
prd, err := types.ToPreRuntimeDigest(*types.NewBabeSecondaryPlainPreDigest(0, 1))
require.NoError(t, err)
err = digest.Add(*prd)
require.NoError(t, err)
Expand Down Expand Up @@ -388,7 +388,7 @@ func newTestStateService(t *testing.T) *state.Service {

func loadTestBlocks(t *testing.T, gh common.Hash, bs *state.BlockState, rt runtime.Instance) {
digest := types.NewDigest()
prd, err := types.NewBabeSecondaryPlainPreDigest(0, 1).ToPreRuntimeDigest()
prd, err := types.ToPreRuntimeDigest(*types.NewBabeSecondaryPlainPreDigest(0, 1))
require.NoError(t, err)
err = digest.Add(*prd)
require.NoError(t, err)
Expand Down
2 changes: 1 addition & 1 deletion dot/rpc/modules/childstate_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ func setupChildStateStorage(t *testing.T) (*ChildStateModule, common.Hash) {
require.NoError(t, err)

digest := types.NewDigest()
prd, err := types.NewBabeSecondaryPlainPreDigest(0, 1).ToPreRuntimeDigest()
prd, err := types.ToPreRuntimeDigest(*types.NewBabeSecondaryPlainPreDigest(0, 1))
require.NoError(t, err)
err = digest.Add(*prd)
require.NoError(t, err)
Expand Down
2 changes: 1 addition & 1 deletion dot/rpc/modules/state_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@ func setupStateModule(t *testing.T) (*StateModule, *common.Hash, *common.Hash) {
require.NoError(t, err)

digest := types.NewDigest()
prd, err := types.NewBabeSecondaryPlainPreDigest(0, 1).ToPreRuntimeDigest()
prd, err := types.ToPreRuntimeDigest(*types.NewBabeSecondaryPlainPreDigest(0, 1))
require.NoError(t, err)
err = digest.Add(*prd)
require.NoError(t, err)
Expand Down
2 changes: 1 addition & 1 deletion dot/rpc/modules/system_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ func setupSystemModule(t *testing.T) *SystemModule {
require.NoError(t, err)

digest := types.NewDigest()
prd, err := types.NewBabeSecondaryPlainPreDigest(0, 1).ToPreRuntimeDigest()
prd, err := types.ToPreRuntimeDigest(*types.NewBabeSecondaryPlainPreDigest(0, 1))
require.NoError(t, err)
err = digest.Add(*prd)
require.NoError(t, err)
Expand Down
6 changes: 3 additions & 3 deletions dot/state/block_finalisation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func TestBlockState_SetFinalisedHash(t *testing.T) {
require.Equal(t, testGenesisHeader.Hash(), h)

digest := types.NewDigest()
di, err := types.NewBabeSecondaryPlainPreDigest(0, 1).ToPreRuntimeDigest()
di, err := types.ToPreRuntimeDigest(*types.NewBabeSecondaryPlainPreDigest(0, 1))
require.NoError(t, err)
require.NotNil(t, di)
err = digest.Add(*di)
Expand Down Expand Up @@ -101,13 +101,13 @@ func TestSetFinalisedHash_setFirstSlotOnFinalisation(t *testing.T) {
firstSlot := uint64(42069)

digest := types.NewDigest()
di, err := types.NewBabeSecondaryPlainPreDigest(0, firstSlot).ToPreRuntimeDigest()
di, err := types.ToPreRuntimeDigest(*types.NewBabeSecondaryPlainPreDigest(0, firstSlot))
require.NoError(t, err)
require.NotNil(t, di)
err = digest.Add(*di)
require.NoError(t, err)
digest2 := types.NewDigest()
di, err = types.NewBabeSecondaryPlainPreDigest(0, firstSlot+100).ToPreRuntimeDigest()
di, err = types.ToPreRuntimeDigest(*types.NewBabeSecondaryPlainPreDigest(0, firstSlot+100))
require.NoError(t, err)
require.NotNil(t, di)
err = digest2.Add(*di)
Expand Down
4 changes: 2 additions & 2 deletions dot/state/block_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -483,13 +483,13 @@ func TestNumberIsFinalised(t *testing.T) {
require.False(t, fin)

digest := types.NewDigest()
prd, err := types.NewBabeSecondaryPlainPreDigest(0, 1).ToPreRuntimeDigest()
prd, err := types.ToPreRuntimeDigest(*types.NewBabeSecondaryPlainPreDigest(0, 1))
require.NoError(t, err)
err = digest.Add(*prd)
require.NoError(t, err)

digest2 := types.NewDigest()
prd, err = types.NewBabeSecondaryPlainPreDigest(0, 100).ToPreRuntimeDigest()
prd, err = types.ToPreRuntimeDigest(*types.NewBabeSecondaryPlainPreDigest(0, 100))
require.NoError(t, err)
err = digest2.Add(*prd)
require.NoError(t, err)
Expand Down
4 changes: 2 additions & 2 deletions dot/state/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ func TestService_PruneStorage(t *testing.T) {
for i := 0; i < 3; i++ {
block, trieState := generateBlockWithRandomTrie(t, serv, nil, int64(i+1))
digest := types.NewDigest()
prd, err := types.NewBabeSecondaryPlainPreDigest(0, uint64(i+1)).ToPreRuntimeDigest()
prd, err := types.ToPreRuntimeDigest(types.NewBabeSecondaryPlainPreDigest(0, uint64(i+1)))
require.NoError(t, err)
err = digest.Add(*prd)
require.NoError(t, err)
Expand Down Expand Up @@ -385,7 +385,7 @@ func TestService_Import(t *testing.T) {
}

digest := types.NewDigest()
prd, err := types.NewBabeSecondaryPlainPreDigest(0, 177).ToPreRuntimeDigest()
prd, err := types.ToPreRuntimeDigest(*types.NewBabeSecondaryPlainPreDigest(0, 177))
require.NoError(t, err)
err = digest.Add(*prd)
require.NoError(t, err)
Expand Down
6 changes: 3 additions & 3 deletions dot/state/test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func AddBlocksToState(t *testing.T, blockState *BlockState, depth int,
for i := startNum + 1; i <= depth+startNum; i++ {
d := types.NewBabePrimaryPreDigest(0, uint64(i), [32]byte{}, [64]byte{})
digest := types.NewDigest()
prd, err := d.ToPreRuntimeDigest()
prd, err := types.ToPreRuntimeDigest(*d)
require.NoError(t, err)
err = digest.Add(*prd)
require.NoError(t, err)
Expand Down Expand Up @@ -166,7 +166,7 @@ func AddBlocksToStateWithFixedBranches(t *testing.T, blockState *BlockState, dep
// create base tree
startNum := int(head.Number.Int64())
for i := startNum + 1; i <= depth; i++ {
d, err := types.NewBabePrimaryPreDigest(0, uint64(i), [32]byte{}, [64]byte{}).ToPreRuntimeDigest()
d, err := types.ToPreRuntimeDigest(*types.NewBabePrimaryPreDigest(0, uint64(i), [32]byte{}, [64]byte{}))
require.NoError(t, err)
require.NotNil(t, d)
digest := types.NewDigest()
Expand Down Expand Up @@ -208,7 +208,7 @@ func AddBlocksToStateWithFixedBranches(t *testing.T, blockState *BlockState, dep
previousHash = branch.hash

for i := branch.depth; i < depth; i++ {
d, err := types.NewBabePrimaryPreDigest(0, uint64(i+j+99), [32]byte{}, [64]byte{}).ToPreRuntimeDigest()
d, err := types.ToPreRuntimeDigest(*types.NewBabePrimaryPreDigest(0, uint64(i+j+99), [32]byte{}, [64]byte{}))
require.NoError(t, err)
require.NotNil(t, d)
digest := types.NewDigest()
Expand Down
2 changes: 1 addition & 1 deletion dot/sync/chain_processor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ func TestChainProcessor_ExecuteBlock(t *testing.T) {
func TestChainProcessor_HandleJustification(t *testing.T) {
syncer := newTestSyncer(t)

d, err := types.NewBabeSecondaryPlainPreDigest(0, 1).ToPreRuntimeDigest()
d, err := types.ToPreRuntimeDigest(*types.NewBabeSecondaryPlainPreDigest(0, 1))
require.NoError(t, err)
digest := types.NewDigest()
err = digest.Add(*d)
Expand Down
2 changes: 1 addition & 1 deletion dot/sync/message_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func addTestBlocksToState(t *testing.T, depth int, blockState BlockState) {
require.Nil(t, err)

digest := types.NewDigest()
prd, err := types.NewBabeSecondaryPlainPreDigest(0, 1).ToPreRuntimeDigest()
prd, err := types.ToPreRuntimeDigest(*types.NewBabeSecondaryPlainPreDigest(0, 1))
require.NoError(t, err)
err = digest.Add(*prd)
require.NoError(t, err)
Expand Down
2 changes: 1 addition & 1 deletion dot/sync/test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (
// BuildBlock ...
func BuildBlock(t *testing.T, instance runtime.Instance, parent *types.Header, ext types.Extrinsic) *types.Block {
digest := types.NewDigest()
prd, err := types.NewBabeSecondaryPlainPreDigest(0, 1).ToPreRuntimeDigest()
prd, err := types.ToPreRuntimeDigest(*types.NewBabeSecondaryPlainPreDigest(0, 1))
require.NoError(t, err)
err = digest.Add(*prd)
require.NoError(t, err)
Expand Down
45 changes: 17 additions & 28 deletions dot/types/babe_digest.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package types

import (
"errors"
"fmt"

"github.com/ChainSafe/gossamer/lib/crypto/sr25519"
"github.com/ChainSafe/gossamer/pkg/scale"
Expand Down Expand Up @@ -51,20 +52,6 @@ func NewBabePrimaryPreDigest(authorityIndex uint32,
}
}

// ToPreRuntimeDigest returns the BabePrimaryPreDigest as a PreRuntimeDigest
func (d *BabePrimaryPreDigest) ToPreRuntimeDigest() (*PreRuntimeDigest, error) {
digest := NewBabeDigest()
err := digest.Set(*d)
if err != nil {
return nil, err
}
enc, err := scale.Marshal(digest)
if err != nil {
return nil, err
}
return NewBABEPreRuntimeDigest(enc), nil
}

// Index Returns VDT index
func (d BabePrimaryPreDigest) Index() uint { return 1 }

Expand All @@ -82,20 +69,6 @@ func NewBabeSecondaryPlainPreDigest(authorityIndex uint32, slotNumber uint64) *B
}
}

// ToPreRuntimeDigest returns the BabePrimaryPreDigest as a PreRuntimeDigest
func (d *BabeSecondaryPlainPreDigest) ToPreRuntimeDigest() (*PreRuntimeDigest, error) {
digest := NewBabeDigest()
err := digest.Set(*d)
if err != nil {
return nil, err
}
enc, err := scale.Marshal(digest)
if err != nil {
return nil, err
}
return NewBABEPreRuntimeDigest(enc), nil
}

// Index Returns VDT index
func (d BabeSecondaryPlainPreDigest) Index() uint { return 2 }

Expand All @@ -121,3 +94,19 @@ func NewBabeSecondaryVRFPreDigest(authorityIndex uint32,

// Index Returns VDT index
func (d BabeSecondaryVRFPreDigest) Index() uint { return 3 }

// ToPreRuntimeDigest returns the VaryingDataTypeValue as a PreRuntimeDigest
func ToPreRuntimeDigest(value scale.VaryingDataTypeValue) (*PreRuntimeDigest, error) {
digest := NewBabeDigest()
err := digest.Set(value)
if err != nil {
return nil, fmt.Errorf("cannot set varying data type value to babe digest: %w", err)
}

enc, err := scale.Marshal(digest)
if err != nil {
return nil, fmt.Errorf("cannot marshal babe digest: %w", err)
}

return NewBABEPreRuntimeDigest(enc), nil
}
10 changes: 5 additions & 5 deletions lib/babe/build_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func createTestBlock(t *testing.T, babeService *Service, parent *types.Header,
rt, err := babeService.blockState.GetRuntime(nil)
require.NoError(t, err)

preRuntimeDigest, err := babeService.runLottery(slotNumber, epoch, epochData)
preRuntimeDigest, err := claimSlot(epoch, slotNumber, epochData, babeService.keypair)
require.NoError(t, err)

block, err := babeService.buildBlock(parent, slot, rt, epochData.authorityIndex, preRuntimeDigest)
Expand Down Expand Up @@ -171,11 +171,11 @@ func TestApplyExtrinsic(t *testing.T) {
}
testVRFOutputAndProof := &VrfOutputAndProof{}

preDigest2, err := types.NewBabePrimaryPreDigest(
preDigest2, err := types.ToPreRuntimeDigest(*types.NewBabePrimaryPreDigest(
authorityIndex, slot2.number,
testVRFOutputAndProof.output,
testVRFOutputAndProof.proof,
).ToPreRuntimeDigest()
))
require.NoError(t, err)

parentHash := babeService.blockState.GenesisHash()
Expand All @@ -187,11 +187,11 @@ func TestApplyExtrinsic(t *testing.T) {
require.NoError(t, err)
rt.SetContextStorage(ts)

preDigest, err := types.NewBabePrimaryPreDigest(
preDigest, err := types.ToPreRuntimeDigest(*types.NewBabePrimaryPreDigest(
authorityIndex, slot.number,
testVRFOutputAndProof.output,
testVRFOutputAndProof.proof,
).ToPreRuntimeDigest()
))
require.NoError(t, err)

digest := types.NewDigest()
Expand Down
39 changes: 35 additions & 4 deletions lib/babe/crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,19 +84,50 @@ func checkPrimaryThreshold(randomness Randomness,
return inoutUint.Compare(threshold) < 0, nil
}

func claimSecondarySlotVRF(randomness Randomness,
slot, epoch uint64,
authorities []types.Authority,
keypair *sr25519.Keypair,
authorityIndex uint32,
) (*VrfOutputAndProof, error) {

secondarySlotAuthor, err := getSecondarySlotAuthor(slot, len(authorities), randomness)
if err != nil {
return nil, fmt.Errorf("cannot get secondary slot author: %w", err)
}

if authorityIndex != secondarySlotAuthor {
return nil, errNotOurTurnToPropose
}

transcript := makeTranscript(randomness, slot, epoch)

out, proof, err := keypair.VrfSign(transcript)
if err != nil {
return nil, fmt.Errorf("cannot verify transcript: %w", err)
}

logger.Debugf("claimed secondary slot, for slot number: %d", slot)

return &VrfOutputAndProof{
output: out,
proof: proof,
}, nil
}

func claimSecondarySlotPlain(randomness Randomness, slot uint64, authorities []types.Authority, authorityIndex uint32,
) error {
secondarySlotAuthor, err := getSecondarySlotAuthor(slot, len(authorities), randomness)
if err != nil {
return fmt.Errorf("cannot get secondary slot author: %w", err)
}

if authorityIndex == secondarySlotAuthor {
logger.Debugf("claimed secondary slot, for slot number: %d", slot)
return nil
if authorityIndex != secondarySlotAuthor {
return errNotOurTurnToPropose
}

return errNotOurTurnToPropose
logger.Debugf("claimed secondary slot, for slot number: %d", slot)
return nil
}

// CalculateThreshold calculates the slot lottery threshold
Expand Down
Loading

0 comments on commit 34f2605

Please sign in to comment.