// Copyright 2018 The dexon-consensus Authors // This file is part of the dexon-consensus library. // // The dexon-consensus library is free software: you can redistribute it // and/or modify it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation, either version 3 of the License, // or (at your option) any later version. // // The dexon-consensus library is distributed in the hope that it will be // useful, but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser // General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with the dexon-consensus library. If not, see // . package test import ( "errors" "fmt" "math" "net" "time" "github.com/dexon-foundation/dexon-consensus/common" "github.com/dexon-foundation/dexon-consensus/core/crypto" "github.com/dexon-foundation/dexon-consensus/core/crypto/ecdsa" "github.com/dexon-foundation/dexon-consensus/core/db" "github.com/dexon-foundation/dexon-consensus/core/types" typesDKG "github.com/dexon-foundation/dexon-consensus/core/types/dkg" "github.com/dexon-foundation/dexon/rlp" ) // GenerateRandomNodeIDs generates randomly a slices of types.NodeID. func GenerateRandomNodeIDs(nodeCount int) (nIDs types.NodeIDs) { nIDs = types.NodeIDs{} for i := 0; i < nodeCount; i++ { nIDs = append(nIDs, types.NodeID{Hash: common.NewRandomHash()}) } return } // GenerateRandomPrivateKeys generate a set of private keys. func GenerateRandomPrivateKeys(nodeCount int) (prvKeys []crypto.PrivateKey) { for i := 0; i < nodeCount; i++ { prvKey, err := ecdsa.NewPrivateKey() if err != nil { panic(err) } prvKeys = append(prvKeys, prvKey) } return } // CalcLatencyStatistics calculates average and deviation from a slice // of latencies. func CalcLatencyStatistics(latencies []time.Duration) (avg, dev time.Duration) { var ( sum float64 sumOfSquareDiff float64 ) // Calculate average. for _, v := range latencies { sum += float64(v) } avgAsFloat := sum / float64(len(latencies)) avg = time.Duration(avgAsFloat) // Calculate deviation for _, v := range latencies { diff := math.Abs(float64(v) - avgAsFloat) sumOfSquareDiff += diff * diff } dev = time.Duration(math.Sqrt(sumOfSquareDiff / float64(len(latencies)-1))) return } // FindMyIP returns local IP address. func FindMyIP() (ip string, err error) { addrs, err := net.InterfaceAddrs() if err != nil { return } for _, a := range addrs { ipnet, ok := a.(*net.IPNet) if !ok { continue } if ipnet.IP.IsLoopback() { continue } if ipnet.IP.To4() != nil { ip = ipnet.IP.String() return } } err = fmt.Errorf("unable to find IP") return } // NewKeys creates private keys and corresponding public keys as slice. func NewKeys(count int) ( prvKeys []crypto.PrivateKey, pubKeys []crypto.PublicKey, err error) { for i := 0; i < count; i++ { var prvKey crypto.PrivateKey if prvKey, err = ecdsa.NewPrivateKey(); err != nil { return } prvKeys = append(prvKeys, prvKey) pubKeys = append(pubKeys, prvKey.PublicKey()) } return } // CloneDKGComplaint clones a tpyesDKG.Complaint instance. func CloneDKGComplaint( comp *typesDKG.Complaint) (copied *typesDKG.Complaint) { b, err := rlp.EncodeToBytes(comp) if err != nil { panic(err) } copied = &typesDKG.Complaint{} if err = rlp.DecodeBytes(b, copied); err != nil { panic(err) } return } // CloneDKGMasterPublicKey clones a typesDKG.MasterPublicKey instance. func CloneDKGMasterPublicKey(mpk *typesDKG.MasterPublicKey) ( copied *typesDKG.MasterPublicKey) { b, err := rlp.EncodeToBytes(mpk) if err != nil { panic(err) } copied = typesDKG.NewMasterPublicKey() if err = rlp.DecodeBytes(b, copied); err != nil { panic(err) } return } // CloneDKGMPKReady clones a typesDKG.MPKReady instance. func CloneDKGMPKReady(ready *typesDKG.MPKReady) ( copied *typesDKG.MPKReady) { b, err := rlp.EncodeToBytes(ready) if err != nil { panic(err) } copied = &typesDKG.MPKReady{} if err = rlp.DecodeBytes(b, copied); err != nil { panic(err) } return } // CloneDKGFinalize clones a typesDKG.Finalize instance. func CloneDKGFinalize(final *typesDKG.Finalize) ( copied *typesDKG.Finalize) { b, err := rlp.EncodeToBytes(final) if err != nil { panic(err) } copied = &typesDKG.Finalize{} if err = rlp.DecodeBytes(b, copied); err != nil { panic(err) } return } // CloneDKGPrivateShare clones a typesDKG.PrivateShare instance. func CloneDKGPrivateShare(prvShare *typesDKG.PrivateShare) ( copied *typesDKG.PrivateShare) { b, err := rlp.EncodeToBytes(prvShare) if err != nil { panic(err) } copied = &typesDKG.PrivateShare{} if err = rlp.DecodeBytes(b, copied); err != nil { panic(err) } return } func cloneBlockRandomnessResult(rand *types.BlockRandomnessResult) ( copied *types.BlockRandomnessResult) { b, err := rlp.EncodeToBytes(rand) if err != nil { panic(err) } copied = &types.BlockRandomnessResult{} if err = rlp.DecodeBytes(b, copied); err != nil { panic(err) } return } var ( // ErrCompactionChainTipBlockNotExists raised when the hash of compaction // chain tip doesn't match a block in database. ErrCompactionChainTipBlockNotExists = errors.New( "compaction chain tip block not exists") // ErrEmptyCompactionChainTipInfo raised when a compaction chain tip info // is empty. ErrEmptyCompactionChainTipInfo = errors.New( "empty compaction chain tip info") // ErrMismatchBlockHash raise when the hash for that block mismatched. ErrMismatchBlockHash = errors.New("mismatched block hash") ) // VerifyDB check if a database is valid after test. func VerifyDB(db db.Database) error { hash, height := db.GetCompactionChainTipInfo() if (hash == common.Hash{}) || height == 0 { return ErrEmptyCompactionChainTipInfo } b, err := db.GetBlock(hash) if err != nil { return err } if b.Hash != hash { return ErrMismatchBlockHash } return nil } func getComplementSet( all, set map[types.NodeID]struct{}) map[types.NodeID]struct{} { complement := make(map[types.NodeID]struct{}) for nID := range all { if _, exists := set[nID]; exists { continue } complement[nID] = struct{}{} } return complement }