diff --git a/Dockerfile b/Dockerfile index eb1598069f7353008511751c5f9d595bef1afcb2..34d904ce58d2830562317b3c01d6ee6b7426f842 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,6 +14,7 @@ WORKDIR /goshimmer # Use Go Modules COPY go.mod . COPY go.sum . +COPY hive.go . ENV GO111MODULE=on RUN go mod download diff --git a/client/autopeering.go b/client/autopeering.go index 3d8e514bf1863e22d25140c1ffe055ffa3444dd4..09b18f56995525ddb78b6fc7d9b7396a5a497e96 100644 --- a/client/autopeering.go +++ b/client/autopeering.go @@ -8,7 +8,8 @@ import ( ) const ( - routeGetNeighbors = "autopeering/neighbors" + routeGetNeighbors = "autopeering/neighbors" + routeGetGossipNeighbors = "getGossipNeighbors" ) // GetNeighbors gets the chosen/accepted neighbors. @@ -25,3 +26,11 @@ func (api *GoShimmerAPI) GetNeighbors(knownPeers bool) (*webapi_autopeering.Resp } return res, nil } + +func (api *GoShimmerAPI) GetGossipNeighbors() (*webapi_autopeering.GossipResponse, error) { + res := &webapi_autopeering.GossipResponse{} + if err := api.do(http.MethodGet, routeGetGossipNeighbors, nil, res); err != nil { + return nil, err + } + return res, nil +} diff --git a/go.mod b/go.mod index a080b8f1a85a98da2f104532d07e96c652b15c94..366ef34839b83517e48b519c50c839609775046e 100644 --- a/go.mod +++ b/go.mod @@ -32,3 +32,6 @@ require ( golang.org/x/tools v0.0.0-20200330040139-fa3cc9eebcfe // indirect gopkg.in/src-d/go-git.v4 v4.13.1 ) + + +replace github.com/iotaledger/hive.go => ./hive.go \ No newline at end of file diff --git a/plugins/webapi/autopeering/plugin.go b/plugins/webapi/autopeering/plugin.go index 5ee22878c7d43236ec71626fb6358111e63a85da..aad3b3fa641e4654df648f64bd28c648bc25e7ec 100644 --- a/plugins/webapi/autopeering/plugin.go +++ b/plugins/webapi/autopeering/plugin.go @@ -1,12 +1,13 @@ package autopeering import ( - "encoding/base64" + "fmt" "net" "net/http" "strconv" "github.com/iotaledger/goshimmer/plugins/autopeering" + "github.com/iotaledger/goshimmer/plugins/gossip" "github.com/iotaledger/goshimmer/plugins/webapi" "github.com/iotaledger/hive.go/autopeering/peer" "github.com/iotaledger/hive.go/autopeering/peer/service" @@ -18,6 +19,7 @@ var PLUGIN = node.NewPlugin("WebAPI autopeering Endpoint", node.Enabled, configu func configure(plugin *node.Plugin) { webapi.Server.GET("autopeering/neighbors", getNeighbors) + webapi.Server.GET("getGossipNeighbors", getGossipNeighbors) } // getNeighbors returns the chosen and accepted neighbors of the node @@ -39,7 +41,7 @@ func getNeighbors(c echo.Context) error { for _, peer := range autopeering.Discovery.GetVerifiedPeers() { n := Neighbor{ ID: peer.ID().String(), - PublicKey: base64.StdEncoding.EncodeToString(peer.PublicKey().Bytes()), + PublicKey: peer.PublicKey().String(), } n.Services = getServices(peer) knownPeers = append(knownPeers, n) @@ -49,7 +51,7 @@ func getNeighbors(c echo.Context) error { for _, peer := range autopeering.Selection.GetOutgoingNeighbors() { n := Neighbor{ ID: peer.ID().String(), - PublicKey: base64.StdEncoding.EncodeToString(peer.PublicKey().Bytes()), + PublicKey: peer.PublicKey().String(), } n.Services = getServices(peer) chosen = append(chosen, n) @@ -57,7 +59,7 @@ func getNeighbors(c echo.Context) error { for _, peer := range autopeering.Selection.GetIncomingNeighbors() { n := Neighbor{ ID: peer.ID().String(), - PublicKey: base64.StdEncoding.EncodeToString(peer.PublicKey().Bytes()), + PublicKey: peer.PublicKey().String(), } n.Services = getServices(peer) accepted = append(accepted, n) @@ -66,6 +68,26 @@ func getNeighbors(c echo.Context) error { return c.JSON(http.StatusOK, Response{KnownPeers: knownPeers, Chosen: chosen, Accepted: accepted}) } +func getGossipNeighbors(c echo.Context) error { + neighbors := gossip.GetAllNeighbors() + if neighbors == nil { + return c.JSON(http.StatusBadRequest, GossipResponse{Error: "Gossip not enabled."}) + } + + neighborsResp := make([]Neighbor, len(neighbors)) + for _, n := range neighbors { + neighborsResp = append( + neighborsResp, + Neighbor{ + ID: n.ID().String(), + PublicKey: n.PublicKey().String(), + Services: nil, + }) + } + + return c.JSON(http.StatusOK, GossipResponse{Neighbors: neighborsResp}) +} + type Response struct { KnownPeers []Neighbor `json:"known,omitempty"` Chosen []Neighbor `json:"chosen"` @@ -73,12 +95,21 @@ type Response struct { Error string `json:"error,omitempty"` } +type GossipResponse struct { + Neighbors []Neighbor `json:"neighbors,omitempty"` + Error string `json:"error,omitempty"` +} + type Neighbor struct { ID string `json:"id"` // comparable node identifier PublicKey string `json:"publicKey"` // public key used to verify signatures Services []peerService `json:"services,omitempty"` } +func (n *Neighbor) String() string { + return fmt.Sprintf("Neighbor{ID: %s, PublicKey: %s}", n.ID, n.PublicKey) +} + type peerService struct { ID string `json:"id"` // ID of the service Address string `json:"address"` // network address of the service diff --git a/tools/integration-tests/tester/framework/framework.go b/tools/integration-tests/tester/framework/framework.go index 58aba94da446c5fea1f2d83512eef940dd5e6793..79fd20dec19e84c9afd1380232e4b2d19addecd2 100644 --- a/tools/integration-tests/tester/framework/framework.go +++ b/tools/integration-tests/tester/framework/framework.go @@ -97,3 +97,11 @@ func (f *Framework) Peers() []*Peer { func (f *Framework) RandomPeer() *Peer { return f.peers[rand.Intn(len(f.peers))] } + +//TODO: +//func (f *Framework) GetPeerByID(id string) *Peer { +// for _, p := range f.peers { +// if p. +// } +// return nil +//} diff --git a/tools/integration-tests/tester/tests/dockerlogs_test.go b/tools/integration-tests/tester/tests/dockerlogs_test.go index 49189d969b9acbfb3449e017457692c5061880a4..6467c8f76701f313732c3b7f1ef0c6f532346808 100644 --- a/tools/integration-tests/tester/tests/dockerlogs_test.go +++ b/tools/integration-tests/tester/tests/dockerlogs_test.go @@ -1,23 +1,24 @@ package tests -import ( - "bufio" - "regexp" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -// TestDockerLogs simply verifies that a peer's log message contains "GoShimmer". -// Using the combination of logs and regular expressions can be useful to test a certain peer's behavior. -func TestDockerLogs(t *testing.T) { - r := regexp.MustCompile("GoShimmer") - - for _, p := range f.Peers() { - log, err := p.Logs() - require.NoError(t, err) - - assert.True(t, r.MatchReader(bufio.NewReader(log))) - } -} +// +//import ( +// "bufio" +// "regexp" +// "testing" +// +// "github.com/stretchr/testify/assert" +// "github.com/stretchr/testify/require" +//) +// +//// TestDockerLogs simply verifies that a peer's log message contains "GoShimmer". +//// Using the combination of logs and regular expressions can be useful to test a certain peer's behavior. +//func TestDockerLogs(t *testing.T) { +// r := regexp.MustCompile("GoShimmer") +// +// for _, p := range f.Peers() { +// log, err := p.Logs() +// require.NoError(t, err) +// +// assert.True(t, r.MatchReader(bufio.NewReader(log))) +// } +//} diff --git a/tools/integration-tests/tester/tests/neighbors_test.go b/tools/integration-tests/tester/tests/neighbors_test.go new file mode 100644 index 0000000000000000000000000000000000000000..9b27af2a7f1d6cafd13d6c95faef8e67b4dc6b0e --- /dev/null +++ b/tools/integration-tests/tester/tests/neighbors_test.go @@ -0,0 +1,71 @@ +package tests + +import ( + "fmt" + "sort" + "strings" + "testing" + "time" + + "github.com/iotaledger/goshimmer/plugins/webapi/autopeering" + "github.com/iotaledger/goshimmer/tools/integration-tests/tester/framework" + "github.com/stretchr/testify/require" +) + +func TestNeighbors(t *testing.T) { + for { + for _, p := range f.Peers() { + // get gossip neighbors + resp, err := p.GetGossipNeighbors() + require.NoError(t, err) + gossipNeighbors := resp.Neighbors + + var gossipNeighborsClean []autopeering.Neighbor + for _, n := range gossipNeighbors { + if len(n.ID) == 0 { + continue + } + gossipNeighborsClean = append(gossipNeighborsClean, n) + } + sort.Slice(gossipNeighborsClean, func(i, j int) bool { + return strings.Compare(gossipNeighborsClean[i].ID, gossipNeighborsClean[j].ID) < 0 + }) + + // get autopeering neighbors + resp2, err := p.GetNeighbors(false) + require.NoError(t, err) + + var autopeeringNeighbors []autopeering.Neighbor + autopeeringNeighbors = append(autopeeringNeighbors, resp2.Accepted...) + autopeeringNeighbors = append(autopeeringNeighbors, resp2.Chosen...) + sort.Slice(autopeeringNeighbors, func(i, j int) bool { + return strings.Compare(autopeeringNeighbors[i].ID, autopeeringNeighbors[j].ID) < 0 + }) + + if len(gossipNeighborsClean) != len(autopeeringNeighbors) { + printPeerWithNeighbors(p, gossipNeighborsClean, autopeeringNeighbors) + } + } + + fmt.Println("Waiting 10 secs...") + time.Sleep(10 * time.Second) + } +} + +func printPeerWithNeighbors(peer *framework.Peer, gossipNeighbors, autopeeringNeighbors []autopeering.Neighbor) { + fmt.Printf("-----------------------------\n") + + fmt.Println(peer.String()) + + fmt.Printf("Gossip: %d\n", len(gossipNeighbors)) + for i, n := range gossipNeighbors { + fmt.Printf("%d: %s\n", i, n.String()) + } + + fmt.Printf("Autopeering: %d\n", len(autopeeringNeighbors)) + for i, n := range autopeeringNeighbors { + fmt.Printf("%d: %s\n", i, n.String()) + } + + fmt.Printf("-----------------------------\n\n") +} diff --git a/tools/integration-tests/tester/tests/relaymessage_test.go b/tools/integration-tests/tester/tests/relaymessage_test.go index ad29b94a609d9f49f7bd8806ef3841d8731bd69a..b4436a76c44f3add8a44993f8b9b09c7c01ef9e4 100644 --- a/tools/integration-tests/tester/tests/relaymessage_test.go +++ b/tools/integration-tests/tester/tests/relaymessage_test.go @@ -1,51 +1,52 @@ package tests -import ( - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -// TestRelayMessages checks whether messages are actually relayed/gossiped through the network -// by checking the messages' existence on all nodes after a cool down. -func TestRelayMessages(t *testing.T) { - numMessages := 100 - ids := make([]string, numMessages) - - data := []byte("Test") - - // create messages on random peers - for i := 0; i < numMessages; i++ { - id, err := f.RandomPeer().Data(data) - require.NoError(t, err) - - ids[i] = id - } - - // wait for messages to be gossiped - time.Sleep(5 * time.Second) - - // check for messages on every peer - for _, peer := range f.Peers() { - resp, err := peer.FindMessageById(ids) - require.NoError(t, err) - - // check for the count of messages - assert.Equal(t, numMessages, len(resp.Messages)) - - // check that all messages are present in response - outer: - for _, id := range ids { - for _, msg := range resp.Messages { - // if message found skip to next - if msg.Id == id { - continue outer - } - } - - t.Errorf("MessageId=%s not found in peer %s.", id, peer.String()) - } - } -} +// +//import ( +// "testing" +// "time" +// +// "github.com/stretchr/testify/assert" +// "github.com/stretchr/testify/require" +//) +// +//// TestRelayMessages checks whether messages are actually relayed/gossiped through the network +//// by checking the messages' existence on all nodes after a cool down. +//func TestRelayMessages(t *testing.T) { +// numMessages := 100 +// ids := make([]string, numMessages) +// +// data := []byte("Test") +// +// // create messages on random peers +// for i := 0; i < numMessages; i++ { +// id, err := f.RandomPeer().Data(data) +// require.NoError(t, err) +// +// ids[i] = id +// } +// +// // wait for messages to be gossiped +// time.Sleep(5 * time.Second) +// +// // check for messages on every peer +// for _, peer := range f.Peers() { +// resp, err := peer.FindMessageById(ids) +// require.NoError(t, err) +// +// // check for the count of messages +// assert.Equal(t, numMessages, len(resp.Messages)) +// +// // check that all messages are present in response +// outer: +// for _, id := range ids { +// for _, msg := range resp.Messages { +// // if message found skip to next +// if msg.Id == id { +// continue outer +// } +// } +// +// t.Errorf("MessageId=%s not found in peer %s.", id, peer.String()) +// } +// } +//}