Skip to content
This repository was archived by the owner on Jan 24, 2025. It is now read-only.

Commit 2ad80b9

Browse files
authored
Merge pull request #681 from iotaledger/fix/docker-tests-candidate-race
Fix race condition when stopping publishing candidate payloads.
2 parents 0e08d0d + 96925a3 commit 2ad80b9

File tree

4 files changed

+70
-66
lines changed

4 files changed

+70
-66
lines changed

components/restapi/core/accounts.go

+1-3
Original file line numberDiff line numberDiff line change
@@ -269,11 +269,9 @@ func selectedCommittee(c echo.Context) (*api.CommitteeResponse, error) {
269269
// by default we return current epoch
270270
slot = timeProvider.SlotFromTime(time.Now())
271271
epoch = timeProvider.EpochFromSlot(slot)
272-
} else {
273-
slot = timeProvider.EpochEnd(epoch)
274272
}
275273

276-
seatedAccounts, exists := deps.Protocol.Engines.Main.Get().SybilProtection.SeatManager().CommitteeInSlot(slot)
274+
seatedAccounts, exists := deps.Protocol.Engines.Main.Get().SybilProtection.SeatManager().CommitteeInEpoch(epoch)
277275
if !exists {
278276
return &api.CommitteeResponse{
279277
Epoch: epoch,

tools/docker-network/docker-compose.yml

+4-1
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ services:
299299
--inx.address=node-1-validator:9029
300300
--validator.ignoreBootstrapped=true
301301
--validator.accountAddress=rms1pzg8cqhfxqhq7pt37y8cs4v5u4kcc48lquy2k73ehsdhf5ukhya3y5rx2w6
302+
--validator.issueCandidacyPayload=${ISSUE_CANDIDACY_PAYLOAD_V1:-true}
302303
303304
inx-validator-2:
304305
image: iotaledger/inx-validator:1.0-alpha
@@ -315,6 +316,7 @@ services:
315316
--logger.level=debug
316317
--inx.address=node-2-validator:9029
317318
--validator.accountAddress=rms1pqm4xk8e9ny5w5rxjkvtp249tfhlwvcshyr3pc0665jvp7g3hc875k538hl
319+
--validator.issueCandidacyPayload=${ISSUE_CANDIDACY_PAYLOAD_V2:-true}
318320
319321
inx-validator-3:
320322
image: iotaledger/inx-validator:1.0-alpha
@@ -331,6 +333,7 @@ services:
331333
--logger.level=debug
332334
--inx.address=node-3-validator:9029
333335
--validator.accountAddress=rms1pp4wuuz0y42caz48vv876qfpmffswsvg40zz8v79sy8cp0jfxm4kunflcgt
336+
--validator.issueCandidacyPayload=${ISSUE_CANDIDACY_PAYLOAD_V3:-true}
334337
335338
inx-validator-4:
336339
image: iotaledger/inx-validator:1.0-alpha
@@ -347,7 +350,7 @@ services:
347350
--logger.level=debug
348351
--inx.address=node-4-validator:9029
349352
--validator.accountAddress=rms1pr8cxs3dzu9xh4cduff4dd4cxdthpjkpwmz2244f75m0urslrsvtsshrrjw
350-
--logger.level=debug
353+
--validator.issueCandidacyPayload=${ISSUE_CANDIDACY_PAYLOAD_V4:-true}
351354
352355
# Create our own network
353356
networks:

tools/docker-network/tests/committeerotation_test.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,10 @@ func Test_NoCandidacyPayload(t *testing.T) {
146146
))
147147
defer d.Stop()
148148

149-
d.AddValidatorNode("V1", "docker-network-inx-validator-1-1", "http://localhost:8050", "rms1pzg8cqhfxqhq7pt37y8cs4v5u4kcc48lquy2k73ehsdhf5ukhya3y5rx2w6")
150-
d.AddValidatorNode("V2", "docker-network-inx-validator-2-1", "http://localhost:8060", "rms1pqm4xk8e9ny5w5rxjkvtp249tfhlwvcshyr3pc0665jvp7g3hc875k538hl")
151-
d.AddValidatorNode("V3", "docker-network-inx-validator-3-1", "http://localhost:8070", "rms1pp4wuuz0y42caz48vv876qfpmffswsvg40zz8v79sy8cp0jfxm4kunflcgt")
152-
d.AddValidatorNode("V4", "docker-network-inx-validator-4-1", "http://localhost:8040", "rms1pr8cxs3dzu9xh4cduff4dd4cxdthpjkpwmz2244f75m0urslrsvtsshrrjw")
149+
d.AddValidatorNode("V1", "docker-network-inx-validator-1-1", "http://localhost:8050", "rms1pzg8cqhfxqhq7pt37y8cs4v5u4kcc48lquy2k73ehsdhf5ukhya3y5rx2w6", false)
150+
d.AddValidatorNode("V2", "docker-network-inx-validator-2-1", "http://localhost:8060", "rms1pqm4xk8e9ny5w5rxjkvtp249tfhlwvcshyr3pc0665jvp7g3hc875k538hl", false)
151+
d.AddValidatorNode("V3", "docker-network-inx-validator-3-1", "http://localhost:8070", "rms1pp4wuuz0y42caz48vv876qfpmffswsvg40zz8v79sy8cp0jfxm4kunflcgt", false)
152+
d.AddValidatorNode("V4", "docker-network-inx-validator-4-1", "http://localhost:8040", "rms1pr8cxs3dzu9xh4cduff4dd4cxdthpjkpwmz2244f75m0urslrsvtsshrrjw", false)
153153
d.AddNode("node5", "docker-network-node-5-1", "http://localhost:8090")
154154

155155
err := d.Run()
@@ -164,7 +164,7 @@ func Test_NoCandidacyPayload(t *testing.T) {
164164
fmt.Println("First finalized slot: ", prevFinalizedSlot)
165165
currentEpoch := clt.CommittedAPI().TimeProvider().EpochFromSlot(status.LatestAcceptedBlockSlot)
166166

167-
d.StopIssueCandidacyPayload(d.Nodes()...)
167+
d.AssertCommittee(currentEpoch+1, d.AccountsFromNodes(d.Nodes()...))
168168

169169
// Due to no candidacy payloads, committee should be reused, remain 4 validators
170170
d.AssertCommittee(currentEpoch+2, d.AccountsFromNodes(d.Nodes()...))

tools/docker-network/tests/dockerframework.go

+60-57
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"crypto/ed25519"
88
"fmt"
99
"log"
10+
"os"
1011
"os/exec"
1112
"sort"
1213
"strings"
@@ -48,13 +49,14 @@ var (
4849
)
4950

5051
type Node struct {
51-
Name string
52-
ContainerName string
53-
ClientURL string
54-
Client *nodeclient.Client
55-
AccountAddressBech32 string
56-
ContainerConfigs string
57-
PrivateKey string
52+
Name string
53+
ContainerName string
54+
ClientURL string
55+
Client *nodeclient.Client
56+
AccountAddressBech32 string
57+
ContainerConfigs string
58+
PrivateKey string
59+
IssueCandidacyPayload bool
5860
}
5961

6062
type Account struct {
@@ -115,21 +117,36 @@ func NewDockerTestFramework(t *testing.T, opts ...options.Option[DockerTestFrame
115117
})
116118
}
117119

120+
func (d *DockerTestFramework) DockerComposeUp(detach ...bool) error {
121+
cmd := exec.Command("docker", "compose", "up")
122+
123+
if len(detach) > 0 && detach[0] {
124+
cmd = exec.Command("docker", "compose", "up", "-d")
125+
}
126+
127+
cmd.Env = os.Environ()
128+
for _, node := range d.nodes {
129+
cmd.Env = append(cmd.Env, fmt.Sprintf("ISSUE_CANDIDACY_PAYLOAD_%s=%t", node.Name, node.IssueCandidacyPayload))
130+
}
131+
132+
var out strings.Builder
133+
cmd.Stderr = &out
134+
err := cmd.Run()
135+
if err != nil {
136+
fmt.Println("Docker compose up failed with error:", err, ":", out.String())
137+
}
138+
139+
return err
140+
}
141+
118142
func (d *DockerTestFramework) Run() error {
119143
ch := make(chan error)
120144
stopCh := make(chan struct{})
121145
defer close(ch)
122146
defer close(stopCh)
123147

124148
go func() {
125-
cmd := exec.Command("docker", "compose", "up")
126-
var out strings.Builder
127-
cmd.Stderr = &out
128-
err := cmd.Run()
129-
130-
if err != nil {
131-
fmt.Println("Docker compose up failed with error:", err, ":", out.String())
132-
}
149+
err := d.DockerComposeUp()
133150

134151
// make sure that the channel is not already closed
135152
select {
@@ -211,12 +228,18 @@ func (d *DockerTestFramework) WaitUntilSync() error {
211228
return nil
212229
}
213230

214-
func (d *DockerTestFramework) AddValidatorNode(name string, containerName string, clientURL string, accAddrBech32 string) {
231+
func (d *DockerTestFramework) AddValidatorNode(name string, containerName string, clientURL string, accAddrBech32 string, optIssueCandidacyPayload ...bool) {
232+
issueCandidacyPayload := true
233+
if len(optIssueCandidacyPayload) > 0 {
234+
issueCandidacyPayload = optIssueCandidacyPayload[0]
235+
}
236+
215237
d.nodes[name] = &Node{
216-
Name: name,
217-
ContainerName: containerName,
218-
ClientURL: clientURL,
219-
AccountAddressBech32: accAddrBech32,
238+
Name: name,
239+
ContainerName: containerName,
240+
ClientURL: clientURL,
241+
AccountAddressBech32: accAddrBech32,
242+
IssueCandidacyPayload: issueCandidacyPayload,
220243
}
221244
}
222245

@@ -273,52 +296,32 @@ func (d *DockerTestFramework) AccountsFromNodes(nodes ...*Node) []string {
273296
return accounts
274297
}
275298

276-
func (d *DockerTestFramework) StopIssueCandidacyPayload(nodes ...*Node) {
277-
// build a new image from the current one so we could set IssueCandidacyPayload to false,
278-
// the committed image will not remember the container configs, so it's fine to commit the first validator of the nodes
279-
newImageName := "no-candidacy-payload-image"
280-
err := exec.Command("docker", "commit", nodes[0].ContainerName, newImageName).Run()
281-
require.NoError(d.Testing, err)
299+
func (d *DockerTestFramework) StartIssueCandidacyPayload(nodes ...*Node) {
300+
if len(nodes) == 0 {
301+
return
302+
}
282303

283304
for _, node := range nodes {
284-
if node.AccountAddressBech32 == "" {
285-
continue
286-
}
305+
node.IssueCandidacyPayload = true
306+
}
287307

288-
// stop the inx-validator that issues candidacy payload
289-
err = d.StopContainer(node.ContainerName)
290-
require.NoError(d.Testing, err)
308+
d.DockerComposeUp(true)
309+
}
291310

292-
// start a new inx-validator that does not issue candidacy payload
293-
newContainerName := fmt.Sprintf("%s-1", node.ContainerName)
294-
cmd := fmt.Sprintf("docker run --network docker-network_iota-core --env %s --name %s %s %s --validator.issueCandidacyPayload=false &", node.PrivateKey, newContainerName, newImageName, node.ContainerConfigs)
295-
err = exec.Command("bash", "-c", cmd).Run()
296-
require.NoError(d.Testing, err)
311+
func (d *DockerTestFramework) StopIssueCandidacyPayload(nodes ...*Node) {
312+
if len(nodes) == 0 {
313+
return
297314
}
298-
}
299315

300-
func (d *DockerTestFramework) StartIssueCandidacyPayload(nodes ...*Node) {
301316
for _, node := range nodes {
302-
if node.AccountAddressBech32 == "" {
303-
continue
304-
}
305-
306-
// stop and remove the inx-validator that does not issue candidacy payload
307-
newContainerName := fmt.Sprintf("%s-1", node.ContainerName)
308-
err := d.StopContainer(newContainerName)
309-
require.NoError(d.Testing, err)
310-
311-
err = exec.Command("docker", "rm", newContainerName).Run()
312-
require.NoError(d.Testing, err)
313-
314-
// start the inx-validator that issues candidacy payload
315-
err = d.RestartContainer(node.ContainerName)
316-
require.NoError(d.Testing, err)
317+
node.IssueCandidacyPayload = false
317318
}
319+
320+
d.DockerComposeUp(true)
318321
}
319322

320323
func (d *DockerTestFramework) CreateAccount(opts ...options.Option[builder.AccountOutputBuilder]) *Account {
321-
// create implicit account by requesting faucet funds
324+
// create an implicit account by requesting faucet funds
322325
ctx := context.TODO()
323326
receiverAddr, implicitPrivateKey := d.getAddress(iotago.AddressImplicitAccountCreation)
324327
implicitOutputID, implicitAccountOutput := d.RequestFaucetFunds(ctx, receiverAddr)
@@ -327,10 +330,10 @@ func (d *DockerTestFramework) CreateAccount(opts ...options.Option[builder.Accou
327330
accountAddress, ok := accountID.ToAddress().(*iotago.AccountAddress)
328331
require.True(d.Testing, ok)
329332

330-
// make sure implicit account is committed
333+
// make sure an implicit account is committed
331334
d.CheckAccountStatus(ctx, iotago.EmptyBlockID, implicitOutputID.TransactionID(), implicitOutputID, accountAddress)
332335

333-
// transition to full account with new Ed25519 address and staking feature
336+
// transition to a full account with new Ed25519 address and staking feature
334337
accEd25519Addr, accPrivateKey := d.getAddress(iotago.AddressEd25519)
335338
accBlockIssuerKey := iotago.Ed25519PublicKeyHashBlockIssuerKeyFromPublicKey(accPrivateKey.Public().(ed25519.PublicKey))
336339
accountOutput := options.Apply(builder.NewAccountOutputBuilder(accEd25519Addr, implicitAccountOutput.BaseTokenAmount()),

0 commit comments

Comments
 (0)