From 63b6d2d01a2a4513dd6d8ace142a02e900435e16 Mon Sep 17 00:00:00 2001 From: Dimitry Kh Date: Wed, 17 Jul 2024 10:19:53 +0200 Subject: [PATCH 01/15] coverage on every pr --- .github/workflows/coverage.yaml | 140 +++++++++++++++++++++++++------- 1 file changed, 112 insertions(+), 28 deletions(-) diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml index 40f7b879d2..8bf3bccf72 100644 --- a/.github/workflows/coverage.yaml +++ b/.github/workflows/coverage.yaml @@ -3,7 +3,7 @@ name: Evmone Coverage Report on: pull_request: paths: - - "converted-ethereum-tests.txt" # This triggers the workflow only for changes in file.txt + - 'tests/**' # This triggers the workflow for any changes in the tests folder jobs: evmone-coverage-diff: @@ -43,12 +43,6 @@ jobs: uv run python --version # Required to fill .py tests - - name: Build GO EVM - uses: ./.github/actions/build-evm-client/geth - id: evm-builder - with: - type: "main" - - name: Build EVMONE EVM uses: ./.github/actions/build-evm-client/evmone id: evm-builder2 @@ -76,14 +70,16 @@ jobs: - name: Parse converted tests from converted-ethereum-tests.txt run: | echo "New lines introduced in converted-ethereum-tests.txt:" - lines=$(git diff origin/${{ github.base_ref }} HEAD -- converted-ethereum-tests.txt | grep "^+" | grep -v "^+++") - files=$(echo "$lines" | grep -oP '(?<=\+).+\.json') - - if [ -z "$files" ]; then - echo "Error: No new JSON files found in converted-ethereum-tests.txt" - exit 1 + lines=$(git diff origin/${{ github.base_ref }} HEAD -- converted-ethereum-tests.txt | grep "^+" | grep -v "^+++" || true) + if [ -z "$lines" ]; then + echo "No new lines in converted-ethereum-tests.txt, check updates instead:" + echo "converted_skip=true" >> $GITHUB_ENV + exit 0 + else + echo "converted_skip=false" >> $GITHUB_ENV fi + files=$(echo "$lines" | grep -oP '(?<=\+).+\.json') for file in $files; do echo $file done @@ -119,7 +115,7 @@ jobs: echo "Error: Failed to find the test file $file in test repo" exit 1 fi - done + done # This command diffs the .py scripts introduced by a PR - name: Parse and fill introduced test sources @@ -150,17 +146,36 @@ jobs: # fill new tests # using `|| true` here because if no tests found, pyspec fill returns error code + FOUND_TEST=false mkdir -p fixtures/state_tests mkdir -p fixtures/eof_tests - echo "$files" | while read line; do + + # Use a while loop with a here-string to avoid subshell issues + while IFS= read -r line; do file=$(echo "$line" | cut -c 3-) - uv run fill $file --until=Cancun --evm-bin evmone-t8n --solc-version=0.8.25 || true >> filloutput.log 2>&1 - (uv run fill $file --fork=CancunEIP7692 --evm-bin evmone-t8n --solc-version=0.8.25 -k eof_test || true) > >(tee -a filloutput.log filloutputEOF.log) 2>&1 - done + if grep -q "def test_" "$file"; then + FOUND_TEST=true + fill "$file" --until=Cancun --evm-bin evmone-t8n || true >> filloutput.log 2>&1 + (fill "$file" --fork=CancunEIP7692 --evm-bin evmone-t8n -k eof_test || true) > >(tee -a filloutput.log filloutputEOF.log) 2>&1 + fi + done <<< "$files" + + echo "Tests found: $FOUND_TEST" + if [[ "$FOUND_TEST" == "false" ]]; then + if [ "${{ env.converted_skip }}" == 'false' ]; then + echo "Error converted-ethereum-tests.txt has new lines, but no test in .py files were found" + exit 1 + fi + echo "No test detected in changed .py files, exiting the script" + echo "coverage_skip=true" >> $GITHUB_ENV + exit 0 + else + echo "coverage_skip=false" >> $GITHUB_ENV + fi if grep -q "FAILURES" filloutput.log; then - echo "Error: failed to generate .py tests." - exit 1 + echo "Error: failed to generate .py tests." + exit 1 fi if [ "${{ matrix.driver }}" = "retesteth" ] && grep -q "passed" filloutputEOF.log; then echo "Disabling retesteth coverage check as EOF tests detected!" @@ -183,8 +198,77 @@ jobs: find fixtures/state_tests -type f -name "*.json" -exec cp {} $PATCH_TEST_PATH \; find fixtures/eof_tests -type f -name "*.json" -exec cp {} $PATCH_TEST_PATH \; + - name: Parse and fill introduced test sources from before the PR + if: ${{ (env.retesteth_skip == 'false' || matrix.driver == 'native') && env.converted_skip == 'true' && env.coverage_skip == 'false'}} + run: | + echo "--------------------" + echo "converted-ethereum-tests.txt seem untouched, try to fill pre-patched version of .py files:" + + if [ "${{ github.event.pull_request.head.repo.full_name }}" != "${{ github.repository }}" ]; then + files=$(git diff --name-status origin/${{ github.base_ref }}...origin/PR-${{ github.event.pull_request.number }} -- tests/ | grep -E '^[AM]' | grep '\.py$') + else + files=$(git diff --name-status origin/${{ github.base_ref }}...origin/${{ github.head_ref }} -- tests/ | grep -E '^[AM]' | grep '\.py$') + fi + + echo "Modified or new .py files in tests folder:" + echo "$files" | while read line; do + file=$(echo "$line" | cut -c 3-) + echo $file + done + + git checkout main + PREV_COMMIT=$(git rev-parse HEAD) + echo "Checkout head $PREV_COMMIT" + + python3 -m venv ./venv/ + source ./venv/bin/activate + + rm -r fixtures + rm filloutput.log + rm filloutputEOF.log + mkdir -p fixtures/state_tests + mkdir -p fixtures/eof_tests + + FOUND_TEST=false + while IFS= read -r line; do + file=$(echo "$line" | cut -c 3-) + if grep -q "def test_" "$file"; then + FOUND_TEST=true + fill "$file" --until=Cancun --evm-bin evmone-t8n || true >> filloutput.log 2>&1 + (fill "$file" --fork=CancunEIP7692 --evm-bin evmone-t8n -k eof_test || true) > >(tee -a filloutput.log filloutputEOF.log) 2>&1 + fi + done <<< "$files" + + echo "Tests found: $FOUND_TEST" + if [[ "$FOUND_TEST" == "false" ]]; then + echo "No test detected in .py files from before the PR, exiting the script" + echo "coverage_skip=true" >> $GITHUB_ENV + exit 0 + fi + + if grep -q "FAILURES" filloutput.log; then + echo "Error: failed to generate .py tests from before the PR." + exit 1 + fi + + filesState=$(find fixtures/state_tests -type f -name "*.json") + filesEOF=$(find fixtures/eof_tests -type f -name "*.json") + if [ -z "$filesState" ] && [ -z "$filesEOF" ]; then + echo "Error: No filled JSON fixtures found in fixtures from before the PR." + exit 1 + fi + + BASE_TEST_PATH=${{ github.workspace }}/evmtest_coverage/coverage/BASE_TESTS + mkdir -p $BASE_TEST_PATH + find fixtures/state_tests -type f -name "*.json" -exec cp {} $BASE_TEST_PATH \; + find fixtures/eof_tests -type f -name "*.json" -exec cp {} $BASE_TEST_PATH \; + for file in $BASE_TEST_PATH/*.json; do + mv "$file" "${file%.json}_$PREV_COMMIT.json" + done + + - name: Print tests that will be covered - if: ${{ env.retesteth_skip == 'false' || matrix.driver == 'native' }} + if: ${{ (env.retesteth_skip == 'false' || matrix.driver == 'native') && env.coverage_skip == 'false' }} run: | echo "Original BASE tests:" ls ${{ github.workspace }}/evmtest_coverage/coverage/BASE_TESTS @@ -194,7 +278,7 @@ jobs: - name: Run coverage of the BASE tests uses: addnab/docker-run-action@v3 - if: ${{ env.retesteth_skip == 'false' || matrix.driver == 'native' }} + if: ${{ (env.retesteth_skip == 'false' || matrix.driver == 'native') && env.coverage_skip == 'false' }} with: image: winsvega/evmone-coverage-script:latest options: -v ${{ github.workspace }}/evmtest_coverage/coverage:/tests @@ -202,7 +286,7 @@ jobs: - name: Run coverage of the PATCH tests uses: addnab/docker-run-action@v3 - if: ${{ env.retesteth_skip == 'false' || matrix.driver == 'native' }} + if: ${{ (env.retesteth_skip == 'false' || matrix.driver == 'native') && env.coverage_skip == 'false' }} with: image: winsvega/evmone-coverage-script:latest options: -v ${{ github.workspace }}/evmtest_coverage/coverage:/tests @@ -210,28 +294,28 @@ jobs: - name: Run coverage DIFF of the PATCH tests compared to BASE tests uses: addnab/docker-run-action@v3 - if: ${{ env.retesteth_skip == 'false' || matrix.driver == 'native' }} + if: ${{ (env.retesteth_skip == 'false' || matrix.driver == 'native') && env.coverage_skip == 'false' }} with: image: winsvega/evmone-coverage-script:latest options: -v ${{ github.workspace }}/evmtest_coverage/coverage:/tests run: /entrypoint.sh --mode=diff --basefile=coverage_BASE.lcov --patchfile=coverage_PATCH.lcov - name: Chmod coverage results - if: ${{ env.retesteth_skip == 'false' || matrix.driver == 'native' }} + if: ${{ (env.retesteth_skip == 'false' || matrix.driver == 'native') && env.coverage_skip == 'false' }} run: | user=$(whoami) sudo chown -R $user:$user ${{ github.workspace }}/evmtest_coverage/coverage - name: Upload coverage results uses: actions/upload-artifact@v3 - if: ${{ env.retesteth_skip == 'false' || matrix.driver == 'native' }} + if: ${{ (env.retesteth_skip == 'false' || matrix.driver == 'native') && env.coverage_skip == 'false' }} with: - name: coverage-diff + name: coverage-diff-${{ matrix.driver }} path: ${{ github.workspace }}/evmtest_coverage/coverage - name: Verify coverage results uses: addnab/docker-run-action@v3 - if: ${{ env.retesteth_skip == 'false' || matrix.driver == 'native' }} + if: ${{ (env.retesteth_skip == 'false' || matrix.driver == 'native') && env.coverage_skip == 'false' }} with: image: winsvega/evmone-coverage-script:latest options: -v ${{ github.workspace }}/evmtest_coverage/coverage:/tests From 641a75db554d69f069f4ea093b3a75ec4ba0ab88 Mon Sep 17 00:00:00 2001 From: Dimitry Kh Date: Tue, 23 Jul 2024 11:59:30 +0200 Subject: [PATCH 02/15] do not try to detect tests in files do not skip the coverage script for safety --- .github/workflows/coverage.yaml | 59 ++++++++------------------------- 1 file changed, 13 insertions(+), 46 deletions(-) diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml index 8bf3bccf72..f91f71eb15 100644 --- a/.github/workflows/coverage.yaml +++ b/.github/workflows/coverage.yaml @@ -115,7 +115,7 @@ jobs: echo "Error: Failed to find the test file $file in test repo" exit 1 fi - done + done # This command diffs the .py scripts introduced by a PR - name: Parse and fill introduced test sources @@ -146,33 +146,16 @@ jobs: # fill new tests # using `|| true` here because if no tests found, pyspec fill returns error code - FOUND_TEST=false mkdir -p fixtures/state_tests mkdir -p fixtures/eof_tests # Use a while loop with a here-string to avoid subshell issues while IFS= read -r line; do file=$(echo "$line" | cut -c 3-) - if grep -q "def test_" "$file"; then - FOUND_TEST=true - fill "$file" --until=Cancun --evm-bin evmone-t8n || true >> filloutput.log 2>&1 - (fill "$file" --fork=CancunEIP7692 --evm-bin evmone-t8n -k eof_test || true) > >(tee -a filloutput.log filloutputEOF.log) 2>&1 - fi + fill "$file" --until=Cancun --evm-bin evmone-t8n || true >> filloutput.log 2>&1 + (fill "$file" --fork=CancunEIP7692 --evm-bin evmone-t8n -k eof_test || true) > >(tee -a filloutput.log filloutputEOF.log) 2>&1 done <<< "$files" - echo "Tests found: $FOUND_TEST" - if [[ "$FOUND_TEST" == "false" ]]; then - if [ "${{ env.converted_skip }}" == 'false' ]; then - echo "Error converted-ethereum-tests.txt has new lines, but no test in .py files were found" - exit 1 - fi - echo "No test detected in changed .py files, exiting the script" - echo "coverage_skip=true" >> $GITHUB_ENV - exit 0 - else - echo "coverage_skip=false" >> $GITHUB_ENV - fi - if grep -q "FAILURES" filloutput.log; then echo "Error: failed to generate .py tests." exit 1 @@ -185,13 +168,8 @@ jobs: echo "retesteth_skip=false" >> $GITHUB_ENV fi - filesState=$(find fixtures/state_tests -type f -name "*.json") filesEOF=$(find fixtures/eof_tests -type f -name "*.json") - if [ -z "$filesState" ] && [ -z "$filesEOF" ]; then - echo "Error: No filled JSON fixtures found in fixtures." - exit 1 - fi PATCH_TEST_PATH=${{ github.workspace }}/evmtest_coverage/coverage/PATCH_TESTS mkdir -p $PATCH_TEST_PATH @@ -199,7 +177,7 @@ jobs: find fixtures/eof_tests -type f -name "*.json" -exec cp {} $PATCH_TEST_PATH \; - name: Parse and fill introduced test sources from before the PR - if: ${{ (env.retesteth_skip == 'false' || matrix.driver == 'native') && env.converted_skip == 'true' && env.coverage_skip == 'false'}} + if: ${{ (env.retesteth_skip == 'false' || matrix.driver == 'native') && env.converted_skip == 'true' }} run: | echo "--------------------" echo "converted-ethereum-tests.txt seem untouched, try to fill pre-patched version of .py files:" @@ -229,23 +207,12 @@ jobs: mkdir -p fixtures/state_tests mkdir -p fixtures/eof_tests - FOUND_TEST=false while IFS= read -r line; do file=$(echo "$line" | cut -c 3-) - if grep -q "def test_" "$file"; then - FOUND_TEST=true - fill "$file" --until=Cancun --evm-bin evmone-t8n || true >> filloutput.log 2>&1 - (fill "$file" --fork=CancunEIP7692 --evm-bin evmone-t8n -k eof_test || true) > >(tee -a filloutput.log filloutputEOF.log) 2>&1 - fi + fill "$file" --until=Cancun --evm-bin evmone-t8n || true >> filloutput.log 2>&1 + (fill "$file" --fork=CancunEIP7692 --evm-bin evmone-t8n -k eof_test || true) > >(tee -a filloutput.log filloutputEOF.log) 2>&1 done <<< "$files" - echo "Tests found: $FOUND_TEST" - if [[ "$FOUND_TEST" == "false" ]]; then - echo "No test detected in .py files from before the PR, exiting the script" - echo "coverage_skip=true" >> $GITHUB_ENV - exit 0 - fi - if grep -q "FAILURES" filloutput.log; then echo "Error: failed to generate .py tests from before the PR." exit 1 @@ -268,7 +235,7 @@ jobs: - name: Print tests that will be covered - if: ${{ (env.retesteth_skip == 'false' || matrix.driver == 'native') && env.coverage_skip == 'false' }} + if: ${{ (env.retesteth_skip == 'false' || matrix.driver == 'native') }} run: | echo "Original BASE tests:" ls ${{ github.workspace }}/evmtest_coverage/coverage/BASE_TESTS @@ -278,7 +245,7 @@ jobs: - name: Run coverage of the BASE tests uses: addnab/docker-run-action@v3 - if: ${{ (env.retesteth_skip == 'false' || matrix.driver == 'native') && env.coverage_skip == 'false' }} + if: ${{ (env.retesteth_skip == 'false' || matrix.driver == 'native') }} with: image: winsvega/evmone-coverage-script:latest options: -v ${{ github.workspace }}/evmtest_coverage/coverage:/tests @@ -286,7 +253,7 @@ jobs: - name: Run coverage of the PATCH tests uses: addnab/docker-run-action@v3 - if: ${{ (env.retesteth_skip == 'false' || matrix.driver == 'native') && env.coverage_skip == 'false' }} + if: ${{ (env.retesteth_skip == 'false' || matrix.driver == 'native') }} with: image: winsvega/evmone-coverage-script:latest options: -v ${{ github.workspace }}/evmtest_coverage/coverage:/tests @@ -294,28 +261,28 @@ jobs: - name: Run coverage DIFF of the PATCH tests compared to BASE tests uses: addnab/docker-run-action@v3 - if: ${{ (env.retesteth_skip == 'false' || matrix.driver == 'native') && env.coverage_skip == 'false' }} + if: ${{ (env.retesteth_skip == 'false' || matrix.driver == 'native') }} with: image: winsvega/evmone-coverage-script:latest options: -v ${{ github.workspace }}/evmtest_coverage/coverage:/tests run: /entrypoint.sh --mode=diff --basefile=coverage_BASE.lcov --patchfile=coverage_PATCH.lcov - name: Chmod coverage results - if: ${{ (env.retesteth_skip == 'false' || matrix.driver == 'native') && env.coverage_skip == 'false' }} + if: ${{ (env.retesteth_skip == 'false' || matrix.driver == 'native') }} run: | user=$(whoami) sudo chown -R $user:$user ${{ github.workspace }}/evmtest_coverage/coverage - name: Upload coverage results uses: actions/upload-artifact@v3 - if: ${{ (env.retesteth_skip == 'false' || matrix.driver == 'native') && env.coverage_skip == 'false' }} + if: ${{ (env.retesteth_skip == 'false' || matrix.driver == 'native') }} with: name: coverage-diff-${{ matrix.driver }} path: ${{ github.workspace }}/evmtest_coverage/coverage - name: Verify coverage results uses: addnab/docker-run-action@v3 - if: ${{ (env.retesteth_skip == 'false' || matrix.driver == 'native') && env.coverage_skip == 'false' }} + if: ${{ (env.retesteth_skip == 'false' || matrix.driver == 'native') }} with: image: winsvega/evmone-coverage-script:latest options: -v ${{ github.workspace }}/evmtest_coverage/coverage:/tests From 4ce1af94d34206e62f63e29bfd54cda1fd80b6fc Mon Sep 17 00:00:00 2001 From: Dimitry Kh Date: Tue, 23 Jul 2024 13:54:54 +0200 Subject: [PATCH 03/15] build the changed files array once --- .github/workflows/coverage.yaml | 97 ++++++++++++++++++--------------- 1 file changed, 54 insertions(+), 43 deletions(-) diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml index f91f71eb15..c42aa19cc8 100644 --- a/.github/workflows/coverage.yaml +++ b/.github/workflows/coverage.yaml @@ -16,8 +16,38 @@ jobs: - name: Checkout code uses: actions/checkout@v3 - - name: Fetch target branch - run: git fetch origin ${{ github.base_ref }}:refs/remotes/origin/${{ github.base_ref }} + - name: Fetch github branches and detect introduces .py files + run: | + if [ "${{ github.event.pull_request.head.repo.full_name }}" != "${{ github.repository }}" ]; then + # Fetch changes when PR comes from remote repo + git fetch origin +refs/heads/${{ github.base_ref }}:refs/remotes/origin/${{ github.base_ref }} + git fetch origin +refs/pull/${{ github.event.pull_request.number }}/head:refs/remotes/origin/PR-${{ github.event.pull_request.number }} + files=$(git diff --name-status origin/${{ github.base_ref }}...origin/PR-${{ github.event.pull_request.number }} -- tests/ | grep -E '^[AM]' | grep '\.py$') + else + # Fetch the base branch and the head branch + git fetch origin ${{ github.base_ref }}:refs/remotes/origin/${{ github.base_ref }} + git fetch origin ${{ github.head_ref }}:refs/remotes/origin/${{ github.head_ref }} + files=$(git diff --name-status origin/${{ github.base_ref }}...origin/${{ github.head_ref }} -- tests/ | grep -E '^[AM]' | grep '\.py$') + fi + + # Eliminate git diff chars, select only .py paths + echo "Collect the changed .py files" + py_files=() + while read -r line; do + file_fixed=$(echo "$line" | cut -c 3-) + py_files+=("$file_fixed") + done <<< "$files" + + echo "Prepare the NEW_TESTS variable" + py_files_str=$(IFS=,; echo "${py_files[*]}") + echo "NEW_TESTS=$py_files_str" >> $GITHUB_ENV + + echo "Detected new/changed .py files:" + source $GITHUB_ENV + files2=$(echo "$NEW_TESTS" | tr ',' '\n') + while IFS= read -r file; do + echo $file + done <<< "$files2" - name: Log in to Docker Hub uses: docker/login-action@v3 @@ -120,38 +150,20 @@ jobs: # This command diffs the .py scripts introduced by a PR - name: Parse and fill introduced test sources run: | + source $GITHUB_ENV + files=$(echo "$NEW_TESTS" | tr ',' '\n') + python3 -m venv ./venv/ source ./venv/bin/activate - if [ "${{ github.event.pull_request.head.repo.full_name }}" != "${{ github.repository }}" ]; then - # Fetch changes when PR comes from remote repo - git fetch origin +refs/heads/${{ github.base_ref }}:refs/remotes/origin/${{ github.base_ref }} - git fetch origin +refs/pull/${{ github.event.pull_request.number }}/head:refs/remotes/origin/PR-${{ github.event.pull_request.number }} - files=$(git diff --name-status origin/${{ github.base_ref }}...origin/PR-${{ github.event.pull_request.number }} -- tests/ | grep -E '^[AM]' | grep '\.py$') - else - # Fetch the base branch and the head branch - git fetch origin ${{ github.base_ref }}:refs/remotes/origin/${{ github.base_ref }} - git fetch origin ${{ github.head_ref }}:refs/remotes/origin/${{ github.head_ref }} - - # Perform the diff - files=$(git diff --name-status origin/${{ github.base_ref }}...origin/${{ github.head_ref }} -- tests/ | grep -E '^[AM]' | grep '\.py$') - fi - - - echo "Modified or new .py files in tests folder:" - echo "$files" | while read line; do - file=$(echo "$line" | cut -c 3-) - echo $file - done - # fill new tests # using `|| true` here because if no tests found, pyspec fill returns error code mkdir -p fixtures/state_tests mkdir -p fixtures/eof_tests # Use a while loop with a here-string to avoid subshell issues - while IFS= read -r line; do - file=$(echo "$line" | cut -c 3-) + while IFS= read -r file; do + echo "Fill: $file" fill "$file" --until=Cancun --evm-bin evmone-t8n || true >> filloutput.log 2>&1 (fill "$file" --fork=CancunEIP7692 --evm-bin evmone-t8n -k eof_test || true) > >(tee -a filloutput.log filloutputEOF.log) 2>&1 done <<< "$files" @@ -170,6 +182,14 @@ jobs: filesState=$(find fixtures/state_tests -type f -name "*.json") filesEOF=$(find fixtures/eof_tests -type f -name "*.json") + if [ -z "$filesState" ] && [ -z "$filesEOF" ]; then + echo "Error: No filled JSON fixtures found in fixtures." + exit 1 + fi + + # Include basic evm operations into coverage by default + # As when we translate from yul/solidity some dup/push opcodes could become untouched + fill tests/homestead/coverage/test_coverage.py --until=Cancun --evm-bin evmone-t8n PATCH_TEST_PATH=${{ github.workspace }}/evmtest_coverage/coverage/PATCH_TESTS mkdir -p $PATCH_TEST_PATH @@ -182,17 +202,9 @@ jobs: echo "--------------------" echo "converted-ethereum-tests.txt seem untouched, try to fill pre-patched version of .py files:" - if [ "${{ github.event.pull_request.head.repo.full_name }}" != "${{ github.repository }}" ]; then - files=$(git diff --name-status origin/${{ github.base_ref }}...origin/PR-${{ github.event.pull_request.number }} -- tests/ | grep -E '^[AM]' | grep '\.py$') - else - files=$(git diff --name-status origin/${{ github.base_ref }}...origin/${{ github.head_ref }} -- tests/ | grep -E '^[AM]' | grep '\.py$') - fi - - echo "Modified or new .py files in tests folder:" - echo "$files" | while read line; do - file=$(echo "$line" | cut -c 3-) - echo $file - done + # load introduces .py files + source $GITHUB_ENV + files=$(echo "$NEW_TESTS" | tr ',' '\n') git checkout main PREV_COMMIT=$(git rev-parse HEAD) @@ -207,8 +219,9 @@ jobs: mkdir -p fixtures/state_tests mkdir -p fixtures/eof_tests - while IFS= read -r line; do - file=$(echo "$line" | cut -c 3-) + # Use a while loop with a here-string to avoid subshell issues + while IFS= read -r file; do + echo "Fill: $file" fill "$file" --until=Cancun --evm-bin evmone-t8n || true >> filloutput.log 2>&1 (fill "$file" --fork=CancunEIP7692 --evm-bin evmone-t8n -k eof_test || true) > >(tee -a filloutput.log filloutputEOF.log) 2>&1 done <<< "$files" @@ -220,17 +233,15 @@ jobs: filesState=$(find fixtures/state_tests -type f -name "*.json") filesEOF=$(find fixtures/eof_tests -type f -name "*.json") - if [ -z "$filesState" ] && [ -z "$filesEOF" ]; then - echo "Error: No filled JSON fixtures found in fixtures from before the PR." - exit 1 - fi BASE_TEST_PATH=${{ github.workspace }}/evmtest_coverage/coverage/BASE_TESTS mkdir -p $BASE_TEST_PATH find fixtures/state_tests -type f -name "*.json" -exec cp {} $BASE_TEST_PATH \; find fixtures/eof_tests -type f -name "*.json" -exec cp {} $BASE_TEST_PATH \; for file in $BASE_TEST_PATH/*.json; do - mv "$file" "${file%.json}_$PREV_COMMIT.json" + if [ -e "$file" ]; then + mv "$file" "${file%.json}_$PREV_COMMIT.json" + fi done From f602a73b12f1586a147d4bedc94f6cb633455c67 Mon Sep 17 00:00:00 2001 From: Dimitry Kh Date: Sat, 10 Aug 2024 10:06:58 +0200 Subject: [PATCH 04/15] simplify regex for gitdiff changed files detection --- .github/workflows/coverage.yaml | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml index c42aa19cc8..5a22685aa9 100644 --- a/.github/workflows/coverage.yaml +++ b/.github/workflows/coverage.yaml @@ -18,25 +18,30 @@ jobs: - name: Fetch github branches and detect introduces .py files run: | + py_files=() if [ "${{ github.event.pull_request.head.repo.full_name }}" != "${{ github.repository }}" ]; then # Fetch changes when PR comes from remote repo git fetch origin +refs/heads/${{ github.base_ref }}:refs/remotes/origin/${{ github.base_ref }} git fetch origin +refs/pull/${{ github.event.pull_request.number }}/head:refs/remotes/origin/PR-${{ github.event.pull_request.number }} - files=$(git diff --name-status origin/${{ github.base_ref }}...origin/PR-${{ github.event.pull_request.number }} -- tests/ | grep -E '^[AM]' | grep '\.py$') + gitdiff=$(git diff --name-status origin/${{ github.base_ref }}...origin/PR-${{ github.event.pull_request.number }} -- tests/) else # Fetch the base branch and the head branch git fetch origin ${{ github.base_ref }}:refs/remotes/origin/${{ github.base_ref }} git fetch origin ${{ github.head_ref }}:refs/remotes/origin/${{ github.head_ref }} - files=$(git diff --name-status origin/${{ github.base_ref }}...origin/${{ github.head_ref }} -- tests/ | grep -E '^[AM]' | grep '\.py$') + + gitdiff=$(git diff --name-status origin/${{ github.base_ref }}...origin/${{ github.head_ref }} -- tests/) fi - # Eliminate git diff chars, select only .py paths - echo "Collect the changed .py files" - py_files=() - while read -r line; do - file_fixed=$(echo "$line" | cut -c 3-) - py_files+=("$file_fixed") - done <<< "$files" + echo "git diff:" + echo "$gitdiff" + paths=$(echo "$gitdiff" | grep -oE '/[^[:space:]]+') + while IFS= read -r line; do + py_files+=("tests$line") + done <<< "$paths" + echo "Extracted file paths:" + for path in "${py_files[@]}"; do + echo "$path" + done echo "Prepare the NEW_TESTS variable" py_files_str=$(IFS=,; echo "${py_files[*]}") From dd3ecaa50600dc371aacc2e79910f923fbb532d2 Mon Sep 17 00:00:00 2001 From: Dimitry Kh Date: Fri, 6 Sep 2024 11:32:53 +0200 Subject: [PATCH 05/15] use uv run in coverage script --- .github/workflows/coverage.yaml | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml index 5a22685aa9..a702958735 100644 --- a/.github/workflows/coverage.yaml +++ b/.github/workflows/coverage.yaml @@ -158,9 +158,6 @@ jobs: source $GITHUB_ENV files=$(echo "$NEW_TESTS" | tr ',' '\n') - python3 -m venv ./venv/ - source ./venv/bin/activate - # fill new tests # using `|| true` here because if no tests found, pyspec fill returns error code mkdir -p fixtures/state_tests @@ -169,8 +166,8 @@ jobs: # Use a while loop with a here-string to avoid subshell issues while IFS= read -r file; do echo "Fill: $file" - fill "$file" --until=Cancun --evm-bin evmone-t8n || true >> filloutput.log 2>&1 - (fill "$file" --fork=CancunEIP7692 --evm-bin evmone-t8n -k eof_test || true) > >(tee -a filloutput.log filloutputEOF.log) 2>&1 + uv run fill "$file" --until=Cancun --evm-bin evmone-t8n || true >> filloutput.log 2>&1 + (uv run fill "$file" --fork=CancunEIP7692 --evm-bin evmone-t8n -k eof_test || true) > >(tee -a filloutput.log filloutputEOF.log) 2>&1 done <<< "$files" if grep -q "FAILURES" filloutput.log; then @@ -194,7 +191,7 @@ jobs: # Include basic evm operations into coverage by default # As when we translate from yul/solidity some dup/push opcodes could become untouched - fill tests/homestead/coverage/test_coverage.py --until=Cancun --evm-bin evmone-t8n + uv run fill tests/homestead/coverage/test_coverage.py --until=Cancun --evm-bin evmone-t8n PATCH_TEST_PATH=${{ github.workspace }}/evmtest_coverage/coverage/PATCH_TESTS mkdir -p $PATCH_TEST_PATH @@ -215,9 +212,6 @@ jobs: PREV_COMMIT=$(git rev-parse HEAD) echo "Checkout head $PREV_COMMIT" - python3 -m venv ./venv/ - source ./venv/bin/activate - rm -r fixtures rm filloutput.log rm filloutputEOF.log @@ -227,8 +221,8 @@ jobs: # Use a while loop with a here-string to avoid subshell issues while IFS= read -r file; do echo "Fill: $file" - fill "$file" --until=Cancun --evm-bin evmone-t8n || true >> filloutput.log 2>&1 - (fill "$file" --fork=CancunEIP7692 --evm-bin evmone-t8n -k eof_test || true) > >(tee -a filloutput.log filloutputEOF.log) 2>&1 + uv run fill "$file" --until=Cancun --evm-bin evmone-t8n || true >> filloutput.log 2>&1 + (uv run fill "$file" --fork=CancunEIP7692 --evm-bin evmone-t8n -k eof_test || true) > >(tee -a filloutput.log filloutputEOF.log) 2>&1 done <<< "$files" if grep -q "FAILURES" filloutput.log; then From bb54c969b8254eb2ef83ce2483c99097d71d3191 Mon Sep 17 00:00:00 2001 From: danceratopz Date: Thu, 26 Sep 2024 05:42:20 +0200 Subject: [PATCH 06/15] refactor(ci): use changed-files action to detect changes in tests/ --- .github/workflows/coverage.yaml | 110 +++++++++++++++++--------------- 1 file changed, 59 insertions(+), 51 deletions(-) diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml index a702958735..52dd8ae7d6 100644 --- a/.github/workflows/coverage.yaml +++ b/.github/workflows/coverage.yaml @@ -14,65 +14,66 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - - name: Fetch github branches and detect introduces .py files + - name: Debug GitHub context run: | - py_files=() - if [ "${{ github.event.pull_request.head.repo.full_name }}" != "${{ github.repository }}" ]; then - # Fetch changes when PR comes from remote repo - git fetch origin +refs/heads/${{ github.base_ref }}:refs/remotes/origin/${{ github.base_ref }} - git fetch origin +refs/pull/${{ github.event.pull_request.number }}/head:refs/remotes/origin/PR-${{ github.event.pull_request.number }} - gitdiff=$(git diff --name-status origin/${{ github.base_ref }}...origin/PR-${{ github.event.pull_request.number }} -- tests/) - else - # Fetch the base branch and the head branch - git fetch origin ${{ github.base_ref }}:refs/remotes/origin/${{ github.base_ref }} - git fetch origin ${{ github.head_ref }}:refs/remotes/origin/${{ github.head_ref }} - - gitdiff=$(git diff --name-status origin/${{ github.base_ref }}...origin/${{ github.head_ref }} -- tests/) - fi + echo "Git reference: ${{ github.ref }}" + echo "Git head ref: ${{ github.head_ref }}" + echo "Git base ref: ${{ github.base_ref }}" - echo "git diff:" - echo "$gitdiff" - paths=$(echo "$gitdiff" | grep -oE '/[^[:space:]]+') - while IFS= read -r line; do - py_files+=("tests$line") - done <<< "$paths" - echo "Extracted file paths:" - for path in "${py_files[@]}"; do - echo "$path" - done + - name: Get all changed python files in tests/ and changes to coverted-ethereum-tests.txt + id: changed-tests + uses: tj-actions/changed-files@v45 + with: + # TODO: non-test modules such as __init__.py or spec.py could effect coverage - in this case we should + # fill all applicable tests (i.e., all the test_*.py files in or under the changed module's directory) + files_yaml: | + tests: + - tests/**/test_*.py + converted_tests: + - converted-ethereum-tests.txt + + - name: Exit workflow if there are no changed python files + if: steps.changed-tests.outputs.tests_any_changed != 'true' + run: | + echo "No python files were changed in ./tests/ - no action necessary" + exit 0 - echo "Prepare the NEW_TESTS variable" - py_files_str=$(IFS=,; echo "${py_files[*]}") - echo "NEW_TESTS=$py_files_str" >> $GITHUB_ENV + - name: Report changed python test moudules + if: steps.changed-tests.outputs.tests_any_changed == 'true' + run: | + echo "Changed python test modules: ${{ steps.changed-tests.outputs.tests_all_changed_files }}" - echo "Detected new/changed .py files:" - source $GITHUB_ENV - files2=$(echo "$NEW_TESTS" | tr ',' '\n') - while IFS= read -r file; do - echo $file - done <<< "$files2" + - name: Debug GitHub context + run: | + echo "Git reference: ${{ github.ref }}" + echo "Git head ref: ${{ github.head_ref }}" + echo "Git base ref: ${{ github.base_ref }}" - name: Log in to Docker Hub + if: ${{ steps.changed-tests.outputs.tests_any_changed == 'true' && github.event.pull_request.head.repo.full_name == github.repository }} uses: docker/login-action@v3 - if: ${{ github.event.pull_request.head.repo.full_name == github.repository }} with: username: winsvega password: ${{ secrets.DOCKERHUB_PASSWORD }} - name: Install deps + if: steps.changed-tests.outputs.tests_any_changed == 'true' run: | echo $(pwd) echo ${{ github.workspace }} - name: Set up uv + if: steps.changed-tests.outputs.tests_any_changed == 'true' uses: ./.github/actions/setup-uv - name: Set up Python + if: steps.changed-tests.outputs.tests_any_changed == 'true' run: uv python install 3.10 - name: Install EEST + if: steps.changed-tests.outputs.tests_any_changed == 'true' run: | uv sync --no-progress uv run python --version @@ -80,12 +81,14 @@ jobs: # Required to fill .py tests - name: Build EVMONE EVM uses: ./.github/actions/build-evm-client/evmone + if: steps.changed-tests.outputs.tests_any_changed == 'true' id: evm-builder2 with: type: "main" - name: Checkout ethereum/tests uses: actions/checkout@v4 + if: steps.changed-tests.outputs.tests_any_changed == 'true' with: repository: ethereum/tests path: testpath @@ -95,6 +98,7 @@ jobs: - name: Checkout ethereum/legacytests uses: actions/checkout@v4 + if: steps.changed-tests.outputs.tests_any_changed == 'true' with: repository: ethereum/legacytests path: legacytestpath @@ -103,6 +107,7 @@ jobs: # This command diffs the file and filters in new lines - name: Parse converted tests from converted-ethereum-tests.txt + if: steps.changed-tests.outputs.tests_any_changed == 'true' run: | echo "New lines introduced in converted-ethereum-tests.txt:" lines=$(git diff origin/${{ github.base_ref }} HEAD -- converted-ethereum-tests.txt | grep "^+" | grep -v "^+++" || true) @@ -154,9 +159,12 @@ jobs: # This command diffs the .py scripts introduced by a PR - name: Parse and fill introduced test sources + if: steps.changed-tests.outputs.tests_any_changed == 'true' + env: + CHANGED_TEST_FILES: ${{ steps.changed-tests.outputs.tests_all_changed_files }} run: | source $GITHUB_ENV - files=$(echo "$NEW_TESTS" | tr ',' '\n') + files=$(echo "$CHANGED_TEST_FILES" | tr ',' '\n') # fill new tests # using `|| true` here because if no tests found, pyspec fill returns error code @@ -171,8 +179,8 @@ jobs: done <<< "$files" if grep -q "FAILURES" filloutput.log; then - echo "Error: failed to generate .py tests." - exit 1 + echo "Error: failed to generate .py tests." + exit 1 fi if [ "${{ matrix.driver }}" = "retesteth" ] && grep -q "passed" filloutputEOF.log; then echo "Disabling retesteth coverage check as EOF tests detected!" @@ -186,7 +194,7 @@ jobs: filesEOF=$(find fixtures/eof_tests -type f -name "*.json") if [ -z "$filesState" ] && [ -z "$filesEOF" ]; then echo "Error: No filled JSON fixtures found in fixtures." - exit 1 + exit 1 fi # Include basic evm operations into coverage by default @@ -199,7 +207,7 @@ jobs: find fixtures/eof_tests -type f -name "*.json" -exec cp {} $PATCH_TEST_PATH \; - name: Parse and fill introduced test sources from before the PR - if: ${{ (env.retesteth_skip == 'false' || matrix.driver == 'native') && env.converted_skip == 'true' }} + if: ${{ steps.changed-tests.outputs.tests_any_changed == 'true' && (env.retesteth_skip == 'false' || matrix.driver == 'native') && env.converted_skip == 'true' }} run: | echo "--------------------" echo "converted-ethereum-tests.txt seem untouched, try to fill pre-patched version of .py files:" @@ -220,13 +228,13 @@ jobs: # Use a while loop with a here-string to avoid subshell issues while IFS= read -r file; do - echo "Fill: $file" - uv run fill "$file" --until=Cancun --evm-bin evmone-t8n || true >> filloutput.log 2>&1 - (uv run fill "$file" --fork=CancunEIP7692 --evm-bin evmone-t8n -k eof_test || true) > >(tee -a filloutput.log filloutputEOF.log) 2>&1 + echo "Fill: $files" + uv run fill "$files" --until=Cancun --evm-bin evmone-t8n || true >> filloutput.log 2>&1 + (uv run fill "$files" --fork=CancunEIP7692 --evm-bin evmone-t8n -k eof_test || true) >> (tee -a filloutput.log filloutputEOF.log) 2>&1 done <<< "$files" if grep -q "FAILURES" filloutput.log; then - echo "Error: failed to generate .py tests from before the PR." + echo "Error: failed to generate .py tests from before the PR." exit 1 fi @@ -245,7 +253,7 @@ jobs: - name: Print tests that will be covered - if: ${{ (env.retesteth_skip == 'false' || matrix.driver == 'native') }} + if: ${{ steps.changed-tests.outputs.tests_any_changed == 'true' && (env.retesteth_skip == 'false' || matrix.driver == 'native') }} run: | echo "Original BASE tests:" ls ${{ github.workspace }}/evmtest_coverage/coverage/BASE_TESTS @@ -255,7 +263,7 @@ jobs: - name: Run coverage of the BASE tests uses: addnab/docker-run-action@v3 - if: ${{ (env.retesteth_skip == 'false' || matrix.driver == 'native') }} + if: ${{ steps.changed-tests.outputs.tests_any_changed == 'true' && (env.retesteth_skip == 'false' || matrix.driver == 'native') }} with: image: winsvega/evmone-coverage-script:latest options: -v ${{ github.workspace }}/evmtest_coverage/coverage:/tests @@ -263,7 +271,7 @@ jobs: - name: Run coverage of the PATCH tests uses: addnab/docker-run-action@v3 - if: ${{ (env.retesteth_skip == 'false' || matrix.driver == 'native') }} + if: ${{ steps.changed-tests.outputs.tests_any_changed == 'true' && (env.retesteth_skip == 'false' || matrix.driver == 'native') }} with: image: winsvega/evmone-coverage-script:latest options: -v ${{ github.workspace }}/evmtest_coverage/coverage:/tests @@ -271,28 +279,28 @@ jobs: - name: Run coverage DIFF of the PATCH tests compared to BASE tests uses: addnab/docker-run-action@v3 - if: ${{ (env.retesteth_skip == 'false' || matrix.driver == 'native') }} + if: ${{ steps.changed-tests.outputs.tests_any_changed == 'true' && (env.retesteth_skip == 'false' || matrix.driver == 'native') }} with: image: winsvega/evmone-coverage-script:latest options: -v ${{ github.workspace }}/evmtest_coverage/coverage:/tests run: /entrypoint.sh --mode=diff --basefile=coverage_BASE.lcov --patchfile=coverage_PATCH.lcov - name: Chmod coverage results - if: ${{ (env.retesteth_skip == 'false' || matrix.driver == 'native') }} + if: ${{ steps.changed-tests.outputs.tests_any_changed == 'true' && (env.retesteth_skip == 'false' || matrix.driver == 'native') }} run: | user=$(whoami) sudo chown -R $user:$user ${{ github.workspace }}/evmtest_coverage/coverage - name: Upload coverage results uses: actions/upload-artifact@v3 - if: ${{ (env.retesteth_skip == 'false' || matrix.driver == 'native') }} + if: ${{ steps.changed-tests.outputs.tests_any_changed == 'true' && (env.retesteth_skip == 'false' || matrix.driver == 'native') }} with: name: coverage-diff-${{ matrix.driver }} path: ${{ github.workspace }}/evmtest_coverage/coverage - name: Verify coverage results uses: addnab/docker-run-action@v3 - if: ${{ (env.retesteth_skip == 'false' || matrix.driver == 'native') }} + if: ${{ steps.changed-tests.outputs.tests_any_changed == 'true' && (env.retesteth_skip == 'false' || matrix.driver == 'native') }} with: image: winsvega/evmone-coverage-script:latest options: -v ${{ github.workspace }}/evmtest_coverage/coverage:/tests From 1773578e5a7867f45f63650f34ea659f38207b96 Mon Sep 17 00:00:00 2001 From: Dimitry Kh Date: Thu, 26 Sep 2024 10:31:50 +0200 Subject: [PATCH 07/15] remove retesteth driver, simplify the coverage script --- .github/workflows/coverage.yaml | 62 +++++++++++++-------------------- 1 file changed, 25 insertions(+), 37 deletions(-) diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml index 52dd8ae7d6..6564af81d0 100644 --- a/.github/workflows/coverage.yaml +++ b/.github/workflows/coverage.yaml @@ -7,10 +7,7 @@ on: jobs: evmone-coverage-diff: - runs-on: ubuntu-24.04 - strategy: - matrix: - driver: [retesteth, native] + runs-on: ubuntu-latest steps: - name: Checkout code @@ -159,7 +156,7 @@ jobs: # This command diffs the .py scripts introduced by a PR - name: Parse and fill introduced test sources - if: steps.changed-tests.outputs.tests_any_changed == 'true' + if: steps.changed-tests.outputs.tests_any_changed == 'true' env: CHANGED_TEST_FILES: ${{ steps.changed-tests.outputs.tests_all_changed_files }} run: | @@ -171,24 +168,13 @@ jobs: mkdir -p fixtures/state_tests mkdir -p fixtures/eof_tests - # Use a while loop with a here-string to avoid subshell issues - while IFS= read -r file; do - echo "Fill: $file" - uv run fill "$file" --until=Cancun --evm-bin evmone-t8n || true >> filloutput.log 2>&1 - (uv run fill "$file" --fork=CancunEIP7692 --evm-bin evmone-t8n -k eof_test || true) > >(tee -a filloutput.log filloutputEOF.log) 2>&1 - done <<< "$files" + uv run fill $files --until=Cancun --evm-bin evmone-t8n || true >> filloutput.log 2>&1 + (uv run fill $files --fork=PragueEIP7692 --evm-bin evmone-t8n || true) > >(tee -a filloutput.log filloutputEOF.log) 2>&1 if grep -q "FAILURES" filloutput.log; then echo "Error: failed to generate .py tests." exit 1 fi - if [ "${{ matrix.driver }}" = "retesteth" ] && grep -q "passed" filloutputEOF.log; then - echo "Disabling retesteth coverage check as EOF tests detected!" - echo "retesteth_skip=true" >> $GITHUB_ENV - exit 0 - else - echo "retesteth_skip=false" >> $GITHUB_ENV - fi filesState=$(find fixtures/state_tests -type f -name "*.json") filesEOF=$(find fixtures/eof_tests -type f -name "*.json") @@ -207,14 +193,15 @@ jobs: find fixtures/eof_tests -type f -name "*.json" -exec cp {} $PATCH_TEST_PATH \; - name: Parse and fill introduced test sources from before the PR - if: ${{ steps.changed-tests.outputs.tests_any_changed == 'true' && (env.retesteth_skip == 'false' || matrix.driver == 'native') && env.converted_skip == 'true' }} + if: ${{ steps.changed-tests.outputs.tests_any_changed == 'true' && env.converted_skip == 'true' }} + env: + CHANGED_TEST_FILES: ${{ steps.changed-tests.outputs.tests_all_changed_files }} run: | echo "--------------------" echo "converted-ethereum-tests.txt seem untouched, try to fill pre-patched version of .py files:" - # load introduces .py files source $GITHUB_ENV - files=$(echo "$NEW_TESTS" | tr ',' '\n') + files=$(echo "$CHANGED_TEST_FILES" | tr ',' '\n') git checkout main PREV_COMMIT=$(git rev-parse HEAD) @@ -226,18 +213,19 @@ jobs: mkdir -p fixtures/state_tests mkdir -p fixtures/eof_tests - # Use a while loop with a here-string to avoid subshell issues - while IFS= read -r file; do - echo "Fill: $files" - uv run fill "$files" --until=Cancun --evm-bin evmone-t8n || true >> filloutput.log 2>&1 - (uv run fill "$files" --fork=CancunEIP7692 --evm-bin evmone-t8n -k eof_test || true) >> (tee -a filloutput.log filloutputEOF.log) 2>&1 - done <<< "$files" + uv run fill $files --until=Cancun --evm-bin evmone-t8n || true >> filloutput.log 2>&1 + (uv run fill $files --fork=PragueEIP7692 --evm-bin evmone-t8n || true) > >(tee -a filloutput.log filloutputEOF.log) 2>&1 if grep -q "FAILURES" filloutput.log; then echo "Error: failed to generate .py tests from before the PR." exit 1 fi + if grep -q "ERROR collecting test session" filloutput.log; then + echo "Error: failed to generate .py tests from before the PR." + exit 1 + fi + filesState=$(find fixtures/state_tests -type f -name "*.json") filesEOF=$(find fixtures/eof_tests -type f -name "*.json") @@ -253,7 +241,7 @@ jobs: - name: Print tests that will be covered - if: ${{ steps.changed-tests.outputs.tests_any_changed == 'true' && (env.retesteth_skip == 'false' || matrix.driver == 'native') }} + if: ${{ steps.changed-tests.outputs.tests_any_changed == 'true' }} run: | echo "Original BASE tests:" ls ${{ github.workspace }}/evmtest_coverage/coverage/BASE_TESTS @@ -263,44 +251,44 @@ jobs: - name: Run coverage of the BASE tests uses: addnab/docker-run-action@v3 - if: ${{ steps.changed-tests.outputs.tests_any_changed == 'true' && (env.retesteth_skip == 'false' || matrix.driver == 'native') }} + if: ${{ steps.changed-tests.outputs.tests_any_changed == 'true' }} with: image: winsvega/evmone-coverage-script:latest options: -v ${{ github.workspace }}/evmtest_coverage/coverage:/tests - run: /entrypoint.sh --mode=cover --driver=${{ matrix.driver }} --testpath=/tests/BASE_TESTS --outputname=BASE + run: /entrypoint.sh --mode=cover --driver=native --testpath=/tests/BASE_TESTS --outputname=BASE - name: Run coverage of the PATCH tests uses: addnab/docker-run-action@v3 - if: ${{ steps.changed-tests.outputs.tests_any_changed == 'true' && (env.retesteth_skip == 'false' || matrix.driver == 'native') }} + if: ${{ steps.changed-tests.outputs.tests_any_changed == 'true' }} with: image: winsvega/evmone-coverage-script:latest options: -v ${{ github.workspace }}/evmtest_coverage/coverage:/tests - run: /entrypoint.sh --mode=cover --driver=${{ matrix.driver }} --testpath=/tests/PATCH_TESTS --outputname=PATCH + run: /entrypoint.sh --mode=cover --driver=native --testpath=/tests/PATCH_TESTS --outputname=PATCH - name: Run coverage DIFF of the PATCH tests compared to BASE tests uses: addnab/docker-run-action@v3 - if: ${{ steps.changed-tests.outputs.tests_any_changed == 'true' && (env.retesteth_skip == 'false' || matrix.driver == 'native') }} + if: ${{ steps.changed-tests.outputs.tests_any_changed == 'true' }} with: image: winsvega/evmone-coverage-script:latest options: -v ${{ github.workspace }}/evmtest_coverage/coverage:/tests run: /entrypoint.sh --mode=diff --basefile=coverage_BASE.lcov --patchfile=coverage_PATCH.lcov - name: Chmod coverage results - if: ${{ steps.changed-tests.outputs.tests_any_changed == 'true' && (env.retesteth_skip == 'false' || matrix.driver == 'native') }} + if: ${{ steps.changed-tests.outputs.tests_any_changed == 'true' }} run: | user=$(whoami) sudo chown -R $user:$user ${{ github.workspace }}/evmtest_coverage/coverage - name: Upload coverage results uses: actions/upload-artifact@v3 - if: ${{ steps.changed-tests.outputs.tests_any_changed == 'true' && (env.retesteth_skip == 'false' || matrix.driver == 'native') }} + if: ${{ steps.changed-tests.outputs.tests_any_changed == 'true' }} with: - name: coverage-diff-${{ matrix.driver }} + name: coverage-diff-native path: ${{ github.workspace }}/evmtest_coverage/coverage - name: Verify coverage results uses: addnab/docker-run-action@v3 - if: ${{ steps.changed-tests.outputs.tests_any_changed == 'true' && (env.retesteth_skip == 'false' || matrix.driver == 'native') }} + if: ${{ steps.changed-tests.outputs.tests_any_changed == 'true' }} with: image: winsvega/evmone-coverage-script:latest options: -v ${{ github.workspace }}/evmtest_coverage/coverage:/tests From 648341ad547201860418d2d85647a4de7b06194d Mon Sep 17 00:00:00 2001 From: Dimitry Kh Date: Mon, 30 Sep 2024 10:18:54 +0200 Subject: [PATCH 08/15] new test introduced, scipt is green --- .../eip1153_tstore/test_basic_tload2.py | 284 ++++++++++++++++++ 1 file changed, 284 insertions(+) create mode 100644 tests/cancun/eip1153_tstore/test_basic_tload2.py diff --git a/tests/cancun/eip1153_tstore/test_basic_tload2.py b/tests/cancun/eip1153_tstore/test_basic_tload2.py new file mode 100644 index 0000000000..4c80ece2c6 --- /dev/null +++ b/tests/cancun/eip1153_tstore/test_basic_tload2.py @@ -0,0 +1,284 @@ +""" +Ethereum Transient Storage EIP Tests +https://eips.ethereum.org/EIPS/eip-1153 +""" + +from typing import Dict, Union + +import pytest + +from ethereum_test_tools import Account, Address, Alloc, Environment, StateTestFiller, Transaction +from ethereum_test_tools.vm.opcode import Opcodes as Op + +from .spec import Spec, ref_spec_1153 + +REFERENCE_SPEC_GIT_PATH = ref_spec_1153.git_path +REFERENCE_SPEC_VERSION = ref_spec_1153.version + + +@pytest.mark.valid_from("Cancun") +def test_basic_tload_transaction_begin2( + state_test: StateTestFiller, + pre: Alloc, +): + """ + Ported .json vectors: + + (01_tloadBeginningTxnFiller.yml) + load arbitrary value is 0 at beginning of transaction + """ + slot_tload_at_transaction_begin_result = 1 + slot_code_worked = 2 + + address_to = pre.deploy_contract( + code=Op.JUMPDEST() + # 01 test + + Op.SSTORE(slot_tload_at_transaction_begin_result, Op.TLOAD(0)) + + Op.SSTORE(slot_code_worked, 1), + storage={ + slot_tload_at_transaction_begin_result: 0xFF, + }, + ) + + post = { + address_to: Account( + storage={ + slot_tload_at_transaction_begin_result: 0x00, + slot_code_worked: 0x01, + } + ) + } + + tx = Transaction( + sender=pre.fund_eoa(7_000_000_000_000_000_000), + to=address_to, + gas_price=10, + data=b"", + gas_limit=5000000, + value=0, + ) + + state_test(env=Environment(), pre=pre, post=post, tx=tx) + + +@pytest.mark.valid_from("Cancun") +def test_basic_tload_works2( + state_test: StateTestFiller, + pre: Alloc, +): + """ + Ported .json vectors: + + (02_tloadAfterTstoreFiller.yml) + tload from same slot after tstore returns correct value + """ + tstore_value = 88 + + slot_tload_after_tstore_result = 0 + slot_tload_after_tstore_result_second_time = 1 + slot_code_worked = 2 + + address_to = pre.deploy_contract( + code=Op.JUMPDEST() + # 02 test + + Op.TSTORE(2, tstore_value) + + Op.SSTORE(slot_tload_after_tstore_result, Op.TLOAD(2)) + + Op.SSTORE(slot_tload_after_tstore_result_second_time, Op.TLOAD(2)) + + Op.SSTORE(slot_code_worked, 1), + storage={ + slot_tload_after_tstore_result: 0xFF, + slot_tload_after_tstore_result_second_time: 0xFF, + }, + ) + + post = { + address_to: Account( + storage={ + slot_tload_after_tstore_result: tstore_value, + slot_tload_after_tstore_result_second_time: tstore_value, + slot_code_worked: 0x01, + } + ) + } + + tx = Transaction( + sender=pre.fund_eoa(7_000_000_000_000_000_000), + to=address_to, + gas_price=10, + data=b"", + gas_limit=5000000, + value=0, + ) + + state_test(env=Environment(), pre=pre, post=post, tx=tx) + + +@pytest.mark.valid_from("Cancun") +def test_basic_tload_other_after_tstore2( + state_test: StateTestFiller, + pre: Alloc, +): + """ + Ported .json vectors: + + (03_tloadAfterStoreIs0Filler.yml) + Loading any other slot after storing to a slot returns 0. + """ + tstore_value = 88 + + slot_tload_untouched_slot_after_tstore_result = 1 + slot_code_worked = 2 + + address_to = pre.deploy_contract( + code=Op.JUMPDEST() + # 03 test + + Op.TSTORE(3, tstore_value) + + Op.SSTORE(slot_tload_untouched_slot_after_tstore_result, Op.TLOAD(0)) + + Op.SSTORE(slot_code_worked, 1), + storage={ + slot_tload_untouched_slot_after_tstore_result: 0xFF, + }, + ) + + post = { + address_to: Account( + storage={ + slot_tload_untouched_slot_after_tstore_result: 0x00, + slot_code_worked: 0x01, + } + ) + } + + tx = Transaction( + sender=pre.fund_eoa(7_000_000_000_000_000_000), + to=address_to, + gas_price=10, + data=b"", + gas_limit=5000000, + value=0, + ) + + state_test(env=Environment(), pre=pre, post=post, tx=tx) + + +@pytest.mark.valid_from("Cancun") +def test_basic_tload_gasprice2( + state_test: StateTestFiller, + pre: Alloc, +): + """ + Ported .json vectors: + + (16_tloadGasFiller.yml) + tload costs 100 gas same as a warm sload + """ + slot_tload_nonzero_gas_price_result = 1 + slot_tload_zero_gas_price_result = 2 + slot_code_worked = 3 + + """ + N OPNAME GAS_COST TOTAL_GAS REMAINING_GAS STACK + 28-1 MSTORE 2 20748 4958252 2:[4ba82f,0,] + MSTORE [0] = 4958255 + 29-1 PUSH1 3 20754 4958246 + 30-1 TLOAD 100 20757 4958243 1:[10,] + 31-1 GAS 2 20857 4958143 1:[2,] + 32-1 PUSH1 3 20859 4958141 2:[2,4ba7bd,] + 33-1 MSTORE 6 20862 4958138 3:[2,4ba7bd,20,] + MSTORE [32] = 4958141 + """ + extra_opcode_gas = 11 # mstore(3), push1(3),gas(2),push1(3) + + address_to = pre.deploy_contract( + code=Op.JUMPDEST() + # 16 test + + Op.TSTORE(16, 2) + + Op.MSTORE(0, Op.GAS()) # hot load the memory to make the extra_opcode_gas be 11 + + Op.MSTORE(0, Op.GAS()) + + Op.TLOAD(16) + + Op.MSTORE(32, Op.GAS()) + + Op.SSTORE(slot_tload_nonzero_gas_price_result, Op.SUB(Op.MLOAD(0), Op.MLOAD(32))) + + Op.SSTORE( + slot_tload_nonzero_gas_price_result, + Op.SUB(Op.SLOAD(slot_tload_nonzero_gas_price_result), extra_opcode_gas), + ) + + Op.MSTORE(0, Op.GAS()) + + Op.TLOAD(5) # tload slot at 5 is 0 + + Op.MSTORE(32, Op.GAS()) + + Op.SSTORE(slot_tload_zero_gas_price_result, Op.SUB(Op.MLOAD(0), Op.MLOAD(32))) + + Op.SSTORE( + slot_tload_zero_gas_price_result, + Op.SUB(Op.SLOAD(slot_tload_zero_gas_price_result), extra_opcode_gas), + ) + + Op.SSTORE(slot_code_worked, 1), + storage={ + slot_tload_nonzero_gas_price_result: 0xFF, + slot_tload_zero_gas_price_result: 0xFF, + }, + ) + + post = { + address_to: Account( + storage={ + slot_tload_nonzero_gas_price_result: Spec.TLOAD_GAS_COST, + slot_tload_zero_gas_price_result: Spec.TLOAD_GAS_COST, + slot_code_worked: 0x01, + } + ) + } + + tx = Transaction( + sender=pre.fund_eoa(7_000_000_000_000_000_000), + to=address_to, + gas_price=10, + data=b"", + gas_limit=5000000, + value=0, + ) + + state_test(env=Environment(), pre=pre, post=post, tx=tx) + + +@pytest.mark.valid_from("Cancun") +def test_basic_tload_after_store2( + state_test: StateTestFiller, + pre: Alloc, +): + """ + Ported .json vectors: + + (18_tloadAfterStoreFiller.yml) + tload from same slot after store returns 0 + """ + slot_tload_from_sstore_result = 1 + slot_code_worked = 2 + + address_to = pre.deploy_contract( + code=Op.JUMPDEST() + # 18 test + + Op.SSTORE(slot_tload_from_sstore_result, 22) + + Op.SSTORE(slot_tload_from_sstore_result, Op.TLOAD(slot_tload_from_sstore_result)) + + Op.SSTORE(slot_code_worked, 1), + storage={ + slot_tload_from_sstore_result: 0xFF, + }, + ) + + post: Dict[Address, Union[Account, object]] = {} + post[address_to] = Account( + storage={ + slot_tload_from_sstore_result: 0x00, + slot_code_worked: 0x01, + } + ) + + tx = Transaction( + sender=pre.fund_eoa(7_000_000_000_000_000_000), + to=address_to, + gas_price=10, + data=b"", + gas_limit=5000000, + value=0, + ) + + state_test(env=Environment(), pre=pre, post=post, tx=tx) From 52550d70e158ef7fc3dcd537edd70a4699c5a6f5 Mon Sep 17 00:00:00 2001 From: Dimitry Kh Date: Mon, 30 Sep 2024 10:30:28 +0200 Subject: [PATCH 09/15] no new tests, only unrelated changes, script is disabled --- tests/cancun/eip1153_tstore/__init__.py | 1 + tests/cancun/eip1153_tstore/spec.py | 1 + .../eip1153_tstore/test_basic_tload2.py | 284 ------------------ 3 files changed, 2 insertions(+), 284 deletions(-) delete mode 100644 tests/cancun/eip1153_tstore/test_basic_tload2.py diff --git a/tests/cancun/eip1153_tstore/__init__.py b/tests/cancun/eip1153_tstore/__init__.py index 0e6fefc2a5..732507bdc4 100644 --- a/tests/cancun/eip1153_tstore/__init__.py +++ b/tests/cancun/eip1153_tstore/__init__.py @@ -1,4 +1,5 @@ """ +touch EIP-1153 Tests """ diff --git a/tests/cancun/eip1153_tstore/spec.py b/tests/cancun/eip1153_tstore/spec.py index d881867ee8..ee8f04f5e8 100644 --- a/tests/cancun/eip1153_tstore/spec.py +++ b/tests/cancun/eip1153_tstore/spec.py @@ -1,4 +1,5 @@ """ +touch Defines EIP-1153 specification constants and functions. """ from dataclasses import dataclass diff --git a/tests/cancun/eip1153_tstore/test_basic_tload2.py b/tests/cancun/eip1153_tstore/test_basic_tload2.py deleted file mode 100644 index 4c80ece2c6..0000000000 --- a/tests/cancun/eip1153_tstore/test_basic_tload2.py +++ /dev/null @@ -1,284 +0,0 @@ -""" -Ethereum Transient Storage EIP Tests -https://eips.ethereum.org/EIPS/eip-1153 -""" - -from typing import Dict, Union - -import pytest - -from ethereum_test_tools import Account, Address, Alloc, Environment, StateTestFiller, Transaction -from ethereum_test_tools.vm.opcode import Opcodes as Op - -from .spec import Spec, ref_spec_1153 - -REFERENCE_SPEC_GIT_PATH = ref_spec_1153.git_path -REFERENCE_SPEC_VERSION = ref_spec_1153.version - - -@pytest.mark.valid_from("Cancun") -def test_basic_tload_transaction_begin2( - state_test: StateTestFiller, - pre: Alloc, -): - """ - Ported .json vectors: - - (01_tloadBeginningTxnFiller.yml) - load arbitrary value is 0 at beginning of transaction - """ - slot_tload_at_transaction_begin_result = 1 - slot_code_worked = 2 - - address_to = pre.deploy_contract( - code=Op.JUMPDEST() - # 01 test - + Op.SSTORE(slot_tload_at_transaction_begin_result, Op.TLOAD(0)) - + Op.SSTORE(slot_code_worked, 1), - storage={ - slot_tload_at_transaction_begin_result: 0xFF, - }, - ) - - post = { - address_to: Account( - storage={ - slot_tload_at_transaction_begin_result: 0x00, - slot_code_worked: 0x01, - } - ) - } - - tx = Transaction( - sender=pre.fund_eoa(7_000_000_000_000_000_000), - to=address_to, - gas_price=10, - data=b"", - gas_limit=5000000, - value=0, - ) - - state_test(env=Environment(), pre=pre, post=post, tx=tx) - - -@pytest.mark.valid_from("Cancun") -def test_basic_tload_works2( - state_test: StateTestFiller, - pre: Alloc, -): - """ - Ported .json vectors: - - (02_tloadAfterTstoreFiller.yml) - tload from same slot after tstore returns correct value - """ - tstore_value = 88 - - slot_tload_after_tstore_result = 0 - slot_tload_after_tstore_result_second_time = 1 - slot_code_worked = 2 - - address_to = pre.deploy_contract( - code=Op.JUMPDEST() - # 02 test - + Op.TSTORE(2, tstore_value) - + Op.SSTORE(slot_tload_after_tstore_result, Op.TLOAD(2)) - + Op.SSTORE(slot_tload_after_tstore_result_second_time, Op.TLOAD(2)) - + Op.SSTORE(slot_code_worked, 1), - storage={ - slot_tload_after_tstore_result: 0xFF, - slot_tload_after_tstore_result_second_time: 0xFF, - }, - ) - - post = { - address_to: Account( - storage={ - slot_tload_after_tstore_result: tstore_value, - slot_tload_after_tstore_result_second_time: tstore_value, - slot_code_worked: 0x01, - } - ) - } - - tx = Transaction( - sender=pre.fund_eoa(7_000_000_000_000_000_000), - to=address_to, - gas_price=10, - data=b"", - gas_limit=5000000, - value=0, - ) - - state_test(env=Environment(), pre=pre, post=post, tx=tx) - - -@pytest.mark.valid_from("Cancun") -def test_basic_tload_other_after_tstore2( - state_test: StateTestFiller, - pre: Alloc, -): - """ - Ported .json vectors: - - (03_tloadAfterStoreIs0Filler.yml) - Loading any other slot after storing to a slot returns 0. - """ - tstore_value = 88 - - slot_tload_untouched_slot_after_tstore_result = 1 - slot_code_worked = 2 - - address_to = pre.deploy_contract( - code=Op.JUMPDEST() - # 03 test - + Op.TSTORE(3, tstore_value) - + Op.SSTORE(slot_tload_untouched_slot_after_tstore_result, Op.TLOAD(0)) - + Op.SSTORE(slot_code_worked, 1), - storage={ - slot_tload_untouched_slot_after_tstore_result: 0xFF, - }, - ) - - post = { - address_to: Account( - storage={ - slot_tload_untouched_slot_after_tstore_result: 0x00, - slot_code_worked: 0x01, - } - ) - } - - tx = Transaction( - sender=pre.fund_eoa(7_000_000_000_000_000_000), - to=address_to, - gas_price=10, - data=b"", - gas_limit=5000000, - value=0, - ) - - state_test(env=Environment(), pre=pre, post=post, tx=tx) - - -@pytest.mark.valid_from("Cancun") -def test_basic_tload_gasprice2( - state_test: StateTestFiller, - pre: Alloc, -): - """ - Ported .json vectors: - - (16_tloadGasFiller.yml) - tload costs 100 gas same as a warm sload - """ - slot_tload_nonzero_gas_price_result = 1 - slot_tload_zero_gas_price_result = 2 - slot_code_worked = 3 - - """ - N OPNAME GAS_COST TOTAL_GAS REMAINING_GAS STACK - 28-1 MSTORE 2 20748 4958252 2:[4ba82f,0,] - MSTORE [0] = 4958255 - 29-1 PUSH1 3 20754 4958246 - 30-1 TLOAD 100 20757 4958243 1:[10,] - 31-1 GAS 2 20857 4958143 1:[2,] - 32-1 PUSH1 3 20859 4958141 2:[2,4ba7bd,] - 33-1 MSTORE 6 20862 4958138 3:[2,4ba7bd,20,] - MSTORE [32] = 4958141 - """ - extra_opcode_gas = 11 # mstore(3), push1(3),gas(2),push1(3) - - address_to = pre.deploy_contract( - code=Op.JUMPDEST() - # 16 test - + Op.TSTORE(16, 2) - + Op.MSTORE(0, Op.GAS()) # hot load the memory to make the extra_opcode_gas be 11 - + Op.MSTORE(0, Op.GAS()) - + Op.TLOAD(16) - + Op.MSTORE(32, Op.GAS()) - + Op.SSTORE(slot_tload_nonzero_gas_price_result, Op.SUB(Op.MLOAD(0), Op.MLOAD(32))) - + Op.SSTORE( - slot_tload_nonzero_gas_price_result, - Op.SUB(Op.SLOAD(slot_tload_nonzero_gas_price_result), extra_opcode_gas), - ) - + Op.MSTORE(0, Op.GAS()) - + Op.TLOAD(5) # tload slot at 5 is 0 - + Op.MSTORE(32, Op.GAS()) - + Op.SSTORE(slot_tload_zero_gas_price_result, Op.SUB(Op.MLOAD(0), Op.MLOAD(32))) - + Op.SSTORE( - slot_tload_zero_gas_price_result, - Op.SUB(Op.SLOAD(slot_tload_zero_gas_price_result), extra_opcode_gas), - ) - + Op.SSTORE(slot_code_worked, 1), - storage={ - slot_tload_nonzero_gas_price_result: 0xFF, - slot_tload_zero_gas_price_result: 0xFF, - }, - ) - - post = { - address_to: Account( - storage={ - slot_tload_nonzero_gas_price_result: Spec.TLOAD_GAS_COST, - slot_tload_zero_gas_price_result: Spec.TLOAD_GAS_COST, - slot_code_worked: 0x01, - } - ) - } - - tx = Transaction( - sender=pre.fund_eoa(7_000_000_000_000_000_000), - to=address_to, - gas_price=10, - data=b"", - gas_limit=5000000, - value=0, - ) - - state_test(env=Environment(), pre=pre, post=post, tx=tx) - - -@pytest.mark.valid_from("Cancun") -def test_basic_tload_after_store2( - state_test: StateTestFiller, - pre: Alloc, -): - """ - Ported .json vectors: - - (18_tloadAfterStoreFiller.yml) - tload from same slot after store returns 0 - """ - slot_tload_from_sstore_result = 1 - slot_code_worked = 2 - - address_to = pre.deploy_contract( - code=Op.JUMPDEST() - # 18 test - + Op.SSTORE(slot_tload_from_sstore_result, 22) - + Op.SSTORE(slot_tload_from_sstore_result, Op.TLOAD(slot_tload_from_sstore_result)) - + Op.SSTORE(slot_code_worked, 1), - storage={ - slot_tload_from_sstore_result: 0xFF, - }, - ) - - post: Dict[Address, Union[Account, object]] = {} - post[address_to] = Account( - storage={ - slot_tload_from_sstore_result: 0x00, - slot_code_worked: 0x01, - } - ) - - tx = Transaction( - sender=pre.fund_eoa(7_000_000_000_000_000_000), - to=address_to, - gas_price=10, - data=b"", - gas_limit=5000000, - value=0, - ) - - state_test(env=Environment(), pre=pre, post=post, tx=tx) From eb56fa62078275c6591ae7998ca210bce455c472 Mon Sep 17 00:00:00 2001 From: Dimitry Kh Date: Mon, 30 Sep 2024 10:34:09 +0200 Subject: [PATCH 10/15] lost coverage in pr detected --- tests/cancun/eip1153_tstore/__init__.py | 1 - tests/cancun/eip1153_tstore/spec.py | 1 - tests/cancun/eip1153_tstore/test_tload_calls.py | 1 + tests/cancun/eip1153_tstore/test_tload_reentrancy.py | 6 +++--- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/cancun/eip1153_tstore/__init__.py b/tests/cancun/eip1153_tstore/__init__.py index 732507bdc4..0e6fefc2a5 100644 --- a/tests/cancun/eip1153_tstore/__init__.py +++ b/tests/cancun/eip1153_tstore/__init__.py @@ -1,5 +1,4 @@ """ -touch EIP-1153 Tests """ diff --git a/tests/cancun/eip1153_tstore/spec.py b/tests/cancun/eip1153_tstore/spec.py index ee8f04f5e8..d881867ee8 100644 --- a/tests/cancun/eip1153_tstore/spec.py +++ b/tests/cancun/eip1153_tstore/spec.py @@ -1,5 +1,4 @@ """ -touch Defines EIP-1153 specification constants and functions. """ from dataclasses import dataclass diff --git a/tests/cancun/eip1153_tstore/test_tload_calls.py b/tests/cancun/eip1153_tstore/test_tload_calls.py index 2501fcee45..38dbdd20c1 100644 --- a/tests/cancun/eip1153_tstore/test_tload_calls.py +++ b/tests/cancun/eip1153_tstore/test_tload_calls.py @@ -1,4 +1,5 @@ """ +touch Ethereum Transient Storage EIP Tests https://eips.ethereum.org/EIPS/eip-1153 """ diff --git a/tests/cancun/eip1153_tstore/test_tload_reentrancy.py b/tests/cancun/eip1153_tstore/test_tload_reentrancy.py index 61c7b9ea5a..cb16ddf15a 100644 --- a/tests/cancun/eip1153_tstore/test_tload_reentrancy.py +++ b/tests/cancun/eip1153_tstore/test_tload_reentrancy.py @@ -34,9 +34,9 @@ class CallDestType(Enum): @pytest.mark.valid_from("Cancun") -@pytest.mark.parametrize("call_type", [Op.CALL, Op.CALLCODE, Op.DELEGATECALL, Op.STATICCALL]) -@pytest.mark.parametrize("call_return", [Op.RETURN, Op.REVERT, Om.OOG]) -@pytest.mark.parametrize("call_dest_type", [CallDestType.REENTRANCY, CallDestType.EXTERNAL_CALL]) +@pytest.mark.parametrize("call_type", [Op.CALL]) +@pytest.mark.parametrize("call_return", [Op.RETURN]) +@pytest.mark.parametrize("call_dest_type", [CallDestType.REENTRANCY]) def test_tload_reentrancy( state_test: StateTestFiller, pre: Alloc, From 41bc7ff0b9ba70419b92baab4934cc54012e131e Mon Sep 17 00:00:00 2001 From: Dimitry Kh Date: Mon, 30 Sep 2024 10:48:40 +0200 Subject: [PATCH 11/15] new coverage in pr detected --- tests/cancun/eip1153_tstore/test_tload_calls.py | 1 - tests/cancun/eip1153_tstore/test_tload_reentrancy.py | 7 ++++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/cancun/eip1153_tstore/test_tload_calls.py b/tests/cancun/eip1153_tstore/test_tload_calls.py index 38dbdd20c1..2501fcee45 100644 --- a/tests/cancun/eip1153_tstore/test_tload_calls.py +++ b/tests/cancun/eip1153_tstore/test_tload_calls.py @@ -1,5 +1,4 @@ """ -touch Ethereum Transient Storage EIP Tests https://eips.ethereum.org/EIPS/eip-1153 """ diff --git a/tests/cancun/eip1153_tstore/test_tload_reentrancy.py b/tests/cancun/eip1153_tstore/test_tload_reentrancy.py index cb16ddf15a..000b138f39 100644 --- a/tests/cancun/eip1153_tstore/test_tload_reentrancy.py +++ b/tests/cancun/eip1153_tstore/test_tload_reentrancy.py @@ -34,9 +34,9 @@ class CallDestType(Enum): @pytest.mark.valid_from("Cancun") -@pytest.mark.parametrize("call_type", [Op.CALL]) -@pytest.mark.parametrize("call_return", [Op.RETURN]) -@pytest.mark.parametrize("call_dest_type", [CallDestType.REENTRANCY]) +@pytest.mark.parametrize("call_type", [Op.CALL, Op.CALLCODE, Op.DELEGATECALL, Op.STATICCALL]) +@pytest.mark.parametrize("call_return", [Op.RETURN, Op.REVERT, Om.OOG]) +@pytest.mark.parametrize("call_dest_type", [CallDestType.REENTRANCY, CallDestType.EXTERNAL_CALL]) def test_tload_reentrancy( state_test: StateTestFiller, pre: Alloc, @@ -94,6 +94,7 @@ def make_call(call_type: Op) -> Bytecode: action=Op.TSTORE(0, tload_value) + Op.MSTORE(0, do_load) + Op.MSTORE(32, 0xFF) + + Op.ADD(10, 10) + Op.SSTORE(slot_subcall_worked, make_call(call_type)) + Op.SSTORE(slot_tload_in_subcall_result, Op.MLOAD(32)) + Op.SSTORE(slot_tload_after_subcall_result, Op.TLOAD(0)) From df0f4290195ce8d694da66e23ae9490b1b469c4b Mon Sep 17 00:00:00 2001 From: Dimitry Kh Date: Mon, 30 Sep 2024 11:05:25 +0200 Subject: [PATCH 12/15] new test in eof --- .../eip1153_tstore/test_tload_reentrancy.py | 1 - .../eip3540_eof_v1/test_eof_example2.py | 156 ++++++++++++++++++ 2 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_eof_example2.py diff --git a/tests/cancun/eip1153_tstore/test_tload_reentrancy.py b/tests/cancun/eip1153_tstore/test_tload_reentrancy.py index 000b138f39..61c7b9ea5a 100644 --- a/tests/cancun/eip1153_tstore/test_tload_reentrancy.py +++ b/tests/cancun/eip1153_tstore/test_tload_reentrancy.py @@ -94,7 +94,6 @@ def make_call(call_type: Op) -> Bytecode: action=Op.TSTORE(0, tload_value) + Op.MSTORE(0, do_load) + Op.MSTORE(32, 0xFF) - + Op.ADD(10, 10) + Op.SSTORE(slot_subcall_worked, make_call(call_type)) + Op.SSTORE(slot_tload_in_subcall_result, Op.MLOAD(32)) + Op.SSTORE(slot_tload_after_subcall_result, Op.TLOAD(0)) diff --git a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_eof_example2.py b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_eof_example2.py new file mode 100644 index 0000000000..bea2628d3f --- /dev/null +++ b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_eof_example2.py @@ -0,0 +1,156 @@ +""" +EOF Classes example use +""" + +import pytest + +from ethereum_test_tools import Bytecode, EOFException, EOFTestFiller +from ethereum_test_tools import Opcodes as Op +from ethereum_test_tools.eof.v1 import AutoSection, Container, Section + +from .. import EOF_FORK_NAME + +REFERENCE_SPEC_GIT_PATH = "EIPS/eip-3540.md" +REFERENCE_SPEC_VERSION = "8dcb0a8c1c0102c87224308028632cc986a61183" + +pytestmark = pytest.mark.valid_from(EOF_FORK_NAME) + + +def test_eof_example2(eof_test: EOFTestFiller): + """ + Example of python EOF classes + """ + # Lets construct an EOF container code + eof_code = Container( + name="valid_container_example", + sections=[ + # TYPES section is constructed automatically based on CODE + # CODE section + Section.Code( + code=Op.CALLF[1](Op.PUSH0) + Op.STOP, # bytecode to be deployed in the body + # Code: call section 1 with a single zero as input, then stop. + max_stack_height=1, # define code header (in body) stack size + ), + # There can be multiple code sections + Section.Code( + # Remove input and call section 2 with no inputs, then remove output and return + code=Op.POP + Op.CALLF[2]() + Op.POP + Op.RETF, + code_inputs=1, + code_outputs=0, + max_stack_height=1, + ), + Section.Code( + # Call section 3 with two inputs (address twice), return + code=Op.CALLF[3](Op.DUP1, Op.ADDRESS) + Op.POP + Op.POP + Op.RETF, + code_outputs=1, + max_stack_height=3, + ), + Section.Code( + # Duplicate one input and return + code=Op.DUP1 + Op.RETF, + code_inputs=2, + code_outputs=3, + max_stack_height=3, + ), + # DATA section + Section.Data("0xef"), + ], + ) + + # This will construct a valid EOF container with these bytes + assert bytes(eof_code) == bytes.fromhex( + "ef0001010010020004000500060008000204000100008000010100000100010003020300035fe300010050" + "e3000250e43080e300035050e480e4ef" + ) + + eof_test( + data=eof_code, + expect_exception=eof_code.validity_error, + ) + + +def test_eof_example_custom_fields2(eof_test: EOFTestFiller): + """ + Example of python EOF container class tuning + """ + # if you need to overwrite certain structure bytes, you can use customization + # this is useful for unit testing the eof structure format, you can reorganize sections + # and overwrite the header bytes for testing purposes + # most of the combinations are covered by the unit tests + + # This features are subject for development and will change in the future + + eof_code = Container( + name="valid_container_example_2", + magic=b"\xef\x00", # magic can be overwritten for test purposes, (default is 0xEF00) + version=b"\x01", # version can be overwritten for testing purposes (default is 0x01) + header_terminator=b"\x00", # terminator byte can be overwritten (default is 0x00) + extra=b"", # extra bytes to be trailed after the container body bytes (default is None) + sections=[ + # TYPES section is constructed automatically based on CODE + # CODE section + Section.Code( + code=Op.PUSH1(2) + + Op.STOP, # this is the actual bytecode to be deployed in the body + max_stack_height=1, # define code header (in body) stack size + ), + # DATA section + Section.Data( + data="0xef", + # custom_size overrides the size bytes, so you can put only 1 byte into data + # but still make the header size of 2 to produce invalid section + # if custom_size != len(data), the section will be invalid + custom_size=1, + ), + ], + # auto generate types section based on provided code sections + # AutoSection.ONLY_BODY - means the section will be generated only for the body bytes + # AutoSection.ONLY_BODY - means the section will be generated only for the header bytes + auto_type_section=AutoSection.AUTO, + # auto generate default data section (0x empty), by default is True + auto_data_section=True, + # auto sort section by order 01 02 03 04 + # AutoSection.ONLY_BODY - means the sorting will be done only for the body bytes + # AutoSection.ONLY_BODY - means the section will be done only for the header bytes + auto_sort_sections=AutoSection.AUTO, + ) + + eof_test( + data=eof_code, + expect_exception=eof_code.validity_error, + ) + + +@pytest.mark.parametrize( + "data_section_bytes", + (b"\x01", b"\xef"), +) +@pytest.mark.parametrize( + "code_section_code, exception", + [(Op.PUSH1(10) + Op.STOP, None), (Op.PUSH1(14), EOFException.MISSING_STOP_OPCODE)], +) +def test_eof_example_parameters2( + eof_test: EOFTestFiller, + data_section_bytes: bytes, + code_section_code: Bytecode, + exception: EOFException, +): + """ + Example of python EOF classes + """ + eof_code = Container( + name="parametrized_eof_example", + sections=[ + Section.Code( + code=code_section_code, + max_stack_height=1, + ), + Section.Data(data_section_bytes), + ], + validity_error=exception, + ) + + eof_test( + data=eof_code, + expect_exception=eof_code.validity_error, + ) From 649bbbf0ecb08952069394e8999cc0d41ae35179 Mon Sep 17 00:00:00 2001 From: Dimitry Kh Date: Mon, 30 Sep 2024 11:15:17 +0200 Subject: [PATCH 13/15] converted files coverage --- converted-ethereum-tests.txt | 36 ++-- .../cancun/eip1153_tstore/test_basic_tload.py | 1 + .../cancun/eip1153_tstore/test_tload_calls.py | 1 + .../eip1153_tstore/test_tload_reentrancy.py | 1 + .../eip1153_tstore/test_tstore_reentrancy.py | 1 + .../eip3540_eof_v1/test_eof_example2.py | 156 ------------------ 6 files changed, 22 insertions(+), 174 deletions(-) delete mode 100644 tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_eof_example2.py diff --git a/converted-ethereum-tests.txt b/converted-ethereum-tests.txt index f11bdc4490..5428a477aa 100644 --- a/converted-ethereum-tests.txt +++ b/converted-ethereum-tests.txt @@ -19,21 +19,21 @@ EOFTests/efValidation/EOF1_returncontract_invalid_.json EOFTests/efValidation/EOF1_returncontract_valid_.json ([#440](https://github.com/ethereum/execution-spec-tests/pull/440)) -GeneralStateTests/Cancun/stEIP1153-transientStorage/01_tloadBeginningTxn.json -GeneralStateTests/Cancun/stEIP1153-transientStorage/02_tloadAfterTstore.json -GeneralStateTests/Cancun/stEIP1153-transientStorage/03_tloadAfterStoreIs0.json -GeneralStateTests/Cancun/stEIP1153-transientStorage/04_tloadAfterCall.json -GeneralStateTests/Cancun/stEIP1153-transientStorage/05_tloadReentrancy.json -GeneralStateTests/Cancun/stEIP1153-transientStorage/06_tstoreInReentrancyCall.json -GeneralStateTests/Cancun/stEIP1153-transientStorage/07_tloadAfterReentrancyStore.json -GeneralStateTests/Cancun/stEIP1153-transientStorage/08_revertUndoesTransientStore.json -GeneralStateTests/Cancun/stEIP1153-transientStorage/09_revertUndoesAll.json - -GeneralStateTests/Cancun/stEIP1153-transientStorage/11_tstoreDelegateCall.json -GeneralStateTests/Cancun/stEIP1153-transientStorage/12_tloadDelegateCall.json -GeneralStateTests/Cancun/stEIP1153-transientStorage/13_tloadStaticCall.json - -GeneralStateTests/Cancun/stEIP1153-transientStorage/16_tloadGas.json -GeneralStateTests/Cancun/stEIP1153-transientStorage/18_tloadAfterStore.json - -GeneralStateTests/Cancun/stEIP1153-transientStorage/20_oogUndoesTransientStoreInCall.json + GeneralStateTests/Cancun/stEIP1153-transientStorage/01_tloadBeginningTxn.json + GeneralStateTests/Cancun/stEIP1153-transientStorage/02_tloadAfterTstore.json + GeneralStateTests/Cancun/stEIP1153-transientStorage/03_tloadAfterStoreIs0.json + GeneralStateTests/Cancun/stEIP1153-transientStorage/04_tloadAfterCall.json + GeneralStateTests/Cancun/stEIP1153-transientStorage/05_tloadReentrancy.json + GeneralStateTests/Cancun/stEIP1153-transientStorage/06_tstoreInReentrancyCall.json + GeneralStateTests/Cancun/stEIP1153-transientStorage/07_tloadAfterReentrancyStore.json + GeneralStateTests/Cancun/stEIP1153-transientStorage/08_revertUndoesTransientStore.json + GeneralStateTests/Cancun/stEIP1153-transientStorage/09_revertUndoesAll.json + + GeneralStateTests/Cancun/stEIP1153-transientStorage/11_tstoreDelegateCall.json + GeneralStateTests/Cancun/stEIP1153-transientStorage/12_tloadDelegateCall.json + GeneralStateTests/Cancun/stEIP1153-transientStorage/13_tloadStaticCall.json + + GeneralStateTests/Cancun/stEIP1153-transientStorage/16_tloadGas.json + GeneralStateTests/Cancun/stEIP1153-transientStorage/18_tloadAfterStore.json + + GeneralStateTests/Cancun/stEIP1153-transientStorage/20_oogUndoesTransientStoreInCall.json diff --git a/tests/cancun/eip1153_tstore/test_basic_tload.py b/tests/cancun/eip1153_tstore/test_basic_tload.py index ac24628290..4ba280c779 100644 --- a/tests/cancun/eip1153_tstore/test_basic_tload.py +++ b/tests/cancun/eip1153_tstore/test_basic_tload.py @@ -1,4 +1,5 @@ """ +touch Ethereum Transient Storage EIP Tests https://eips.ethereum.org/EIPS/eip-1153 """ diff --git a/tests/cancun/eip1153_tstore/test_tload_calls.py b/tests/cancun/eip1153_tstore/test_tload_calls.py index 2501fcee45..38dbdd20c1 100644 --- a/tests/cancun/eip1153_tstore/test_tload_calls.py +++ b/tests/cancun/eip1153_tstore/test_tload_calls.py @@ -1,4 +1,5 @@ """ +touch Ethereum Transient Storage EIP Tests https://eips.ethereum.org/EIPS/eip-1153 """ diff --git a/tests/cancun/eip1153_tstore/test_tload_reentrancy.py b/tests/cancun/eip1153_tstore/test_tload_reentrancy.py index 61c7b9ea5a..63741da5f4 100644 --- a/tests/cancun/eip1153_tstore/test_tload_reentrancy.py +++ b/tests/cancun/eip1153_tstore/test_tload_reentrancy.py @@ -1,4 +1,5 @@ """ +touch Ethereum Transient Storage EIP Tests https://eips.ethereum.org/EIPS/eip-1153 """ diff --git a/tests/cancun/eip1153_tstore/test_tstore_reentrancy.py b/tests/cancun/eip1153_tstore/test_tstore_reentrancy.py index dff47ddbcb..aacf4faf18 100644 --- a/tests/cancun/eip1153_tstore/test_tstore_reentrancy.py +++ b/tests/cancun/eip1153_tstore/test_tstore_reentrancy.py @@ -1,4 +1,5 @@ """ +touch Ethereum Transient Storage EIP Tests https://eips.ethereum.org/EIPS/eip-1153 """ diff --git a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_eof_example2.py b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_eof_example2.py deleted file mode 100644 index bea2628d3f..0000000000 --- a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_eof_example2.py +++ /dev/null @@ -1,156 +0,0 @@ -""" -EOF Classes example use -""" - -import pytest - -from ethereum_test_tools import Bytecode, EOFException, EOFTestFiller -from ethereum_test_tools import Opcodes as Op -from ethereum_test_tools.eof.v1 import AutoSection, Container, Section - -from .. import EOF_FORK_NAME - -REFERENCE_SPEC_GIT_PATH = "EIPS/eip-3540.md" -REFERENCE_SPEC_VERSION = "8dcb0a8c1c0102c87224308028632cc986a61183" - -pytestmark = pytest.mark.valid_from(EOF_FORK_NAME) - - -def test_eof_example2(eof_test: EOFTestFiller): - """ - Example of python EOF classes - """ - # Lets construct an EOF container code - eof_code = Container( - name="valid_container_example", - sections=[ - # TYPES section is constructed automatically based on CODE - # CODE section - Section.Code( - code=Op.CALLF[1](Op.PUSH0) + Op.STOP, # bytecode to be deployed in the body - # Code: call section 1 with a single zero as input, then stop. - max_stack_height=1, # define code header (in body) stack size - ), - # There can be multiple code sections - Section.Code( - # Remove input and call section 2 with no inputs, then remove output and return - code=Op.POP + Op.CALLF[2]() + Op.POP + Op.RETF, - code_inputs=1, - code_outputs=0, - max_stack_height=1, - ), - Section.Code( - # Call section 3 with two inputs (address twice), return - code=Op.CALLF[3](Op.DUP1, Op.ADDRESS) + Op.POP + Op.POP + Op.RETF, - code_outputs=1, - max_stack_height=3, - ), - Section.Code( - # Duplicate one input and return - code=Op.DUP1 + Op.RETF, - code_inputs=2, - code_outputs=3, - max_stack_height=3, - ), - # DATA section - Section.Data("0xef"), - ], - ) - - # This will construct a valid EOF container with these bytes - assert bytes(eof_code) == bytes.fromhex( - "ef0001010010020004000500060008000204000100008000010100000100010003020300035fe300010050" - "e3000250e43080e300035050e480e4ef" - ) - - eof_test( - data=eof_code, - expect_exception=eof_code.validity_error, - ) - - -def test_eof_example_custom_fields2(eof_test: EOFTestFiller): - """ - Example of python EOF container class tuning - """ - # if you need to overwrite certain structure bytes, you can use customization - # this is useful for unit testing the eof structure format, you can reorganize sections - # and overwrite the header bytes for testing purposes - # most of the combinations are covered by the unit tests - - # This features are subject for development and will change in the future - - eof_code = Container( - name="valid_container_example_2", - magic=b"\xef\x00", # magic can be overwritten for test purposes, (default is 0xEF00) - version=b"\x01", # version can be overwritten for testing purposes (default is 0x01) - header_terminator=b"\x00", # terminator byte can be overwritten (default is 0x00) - extra=b"", # extra bytes to be trailed after the container body bytes (default is None) - sections=[ - # TYPES section is constructed automatically based on CODE - # CODE section - Section.Code( - code=Op.PUSH1(2) - + Op.STOP, # this is the actual bytecode to be deployed in the body - max_stack_height=1, # define code header (in body) stack size - ), - # DATA section - Section.Data( - data="0xef", - # custom_size overrides the size bytes, so you can put only 1 byte into data - # but still make the header size of 2 to produce invalid section - # if custom_size != len(data), the section will be invalid - custom_size=1, - ), - ], - # auto generate types section based on provided code sections - # AutoSection.ONLY_BODY - means the section will be generated only for the body bytes - # AutoSection.ONLY_BODY - means the section will be generated only for the header bytes - auto_type_section=AutoSection.AUTO, - # auto generate default data section (0x empty), by default is True - auto_data_section=True, - # auto sort section by order 01 02 03 04 - # AutoSection.ONLY_BODY - means the sorting will be done only for the body bytes - # AutoSection.ONLY_BODY - means the section will be done only for the header bytes - auto_sort_sections=AutoSection.AUTO, - ) - - eof_test( - data=eof_code, - expect_exception=eof_code.validity_error, - ) - - -@pytest.mark.parametrize( - "data_section_bytes", - (b"\x01", b"\xef"), -) -@pytest.mark.parametrize( - "code_section_code, exception", - [(Op.PUSH1(10) + Op.STOP, None), (Op.PUSH1(14), EOFException.MISSING_STOP_OPCODE)], -) -def test_eof_example_parameters2( - eof_test: EOFTestFiller, - data_section_bytes: bytes, - code_section_code: Bytecode, - exception: EOFException, -): - """ - Example of python EOF classes - """ - eof_code = Container( - name="parametrized_eof_example", - sections=[ - Section.Code( - code=code_section_code, - max_stack_height=1, - ), - Section.Data(data_section_bytes), - ], - validity_error=exception, - ) - - eof_test( - data=eof_code, - expect_exception=eof_code.validity_error, - ) From fe6384503b3870ca35ea34009fb0a4b7bba8f620 Mon Sep 17 00:00:00 2001 From: Dimitry Kh Date: Mon, 30 Sep 2024 11:28:14 +0200 Subject: [PATCH 14/15] converted test files, files are missing in tests --- converted-ethereum-tests.txt | 40 +++++++++---------- .../cancun/eip1153_tstore/test_basic_tload.py | 1 - .../cancun/eip1153_tstore/test_tload_calls.py | 1 - .../eip1153_tstore/test_tload_reentrancy.py | 1 - .../eip1153_tstore/test_tstore_reentrancy.py | 1 - .../eip3540_eof_v1/test_eof_example.py | 1 + 6 files changed, 21 insertions(+), 24 deletions(-) diff --git a/converted-ethereum-tests.txt b/converted-ethereum-tests.txt index 5428a477aa..34934f428e 100644 --- a/converted-ethereum-tests.txt +++ b/converted-ethereum-tests.txt @@ -15,25 +15,25 @@ EOFTests/efValidation/EOF1_section_order_.json EOFTests/efValidation/EOF1_truncated_section_.json ([#647](https://github.com/ethereum/execution-spec-tests/pull/647)) -EOFTests/efValidation/EOF1_returncontract_invalid_.json -EOFTests/efValidation/EOF1_returncontract_valid_.json + EOFTests/efValidation/EOF1_returncontract_invalid_.json + EOFTests/efValidation/EOF1_returncontract_valid_.json ([#440](https://github.com/ethereum/execution-spec-tests/pull/440)) - GeneralStateTests/Cancun/stEIP1153-transientStorage/01_tloadBeginningTxn.json - GeneralStateTests/Cancun/stEIP1153-transientStorage/02_tloadAfterTstore.json - GeneralStateTests/Cancun/stEIP1153-transientStorage/03_tloadAfterStoreIs0.json - GeneralStateTests/Cancun/stEIP1153-transientStorage/04_tloadAfterCall.json - GeneralStateTests/Cancun/stEIP1153-transientStorage/05_tloadReentrancy.json - GeneralStateTests/Cancun/stEIP1153-transientStorage/06_tstoreInReentrancyCall.json - GeneralStateTests/Cancun/stEIP1153-transientStorage/07_tloadAfterReentrancyStore.json - GeneralStateTests/Cancun/stEIP1153-transientStorage/08_revertUndoesTransientStore.json - GeneralStateTests/Cancun/stEIP1153-transientStorage/09_revertUndoesAll.json - - GeneralStateTests/Cancun/stEIP1153-transientStorage/11_tstoreDelegateCall.json - GeneralStateTests/Cancun/stEIP1153-transientStorage/12_tloadDelegateCall.json - GeneralStateTests/Cancun/stEIP1153-transientStorage/13_tloadStaticCall.json - - GeneralStateTests/Cancun/stEIP1153-transientStorage/16_tloadGas.json - GeneralStateTests/Cancun/stEIP1153-transientStorage/18_tloadAfterStore.json - - GeneralStateTests/Cancun/stEIP1153-transientStorage/20_oogUndoesTransientStoreInCall.json +GeneralStateTests/Cancun/stEIP1153-transientStorage/01_tloadBeginningTxn.json +GeneralStateTests/Cancun/stEIP1153-transientStorage/02_tloadAfterTstore.json +GeneralStateTests/Cancun/stEIP1153-transientStorage/03_tloadAfterStoreIs0.json +GeneralStateTests/Cancun/stEIP1153-transientStorage/04_tloadAfterCall.json +GeneralStateTests/Cancun/stEIP1153-transientStorage/05_tloadReentrancy.json +GeneralStateTests/Cancun/stEIP1153-transientStorage/06_tstoreInReentrancyCall.json +GeneralStateTests/Cancun/stEIP1153-transientStorage/07_tloadAfterReentrancyStore.json +GeneralStateTests/Cancun/stEIP1153-transientStorage/08_revertUndoesTransientStore.json +GeneralStateTests/Cancun/stEIP1153-transientStorage/09_revertUndoesAll.json + +GeneralStateTests/Cancun/stEIP1153-transientStorage/11_tstoreDelegateCall.json +GeneralStateTests/Cancun/stEIP1153-transientStorage/12_tloadDelegateCall.json +GeneralStateTests/Cancun/stEIP1153-transientStorage/13_tloadStaticCall.json + +GeneralStateTests/Cancun/stEIP1153-transientStorage/16_tloadGas.json +GeneralStateTests/Cancun/stEIP1153-transientStorage/18_tloadAfterStore.json + +GeneralStateTests/Cancun/stEIP1153-transientStorage/20_oogUndoesTransientStoreInCall.json diff --git a/tests/cancun/eip1153_tstore/test_basic_tload.py b/tests/cancun/eip1153_tstore/test_basic_tload.py index 4ba280c779..ac24628290 100644 --- a/tests/cancun/eip1153_tstore/test_basic_tload.py +++ b/tests/cancun/eip1153_tstore/test_basic_tload.py @@ -1,5 +1,4 @@ """ -touch Ethereum Transient Storage EIP Tests https://eips.ethereum.org/EIPS/eip-1153 """ diff --git a/tests/cancun/eip1153_tstore/test_tload_calls.py b/tests/cancun/eip1153_tstore/test_tload_calls.py index 38dbdd20c1..2501fcee45 100644 --- a/tests/cancun/eip1153_tstore/test_tload_calls.py +++ b/tests/cancun/eip1153_tstore/test_tload_calls.py @@ -1,5 +1,4 @@ """ -touch Ethereum Transient Storage EIP Tests https://eips.ethereum.org/EIPS/eip-1153 """ diff --git a/tests/cancun/eip1153_tstore/test_tload_reentrancy.py b/tests/cancun/eip1153_tstore/test_tload_reentrancy.py index 63741da5f4..61c7b9ea5a 100644 --- a/tests/cancun/eip1153_tstore/test_tload_reentrancy.py +++ b/tests/cancun/eip1153_tstore/test_tload_reentrancy.py @@ -1,5 +1,4 @@ """ -touch Ethereum Transient Storage EIP Tests https://eips.ethereum.org/EIPS/eip-1153 """ diff --git a/tests/cancun/eip1153_tstore/test_tstore_reentrancy.py b/tests/cancun/eip1153_tstore/test_tstore_reentrancy.py index aacf4faf18..dff47ddbcb 100644 --- a/tests/cancun/eip1153_tstore/test_tstore_reentrancy.py +++ b/tests/cancun/eip1153_tstore/test_tstore_reentrancy.py @@ -1,5 +1,4 @@ """ -touch Ethereum Transient Storage EIP Tests https://eips.ethereum.org/EIPS/eip-1153 """ diff --git a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_eof_example.py b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_eof_example.py index 0ecaad8228..a93d60d876 100644 --- a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_eof_example.py +++ b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_eof_example.py @@ -1,4 +1,5 @@ """ +touch EOF Classes example use """ From ce939d93b931daae4010bdb40f929b38cf6c186a Mon Sep 17 00:00:00 2001 From: Dimitry Kh Date: Mon, 30 Sep 2024 11:38:21 +0200 Subject: [PATCH 15/15] rename test --- .github/workflows/coverage.yaml | 21 +- converted-ethereum-tests.txt | 4 +- ...c_tload.py => test_basic_tload_renamed.py} | 0 ...d_calls.py => test_tload_calls_renamed.py} | 0 .../eip1153_tstore/test_tstore_reentrancy.py | 214 ------------------ .../eip3540_eof_v1/test_eof_example.py | 1 - 6 files changed, 19 insertions(+), 221 deletions(-) rename tests/cancun/eip1153_tstore/{test_basic_tload.py => test_basic_tload_renamed.py} (100%) rename tests/cancun/eip1153_tstore/{test_tload_calls.py => test_tload_calls_renamed.py} (100%) delete mode 100644 tests/cancun/eip1153_tstore/test_tstore_reentrancy.py diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml index 6564af81d0..3ad77835e6 100644 --- a/.github/workflows/coverage.yaml +++ b/.github/workflows/coverage.yaml @@ -25,6 +25,8 @@ jobs: with: # TODO: non-test modules such as __init__.py or spec.py could effect coverage - in this case we should # fill all applicable tests (i.e., all the test_*.py files in or under the changed module's directory) + include_all_old_new_renamed_files: true + output_renamed_files_as_deleted_and_added: true files_yaml: | tests: - tests/**/test_*.py @@ -40,7 +42,8 @@ jobs: - name: Report changed python test moudules if: steps.changed-tests.outputs.tests_any_changed == 'true' run: | - echo "Changed python test modules: ${{ steps.changed-tests.outputs.tests_all_changed_files }}" + echo "${{ toJson(steps.changed-tests.outputs) }}" + echo "Changed python test modules: ${{ steps.changed-tests.outputs.tests_all_modified_files }}" - name: Debug GitHub context run: | @@ -195,7 +198,7 @@ jobs: - name: Parse and fill introduced test sources from before the PR if: ${{ steps.changed-tests.outputs.tests_any_changed == 'true' && env.converted_skip == 'true' }} env: - CHANGED_TEST_FILES: ${{ steps.changed-tests.outputs.tests_all_changed_files }} + CHANGED_TEST_FILES: ${{ steps.changed-tests.outputs.tests_all_modified_files }} run: | echo "--------------------" echo "converted-ethereum-tests.txt seem untouched, try to fill pre-patched version of .py files:" @@ -207,14 +210,24 @@ jobs: PREV_COMMIT=$(git rev-parse HEAD) echo "Checkout head $PREV_COMMIT" + # Take only those files that exist in the filesystem (ignore newly created files) + files_fixed=$(echo "$files" | tr ' ' '\n' | while read file; do + if [ -f "$file" ]; then + echo "$file" + fi + done | tr '\n' ' ') + + echo "Select files that were changed and exist on the main branch:" + echo $files_fixed + rm -r fixtures rm filloutput.log rm filloutputEOF.log mkdir -p fixtures/state_tests mkdir -p fixtures/eof_tests - uv run fill $files --until=Cancun --evm-bin evmone-t8n || true >> filloutput.log 2>&1 - (uv run fill $files --fork=PragueEIP7692 --evm-bin evmone-t8n || true) > >(tee -a filloutput.log filloutputEOF.log) 2>&1 + uv run fill $files_fixed --until=Cancun --evm-bin evmone-t8n || true >> filloutput.log 2>&1 + (uv run fill $files_fixed --fork=PragueEIP7692 --evm-bin evmone-t8n || true) > >(tee -a filloutput.log filloutputEOF.log) 2>&1 if grep -q "FAILURES" filloutput.log; then echo "Error: failed to generate .py tests from before the PR." diff --git a/converted-ethereum-tests.txt b/converted-ethereum-tests.txt index 34934f428e..f11bdc4490 100644 --- a/converted-ethereum-tests.txt +++ b/converted-ethereum-tests.txt @@ -15,8 +15,8 @@ EOFTests/efValidation/EOF1_section_order_.json EOFTests/efValidation/EOF1_truncated_section_.json ([#647](https://github.com/ethereum/execution-spec-tests/pull/647)) - EOFTests/efValidation/EOF1_returncontract_invalid_.json - EOFTests/efValidation/EOF1_returncontract_valid_.json +EOFTests/efValidation/EOF1_returncontract_invalid_.json +EOFTests/efValidation/EOF1_returncontract_valid_.json ([#440](https://github.com/ethereum/execution-spec-tests/pull/440)) GeneralStateTests/Cancun/stEIP1153-transientStorage/01_tloadBeginningTxn.json diff --git a/tests/cancun/eip1153_tstore/test_basic_tload.py b/tests/cancun/eip1153_tstore/test_basic_tload_renamed.py similarity index 100% rename from tests/cancun/eip1153_tstore/test_basic_tload.py rename to tests/cancun/eip1153_tstore/test_basic_tload_renamed.py diff --git a/tests/cancun/eip1153_tstore/test_tload_calls.py b/tests/cancun/eip1153_tstore/test_tload_calls_renamed.py similarity index 100% rename from tests/cancun/eip1153_tstore/test_tload_calls.py rename to tests/cancun/eip1153_tstore/test_tload_calls_renamed.py diff --git a/tests/cancun/eip1153_tstore/test_tstore_reentrancy.py b/tests/cancun/eip1153_tstore/test_tstore_reentrancy.py deleted file mode 100644 index dff47ddbcb..0000000000 --- a/tests/cancun/eip1153_tstore/test_tstore_reentrancy.py +++ /dev/null @@ -1,214 +0,0 @@ -""" -Ethereum Transient Storage EIP Tests -https://eips.ethereum.org/EIPS/eip-1153 -""" - -from enum import Enum - -import pytest - -from ethereum_test_tools import ( - Account, - Address, - Alloc, - Case, - Environment, - Hash, - StateTestFiller, - Switch, - Transaction, -) -from ethereum_test_tools.vm.opcode import Bytecode -from ethereum_test_tools.vm.opcode import Macros as Om -from ethereum_test_tools.vm.opcode import Opcodes as Op - -REFERENCE_SPEC_GIT_PATH = "EIPS/eip-1153.md" -REFERENCE_SPEC_VERSION = "2f8299df31bb8173618901a03a8366a3183479b0" - - -class CallDestType(Enum): - """Call dest type""" - - REENTRANCY = 1 - EXTERNAL_CALL = 2 - - -@pytest.mark.valid_from("Cancun") -@pytest.mark.parametrize("call_type", [Op.CALL, Op.CALLCODE, Op.DELEGATECALL, Op.STATICCALL]) -@pytest.mark.parametrize("call_return", [Op.RETURN, Op.REVERT, Om.OOG]) -@pytest.mark.parametrize("call_dest_type", [CallDestType.REENTRANCY, CallDestType.EXTERNAL_CALL]) -def test_tstore_reentrancy( - state_test: StateTestFiller, - pre: Alloc, - call_type: Op, - call_return: Op, - call_dest_type: CallDestType, -): - """ - Ported .json vectors: - - (06_tstoreInReentrancyCallFiller.yml) - Reentrant calls access the same transient storage - - (07_tloadAfterReentrancyStoreFiller.yml) - Successfully returned calls do not revert transient storage writes - - (08_revertUndoesTransientStoreFiller.yml) - Revert undoes the transient storage writes from a call. - - (09_revertUndoesAllFiller.yml) - Revert undoes all the transient storage writes to the same key from the failed call. - - (11_tstoreDelegateCallFiller.yml) - delegatecall manipulates transient storage in the context of the current address. - - (13_tloadStaticCallFiller.yml) - Transient storage cannot be manipulated in a static context, tstore reverts - - (20_oogUndoesTransientStoreInCallFiller.yml) - Out of gas undoes the transient storage writes from a call. - """ - tload_value_set_before_call = 80 - tload_value_set_in_call = 90 - - # Storage cells - slot_tload_before_call = 0 - slot_tload_in_subcall_result = 1 - slot_tload_after_call = 2 - slot_subcall_worked = 3 - slot_tload_1_after_call = 4 - slot_tstore_overwrite = 5 - slot_code_worked = 6 - - # Function names - do_tstore = 1 - do_reenter = 2 - call_dest_address: Bytecode | Address - call_dest_address = Op.ADDRESS() - - def make_call(call_type: Op) -> Bytecode: - if call_type == Op.DELEGATECALL or call_type == Op.STATICCALL: - return call_type(Op.GAS(), call_dest_address, 0, 32, 32, 32) - else: - return call_type(Op.GAS(), call_dest_address, 0, 0, 32, 32, 32) - - subcall_code = ( - Op.TSTORE(0, 89) - + Op.TSTORE(0, tload_value_set_in_call) - + Op.TSTORE(1, 11) - + Op.TSTORE(1, 12) - + Op.MSTORE(0, Op.TLOAD(0)) - + call_return(0, 32) - ) - - address_code = pre.deploy_contract( - balance=0, - code=subcall_code, - storage={}, - ) - if call_dest_type == CallDestType.EXTERNAL_CALL: - call_dest_address = address_code - - address_to = pre.deploy_contract( - balance=1_000_000_000_000_000_000, - code=Switch( - cases=[ - Case( - condition=Op.EQ(Op.CALLDATALOAD(0), do_tstore), - action=subcall_code, - ), - Case( - condition=Op.EQ(Op.CALLDATALOAD(0), do_reenter), - action=Op.TSTORE(0, tload_value_set_before_call) - + Op.SSTORE(slot_tload_before_call, Op.TLOAD(0)) - + Op.MSTORE(0, do_tstore) - + Op.MSTORE(32, 0xFF) - + Op.SSTORE(slot_subcall_worked, make_call(call_type)) - + Op.SSTORE(slot_tload_in_subcall_result, Op.MLOAD(32)) - + Op.SSTORE(slot_tload_after_call, Op.TLOAD(0)) - + Op.SSTORE(slot_tload_1_after_call, Op.TLOAD(1)) - + Op.TSTORE(0, 50) - + Op.SSTORE(slot_tstore_overwrite, Op.TLOAD(0)) - + Op.SSTORE(slot_code_worked, 1), - ), - ], - default_action=None, - ), - storage={ - slot_tload_before_call: 0xFF, - slot_tload_in_subcall_result: 0xFF, - slot_tload_after_call: 0xFF, - slot_subcall_worked: 0xFF, - slot_tload_1_after_call: 0xFF, - slot_tstore_overwrite: 0xFF, - slot_code_worked: 0xFF, - }, - ) - - on_failing_calls = call_type == Op.STATICCALL or call_return in [Op.REVERT, Om.OOG] - on_successful_delegate_or_callcode = call_type in [ - Op.DELEGATECALL, - Op.CALLCODE, - ] and call_return not in [Op.REVERT, Om.OOG] - - if call_dest_type == CallDestType.REENTRANCY: - post = { - address_to: Account( - storage={ - slot_code_worked: 1, - slot_tload_before_call: tload_value_set_before_call, - slot_tload_in_subcall_result: ( - # we fail to obtain in call result if it fails - 0xFF - if call_type == Op.STATICCALL or call_return == Om.OOG - else tload_value_set_in_call - ), - # reentrant tstore overrides value in upper level - slot_tload_after_call: ( - tload_value_set_before_call - if on_failing_calls - else tload_value_set_in_call - ), - slot_tload_1_after_call: 0 if on_failing_calls else 12, - slot_tstore_overwrite: 50, - # tstore in static call not allowed - slot_subcall_worked: 0 if on_failing_calls else 1, - } - ) - } - else: - post = { - address_to: Account( - storage={ - slot_code_worked: 1, - slot_tload_before_call: tload_value_set_before_call, - slot_tload_in_subcall_result: ( - # we fail to obtain in call result if it fails - 0xFF - if call_type == Op.STATICCALL or call_return == Om.OOG - else tload_value_set_in_call - ), - # external tstore overrides value in upper level only in delegate and callcode - slot_tload_after_call: ( - tload_value_set_in_call - if on_successful_delegate_or_callcode - else tload_value_set_before_call - ), - slot_tload_1_after_call: 12 if on_successful_delegate_or_callcode else 0, - slot_tstore_overwrite: 50, - # tstore in static call not allowed, reentrancy means external call here - slot_subcall_worked: 0 if on_failing_calls else 1, - } - ) - } - - tx = Transaction( - sender=pre.fund_eoa(7_000_000_000_000_000_000), - to=address_to, - gas_price=10, - data=Hash(do_reenter), - gas_limit=5000000, - value=0, - ) - - state_test(env=Environment(), pre=pre, post=post, tx=tx) diff --git a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_eof_example.py b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_eof_example.py index a93d60d876..0ecaad8228 100644 --- a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_eof_example.py +++ b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_eof_example.py @@ -1,5 +1,4 @@ """ -touch EOF Classes example use """