From 21a2aa7bf7c07252ca00d20f423c34c06545851e Mon Sep 17 00:00:00 2001 From: jkrvivian Date: Wed, 8 May 2024 14:34:33 +0800 Subject: [PATCH 01/24] Add some activity to Test_SyncFromSnapshot --- .../tests/api_management_test.go | 10 ++-- .../tests/dockertestframework/awaits.go | 2 +- .../tests/sync_snapshot_test.go | 54 ++++++++++++++++--- 3 files changed, 53 insertions(+), 13 deletions(-) diff --git a/tools/docker-network/tests/api_management_test.go b/tools/docker-network/tests/api_management_test.go index 6bf9023da..76ebb7c16 100644 --- a/tools/docker-network/tests/api_management_test.go +++ b/tools/docker-network/tests/api_management_test.go @@ -221,9 +221,9 @@ func Test_ManagementAPI_Pruning(t *testing.T) { name: "Test_PruneDatabase_ByEpoch", testFunc: func(t *testing.T) { // we need to wait until epoch 3 to be able to prune epoch 1 - d.AwaitNextEpoch() - d.AwaitNextEpoch() - d.AwaitNextEpoch() + d.AwaitEpochFinalized() + d.AwaitEpochFinalized() + d.AwaitEpochFinalized() // prune database by epoch pruneDatabaseResponse, err := managementClient.PruneDatabaseByEpoch(getContextWithTimeout(5*time.Second), 1) @@ -235,7 +235,7 @@ func Test_ManagementAPI_Pruning(t *testing.T) { name: "Test_PruneDatabase_ByDepth", testFunc: func(t *testing.T) { // wait for the next epoch to start - d.AwaitNextEpoch() + d.AwaitEpochFinalized() // prune database by depth pruneDatabaseResponse, err := managementClient.PruneDatabaseByDepth(getContextWithTimeout(5*time.Second), 1) @@ -247,7 +247,7 @@ func Test_ManagementAPI_Pruning(t *testing.T) { name: "Test_PruneDatabase_BySize", testFunc: func(t *testing.T) { // wait for the next epoch to start - d.AwaitNextEpoch() + d.AwaitEpochFinalized() // prune database by size pruneDatabaseResponse, err := managementClient.PruneDatabaseBySize(getContextWithTimeout(5*time.Second), "5G") diff --git a/tools/docker-network/tests/dockertestframework/awaits.go b/tools/docker-network/tests/dockertestframework/awaits.go index 553134cfb..885a159d9 100644 --- a/tools/docker-network/tests/dockertestframework/awaits.go +++ b/tools/docker-network/tests/dockertestframework/awaits.go @@ -102,7 +102,7 @@ func (d *DockerTestFramework) AwaitFinalization(targetSlot iotago.SlotIndex) { }) } -func (d *DockerTestFramework) AwaitNextEpoch() { +func (d *DockerTestFramework) AwaitEpochFinalized() { //nolint:lostcancel ctx, _ := context.WithTimeout(context.Background(), 5*time.Second) diff --git a/tools/docker-network/tests/sync_snapshot_test.go b/tools/docker-network/tests/sync_snapshot_test.go index 912cc29b5..1f0e8efd0 100644 --- a/tools/docker-network/tests/sync_snapshot_test.go +++ b/tools/docker-network/tests/sync_snapshot_test.go @@ -3,6 +3,7 @@ package tests import ( + "context" "testing" "time" @@ -15,8 +16,8 @@ import ( func Test_SyncFromSnapshot(t *testing.T) { d := dockertestframework.NewDockerTestFramework(t, dockertestframework.WithProtocolParametersOptions( - iotago.WithTimeProviderOptions(0, time.Now().Unix(), 4, 4), - iotago.WithLivenessOptions(3, 4, 2, 4, 5), + iotago.WithTimeProviderOptions(0, time.Now().Unix(), 10, 3), + iotago.WithLivenessOptions(10, 10, 2, 4, 5), iotago.WithCongestionControlOptions(1, 1, 1, 400_000, 250_000, 50_000_000, 1000, 100), iotago.WithRewardsOptions(8, 10, 2, 384), iotago.WithTargetCommitteeSize(4), @@ -27,16 +28,47 @@ func Test_SyncFromSnapshot(t *testing.T) { d.AddValidatorNode("V2", "docker-network-inx-validator-2-1", "http://localhost:8060", "rms1pqm4xk8e9ny5w5rxjkvtp249tfhlwvcshyr3pc0665jvp7g3hc875k538hl") d.AddValidatorNode("V3", "docker-network-inx-validator-3-1", "http://localhost:8070", "rms1pp4wuuz0y42caz48vv876qfpmffswsvg40zz8v79sy8cp0jfxm4kunflcgt") d.AddValidatorNode("V4", "docker-network-inx-validator-4-1", "http://localhost:8040", "rms1pr8cxs3dzu9xh4cduff4dd4cxdthpjkpwmz2244f75m0urslrsvtsshrrjw") - d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8090") + d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8080") err := d.Run() require.NoError(t, err) d.WaitUntilNetworkReady() - d.AwaitNextEpoch() - d.AwaitNextEpoch() + ctx := context.Background() + delegatorWallet, accountData := d.CreateAccountFromFaucet() + clt := delegatorWallet.Client + // delegate funds to V2 + delegationOutputData := d.DelegateToValidator(delegatorWallet, d.Node("V2").AccountAddress(t)) + d.AwaitCommitment(delegationOutputData.ID.CreationSlot()) + + // check if V2 received the delegator stake + v2Resp, err := clt.Validator(ctx, d.Node("V2").AccountAddress(t)) + require.NoError(t, err) + require.Greater(t, v2Resp.PoolStake, v2Resp.ValidatorStake) + + //nolint:forcetypeassert + currentEpoch := clt.CommittedAPI().TimeProvider().EpochFromSlot(delegatorWallet.CurrentSlot()) + expectedEpoch := delegationOutputData.Output.(*iotago.DelegationOutput).StartEpoch + 2 + for range expectedEpoch - currentEpoch { + d.AwaitEpochFinalized() + } + + // claim rewards that put to an basic output + rewardsOutputID := d.ClaimRewardsForDelegator(ctx, delegatorWallet, delegationOutputData) + + // check if the mana increased as expected + node5Clt := d.Client("node5") + outputFromAPI, err := node5Clt.OutputByID(ctx, rewardsOutputID) + require.NoError(t, err) + + rewardsOutput := delegatorWallet.Output(rewardsOutputID) + require.Equal(t, rewardsOutput.Output.StoredMana(), outputFromAPI.StoredMana()) + + d.AwaitEpochFinalized() + + // create snapshot nodeClientV1 := d.Client("V1") managementClient, err := nodeClientV1.Management(getContextWithTimeout(5 * time.Second)) require.NoError(t, err) @@ -47,6 +79,14 @@ func Test_SyncFromSnapshot(t *testing.T) { // Deletes the database of node5 and restarts it with the just created snapshot. d.ResetNode("node5", response.FilePath) - d.AwaitNextEpoch() - d.AwaitNextEpoch() + d.AwaitEpochFinalized() + d.AwaitEpochFinalized() + + // check if the account and rewardsOutput are available + node5Clt = d.Client("node5") + _, err = node5Clt.Validator(ctx, accountData.Address) + require.NoError(t, err) + + outputFromAPI, err = node5Clt.OutputByID(ctx, rewardsOutputID) + require.NoError(t, err) } From 55932e84ebab38618c6a5a7daaef7138c1fa0280 Mon Sep 17 00:00:00 2001 From: jkrvivian Date: Wed, 8 May 2024 15:57:56 +0800 Subject: [PATCH 02/24] Wait with EventuallyWithDurations in AwaitFinalization --- .../tests/dockertestframework/awaits.go | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/tools/docker-network/tests/dockertestframework/awaits.go b/tools/docker-network/tests/dockertestframework/awaits.go index 885a159d9..872d28f47 100644 --- a/tools/docker-network/tests/dockertestframework/awaits.go +++ b/tools/docker-network/tests/dockertestframework/awaits.go @@ -92,14 +92,25 @@ func (d *DockerTestFramework) AwaitCommitment(targetSlot iotago.SlotIndex) { } func (d *DockerTestFramework) AwaitFinalization(targetSlot iotago.SlotIndex) { - d.Eventually(func() error { + currentFinalizedSlot := d.NodeStatus("V1").LatestFinalizedSlot + + // we wait at max "targetSlot - currentFinalizedSlot" times * slot duration + deadline := time.Duration(d.defaultWallet.Client.CommittedAPI().ProtocolParameters().SlotDurationInSeconds()) * time.Second + if currentFinalizedSlot < targetSlot { + deadline *= time.Duration(targetSlot - currentFinalizedSlot) + } + + // give some extra time for peering etc + deadline += 30 * time.Second + + d.EventuallyWithDurations(func() error { currentFinalisedSlot := d.NodeStatus("V1").LatestFinalizedSlot if targetSlot > currentFinalisedSlot { return ierrors.Errorf("finalized slot %d is not reached yet", targetSlot) } return nil - }) + }, deadline, 1*time.Second) } func (d *DockerTestFramework) AwaitEpochFinalized() { From 8a78ffed0c21c9522a8703d9c2f411c37a60faf2 Mon Sep 17 00:00:00 2001 From: jkrvivian Date: Wed, 8 May 2024 16:19:44 +0800 Subject: [PATCH 03/24] Create snapshot when the last epoch is finalized in Test_ManagementAPI_Snapshots --- tools/docker-network/tests/api_management_test.go | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/tools/docker-network/tests/api_management_test.go b/tools/docker-network/tests/api_management_test.go index 76ebb7c16..3d96a484f 100644 --- a/tools/docker-network/tests/api_management_test.go +++ b/tools/docker-network/tests/api_management_test.go @@ -291,16 +291,6 @@ func Test_ManagementAPI_Snapshots(t *testing.T) { managementClient, err := nodeClientV1.Management(getContextWithTimeout(5 * time.Second)) require.NoError(t, err) - awaitNextCommittedEpoch := func() { - info, err := nodeClientV1.Info(getContextWithTimeout(5 * time.Second)) - require.NoError(t, err) - - currentEpoch := nodeClientV1.CommittedAPI().TimeProvider().EpochFromSlot(info.Status.LatestCommitmentID.Slot()) - - // await the start slot of the next epoch - d.AwaitCommitment(nodeClientV1.CommittedAPI().TimeProvider().EpochStart(currentEpoch + 1)) - } - type test struct { name string testFunc func(t *testing.T) @@ -311,7 +301,7 @@ func Test_ManagementAPI_Snapshots(t *testing.T) { name: "Test_CreateSnapshot", testFunc: func(t *testing.T) { // wait for the next epoch to start - awaitNextCommittedEpoch() + d.AwaitEpochFinalized() // create snapshot snapshotResponse, err := managementClient.CreateSnapshot(getContextWithTimeout(5 * time.Second)) From d3bcb911665fc7c15733bfc64afca7c18127d827 Mon Sep 17 00:00:00 2001 From: jkrvivian Date: Wed, 8 May 2024 16:30:46 +0800 Subject: [PATCH 04/24] Fix Test_ManagementAPI_Snapshots --- tools/docker-network/tests/api_management_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/docker-network/tests/api_management_test.go b/tools/docker-network/tests/api_management_test.go index 3d96a484f..5c0dd67aa 100644 --- a/tools/docker-network/tests/api_management_test.go +++ b/tools/docker-network/tests/api_management_test.go @@ -185,8 +185,8 @@ func Test_ManagementAPI_Peers_BadRequests(t *testing.T) { func Test_ManagementAPI_Pruning(t *testing.T) { d := dockertestframework.NewDockerTestFramework(t, dockertestframework.WithProtocolParametersOptions( - iotago.WithTimeProviderOptions(0, time.Now().Unix(), 4, 4), - iotago.WithLivenessOptions(3, 4, 2, 4, 5), + iotago.WithTimeProviderOptions(0, time.Now().Unix(), 10, 3), + iotago.WithLivenessOptions(10, 10, 2, 4, 5), iotago.WithCongestionControlOptions(1, 1, 1, 400_000, 250_000, 50_000_000, 1000, 100), iotago.WithRewardsOptions(8, 10, 2, 384), iotago.WithTargetCommitteeSize(4), @@ -266,8 +266,8 @@ func Test_ManagementAPI_Pruning(t *testing.T) { func Test_ManagementAPI_Snapshots(t *testing.T) { d := dockertestframework.NewDockerTestFramework(t, dockertestframework.WithProtocolParametersOptions( - iotago.WithTimeProviderOptions(0, time.Now().Unix(), 3, 4), - iotago.WithLivenessOptions(3, 4, 2, 4, 8), + iotago.WithTimeProviderOptions(0, time.Now().Unix(), 10, 3), + iotago.WithLivenessOptions(10, 10, 2, 4, 5), iotago.WithCongestionControlOptions(1, 1, 1, 400_000, 250_000, 50_000_000, 1000, 100), iotago.WithRewardsOptions(8, 10, 2, 384), iotago.WithTargetCommitteeSize(4), From b6c32114ad67fc8ca2aea395ce8c478a6e736ebc Mon Sep 17 00:00:00 2001 From: jkrvivian Date: Wed, 8 May 2024 16:42:00 +0800 Subject: [PATCH 05/24] Use the correct port of node5 in dockertests --- tools/docker-network/tests/accounttransition_test.go | 2 +- tools/docker-network/tests/api_core_test.go | 6 +++--- tools/docker-network/tests/api_management_test.go | 8 ++++---- tools/docker-network/tests/committeerotation_test.go | 10 +++++----- tools/docker-network/tests/eventapi_test.go | 2 +- .../tests/mempool_invalid_signatures_test.go | 2 +- tools/docker-network/tests/rewards_test.go | 6 +++--- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/tools/docker-network/tests/accounttransition_test.go b/tools/docker-network/tests/accounttransition_test.go index 54f72324b..e7b638c8c 100644 --- a/tools/docker-network/tests/accounttransition_test.go +++ b/tools/docker-network/tests/accounttransition_test.go @@ -32,7 +32,7 @@ func Test_AccountTransitions(t *testing.T) { d.AddValidatorNode("V2", "docker-network-inx-validator-2-1", "http://localhost:8060", "rms1pqm4xk8e9ny5w5rxjkvtp249tfhlwvcshyr3pc0665jvp7g3hc875k538hl") d.AddValidatorNode("V3", "docker-network-inx-validator-3-1", "http://localhost:8070", "rms1pp4wuuz0y42caz48vv876qfpmffswsvg40zz8v79sy8cp0jfxm4kunflcgt") d.AddValidatorNode("V4", "docker-network-inx-validator-4-1", "http://localhost:8040", "rms1pr8cxs3dzu9xh4cduff4dd4cxdthpjkpwmz2244f75m0urslrsvtsshrrjw") - d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8090") + d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8080") err := d.Run() require.NoError(t, err) diff --git a/tools/docker-network/tests/api_core_test.go b/tools/docker-network/tests/api_core_test.go index 838f5d5b4..117afd472 100644 --- a/tools/docker-network/tests/api_core_test.go +++ b/tools/docker-network/tests/api_core_test.go @@ -272,7 +272,7 @@ func Test_ValidatorsAPI(t *testing.T) { d.AddValidatorNode("V2", "docker-network-inx-validator-2-1", "http://localhost:8060", "rms1pqm4xk8e9ny5w5rxjkvtp249tfhlwvcshyr3pc0665jvp7g3hc875k538hl") d.AddValidatorNode("V3", "docker-network-inx-validator-3-1", "http://localhost:8070", "rms1pp4wuuz0y42caz48vv876qfpmffswsvg40zz8v79sy8cp0jfxm4kunflcgt") d.AddValidatorNode("V4", "docker-network-inx-validator-4-1", "http://localhost:8040", "rms1pr8cxs3dzu9xh4cduff4dd4cxdthpjkpwmz2244f75m0urslrsvtsshrrjw") - d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8090") + d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8080") runErr := d.Run() require.NoError(t, runErr) @@ -343,7 +343,7 @@ func Test_CoreAPI(t *testing.T) { d.AddValidatorNode("V2", "docker-network-inx-validator-2-1", "http://localhost:8060", "rms1pqm4xk8e9ny5w5rxjkvtp249tfhlwvcshyr3pc0665jvp7g3hc875k538hl") d.AddValidatorNode("V3", "docker-network-inx-validator-3-1", "http://localhost:8070", "rms1pp4wuuz0y42caz48vv876qfpmffswsvg40zz8v79sy8cp0jfxm4kunflcgt") d.AddValidatorNode("V4", "docker-network-inx-validator-4-1", "http://localhost:8040", "rms1pr8cxs3dzu9xh4cduff4dd4cxdthpjkpwmz2244f75m0urslrsvtsshrrjw") - d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8090") + d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8080") runErr := d.Run() require.NoError(t, runErr) @@ -688,7 +688,7 @@ func Test_CoreAPI_BadRequests(t *testing.T) { d.AddValidatorNode("V2", "docker-network-inx-validator-2-1", "http://localhost:8060", "rms1pqm4xk8e9ny5w5rxjkvtp249tfhlwvcshyr3pc0665jvp7g3hc875k538hl") d.AddValidatorNode("V3", "docker-network-inx-validator-3-1", "http://localhost:8070", "rms1pp4wuuz0y42caz48vv876qfpmffswsvg40zz8v79sy8cp0jfxm4kunflcgt") d.AddValidatorNode("V4", "docker-network-inx-validator-4-1", "http://localhost:8040", "rms1pr8cxs3dzu9xh4cduff4dd4cxdthpjkpwmz2244f75m0urslrsvtsshrrjw") - d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8090") + d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8080") runErr := d.Run() require.NoError(t, runErr) diff --git a/tools/docker-network/tests/api_management_test.go b/tools/docker-network/tests/api_management_test.go index 5c0dd67aa..5b0533cdd 100644 --- a/tools/docker-network/tests/api_management_test.go +++ b/tools/docker-network/tests/api_management_test.go @@ -43,7 +43,7 @@ func Test_ManagementAPI_Peers(t *testing.T) { d.AddValidatorNode("V2", "docker-network-inx-validator-2-1", "http://localhost:8060", "rms1pqm4xk8e9ny5w5rxjkvtp249tfhlwvcshyr3pc0665jvp7g3hc875k538hl") d.AddValidatorNode("V3", "docker-network-inx-validator-3-1", "http://localhost:8070", "rms1pp4wuuz0y42caz48vv876qfpmffswsvg40zz8v79sy8cp0jfxm4kunflcgt") d.AddValidatorNode("V4", "docker-network-inx-validator-4-1", "http://localhost:8040", "rms1pr8cxs3dzu9xh4cduff4dd4cxdthpjkpwmz2244f75m0urslrsvtsshrrjw") - d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8090") + d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8080") runErr := d.Run() require.NoError(t, runErr) @@ -132,7 +132,7 @@ func Test_ManagementAPI_Peers_BadRequests(t *testing.T) { d.AddValidatorNode("V2", "docker-network-inx-validator-2-1", "http://localhost:8060", "rms1pqm4xk8e9ny5w5rxjkvtp249tfhlwvcshyr3pc0665jvp7g3hc875k538hl") d.AddValidatorNode("V3", "docker-network-inx-validator-3-1", "http://localhost:8070", "rms1pp4wuuz0y42caz48vv876qfpmffswsvg40zz8v79sy8cp0jfxm4kunflcgt") d.AddValidatorNode("V4", "docker-network-inx-validator-4-1", "http://localhost:8040", "rms1pr8cxs3dzu9xh4cduff4dd4cxdthpjkpwmz2244f75m0urslrsvtsshrrjw") - d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8090") + d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8080") runErr := d.Run() require.NoError(t, runErr) @@ -198,7 +198,7 @@ func Test_ManagementAPI_Pruning(t *testing.T) { d.AddValidatorNode("V2", "docker-network-inx-validator-2-1", "http://localhost:8060", "rms1pqm4xk8e9ny5w5rxjkvtp249tfhlwvcshyr3pc0665jvp7g3hc875k538hl") d.AddValidatorNode("V3", "docker-network-inx-validator-3-1", "http://localhost:8070", "rms1pp4wuuz0y42caz48vv876qfpmffswsvg40zz8v79sy8cp0jfxm4kunflcgt") d.AddValidatorNode("V4", "docker-network-inx-validator-4-1", "http://localhost:8040", "rms1pr8cxs3dzu9xh4cduff4dd4cxdthpjkpwmz2244f75m0urslrsvtsshrrjw") - d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8090") + d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8080") runErr := d.Run() require.NoError(t, runErr) @@ -278,7 +278,7 @@ func Test_ManagementAPI_Snapshots(t *testing.T) { d.AddValidatorNode("V2", "docker-network-inx-validator-2-1", "http://localhost:8060", "rms1pqm4xk8e9ny5w5rxjkvtp249tfhlwvcshyr3pc0665jvp7g3hc875k538hl") d.AddValidatorNode("V3", "docker-network-inx-validator-3-1", "http://localhost:8070", "rms1pp4wuuz0y42caz48vv876qfpmffswsvg40zz8v79sy8cp0jfxm4kunflcgt") d.AddValidatorNode("V4", "docker-network-inx-validator-4-1", "http://localhost:8040", "rms1pr8cxs3dzu9xh4cduff4dd4cxdthpjkpwmz2244f75m0urslrsvtsshrrjw") - d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8090") + d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8080") runErr := d.Run() require.NoError(t, runErr) diff --git a/tools/docker-network/tests/committeerotation_test.go b/tools/docker-network/tests/committeerotation_test.go index 6e117dcc4..576be1af8 100644 --- a/tools/docker-network/tests/committeerotation_test.go +++ b/tools/docker-network/tests/committeerotation_test.go @@ -36,7 +36,7 @@ func Test_SmallerCommittee(t *testing.T) { d.AddValidatorNode("V2", "docker-network-inx-validator-2-1", "http://localhost:8060", "rms1pqm4xk8e9ny5w5rxjkvtp249tfhlwvcshyr3pc0665jvp7g3hc875k538hl") d.AddValidatorNode("V3", "docker-network-inx-validator-3-1", "http://localhost:8070", "rms1pp4wuuz0y42caz48vv876qfpmffswsvg40zz8v79sy8cp0jfxm4kunflcgt") d.AddValidatorNode("V4", "docker-network-inx-validator-4-1", "http://localhost:8040", "rms1pr8cxs3dzu9xh4cduff4dd4cxdthpjkpwmz2244f75m0urslrsvtsshrrjw") - d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8090") + d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8080") err := d.Run() require.NoError(t, err) @@ -81,7 +81,7 @@ func Test_ReuseDueToNoFinalization(t *testing.T) { d.AddValidatorNode("V2", "docker-network-inx-validator-2-1", "http://localhost:8060", "rms1pqm4xk8e9ny5w5rxjkvtp249tfhlwvcshyr3pc0665jvp7g3hc875k538hl") d.AddValidatorNode("V3", "docker-network-inx-validator-3-1", "http://localhost:8070", "rms1pp4wuuz0y42caz48vv876qfpmffswsvg40zz8v79sy8cp0jfxm4kunflcgt") d.AddValidatorNode("V4", "docker-network-inx-validator-4-1", "http://localhost:8040", "rms1pr8cxs3dzu9xh4cduff4dd4cxdthpjkpwmz2244f75m0urslrsvtsshrrjw") - d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8090") + d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8080") err := d.Run() require.NoError(t, err) @@ -150,7 +150,7 @@ func Test_NoCandidacyPayload(t *testing.T) { d.AddValidatorNode("V2", "docker-network-inx-validator-2-1", "http://localhost:8060", "rms1pqm4xk8e9ny5w5rxjkvtp249tfhlwvcshyr3pc0665jvp7g3hc875k538hl", false) d.AddValidatorNode("V3", "docker-network-inx-validator-3-1", "http://localhost:8070", "rms1pp4wuuz0y42caz48vv876qfpmffswsvg40zz8v79sy8cp0jfxm4kunflcgt", false) d.AddValidatorNode("V4", "docker-network-inx-validator-4-1", "http://localhost:8040", "rms1pr8cxs3dzu9xh4cduff4dd4cxdthpjkpwmz2244f75m0urslrsvtsshrrjw", false) - d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8090") + d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8080") err := d.Run() require.NoError(t, err) @@ -200,7 +200,7 @@ func Test_Staking(t *testing.T) { d.AddValidatorNode("V2", "docker-network-inx-validator-2-1", "http://localhost:8060", "rms1pqm4xk8e9ny5w5rxjkvtp249tfhlwvcshyr3pc0665jvp7g3hc875k538hl") d.AddValidatorNode("V3", "docker-network-inx-validator-3-1", "http://localhost:8070", "rms1pp4wuuz0y42caz48vv876qfpmffswsvg40zz8v79sy8cp0jfxm4kunflcgt") d.AddValidatorNode("V4", "docker-network-inx-validator-4-1", "http://localhost:8040", "rms1pr8cxs3dzu9xh4cduff4dd4cxdthpjkpwmz2244f75m0urslrsvtsshrrjw") - d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8090") + d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8080") err := d.Run() require.NoError(t, err) @@ -247,7 +247,7 @@ func Test_Delegation(t *testing.T) { d.AddValidatorNode("V3", "docker-network-inx-validator-3-1", "http://localhost:8070", "rms1pp4wuuz0y42caz48vv876qfpmffswsvg40zz8v79sy8cp0jfxm4kunflcgt") // V4 pubKey in hex: 0xc9ceac37d293155a578381aa313ee74edfa3ac73ee930d045564aae7771e8ffe d.AddValidatorNode("V4", "docker-network-inx-validator-4-1", "http://localhost:8040", "rms1pr8cxs3dzu9xh4cduff4dd4cxdthpjkpwmz2244f75m0urslrsvtsshrrjw") - d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8090") + d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8080") err := d.Run() require.NoError(t, err) diff --git a/tools/docker-network/tests/eventapi_test.go b/tools/docker-network/tests/eventapi_test.go index 7e2eb378c..b1255624e 100644 --- a/tools/docker-network/tests/eventapi_test.go +++ b/tools/docker-network/tests/eventapi_test.go @@ -38,7 +38,7 @@ func Test_MQTTTopics(t *testing.T) { d.AddValidatorNode("V2", "docker-network-inx-validator-2-1", "http://localhost:8060", "rms1pqm4xk8e9ny5w5rxjkvtp249tfhlwvcshyr3pc0665jvp7g3hc875k538hl") d.AddValidatorNode("V3", "docker-network-inx-validator-3-1", "http://localhost:8070", "rms1pp4wuuz0y42caz48vv876qfpmffswsvg40zz8v79sy8cp0jfxm4kunflcgt") d.AddValidatorNode("V4", "docker-network-inx-validator-4-1", "http://localhost:8040", "rms1pr8cxs3dzu9xh4cduff4dd4cxdthpjkpwmz2244f75m0urslrsvtsshrrjw") - d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8090") + d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8080") err := d.Run() require.NoError(t, err) diff --git a/tools/docker-network/tests/mempool_invalid_signatures_test.go b/tools/docker-network/tests/mempool_invalid_signatures_test.go index feee13e79..6af13dcac 100644 --- a/tools/docker-network/tests/mempool_invalid_signatures_test.go +++ b/tools/docker-network/tests/mempool_invalid_signatures_test.go @@ -30,7 +30,7 @@ func Test_MempoolInvalidSignatures(t *testing.T) { d.AddValidatorNode("V2", "docker-network-inx-validator-2-1", "http://localhost:8060", "rms1pqm4xk8e9ny5w5rxjkvtp249tfhlwvcshyr3pc0665jvp7g3hc875k538hl") d.AddValidatorNode("V3", "docker-network-inx-validator-3-1", "http://localhost:8070", "rms1pp4wuuz0y42caz48vv876qfpmffswsvg40zz8v79sy8cp0jfxm4kunflcgt") d.AddValidatorNode("V4", "docker-network-inx-validator-4-1", "http://localhost:8040", "rms1pr8cxs3dzu9xh4cduff4dd4cxdthpjkpwmz2244f75m0urslrsvtsshrrjw") - d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8090") + d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8080") err := d.Run() require.NoError(t, err) diff --git a/tools/docker-network/tests/rewards_test.go b/tools/docker-network/tests/rewards_test.go index 55950108b..539e6e7c9 100644 --- a/tools/docker-network/tests/rewards_test.go +++ b/tools/docker-network/tests/rewards_test.go @@ -34,7 +34,7 @@ func Test_ValidatorRewards(t *testing.T) { d.AddValidatorNode("V2", "docker-network-inx-validator-2-1", "http://localhost:8060", "rms1pqm4xk8e9ny5w5rxjkvtp249tfhlwvcshyr3pc0665jvp7g3hc875k538hl") d.AddValidatorNode("V3", "docker-network-inx-validator-3-1", "http://localhost:8070", "rms1pp4wuuz0y42caz48vv876qfpmffswsvg40zz8v79sy8cp0jfxm4kunflcgt") d.AddValidatorNode("V4", "docker-network-inx-validator-4-1", "http://localhost:8040", "rms1pr8cxs3dzu9xh4cduff4dd4cxdthpjkpwmz2244f75m0urslrsvtsshrrjw") - d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8090") + d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8080") err := d.Run() require.NoError(t, err) @@ -151,7 +151,7 @@ func Test_DelegatorRewards(t *testing.T) { d.AddValidatorNode("V2", "docker-network-inx-validator-2-1", "http://localhost:8060", "rms1pqm4xk8e9ny5w5rxjkvtp249tfhlwvcshyr3pc0665jvp7g3hc875k538hl") d.AddValidatorNode("V3", "docker-network-inx-validator-3-1", "http://localhost:8070", "rms1pp4wuuz0y42caz48vv876qfpmffswsvg40zz8v79sy8cp0jfxm4kunflcgt") d.AddValidatorNode("V4", "docker-network-inx-validator-4-1", "http://localhost:8040", "rms1pr8cxs3dzu9xh4cduff4dd4cxdthpjkpwmz2244f75m0urslrsvtsshrrjw") - d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8090") + d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8080") err := d.Run() require.NoError(t, err) @@ -209,7 +209,7 @@ func Test_DelayedClaimingRewards(t *testing.T) { d.AddValidatorNode("V2", "docker-network-inx-validator-2-1", "http://localhost:8060", "rms1pqm4xk8e9ny5w5rxjkvtp249tfhlwvcshyr3pc0665jvp7g3hc875k538hl") d.AddValidatorNode("V3", "docker-network-inx-validator-3-1", "http://localhost:8070", "rms1pp4wuuz0y42caz48vv876qfpmffswsvg40zz8v79sy8cp0jfxm4kunflcgt") d.AddValidatorNode("V4", "docker-network-inx-validator-4-1", "http://localhost:8040", "rms1pr8cxs3dzu9xh4cduff4dd4cxdthpjkpwmz2244f75m0urslrsvtsshrrjw") - d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8090") + d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8080") err := d.Run() require.NoError(t, err) From 9e9df61b71d8fd22f59b57b7c54abf4161856068 Mon Sep 17 00:00:00 2001 From: jkrvivian Date: Wed, 8 May 2024 21:01:17 +0800 Subject: [PATCH 06/24] Remove slot comparison in AssertCommittee --- tools/docker-network/tests/dockertestframework/asserts.go | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/docker-network/tests/dockertestframework/asserts.go b/tools/docker-network/tests/dockertestframework/asserts.go index 3764ee2c3..49b3e79bd 100644 --- a/tools/docker-network/tests/dockertestframework/asserts.go +++ b/tools/docker-network/tests/dockertestframework/asserts.go @@ -76,7 +76,6 @@ func (d *DockerTestFramework) AssertCommittee(expectedEpoch iotago.EpochIndex, e status := d.NodeStatus("V1") testAPI := d.defaultWallet.Client.CommittedAPI() expectedSlotStart := testAPI.TimeProvider().EpochStart(expectedEpoch) - require.Greater(d.Testing, expectedSlotStart, status.LatestAcceptedBlockSlot) if status.LatestAcceptedBlockSlot < expectedSlotStart { slotToWait := expectedSlotStart - status.LatestAcceptedBlockSlot From 6347bed90eef53f35569da179dded894610c1ec6 Mon Sep 17 00:00:00 2001 From: jkrvivian Date: Wed, 8 May 2024 21:02:36 +0800 Subject: [PATCH 07/24] Extend Test_SyncFromSnapshot to include committee rotation via delegation --- .../tests/sync_snapshot_test.go | 123 +++++++++++++----- 1 file changed, 93 insertions(+), 30 deletions(-) diff --git a/tools/docker-network/tests/sync_snapshot_test.go b/tools/docker-network/tests/sync_snapshot_test.go index 1f0e8efd0..f800a426f 100644 --- a/tools/docker-network/tests/sync_snapshot_test.go +++ b/tools/docker-network/tests/sync_snapshot_test.go @@ -4,11 +4,13 @@ package tests import ( "context" + "fmt" "testing" "time" "github.com/stretchr/testify/require" + "github.com/iotaledger/iota-core/pkg/testsuite/mock" "github.com/iotaledger/iota-core/tools/docker-network/tests/dockertestframework" iotago "github.com/iotaledger/iota.go/v4" ) @@ -20,7 +22,7 @@ func Test_SyncFromSnapshot(t *testing.T) { iotago.WithLivenessOptions(10, 10, 2, 4, 5), iotago.WithCongestionControlOptions(1, 1, 1, 400_000, 250_000, 50_000_000, 1000, 100), iotago.WithRewardsOptions(8, 10, 2, 384), - iotago.WithTargetCommitteeSize(4), + iotago.WithTargetCommitteeSize(3), )) defer d.Stop() @@ -36,57 +38,118 @@ func Test_SyncFromSnapshot(t *testing.T) { d.WaitUntilNetworkReady() ctx := context.Background() - delegatorWallet, accountData := d.CreateAccountFromFaucet() - clt := delegatorWallet.Client + clt := d.DefaultWallet().Client - // delegate funds to V2 - delegationOutputData := d.DelegateToValidator(delegatorWallet, d.Node("V2").AccountAddress(t)) - d.AwaitCommitment(delegationOutputData.ID.CreationSlot()) + createAccountAndDelegateTo := func(receiver *dockertestframework.Node) (*mock.Wallet, *mock.AccountData, *mock.OutputData) { + delegatorWallet, accountData := d.CreateAccountFromFaucet() + clt := delegatorWallet.Client - // check if V2 received the delegator stake - v2Resp, err := clt.Validator(ctx, d.Node("V2").AccountAddress(t)) - require.NoError(t, err) - require.Greater(t, v2Resp.PoolStake, v2Resp.ValidatorStake) + // delegate funds to receiver + delegationOutputData := d.DelegateToValidator(delegatorWallet, receiver.AccountAddress(t)) + d.AwaitCommitment(delegationOutputData.ID.CreationSlot()) + + // check if receiver received the delegator stake + resp, err := clt.Validator(ctx, receiver.AccountAddress(t)) + require.NoError(t, err) + require.Greater(t, resp.PoolStake, resp.ValidatorStake) + + return delegatorWallet, accountData, delegationOutputData + } + + v1DelegatorWallet, v1DelegatorAccountData, v1DelegationOutputData := createAccountAndDelegateTo(d.Node("V1")) + v2DelegatorWallet, v2DelegatorAccountData, v2DelegationOutputData := createAccountAndDelegateTo(d.Node("V2")) //nolint:forcetypeassert - currentEpoch := clt.CommittedAPI().TimeProvider().EpochFromSlot(delegatorWallet.CurrentSlot()) - expectedEpoch := delegationOutputData.Output.(*iotago.DelegationOutput).StartEpoch + 2 + currentEpoch := clt.CommittedAPI().TimeProvider().CurrentEpoch() + expectedEpoch := v2DelegationOutputData.Output.(*iotago.DelegationOutput).StartEpoch + 2 for range expectedEpoch - currentEpoch { d.AwaitEpochFinalized() } + d.AssertCommittee(expectedEpoch, d.AccountsFromNodes(d.Nodes("V1", "V2", "V4")...)) - // claim rewards that put to an basic output - rewardsOutputID := d.ClaimRewardsForDelegator(ctx, delegatorWallet, delegationOutputData) + // claim rewards for v1 delegator + v1DelegatorRewardsOutputID := d.ClaimRewardsForDelegator(ctx, v1DelegatorWallet, v1DelegationOutputData) // check if the mana increased as expected node5Clt := d.Client("node5") - outputFromAPI, err := node5Clt.OutputByID(ctx, rewardsOutputID) + outputFromAPI, err := node5Clt.OutputByID(ctx, v1DelegatorRewardsOutputID) require.NoError(t, err) - rewardsOutput := delegatorWallet.Output(rewardsOutputID) + rewardsOutput := v1DelegatorWallet.Output(v1DelegatorRewardsOutputID) require.Equal(t, rewardsOutput.Output.StoredMana(), outputFromAPI.StoredMana()) d.AwaitEpochFinalized() - // create snapshot - nodeClientV1 := d.Client("V1") - managementClient, err := nodeClientV1.Management(getContextWithTimeout(5 * time.Second)) + managementClient, err := clt.Management(getContextWithTimeout(5 * time.Second)) require.NoError(t, err) - response, err := managementClient.CreateSnapshot(getContextWithTimeout(5 * time.Second)) - require.NoError(t, err) + // take the snapshot and restart node5 + { + fmt.Println("Create the first snapshot...") + response, err := managementClient.CreateSnapshot(getContextWithTimeout(5 * time.Second)) + require.NoError(t, err) - // Deletes the database of node5 and restarts it with the just created snapshot. - d.ResetNode("node5", response.FilePath) + // Deletes the database of node5 and restarts it with the just created snapshot. + d.ResetNode("node5", response.FilePath) - d.AwaitEpochFinalized() - d.AwaitEpochFinalized() + d.AwaitEpochFinalized() + d.AwaitEpochFinalized() - // check if the account and rewardsOutput are available - node5Clt = d.Client("node5") - _, err = node5Clt.Validator(ctx, accountData.Address) - require.NoError(t, err) + // check if the committee is the same among nodes + currentEpoch := clt.CommittedAPI().TimeProvider().CurrentEpoch() + d.AssertCommittee(currentEpoch, d.AccountsFromNodes(d.Nodes("V1", "V2", "V4")...)) + + // check if the account and rewardsOutput are available + node5Clt = d.Client("node5") + _, err = node5Clt.Validator(ctx, v1DelegatorAccountData.Address) + require.NoError(t, err) + _, err = node5Clt.Validator(ctx, v2DelegatorAccountData.Address) + require.NoError(t, err) - outputFromAPI, err = node5Clt.OutputByID(ctx, rewardsOutputID) + _, err = node5Clt.OutputByID(ctx, v1DelegatorRewardsOutputID) + require.NoError(t, err) + + } + + // claim rewards for V2 delegator, and see if the output is available on node5 + v2DelegatorRewardsOutputID := d.ClaimRewardsForDelegator(ctx, v2DelegatorWallet, v2DelegationOutputData) + _, err = node5Clt.OutputByID(ctx, v2DelegatorRewardsOutputID) require.NoError(t, err) + + // create V3 delegator, the committee should change to V1, V3, V4 + v3DelegatorWallet, v3DelegatorAccountData, v3DelegationOutputData := createAccountAndDelegateTo(d.Node("V3")) + currentEpoch = clt.CommittedAPI().TimeProvider().CurrentEpoch() + expectedEpoch = v3DelegationOutputData.Output.(*iotago.DelegationOutput).StartEpoch + 1 + for range expectedEpoch - currentEpoch { + d.AwaitEpochFinalized() + } + + d.AssertCommittee(expectedEpoch, d.AccountsFromNodes(d.Nodes("V1", "V3", "V4")...)) + + d.AwaitEpochFinalized() + + // take the snapshot again and restart node5 + { + fmt.Println("Create the second snapshot...") + response, err := managementClient.CreateSnapshot(getContextWithTimeout(5 * time.Second)) + require.NoError(t, err) + + // Deletes the database of node5 and restarts it with the just created snapshot. + d.ResetNode("node5", response.FilePath) + currentEpoch = clt.CommittedAPI().TimeProvider().EpochFromSlot(v3DelegatorWallet.CurrentSlot()) + d.AssertCommittee(currentEpoch, d.AccountsFromNodes(d.Nodes("V1", "V3", "V4")...)) + + node5Clt = d.Client("node5") + _, err = node5Clt.Validator(ctx, v1DelegatorAccountData.Address) + require.NoError(t, err) + _, err = node5Clt.Validator(ctx, v2DelegatorAccountData.Address) + require.NoError(t, err) + _, err = node5Clt.Validator(ctx, v3DelegatorAccountData.Address) + require.NoError(t, err) + + _, err = node5Clt.OutputByID(ctx, v1DelegatorRewardsOutputID) + require.NoError(t, err) + _, err = node5Clt.OutputByID(ctx, v2DelegatorRewardsOutputID) + require.NoError(t, err) + } } From 477340a49500102a2d1bc79e8c00f39888ef9ab1 Mon Sep 17 00:00:00 2001 From: muXxer Date: Wed, 8 May 2024 18:10:14 +0200 Subject: [PATCH 08/24] Make sure dockertestframework starts with clean state --- tools/docker-network/tests/dockertestframework/framework.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/docker-network/tests/dockertestframework/framework.go b/tools/docker-network/tests/dockertestframework/framework.go index a6b203b77..31332dfeb 100644 --- a/tools/docker-network/tests/dockertestframework/framework.go +++ b/tools/docker-network/tests/dockertestframework/framework.go @@ -130,6 +130,9 @@ func (d *DockerTestFramework) DockerComposeUp(detach ...bool) error { } func (d *DockerTestFramework) Run() error { + // first we remove old containers, volumes and orphans + _ = exec.Command("docker", "compose", "down", "-v", "--remove-orphans").Run() + ch := make(chan error) stopCh := make(chan struct{}) defer close(ch) @@ -183,7 +186,8 @@ func (d *DockerTestFramework) Stop() { fmt.Println("Stop the network...") defer fmt.Println("Stop the network.....done") - _ = exec.Command("docker", "compose", "down").Run() + // remove volumes and orphans + _ = exec.Command("docker", "compose", "down", "-v", "--remove-orphans").Run() _ = exec.Command("rm", d.snapshotPath).Run() //nolint:gosec } From 2a41617140c99a1b448c330d1676c755a1c4dcbd Mon Sep 17 00:00:00 2001 From: muXxer Date: Wed, 8 May 2024 18:10:49 +0200 Subject: [PATCH 09/24] Randomly create network names for docker tests to avoid autopeering problems --- tools/docker-network/tests/dockertestframework/options.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/docker-network/tests/dockertestframework/options.go b/tools/docker-network/tests/dockertestframework/options.go index 1df7097b9..b706ce12a 100644 --- a/tools/docker-network/tests/dockertestframework/options.go +++ b/tools/docker-network/tests/dockertestframework/options.go @@ -3,6 +3,7 @@ package dockertestframework import ( + "fmt" "time" "github.com/iotaledger/hive.go/runtime/options" @@ -13,7 +14,7 @@ import ( ) var DefaultProtocolParametersOptions = []options.Option[iotago.V3ProtocolParameters]{ - iotago.WithNetworkOptions("docker", iotago.PrefixTestnet), + iotago.WithNetworkOptions(fmt.Sprintf("docker-tests-%d", time.Now().Unix()), iotago.PrefixTestnet), } // DefaultAccountOptions are the default snapshot options for the docker network. From 28a7f47c18d739047ac4de6af4ea080e90d8d325 Mon Sep 17 00:00:00 2001 From: muXxer Date: Wed, 8 May 2024 18:14:28 +0200 Subject: [PATCH 10/24] Fix WithTargetCommitteeSize in Test_SyncFromSnapshot --- tools/docker-network/tests/sync_snapshot_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/docker-network/tests/sync_snapshot_test.go b/tools/docker-network/tests/sync_snapshot_test.go index f800a426f..e31119382 100644 --- a/tools/docker-network/tests/sync_snapshot_test.go +++ b/tools/docker-network/tests/sync_snapshot_test.go @@ -22,7 +22,7 @@ func Test_SyncFromSnapshot(t *testing.T) { iotago.WithLivenessOptions(10, 10, 2, 4, 5), iotago.WithCongestionControlOptions(1, 1, 1, 400_000, 250_000, 50_000_000, 1000, 100), iotago.WithRewardsOptions(8, 10, 2, 384), - iotago.WithTargetCommitteeSize(3), + iotago.WithTargetCommitteeSize(4), )) defer d.Stop() From bda276d08610dc8ece5b0fea5b46fb70063c725b Mon Sep 17 00:00:00 2001 From: muXxer Date: Wed, 8 May 2024 18:28:59 +0200 Subject: [PATCH 11/24] Fix AssertCommittee --- .../tests/dockertestframework/asserts.go | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/tools/docker-network/tests/dockertestframework/asserts.go b/tools/docker-network/tests/dockertestframework/asserts.go index 49b3e79bd..2022e9d44 100644 --- a/tools/docker-network/tests/dockertestframework/asserts.go +++ b/tools/docker-network/tests/dockertestframework/asserts.go @@ -77,6 +77,9 @@ func (d *DockerTestFramework) AssertCommittee(expectedEpoch iotago.EpochIndex, e testAPI := d.defaultWallet.Client.CommittedAPI() expectedSlotStart := testAPI.TimeProvider().EpochStart(expectedEpoch) + // the expected slot needs to be at least now or in the future, otherwise we can't wait for it and get wrong results + require.GreaterOrEqual(d.Testing, expectedSlotStart, status.LatestAcceptedBlockSlot) + if status.LatestAcceptedBlockSlot < expectedSlotStart { slotToWait := expectedSlotStart - status.LatestAcceptedBlockSlot secToWait := time.Duration(slotToWait) * time.Duration(testAPI.ProtocolParameters().SlotDurationInSeconds()) * time.Second @@ -91,17 +94,17 @@ func (d *DockerTestFramework) AssertCommittee(expectedEpoch iotago.EpochIndex, e return err } - if resp.Epoch == expectedEpoch { - members := make([]string, len(resp.Committee)) - for i, member := range resp.Committee { - members[i] = member.AddressBech32 - } + if resp.Epoch != expectedEpoch { + return ierrors.Errorf("expected epoch %d, but got %d", expectedEpoch, resp.Epoch) + } - sort.Strings(members) - if match := lo.Equal(expectedCommitteeMember, members); match { - return nil - } + members := make([]string, len(resp.Committee)) + for i, member := range resp.Committee { + members[i] = member.AddressBech32 + } + sort.Strings(members) + if !lo.Equal(expectedCommitteeMember, members) { return ierrors.Errorf("committee members does not match as expected, expected: %v, actual: %v", expectedCommitteeMember, members) } } From dbd1b055759649ee3197a8e4479f1e9609af65e0 Mon Sep 17 00:00:00 2001 From: muXxer Date: Wed, 8 May 2024 18:29:28 +0200 Subject: [PATCH 12/24] Fix WaitUntilNetworkHealthy --- .../tests/dockertestframework/awaits.go | 4 +-- .../tests/dockertestframework/nodes.go | 28 ++++++++++++------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/tools/docker-network/tests/dockertestframework/awaits.go b/tools/docker-network/tests/dockertestframework/awaits.go index 872d28f47..14c9b696e 100644 --- a/tools/docker-network/tests/dockertestframework/awaits.go +++ b/tools/docker-network/tests/dockertestframework/awaits.go @@ -63,9 +63,9 @@ func (d *DockerTestFramework) AwaitTransactionFailure(ctx context.Context, txID if expectedReason == resp.TransactionFailureReason { return nil - } else { - return ierrors.Errorf("expected transaction %s to have failure reason '%s', got '%s' instead, failure details: %s", txID, expectedReason, resp.TransactionFailureReason, resp.TransactionFailureDetails) } + + return ierrors.Errorf("expected transaction %s to have failure reason '%s', got '%s' instead, failure details: %s", txID, expectedReason, resp.TransactionFailureReason, resp.TransactionFailureDetails) }) } diff --git a/tools/docker-network/tests/dockertestframework/nodes.go b/tools/docker-network/tests/dockertestframework/nodes.go index 1dd7038a4..4fd32e9f4 100644 --- a/tools/docker-network/tests/dockertestframework/nodes.go +++ b/tools/docker-network/tests/dockertestframework/nodes.go @@ -88,18 +88,26 @@ func (d *DockerTestFramework) WaitUntilNetworkHealthy() { fmt.Println("Wait until the network is healthy...") defer fmt.Println("Wait until the network is healthy......done") + // remember a map of nodes that were synced so we don't print the same node multiple times + syncedNodes := make(map[string]struct{}) + d.Eventually(func() error { for _, node := range d.Nodes() { - for { - info, err := d.Client(node.Name).Info(context.TODO()) - if err != nil { - return err - } - - if info.Status.IsNetworkHealthy { - fmt.Println("Node", node.Name, "is synced") - break - } + info, err := d.Client(node.Name).Info(context.TODO()) + if err != nil { + delete(syncedNodes, node.Name) + return ierrors.Errorf("failed to get node %s's info: %w", node.Name, err) + } + + if !info.Status.IsNetworkHealthy { + delete(syncedNodes, node.Name) + return ierrors.Errorf("node %s's network is not healthy", node.Name) + } + + if _, exist := syncedNodes[node.Name]; !exist { + syncedNodes[node.Name] = struct{}{} + + fmt.Println(fmt.Sprintf("Node %s's network is now healthy!", node.Name)) } } From eba25ea6c7d82f267b55415f28d5b9ddb3091365 Mon Sep 17 00:00:00 2001 From: muXxer Date: Wed, 8 May 2024 20:29:54 +0200 Subject: [PATCH 13/24] Print duration until nodes become healthy --- tools/docker-network/tests/dockertestframework/nodes.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/docker-network/tests/dockertestframework/nodes.go b/tools/docker-network/tests/dockertestframework/nodes.go index 4fd32e9f4..65471d7b2 100644 --- a/tools/docker-network/tests/dockertestframework/nodes.go +++ b/tools/docker-network/tests/dockertestframework/nodes.go @@ -7,6 +7,7 @@ import ( "fmt" "math/rand" "testing" + "time" "github.com/stretchr/testify/require" @@ -91,6 +92,8 @@ func (d *DockerTestFramework) WaitUntilNetworkHealthy() { // remember a map of nodes that were synced so we don't print the same node multiple times syncedNodes := make(map[string]struct{}) + ts := time.Now() + d.Eventually(func() error { for _, node := range d.Nodes() { info, err := d.Client(node.Name).Info(context.TODO()) @@ -107,7 +110,7 @@ func (d *DockerTestFramework) WaitUntilNetworkHealthy() { if _, exist := syncedNodes[node.Name]; !exist { syncedNodes[node.Name] = struct{}{} - fmt.Println(fmt.Sprintf("Node %s's network is now healthy!", node.Name)) + fmt.Println(fmt.Sprintf("Node %s's network is healthy after %v!", node.Name, time.Since(ts).Truncate(time.Millisecond))) } } From 9dbcf09c9619acabe23fccbf22b2c80f0e3a27f3 Mon Sep 17 00:00:00 2001 From: muXxer Date: Wed, 8 May 2024 22:01:47 +0200 Subject: [PATCH 14/24] Refactor access to nodes and clients --- tools/docker-network/tests/api_core_test.go | 212 +++++++++--------- .../tests/dockertestframework/framework.go | 5 +- .../tests/dockertestframework/nodes.go | 22 +- 3 files changed, 119 insertions(+), 120 deletions(-) diff --git a/tools/docker-network/tests/api_core_test.go b/tools/docker-network/tests/api_core_test.go index 117afd472..5f5dedeee 100644 --- a/tools/docker-network/tests/api_core_test.go +++ b/tools/docker-network/tests/api_core_test.go @@ -357,21 +357,21 @@ func Test_CoreAPI(t *testing.T) { tests := []struct { name string - testFunc func(t *testing.T, nodeAlias string) + testFunc func(t *testing.T, node *dockertestframework.Node, client mock.Client) }{ { name: "Test_Info", - testFunc: func(t *testing.T, nodeAlias string) { - resp, err := d.Client(nodeAlias).Info(context.Background()) + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { + resp, err := client.Info(context.Background()) require.NoError(t, err) require.NotNil(t, resp) }, }, { name: "Test_BlockByBlockID", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { assetsPerSlot.forEachBlock(t, func(t *testing.T, block *iotago.Block) { - respBlock, err := d.Client(nodeAlias).BlockByBlockID(context.Background(), block.MustID()) + respBlock, err := client.BlockByBlockID(context.Background(), block.MustID()) require.NoError(t, err) require.NotNil(t, respBlock) require.Equal(t, block.MustID(), respBlock.MustID(), "BlockID of retrieved block does not match: %s != %s", block.MustID(), respBlock.MustID()) @@ -380,9 +380,9 @@ func Test_CoreAPI(t *testing.T) { }, { name: "Test_BlockMetadataByBlockID", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { assetsPerSlot.forEachBlock(t, func(t *testing.T, block *iotago.Block) { - resp, err := d.Client(nodeAlias).BlockMetadataByBlockID(context.Background(), block.MustID()) + resp, err := client.BlockMetadataByBlockID(context.Background(), block.MustID()) require.NoError(t, err) require.NotNil(t, resp) require.Equal(t, block.MustID(), resp.BlockID, "BlockID of retrieved block does not match: %s != %s", block.MustID(), resp.BlockID) @@ -390,7 +390,7 @@ func Test_CoreAPI(t *testing.T) { }) assetsPerSlot.forEachReattachment(t, func(t *testing.T, blockID iotago.BlockID) { - resp, err := d.Client(nodeAlias).BlockMetadataByBlockID(context.Background(), blockID) + resp, err := client.BlockMetadataByBlockID(context.Background(), blockID) require.NoError(t, err) require.NotNil(t, resp) require.Equal(t, blockID, resp.BlockID, "BlockID of retrieved block does not match: %s != %s", blockID, resp.BlockID) @@ -400,9 +400,9 @@ func Test_CoreAPI(t *testing.T) { }, { name: "Test_BlockWithMetadata", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { assetsPerSlot.forEachBlock(t, func(t *testing.T, block *iotago.Block) { - resp, err := d.Client(nodeAlias).BlockWithMetadataByBlockID(context.Background(), block.MustID()) + resp, err := client.BlockWithMetadataByBlockID(context.Background(), block.MustID()) require.NoError(t, err) require.NotNil(t, resp) require.Equal(t, block.MustID(), resp.Block.MustID(), "BlockID of retrieved block does not match: %s != %s", block.MustID(), resp.Block.MustID()) @@ -412,8 +412,8 @@ func Test_CoreAPI(t *testing.T) { }, { name: "Test_BlockIssuance", - testFunc: func(t *testing.T, nodeAlias string) { - resp, err := d.Client(nodeAlias).BlockIssuance(context.Background()) + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { + resp, err := client.BlockIssuance(context.Background()) require.NoError(t, err) require.NotNil(t, resp) @@ -422,79 +422,79 @@ func Test_CoreAPI(t *testing.T) { }, { name: "Test_CommitmentBySlot", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { assetsPerSlot.forEachSlot(t, func(t *testing.T, slot iotago.SlotIndex, commitmentsPerNode map[string]iotago.CommitmentID) { - resp, err := d.Client(nodeAlias).CommitmentBySlot(context.Background(), slot) + resp, err := client.CommitmentBySlot(context.Background(), slot) require.NoError(t, err) require.NotNil(t, resp) - commitmentsPerNode[nodeAlias] = resp.MustID() + commitmentsPerNode[node.Name] = resp.MustID() }) }, }, { name: "Test_CommitmentByID", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { assetsPerSlot.forEachCommitment(t, func(t *testing.T, commitmentsPerNode map[string]iotago.CommitmentID) { - resp, err := d.Client(nodeAlias).CommitmentByID(context.Background(), commitmentsPerNode[nodeAlias]) + resp, err := client.CommitmentByID(context.Background(), commitmentsPerNode[node.Name]) require.NoError(t, err) require.NotNil(t, resp) - require.Equal(t, commitmentsPerNode[nodeAlias], resp.MustID(), "Commitment does not match commitment got for the same slot from the same node: %s != %s", commitmentsPerNode[nodeAlias], resp.MustID()) + require.Equal(t, commitmentsPerNode[node.Name], resp.MustID(), "Commitment does not match commitment got for the same slot from the same node: %s != %s", commitmentsPerNode[node.Name], resp.MustID()) }) }, }, { name: "Test_CommitmentUTXOChangesByID", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { assetsPerSlot.forEachCommitment(t, func(t *testing.T, commitmentsPerNode map[string]iotago.CommitmentID) { - resp, err := d.Client(nodeAlias).CommitmentUTXOChangesByID(context.Background(), commitmentsPerNode[nodeAlias]) + resp, err := client.CommitmentUTXOChangesByID(context.Background(), commitmentsPerNode[node.Name]) require.NoError(t, err) require.NotNil(t, resp) - assetsPerSlot.assertUTXOOutputIDsInSlot(t, commitmentsPerNode[nodeAlias].Slot(), resp.CreatedOutputs, resp.ConsumedOutputs) - require.Equal(t, commitmentsPerNode[nodeAlias], resp.CommitmentID, "CommitmentID of retrieved UTXO changes does not match: %s != %s", commitmentsPerNode[nodeAlias], resp.CommitmentID) + assetsPerSlot.assertUTXOOutputIDsInSlot(t, commitmentsPerNode[node.Name].Slot(), resp.CreatedOutputs, resp.ConsumedOutputs) + require.Equal(t, commitmentsPerNode[node.Name], resp.CommitmentID, "CommitmentID of retrieved UTXO changes does not match: %s != %s", commitmentsPerNode[node.Name], resp.CommitmentID) }) }, }, { "Test_CommitmentUTXOChangesFullByID", - func(t *testing.T, nodeAlias string) { + func(t *testing.T, node *dockertestframework.Node, client mock.Client) { assetsPerSlot.forEachCommitment(t, func(t *testing.T, commitmentsPerNode map[string]iotago.CommitmentID) { - resp, err := d.Client(nodeAlias).CommitmentUTXOChangesFullByID(context.Background(), commitmentsPerNode[nodeAlias]) + resp, err := client.CommitmentUTXOChangesFullByID(context.Background(), commitmentsPerNode[node.Name]) require.NoError(t, err) require.NotNil(t, resp) - assetsPerSlot.assertUTXOOutputsInSlot(t, commitmentsPerNode[nodeAlias].Slot(), resp.CreatedOutputs, resp.ConsumedOutputs) - require.Equal(t, commitmentsPerNode[nodeAlias], resp.CommitmentID, "CommitmentID of retrieved UTXO changes does not match: %s != %s", commitmentsPerNode[nodeAlias], resp.CommitmentID) + assetsPerSlot.assertUTXOOutputsInSlot(t, commitmentsPerNode[node.Name].Slot(), resp.CreatedOutputs, resp.ConsumedOutputs) + require.Equal(t, commitmentsPerNode[node.Name], resp.CommitmentID, "CommitmentID of retrieved UTXO changes does not match: %s != %s", commitmentsPerNode[node.Name], resp.CommitmentID) }) }, }, { name: "Test_CommitmentUTXOChangesBySlot", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { assetsPerSlot.forEachCommitment(t, func(t *testing.T, commitmentsPerNode map[string]iotago.CommitmentID) { - resp, err := d.Client(nodeAlias).CommitmentUTXOChangesBySlot(context.Background(), commitmentsPerNode[nodeAlias].Slot()) + resp, err := client.CommitmentUTXOChangesBySlot(context.Background(), commitmentsPerNode[node.Name].Slot()) require.NoError(t, err) require.NotNil(t, resp) - assetsPerSlot.assertUTXOOutputIDsInSlot(t, commitmentsPerNode[nodeAlias].Slot(), resp.CreatedOutputs, resp.ConsumedOutputs) - require.Equal(t, commitmentsPerNode[nodeAlias], resp.CommitmentID, "CommitmentID of retrieved UTXO changes does not match: %s != %s", commitmentsPerNode[nodeAlias], resp.CommitmentID) + assetsPerSlot.assertUTXOOutputIDsInSlot(t, commitmentsPerNode[node.Name].Slot(), resp.CreatedOutputs, resp.ConsumedOutputs) + require.Equal(t, commitmentsPerNode[node.Name], resp.CommitmentID, "CommitmentID of retrieved UTXO changes does not match: %s != %s", commitmentsPerNode[node.Name], resp.CommitmentID) }) }, }, { name: "Test_CommitmentUTXOChangesFullBySlot", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { assetsPerSlot.forEachCommitment(t, func(t *testing.T, commitmentsPerNode map[string]iotago.CommitmentID) { - resp, err := d.Client(nodeAlias).CommitmentUTXOChangesFullBySlot(context.Background(), commitmentsPerNode[nodeAlias].Slot()) + resp, err := client.CommitmentUTXOChangesFullBySlot(context.Background(), commitmentsPerNode[node.Name].Slot()) require.NoError(t, err) require.NotNil(t, resp) - assetsPerSlot.assertUTXOOutputsInSlot(t, commitmentsPerNode[nodeAlias].Slot(), resp.CreatedOutputs, resp.ConsumedOutputs) - require.Equal(t, commitmentsPerNode[nodeAlias], resp.CommitmentID, "CommitmentID of retrieved UTXO changes does not match: %s != %s", commitmentsPerNode[nodeAlias], resp.CommitmentID) + assetsPerSlot.assertUTXOOutputsInSlot(t, commitmentsPerNode[node.Name].Slot(), resp.CreatedOutputs, resp.ConsumedOutputs) + require.Equal(t, commitmentsPerNode[node.Name], resp.CommitmentID, "CommitmentID of retrieved UTXO changes does not match: %s != %s", commitmentsPerNode[node.Name], resp.CommitmentID) }) }, }, { name: "Test_OutputByID", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { assetsPerSlot.forEachOutput(t, func(t *testing.T, outputID iotago.OutputID, output iotago.Output) { - resp, err := d.Client(nodeAlias).OutputByID(context.Background(), outputID) + resp, err := client.OutputByID(context.Background(), outputID) require.NoError(t, err) require.NotNil(t, resp) require.EqualValues(t, output, resp, "Output created is different than retrieved from the API: %s != %s", output, resp) @@ -503,9 +503,9 @@ func Test_CoreAPI(t *testing.T) { }, { name: "Test_OutputMetadata", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { assetsPerSlot.forEachOutput(t, func(t *testing.T, outputID iotago.OutputID, output iotago.Output) { - resp, err := d.Client(nodeAlias).OutputMetadataByID(context.Background(), outputID) + resp, err := client.OutputMetadataByID(context.Background(), outputID) require.NoError(t, err) require.NotNil(t, resp) require.EqualValues(t, outputID, resp.OutputID, "OutputID of retrieved output does not match: %s != %s", outputID, resp.OutputID) @@ -515,9 +515,9 @@ func Test_CoreAPI(t *testing.T) { }, { name: "Test_OutputWithMetadata", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { assetsPerSlot.forEachOutput(t, func(t *testing.T, outputID iotago.OutputID, output iotago.Output) { - out, outMetadata, err := d.Client(nodeAlias).OutputWithMetadataByID(context.Background(), outputID) + out, outMetadata, err := client.OutputWithMetadataByID(context.Background(), outputID) require.NoError(t, err) require.NotNil(t, outMetadata) require.NotNil(t, out) @@ -529,10 +529,10 @@ func Test_CoreAPI(t *testing.T) { }, { name: "Test_TransactionByID", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { assetsPerSlot.forEachTransaction(t, func(t *testing.T, transaction *iotago.SignedTransaction, firstAttachmentID iotago.BlockID) { txID := transaction.Transaction.MustID() - resp, err := d.Client(nodeAlias).TransactionByID(context.Background(), txID) + resp, err := client.TransactionByID(context.Background(), txID) require.NoError(t, err) require.NotNil(t, resp) require.EqualValues(t, txID, resp.MustID()) @@ -541,9 +541,9 @@ func Test_CoreAPI(t *testing.T) { }, { name: "Test_TransactionsIncludedBlock", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { assetsPerSlot.forEachTransaction(t, func(t *testing.T, transaction *iotago.SignedTransaction, firstAttachmentID iotago.BlockID) { - resp, err := d.Client(nodeAlias).TransactionIncludedBlock(context.Background(), transaction.Transaction.MustID()) + resp, err := client.TransactionIncludedBlock(context.Background(), transaction.Transaction.MustID()) require.NoError(t, err) require.NotNil(t, resp) require.EqualValues(t, firstAttachmentID, resp.MustID()) @@ -552,9 +552,9 @@ func Test_CoreAPI(t *testing.T) { }, { name: "Test_TransactionsIncludedBlockMetadata", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { assetsPerSlot.forEachTransaction(t, func(t *testing.T, transaction *iotago.SignedTransaction, firstAttachmentID iotago.BlockID) { - resp, err := d.Client(nodeAlias).TransactionIncludedBlockMetadata(context.Background(), transaction.Transaction.MustID()) + resp, err := client.TransactionIncludedBlockMetadata(context.Background(), transaction.Transaction.MustID()) require.NoError(t, err) require.NotNil(t, resp) require.EqualValues(t, api.BlockStateFinalized, resp.BlockState) @@ -564,9 +564,9 @@ func Test_CoreAPI(t *testing.T) { }, { name: "Test_TransactionsMetadata", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { assetsPerSlot.forEachTransaction(t, func(t *testing.T, transaction *iotago.SignedTransaction, firstAttachmentID iotago.BlockID) { - resp, err := d.Client(nodeAlias).TransactionMetadata(context.Background(), transaction.Transaction.MustID()) + resp, err := client.TransactionMetadata(context.Background(), transaction.Transaction.MustID()) require.NoError(t, err) require.NotNil(t, resp) require.Equal(t, api.TransactionStateFinalized, resp.TransactionState) @@ -576,42 +576,42 @@ func Test_CoreAPI(t *testing.T) { }, { name: "Test_Congestion", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { assetsPerSlot.forEachAccountAddress(t, func( t *testing.T, accountAddress *iotago.AccountAddress, commitmentPerNode map[string]iotago.CommitmentID, bicPerNoode map[string]iotago.BlockIssuanceCredits, ) { - resp, err := d.Client(nodeAlias).Congestion(context.Background(), accountAddress, 0) + resp, err := client.Congestion(context.Background(), accountAddress, 0) require.NoError(t, err) require.NotNil(t, resp) // node allows to get account only for the slot newer than lastCommittedSlot - MCA, we need fresh commitment - infoRes, err := d.Client(nodeAlias).Info(context.Background()) + infoRes, err := client.Info(context.Background()) require.NoError(t, err) - commitment, err := d.Client(nodeAlias).CommitmentBySlot(context.Background(), infoRes.Status.LatestCommitmentID.Slot()) + commitment, err := client.CommitmentBySlot(context.Background(), infoRes.Status.LatestCommitmentID.Slot()) require.NoError(t, err) - resp, err = d.Client(nodeAlias).Congestion(context.Background(), accountAddress, 0, commitment.MustID()) + resp, err = client.Congestion(context.Background(), accountAddress, 0, commitment.MustID()) require.NoError(t, err) require.NotNil(t, resp) // later we check if all nodes have returned the same BIC value for this account - bicPerNoode[nodeAlias] = resp.BlockIssuanceCredits + bicPerNoode[node.Name] = resp.BlockIssuanceCredits }) }, }, { name: "Test_Validators", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { pageSize := uint64(3) - resp, err := d.Client(nodeAlias).Validators(context.Background(), pageSize) + resp, err := client.Validators(context.Background(), pageSize) require.NoError(t, err) require.NotNil(t, resp) //TODO after finishing validators endpoint and including registered validators //require.Equal(t, int(pageSize), len(resp.Validators), "There should be exactly %d validators returned on the first page", pageSize) - resp, err = d.Client(nodeAlias).Validators(context.Background(), pageSize, resp.Cursor) + resp, err = client.Validators(context.Background(), pageSize, resp.Cursor) require.NoError(t, err) require.NotNil(t, resp) //TODO after finishing validators endpoint and including registered validators @@ -620,8 +620,8 @@ func Test_CoreAPI(t *testing.T) { }, { name: "Test_ValidatorsAll", - testFunc: func(t *testing.T, nodeAlias string) { - resp, all, err := d.Client(nodeAlias).ValidatorsAll(context.Background()) + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { + resp, all, err := client.ValidatorsAll(context.Background()) require.NoError(t, err) require.True(t, all) require.Equal(t, 4, len(resp.Validators)) @@ -629,13 +629,13 @@ func Test_CoreAPI(t *testing.T) { }, { name: "Test_Rewards", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { assetsPerSlot.forEachOutput(t, func(t *testing.T, outputID iotago.OutputID, output iotago.Output) { if output.Type() != iotago.OutputDelegation { return } - resp, err := d.Client(nodeAlias).Rewards(context.Background(), outputID) + resp, err := client.Rewards(context.Background(), outputID) require.NoError(t, err) require.NotNil(t, resp) // rewards are zero, because we do not wait for the epoch end @@ -645,8 +645,8 @@ func Test_CoreAPI(t *testing.T) { }, { name: "Test_Committee", - testFunc: func(t *testing.T, nodeAlias string) { - resp, err := d.Client(nodeAlias).Committee(context.Background()) + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { + resp, err := client.Committee(context.Background()) require.NoError(t, err) require.NotNil(t, resp) require.EqualValues(t, 4, len(resp.Committee)) @@ -654,8 +654,8 @@ func Test_CoreAPI(t *testing.T) { }, { name: "Test_CommitteeWithEpoch", - testFunc: func(t *testing.T, nodeAlias string) { - resp, err := d.Client(nodeAlias).Committee(context.Background(), 0) + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { + resp, err := client.Committee(context.Background(), 0) require.NoError(t, err) require.Equal(t, iotago.EpochIndex(0), resp.Epoch) require.Equal(t, 4, len(resp.Committee)) @@ -665,7 +665,9 @@ func Test_CoreAPI(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - d.RequestFromNodes(test.testFunc) + for _, node := range d.Nodes() { + test.testFunc(d.Testing, node, d.Client(node.Name)) + } }) } @@ -697,13 +699,13 @@ func Test_CoreAPI_BadRequests(t *testing.T) { tests := []struct { name string - testFunc func(t *testing.T, nodeAlias string) + testFunc func(t *testing.T, node *dockertestframework.Node, client mock.Client) }{ { name: "Test_BlockByBlockID_Failure", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { blockID := tpkg.RandBlockID() - respBlock, err := d.Client(nodeAlias).BlockByBlockID(context.Background(), blockID) + respBlock, err := client.BlockByBlockID(context.Background(), blockID) require.Error(t, err) require.True(t, dockertestframework.IsStatusCode(err, http.StatusNotFound)) require.Nil(t, respBlock) @@ -711,9 +713,9 @@ func Test_CoreAPI_BadRequests(t *testing.T) { }, { name: "Test_BlockMetadataByBlockID_Failure", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { blockID := tpkg.RandBlockID() - resp, err := d.Client(nodeAlias).BlockMetadataByBlockID(context.Background(), blockID) + resp, err := client.BlockMetadataByBlockID(context.Background(), blockID) require.Error(t, err) require.True(t, dockertestframework.IsStatusCode(err, http.StatusNotFound)) require.Nil(t, resp) @@ -721,9 +723,9 @@ func Test_CoreAPI_BadRequests(t *testing.T) { }, { name: "Test_BlockWithMetadata_Failure", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { blockID := tpkg.RandBlockID() - resp, err := d.Client(nodeAlias).BlockWithMetadataByBlockID(context.Background(), blockID) + resp, err := client.BlockWithMetadataByBlockID(context.Background(), blockID) require.Error(t, err) require.True(t, dockertestframework.IsStatusCode(err, http.StatusNotFound)) require.Nil(t, resp) @@ -731,9 +733,9 @@ func Test_CoreAPI_BadRequests(t *testing.T) { }, { name: "Test_CommitmentBySlot_Failure", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { slot := iotago.SlotIndex(1000_000_000) - resp, err := d.Client(nodeAlias).CommitmentBySlot(context.Background(), slot) + resp, err := client.CommitmentBySlot(context.Background(), slot) require.Error(t, err) require.True(t, dockertestframework.IsStatusCode(err, http.StatusNotFound)) require.Nil(t, resp) @@ -741,9 +743,9 @@ func Test_CoreAPI_BadRequests(t *testing.T) { }, { name: "Test_CommitmentByID_Failure", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { committmentID := tpkg.RandCommitmentID() - resp, err := d.Client(nodeAlias).CommitmentByID(context.Background(), committmentID) + resp, err := client.CommitmentByID(context.Background(), committmentID) require.Error(t, err) require.True(t, dockertestframework.IsStatusCode(err, http.StatusNotFound)) require.Nil(t, resp) @@ -751,9 +753,9 @@ func Test_CoreAPI_BadRequests(t *testing.T) { }, { name: "Test_CommitmentUTXOChangesByID_Failure", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { committmentID := tpkg.RandCommitmentID() - resp, err := d.Client(nodeAlias).CommitmentUTXOChangesByID(context.Background(), committmentID) + resp, err := client.CommitmentUTXOChangesByID(context.Background(), committmentID) require.Error(t, err) // commitmentID is valid, but the UTXO changes does not exist in the storage require.True(t, dockertestframework.IsStatusCode(err, http.StatusNotFound)) @@ -762,10 +764,10 @@ func Test_CoreAPI_BadRequests(t *testing.T) { }, { "Test_CommitmentUTXOChangesFullByID_Failure", - func(t *testing.T, nodeAlias string) { + func(t *testing.T, node *dockertestframework.Node, client mock.Client) { committmentID := tpkg.RandCommitmentID() - resp, err := d.Client(nodeAlias).CommitmentUTXOChangesFullByID(context.Background(), committmentID) + resp, err := client.CommitmentUTXOChangesFullByID(context.Background(), committmentID) require.Error(t, err) // commitmentID is valid, but the UTXO changes does not exist in the storage require.True(t, dockertestframework.IsStatusCode(err, http.StatusNotFound)) @@ -774,9 +776,9 @@ func Test_CoreAPI_BadRequests(t *testing.T) { }, { name: "Test_CommitmentUTXOChangesBySlot_Failure", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { slot := iotago.SlotIndex(1000_000_000) - resp, err := d.Client(nodeAlias).CommitmentUTXOChangesBySlot(context.Background(), slot) + resp, err := client.CommitmentUTXOChangesBySlot(context.Background(), slot) require.Error(t, err) require.True(t, dockertestframework.IsStatusCode(err, http.StatusNotFound)) require.Nil(t, resp) @@ -784,10 +786,10 @@ func Test_CoreAPI_BadRequests(t *testing.T) { }, { name: "Test_CommitmentUTXOChangesFullBySlot_Failure", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { slot := iotago.SlotIndex(1000_000_000) - resp, err := d.Client(nodeAlias).CommitmentUTXOChangesFullBySlot(context.Background(), slot) + resp, err := client.CommitmentUTXOChangesFullBySlot(context.Background(), slot) require.Error(t, err) require.True(t, dockertestframework.IsStatusCode(err, http.StatusNotFound)) require.Nil(t, resp) @@ -795,9 +797,9 @@ func Test_CoreAPI_BadRequests(t *testing.T) { }, { name: "Test_OutputByID_Failure", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { outputID := tpkg.RandOutputID(0) - resp, err := d.Client(nodeAlias).OutputByID(context.Background(), outputID) + resp, err := client.OutputByID(context.Background(), outputID) require.Error(t, err) require.True(t, dockertestframework.IsStatusCode(err, http.StatusNotFound)) require.Nil(t, resp) @@ -805,10 +807,10 @@ func Test_CoreAPI_BadRequests(t *testing.T) { }, { name: "Test_OutputMetadata_Failure", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { outputID := tpkg.RandOutputID(0) - resp, err := d.Client(nodeAlias).OutputMetadataByID(context.Background(), outputID) + resp, err := client.OutputMetadataByID(context.Background(), outputID) require.Error(t, err) require.True(t, dockertestframework.IsStatusCode(err, http.StatusNotFound)) require.Nil(t, resp) @@ -816,10 +818,10 @@ func Test_CoreAPI_BadRequests(t *testing.T) { }, { name: "Test_OutputWithMetadata_Failure", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { outputID := tpkg.RandOutputID(0) - out, outMetadata, err := d.Client(nodeAlias).OutputWithMetadataByID(context.Background(), outputID) + out, outMetadata, err := client.OutputWithMetadataByID(context.Background(), outputID) require.Error(t, err) require.Nil(t, out) require.Nil(t, outMetadata) @@ -828,9 +830,9 @@ func Test_CoreAPI_BadRequests(t *testing.T) { }, { name: "Test_TransactionsIncludedBlock_Failure", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { txID := tpkg.RandTransactionID() - resp, err := d.Client(nodeAlias).TransactionIncludedBlock(context.Background(), txID) + resp, err := client.TransactionIncludedBlock(context.Background(), txID) require.Error(t, err) require.True(t, dockertestframework.IsStatusCode(err, http.StatusNotFound)) require.Nil(t, resp) @@ -838,10 +840,10 @@ func Test_CoreAPI_BadRequests(t *testing.T) { }, { name: "Test_TransactionsIncludedBlockMetadata_Failure", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { txID := tpkg.RandTransactionID() - resp, err := d.Client(nodeAlias).TransactionIncludedBlockMetadata(context.Background(), txID) + resp, err := client.TransactionIncludedBlockMetadata(context.Background(), txID) require.Error(t, err) require.True(t, dockertestframework.IsStatusCode(err, http.StatusNotFound)) require.Nil(t, resp) @@ -849,10 +851,10 @@ func Test_CoreAPI_BadRequests(t *testing.T) { }, { name: "Test_TransactionsMetadata_Failure", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { txID := tpkg.RandTransactionID() - resp, err := d.Client(nodeAlias).TransactionMetadata(context.Background(), txID) + resp, err := client.TransactionMetadata(context.Background(), txID) require.Error(t, err) require.True(t, dockertestframework.IsStatusCode(err, http.StatusNotFound)) require.Nil(t, resp) @@ -860,10 +862,10 @@ func Test_CoreAPI_BadRequests(t *testing.T) { }, { name: "Test_Congestion_Failure", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { accountAddress := tpkg.RandAccountAddress() commitmentID := tpkg.RandCommitmentID() - resp, err := d.Client(nodeAlias).Congestion(context.Background(), accountAddress, 0, commitmentID) + resp, err := client.Congestion(context.Background(), accountAddress, 0, commitmentID) require.Error(t, err) require.True(t, dockertestframework.IsStatusCode(err, http.StatusNotFound)) require.Nil(t, resp) @@ -871,8 +873,8 @@ func Test_CoreAPI_BadRequests(t *testing.T) { }, { name: "Test_Committee_Failure", - testFunc: func(t *testing.T, nodeAlias string) { - resp, err := d.Client(nodeAlias).Committee(context.Background(), 4) + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { + resp, err := client.Committee(context.Background(), 4) require.Error(t, err) require.True(t, dockertestframework.IsStatusCode(err, http.StatusBadRequest)) require.Nil(t, resp) @@ -880,9 +882,9 @@ func Test_CoreAPI_BadRequests(t *testing.T) { }, { name: "Test_Rewards_Failure", - testFunc: func(t *testing.T, nodeAlias string) { + testFunc: func(t *testing.T, node *dockertestframework.Node, client mock.Client) { outputID := tpkg.RandOutputID(0) - resp, err := d.Client(nodeAlias).Rewards(context.Background(), outputID) + resp, err := client.Rewards(context.Background(), outputID) require.Error(t, err) require.True(t, dockertestframework.IsStatusCode(err, http.StatusNotFound)) require.Nil(t, resp) @@ -892,7 +894,9 @@ func Test_CoreAPI_BadRequests(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - d.RequestFromNodes(test.testFunc) + for _, node := range d.Nodes() { + test.testFunc(d.Testing, node, d.Client(node.Name)) + } }) } } diff --git a/tools/docker-network/tests/dockertestframework/framework.go b/tools/docker-network/tests/dockertestframework/framework.go index 31332dfeb..674068fee 100644 --- a/tools/docker-network/tests/dockertestframework/framework.go +++ b/tools/docker-network/tests/dockertestframework/framework.go @@ -246,12 +246,10 @@ func (d *DockerTestFramework) DumpContainerLog(name string, optLogNameExtension func (d *DockerTestFramework) GetContainersConfigs() { // get container configs - nodes := d.Nodes() - d.nodesLock.Lock() defer d.nodesLock.Unlock() - for _, node := range nodes { + for _, node := range d.nodesWithoutLocking() { cmd := fmt.Sprintf("docker inspect --format='{{.Config.Cmd}}' %s", node.ContainerName) containerConfigsBytes, err := exec.Command("bash", "-c", cmd).Output() require.NoError(d.Testing, err) @@ -270,6 +268,7 @@ func (d *DockerTestFramework) GetContainersConfigs() { node.ContainerConfigs = configs node.PrivateKey = envs + d.nodes[node.Name] = node } } diff --git a/tools/docker-network/tests/dockertestframework/nodes.go b/tools/docker-network/tests/dockertestframework/nodes.go index 65471d7b2..5fdf41015 100644 --- a/tools/docker-network/tests/dockertestframework/nodes.go +++ b/tools/docker-network/tests/dockertestframework/nodes.go @@ -51,12 +51,10 @@ func (d *DockerTestFramework) NodeStatus(name string) *api.InfoResNodeStatus { } func (d *DockerTestFramework) waitForNodesAndGetClients() error { - nodes := d.Nodes() - d.nodesLock.Lock() defer d.nodesLock.Unlock() - for _, node := range nodes { + for _, node := range d.nodesWithoutLocking() { client, err := nodeclient.New(node.ClientURL) if err != nil { return ierrors.Wrapf(err, "failed to create node client for node %s", node.Name) @@ -147,10 +145,7 @@ func (d *DockerTestFramework) AddNode(name string, containerName string, clientU } } -func (d *DockerTestFramework) Nodes(names ...string) []*Node { - d.nodesLock.RLock() - defer d.nodesLock.RUnlock() - +func (d *DockerTestFramework) nodesWithoutLocking(names ...string) []*Node { if len(names) == 0 { nodes := make([]*Node, 0, len(d.nodes)) for _, node := range d.nodes { @@ -168,6 +163,13 @@ func (d *DockerTestFramework) Nodes(names ...string) []*Node { return nodes } +func (d *DockerTestFramework) Nodes(names ...string) []*Node { + d.nodesLock.RLock() + defer d.nodesLock.RUnlock() + + return d.nodesWithoutLocking(names...) +} + func (d *DockerTestFramework) Node(name string) *Node { d.nodesLock.RLock() defer d.nodesLock.RUnlock() @@ -201,9 +203,3 @@ func (d *DockerTestFramework) ResetNode(alias string, newSnapshotPath string) { d.DumpContainerLog(d.Node(alias).ContainerName, "reset1") d.WaitUntilNetworkHealthy() } - -func (d *DockerTestFramework) RequestFromNodes(testFunc func(*testing.T, string)) { - for nodeAlias := range d.nodes { - testFunc(d.Testing, nodeAlias) - } -} From 8000da0c7858b03f552f13d822197b06dcce648c Mon Sep 17 00:00:00 2001 From: muXxer Date: Wed, 8 May 2024 22:02:15 +0200 Subject: [PATCH 15/24] Solve TODOs in Test_Validators --- tools/docker-network/tests/api_core_test.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tools/docker-network/tests/api_core_test.go b/tools/docker-network/tests/api_core_test.go index 5f5dedeee..5ddbe18f8 100644 --- a/tools/docker-network/tests/api_core_test.go +++ b/tools/docker-network/tests/api_core_test.go @@ -608,14 +608,12 @@ func Test_CoreAPI(t *testing.T) { resp, err := client.Validators(context.Background(), pageSize) require.NoError(t, err) require.NotNil(t, resp) - //TODO after finishing validators endpoint and including registered validators - //require.Equal(t, int(pageSize), len(resp.Validators), "There should be exactly %d validators returned on the first page", pageSize) + require.Equal(t, int(pageSize), len(resp.Validators), "There should be exactly %d validators returned on the first page", pageSize) resp, err = client.Validators(context.Background(), pageSize, resp.Cursor) require.NoError(t, err) require.NotNil(t, resp) - //TODO after finishing validators endpoint and including registered validators - //require.Equal(t, 1, len(resp.Validators), "There should be only one validator returned on the last page") + require.Equal(t, 1, len(resp.Validators), "There should be only one validator returned on the last page") }, }, { From dff39800211272c6c60f736e874f3779e46eac00 Mon Sep 17 00:00:00 2001 From: muXxer Date: Wed, 8 May 2024 23:20:20 +0200 Subject: [PATCH 16/24] Print duration until nodes become online --- .../tests/dockertestframework/framework.go | 3 ++- .../docker-network/tests/dockertestframework/nodes.go | 10 ++++++++-- .../docker-network/tests/dockertestframework/utils.go | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/tools/docker-network/tests/dockertestframework/framework.go b/tools/docker-network/tests/dockertestframework/framework.go index 674068fee..abb474795 100644 --- a/tools/docker-network/tests/dockertestframework/framework.go +++ b/tools/docker-network/tests/dockertestframework/framework.go @@ -138,6 +138,7 @@ func (d *DockerTestFramework) Run() error { defer close(ch) defer close(stopCh) + ts := time.Now() go func() { err := d.DockerComposeUp() @@ -168,7 +169,7 @@ loop: } case <-ticker.C: fmt.Println("Waiting for nodes to become available...") - if d.waitForNodesAndGetClients() == nil { + if d.waitForNodesOnlineAndInitClients(ts) == nil { break loop } } diff --git a/tools/docker-network/tests/dockertestframework/nodes.go b/tools/docker-network/tests/dockertestframework/nodes.go index 5fdf41015..94c5f1366 100644 --- a/tools/docker-network/tests/dockertestframework/nodes.go +++ b/tools/docker-network/tests/dockertestframework/nodes.go @@ -50,16 +50,22 @@ func (d *DockerTestFramework) NodeStatus(name string) *api.InfoResNodeStatus { return info.Status } -func (d *DockerTestFramework) waitForNodesAndGetClients() error { +func (d *DockerTestFramework) waitForNodesOnlineAndInitClients(ts time.Time) error { d.nodesLock.Lock() defer d.nodesLock.Unlock() for _, node := range d.nodesWithoutLocking() { + // check if the node is online and initialize the client client, err := nodeclient.New(node.ClientURL) if err != nil { + delete(d.clients, node.Name) return ierrors.Wrapf(err, "failed to create node client for node %s", node.Name) } - d.nodes[node.Name] = node + + if _, exist := d.clients[node.Name]; !exist { + fmt.Println(fmt.Sprintf("Node %s became available after %v!", node.Name, time.Since(ts).Truncate(time.Millisecond))) + } + d.clients[node.Name] = client } diff --git a/tools/docker-network/tests/dockertestframework/utils.go b/tools/docker-network/tests/dockertestframework/utils.go index f96154048..5ab37792b 100644 --- a/tools/docker-network/tests/dockertestframework/utils.go +++ b/tools/docker-network/tests/dockertestframework/utils.go @@ -34,8 +34,8 @@ func (d *DockerTestFramework) EventuallyWithDurations(condition func() error, de tick = nil go func() { ch <- condition() }() case lastErr = <-ch: - // The condition is satisfied, we can exit. if lastErr == nil { + // The condition is satisfied, we can exit. return } tick = ticker.C From b3334fc3c92e5e537bbffd5d75c0e083ebc8814e Mon Sep 17 00:00:00 2001 From: muXxer Date: Thu, 9 May 2024 00:53:45 +0200 Subject: [PATCH 17/24] Fix docker container restarts --- tools/docker-network/docker-compose.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/docker-network/docker-compose.yml b/tools/docker-network/docker-compose.yml index 2864be3a3..205037762 100644 --- a/tools/docker-network/docker-compose.yml +++ b/tools/docker-network/docker-compose.yml @@ -202,7 +202,7 @@ services: prometheus: image: prom/prometheus:latest stop_grace_period: 1m - restart: no + restart: unless-stopped depends_on: node-1-validator: condition: service_started @@ -219,7 +219,7 @@ services: grafana: image: grafana/grafana:9.5.6 - restart: no + restart: unless-stopped networks: - iota-core ports: @@ -259,7 +259,7 @@ services: inx-mqtt: image: iotaledger/inx-mqtt:2.0-alpha stop_grace_period: 1m - restart: no + restart: unless-stopped depends_on: node-1-validator: condition: service_healthy @@ -370,7 +370,7 @@ services: inx-validator-4: image: iotaledger/inx-validator:1.0-alpha stop_grace_period: 1m - restart: unless-stopped + restart: no depends_on: node-4-validator: condition: service_started From eb2da31adb71736327557239f4b50b0a50ac2497 Mon Sep 17 00:00:00 2001 From: muXxer Date: Thu, 9 May 2024 00:54:37 +0200 Subject: [PATCH 18/24] Add `WaitUntilNodesHealthy` --- .../tests/dockertestframework/nodes.go | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/tools/docker-network/tests/dockertestframework/nodes.go b/tools/docker-network/tests/dockertestframework/nodes.go index 94c5f1366..7cac38dd8 100644 --- a/tools/docker-network/tests/dockertestframework/nodes.go +++ b/tools/docker-network/tests/dockertestframework/nodes.go @@ -89,9 +89,42 @@ func (d *DockerTestFramework) WaitUntilNetworkReady() { d.DumpContainerLogsToFiles() } +func (d *DockerTestFramework) WaitUntilNodesHealthy() { + fmt.Println("Wait until all the nodes are healthy...") + defer fmt.Println("Wait until all the nodes are healthy... done!") + + // remember a map of nodes that were synced so we don't print the same node multiple times + healthyNodes := make(map[string]struct{}) + + ts := time.Now() + + d.Eventually(func() error { + for _, node := range d.Nodes() { + info, err := d.Client(node.Name).Info(context.TODO()) + if err != nil { + delete(healthyNodes, node.Name) + return ierrors.Errorf("failed to get node %s's info: %w", node.Name, err) + } + + if !info.Status.IsHealthy { + delete(healthyNodes, node.Name) + return ierrors.Errorf("node %s's network is not healthy", node.Name) + } + + if _, exist := healthyNodes[node.Name]; !exist { + healthyNodes[node.Name] = struct{}{} + + fmt.Println(fmt.Sprintf("Node %s became healthy after %v!", node.Name, time.Since(ts).Truncate(time.Millisecond))) + } + } + + return nil + }, true) +} + func (d *DockerTestFramework) WaitUntilNetworkHealthy() { fmt.Println("Wait until the network is healthy...") - defer fmt.Println("Wait until the network is healthy......done") + defer fmt.Println("Wait until the network is healthy... done!") // remember a map of nodes that were synced so we don't print the same node multiple times syncedNodes := make(map[string]struct{}) From 8055580ec7c014a15bcc24246f1fc834ed61ac23 Mon Sep 17 00:00:00 2001 From: muXxer Date: Thu, 9 May 2024 01:36:41 +0200 Subject: [PATCH 19/24] Fix missing pass of expectedEpoch to committee API call --- tools/docker-network/tests/dockertestframework/asserts.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tools/docker-network/tests/dockertestframework/asserts.go b/tools/docker-network/tests/dockertestframework/asserts.go index 2022e9d44..16dc0f4e7 100644 --- a/tools/docker-network/tests/dockertestframework/asserts.go +++ b/tools/docker-network/tests/dockertestframework/asserts.go @@ -77,9 +77,6 @@ func (d *DockerTestFramework) AssertCommittee(expectedEpoch iotago.EpochIndex, e testAPI := d.defaultWallet.Client.CommittedAPI() expectedSlotStart := testAPI.TimeProvider().EpochStart(expectedEpoch) - // the expected slot needs to be at least now or in the future, otherwise we can't wait for it and get wrong results - require.GreaterOrEqual(d.Testing, expectedSlotStart, status.LatestAcceptedBlockSlot) - if status.LatestAcceptedBlockSlot < expectedSlotStart { slotToWait := expectedSlotStart - status.LatestAcceptedBlockSlot secToWait := time.Duration(slotToWait) * time.Duration(testAPI.ProtocolParameters().SlotDurationInSeconds()) * time.Second @@ -89,7 +86,7 @@ func (d *DockerTestFramework) AssertCommittee(expectedEpoch iotago.EpochIndex, e d.Eventually(func() error { for _, node := range d.Nodes() { - resp, err := d.Client(node.Name).Committee(context.TODO()) + resp, err := d.Client(node.Name).Committee(context.TODO(), expectedEpoch) if err != nil { return err } From bf4393c786ebacf5092bb7584a353cfe4a486438 Mon Sep 17 00:00:00 2001 From: jkrvivian Date: Thu, 9 May 2024 14:26:16 +0800 Subject: [PATCH 20/24] Fix waiting time in `issueCandidacyPayloadInBackground` --- tools/docker-network/tests/api_core_test.go | 2 +- .../tests/dockertestframework/validator.go | 4 +-- tools/docker-network/tests/rewards_test.go | 27 +++++++++++-------- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/tools/docker-network/tests/api_core_test.go b/tools/docker-network/tests/api_core_test.go index 5ddbe18f8..5c064ce61 100644 --- a/tools/docker-network/tests/api_core_test.go +++ b/tools/docker-network/tests/api_core_test.go @@ -311,7 +311,7 @@ func Test_ValidatorsAPI(t *testing.T) { // issue candidacy payload in the next epoch (currentEpoch + 1), in order to issue it before epochNearingThreshold d.AwaitCommitment(clt.CommittedAPI().TimeProvider().EpochEnd(currentEpoch)) - blkID := d.IssueCandidacyPayloadFromAccount(wallet) + blkID := d.IssueCandidacyPayloadFromAccount(ctx, wallet) fmt.Println("Candidacy payload:", blkID.ToHex(), blkID.Slot()) d.AwaitCommitment(blkID.Slot()) }() diff --git a/tools/docker-network/tests/dockertestframework/validator.go b/tools/docker-network/tests/dockertestframework/validator.go index 68c57335f..534c7e21e 100644 --- a/tools/docker-network/tests/dockertestframework/validator.go +++ b/tools/docker-network/tests/dockertestframework/validator.go @@ -37,8 +37,8 @@ func (d *DockerTestFramework) StopIssueCandidacyPayload(nodes ...*Node) { require.NoError(d.Testing, err) } -func (d *DockerTestFramework) IssueCandidacyPayloadFromAccount(wallet *mock.Wallet) iotago.BlockID { - block, err := wallet.CreateAndSubmitBasicBlock(context.TODO(), "candidacy_payload", mock.WithPayload(&iotago.CandidacyAnnouncement{})) +func (d *DockerTestFramework) IssueCandidacyPayloadFromAccount(ctx context.Context, wallet *mock.Wallet) iotago.BlockID { + block, err := wallet.CreateAndSubmitBasicBlock(ctx, "candidacy_payload", mock.WithPayload(&iotago.CandidacyAnnouncement{})) require.NoError(d.Testing, err) return block.ID() diff --git a/tools/docker-network/tests/rewards_test.go b/tools/docker-network/tests/rewards_test.go index 539e6e7c9..3a3022c25 100644 --- a/tools/docker-network/tests/rewards_test.go +++ b/tools/docker-network/tests/rewards_test.go @@ -73,8 +73,7 @@ func Test_ValidatorRewards(t *testing.T) { d, goodWallet, clt.CommittedAPI().TimeProvider().CurrentSlot(), - goodClaimingSlot, - slotsDuration) + goodClaimingSlot) // create lazy account lazyWallet, lazyAccountOutputData := d.CreateImplicitAccount(ctx) @@ -98,8 +97,7 @@ func Test_ValidatorRewards(t *testing.T) { d, lazyWallet, clt.CommittedAPI().TimeProvider().CurrentSlot(), - lazyClaimingSlot, - slotsDuration) + lazyClaimingSlot) // make sure the account is in the committee, so it can issue validation blocks goodAccountAddrBech32 := goodAccountData.Address.Bech32(clt.CommittedAPI().ProtocolParameters().Bech32HRP()) @@ -273,19 +271,26 @@ func Test_DelayedClaimingRewards(t *testing.T) { } } -func issueCandidacyPayloadInBackground(ctx context.Context, d *dockertestframework.DockerTestFramework, wallet *mock.Wallet, startSlot, endSlot iotago.SlotIndex, slotDuration uint8) { +func issueCandidacyPayloadInBackground(ctx context.Context, d *dockertestframework.DockerTestFramework, wallet *mock.Wallet, startSlot, endSlot iotago.SlotIndex) { go func() { fmt.Println("Issuing candidacy payloads for account", wallet.BlockIssuer.AccountData.ID, "in the background...") defer fmt.Println("Issuing candidacy payloads for account", wallet.BlockIssuer.AccountData.ID, "in the background......done") for i := startSlot; i < endSlot; i++ { - if ctx.Err() != nil { - // context is canceled - return + // wait until the slot is reached + for { + if ctx.Err() != nil { + // context is canceled + return + } + + if wallet.CurrentSlot() == i { + break + } + time.Sleep(2 * time.Second) } - d.IssueCandidacyPayloadFromAccount(wallet) - time.Sleep(time.Duration(slotDuration) * time.Second) + d.IssueCandidacyPayloadFromAccount(ctx, wallet) } }() } @@ -318,7 +323,7 @@ func issueValidationBlockInBackground(ctx context.Context, wg *sync.WaitGroup, w return } - wallet.CreateAndSubmitValidationBlock(context.Background(), "", nil) + wallet.CreateAndSubmitValidationBlock(ctx, "", nil) time.Sleep(1 * time.Second) } } From b5fbc47e88899edd4d593d881b0a986de19c2df5 Mon Sep 17 00:00:00 2001 From: jkrvivian Date: Thu, 9 May 2024 15:51:50 +0800 Subject: [PATCH 21/24] Set TargetCommitteeSize to 3 to test if the delegation worked as expected --- tools/docker-network/tests/sync_snapshot_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/docker-network/tests/sync_snapshot_test.go b/tools/docker-network/tests/sync_snapshot_test.go index e31119382..f800a426f 100644 --- a/tools/docker-network/tests/sync_snapshot_test.go +++ b/tools/docker-network/tests/sync_snapshot_test.go @@ -22,7 +22,7 @@ func Test_SyncFromSnapshot(t *testing.T) { iotago.WithLivenessOptions(10, 10, 2, 4, 5), iotago.WithCongestionControlOptions(1, 1, 1, 400_000, 250_000, 50_000_000, 1000, 100), iotago.WithRewardsOptions(8, 10, 2, 384), - iotago.WithTargetCommitteeSize(4), + iotago.WithTargetCommitteeSize(3), )) defer d.Stop() From 339e93df4d93c1f6c1797ed15dc54c3af53cde21 Mon Sep 17 00:00:00 2001 From: jkrvivian Date: Fri, 10 May 2024 16:01:48 +0800 Subject: [PATCH 22/24] Set issuing time after BlockIssuance api in CreateValidationBlock --- pkg/testsuite/mock/blockissuer.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkg/testsuite/mock/blockissuer.go b/pkg/testsuite/mock/blockissuer.go index d8e1498f0..81ef8267a 100644 --- a/pkg/testsuite/mock/blockissuer.go +++ b/pkg/testsuite/mock/blockissuer.go @@ -94,6 +94,9 @@ func (i *BlockIssuer) Address() iotago.Address { func (i *BlockIssuer) CreateValidationBlock(ctx context.Context, alias string, node *Node, opts ...options.Option[ValidationBlockParams]) (*blocks.Block, error) { blockParams := options.Apply(NewValidationBlockParams(), opts) + blockIssuanceInfo, err := i.Client.BlockIssuance(ctx) + require.NoError(i.Testing, err) + if blockParams.BlockHeader.IssuingTime == nil { issuingTime := time.Now().UTC() blockParams.BlockHeader.IssuingTime = &issuingTime @@ -101,8 +104,7 @@ func (i *BlockIssuer) CreateValidationBlock(ctx context.Context, alias string, n apiForBlock := i.retrieveAPI(blockParams.BlockHeader) protoParams := apiForBlock.ProtocolParameters() - blockIssuanceInfo, err := i.Client.BlockIssuance(ctx) - require.NoError(i.Testing, err) + if blockParams.BlockHeader.SlotCommitment == nil { commitment := blockIssuanceInfo.LatestCommitment blockSlot := apiForBlock.TimeProvider().SlotFromTime(*blockParams.BlockHeader.IssuingTime) @@ -133,7 +135,7 @@ func (i *BlockIssuer) CreateValidationBlock(ctx context.Context, alias string, n } if blockParams.BlockHeader.References == nil { - blockParams.BlockHeader.References = referencesFromBlockIssuanceResponse(i.latestBlockIssuanceResponse(ctx)) + blockParams.BlockHeader.References = referencesFromBlockIssuanceResponse(blockIssuanceInfo) } err = i.setDefaultBlockParams(ctx, blockParams.BlockHeader) From 43f22efa8dbf0738ecd2e278801e9f13be97908b Mon Sep 17 00:00:00 2001 From: jkrvivian Date: Fri, 10 May 2024 20:08:11 +0800 Subject: [PATCH 23/24] Make sure the block IssuingTime comes after LatestParentBlockIssuingTime --- pkg/testsuite/mock/blockissuer.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pkg/testsuite/mock/blockissuer.go b/pkg/testsuite/mock/blockissuer.go index 81ef8267a..835dd9339 100644 --- a/pkg/testsuite/mock/blockissuer.go +++ b/pkg/testsuite/mock/blockissuer.go @@ -99,6 +99,10 @@ func (i *BlockIssuer) CreateValidationBlock(ctx context.Context, alias string, n if blockParams.BlockHeader.IssuingTime == nil { issuingTime := time.Now().UTC() + if issuingTime.Before(blockIssuanceInfo.LatestParentBlockIssuingTime) { + issuingTime = blockIssuanceInfo.LatestParentBlockIssuingTime.Add(time.Nanosecond) + } + blockParams.BlockHeader.IssuingTime = &issuingTime } @@ -246,6 +250,10 @@ func (i *BlockIssuer) CreateBasicBlock(ctx context.Context, alias string, opts . // set the issuing time last to ensure the timestamp is greater than that of the parents selected. if blockParams.BlockHeader.IssuingTime == nil { issuingTime := time.Now().UTC() + if issuingTime.Before(blockIssuanceInfo.LatestParentBlockIssuingTime) { + issuingTime = blockIssuanceInfo.LatestParentBlockIssuingTime.Add(time.Nanosecond) + } + blockParams.BlockHeader.IssuingTime = &issuingTime } blockBuilder.IssuingTime(*blockParams.BlockHeader.IssuingTime) From 3f049a46c0f80127de9663a3bc3f9ce159904373 Mon Sep 17 00:00:00 2001 From: jkrvivian Date: Sat, 11 May 2024 14:58:44 +0800 Subject: [PATCH 24/24] Wait longer for autopeering in Test_ManagementAPI_Peers --- tools/docker-network/tests/api_management_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/docker-network/tests/api_management_test.go b/tools/docker-network/tests/api_management_test.go index 5b0533cdd..c10c36b95 100644 --- a/tools/docker-network/tests/api_management_test.go +++ b/tools/docker-network/tests/api_management_test.go @@ -50,6 +50,9 @@ func Test_ManagementAPI_Peers(t *testing.T) { d.WaitUntilNetworkReady() + // wait longer for autopeering + d.AwaitCommitment(d.DefaultWallet().CurrentSlot()) + // get the management client managementClient, err := d.Client("V1").Management(getContextWithTimeout(5 * time.Second)) require.NoError(t, err)