Skip to content

Commit

Permalink
feat(lib/babe): add check of types.ConfigData.SecondarySlots for disa…
Browse files Browse the repository at this point in the history
…bling secondary verification (ChainSafe#1910)

* add check for types.ConfigData.SecondarySlots

* Update lib/babe/verify.go

Co-authored-by: Quentin McGaw <quentin.mcgaw@gmail.com>

* update ok = false if !b.secondarySlots

* stub test for secondary verification

* add test to verify secondary digest

* address PR comments

* add err check

* update pointers to fix tests

* add tests for decoding

* my wip

* fix VRF encoding

* update linter tags

Co-authored-by: Quentin McGaw <quentin.mcgaw@gmail.com>
Co-authored-by: Tim Wu <timwu20@gmail.com>
  • Loading branch information
3 people committed Dec 6, 2021
1 parent 13c92ea commit 7bc2e32
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 23 deletions.
2 changes: 1 addition & 1 deletion dot/types/babe.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func (d *EpochDataRaw) ToEpochData() (*EpochData, error) {
type ConfigData struct {
C1 uint64
C2 uint64
SecondarySlots byte // TODO: this is unused, will need to update BABE verifier to use this (#1863)
SecondarySlots byte
}

// GetSlotFromHeader returns the BABE slot from the given header
Expand Down
53 changes: 35 additions & 18 deletions lib/babe/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ import (
// verifierInfo contains the information needed to verify blocks
// it remains the same for an epoch
type verifierInfo struct {
authorities []types.Authority
randomness Randomness
threshold *common.Uint128
authorities []types.Authority
randomness Randomness
threshold *common.Uint128
secondarySlots bool
}

// onDisabledInfo contains information about an authority that's been disabled at a certain
Expand Down Expand Up @@ -224,9 +225,10 @@ func (v *VerificationManager) getVerifierInfo(epoch uint64) (*verifierInfo, erro
}

return &verifierInfo{
authorities: epochData.Authorities,
randomness: epochData.Randomness,
threshold: threshold,
authorities: epochData.Authorities,
randomness: epochData.Randomness,
threshold: threshold,
secondarySlots: configData.SecondarySlots > 0,
}, nil
}

Expand All @@ -247,11 +249,12 @@ func (v *VerificationManager) getConfigData(epoch uint64) (*types.ConfigData, er

// verifier is a BABE verifier for a specific authority set, randomness, and threshold
type verifier struct {
blockState BlockState
epoch uint64
authorities []types.Authority
randomness Randomness
threshold *common.Uint128
blockState BlockState
epoch uint64
authorities []types.Authority
randomness Randomness
threshold *common.Uint128
secondarySlots bool
}

// newVerifier returns a Verifier for the epoch described by the given descriptor
Expand All @@ -261,11 +264,12 @@ func newVerifier(blockState BlockState, epoch uint64, info *verifierInfo) (*veri
}

return &verifier{
blockState: blockState,
epoch: epoch,
authorities: info.authorities,
randomness: info.randomness,
threshold: info.threshold,
blockState: blockState,
epoch: epoch,
authorities: info.authorities,
randomness: info.randomness,
threshold: info.threshold,
secondarySlots: info.secondarySlots,
}, nil
}

Expand Down Expand Up @@ -409,15 +413,28 @@ func (b *verifier) verifyPreRuntimeDigest(digest *types.PreRuntimeDigest) (scale
case types.BabePrimaryPreDigest:
ok, err = b.verifyPrimarySlotWinner(d.AuthorityIndex, d.SlotNumber, d.VRFOutput, d.VRFProof)
case types.BabeSecondaryVRFPreDigest:
if !b.secondarySlots {
ok = false
break
}
pub := b.authorities[d.AuthorityIndex].Key
var pk *sr25519.PublicKey
pk, err = sr25519.NewPublicKey(pub.Encode())

pk, err := sr25519.NewPublicKey(pub.Encode())
if err != nil {
return nil, err
}

ok, err = verifySecondarySlotVRF(&d, pk, b.epoch, len(b.authorities), b.randomness)
if err != nil {
return nil, err
}

case types.BabeSecondaryPlainPreDigest:
if !b.secondarySlots {
ok = false
break
}

ok = true
err = verifySecondarySlotPlain(d.AuthorityIndex, d.SlotNumber, len(b.authorities), b.randomness)
}
Expand Down
69 changes: 65 additions & 4 deletions lib/babe/verify_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,19 @@ package babe
import (
"errors"
"io/ioutil"
"math/big"
"os"
"testing"
"time"

"github.com/ChainSafe/gossamer/lib/genesis"
"github.com/stretchr/testify/require"

"github.com/ChainSafe/gossamer/dot/state"
"github.com/ChainSafe/gossamer/dot/types"
"github.com/ChainSafe/gossamer/lib/common"
"github.com/ChainSafe/gossamer/lib/crypto/sr25519"

"github.com/ChainSafe/gossamer/lib/genesis"
"github.com/ChainSafe/gossamer/pkg/scale"
log "github.com/ChainSafe/log15"
"github.com/stretchr/testify/require"
)

func newTestVerificationManager(t *testing.T, genCfg *types.BabeConfiguration) *VerificationManager {
Expand Down Expand Up @@ -162,6 +163,66 @@ func TestVerificationManager_VerifyBlock_Ok(t *testing.T) {
require.NoError(t, err)
}

func TestVerificationManager_VerifyBlock_Secondary(t *testing.T) {
babeService := createTestService(t, nil)
rt, err := babeService.blockState.GetRuntime(nil)
require.NoError(t, err)

cfg, err := rt.BabeConfiguration()
require.NoError(t, err)

cfg.GenesisAuthorities = types.AuthoritiesToRaw(babeService.epochData.authorities)
cfg.C1 = 1
cfg.C2 = 1
cfg.SecondarySlots = 0

vm := newTestVerificationManager(t, cfg)

kp, err := sr25519.GenerateKeypair()
require.NoError(t, err)

dig := createSecondaryVRFPreDigest(t, kp, 0, uint64(0), uint64(0), Randomness{})

bd := types.NewBabeDigest()
err = bd.Set(dig)
require.NoError(t, err)

bdEnc, err := scale.Marshal(bd)
require.NoError(t, err)

// create pre-digest
preDigest := &types.PreRuntimeDigest{
ConsensusEngineID: types.BabeEngineID,
Data: bdEnc,
}

// create new block header
number := big.NewInt(1)
digest := types.NewDigest()
err = digest.Add(*preDigest)
require.NoError(t, err)

// create seal and add to digest
seal := &types.SealDigest{
ConsensusEngineID: types.BabeEngineID,
Data: []byte{0},
}
require.NoError(t, err)

err = digest.Add(*seal)
require.NoError(t, err)

header, err := types.NewHeader(common.Hash{}, common.Hash{}, common.Hash{}, number, digest)
require.NoError(t, err)

block := types.Block{
Header: *header,
Body: nil,
}
err = vm.VerifyBlock(&block.Header)
require.EqualError(t, err, "failed to verify pre-runtime digest: could not verify slot claim VRF proof")
}

func TestVerificationManager_VerifyBlock_MultipleEpochs(t *testing.T) {
babeService := createTestService(t, nil)
rt, err := babeService.blockState.GetRuntime(nil)
Expand Down

0 comments on commit 7bc2e32

Please sign in to comment.