Skip to content

Commit

Permalink
Jimmy/babe unit tests (#2127)
Browse files Browse the repository at this point in the history
* chore(pkg/scale): return error if `Result` already has an assigned value  (#2143)

* fix: return error if result already has an assigned value

* chore: include unit test

* chore: fix typo `ErrResultAlreadySet`

* chore: remove unneeded `require.Error`

* chore: fix undeclared name

* chore: remove packaged scope var to avoid problems with result type

* chore: fix result.Set error at offchain test

* init

* migrate current tests to integration tests

* fix linting

* test line endings

* remove test comments

* test getSecondarySlotAuthor

* secondary unit tests

* calculate threshold tests

* remove logs

* test checkPrimaryThreshold

* test babe/crypto

* getAuthorityIndex test

* babe mocks with mockgen

* test verifyPrimarySlotWinner

* test verifyPreruntime Digest

* WIP/Test cases for verify authorship right

* finish hitting test cases for equivocation

* clean up naming for verifyBlockAuthor test

* create helper for making verifier

* use helpers to clean up verifyAuthorship test

* clean up mocks

* getConfigData test

* test getVerifierInfo

* remove logs

* test first block cases for block verification

* test VerifyBlock

* finish first half of babe unit tests

* remove coverage files

* remove accidental diff

* remove accidental diff again

* fix linting

* remove testing aliases

* make calculate threshold error global

* add go generate comment for babe state TODO/make sure ok form

* fix mock generation

* add newline to end of build integration test

* newlines

* wip/newline

* test line endings

* wip

* remove crypto integration test

* change threshold err message

* wip

* test

* remove test comments

* clean up

* fix build error

* CR feedback

* more CR feedback

* change threshold error name

* remove empty fields

* change how mockgen used

* remove test log

* cr feedback

* remove errors from helper funcs

* final helper fix

* rebase and lint

* CR feedback

* lint

Co-authored-by: Eclésio Junior <eclesiomelo.1@gmail.com>
  • Loading branch information
jimjbrettj and EclesioMeloJunior authored Jan 14, 2022
1 parent cb360ab commit e1f7f96
Show file tree
Hide file tree
Showing 13 changed files with 2,728 additions and 382 deletions.
4 changes: 3 additions & 1 deletion lib/babe/babe_test.go → lib/babe/babe_integration_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// Copyright 2021 ChainSafe Systems (ON)
// SPDX-License-Identifier: LGPL-3.0-only

//go:build integration
// +build integration

package babe

import (
Expand Down Expand Up @@ -39,7 +42,6 @@ var (
keyring, _ = keystore.NewSr25519Keyring()

maxThreshold = scale.MaxUint128
minThreshold = &scale.Uint128{}

genesisHeader *types.Header
emptyHeader = &types.Header{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// Copyright 2021 ChainSafe Systems (ON)
// SPDX-License-Identifier: LGPL-3.0-only

//go:build integration
// +build integration

package babe

import (
Expand Down Expand Up @@ -392,7 +395,7 @@ func TestBuildBlock_failing(t *testing.T) {
}

// create proof that we can authorize this block
babeService.epochData.threshold = minThreshold
babeService.epochData.threshold = &scale.Uint128{}
var slotNumber uint64 = 1

outAndProof, err := babeService.runLottery(slotNumber, testEpochIndex)
Expand Down
3 changes: 3 additions & 0 deletions lib/babe/crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ func checkPrimaryThreshold(randomness Randomness,
// 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
func CalculateThreshold(C1, C2 uint64, numAuths int) (*scale.Uint128, error) {
if C1 == 0 || C2 == 0 {
return nil, ErrThresholdOneIsZero
}
c := float64(C1) / float64(C2)
if c > 1 {
return nil, errors.New("invalid C1/C2: greater than 1")
Expand Down
194 changes: 159 additions & 35 deletions lib/babe/crypto_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,46 +4,170 @@
package babe

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestRunLottery(t *testing.T) {
babeService := createTestService(t, nil)

babeService.epochData.threshold = maxThreshold

outAndProof, err := babeService.runLottery(0, testEpochIndex)
require.NoError(t, err)
require.NotNil(t, outAndProof)
}
"errors"

func TestRunLottery_False(t *testing.T) {
babeService := createTestService(t, nil)
babeService.epochData.threshold = minThreshold
"github.com/ChainSafe/gossamer/lib/crypto/sr25519"
"github.com/ChainSafe/gossamer/lib/keystore"
"github.com/ChainSafe/gossamer/pkg/scale"
"github.com/stretchr/testify/assert"

outAndProof, err := babeService.runLottery(0, testEpochIndex)
require.ErrorIs(t, err, errOverPrimarySlotThreshold)
require.Nil(t, outAndProof)
}
"testing"
)

func TestCalculateThreshold(t *testing.T) {
// C = 1
var C1 uint64 = 1
var C2 uint64 = 1

expected := maxThreshold

threshold, err := CalculateThreshold(C1, C2, 3)
require.NoError(t, err)
require.Equal(t, expected, threshold)
type args struct {
C1 uint64
C2 uint64
numAuths int
}
tests := []struct {
name string
args args
exp *scale.Uint128
expErr error
}{
{
name: "happy path",
args: args{
C1: 1,
C2: 2,
numAuths: 3,
},
exp: &scale.Uint128{Upper: 0x34d00ad6148e1800, Lower: 0x0},
},
{
name: "0 value input",
args: args{
C1: 0,
C2: 0,
numAuths: 0,
},
expErr: ErrThresholdOneIsZero,
},
{
name: "C1 > C2",
args: args{
C1: 5,
C2: 2,
numAuths: 0,
},
expErr: errors.New("invalid C1/C2: greater than 1"),
},
{
name: "max threshold",
args: args{
C1: 1,
C2: 1,
numAuths: 3,
},
exp: scale.MaxUint128,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
res, err := CalculateThreshold(tt.args.C1, tt.args.C2, tt.args.numAuths)
if tt.expErr != nil {
assert.EqualError(t, err, tt.expErr.Error())
} else {
assert.NoError(t, err)
}
assert.Equal(t, tt.exp, res)
})
}
}

func TestCalculateThreshold_Failing(t *testing.T) {
var C1 uint64 = 5
var C2 uint64 = 4
func Test_checkPrimaryThreshold(t *testing.T) {
keyring, _ := keystore.NewSr25519Keyring()
aliceKeypair := keyring.Alice().(*sr25519.Keypair)
type args struct {
randomness Randomness
slot uint64
epoch uint64
output [sr25519.VRFOutputLength]byte
threshold *scale.Uint128
pub *sr25519.PublicKey
}
tests := []struct {
name string
args args
exp bool
}{
{
name: "happy path true",
args: args{
threshold: scale.MaxUint128,
pub: aliceKeypair.Public().(*sr25519.PublicKey),
},
exp: true,
},
{
name: "happy path false",
args: args{
threshold: &scale.Uint128{},
pub: aliceKeypair.Public().(*sr25519.PublicKey),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
res, err := checkPrimaryThreshold(tt.args.randomness, tt.args.slot, tt.args.epoch,
tt.args.output, tt.args.threshold, tt.args.pub)
assert.NoError(t, err)
assert.Equal(t, tt.exp, res)
})
}
}

_, err := CalculateThreshold(C1, C2, 3)
require.NotNil(t, err)
func Test_claimPrimarySlot(t *testing.T) {
keyring, _ := keystore.NewSr25519Keyring()
type args struct {
randomness Randomness
slot uint64
epoch uint64
threshold *scale.Uint128
keypair *sr25519.Keypair
}
tests := []struct {
name string
args args
exp *VrfOutputAndProof
expErr error
}{
{
name: "authority not authorized",
args: args{
slot: 1,
epoch: 2,
threshold: &scale.Uint128{},
keypair: keyring.Alice().(*sr25519.Keypair),
},
expErr: errors.New("cannot claim slot, over primary threshold: for slot 1, epoch 2 and threshold 0"),
},
{
name: "authority authorized",
args: args{
slot: 1,
epoch: 2,
threshold: scale.MaxUint128,
keypair: keyring.Alice().(*sr25519.Keypair),
},
exp: &VrfOutputAndProof{
output: [32]uint8{0x80, 0xf0, 0x8a, 0x7d, 0xa1, 0x71, 0x77, 0xdc, 0x7, 0x7f, 0x6, 0xd5, 0xc1, 0x5d, 0x90,
0x4f, 0x64, 0x21, 0xb6, 0x1d, 0x1c, 0xa8, 0x55, 0x3a, 0x97, 0x1a, 0xbb, 0xf3, 0x35, 0x12, 0x25, 0x18},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
res, err := claimPrimarySlot(tt.args.randomness, tt.args.slot, tt.args.epoch, tt.args.threshold, tt.args.keypair)
if tt.expErr != nil {
assert.EqualError(t, err, tt.expErr.Error())
} else {
assert.NoError(t, err)
}
if tt.exp != nil && res != nil {
assert.Equal(t, tt.exp.output, res.output)
}
})
}
}
3 changes: 3 additions & 0 deletions lib/babe/epoch_test.go → lib/babe/epoch_integration_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// Copyright 2021 ChainSafe Systems (ON)
// SPDX-License-Identifier: LGPL-3.0-only

//go:build integration
// +build integration

package babe

import (
Expand Down
12 changes: 12 additions & 0 deletions lib/babe/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ var (
// ErrNotAuthority is returned when trying to perform authority functions when not an authority
ErrNotAuthority = errors.New("node is not an authority")

// ErrThresholdOneIsZero is returned when one of or both parameters to CalculateThreshold is zero
ErrThresholdOneIsZero = errors.New("numerator or denominator cannot be 0")

errNilBlockImportHandler = errors.New("cannot have nil BlockImportHandler")
errNilBlockState = errors.New("cannot have nil BlockState")
errNilEpochState = errors.New("cannot have nil EpochState")
Expand All @@ -67,6 +70,15 @@ var (
errFirstBlockTimeout = errors.New("timed out waiting for first block")
errChannelClosed = errors.New("block notifier channel was closed")
errOverPrimarySlotThreshold = errors.New("cannot claim slot, over primary threshold")
errNoConfigData = errors.New("cannot find ConfigData for epoch")
errGetEpochData = errors.New("get epochData error")
errFailedFinalisation = errors.New("failed to check finalisation")
errMissingDigest = errors.New("chain head missing digest")
errSetFirstSlot = errors.New("set first slot error")
errGetEpoch = errors.New("get epoch error")
errSkipVerify = errors.New("skipVerify error")
errMissingDigestItems = errors.New("block header is missing digest items")
errDescendant = errors.New("descendant err")

other Other
invalidCustom InvalidCustom
Expand Down
Loading

0 comments on commit e1f7f96

Please sign in to comment.