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







                                               
                                                  





                                                        




                                              


                               
                                                    



















                                                            

                                                                        




                                             
                                                         




                                            























                                             
                                                          












































                                                              
                                                          






















































                                                                  
                                                          
































































                                                                      
                                                          















































                                                              
                                                            



















                                                            




                                              



                                
                                                                          




                                                                        
                                                    




                                            























                                             
                                                          



































                                                           
                                                          



































                                                           
                                                          





































                                                               
                                                          






























                                                           
                                                            


























                                                                            

                                                                       
                                                                       
                                                       

         
                                                       



























































































                                                                                        
package dex

import (
    "fmt"
    "math/big"
    "testing"

    mapset "github.com/deckarep/golang-set"
    "github.com/dexon-foundation/dexon/crypto"
    "github.com/dexon-foundation/dexon/p2p/discover"
    "github.com/dexon-foundation/dexon/p2p/enode"
)

func TestPeerSetBuildAndForgetNotaryConn(t *testing.T) {
    self := discover.Node{ID: nodeID(0)}
    key, err := crypto.GenerateKey()
    if err != nil {
        t.Fatal(err)
    }
    server := newTestP2PServer(&self, key)
    table := newNodeTable()

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

    round10 := [][]enode.ID{
        []enode.ID{nodeID(0), nodeID(1), nodeID(2)},
        []enode.ID{nodeID(1), nodeID(3)},
        []enode.ID{nodeID(2), nodeID(4)},
    }
    round11 := [][]enode.ID{
        []enode.ID{nodeID(0), nodeID(1), nodeID(5)},
        []enode.ID{nodeID(5), nodeID(6)},
        []enode.ID{nodeID(0), nodeID(2), nodeID(4)},
    }
    round12 := [][]enode.ID{
        []enode.ID{nodeID(0), nodeID(3), nodeID(5)},
        []enode.ID{nodeID(0), nodeID(7), nodeID(8)},
        []enode.ID{nodeID(0), nodeID(2), nodeID(6)},
    }

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

    ps := newPeerSet(gov, server, table)
    peer1 := newDummyPeer(nodeID(1))
    peer2 := newDummyPeer(nodeID(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 = checkLabels(peer1, []peerLabel{
        peerLabel{notaryset, 0, 10},
    })
    if err != nil {
        t.Error(err)
    }
    err = checkLabels(peer2, []peerLabel{
        peerLabel{notaryset, 0, 10},
    })
    if err != nil {
        t.Error(err)
    }
    err = checkPeer2Labels(ps, map[string][]peerLabel{
        nodeID(1).String(): []peerLabel{
            peerLabel{notaryset, 0, 10},
        },
        nodeID(2).String(): []peerLabel{
            peerLabel{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{
        nodeID(1), nodeID(2),
    })
    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 = checkLabels(peer1, []peerLabel{
        peerLabel{notaryset, 0, 10},
        peerLabel{notaryset, 0, 11},
    })
    if err != nil {
        t.Error(err)
    }
    err = checkLabels(peer2, []peerLabel{
        peerLabel{notaryset, 0, 10},
        peerLabel{notaryset, 2, 11},
    })
    if err != nil {
        t.Error(err)
    }
    err = checkPeer2Labels(ps, map[string][]peerLabel{
        nodeID(1).String(): []peerLabel{
            peerLabel{notaryset, 0, 10},
            peerLabel{notaryset, 0, 11},
        },
        nodeID(2).String(): []peerLabel{
            peerLabel{notaryset, 0, 10},
            peerLabel{notaryset, 2, 11},
        },
        nodeID(4).String(): []peerLabel{
            peerLabel{notaryset, 2, 11},
        },
        nodeID(5).String(): []peerLabel{
            peerLabel{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{
        nodeID(1), nodeID(2), nodeID(4), nodeID(5),
    })
    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 = checkLabels(peer1, []peerLabel{
        peerLabel{notaryset, 0, 10},
        peerLabel{notaryset, 0, 11},
    })
    if err != nil {
        t.Error(err)
    }
    err = checkLabels(peer2, []peerLabel{
        peerLabel{notaryset, 0, 10},
        peerLabel{notaryset, 2, 11},
        peerLabel{notaryset, 2, 12},
    })
    if err != nil {
        t.Error(err)
    }
    err = checkPeer2Labels(ps, map[string][]peerLabel{
        nodeID(1).String(): []peerLabel{
            peerLabel{notaryset, 0, 10},
            peerLabel{notaryset, 0, 11},
        },
        nodeID(2).String(): []peerLabel{
            peerLabel{notaryset, 0, 10},
            peerLabel{notaryset, 2, 11},
            peerLabel{notaryset, 2, 12},
        },
        nodeID(3).String(): []peerLabel{
            peerLabel{notaryset, 0, 12},
        },
        nodeID(4).String(): []peerLabel{
            peerLabel{notaryset, 2, 11},
        },
        nodeID(5).String(): []peerLabel{
            peerLabel{notaryset, 0, 11},
            peerLabel{notaryset, 0, 12},
        },
        nodeID(6).String(): []peerLabel{
            peerLabel{notaryset, 2, 12},
        },
        nodeID(7).String(): []peerLabel{
            peerLabel{notaryset, 1, 12},
        },
        nodeID(8).String(): []peerLabel{
            peerLabel{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{
        nodeID(1), nodeID(2), nodeID(3), nodeID(4),
        nodeID(5), nodeID(6), nodeID(7), nodeID(8),
    })
    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 = checkLabels(peer1, []peerLabel{})
    if err != nil {
        t.Error(err)
    }
    err = checkLabels(peer2, []peerLabel{
        peerLabel{notaryset, 2, 12},
    })
    if err != nil {
        t.Error(err)
    }
    err = checkPeer2Labels(ps, map[string][]peerLabel{
        nodeID(2).String(): []peerLabel{
            peerLabel{notaryset, 2, 12},
        },
        nodeID(3).String(): []peerLabel{
            peerLabel{notaryset, 0, 12},
        },
        nodeID(5).String(): []peerLabel{
            peerLabel{notaryset, 0, 12},
        },
        nodeID(6).String(): []peerLabel{
            peerLabel{notaryset, 2, 12},
        },
        nodeID(7).String(): []peerLabel{
            peerLabel{notaryset, 1, 12},
        },
        nodeID(8).String(): []peerLabel{
            peerLabel{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{
        nodeID(2), nodeID(3),
        nodeID(5), nodeID(6), nodeID(7), nodeID(8),
    })
    if err != nil {
        t.Error(err)
    }
    err = checkGroup(server, []string{})
    if err != nil {
        t.Error(err)
    }

    // forget round 12
    ps.ForgetNotaryConn(12)
    err = checkLabels(peer1, []peerLabel{})
    if err != nil {
        t.Error(err)
    }
    err = checkLabels(peer2, []peerLabel{})
    if err != nil {
        t.Error(err)
    }
    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) {
    self := discover.Node{ID: nodeID(0)}
    key, err := crypto.GenerateKey()
    if err != nil {
        t.Fatal(err)
    }
    server := newTestP2PServer(&self, key)
    table := newNodeTable()

    gov := &testGovernance{}

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

    ps := newPeerSet(gov, server, table)
    peer1 := newDummyPeer(nodeID(1))
    peer2 := newDummyPeer(nodeID(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 = checkLabels(peer1, []peerLabel{
        peerLabel{dkgset, 0, 10},
    })
    if err != nil {
        t.Error(err)
    }
    err = checkLabels(peer2, []peerLabel{
        peerLabel{dkgset, 0, 10},
    })
    if err != nil {
        t.Error(err)
    }
    err = checkPeer2Labels(ps, map[string][]peerLabel{
        nodeID(1).String(): []peerLabel{
            peerLabel{dkgset, 0, 10},
        },
        nodeID(2).String(): []peerLabel{
            peerLabel{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{
        nodeID(1), nodeID(2),
    })
    if err != nil {
        t.Error(err)
    }

    // build round 11
    ps.BuildDKGConn(11)

    err = checkLabels(peer1, []peerLabel{
        peerLabel{dkgset, 0, 10},
    })
    if err != nil {
        t.Error(err)
    }
    err = checkLabels(peer2, []peerLabel{
        peerLabel{dkgset, 0, 10},
    })
    if err != nil {
        t.Error(err)
    }
    err = checkPeer2Labels(ps, map[string][]peerLabel{
        nodeID(1).String(): []peerLabel{
            peerLabel{dkgset, 0, 10},
        },
        nodeID(2).String(): []peerLabel{
            peerLabel{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{
        nodeID(1), nodeID(2),
    })
    if err != nil {
        t.Error(err)
    }

    // build round 12
    ps.BuildDKGConn(12)

    err = checkLabels(peer1, []peerLabel{
        peerLabel{dkgset, 0, 10},
    })
    if err != nil {
        t.Error(err)
    }
    err = checkLabels(peer2, []peerLabel{
        peerLabel{dkgset, 0, 10},
    })
    if err != nil {
        t.Error(err)
    }
    err = checkPeer2Labels(ps, map[string][]peerLabel{
        nodeID(1).String(): []peerLabel{
            peerLabel{dkgset, 0, 10},
        },
        nodeID(2).String(): []peerLabel{
            peerLabel{dkgset, 0, 10},
        },
        nodeID(3).String(): []peerLabel{
            peerLabel{dkgset, 0, 12},
        },
        nodeID(5).String(): []peerLabel{
            peerLabel{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{
        nodeID(1), nodeID(2), nodeID(3), nodeID(5),
    })
    if err != nil {
        t.Error(err)
    }

    // forget round 11
    ps.ForgetDKGConn(11)

    err = checkLabels(peer1, []peerLabel{})
    if err != nil {
        t.Error(err)
    }
    err = checkLabels(peer2, []peerLabel{})
    if err != nil {
        t.Error(err)
    }
    err = checkPeer2Labels(ps, map[string][]peerLabel{
        nodeID(3).String(): []peerLabel{
            peerLabel{dkgset, 0, 12},
        },
        nodeID(5).String(): []peerLabel{
            peerLabel{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{
        nodeID(3), nodeID(5),
    })
    if err != nil {
        t.Error(err)
    }

    // forget round 12
    ps.ForgetDKGConn(12)
    err = checkLabels(peer1, []peerLabel{})
    if err != nil {
        t.Error(err)
    }
    err = checkLabels(peer2, []peerLabel{})
    if err != nil {
        t.Error(err)
    }
    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 checkLabels(p *peer, want []peerLabel) error {
    if p.labels.Cardinality() != len(want) {
        return fmt.Errorf("num of labels mismatch: got %d, want %d",
            p.labels.Cardinality(), len(want))
    }

    for _, label := range want {
        if !p.labels.Contains(label) {
            return fmt.Errorf("label %+v not exist", label)
        }
    }
    return nil
}

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 {
                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 nodeID(n int64) enode.ID {
    b := big.NewInt(n).Bytes()
    var id enode.ID
    copy(id[len(id)-len(b):], b)
    return id
}

func newTestNodeSet(nodes []enode.ID) map[string]struct{} {
    m := make(map[string]struct{})
    for _, node := range nodes {
        m[node.String()] = struct{}{}
    }
    return m
}

func newDummyPeer(id enode.ID) *peer {
    return &peer{
        labels: mapset.NewSet(),
        id:     id.String(),
    }
}