Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Consensus] Use SignerIndices in CollectionGuarantee (3/4) #2140

Merged
merged 56 commits into from
Mar 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
322f342
implement IdentitiesByIndices
zhangchiqing Feb 25, 2022
45d32dc
implement encoding and decoding
zhangchiqing Mar 2, 2022
6fc869a
remove IdentitiesByIndices
zhangchiqing Mar 3, 2022
10d3afe
use ParentVoterIndices
zhangchiqing Mar 8, 2022
f7b85bc
use chainID
zhangchiqing Mar 8, 2022
3988014
add ChainID
zhangchiqing Mar 10, 2022
3bb324e
fix test case
zhangchiqing Mar 10, 2022
3392230
remove file
zhangchiqing Mar 10, 2022
7654289
sort assignment to canonical order
zhangchiqing Mar 10, 2022
b394261
fix guarantee
zhangchiqing Mar 10, 2022
e604715
fix execution ingestion core
zhangchiqing Mar 11, 2022
205a108
use signer indices
zhangchiqing Mar 11, 2022
1b5beb5
add identifierOrder
zhangchiqing Mar 11, 2022
23d069d
use guarantor.FindGuarantors
zhangchiqing Mar 11, 2022
7b3a1ee
fix tests
zhangchiqing Mar 11, 2022
637f768
fix tests
zhangchiqing Mar 11, 2022
b5c1ae9
fix tests
zhangchiqing Mar 11, 2022
1865e88
disable tests
zhangchiqing Mar 14, 2022
9a67913
fix tests
zhangchiqing Mar 14, 2022
8363d31
fix tests, add validation
zhangchiqing Mar 15, 2022
758f675
fix fvm test
zhangchiqing Mar 15, 2022
e7c9621
fix access tests
zhangchiqing Mar 15, 2022
5f677dc
fix tests
zhangchiqing Mar 15, 2022
c904dae
fix tests
zhangchiqing Mar 15, 2022
9d29c1c
fix select_filter_test tests
zhangchiqing Mar 15, 2022
93eff7f
fix access tests
zhangchiqing Mar 15, 2022
81bde78
fix access integration
zhangchiqing Mar 15, 2022
e73964b
fix access integration tests
zhangchiqing Mar 15, 2022
f2b16d6
revert fvm_test changes
zhangchiqing Mar 16, 2022
9f6e10c
update fvm_test
zhangchiqing Mar 16, 2022
e5abf7b
fix exec tests
zhangchiqing Mar 16, 2022
5dd7c4c
fix ingestion engine tests
zhangchiqing Mar 16, 2022
d88c7d2
fix test cases
zhangchiqing Mar 17, 2022
310acdc
remove todo
zhangchiqing Mar 17, 2022
84560ca
fix error handling
zhangchiqing Mar 17, 2022
aa1d52f
add comment
zhangchiqing Mar 17, 2022
a681d60
fix tests
zhangchiqing Mar 18, 2022
c4e63d4
update logging
zhangchiqing Mar 18, 2022
6adfcdf
refactor
zhangchiqing Mar 21, 2022
b06fec6
fix tests
zhangchiqing Mar 21, 2022
9e45942
remove function
zhangchiqing Mar 25, 2022
bf1ab10
fix error wrapping
zhangchiqing Mar 25, 2022
1ee8ba8
update comment
zhangchiqing Mar 25, 2022
7c88ade
update tests
zhangchiqing Mar 25, 2022
553603a
remove unverified signature
zhangchiqing Mar 25, 2022
b885f9d
revert mutator tests change
zhangchiqing Mar 25, 2022
8dd8c35
update comment
zhangchiqing Mar 25, 2022
16bfbfc
address comments
zhangchiqing Mar 28, 2022
69196e7
add tests
zhangchiqing Mar 28, 2022
fbd30bf
add check in NewClusterList to ensure the assignments are sorted in
zhangchiqing Mar 28, 2022
34c8a03
rename method
zhangchiqing Mar 28, 2022
ecabd59
consensus ingestion core log signer indices
zhangchiqing Mar 28, 2022
765ea0e
remove tests log
zhangchiqing Mar 28, 2022
207fe59
refactor canonical order check
zhangchiqing Mar 28, 2022
770e549
replace order.ByNodeIDAsc with order.Canonical
zhangchiqing Mar 28, 2022
f7a9f89
[Consensus] Refactor for guarantee signer indices (4/4) (#2204)
zhangchiqing Mar 30, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions cmd/bootstrap/cmd/clusters.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
model "github.com/onflow/flow-go/model/bootstrap"
"github.com/onflow/flow-go/model/cluster"
"github.com/onflow/flow-go/model/flow"
"github.com/onflow/flow-go/model/flow/assignment"
"github.com/onflow/flow-go/model/flow/factory"
"github.com/onflow/flow-go/model/flow/filter"
)

Expand All @@ -23,20 +25,22 @@ func constructClusterAssignment(partnerNodes, internalNodes []model.NodeInfo, se
internals = internals.DeterministicShuffle(seed)

nClusters := flagCollectionClusters
assignments := make(flow.AssignmentList, nClusters)
identifierLists := make([]flow.IdentifierList, nClusters)

// first, round-robin internal nodes into each cluster
for i, node := range internals {
assignments[i%len(assignments)] = append(assignments[i%len(assignments)], node.NodeID)
identifierLists[i%len(identifierLists)] = append(identifierLists[i%len(identifierLists)], node.NodeID)
}

// next, round-robin partner nodes into each cluster
for i, node := range partners {
assignments[i%len(assignments)] = append(assignments[i%len(assignments)], node.NodeID)
identifierLists[i%len(identifierLists)] = append(identifierLists[i%len(identifierLists)], node.NodeID)
}

assignments := assignment.FromIdentifierLists(identifierLists)

collectors := append(partners, internals...)
clusters, err := flow.NewClusterList(assignments, collectors)
clusters, err := factory.NewClusterList(assignments, collectors)
if err != nil {
log.Fatal().Err(err).Msg("could not create cluster list")
}
Expand Down
12 changes: 6 additions & 6 deletions cmd/bootstrap/cmd/constraints.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,12 @@ func checkConstraints(partnerNodes, internalNodes []model.NodeInfo) {
if _, exists := internals.ByNodeID(node.NodeID); exists {
clusterInternalCount++
}
if clusterInternalCount <= clusterPartnerCount*2 {
log.Fatal().Msgf(
"will not bootstrap configuration without Byzantine majority within cluster: "+
"(partners=%d, internals=%d, min_internals=%d)",
clusterPartnerCount, clusterInternalCount, clusterPartnerCount*2+1)
}
}
if clusterInternalCount <= clusterPartnerCount*2 {
log.Fatal().Msgf(
"will not bootstrap configuration without Byzantine majority within cluster: "+
"(partners=%d, internals=%d, min_internals=%d)",
clusterPartnerCount, clusterInternalCount, clusterPartnerCount*2+1)
}
partnerCOLCount += clusterPartnerCount
internalCOLCount += clusterInternalCount
Expand Down
4 changes: 2 additions & 2 deletions cmd/bootstrap/cmd/seal.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"github.com/onflow/flow-go/model/dkg"
"github.com/onflow/flow-go/model/flow"
"github.com/onflow/flow-go/model/flow/order"
"github.com/onflow/flow-go/module/packer"
"github.com/onflow/flow-go/module/signature"
)

func constructRootResultAndSeal(
Expand Down Expand Up @@ -47,7 +47,7 @@ func constructRootResultAndSeal(
qcsWithSignerIDs := make([]*flow.QuorumCertificateWithSignerIDs, 0, len(clusterQCs))
for i, clusterQC := range clusterQCs {
members := assignments[i]
signerIDs, err := packer.DecodeSignerIdentifiersFromIndices(members, clusterQC.SignerIndices)
signerIDs, err := signature.DecodeSignerIndicesToIdentifiers(members, clusterQC.SignerIndices)
if err != nil {
log.Fatal().Err(err).Msgf("could not decode signer IDs from clusterQC at index %v", i)
}
Expand Down
4 changes: 2 additions & 2 deletions cmd/util/cmd/epochs/cmd/reset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func TestReset_LocalSnapshot(t *testing.T) {
unittest.RunWithTempDir(t, func(bootDir string) {

// create a root snapshot
rootSnapshot := unittest.RootSnapshotFixture(unittest.IdentityListFixture(10))
rootSnapshot := unittest.RootSnapshotFixture(unittest.IdentityListFixture(10, unittest.WithAllRoles()))

// write snapshot to correct path in bootDir
err := writeRootSnapshot(bootDir, rootSnapshot)
Expand Down Expand Up @@ -62,7 +62,7 @@ func TestReset_LocalSnapshot(t *testing.T) {
unittest.RunWithTempDir(t, func(bootDir string) {

// create a root snapshot
rootSnapshot := unittest.RootSnapshotFixture(unittest.IdentityListFixture(10))
rootSnapshot := unittest.RootSnapshotFixture(unittest.IdentityListFixture(10, unittest.WithAllRoles()))

// write snapshot to correct path in bootDir
err := writeRootSnapshot(bootDir, rootSnapshot)
Expand Down
13 changes: 7 additions & 6 deletions consensus/follower_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"testing"
"time"

"github.com/onflow/flow-go/module/signature"

"github.com/rs/zerolog"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
Expand All @@ -16,7 +18,6 @@ import (
"github.com/onflow/flow-go/consensus/hotstuff/model"
"github.com/onflow/flow-go/model/flow"
mockmodule "github.com/onflow/flow-go/module/mock"
"github.com/onflow/flow-go/module/packer"
mockstorage "github.com/onflow/flow-go/storage/mock"
"github.com/onflow/flow-go/utils/unittest"
)
Expand Down Expand Up @@ -69,9 +70,9 @@ func (s *HotStuffFollowerSuite) SetupTest() {

// mock consensus committee
s.committee = &mockhotstuff.Committee{}
s.committee.On("Identities", mock.Anything, mock.Anything).Return(
func(blockID flow.Identifier, selector flow.IdentityFilter) flow.IdentityList {
return identities.Filter(selector)
s.committee.On("Identities", mock.Anything).Return(
func(blockID flow.Identifier) flow.IdentityList {
return identities
},
nil,
)
Expand Down Expand Up @@ -107,7 +108,7 @@ func (s *HotStuffFollowerSuite) SetupTest() {
View: 52078,
}

signerIndices, err := packer.EncodeSignerIdentifiersToIndices(identities.NodeIDs(), identities.NodeIDs()[:3])
signerIndices, err := signature.EncodeSignersToIndices(identities.NodeIDs(), identities.NodeIDs()[:3])
require.NoError(s.T(), err)
s.rootQC = &flow.QuorumCertificate{
View: s.rootHeader.View,
Expand Down Expand Up @@ -339,7 +340,7 @@ func (mc *MockConsensus) extendBlock(blockView uint64, parent *flow.Header) *flo
nextBlock := unittest.BlockHeaderWithParentFixture(parent)
nextBlock.View = blockView
nextBlock.ProposerID = mc.identities[int(blockView)%len(mc.identities)].NodeID
signerIndices, _ := packer.EncodeSignerIdentifiersToIndices(mc.identities.NodeIDs(), mc.identities.NodeIDs())
signerIndices, _ := signature.EncodeSignersToIndices(mc.identities.NodeIDs(), mc.identities.NodeIDs())
nextBlock.ParentVoterIndices = signerIndices
return &nextBlock
}
76 changes: 36 additions & 40 deletions consensus/hotstuff/committees/leader/leader_selection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,59 +304,55 @@ func TestZeroStakedNodeWillNotBeSelected(t *testing.T) {
rng, err := random.NewChacha20PRG(someSeed, []byte("leader_selec"))
require.NoError(t, err)

for i := 0; i < 100; i++ {
// create 1002 nodes with all 0 stake
identities := unittest.IdentityListFixture(1002, unittest.WithStake(0))

// create 2 nodes with 1 stake, and place them in between
// index 233-777
n := rng.UintN(777-233) + 233
m := rng.UintN(777-233) + 233
identities[n].Stake = 1
identities[m].Stake = 1

// the following code check the zero staker should not be selected
stakeful := identities.Filter(filter.HasStake(true))

count := 1000
selectionFromAll, err := ComputeLeaderSelectionFromSeed(0, someSeed, count, identities)
require.NoError(t, err)
// create 1002 nodes with all 0 stake
identities := unittest.IdentityListFixture(1002, unittest.WithStake(0))

selectionFromStakeful, err := ComputeLeaderSelectionFromSeed(0, someSeed, count, stakeful)
require.NoError(t, err)
// create 2 nodes with 1 stake, and place them in between
// index 233-777
n := rng.UintN(777-233) + 233
m := rng.UintN(777-233) + 233
identities[n].Stake = 1
identities[m].Stake = 1

for i := 0; i < count; i++ {
nodeIDFromAll, err := selectionFromAll.LeaderForView(uint64(i))
require.NoError(t, err)
// the following code check the zero staker should not be selected
stakeful := identities.Filter(filter.HasStake(true))

nodeIDFromStakeful, err := selectionFromStakeful.LeaderForView(uint64(i))
require.NoError(t, err)
count := 1000
selectionFromAll, err := ComputeLeaderSelectionFromSeed(0, someSeed, count, identities)
require.NoError(t, err)

// the selection should be the same
require.Equal(t, nodeIDFromStakeful, nodeIDFromAll)
}
selectionFromStakeful, err := ComputeLeaderSelectionFromSeed(0, someSeed, count, stakeful)
require.NoError(t, err)

for i := 0; i < count; i++ {
nodeIDFromAll, err := selectionFromAll.LeaderForView(uint64(i))
require.NoError(t, err)

nodeIDFromStakeful, err := selectionFromStakeful.LeaderForView(uint64(i))
require.NoError(t, err)

// the selection should be the same
require.Equal(t, nodeIDFromStakeful, nodeIDFromAll)
}

t.Run("if there is only 1 node has stake, then it will be always be the leader and the only leader", func(t *testing.T) {
rng, err := random.NewChacha20PRG(someSeed, []byte("leader_selec"))
require.NoError(t, err)

for i := 0; i < 100; i++ {
identities := unittest.IdentityListFixture(1000, unittest.WithStake(0))
identities := unittest.IdentityListFixture(1000, unittest.WithStake(0))

n := rng.UintN(1000)
stake := n + 1
identities[n].Stake = stake
onlyStaked := identities[n]
n := rng.UintN(1000)
stake := n + 1
identities[n].Stake = stake
onlyStaked := identities[n]

selections, err := ComputeLeaderSelectionFromSeed(0, someSeed, 1000, identities)
require.NoError(t, err)
selections, err := ComputeLeaderSelectionFromSeed(0, someSeed, 1000, identities)
require.NoError(t, err)

for i := 0; i < 1000; i++ {
nodeID, err := selections.LeaderForView(uint64(i))
require.NoError(t, err)
require.Equal(t, onlyStaked.NodeID, nodeID)
}
for i := 0; i < 1000; i++ {
nodeID, err := selections.LeaderForView(uint64(i))
require.NoError(t, err)
require.Equal(t, onlyStaked.NodeID, nodeID)
}
})
})
Expand Down
16 changes: 4 additions & 12 deletions consensus/hotstuff/integration/instance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,13 @@ import (
"github.com/onflow/flow-go/consensus/hotstuff/notifications"
"github.com/onflow/flow-go/consensus/hotstuff/pacemaker"
"github.com/onflow/flow-go/consensus/hotstuff/pacemaker/timeout"
hsig "github.com/onflow/flow-go/consensus/hotstuff/signature"
"github.com/onflow/flow-go/consensus/hotstuff/validator"
"github.com/onflow/flow-go/consensus/hotstuff/voteaggregator"
"github.com/onflow/flow-go/consensus/hotstuff/votecollector"
"github.com/onflow/flow-go/consensus/hotstuff/voter"
"github.com/onflow/flow-go/model/flow"
"github.com/onflow/flow-go/module/irrecoverable"
module "github.com/onflow/flow-go/module/mock"
"github.com/onflow/flow-go/module/packer"
msig "github.com/onflow/flow-go/module/signature"
"github.com/onflow/flow-go/utils/unittest"
)
Expand Down Expand Up @@ -209,7 +207,7 @@ func NewInstance(t require.TestingT, options ...Option) *Instance {
View: block.View,
BlockID: block.BlockID,
SignerID: in.localID,
SigData: unittest.RandomBytes(hsig.SigLen * 2), // double sig, one staking, one beacon
SigData: unittest.RandomBytes(msig.SigLen * 2), // double sig, one staking, one beacon
}
return vote
},
Expand All @@ -222,10 +220,8 @@ func NewInstance(t require.TestingT, options ...Option) *Instance {
voterIDs = append(voterIDs, vote.SignerID)
}

signerIndices, err := packer.EncodeSignerIdentifiersToIndices(in.participants.NodeIDs(), voterIDs)
if err != nil {
panic(fmt.Errorf("could not encode signer indices: %w", err))
}
signerIndices, err := msig.EncodeSignersToIndices(in.participants.NodeIDs(), voterIDs)
require.NoError(t, err, "could not encode signer indices")

qc := &flow.QuorumCertificate{
View: votes[0].View,
Expand Down Expand Up @@ -351,7 +347,7 @@ func NewInstance(t require.TestingT, options ...Option) *Instance {
rbRector := helper.MakeRandomBeaconReconstructor(msig.RandomBeaconThreshold(int(in.participants.Count())))
rbRector.On("Verify", mock.Anything, mock.Anything).Return(nil).Maybe()

indices, err := toIndices(in.participants.NodeIDs(), in.participants.NodeIDs())
indices, err := msig.EncodeSignersToIndices(in.participants.NodeIDs(), []flow.Identifier(in.participants.NodeIDs()))
require.NoError(t, err)

packer := &mocks.Packer{}
Expand Down Expand Up @@ -391,10 +387,6 @@ func NewInstance(t require.TestingT, options ...Option) *Instance {
return &in
}

func toIndices(all []flow.Identifier, signers []flow.Identifier) ([]byte, error) {
return packer.EncodeSignerIdentifiersToIndices(all, signers)
}

func (in *Instance) Run() error {
ctx, cancel := context.WithCancel(context.Background())
defer func() {
Expand Down
6 changes: 3 additions & 3 deletions consensus/hotstuff/mocks/packer.go

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

8 changes: 4 additions & 4 deletions consensus/hotstuff/mocks/verifier.go

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

23 changes: 22 additions & 1 deletion consensus/hotstuff/model/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (

var (
ErrUnverifiableBlock = errors.New("block proposal can't be verified, because its view is above the finalized view, but its QC is below the finalized view")
ErrInvalidFormat = errors.New("invalid signature format")
ErrInvalidSignature = errors.New("invalid signature")
)

Expand All @@ -26,6 +25,28 @@ func IsNoVoteError(err error) bool {
return errors.As(err, &e)
}

// InvalidFormatError indicates that some data has an incompatible format.
type InvalidFormatError struct {
err error
}

func NewInvalidFormatError(err error) error {
return InvalidFormatError{err}
}

func NewInvalidFormatErrorf(msg string, args ...interface{}) error {
return InvalidFormatError{fmt.Errorf(msg, args...)}
}

func (e InvalidFormatError) Error() string { return e.err.Error() }
func (e InvalidFormatError) Unwrap() error { return e.err }

// IsInvalidFormatError returns whether err is a InvalidFormatError
func IsInvalidFormatError(err error) bool {
var e InvalidFormatError
return errors.As(err, &e)
}

// ConfigurationError indicates that a constructor or component was initialized with
// invalid or inconsistent parameters.
type ConfigurationError struct {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package packer
package model

import (
"bytes"
"fmt"

"github.com/onflow/flow-go/consensus/hotstuff/model"
"github.com/onflow/flow-go/crypto"
"github.com/onflow/flow-go/model/encoding/rlp"
)
Expand Down Expand Up @@ -49,7 +47,7 @@ func UnpackRandomBeaconSig(sigData []byte) (crypto.Signature, error) {
packer := SigDataPacker{}
sig, err := packer.Decode(sigData)
if err != nil {
return nil, fmt.Errorf("could not decode sig data %s: %w", err, model.ErrInvalidFormat)
return nil, NewInvalidFormatErrorf("could not decode sig data: %w", err)
}
return sig.ReconstructedRandomBeaconSig, nil
}
Loading