package consensus import ( "testing" "time" "github.com/harmony-one/abool" "github.com/harmony-one/harmony/consensus/quorum" "github.com/harmony-one/harmony/crypto/bls" "github.com/harmony-one/harmony/internal/utils" "github.com/harmony-one/harmony/multibls" "github.com/harmony-one/harmony/p2p" "github.com/harmony-one/harmony/shard" "github.com/harmony-one/harmony/staking/slash" "github.com/harmony-one/harmony/test/helpers" "github.com/stretchr/testify/assert" ) func TestConsensusInitialization(t *testing.T) { host, multiBLSPrivateKey, consensus, decider, err := GenerateConsensusForTesting() assert.NoError(t, err) messageSender := &MessageSender{host: host, retryTimes: int(phaseDuration.Seconds()) / RetryIntervalInSec} fbtLog := NewFBFTLog() state := State{mode: Normal} timeouts := createTimeout() expectedTimeouts := make(map[TimeoutType]time.Duration) expectedTimeouts[timeoutConsensus] = phaseDuration expectedTimeouts[timeoutViewChange] = viewChangeDuration expectedTimeouts[timeoutBootstrap] = bootstrapDuration assert.Equal(t, decider, consensus.Decider) assert.Equal(t, host, consensus.host) assert.Equal(t, messageSender, consensus.msgSender) assert.IsType(t, make(chan struct{}), consensus.BlockNumLowChan) // FBFTLog assert.Equal(t, fbtLog, consensus.FBFTLog) assert.Equal(t, FBFTAnnounce, consensus.phase.Get()) // State / consensus.current assert.Equal(t, state.mode, consensus.current.mode) assert.Equal(t, state.GetViewChangingID(), consensus.current.GetViewChangingID()) // FBFT timeout assert.IsType(t, make(map[TimeoutType]*utils.Timeout), consensus.consensusTimeout) for timeoutType, timeout := range expectedTimeouts { duration := consensus.consensusTimeout[timeoutType].Duration() assert.Equal(t, timeouts[timeoutType].Duration().Nanoseconds(), duration.Nanoseconds()) assert.Equal(t, timeout.Nanoseconds(), duration.Nanoseconds()) } // MultiBLS assert.Equal(t, multiBLSPrivateKey, consensus.priKey) assert.Equal(t, multiBLSPrivateKey.GetPublicKeys(), consensus.GetPublicKeys()) // Misc assert.Equal(t, uint64(0), consensus.GetViewChangingID()) assert.Equal(t, uint32(shard.BeaconChainShardID), consensus.ShardID) assert.IsType(t, make(chan struct{}), consensus.syncReadyChan) assert.NotNil(t, consensus.syncReadyChan) assert.IsType(t, make(chan struct{}), consensus.syncNotReadyChan) assert.NotNil(t, consensus.syncNotReadyChan) assert.IsType(t, make(chan slash.Record), consensus.SlashChan) assert.NotNil(t, consensus.SlashChan) assert.IsType(t, make(chan ProposalType), consensus.ReadySignal) assert.NotNil(t, consensus.ReadySignal) assert.IsType(t, make(chan [vdfAndSeedSize]byte), consensus.RndChannel) assert.NotNil(t, consensus.RndChannel) assert.IsType(t, abool.NewBool(false), consensus.IgnoreViewIDCheck) assert.NotNil(t, consensus.IgnoreViewIDCheck) } // GenerateConsensusForTesting - helper method to generate a basic consensus func GenerateConsensusForTesting() (p2p.Host, multibls.PrivateKeys, *Consensus, quorum.Decider, error) { hostData := helpers.Hosts[0] host, _, err := helpers.GenerateHost(hostData.IP, hostData.Port) if err != nil { return nil, nil, nil, nil, err } peer := host.GetSelfPeer() decider := quorum.NewDecider(quorum.SuperMajorityVote, shard.BeaconChainShardID) multiBLSPrivateKey := multibls.GetPrivateKeys(bls.RandPrivateKey()) consensus, err := New(host, shard.BeaconChainShardID, peer, multiBLSPrivateKey, decider) if err != nil { return nil, nil, nil, nil, err } return host, multiBLSPrivateKey, consensus, decider, nil }