From f5d921bad2a730ca39b18eabb2db155892a1aa86 Mon Sep 17 00:00:00 2001 From: Daniel Liu <139250065@qq.com> Date: Mon, 19 Jan 2026 14:43:50 +0800 Subject: [PATCH] accounts/abi/bind: fix data race in TestWaitDeployedCornerCases #32740 #33041 (#1949) --- accounts/abi/bind/v2/util_test.go | 65 ++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 22 deletions(-) diff --git a/accounts/abi/bind/v2/util_test.go b/accounts/abi/bind/v2/util_test.go index 6ea30493e9..e268b4308a 100644 --- a/accounts/abi/bind/v2/util_test.go +++ b/accounts/abi/bind/v2/util_test.go @@ -106,27 +106,33 @@ func TestWaitDeployed(t *testing.T) { } func TestWaitDeployedCornerCases(t *testing.T) { - t.Parallel() config := *params.TestXDPoSMockChainConfig config.Eip1559Block = big.NewInt(0) - backend := backends.NewXDCSimulatedBackend( - types.GenesisAlloc{ - crypto.PubkeyToAddress(testKey.PublicKey): {Balance: big.NewInt(100000000000000000)}, - }, - 10000000, - &config, + var ( + backend = backends.NewXDCSimulatedBackend( + types.GenesisAlloc{ + crypto.PubkeyToAddress(testKey.PublicKey): {Balance: big.NewInt(100000000000000000)}, + }, + 10000000, + &config, + ) + head, _ = backend.HeaderByNumber(context.Background(), nil) // Should be child's, good enough + gasPrice = new(big.Int).Add(head.BaseFee, big.NewInt(1)) + signer = types.LatestSigner(&config) + code = common.FromHex("6060604052600a8060106000396000f360606040526008565b00") + ctx, cancel = context.WithCancel(t.Context()) ) defer backend.Close() - head, _ := backend.HeaderByNumber(context.Background(), nil) // Should be child's, good enough - gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1)) - - // Create a transaction to an account. - code := "6060604052600a8060106000396000f360606040526008565b00" - tx := types.NewTransaction(0, common.HexToAddress("0x01"), big.NewInt(0), 3000000, gasPrice, common.FromHex(code)) - tx, _ = types.SignTx(tx, types.HomesteadSigner{}, testKey) - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + // 1. WaitDeploy on a transaction that does not deploy a contract, verify it + // returns an error. + tx := types.MustSignNewTx(testKey, signer, &types.LegacyTx{ + Nonce: 0, + To: &common.Address{0x01}, + Gas: 300000, + GasPrice: gasPrice, + Data: code, + }) if err := backend.SendTransaction(ctx, tx); err != nil { t.Errorf("failed to send transaction: %q", err) } @@ -135,14 +141,22 @@ func TestWaitDeployedCornerCases(t *testing.T) { t.Errorf("error mismatch: want %q, got %q, ", bind.ErrNoAddressInReceipt, err) } - // Create a transaction that is not mined. - tx = types.NewContractCreation(1, big.NewInt(0), 3000000, gasPrice, common.FromHex(code)) - tx, _ = types.SignTx(tx, types.HomesteadSigner{}, testKey) + // 2. Create a contract, but cancel the WaitDeploy before it is mined. + tx = types.MustSignNewTx(testKey, signer, &types.LegacyTx{ + Nonce: 1, + Gas: 300000, + GasPrice: gasPrice, + Data: code, + }) + // Wait in another thread so that we can quickly cancel it after submitting + // the transaction. + done := make(chan struct{}) go func() { - contextCanceled := errors.New("context canceled") - if _, err := bind.WaitDeployed(ctx, backend, tx.Hash()); err.Error() != contextCanceled.Error() { - t.Errorf("error mismatch: want %q, got %q, ", contextCanceled, err) + defer close(done) + _, err := bind.WaitDeployed(ctx, backend, tx.Hash()) + if !errors.Is(err, context.Canceled) { + t.Errorf("error mismatch: want %v, got %v", context.Canceled, err) } }() @@ -150,4 +164,11 @@ func TestWaitDeployedCornerCases(t *testing.T) { t.Errorf("failed to send transaction: %q", err) } cancel() + + // Wait for goroutine to exit or for a timeout. + select { + case <-done: + case <-time.After(time.Second * 2): + t.Fatalf("failed to cancel wait deploy") + } }