Skip to content

Commit

Permalink
feat(lib/babe): implement secondary slot block production
Browse files Browse the repository at this point in the history
  • Loading branch information
kishansagathiya committed Feb 1, 2022
1 parent 6fb057e commit ee5be4d
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 1 deletion.
41 changes: 41 additions & 0 deletions lib/babe/crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
package babe

import (
"bytes"
"errors"
"fmt"
"math"
"math/big"

"github.com/ChainSafe/gossamer/dot/types"
"github.com/ChainSafe/gossamer/lib/crypto"
"github.com/ChainSafe/gossamer/lib/crypto/sr25519"
"github.com/ChainSafe/gossamer/pkg/scale"
Expand Down Expand Up @@ -83,6 +85,45 @@ func checkPrimaryThreshold(randomness Randomness,
return inoutUint.Compare(threshold) < 0, nil
}

func i32toBytes(val uint32) []byte {
r := make([]byte, 4)
for i := uint32(0); i < 4; i++ {
r[i] = byte((val >> (8 * i)) & 0xff)
}
return r
}

func claimSecondarySlot(randomness Randomness,
slot, epoch uint64,
authorities []types.Authority,
threshold *scale.Uint128,
keypair *sr25519.Keypair,
) (*VrfOutputAndProof, error) {

secondarySlotAuthor, err := getSecondarySlotAuthor(slot, len(authorities), randomness)
if err != nil {
return nil, err
}

for _, authority := range authorities {
if bytes.Equal(authority.ToRaw().Key[:], i32toBytes(secondarySlotAuthor)) {
transcript := makeTranscript(randomness, slot, epoch)

out, proof, err := keypair.VrfSign(transcript)
if err != nil {
return nil, err
}

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

return nil, nil
}

// CalculateThreshold calculates the slot lottery threshold
// equation: threshold = 2^128 * (1 - (1-c)^(1/len(authorities))
// see https://github.com/paritytech/substrate/blob/master/client/consensus/babe/src/authorship.rs#L44
Expand Down
13 changes: 12 additions & 1 deletion lib/babe/epoch.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ func (b *Service) initiateEpoch(epoch uint64) error {
authorities: data.Authorities,
authorityIndex: idx,
threshold: threshold,
secondary: cfgData.SecondarySlots,
}
} else {
b.epochData = &epochData{
Expand Down Expand Up @@ -174,11 +175,21 @@ func (b *Service) incrementEpoch() (uint64, error) {
// if it is not authorised.
// output = return[0:32]; proof = return[32:96]
func (b *Service) runLottery(slot, epoch uint64) (*VrfOutputAndProof, error) {
return claimPrimarySlot(
// here: If we can't claim primary slot, claim secondary slot
proof, err := claimPrimarySlot(
b.epochData.randomness,
slot,
epoch,
b.epochData.threshold,
b.keypair,
)
if err == nil {
return proof, nil
}

if b.epochData.secondary != 1 && b.epochData.secondary != 2 {
return nil, err
}

return claimSecondarySlot(b.epochData.randomness, slot, epoch, b.epochData.authorities, b.epochData.threshold, b.keypair)
}
1 change: 1 addition & 0 deletions lib/babe/secondary.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/ChainSafe/gossamer/lib/crypto/sr25519"
)

// https://github.com/paritytech/substrate/blob/b07765f9ecc4c508fb4d0fba930b476c8509f5c2/client/consensus/babe/src/authorship.rs#L98
func getSecondarySlotAuthor(slot uint64, numAuths int, randomness Randomness) (uint32, error) {
s := make([]byte, 8)
binary.LittleEndian.PutUint64(s, slot)
Expand Down
1 change: 1 addition & 0 deletions lib/babe/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ type epochData struct {
authorityIndex uint32
authorities []types.Authority
threshold *scale.Uint128
secondary byte
}

func (ed *epochData) String() string {
Expand Down

0 comments on commit ee5be4d

Please sign in to comment.