aboutsummaryrefslogblamecommitdiffstats
path: root/core/test/utils.go
blob: d85395b378852a9d156f839e5a810e4e408627dc (plain) (tree)
1
2
3
4
5
6
7
8
9

                                                    
  
                                                                        



                                                                               
                                                                         




                                                                           
                                                      




                                  
                 
                
             
              
             

              


                                                                       
                                                             
                                                                

                                                                             

 




                                                                               


              
 











                                                                             





















                                                                                   






















                                              













                                                                             
 

                                                          











                                                                

                                                                      











                                                         

                                                        











                                                         

                                                        










                                                         
 













                                                                











                                                                    




























                                                                                 

















                                                                                











                                                                       
// 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
// <http://www.gnu.org/licenses/>.

package test

import (
    "context"
    "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
}

// LaunchDummyReceiver launches a go routine to receive and drop messages from
// a network module. An optional context could be passed to stop the go routine.
func LaunchDummyReceiver(
    ctx context.Context, networkModule *Network) context.CancelFunc {
    dummyCtx, dummyCancel := context.WithCancel(ctx)
    go func() {
    loop:
        for {
            select {
            case <-dummyCtx.Done():
                break loop
            case <-networkModule.ReceiveChan():
            }
        }
    }()
    return dummyCancel
}

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
}