Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge e2e tests to sim tests #4759

Merged
merged 24 commits into from
Nov 16, 2022
Merged

Merge e2e tests to sim tests #4759

merged 24 commits into from
Nov 16, 2022

Conversation

nazarhussain
Copy link
Contributor

Motivation

To save time on CI jobs.

Description

Migrate e2e tests to sim-tests.

Partially Resolves: #4275

Steps to test or reproduce

Run sim tests.

@nazarhussain nazarhussain self-assigned this Nov 11, 2022
@github-actions
Copy link
Contributor

github-actions bot commented Nov 11, 2022

Performance Report

✔️ no performance regression detected

Full benchmark results
Benchmark suite Current: 3c876c1 Previous: 5cbcca0 Ratio
getPubkeys - index2pubkey - req 1000 vs - 250000 vc 2.4706 ms/op 2.5770 ms/op 0.96
getPubkeys - validatorsArr - req 1000 vs - 250000 vc 98.305 us/op 87.882 us/op 1.12
BLS verify - blst-native 1.8489 ms/op 2.1586 ms/op 0.86
BLS verifyMultipleSignatures 3 - blst-native 3.9102 ms/op 4.5189 ms/op 0.87
BLS verifyMultipleSignatures 8 - blst-native 8.6872 ms/op 9.5846 ms/op 0.91
BLS verifyMultipleSignatures 32 - blst-native 30.199 ms/op 34.861 ms/op 0.87
BLS aggregatePubkeys 32 - blst-native 40.543 us/op 45.552 us/op 0.89
BLS aggregatePubkeys 128 - blst-native 153.81 us/op 178.76 us/op 0.86
getAttestationsForBlock 94.680 ms/op 108.73 ms/op 0.87
isKnown best case - 1 super set check 420.00 ns/op 627.00 ns/op 0.67
isKnown normal case - 2 super set checks 438.00 ns/op 595.00 ns/op 0.74
isKnown worse case - 16 super set checks 416.00 ns/op 588.00 ns/op 0.71
CheckpointStateCache - add get delete 10.127 us/op 10.448 us/op 0.97
validate gossip signedAggregateAndProof - struct 4.4009 ms/op 4.9437 ms/op 0.89
validate gossip attestation - struct 2.0787 ms/op 2.3925 ms/op 0.87
pickEth1Vote - no votes 2.1583 ms/op 2.4408 ms/op 0.88
pickEth1Vote - max votes 23.810 ms/op 24.408 ms/op 0.98
pickEth1Vote - Eth1Data hashTreeRoot value x2048 12.322 ms/op 13.229 ms/op 0.93
pickEth1Vote - Eth1Data hashTreeRoot tree x2048 21.107 ms/op 24.471 ms/op 0.86
pickEth1Vote - Eth1Data fastSerialize value x2048 1.5825 ms/op 1.8856 ms/op 0.84
pickEth1Vote - Eth1Data fastSerialize tree x2048 14.001 ms/op 16.620 ms/op 0.84
bytes32 toHexString 1.1580 us/op 1.2570 us/op 0.92
bytes32 Buffer.toString(hex) 629.00 ns/op 835.00 ns/op 0.75
bytes32 Buffer.toString(hex) from Uint8Array 936.00 ns/op 1.0850 us/op 0.86
bytes32 Buffer.toString(hex) + 0x 641.00 ns/op 826.00 ns/op 0.78
Object access 1 prop 0.32900 ns/op 0.42900 ns/op 0.77
Map access 1 prop 0.27500 ns/op 0.34500 ns/op 0.80
Object get x1000 13.333 ns/op 20.718 ns/op 0.64
Map get x1000 0.87900 ns/op 1.1540 ns/op 0.76
Object set x1000 86.809 ns/op 141.11 ns/op 0.62
Map set x1000 62.145 ns/op 85.289 ns/op 0.73
Return object 10000 times 0.34290 ns/op 0.42500 ns/op 0.81
Throw Error 10000 times 5.6332 us/op 6.8486 us/op 0.82
fastMsgIdFn sha256 / 200 bytes 4.2350 us/op 4.9780 us/op 0.85
fastMsgIdFn h32 xxhash / 200 bytes 488.00 ns/op 653.00 ns/op 0.75
fastMsgIdFn h64 xxhash / 200 bytes 642.00 ns/op 878.00 ns/op 0.73
fastMsgIdFn sha256 / 1000 bytes 13.670 us/op 15.415 us/op 0.89
fastMsgIdFn h32 xxhash / 1000 bytes 674.00 ns/op 829.00 ns/op 0.81
fastMsgIdFn h64 xxhash / 1000 bytes 799.00 ns/op 865.00 ns/op 0.92
fastMsgIdFn sha256 / 10000 bytes 122.56 us/op 132.20 us/op 0.93
fastMsgIdFn h32 xxhash / 10000 bytes 2.4330 us/op 2.7370 us/op 0.89
fastMsgIdFn h64 xxhash / 10000 bytes 1.7990 us/op 1.9660 us/op 0.92
enrSubnets - fastDeserialize 64 bits 2.5350 us/op 3.1780 us/op 0.80
enrSubnets - ssz BitVector 64 bits 756.00 ns/op 851.00 ns/op 0.89
enrSubnets - fastDeserialize 4 bits 356.00 ns/op 429.00 ns/op 0.83
enrSubnets - ssz BitVector 4 bits 721.00 ns/op 848.00 ns/op 0.85
prioritizePeers score -10:0 att 32-0.1 sync 2-0 101.38 us/op 111.36 us/op 0.91
prioritizePeers score 0:0 att 32-0.25 sync 2-0.25 139.06 us/op 158.55 us/op 0.88
prioritizePeers score 0:0 att 32-0.5 sync 2-0.5 238.96 us/op 265.88 us/op 0.90
prioritizePeers score 0:0 att 64-0.75 sync 4-0.75 595.35 us/op 455.99 us/op 1.31
prioritizePeers score 0:0 att 64-1 sync 4-1 508.05 us/op 526.60 us/op 0.96
RateTracker 1000000 limit, 1 obj count per request 181.31 ns/op 221.50 ns/op 0.82
RateTracker 1000000 limit, 2 obj count per request 122.12 ns/op 168.22 ns/op 0.73
RateTracker 1000000 limit, 4 obj count per request 104.22 ns/op 135.86 ns/op 0.77
RateTracker 1000000 limit, 8 obj count per request 94.676 ns/op 121.71 ns/op 0.78
RateTracker with prune 4.2450 us/op 4.9660 us/op 0.85
array of 16000 items push then shift 4.4322 us/op 3.6718 us/op 1.21
LinkedList of 16000 items push then shift 17.595 ns/op 20.115 ns/op 0.87
array of 16000 items push then pop 238.18 ns/op 269.27 ns/op 0.88
LinkedList of 16000 items push then pop 16.662 ns/op 19.073 ns/op 0.87
array of 24000 items push then shift 6.6659 us/op 5.3050 us/op 1.26
LinkedList of 24000 items push then shift 19.632 ns/op 23.172 ns/op 0.85
array of 24000 items push then pop 221.25 ns/op 241.83 ns/op 0.91
LinkedList of 24000 items push then pop 15.555 ns/op 21.228 ns/op 0.73
intersect bitArray bitLen 8 10.027 ns/op 13.801 ns/op 0.73
intersect array and set length 8 164.43 ns/op 195.20 ns/op 0.84
intersect bitArray bitLen 128 60.556 ns/op 84.111 ns/op 0.72
intersect array and set length 128 1.9548 us/op 2.6380 us/op 0.74
Buffer.concat 32 items 2.0080 ns/op 2.2150 ns/op 0.91
pass gossip attestations to forkchoice per slot 3.6367 ms/op 4.7020 ms/op 0.77
computeDeltas 5.2286 ms/op 7.4588 ms/op 0.70
computeProposerBoostScoreFromBalances 794.25 us/op 1.0930 ms/op 0.73
altair processAttestation - 250000 vs - 7PWei normalcase 3.6716 ms/op 4.5722 ms/op 0.80
altair processAttestation - 250000 vs - 7PWei worstcase 6.3143 ms/op 7.3105 ms/op 0.86
altair processAttestation - setStatus - 1/6 committees join 209.66 us/op 245.11 us/op 0.86
altair processAttestation - setStatus - 1/3 committees join 412.04 us/op 467.73 us/op 0.88
altair processAttestation - setStatus - 1/2 committees join 570.68 us/op 697.93 us/op 0.82
altair processAttestation - setStatus - 2/3 committees join 827.38 us/op 885.33 us/op 0.93
altair processAttestation - setStatus - 4/5 committees join 1.1001 ms/op 1.1652 ms/op 0.94
altair processAttestation - setStatus - 100% committees join 1.3553 ms/op 1.3766 ms/op 0.98
altair processBlock - 250000 vs - 7PWei normalcase 28.530 ms/op 33.889 ms/op 0.84
altair processBlock - 250000 vs - 7PWei normalcase hashState 36.293 ms/op 49.343 ms/op 0.74
altair processBlock - 250000 vs - 7PWei worstcase 84.302 ms/op 92.159 ms/op 0.91
altair processBlock - 250000 vs - 7PWei worstcase hashState 101.96 ms/op 115.89 ms/op 0.88
phase0 processBlock - 250000 vs - 7PWei normalcase 3.5047 ms/op 4.3966 ms/op 0.80
phase0 processBlock - 250000 vs - 7PWei worstcase 44.513 ms/op 55.512 ms/op 0.80
altair processEth1Data - 250000 vs - 7PWei normalcase 847.87 us/op 1.0940 ms/op 0.78
Tree 40 250000 create 814.35 ms/op 942.78 ms/op 0.86
Tree 40 250000 get(125000) 275.80 ns/op 339.08 ns/op 0.81
Tree 40 250000 set(125000) 2.3764 us/op 3.1150 us/op 0.76
Tree 40 250000 toArray() 31.042 ms/op 37.668 ms/op 0.82
Tree 40 250000 iterate all - toArray() + loop 31.086 ms/op 37.754 ms/op 0.82
Tree 40 250000 iterate all - get(i) 107.40 ms/op 130.24 ms/op 0.82
MutableVector 250000 create 14.394 ms/op 21.499 ms/op 0.67
MutableVector 250000 get(125000) 11.598 ns/op 17.560 ns/op 0.66
MutableVector 250000 set(125000) 599.76 ns/op 742.21 ns/op 0.81
MutableVector 250000 toArray() 7.0280 ms/op 8.5894 ms/op 0.82
MutableVector 250000 iterate all - toArray() + loop 7.1753 ms/op 9.1733 ms/op 0.78
MutableVector 250000 iterate all - get(i) 3.0185 ms/op 4.0032 ms/op 0.75
Array 250000 create 6.4805 ms/op 7.7604 ms/op 0.84
Array 250000 clone - spread 4.0560 ms/op 4.3137 ms/op 0.94
Array 250000 get(125000) 1.6480 ns/op 1.8260 ns/op 0.90
Array 250000 set(125000) 1.4430 ns/op 1.7880 ns/op 0.81
Array 250000 iterate all - loop 127.86 us/op 200.81 us/op 0.64
effectiveBalanceIncrements clone Uint8Array 300000 117.20 us/op 107.70 us/op 1.09
effectiveBalanceIncrements clone MutableVector 300000 622.00 ns/op 1.3590 us/op 0.46
effectiveBalanceIncrements rw all Uint8Array 300000 250.57 us/op 300.57 us/op 0.83
effectiveBalanceIncrements rw all MutableVector 300000 156.69 ms/op 251.78 ms/op 0.62
phase0 afterProcessEpoch - 250000 vs - 7PWei 161.50 ms/op 219.80 ms/op 0.73
phase0 beforeProcessEpoch - 250000 vs - 7PWei 71.653 ms/op 105.22 ms/op 0.68
altair processEpoch - mainnet_e81889 612.46 ms/op 687.89 ms/op 0.89
mainnet_e81889 - altair beforeProcessEpoch 140.16 ms/op 180.85 ms/op 0.78
mainnet_e81889 - altair processJustificationAndFinalization 65.029 us/op 34.605 us/op 1.88
mainnet_e81889 - altair processInactivityUpdates 9.5646 ms/op 13.655 ms/op 0.70
mainnet_e81889 - altair processRewardsAndPenalties 90.823 ms/op 107.42 ms/op 0.85
mainnet_e81889 - altair processRegistryUpdates 15.644 us/op 7.3420 us/op 2.13
mainnet_e81889 - altair processSlashings 3.8810 us/op 1.8330 us/op 2.12
mainnet_e81889 - altair processEth1DataReset 4.0060 us/op 1.8200 us/op 2.20
mainnet_e81889 - altair processEffectiveBalanceUpdates 2.0289 ms/op 2.6744 ms/op 0.76
mainnet_e81889 - altair processSlashingsReset 23.021 us/op 11.609 us/op 1.98
mainnet_e81889 - altair processRandaoMixesReset 25.285 us/op 12.025 us/op 2.10
mainnet_e81889 - altair processHistoricalRootsUpdate 3.9570 us/op 1.8580 us/op 2.13
mainnet_e81889 - altair processParticipationFlagUpdates 15.485 us/op 7.4510 us/op 2.08
mainnet_e81889 - altair processSyncCommitteeUpdates 3.3920 us/op 1.8130 us/op 1.87
mainnet_e81889 - altair afterProcessEpoch 175.46 ms/op 228.73 ms/op 0.77
phase0 processEpoch - mainnet_e58758 528.26 ms/op 623.25 ms/op 0.85
mainnet_e58758 - phase0 beforeProcessEpoch 253.56 ms/op 272.94 ms/op 0.93
mainnet_e58758 - phase0 processJustificationAndFinalization 58.285 us/op 24.181 us/op 2.41
mainnet_e58758 - phase0 processRewardsAndPenalties 126.55 ms/op 158.49 ms/op 0.80
mainnet_e58758 - phase0 processRegistryUpdates 31.991 us/op 18.948 us/op 1.69
mainnet_e58758 - phase0 processSlashings 3.0900 us/op 1.6110 us/op 1.92
mainnet_e58758 - phase0 processEth1DataReset 3.6470 us/op 1.6100 us/op 2.27
mainnet_e58758 - phase0 processEffectiveBalanceUpdates 1.8493 ms/op 2.8670 ms/op 0.65
mainnet_e58758 - phase0 processSlashingsReset 15.535 us/op 9.0820 us/op 1.71
mainnet_e58758 - phase0 processRandaoMixesReset 25.750 us/op 12.619 us/op 2.04
mainnet_e58758 - phase0 processHistoricalRootsUpdate 4.3750 us/op 1.8880 us/op 2.32
mainnet_e58758 - phase0 processParticipationRecordUpdates 24.238 us/op 10.313 us/op 2.35
mainnet_e58758 - phase0 afterProcessEpoch 150.33 ms/op 185.28 ms/op 0.81
phase0 processEffectiveBalanceUpdates - 250000 normalcase 2.2416 ms/op 3.1058 ms/op 0.72
phase0 processEffectiveBalanceUpdates - 250000 worstcase 0.5 2.4178 ms/op 4.2060 ms/op 0.57
altair processInactivityUpdates - 250000 normalcase 52.764 ms/op 47.658 ms/op 1.11
altair processInactivityUpdates - 250000 worstcase 68.700 ms/op 56.995 ms/op 1.21
phase0 processRegistryUpdates - 250000 normalcase 27.642 us/op 15.738 us/op 1.76
phase0 processRegistryUpdates - 250000 badcase_full_deposits 558.28 us/op 590.07 us/op 0.95
phase0 processRegistryUpdates - 250000 worstcase 0.5 255.04 ms/op 263.49 ms/op 0.97
altair processRewardsAndPenalties - 250000 normalcase 148.28 ms/op 163.29 ms/op 0.91
altair processRewardsAndPenalties - 250000 worstcase 89.739 ms/op 101.12 ms/op 0.89
phase0 getAttestationDeltas - 250000 normalcase 13.456 ms/op 16.034 ms/op 0.84
phase0 getAttestationDeltas - 250000 worstcase 14.531 ms/op 16.951 ms/op 0.86
phase0 processSlashings - 250000 worstcase 6.3809 ms/op 6.3429 ms/op 1.01
altair processSyncCommitteeUpdates - 250000 316.48 ms/op 365.12 ms/op 0.87
BeaconState.hashTreeRoot - No change 602.00 ns/op 580.00 ns/op 1.04
BeaconState.hashTreeRoot - 1 full validator 76.613 us/op 73.958 us/op 1.04
BeaconState.hashTreeRoot - 32 full validator 802.26 us/op 755.39 us/op 1.06
BeaconState.hashTreeRoot - 512 full validator 9.1295 ms/op 7.5605 ms/op 1.21
BeaconState.hashTreeRoot - 1 validator.effectiveBalance 90.086 us/op 92.796 us/op 0.97
BeaconState.hashTreeRoot - 32 validator.effectiveBalance 1.3534 ms/op 1.4303 ms/op 0.95
BeaconState.hashTreeRoot - 512 validator.effectiveBalance 18.731 ms/op 19.121 ms/op 0.98
BeaconState.hashTreeRoot - 1 balances 72.166 us/op 71.093 us/op 1.02
BeaconState.hashTreeRoot - 32 balances 643.19 us/op 721.77 us/op 0.89
BeaconState.hashTreeRoot - 512 balances 6.3244 ms/op 7.2683 ms/op 0.87
BeaconState.hashTreeRoot - 250000 balances 113.76 ms/op 109.20 ms/op 1.04
aggregationBits - 2048 els - zipIndexesInBitList 33.060 us/op 34.926 us/op 0.95
regular array get 100000 times 56.046 us/op 80.479 us/op 0.70
wrappedArray get 100000 times 57.555 us/op 79.445 us/op 0.72
arrayWithProxy get 100000 times 36.344 ms/op 32.385 ms/op 1.12
ssz.Root.equals 572.00 ns/op 536.00 ns/op 1.07
byteArrayEquals 544.00 ns/op 522.00 ns/op 1.04
shuffle list - 16384 els 11.015 ms/op 13.001 ms/op 0.85
shuffle list - 250000 els 149.85 ms/op 189.17 ms/op 0.79
processSlot - 1 slots 15.630 us/op 14.290 us/op 1.09
processSlot - 32 slots 2.5286 ms/op 2.1349 ms/op 1.18
getEffectiveBalanceIncrementsZeroInactive - 250000 vs - 7PWei 907.56 us/op 495.28 us/op 1.83
getCommitteeAssignments - req 1 vs - 250000 vc 5.0435 ms/op 6.2324 ms/op 0.81
getCommitteeAssignments - req 100 vs - 250000 vc 8.2532 ms/op 8.5295 ms/op 0.97
getCommitteeAssignments - req 1000 vs - 250000 vc 8.4866 ms/op 9.1465 ms/op 0.93
RootCache.getBlockRootAtSlot - 250000 vs - 7PWei 9.7900 ns/op 11.420 ns/op 0.86
state getBlockRootAtSlot - 250000 vs - 7PWei 1.4669 us/op 1.2421 us/op 1.18
computeProposers - vc 250000 23.007 ms/op 19.912 ms/op 1.16
computeEpochShuffling - vc 250000 187.96 ms/op 200.05 ms/op 0.94
getNextSyncCommittee - vc 250000 342.33 ms/op 335.06 ms/op 1.02

by benchmarkbot/action

});
await unknownBlockSync.jobs.el.start();
await unknownBlockSync.jobs.cl.start();
const head = await env.nodes[0].cl.api.beacon.getBlock("head");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should also assert that this node syncs to the head, you can bundle with the other sync tests. Just do this setup before hand

@nazarhussain nazarhussain marked this pull request as ready for review November 14, 2022 22:44
@nazarhussain nazarhussain requested a review from a team as a code owner November 14, 2022 22:44
});
await unknownBlockSync.jobs.el.start();
await unknownBlockSync.jobs.cl.start();
const head = await env.nodes[0].cl.api.beacon.getBlockV2("head");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You must assert that unknownBlockSync syncs up to the block slot of head variable here.

});
}
}
await waitForNodeSync(unknownBlockSync.nodePair, env.options.controller.signal);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This condition is not enough. You are just checking that at some point sync status it not syncing. You must assert that the head of this node is exactly head. Since this is not normal usage I can't do any guarantees of what will the syncing status do. Please do not use syncing status in unknown root sync test. For the rest of usage of waitForNodeSync you must assert that the node declares itself as synced + syncs past a specific head too.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've reviewed the logs on the unknown block sync node completes syncing at

Eph 6/6 0.986[unknown-block-sync-node-cl-lodestar/chain] �[36mverbose�[39m: New chain head headSlot=51, headRoot=0x74e92383d9084442240ee46fd1aaaeb3fed1bfd504b3764c48c700bc9e92e122, delaySec=12.986000061035156
Eph 6/6 0.986[unknown-block-sync-node-cl-lodestar/chain] �[36mverbose�[39m: Block processed slot=51, root=0x74e92383d9084442240ee46fd1aaaeb3fed1bfd504b3764c48c700bc9e92e122, delaySec=12.986000061035156
Eph 6/6 1.258[unknown-block-sync-node-cl-lodestar/rest] �[34mdebug�[39m: Req req-g 127.0.0.1 getSyncingStatus
Eph 6/6 1.259[unknown-block-sync-node-cl-lodestar/rest] �[34mdebug�[39m: Res req-g getSyncingStatus - 200
Eph 6/6 2.001[unknown-block-sync-node-cl-lodestar] �[32minfo�[39m: Synced - slot: 54 (skipped 3) - head: 51 0x74e9…e122 - execution: valid(0xc9a2…a9bb) - 

The initial error is triggered at

Eph 6/4 0.208[unknown-block-sync-node-cl-lodestar/chain] �[31merror�[39m: Block error slot=51 code=BLOCK_ERROR_PARENT_UNKNOWN, parentRoot=0x62bfece4644b0c9901e8298eda2c926800991418308b09bb15c7b9e7326ef8f9

Which is the second to last block that's processed

Eph 6/6 0.971[unknown-block-sync-node-cl-lodestar/chain] �[36mverbose�[39m: New chain head headSlot=50, headRoot=0x62bfece4644b0c9901e8298eda2c926800991418308b09bb15c7b9e7326ef8f9, delaySec=16.97099995613098

Then the node stalls.

So yes, do not use syncing status here. The node returns not syncing just because it so happens to be close to the head, but that's a "coincidence".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did it as of the comment on the isSynced mentioned. In that controlled environment, don't think node can sync to any other head as we have assertions that heads on all nodes must be same.

Set to true if the node is syncing, false if the node is synced

Will extend the logic to track the head during the sync assertion.

Copy link
Contributor

@dapplion dapplion left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent! Great deduping

@dapplion dapplion merged commit bfe5da8 into unstable Nov 16, 2022
@dapplion dapplion deleted the nh/4275-e2e-to-sim branch November 16, 2022 09:36
@nazarhussain nazarhussain linked an issue Nov 16, 2022 that may be closed by this pull request
dapplion pushed a commit that referenced this pull request Nov 18, 2022
* Remove already covered tests

* Move some instance functions to pure functions to be reuseable

* Add uknonw block parent assertions

* Update the wait time

* Update block error message

* Disable range sync for the uknown block sync node

* Update the failing unit tests

* Use getBlockV2 instead of getBlock

* Fix linter warnings

* Remove unknownBlockSync test covered in sim tests

* Move few e2e tests to sim tests

* Update the sim run command

* Update docker runner

* Fix child process stopping issue

* Remove unnecessary e2e tests

* Fix unit tests for new beacon options

* Update a unit test

* Remove an accidental committed file

* Add sync check for the unkown sync node

* Add simulation repoter interface

* Update tracker event handling

* Update repoter

* Add logging for debugging

* Update logic for head checking
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Sim tests overhaul Consolidate sim and e2e tests for clarity and scale
2 participants