diff --git a/tools/integration-tests/runTests.sh b/tools/integration-tests/runTests.sh index 9f885f01f363c656b2dc6bebdeb4186392c989b3..bb0674097775df377d9b9aa36ef94c03870a5983 100755 --- a/tools/integration-tests/runTests.sh +++ b/tools/integration-tests/runTests.sh @@ -3,6 +3,9 @@ echo "Build GoShimmer image" docker build -t iotaledger/goshimmer ../../. +echo "Pulling drand image" +docker pull angelocapossele/drand:latest + echo "Run integration tests" docker-compose -f tester/docker-compose.yml up --abort-on-container-exit --exit-code-from tester --build diff --git a/tools/integration-tests/tester/framework/docker.go b/tools/integration-tests/tester/framework/docker.go index ff5f9a45bffc673c95fb74142c5dca928000cc76..d70214f2339a074551cd9f4d5895a4bcbef2739d 100644 --- a/tools/integration-tests/tester/framework/docker.go +++ b/tools/integration-tests/tester/framework/docker.go @@ -69,7 +69,7 @@ func (d *DockerContainer) CreateGoShimmerEntryNode(name string, seed string) err } // CreateGoShimmerPeer creates a new container with the GoShimmer peer's configuration. -func (d *DockerContainer) CreateGoShimmerPeer(conf GoShimmerConfig) error { +func (d *DockerContainer) CreateGoShimmerPeer(config GoShimmerConfig) error { // configure GoShimmer container instance containerConfig := &container.Config{ Image: "iotaledger/goshimmer", @@ -77,24 +77,24 @@ func (d *DockerContainer) CreateGoShimmerPeer(conf GoShimmerConfig) error { nat.Port("8080/tcp"): {}, }, Cmd: strslice.StrSlice{ - fmt.Sprintf("--node.disablePlugins=%s", conf.DisabledPlugins), + fmt.Sprintf("--node.disablePlugins=%s", config.DisabledPlugins), fmt.Sprintf("--node.enablePlugins=%s", func() string { - if conf.Bootstrap { + if config.Bootstrap { return "Bootstrap" } return "" }()), "--webapi.bindAddress=0.0.0.0:8080", - fmt.Sprintf("--autopeering.seed=%s", conf.Seed), - fmt.Sprintf("--autopeering.entryNodes=%s@%s:14626", conf.EntryNodePublicKey, conf.EntryNodeHost), - fmt.Sprintf("--drng.instanceId=%d", conf.DRNGInstance), - fmt.Sprintf("--drng.threshold=%d", conf.DRNGThreshold), - fmt.Sprintf("--drng.committeeMembers=%s", conf.DRNGCommittee), - fmt.Sprintf("--drng.distributedPubKey=%s", conf.DRNGDistKey), + fmt.Sprintf("--autopeering.seed=%s", config.Seed), + fmt.Sprintf("--autopeering.entryNodes=%s@%s:14626", config.EntryNodePublicKey, config.EntryNodeHost), + fmt.Sprintf("--drng.instanceId=%d", config.DRNGInstance), + fmt.Sprintf("--drng.threshold=%d", config.DRNGThreshold), + fmt.Sprintf("--drng.committeeMembers=%s", config.DRNGCommittee), + fmt.Sprintf("--drng.distributedPubKey=%s", config.DRNGDistKey), }, } - return d.CreateContainer(conf.Name, containerConfig) + return d.CreateContainer(config.Name, containerConfig) } // CreateDrandMember creates a new container with the drand configuration. diff --git a/tools/integration-tests/tester/framework/drngnetwork.go b/tools/integration-tests/tester/framework/drngnetwork.go index 082c8244394c14eb127980bc948c9c5c192765f9..b0d67d5d75c1e007603c8c1649ae0c41b6c35a79 100644 --- a/tools/integration-tests/tester/framework/drngnetwork.go +++ b/tools/integration-tests/tester/framework/drngnetwork.go @@ -19,7 +19,7 @@ type DRNGNetwork struct { distKey []byte } -// newDRNGNetwork returns a Network instance, creates its underlying Docker network and adds the tester container to the network. +// newDRNGNetwork returns a DRNGNetwork instance, creates its underlying Docker network and adds the tester container to the network. func newDRNGNetwork(dockerClient *client.Client, name string, tester *DockerContainer) (*DRNGNetwork, error) { network, err := newNetwork(dockerClient, name, tester) if err != nil { @@ -34,15 +34,15 @@ func newDRNGNetwork(dockerClient *client.Client, name string, tester *DockerCont func (n *DRNGNetwork) CreatePeer(c GoShimmerConfig, publicKey hive_ed25519.PublicKey) (*Peer, error) { name := n.network.namePrefix(fmt.Sprintf("%s%d", containerNameReplica, len(n.network.peers))) - conf := c - conf.Name = name - conf.EntryNodeHost = n.network.namePrefix(containerNameEntryNode) - conf.EntryNodePublicKey = n.network.entryNodePublicKey() - conf.DisabledPlugins = disabledPluginsPeer + config := c + config.Name = name + config.EntryNodeHost = n.network.namePrefix(containerNameEntryNode) + config.EntryNodePublicKey = n.network.entryNodePublicKey() + config.DisabledPlugins = disabledPluginsPeer // create Docker container container := NewDockerContainer(n.network.dockerClient) - err := container.CreateGoShimmerPeer(conf) + err := container.CreateGoShimmerPeer(config) if err != nil { return nil, err } @@ -126,18 +126,8 @@ func (n *DRNGNetwork) WaitForDKG() error { defer log.Printf("Waiting for DKG... done\n") for i := dkgMaxTries; i > 0; i-- { - - //var dkey *drand.DistKeyResponse - for _, m := range n.members { - - if dkey, err := m.Client.DistKey(m.name+":8000", false); err != nil { - log.Printf("request error: %v\n", err) - } else { - n.SetDistKey(dkey.Key) - } - } - - if len(n.distKey) != 0 { + if dkey, err := n.members[0].Client.DistKey(n.members[0].name+":8000", false); err == nil { + n.SetDistKey(dkey.Key) log.Printf("DistKey: %v", hex.EncodeToString(n.distKey)) return nil } diff --git a/tools/integration-tests/tester/framework/framework.go b/tools/integration-tests/tester/framework/framework.go index 32c7da0d93634871a28444ab76cde5b5e9b5290f..75383ec28027a4d1b72f2abe367fa3857c1ce0b6 100644 --- a/tools/integration-tests/tester/framework/framework.go +++ b/tools/integration-tests/tester/framework/framework.go @@ -14,7 +14,6 @@ import ( "github.com/docker/docker/client" hive_ed25519 "github.com/iotaledger/hive.go/crypto/ed25519" - "github.com/mr-tron/base58" ) var ( @@ -92,7 +91,7 @@ func (f *Framework) CreateNetwork(name string, peers int, minimumNeighbors int) } // CreateDRNGNetwork creates and returns a (Docker) Network that contains drand and `peers` GoShimmer nodes. -func (f *Framework) CreateDRNGNetwork(name string, members, peers int) (*DRNGNetwork, error) { +func (f *Framework) CreateDRNGNetwork(name string, members, peers, minimumNeighbors int) (*DRNGNetwork, error) { drng, err := newDRNGNetwork(f.dockerClient, strings.ToLower(name), f.tester) if err != nil { return nil, err @@ -112,7 +111,7 @@ func (f *Framework) CreateDRNGNetwork(name string, members, peers int) (*DRNGNet } // wait until containers are fully started - time.Sleep(60 * time.Second) + time.Sleep(1 * time.Second) err = drng.WaitForDKG() if err != nil { return nil, err @@ -133,11 +132,11 @@ func (f *Framework) CreateDRNGNetwork(name string, members, peers int) (*DRNGNet if drngCommittee != "" { drngCommittee += fmt.Sprintf(",") } - drngCommittee += fmt.Sprintf("%s", base58.Encode(pubKeys[i][:])) + drngCommittee += pubKeys[i].String() } } - conf := GoShimmerConfig{ + config := GoShimmerConfig{ DRNGInstance: 1, DRNGThreshold: 3, DRNGDistKey: hex.EncodeToString(drng.distKey), @@ -146,16 +145,16 @@ func (f *Framework) CreateDRNGNetwork(name string, members, peers int) (*DRNGNet // create peers/GoShimmer nodes for i := 0; i < peers; i++ { - conf.Bootstrap = i == 0 - conf.Seed = base64.StdEncoding.EncodeToString(ed25519.PrivateKey(privKeys[i].Bytes()).Seed()) - if _, err = drng.CreatePeer(conf, pubKeys[i]); err != nil { + config.Bootstrap = i == 0 + config.Seed = base64.StdEncoding.EncodeToString(ed25519.PrivateKey(privKeys[i].Bytes()).Seed()) + if _, err = drng.CreatePeer(config, pubKeys[i]); err != nil { return nil, err } } // wait until peers are fully started and connected time.Sleep(1 * time.Second) - err = drng.network.WaitForAutopeering(3) + err = drng.network.WaitForAutopeering(minimumNeighbors) if err != nil { return nil, err } diff --git a/tools/integration-tests/tester/tests/drng_test.go b/tools/integration-tests/tester/tests/drng_test.go index fff44925cb22d66313e0d71827947472e2828be6..0832f04ae9553522cd09097c5964ae2c6ab4ff3d 100644 --- a/tools/integration-tests/tester/tests/drng_test.go +++ b/tools/integration-tests/tester/tests/drng_test.go @@ -1,45 +1,81 @@ package tests import ( - "encoding/hex" + "encoding/json" + "fmt" "log" + "sync" "testing" "time" + "github.com/iotaledger/goshimmer/tools/integration-tests/tester/framework" "github.com/stretchr/testify/require" ) +var ( + errWrongRound = fmt.Errorf("wrong round") +) + // TestDRNG checks whether drng messages are actually relayed/gossiped through the network // by checking the messages' existence on all nodes after a cool down. func TestDRNG(t *testing.T) { - drng, err := f.CreateDRNGNetwork("TestDRNG", 5, 8) + var wg sync.WaitGroup + + drng, err := f.CreateDRNGNetwork("TestDRNG", 5, 8, 3) require.NoError(t, err) defer drng.Shutdown() // wait for randomness generation to be started log.Printf("Waiting for randomness generation to be started...\n") - time.Sleep(100 * time.Second) - - peers := len(drng.Peers()) - randomnessMap := make(map[string]int) - - // check for randomness on every peer - for i := 0; i < 3; i++ { - for _, peer := range drng.Peers() { - resp, err := peer.GetRandomness() - require.NoError(t, err) - log.Println(resp) - randomnessMap[hex.EncodeToString(resp.Randomness)]++ + + // randomness starts at round = 2 + firstRound := uint64(2) + _, err = waitForRound(t, drng.Peers()[0], firstRound, 200) + require.NoError(t, err) + + log.Printf("Waiting for randomness generation to be started... done\n") + + ticker := time.NewTimer(0) + defer ticker.Stop() + + numChecks := 3 + i := 0 + for { + select { + case <-ticker.C: + ticker.Reset(10 * time.Second) + + // check for randomness on every peer + for _, peer := range drng.Peers() { + wg.Add(1) + go func(peer *framework.Peer) { + defer wg.Done() + s, err := waitForRound(t, peer, firstRound+uint64(i), 8) + require.NoError(t, err, peer.ID().String(), s) + t.Log(peer.ID().String(), s) + }(peer) + } + + wg.Wait() + i++ + + if i == numChecks { + return + } } - // wait for the next randomness - time.Sleep(10 * time.Second) } +} - // check that we got at least 3 different random values - require.GreaterOrEqual(t, len(randomnessMap), 3) - - // check that each random values has been received by all the peers. - for _, v := range randomnessMap { - require.GreaterOrEqual(t, v, peers) +func waitForRound(t *testing.T, peer *framework.Peer, round uint64, maxAttempts int) (string, error) { + var b []byte + for i := 0; i < maxAttempts; i++ { + resp, err := peer.GetRandomness() + require.NoError(t, err) + b, _ = json.MarshalIndent(resp, "", " ") + if resp.Round == round { + return string(b), nil + } + time.Sleep(1 * time.Second) } + return string(b), errWrongRound }