aboutsummaryrefslogblamecommitdiffstats
path: root/dex/peer_test.go
blob: 9caa62d1ede5e51191597077af33cde5f325d8ec (plain) (tree)
1
2
3
4
5
6
7
8


           
                      
             

                 
                                                  



                                                        



                                        

                                       


                               
                                                    



                                

                                
                                                   
         

                                   


                                           

                                   


                                           
         
                                   


                                           

         

                                                                        
                                                



                                    
                                                         


                                            

                                       











                                
                                                          

                                           
                  

                                           









                                                              
                                             














                                          
                                                          


                                           
                  


                                           
                  

                                           
                  

                                           









                                                                  
                                                                           















                                          
                                                          


                                           
                  



                                           
                  

                                           
                  

                                           
                  


                                           
                  

                                           
                  

                                           
                  

                                           









                                                                      

                                                                           















                                          
                                                          

                                           
                  

                                           
                  

                                           
                  

                                           
                  

                                           
                  

                                           









                                                              

                                                                           










                                            
                                                            


















                                                            



                                        

                                       

                               

                                
                                                   

         

                                
                                                                          
                                              


                                                           
                 
                                                    


                                            

                                       











                                
                                                          

                                         
                  

                                         









                                                           
                                             







                            
                                                          

                                         
                  

                                         









                                                           
                                             







                            
                                                          

                                         
                  

                                         
                  

                                         
                  

                                         









                                                               
                                                                           







                            
                                                          

                                         
                  

                                         









                                                           
                                             






                            
                                                            












                                                         

                                                                       
                                                                       
                                                       

         
                                                       












                                                                                        
                                                                                 
























































                                                                                   
                                                              

                                      

                                                       



                

                                            
 
package dex

import (
    "encoding/hex"
    "fmt"
    "testing"

    "github.com/dexon-foundation/dexon/crypto"
    "github.com/dexon-foundation/dexon/p2p/enode"
)

func TestPeerSetBuildAndForgetNotaryConn(t *testing.T) {
    key, err := crypto.GenerateKey()
    if err != nil {
        t.Fatal(err)
    }
    server := newTestP2PServer(key)
    self := server.Self()
    table := newNodeTable()

    gov := &testGovernance{
        numChainsFunc: func(uint64) uint32 {
            return 3
        },
    }

    var nodes []*enode.Node
    for i := 0; i < 9; i++ {
        nodes = append(nodes, randomNode())
    }

    round10 := [][]*enode.Node{
        {self, nodes[1], nodes[2]},
        {nodes[1], nodes[3]},
        {nodes[2], nodes[4]},
    }
    round11 := [][]*enode.Node{
        {self, nodes[1], nodes[5]},
        {nodes[5], nodes[6]},
        {self, nodes[2], nodes[4]},
    }
    round12 := [][]*enode.Node{
        {self, nodes[3], nodes[5]},
        {self, nodes[7], nodes[8]},
        {self, nodes[2], nodes[6]},
    }

    gov.notarySetFunc = func(
        round uint64, cid uint32) (map[string]struct{}, error) {
        m := map[uint64][][]*enode.Node{
            10: round10,
            11: round11,
            12: round12,
        }
        return newTestNodeSet(m[round][cid]), nil
    }

    ps := newPeerSet(gov, server, table)
    peer1 := newDummyPeer(nodes[1])
    peer2 := newDummyPeer(nodes[2])
    err = ps.Register(peer1)
    if err != nil {
        t.Error(err)
    }
    err = ps.Register(peer2)
    if err != nil {
        t.Error(err)
    }

    // build round 10
    ps.BuildNotaryConn(10)

    err = checkPeer2Labels(ps, map[string][]peerLabel{
        nodes[1].ID().String(): {
            {notaryset, 0, 10},
        },
        nodes[2].ID().String(): {
            {notaryset, 0, 10},
        },
    })
    if err != nil {
        t.Error(err)
    }
    err = checkPeerSetHistory(ps, []uint64{10}, notaryset)
    if err != nil {
        t.Error(err)
    }
    err = checkDirectPeer(server, []enode.ID{
        nodes[1].ID(), nodes[2].ID(),
    })
    if err != nil {
        t.Error(err)
    }
    err = checkGroup(server, []string{
        notarySetName(1, 10),
        notarySetName(2, 10),
    })
    if err != nil {
        t.Error(err)
    }

    // build round 11
    ps.BuildNotaryConn(11)

    err = checkPeer2Labels(ps, map[string][]peerLabel{
        nodes[1].ID().String(): {
            {notaryset, 0, 10},
            {notaryset, 0, 11},
        },
        nodes[2].ID().String(): {
            {notaryset, 0, 10},
            {notaryset, 2, 11},
        },
        nodes[4].ID().String(): {
            {notaryset, 2, 11},
        },
        nodes[5].ID().String(): {
            {notaryset, 0, 11},
        },
    })
    if err != nil {
        t.Error(err)
    }
    err = checkPeerSetHistory(ps, []uint64{10, 11}, notaryset)
    if err != nil {
        t.Error(err)
    }
    err = checkDirectPeer(server, []enode.ID{
        nodes[1].ID(), nodes[2].ID(), nodes[4].ID(), nodes[5].ID(),
    })
    if err != nil {
        t.Error(err)
    }
    err = checkGroup(server, []string{
        notarySetName(1, 10),
        notarySetName(2, 10),
        notarySetName(1, 11),
    })
    if err != nil {
        t.Error(err)
    }

    // build round 12
    ps.BuildNotaryConn(12)

    err = checkPeer2Labels(ps, map[string][]peerLabel{
        nodes[1].ID().String(): {
            {notaryset, 0, 10},
            {notaryset, 0, 11},
        },
        nodes[2].ID().String(): {
            {notaryset, 0, 10},
            {notaryset, 2, 11},
            {notaryset, 2, 12},
        },
        nodes[3].ID().String(): {
            {notaryset, 0, 12},
        },
        nodes[4].ID().String(): {
            {notaryset, 2, 11},
        },
        nodes[5].ID().String(): {
            {notaryset, 0, 11},
            {notaryset, 0, 12},
        },
        nodes[6].ID().String(): {
            {notaryset, 2, 12},
        },
        nodes[7].ID().String(): {
            {notaryset, 1, 12},
        },
        nodes[8].ID().String(): {
            {notaryset, 1, 12},
        },
    })
    if err != nil {
        t.Error(err)
    }
    err = checkPeerSetHistory(ps, []uint64{10, 11, 12}, notaryset)
    if err != nil {
        t.Error(err)
    }
    err = checkDirectPeer(server, []enode.ID{
        nodes[1].ID(), nodes[2].ID(), nodes[3].ID(), nodes[4].ID(),
        nodes[5].ID(), nodes[6].ID(), nodes[7].ID(), nodes[8].ID(),
    })
    if err != nil {
        t.Error(err)
    }
    err = checkGroup(server, []string{
        notarySetName(1, 10),
        notarySetName(2, 10),
        notarySetName(1, 11),
    })
    if err != nil {
        t.Error(err)
    }

    // forget round 11
    ps.ForgetNotaryConn(11)

    err = checkPeer2Labels(ps, map[string][]peerLabel{
        nodes[2].ID().String(): {
            {notaryset, 2, 12},
        },
        nodes[3].ID().String(): {
            {notaryset, 0, 12},
        },
        nodes[5].ID().String(): {
            {notaryset, 0, 12},
        },
        nodes[6].ID().String(): {
            {notaryset, 2, 12},
        },
        nodes[7].ID().String(): {
            {notaryset, 1, 12},
        },
        nodes[8].ID().String(): {
            {notaryset, 1, 12},
        },
    })
    if err != nil {
        t.Error(err)
    }
    err = checkPeerSetHistory(ps, []uint64{12}, notaryset)
    if err != nil {
        t.Error(err)
    }
    err = checkDirectPeer(server, []enode.ID{
        nodes[2].ID(), nodes[3].ID(),
        nodes[5].ID(), nodes[6].ID(), nodes[7].ID(), nodes[8].ID(),
    })
    if err != nil {
        t.Error(err)
    }
    err = checkGroup(server, []string{})
    if err != nil {
        t.Error(err)
    }

    // forget round 12
    ps.ForgetNotaryConn(12)
    err = checkPeer2Labels(ps, map[string][]peerLabel{})
    if err != nil {
        t.Error(err)
    }
    err = checkPeerSetHistory(ps, []uint64{}, notaryset)
    if err != nil {
        t.Error(err)
    }
    err = checkDirectPeer(server, []enode.ID{})
    if err != nil {
        t.Error(err)
    }
    err = checkGroup(server, []string{})
    if err != nil {
        t.Error(err)
    }

}

func TestPeerSetBuildDKGConn(t *testing.T) {
    key, err := crypto.GenerateKey()
    if err != nil {
        t.Fatal(err)
    }
    server := newTestP2PServer(key)
    self := server.Self()
    table := newNodeTable()

    var nodes []*enode.Node
    for i := 0; i < 6; i++ {
        nodes = append(nodes, randomNode())
    }

    gov := &testGovernance{}

    gov.dkgSetFunc = func(round uint64) (map[string]struct{}, error) {
        m := map[uint64][]*enode.Node{
            10: {self, nodes[1], nodes[2]},
            11: {nodes[1], nodes[2], nodes[5]},
            12: {self, nodes[3], nodes[5]},
        }
        return newTestNodeSet(m[round]), nil
    }

    ps := newPeerSet(gov, server, table)
    peer1 := newDummyPeer(nodes[1])
    peer2 := newDummyPeer(nodes[2])
    err = ps.Register(peer1)
    if err != nil {
        t.Error(err)
    }
    err = ps.Register(peer2)
    if err != nil {
        t.Error(err)
    }

    // build round 10
    ps.BuildDKGConn(10)

    err = checkPeer2Labels(ps, map[string][]peerLabel{
        nodes[1].ID().String(): {
            {dkgset, 0, 10},
        },
        nodes[2].ID().String(): {
            {dkgset, 0, 10},
        },
    })
    if err != nil {
        t.Error(err)
    }
    err = checkPeerSetHistory(ps, []uint64{10}, dkgset)
    if err != nil {
        t.Error(err)
    }
    err = checkDirectPeer(server, []enode.ID{
        nodes[1].ID(), nodes[2].ID(),
    })
    if err != nil {
        t.Error(err)
    }

    // build round 11
    ps.BuildDKGConn(11)

    err = checkPeer2Labels(ps, map[string][]peerLabel{
        nodes[1].ID().String(): {
            {dkgset, 0, 10},
        },
        nodes[2].ID().String(): {
            {dkgset, 0, 10},
        },
    })
    if err != nil {
        t.Error(err)
    }
    err = checkPeerSetHistory(ps, []uint64{10}, dkgset)
    if err != nil {
        t.Error(err)
    }
    err = checkDirectPeer(server, []enode.ID{
        nodes[1].ID(), nodes[2].ID(),
    })
    if err != nil {
        t.Error(err)
    }

    // build round 12
    ps.BuildDKGConn(12)

    err = checkPeer2Labels(ps, map[string][]peerLabel{
        nodes[1].ID().String(): {
            {dkgset, 0, 10},
        },
        nodes[2].ID().String(): {
            {dkgset, 0, 10},
        },
        nodes[3].ID().String(): {
            {dkgset, 0, 12},
        },
        nodes[5].ID().String(): {
            {dkgset, 0, 12},
        },
    })
    if err != nil {
        t.Error(err)
    }
    err = checkPeerSetHistory(ps, []uint64{10, 12}, dkgset)
    if err != nil {
        t.Error(err)
    }
    err = checkDirectPeer(server, []enode.ID{
        nodes[1].ID(), nodes[2].ID(), nodes[3].ID(), nodes[5].ID(),
    })
    if err != nil {
        t.Error(err)
    }

    // forget round 11
    ps.ForgetDKGConn(11)

    err = checkPeer2Labels(ps, map[string][]peerLabel{
        nodes[3].ID().String(): {
            {dkgset, 0, 12},
        },
        nodes[5].ID().String(): {
            {dkgset, 0, 12},
        },
    })
    if err != nil {
        t.Error(err)
    }
    err = checkPeerSetHistory(ps, []uint64{12}, dkgset)
    if err != nil {
        t.Error(err)
    }
    err = checkDirectPeer(server, []enode.ID{
        nodes[3].ID(), nodes[5].ID(),
    })
    if err != nil {
        t.Error(err)
    }

    // forget round 12
    ps.ForgetDKGConn(12)
    err = checkPeer2Labels(ps, map[string][]peerLabel{})
    if err != nil {
        t.Error(err)
    }
    err = checkPeerSetHistory(ps, []uint64{}, dkgset)
    if err != nil {
        t.Error(err)
    }
    err = checkDirectPeer(server, []enode.ID{})
    if err != nil {
        t.Error(err)
    }
}

func checkPeer2Labels(ps *peerSet, want map[string][]peerLabel) error {
    if len(ps.peer2Labels) != len(want) {
        return fmt.Errorf("peer num mismatch: got %d, want %d",
            len(ps.peer2Labels), len(want))
    }

    for peerID, gotLabels := range ps.peer2Labels {
        wantLabels, ok := want[peerID]
        if !ok {
            return fmt.Errorf("peer id %s not exists", peerID)
        }

        if len(gotLabels) != len(wantLabels) {
            return fmt.Errorf(
                "num of labels of peer id %s mismatch: got %d, want %d",
                peerID, len(gotLabels), len(wantLabels))
        }

        for _, label := range wantLabels {
            if _, ok := gotLabels[label]; !ok {
                return fmt.Errorf("label: %+v not exists", label)
            }
        }
    }
    return nil
}

func checkPeerSetHistory(ps *peerSet, want []uint64, set setType) error {
    var history map[uint64]struct{}
    switch set {
    case notaryset:
        history = ps.notaryHistory
    case dkgset:
        history = ps.dkgHistory
    default:
        return fmt.Errorf("invalid set: %d", set)
    }

    if len(history) != len(want) {
        return fmt.Errorf("num of history mismatch: got %d, want %d",
            len(history), len(want))
    }

    for _, r := range want {
        if _, ok := history[r]; !ok {
            return fmt.Errorf("round %d not exists", r)
        }
    }
    return nil
}

func checkDirectPeer(srvr *testP2PServer, want []enode.ID) error {
    if len(srvr.direct) != len(want) {
        return fmt.Errorf("num of direct peer mismatch: got %d, want %d",
            len(srvr.direct), len(want))
    }

    for _, id := range want {
        if _, ok := srvr.direct[id]; !ok {
            return fmt.Errorf("direct peer %s not exists", id.String())
        }
    }
    return nil
}
func checkGroup(srvr *testP2PServer, want []string) error {
    if len(srvr.group) != len(want) {
        return fmt.Errorf("num of group mismatch: got %d, want %d",
            len(srvr.group), len(want))
    }

    for _, name := range want {
        if _, ok := srvr.group[name]; !ok {
            return fmt.Errorf("group %s not exists", name)
        }
    }
    return nil
}

func newTestNodeSet(nodes []*enode.Node) map[string]struct{} {
    m := make(map[string]struct{})
    for _, node := range nodes {
        b := crypto.FromECDSAPub(node.Pubkey())
        m[hex.EncodeToString(b)] = struct{}{}
    }
    return m
}

func newDummyPeer(node *enode.Node) *peer {
    return &peer{id: node.ID().String()}
}